Open MattiasBuelens opened 2 years ago
This does have the side effect of releasing the reader before the pipe promise resolves. I don't know if this is acceptable.
Hmm, this means that the pipe could still cancel the readable after it has released its reader lock but before it settles the pipe promise. That might be quite unexpected: the user might have already acquired a new reader, and only that new reader should have the ability to cancel the stream.
Possible solutions:
ReadableStream(Default|BYOB)Release
, such that the read requests are already rejected but the reader is still locked to the stream. We would then actually release the reader as part of the "finalize" steps (as in the current spec).Option 2 is probably the easiest to implement, but it may require a note to explain why this weird "release + acquire" dance is necessary. Then again, we already mention that:
the exact manner in which this happens is not observable to author code, and so there is flexibility in how this is done
so user agents are free to implement these steps differently if they want. 🤷♂️
Yes, they're equivalent. I'll go with option 2. 👍
I've generalized the implementation a bit. I added two new helpers:
readerAddStateChangeListener(reader, stateChangeListener)
stateChangeListener
the next time reader._stream._state
changes.writerAddStateChangeListener(writer, stateChangeListener)
stateChangeListener
the next time writer._stream._state
changes.The pipeTo()
reference implementation now uses these helpers instead of reader._closedPromise
and writer._closedPromise
to detect state changes. A checkState()
helper checks the shutdown conditions when the pipe starts, and when the state of one of the streams changes.
This should handle all possible synchronous state transitions, and check the shutdown conditions in the correct order as specified by the standard's text.
(Perhaps we want to also use these helpers for tee()
, and possibly eliminate the extra microtask from readRequest's chunk steps there? I'll leave that for another time though. 😛)
In #1207, we raised concern about whether it's currently possible for
pipeTo()
to drop chunks when the pipe shuts down while it still has a pending read request.It turns out that this is indeed possible. The new WPT tests demonstrate at least one way this can happen: by aborting a pipe with an
AbortSignal
, and then enqueuing a chunk immediately after aborting the signal.This PR fixes this by releasing the pipe's reader immediately when starting the shutdown process, rather than when it finalizes the shutdown. This ensures that any pending reads that were started are immediately rejected, and the chunks stay in the source's queue.
~This does have the side effect of releasing the reader before the pipe promise resolves. I don't know if this is acceptable.~ Fixed in https://github.com/whatwg/streams/pull/1208#issuecomment-1015911238.
(See WHATWG Working Mode: Changes for more details.)
Preview | Diff