v158 · resource timing · gating

The gate matrix

Five fetches, five header situations, all real. Two rows are discriminators: the old TAO rule and the new CORS rule give opposite answers for them. Run the matrix and this page reads the actual PerformanceResourceTiming entries and tells you which rule the browser you are holding implements — no user-agent sniffing, just the numbers.

Chrome ships the CORS gate in Chrome 158; the Blink runtime feature is ResourceTimingUseCORSForBodySizes (status test in today's tree, so pre-158 builds can only enable it with --enable-blink-features=ResourceTimingUseCORSForBodySizes — there is no chrome://flags entry). The rows fetch public CDN endpoints whose headers were verified when this page was written (shown per row); if your network blocks one, its row reports the real fetch error rather than inventing numbers.

Run the five fetches

Byte-count exposure by gate — live values from this browser
resource / gates encodedBodySize decodedBodySize transferSize responseStatus (CORS-gated precedent) old TAO rule says new CORS rule says

Rows marked with a blue edge are the discriminators. “exposed” = value > 0 for these multi-kilobyte resources; “hidden” = 0, which the spec uses as the gated value.

Not run yet.

why these five rows

Same-origin is the control: always exposed. CORS + TAO (jsDelivr fetched with mode: "cors") satisfies both rules, so it is exposed under both — including transferSize, which under the new rule needs both headers. TAO-only is jsDelivr again but fetched with mode: "no-cors": the response is opaque (no CORS), yet Timing-Allow-Origin: * is present — the old rule exposes its sizes, the new rule hides them. CORS-only is raw.githubusercontent.com, which sends Access-Control-Allow-Origin: * but no TAO — the old rule hides its sizes, the new rule exposes encoded/decoded while transferSize stays 0 (it needs both). Neither (gstatic, opaque) is the floor: hidden under every rule, like the already-CORS-gated responseStatus column shows throughout.

code path

// The discriminating pair, verbatim:
const taoOnly = await fetch("https://cdn.jsdelivr.net/npm/preact/...", {
  mode: "no-cors",   // opaque: NOT CORS — but the response carries TAO: *
});
const corsOnly = await fetch("https://raw.githubusercontent.com/...", {
  mode: "cors",      // CORS ok — but the response has no TAO header
});

// old (TAO) rule:  taoOnly sizes exposed,  corsOnly sizes 0
// new (CORS) rule: taoOnly sizes 0,        corsOnly encoded/decoded exposed
//                  (corsOnly transferSize stays 0 — it needs CORS *and* TAO)

see also