Re: [whatwg/streams] Support teeing readable byte streams (#1114)

@MattiasBuelens commented on this pull request.



> +          if (forBranch2 === true) {
+            if (canceled1 === false) {
+              const clonedChunk = CloneArrayBufferView(chunk);
+              ReadableByteStreamControllerEnqueue(branch1._controller, clonedChunk);
+            }
+            if (canceled2 === true) {
+              chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, 0);
+            }
+            ReadableByteStreamControllerRespondWithNewView(branch2._controller, chunk);
+          } else {
+            if (canceled2 === false) {
+              const clonedChunk = CloneArrayBufferView(chunk);
+              ReadableByteStreamControllerEnqueue(branch2._controller, clonedChunk);
+            }
+            if (canceled1 === true) {
+              chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, 0);

This is a tricky one! This is how we get to this point:
1. _branch1_ pulls with a BYOB request. We call _pullWithBYOBReader_ with `forBranch2 = false`, and start a BYOB read on the original stream using the buffer from _branch1_'s BYOB request. Note that this **transfers control of the buffer** from _branch1_ to the original stream.
2. _branch1_ gets canceled. We set `canceled1 = true` in _cancel1Algorithm_. However, we cannot yet "finish" _branch1_'s BYOB request at this point, because we cannot yet return control of the BYOB request's buffer back to _branch1_. Any attempt to call `byobRequest.respond()` here would throw an "already transferred" error (at step 1 in [ReadableByteStreamControllerRespondInClosedState](https://streams.spec.whatwg.org/commit-snapshots/dd76a17a3738d78708a8dfd8f0508e717d6a1988/#readable-byte-stream-controller-respond-in-closed-state)).
3. The BYOB read on the original stream completes. We get passed _chunk_, filled with new data. But more importantly: we get control back over _chunk_'s underlying buffer! So **now** we can finally respond to _branch1_'s BYOB request. But we can't use `byobRequest.respond()`, since that will still try to use the old (transferred) buffer. We **have** to use `.respondWithNewView()` instead, so it'll use the new buffer.
4. Since `canceled1 === true`, `branch1.[[state]] === "closed"`. This means we **must** respond to the BYOB request with exactly 0 bytes written, as per step 3.1 in [ReadableByteStreamControllerRespondInternal](https://streams.spec.whatwg.org/commit-snapshots/dd76a17a3738d78708a8dfd8f0508e717d6a1988/#readable-byte-stream-controller-respond-internal). But the chunk *was* filled with some data (which we can still copy and pass to _branch2_), so we first have to turn the filled view into an empty one before responding.


-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/pull/1114#discussion_r601890120

Received on Thursday, 25 March 2021 22:55:15 UTC