- From: Mattias Buelens <notifications@github.com>
- Date: Thu, 20 Jan 2022 13:34:25 -0800
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1207/1017947644@github.com>
Thinking about it some more, I don't think that will work. I think I got a bit confused when I wrote my previous reply. 😬
The problem is not that we *start* a new read after the destination has become errored. We're already awaiting `writer.ready` which is always rejected *immediately* in [step 8 of WritableStreamStartErroring](https://streams.spec.whatwg.org/commit-snapshots/908ceddfb813ec0d9c727393edfb13d810e694f1/#writable-stream-start-erroring). It *might* be possible that the destination becomes errored *during the same microtask* that `writer.ready` becomes resolved, so a synchronous check may still be appropriate.
The real problem is when there's *already* a pending read, and *then* the destination becomes errored at the same time that a chunk is enqueued onto the source. So:
```javascript
writableController.error("💥");
readableController.enqueue("a");
```
Erroring the writable will *asynchronously* reject `writer.closed`, but enqueuing a chunk will *synchronously* call the read request's chunk steps. Even if we added a synchronous check [here](https://github.com/whatwg/streams/blob/908ceddfb813ec0d9c727393edfb13d810e694f1/reference-implementation/lib/abstract-ops/readable-streams.js#L204-L217):
```javascript
ReadableStreamDefaultReaderRead(
reader,
{
chunkSteps: chunk => {
if (dest._state !== 'writable') {
// ...now what? 🤷♂️
}
currentWrite = transformPromiseWith(
WritableStreamDefaultWriterWrite(writer, chunk), undefined, () => {}
);
resolveRead(false);
},
closeSteps: () => resolveRead(true),
errorSteps: rejectRead
}
);
```
...we would still be unable to do anything useful with `chunk`. Ideally, we'd put it back *at the start* of the source's queue, but we don't have a way to do that.
The only way we can avoid this is if we can *synchronously* release the reader as soon as the destination becomes errored, i.e. attach an error callback to the writer.
(Note that doing `enqueue()` followed by `error()` *can* result in the newly enqueued chunk being successfully written to the destination *before* the destination becomes errored. The read request's chunk steps synchronously call `writer.write()`, which can synchronously call `sink.write()` and complete the write. So we don't "accidentally" drop a chunk in this case.)
--
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/1207#issuecomment-1017947644
You are receiving this because you are subscribed to this thread.
Message ID: <whatwg/streams/issues/1207/1017947644@github.com>
Received on Thursday, 20 January 2022 21:34:38 UTC