- From: James M Snell <notifications@github.com>
- Date: Wed, 28 Feb 2024 07:40:58 -0800
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1307/1969256958@github.com>
Le's focus specifically on `ReadableStream` ... and just go through some of the scenarios to tease out the details (much of the following is obvious, I'm detailing it to make the conversation more concrete) If the `ReadableStream` is not locked, then Async-disposal being the equivalent of `await readable.cancel()` makes sense... but o course, if the `ReadableStream` is locked, `readable.cancel()` fails. So the following would necessarily fail because the reader is not defined as being disposed. ```js { await using rs = new ReadableStream(); const reader = rs.getReader(); } ``` If we define reader as being sync disposable such that it releases the lock, then the following should work just fine, releasing the lock then async canceling the stream... ```js { await using rs = new ReadableStream(); using reader = rs.getReader(); // equivalent to // reader.releaseLock() // await rs.cancel(); } ``` If the stream is locked to a reader, then I do think it is worth considering whether `async using reader` would be equivalent to `await reader.cancel()`: ```js { const rs = new ReadableStream(); await using reader = rs.getReader(); // equivalent to await reader.cancel(); } ``` This would make sense especially given the idea that the `Reader` is essentially viewed as taking ownership over the stream. But this can be a bit tricky, of course. In the pipeTo/pipeThrough scenario, the readable stream remains locked so `await readable.cancel()` would be expected to fail, so the following case would end with an error if `async using readable` assumes `await readable.cancel()` ```js let dest; { await using readable = new ReadableStream(); dest = readable.pipeThrough(new MyTransformStream()); // async dispose fails because readable is locked by the pipe } ``` But what if the destination is disposable? This should work fine, I think? The `dest` should be disposed of first, which should end up releasing the lock on `readable`, allowing it to be canceled? ```js { await using readable = new ReadableStream(); await using dest = readable.pipeThrough(new MyTransformStream()); } ``` For tee, yeah... that's a bit wonky. Not sure what to do here. ```js { await using readable = new ReadableStream(); const [b1, b2] = readable.tee(); // Async dispose fails because readable is locked } ``` ```js { await using readable = new ReadableStream(); await using [b1, b2] = readable.tee(); // Async dispose of the branches works fine... but // Async dispose of readable still fails since canceling the branches does not release the lock on readable } ``` Perhaps if we redefined it so that if all branches are canceled/closed the lock on the original stream is released? Another interesting question, which may actually be a question for the TC-39 proposal authors because I'm not sure if this would even be possible... If the block exists because an exception is thrown, should the pending exception be passed into the `readable.cancel(...)` call when disposing the stream? I don't think this is currently possible with the current spec tho... That is, for instance: ```js { async using readable = new ReadableStream(); throw new Error('boom'); // Should the async dispose be equivalent to `await readable.cancel(error)` where `error` is the error that is thrown } ``` -- Reply to this email directly or view it on GitHub: https://github.com/whatwg/streams/issues/1307#issuecomment-1969256958 You are receiving this because you are subscribed to this thread. Message ID: <whatwg/streams/issues/1307/1969256958@github.com>
Received on Wednesday, 28 February 2024 15:41:02 UTC