v158 · performance · resource timing
Resource timing: get encoded/decoded body size with CORS instead of TAO
A PerformanceResourceTiming entry reports three byte counts — encodedBodySize, decodedBodySize, transferSize — but for cross-origin resources they are gated. Historically the gate was the Timing-Allow-Origin header. Chrome 158 changes which gate applies: body sizes are facts about the content, not the fetch, so they follow the CORS opt-in that already guards responseStatus and contentType — while transferSize, which mixes content and network detail, now requires both CORS and TAO.
concepts
-
Body size basics
Fetch this site's own assets and read the three byte counts off the real
PerformanceResourceTimingentry, delivered live by aPerformanceObserver: compression ratio from encoded vs decoded, cache hits fromtransferSize === 0, and header overhead from transfer minus encoded. Same-origin, so every field is always exposed — the baseline the gates subtract from. -
The gate matrix
Five real fetches — same-origin, CORS+TAO, TAO-only (opaque), CORS-only, and neither — against public endpoints whose headers are documented in-page. Two of the rows disagree between the old TAO rule and the new CORS rule, so the matrix doesn't just explain the change: it detects which regime the browser you are using right now actually implements, and says so.
-
Third-party weight audit
The practical stakes: a RUM-style auditor that fetches any third-party URL you give it and reports exactly which byte counts your analytics could see for it, in this browser, plus which response header —
Access-Control-Allow-OriginorTiming-Allow-Origin— the resource's owner would need to add under the old and new rules to unlock the rest.
why it shipped
The resource-timing group concluded years ago (issue #220) that Timing-Allow-Origin should opt a resource into timing — and body sizes say more about a response's content than about the process of fetching it. The CORS-protected attributes added since (responseStatus, contentType, contentEncoding) already follow that logic. Chrome 158 brings encodedBodySize and decodedBodySize into line: exposed for cross-origin resources fetched with CORS, no longer unlocked by TAO alone. transferSize straddles the line — bytes on the wire are both content and network — so it requires both opt-ins. Firefox and Safari signalled support; WebKit today is stricter still, exposing body sizes only same-origin.
the API
const res = await fetch("https://cdn.example/lib.js"); // mode: "cors"
await res.blob(); // finish the body
const [entry] = performance.getEntriesByName(res.url).slice(-1);
entry.decodedBodySize; // bytes after decompression
entry.encodedBodySize; // bytes before decompression (as transferred body)
entry.transferSize; // body + ~header estimate; 0 for cache hits & when gated
// Gating for CROSS-ORIGIN resources:
// pre-158 Chrome Chrome 158+
// encoded/decodedBodySize: TAO -> CORS (response not opaque)
// transferSize: TAO -> CORS *and* TAO