Re: [whatwg/xhr] Synchronous send() can report timing with null reporting steps after timeout (Issue #412)

sideshowbarker left a comment (whatwg/xhr#412)

tl;dr: It looks like what both Blink and Gecko do matches keeping step 12.7, and having Fetch set the report timing steps on every path that ends a fetch (termination included, with the opaque start/end timing). And it’d also fix the same assertion’s other trigger, in the HTML preload algorithm.

> What do implementations do?

Based on looking at all the engine code, for a sync XHR in a worker that times out:

- Blink and Gecko both report a resource-timing entry
- WebKit doesn’t

WebKit doesn’t report entries for *any* failed or canceled load.

<details>
<summary>Engine details</summary>

- **Blink:** `SyncLoadContext::OnTimeout()` completes the sync load with `ERR_TIMED_OUT`, and `ResourceLoader::RequestSynchronously()` hands that to `DidFail()`, which reaches `ResourceFetcher::HandleLoaderError()`. That adds an entry for every failed HTTP(S) load, with no exception for timeouts or cancellation; with no response, the entry has just the URL, start time, and end time.
- **Gecko:** A worker’s sync XHR runs an async main-thread XHR under a sync loop. On timeout, `CloseRequestWithError()` cancels the channel with `NS_BINDING_ABORTED`, and `HttpChannelChild::DoPreOnStopRequest()` then calls `MaybeReportTimingData()` whatever the status. (The exception is a failure inside `AsyncOpen()` itself, which skips that call.)
- **WebKit:** `ResourceTimingInformation::shouldAddResourceTiming()` returns false if `loadFailedOrCanceled()`, and neither `SubresourceLoader::didFail()` nor its cancel path calls `reportResourceTiming()`. Its checked-in WPT expectations agree: The CORS-failure subtest of `resource-timing/xhr-resource-timing.html` and `entries-for-network-errors.sub.https.html` both time out waiting for an entry.

</details>

Async XHR timeouts and `abort()` behave the same way in each engine: Blink and Gecko report an entry, and WebKit doesn’t.

> Also not sure we report timing for network errors?

It looks like Fetch does: It reports an opaque timing info for a network error, and `entries-for-network-errors.sub.https.html` tests that for failed CORS, DNS failure, mixed content, too many redirects, and more.

And Blink and Gecko ship that. But it doesn’t look like there’s any WPT test that checks resource timing for a timed-out or aborted XHR or `fetch()`.

Ladybird currently implements the spec steps as written. So it reports opaque timing for network errors, and a timed-out sync XHR in a worker hits the assertion.

It has also hit the same assertion from another caller: The HTML preload algorithm calls “report timing” from processResponseConsumeBody, which also runs when reading the body fails. But Fetch sets the report timing steps only in processResponseEndOfBody, which runs only once the body has been read in full.

So Ladybird sets them on the error path too, as an ad-hoc fix.


-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/xhr/issues/412#issuecomment-6396778488
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/xhr/issues/412/6396778488@github.com>

Received on Sunday, 25 October 2026 10:58:36 UTC