Skip to content

Let Chrome choose its remote debugging port - #2778

Merged
natebosch merged 5 commits into
masterfrom
chrome-debug-port-from-output
Oct 6, 2026
Merged

natebosch merged 5 commits into
masterfrom
chrome-debug-port-from-output

Conversation

@natebosch

@natebosch natebosch commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

When debugging or collecting coverage, the runner picked a probably-unused
port with getUnusedPort and passed it to Chrome with
--remote-debugging-port. Chrome gives no reliable signal that it bound
the port, so there was a window where another process could take it, and
tryPort had to report the chosen port back through a completer for
_connect to use.

Pass --remote-debugging-port=0 so Chrome binds an unused port itself,
and read the port from the URL in the "DevTools listening on" line, which
_connect already waits for. With no port to choose or pass along,
tryPort, the port completer, and the private constructor go away, and
Chrome has a plain generative constructor. spawn already falls back
to the default Chrome settings.

Update the fake Chrome test to report a fake DevTools server's port in its
DevTools line, and check that connecting reaches that server and that
Chrome is started with --remote-debugging-port=0.

When Chrome runs with a remote debugging port, which happens with
`--debug`, `--pause-after-load`, and `--coverage`, `_connect` listened to
the process's stderr to wait for the "DevTools listening" line. The
`Browser` base class listens to the same single-subscription stream to
collect the browser output, and that second listen threw a `StateError`
which was silently caught. Once `firstWhere` found the line it cancelled
the subscription, which closes the pipe, so all of Chrome's stderr,
including its console logging, was missing from the "Browser output" in
load failures and timeouts.

Rename the `output` list on `Browser` to `accumulatedOutput`, and add an
`output` stream built with `Stream.multi` which replays the accumulated
lines to each new listener and then forwards new lines. It closes when
both stdout and stderr are done, when the browser is closed, or when
starting or running the browser fails.

In `Chrome`, `tryPort` now only reports which debugging port it used, and
`_connect` is an instance method which reads that port and waits for the
DevTools line on `output`. The tab connection and the remote debugger URL
come from a single lazy `_connection` future in place of the two
completers, started by the first read of `remoteDebuggerUrl` or
`gatherCoverage`. `BrowserManager` reads `remoteDebuggerUrl` before it
loads any suites, so coverage collection still starts before tests run,
and the replay means a late start still sees the DevTools line.

Drop the `StateError` catch in `drainOutput`. Nothing else listens to the
process streams now, and a future second listener should fail loudly
instead of losing output.
When debugging or collecting coverage, the runner picked a probably-unused
port with `getUnusedPort` and passed it to Chrome with
`--remote-debugging-port`. Chrome gives no reliable signal that it bound
the port, so there was a window where another process could take it, and
`tryPort` had to report the chosen port back through a completer for
`_connect` to use.

Pass `--remote-debugging-port=0` so Chrome binds an unused port itself,
and read the port from the URL in the "DevTools listening on" line, which
`_connect` already waits for. With no port to choose or pass along,
`tryPort`, the port completer, and the private constructor go away, and
`Chrome` has a plain generative constructor. `spawn` already falls back
to the default Chrome settings.

Update the fake Chrome test to report a fake DevTools server's port in its
DevTools line, and check that connecting reaches that server and that
Chrome is started with `--remote-debugging-port=0`.
@natebosch
natebosch requested a review from a team as a code owner October 6, 2026 05:04
@natebosch
natebosch requested a review from sigurdm October 6, 2026 05:09
Base automatically changed from chrome-debug-stderr to master October 6, 2026 16:35
# Conflicts:
#	pkgs/test/lib/src/runner/browser/chrome.dart
#	pkgs/test/test/runner/browser/chrome_test.dart
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

PR Health

Changelog Entry ✔️
Package Changed Files

Changes to files need to be accounted for in their respective changelogs.

This check can be disabled by tagging the PR with skip-changelog-check.

`Uri.port` is 0 when the URL has no port, which would turn into a
confusing connection failure on port 0. Throw a `StateError` naming the
line instead, which also covers a URL that does not parse.
@natebosch
natebosch merged commit 4a363d7 into master Oct 6, 2026
71 checks passed
@natebosch
natebosch deleted the chrome-debug-port-from-output branch October 6, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants