[whatwg/streams] Writing twice synchronously on a native no-backpressure WritableStream may have surprising effects (Issue #1385)

youennf created an issue (whatwg/streams#1385)

### What is the issue with the Streams Standard?

[VideoTrackGenerator](https://w3c.github.io/mediacapture-transform/#dom-videotrackgenerator-writable) or [RTCRtpScriptTransformer.writable](https://w3c.github.io/webrtc-encoded-transform/#dom-rtcrtpscripttransformer-writable) have the same principle:
- They apply no backpressure
- They mutate the JS objects (closing the VideoFrame or transferring the RTCEncodedFrame data member)

When a website calls synchronously twice `WritableStream.write`, the following happens:
1. JS calls writer.write(A)
2. A is sent to the native sink writeAlgorithm, which will convert the JS object to an IDL object and mutate it. Native sink returns a resolved promise.
3. JS can validate that A is mutated synchronously.
4. JS calls writer.write(B)
5. B is not sent to the native sink yet
6. JS can validate that B is not mutated. It can mutate it after having written it.
7. Wait a microtask
8. B is sent to the native sink writeAlgorithm, which will convert the JS object to an IDL object and mutate it.
9. JS can validate that B is mutated.

From tests I have done, this behavior is supported in all browsers (https://codepen.io/editor/youennf/pen/01a120dd-c51e-7415-a78b-2c1a1f79f8e3 for VideoTrackGenerator and https://codepen.io/editor/youennf/pen/01a120e3-ea49-7b84-9c85-96d27c516821 for RTCRtpScriptTransformer).

While this follows spec, this is somehow surprising and could lead to bugs.
For instance, if we had defined a direct `RTCRtpScriptTransformer.write`, the WebIDL conversion and the mutation of the chunks would certainly be done synchronously (the remaining work being anyway done in parallel).

I wonder whether we could allow native sinks that never apply any backpressure to be allowed to always process chunks synchronously.

In spec terms, this could mean that https://streams.spec.whatwg.org/#writable-stream-default-controller-process-write would have an option to run the upon fulfilment steps synchronously, for those native sinks that never apply backpressure.

The downsides of this approach is of course that some streams could behave slightly differently from others, which makes me a bit hesitant to push for this.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/1385
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/streams/issues/1385@github.com>

Received on Friday, 9 October 2026 14:18:47 UTC