Repository navigation
Let Chrome choose its remote debugging port - #2778
Merged
Merged
Conversation
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`.
sigurdm
approved these changes
Oct 6, 2026
# Conflicts: # pkgs/test/lib/src/runner/browser/chrome.dart # pkgs/test/test/runner/browser/chrome_test.dart
PR HealthChangelog Entry ✔️
Changes to files need to be accounted for in their respective changelogs. This check can be disabled by tagging the PR with |
`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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When debugging or collecting coverage, the runner picked a probably-unused
port with
getUnusedPortand passed it to Chrome with--remote-debugging-port. Chrome gives no reliable signal that it boundthe port, so there was a window where another process could take it, and
tryPorthad to report the chosen port back through a completer for_connectto use.Pass
--remote-debugging-port=0so Chrome binds an unused port itself,and read the port from the URL in the "DevTools listening on" line, which
_connectalready waits for. With no port to choose or pass along,tryPort, the port completer, and the private constructor go away, andChromehas a plain generative constructor.spawnalready falls backto 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.