Repository navigation
Time out browser loads just before the suite load timeout - #2786
Conversation
Fixes #2691 The browser platform gave up waiting for a browser to load a compiled suite after the test timeout, or 30 seconds if that was longer. This timeout was added in #2080, before `suite_load_timeout` existed, to get better diagnostics for browser loads that never completed. The test timeout has nothing to do with loading, and `suite_load_timeout` had no effect on this limit, so the only way to give a slow browser more time was to raise the timeout for every test. Start a stopwatch in the load suite's body, right after the invoker starts the load test's timeout, and expose the time left before that timeout through a static `PlatformPlugin.remainingLoadTime` getter that platforms can read during `load`. It reads a zone value set by the load suite, so platforms need no new imports, and it is static so classes implementing `PlatformPlugin` don't need to change. It is `null` when loading can't time out because the suite load timeout is `none` or timeouts are ignored. The value is only meaningful during `load`; callbacks registered while loading run in the same zone and may see a stale value later. Have the browser platform give up 1 second before the remaining load time runs out, so its error, which includes the browser output, wins over the generic timeout on the load test. Retries in the loader share the same budget. When there is no remaining load time, don't time out the browser, matching how other platforms load suites without a suite load timeout. Configuring `suite_load_timeout` restores a limit along with the more detailed error. Bump test_core to 0.6.22-wip for the new API and pin it from test.
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 |
natebosch
left a comment
There was a problem hiding this comment.
I don't have immediate plans to add narrow timeouts in other platforms, but this is a better design for the browser timeouts, and this will be handy if we end up needing to add narrow timeouts to debug future loading issues.
| /// more specific error before the suite fails with a generic timeout. The | ||
| /// value is only meaningful while [load] is running; callbacks a platform | ||
| /// registers during [load] may see a stale value when they run later. |
There was a problem hiding this comment.
For reviewers - this note is here out of an abundance of caution. No platforms would have any reason to read this (nor generally to execute callbacks) past loading and platform plugin APIs are expert facing, not end-user facing. There's no reason to make the zone interactions more complex to protect against misuse.
There was a problem hiding this comment.
Do they implement this class though? Is this breaking?
There was a problem hiding this comment.
consider making this an extension method if so
There was a problem hiding this comment.
It was written as a static so that it will be safely non-breaking for existing implementations (although I think in practice we could probably make it a base class).
jakemac53
left a comment
There was a problem hiding this comment.
Just the one comment about whether or not adding the new getter is breaking.
A browser had 30 seconds to connect, and one that didn't was replaced, up to 3 attempts, regardless of `suite_load_timeout`. #2786 gave browser suite loads until shortly before the suite load timeout instead, so the connection is the last part of loading a browser suite with its own fixed limit. Give the connection the same budget: until shortly before the suite load timeout, or no limit without one. A browser that times out uses the whole budget, so it isn't replaced. Timeouts were the only failure that was retried, so instead retry a browser that starts and then exits before connecting, up to 3 attempts while time remains. A process that fails to start, such as one with a missing executable, would fail the same way again and isn't retried. Each failed attempt is described in the error, including the output of browsers that exited. Without a suite load timeout a browser that never connects now hangs the run instead of failing, so add a `suite_load_timeout` to the wasm and spawn_hybrid integration tests, which run in browsers on CI.
Revisions updated by `dart tools/rev_sdk_deps.dart`. dartdoc (https://github.com/dart-lang/dartdoc/compare/5eb0f2c..e1859cf): e1859cfc Fri Oct 9 14:53:01 2026 +0200 Sarah Zakarias Link a bare prefix only when it maps to exactly one library (dart-lang/dartdoc#4295) c48f6fb9 Fri Oct 9 14:25:42 2026 +0200 Sarah Zakarias Resolve prefixes through the analyzer's PrefixElement.scopeLibraries (dart-lang/dartdoc#4294) 3a6297e2 Wed Oct 7 12:56:14 2026 +0200 Sarah Zakarias Require analyzer 14.5.0 and bump to 9.0.10 (dart-lang/dartdoc#4292) ecosystem (https://github.com/dart-lang/ecosystem/compare/16dca7a..622ef61): 622ef61 Mon Oct 12 00:23:27 2026 -0700 Kevin Moore fix(firehose): enforce -wip on published versions and tighten changelog checks (dart-lang/ecosystem#467) 5576a85 Wed Oct 7 09:29:44 2026 +0200 Moritz Support use-flutter option in groundskeeper workflow (dart-lang/ecosystem#444) http (https://github.com/dart-lang/http/compare/585d433..23f8574): 23f8574 Thu Oct 8 23:27:25 2026 +0700 Cong Bang feat(http2): configurable receive windows and frame size (dart-lang/http#1999) 18051a6 Thu Oct 8 10:39:38 2026 +0200 Moritz Enable Flutter in Groundskeeper workflow for Flutter packages (dart-lang/http#2004) native (https://github.com/dart-lang/native/compare/a2a6179..10515af): 10515afca Mon Oct 12 12:21:52 2026 +0200 Daco Harkes [native_toolchain_c] Do not pass linker flags when compiling static libraries (dart-lang/native#3731) native is held back at 10515af, before dart-lang/native#3728, because it breaks the dartdev `dart install` native assets tests. See dart-lang/native#3743. test (https://github.com/dart-lang/test/compare/d749b10..30acb69): 30acb69e Mon Oct 12 12:42:54 2026 -0700 Nate Bosch Time out browser loads just before the suite load timeout (dart-lang/test#2786) 597a0326 Mon Oct 12 12:22:53 2026 -0700 Kevin Moore Fix misplaced changelog entries and remove no-op health check (dart-lang/test#2789) 0b6efee8 Mon Oct 12 12:16:29 2026 -0700 Nate Bosch [checks] Collapse nested subjects in condition descriptions (dart-lang/test#2784) 17c98493 Mon Oct 12 12:08:23 2026 -0700 Nate Bosch Follow symlinks in precompiled browser test directories (dart-lang/test#2787) 1cc813ec Fri Oct 9 11:59:56 2026 -0700 Nate Bosch [checks] Join nested collapsed subjects with "that" (dart-lang/test#2783) ada7b950 Thu Oct 8 12:03:42 2026 -0700 Nate Bosch Prepare to publish (dart-lang/test#2780) c4b165b3 Wed Oct 7 11:29:08 2026 -0700 Kevin Moore [checks] Require package:meta ^1.17.0 (dart-lang/test#2779) 4a363d70 Tue Oct 6 10:46:31 2026 -0700 Nate Bosch Let Chrome choose its remote debugging port (dart-lang/test#2778) 465d66ab Tue Oct 6 09:35:22 2026 -0700 Nate Bosch Keep Chrome stderr in the browser output when debugging (dart-lang/test#2777) tools (https://github.com/dart-lang/tools/compare/a66d517..2b54c71): 2b54c71af Mon Oct 12 10:16:45 2026 +0200 dart-ecosystem-bot[bot] [boring] Update BoringSSL to 3fed4f20 (dart-lang/tools#2655) 2337f995a Sat Oct 10 03:11:40 2026 +0300 Hasan Armoush [json_rpc_2] Add strictProtocolChecks parameter to Client (dart-lang/tools#2555) c65c69ed1 Fri Oct 9 08:54:25 2026 +0200 Moritz [boring] Move package:boring to dart-lang/tools (2/4): FFI helpers from package:webcrypto (dart-lang/tools#2615) a04e45491 Thu Oct 8 21:07:18 2026 -0700 Kevin Moore chore: wire package:api_summary and package:string_scanner PR auto-labeler (dart-lang/tools#2652) 8bdd4b92c Thu Oct 8 09:20:48 2026 +0200 Morgan :) [code_builder] Allow built_collection 6.x. (dart-lang/tools#2645) c16040d35 Wed Oct 7 17:30:08 2026 -0700 Kevin Moore [api_summary] Sort primary barrel first and experimental entry points last (v1.2.0) (dart-lang/tools#2619) b2d0780db Wed Oct 7 11:27:16 2026 -0700 Kevin Moore [stream_channel] Require package:async ^2.6.0 (dart-lang/tools#2644) 3ab7bf9d0 Wed Oct 7 11:35:27 2026 +0200 Moritz [boring] Move package:boring to dart-lang/tools (1/4): vendored BoringSSL, bindings and source build (dart-lang/tools#2614) 29df6348b Tue Oct 6 15:21:44 2026 -0700 Kevin Moore feat(coverage): support web coverage reports in test_with_coverage (dart-lang/tools#2448) Regenerate pkg/{analyzer,analyzer_plugin,analyzer_testing}/api.txt. The rolled package:api_summary v1.2.0 (dart-lang/tools#2619) sorts the primary barrel first and other entry points after it, so entries in these files are reordered. The APIs themselves are unchanged. Change-Id: Ie8ff19c5a981ea8ecee8939c75457986a947e0a7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/563220 Reviewed-by: Samuel Rawlins <[email protected]> Auto-Submit: Nate Bosch <[email protected]> Reviewed-by: Paul Berry <[email protected]> Commit-Queue: Paul Berry <[email protected]>
… load timeout (#2788) A wasm integration test failed with "Timed out waiting for Firefox to connect." and an empty "Browser output:" (https://github.com/dart-lang/test/actions/runs/37977193562/job/113978908374). All three connection attempts had failed, but the error only showed the last attempt's output, and Firefox writes almost nothing to stdout or stderr, so there was no way to tell how far the browser got. ### Diagnostics When a browser fails to connect, describe each attempt: how long it waited, whether the browser process was still running or its exit code, the command used to start it, its output, and the requests it made to the test server. A new `BrowserRequestLog` wraps each compiler's server and records the host page, the resources it loads, and WebSocket upgrades, matched to the browser manager by the `managerUrl` query parameter or the `Referer` header. Requests are labeled by file name so the server secret is not printed. Set Firefox preferences that print page console output and `dump()` calls to stdout, so errors in the host page show up in the browser output. ### Connect timeout A browser had 30 seconds to connect, and one that didn't was replaced, up to 3 attempts, regardless of `suite_load_timeout`. Following #2786, give the connection until shortly before the suite load timeout instead, or no limit without one. Connecting and then loading the suite are consecutive steps of loading a suite, so they share that deadline, and loading gets whatever time connecting left. A browser that times out uses the whole budget, so it isn't replaced. Timeouts were the only failure that was retried; instead, retry a browser that starts and then exits before connecting, up to 3 attempts while time remains. A process that fails to start, such as one with a missing executable, isn't retried. Without a suite load timeout a browser that never connects now hangs the run instead of failing, so add `suite_load_timeout: 2m` to the wasm and spawn_hybrid integration tests, which run in browsers on CI.
Fixes #2691
The browser platform gave up waiting for a browser to load a compiled
suite after the test timeout, or 30 seconds if that was longer. This
timeout was added in #2080, before
suite_load_timeoutexisted, to getbetter diagnostics for browser loads that never completed. The test
timeout has nothing to do with loading, and
suite_load_timeouthad noeffect on this limit, so the only way to give a slow browser more time
was to raise the timeout for every test.
Start a stopwatch in the load suite's body, right after the invoker
starts the load test's timeout, and expose the time left before that
timeout through a static
PlatformPlugin.remainingLoadTimegetter thatplatforms can read during
load. It reads a zone value set by the loadsuite, so platforms need no new imports, and it is static so classes
implementing
PlatformPlugindon't need to change. It isnullwhenloading can't time out because the suite load timeout is
noneortimeouts are ignored. The value is only meaningful during
load;callbacks registered while loading run in the same zone and may see a
stale value later.
Have the browser platform give up 1 second before the remaining load
time runs out, so its error, which includes the browser output, wins
over the generic timeout on the load test. Retries in the loader share
the same budget. When there is no remaining load time, don't time out
the browser, matching how other platforms load suites without a suite
load timeout. Configuring
suite_load_timeoutrestores a limit alongwith the more detailed error.
Bump test_core to 0.6.22-wip for the new API and pin it from test.