- From: Mattias Buelens <notifications@github.com>
- Date: Fri, 06 Aug 2021 15:19:28 -0700
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1158@github.com>
Right now, piping to a writable stream with `{ highWaterMark: 0 }` stalls indefinitely: ```javascript const rs = new ReadableStream({ start(c) { c.enqueue("a"); c.enqueue("b"); c.enqueue("c"); c.close(); } }); const ws = new WritableStream({ write(chunk) { console.log("wrote:", chunk); } }, { highWaterMark: 0 }); rs.pipeTo(ws); // never resolves, and no messages are logged ``` This makes it impossible to pipe through a `TransformStream` without increasing the total queue size of a pipe chain by at least one chunk: ```javascript const upperCaseTransform = new TransformStream({ transform(chunk, controller) { controller.enqueue(chunk.toUpperCase()); } }, { highWaterMark: 0 }, { highWaterMark: 0 }); rs.pipeThrough(upperCaseTransform).pipeTo(ws); // stalls indefinitely const upperCaseTransform = new TransformStream({ transform(chunk, controller) { controller.enqueue(chunk.toUpperCase()); } }, { highWaterMark: 1 }, { highWaterMark: 0 }); // same as default strategies rs.pipeThrough(upperCaseTransform); // works, but already pulls the first chunk from `rs` ``` This is unfortunate, since there are many use cases for synchronous `TransformStream`s that shouldn't need buffering (i.e. every call to `transform()` immediately results in at least one `enqueue()`): * A generic `mapTransform(fn)`, similar to `array.map(fn)`: ```javascript function mapTransform(fn) { return new TransformStream({ transform(chunk, controller) { controller.enqueue(fn(chunk)); } }); } rs.pipeThrough(mapTransform(x => x.toUpperCase())); ``` * `TextEncoderStream` and `TextDecoderStream` from [Encoding](https://encoding.spec.whatwg.org/). Prior discussions on this topic noted that this is not possible. `writer.desiredSize` is always `<= 0`, so `writer.ready` is always pending: * #777: > We can't reduce the HWM of the writableStrategy to 0 because it would have permanent backpressure preventing the pipe from working. * [#1083](https://github.com/whatwg/streams/pull/1083#discussion_r562292762): > Yes. As you observed, a writable stream with a HWM of 0 will always have backpressure. So adding an identity TransformStream to a pipe can't be a complete no-op: it always increases the total queue size by 1. But that got me thinking. A `ReadableStream`'s source can be `pull()`ed as a result of `reader.read()`, even if `controller.desiredSize <= 0`. Maybe a `WritableStream`'s sink should then also be able to release backpressure even if `writer.desiredSize <= 0`? 🤔 We could add a method on `WritableStreamDefaultController` (`controller.pull()`? `controller.releaseBackpressure()`? `controller.notifyReady()`?) that would have the result of immediately resolving the current `writer.ready` promise. Internally, we would do something like `WritableStreamUpdateBackpressure(stream, false)`. My hope is that we can then use this inside `TransformStreamSetBackpressure()`, so that pulling from the readable end of a transform stream would also resolve `ready` on the writable end. ...Or am I missing something very obvious? 😛 -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/whatwg/streams/issues/1158
Received on Friday, 6 August 2021 22:19:41 UTC