- 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