v158 · network · webtransport

WebTransportReceiveStream

Incoming WebTransport streams in Chromium have historically been plain ReadableStream objects. Chrome 158 gives them the type the spec has named all along: WebTransportReceiveStream, a ReadableStream subclass whose one addition is getStats() — per-stream byte counters separating what the network delivered (bytesReceived) from what your code has actually consumed (bytesRead).

concepts

  1. The subclass, member by member

    Interrogate the real interface object: the prototype chain down to ReadableStream, getStats as the subclass's own single addition, the illegal-constructor rule, and where instances actually come from on a live session.

  2. bytesReceived vs bytesRead

    The diagnosis the two counters exist for: is the network slow, or is your consumer? Probe the real stats surface, then drive a real ReadableStream producer/consumer rig — clearly labelled as a local stand-in — where the gap between the two counters is the backlog you can watch grow and drain.

  3. Migration: what old code sees

    A subclass is the compatible way to change a runtime type. Run the instanceof and own-property matrix that proves plain-ReadableStream code keeps working, and see the feature-detect branches new code should use — including Firefox's shipped-but-rejecting getStats.

why it shipped

Two reasons, one practical and one structural. Practically: an application receiving a large or latency-sensitive stream cannot tell browser-side buffering from network stall. getStats() splits the question — bytesReceived counts contiguous application bytes the browser has taken off the network for this stream, bytesRead counts what JavaScript has pulled out; a growing gap means your consumer is the bottleneck, not the connection. Structurally: the spec says incoming unidirectional streams and the readable half of bidirectional streams are WebTransportReceiveStreams, and Firefox and Safari already ship the type — exposing it aligns Chromium's runtime types with the spec and the other engines.

the API

interface WebTransportReceiveStream : ReadableStream {
  Promise<WebTransportReceiveStreamStats> getStats();
};
// stats: { bytesReceived, bytesRead }  — bytesRead ≤ bytesReceived

const reader = transport.incomingUnidirectionalStreams.getReader();
const { value: stream } = await reader.read();   // a WebTransportReceiveStream
const { bytesReceived, bytesRead } = await stream.getStats();
const bufferedInBrowser = bytesReceived - bytesRead;

references