- From: Mattias Buelens <notifications@github.com>
- Date: Wed, 26 Jan 2022 16:35:31 -0800
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/pull/1208/review/864259019@github.com>
@MattiasBuelens commented on this pull request. > @@ -475,6 +483,20 @@ function WritableStreamDefaultWriterGetDesiredSize(writer) { return WritableStreamDefaultControllerGetDesiredSize(stream._controller); } +function WritableStreamDefaultWriterIsOrBecomesErrored(writer, errorListener) { Oh boy, this is a can of worms... 😅 Making `waitForWritesToFinish()` possibly synchronous (https://github.com/MattiasBuelens/streams/commit/7eef3d2ccd447f674b2b2f82b4651201a91cd6d0) allows weird things to happen: 1. `pipeTo()` calls `ReadableStreamDefaultReaderRead()`, reading the *last* chunk of the stream. 2. `ReadableStreamDefaultController[[PullSteps]]` dequeues the chunk, and notices that the queue is now empty *and* close was requested. So it calls `ReadableStreamClose()`. 3. `ReadableStreamClose` changes `[[state]]` to `"closed"`, which fires `pipeTo()`'s state change listener. 4. `pipeTo()` starts the shutdown process. There's no pending write, so it immediately finalizes the pipe and releases both the reader and the writer. 5. The call stack unwinds up to `ReadableStreamDefaultController[[PullSteps]]`. We continue with `readRequest.chunkSteps()`. 6. `chunkSteps()` brings us back inside `pipeTo()`. It now wants to start a new write for this chunk, *but we've already released the writer.* 💥 This wasn't a problem before, since even if we never actually started a write, `currentWrite` would still be initialized to `Promise.resolve(undefined)`. `waitForWritesToFinish()` would always have to wait at least one microtask to detect that this is indeed the last write, which is enough time for `chunkSteps()` to *actually* start a new write on time. The root of the problem is that the state change listener is called *in the middle* of `ReadableStreamDefaultReaderRead()`, before we call `chunkSteps()`. * We could try to only call the state change listeners *at the end* of all "top-level" abstract ops. That is, instead of calling them within the internal `ReadableStreamClose()`, we call them at the end of `ReadableStreamDefaultReaderRead()` etc. However, this could quickly become unmaintainable. 😕 * We could have `pipeTo()` "remember" that it still has a pending read, and *wait* until either its `chunkSteps`, `closeSteps` or `errorSteps` have been called before finalizing the pipe. But then I'm not sure if `waitForWritesToFinish()` would still be synchronous in the cases where it matters... 🤔 -- Reply to this email directly or view it on GitHub: https://github.com/whatwg/streams/pull/1208#discussion_r793162698 You are receiving this because you are subscribed to this thread. Message ID: <whatwg/streams/pull/1208/review/864259019@github.com>
Received on Thursday, 27 January 2022 00:35:43 UTC