Tests: De-flake abortsignal-timeout by dropping its wall-clock assertion

Problem: The abortsignal-timeout.html test was (still) intermittently
failing under CI — printing “…at least 10 milliseconds: false”.

Cause: The test asserts AbortSignal.timeout(10) fired >= 10ms later,
measured as a wall-clock time of performance.now() delta + 1ms fudge.
But that involves timings from two *different* clocks: performance.now()
uses CLOCK_MONOTONIC, while the timeout timer is armed and fired against
CLOCK_MONOTONIC_COARSE (the event-loop clock) — which is quantized to
the kernel tick, and which lags the precise clock by up to a tick. Thus,
a 10ms coarse-scheduled timeout can fall short of 10ms of precise time
by up to one tick. So what was likely happening is: When that shortfall
exceeds the 1ms fudge (coarse-tick kernels, or ticks delayed under CI
load), the delta landed under 10ms. The 1ms fudge added by 6fa32fbf69
narrowed but never closed the race — because the check gates on host
timer/clock precision, rather than on AbortSignal behavior.

Fix: Drop the wall-clock timing assertion. Keep the deterministic checks
that actually exercise AbortSignal.timeout: The abort fires, its
reason is TimeoutError, and the event is trusted. And add a synchronous
check that the signal isn’t aborted immediately after creation – which
confirms the abort is deferred, without racing the clock.
This commit is contained in:
sideshowbarker 2026-06-05 18:25:43 +09:00 committed by Jelle Raaijmakers
parent 3e6cfb1ba6
commit bbfa1ca7ae
2 changed files with 5 additions and 14 deletions

View file

@ -1,3 +1,3 @@
Time passed before abort event fired is at least 10 milliseconds: true
aborted synchronously: false
Reason type: TimeoutError
onabort event isTrusted: true

View file

@ -2,21 +2,12 @@
<script src="include.js"></script>
<script>
asyncTest(done => {
const timeout_milliseconds = 10;
const test_start_time = performance.now();
const signal = AbortSignal.timeout(timeout_milliseconds);
signal.onabort = (event) => {
const abort_event_time = performance.now();
const time_taken_milliseconds = (abort_event_time - test_start_time) + 1; // Add 1ms for possible coarse clock skew
println(`Time passed before abort event fired is at least ${timeout_milliseconds} milliseconds: ${time_taken_milliseconds >= timeout_milliseconds}`);
const signal = AbortSignal.timeout(10);
// The timeout aborts asynchronously — so the signal must not be aborted yet.
println(`aborted synchronously: ${signal.aborted}`);
signal.onabort = event => {
println(`Reason type: ${signal.reason.name}`);
println(`onabort event isTrusted: ${event.isTrusted}`);
if (time_taken_milliseconds < timeout_milliseconds) {
println(`start time: ${test_start_time}`);
println(`abort time: ${abort_event_time}`);
println(`difference (coarse adjusted): ${time_taken_milliseconds}`);
println(`difference (actual): ${time_taken_milliseconds - 1}`);
}
done();
};
});