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

@MattiasBuelens commented on this pull request.



> @@ -3205,7 +3442,7 @@ The following abstract operations support the implementation of the
  1. Let |firstDescriptor| be |controller|.[=ReadableByteStreamController/[[pendingPullIntos]]=][0].
  1. If |firstDescriptor|'s [=pull-into descriptor/byte offset=] + |firstDescriptor|' [=pull-into
     descriptor/bytes filled=] is not |view|.\[[ByteOffset]], throw a {{RangeError}} exception.
- 1. If |firstDescriptor|'s [=pull-into descriptor/byte length=] is not |view|.\[[ByteLength]], throw
+ 1. If |firstDescriptor|'s [=pull-into descriptor/byte length=] < |view|.\[[ByteLength]], throw

Note that [this example in the specification](https://streams.spec.whatwg.org/#example-manual-read-bytes) *relies* on `read()` returning a view on the same (transferred) buffer. Otherwise the `offset < buffer.byteLength` check wouldn't work, and you might read more or fewer bytes than initially requested. It also assumes that data from previous reads is still available in `buffer`, so the underlying byte source cannot change any of the bytes outside of `byobRequest.view` either.

To summarize, the caller of `byobRequest.respondWithNewView(newView)` (i.e. the underlying byte source) must guarantee the following:
* `newView.byteOffset` must equal `byobRequest.view.byteOffset`, and `newView.byteLength` must be `<= byobRequest.view.byteLength`.
* `newView.buffer` has the exact same `byteLength` as `byobRequest.view.buffer`. This can be done by either transferring the original buffer, or by copying it (although that would defeat the purpose of using a BYOB request).
* Within `newView.buffer`, the byte ranges from `0` to `byobRequest.view.byteOffset` and from `byobRequest.view.byteOffset + byobRequest.view.byteLength` to `byobRequest.view.buffer.byteLength` must be unmodified. In other words, only bytes within the range of `byobRequest.view` can be changed. (This also applies to `byobRequest.respond(bytesWritten)`.)

Currently, we check the first condition. We could *feasibly* check the second one, by remembering the original `byteLength` as part of the pull-into descriptor. However, it's not possible to check the third condition without copying the original buffer upfront, which would defeat the purpose of BYOB. So we have to *assume* that the developer doesn't do anything weird in their underlying byte source... 😅

-- 
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_r602722303

Received on Saturday, 27 March 2021 13:56:05 UTC