- From: Mattias Buelens <notifications@github.com>
- Date: Wed, 05 Jan 2022 09:55:19 -0800
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/pull/1168/review/844884731@github.com>
@MattiasBuelens commented on this pull request.
> + 1. Perform ? [$ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue$](|controller|,
+ |firstPendingPullInto|).
This bit is tricky. `controller.enqueue()` may throw because we failed to allocate a new `ArrayBuffer` to hold any remaining bytes from a now-detached BYOB request:
```javascript
let controller;
const readable = new ReadableStream({
type: 'bytes',
start(c) { controller = c }
});
const reader1 = readable.getReader({ mode: 'byob' });
reader1.read(new Uint16Array(1));
// controller.byobRequest.view.byteLength === 2
controller.byobRequest.view[0] = 0xaa;
controller.byobRequest.respond(1);
// not enough to fill the BYOB request, so read() remains pending
// controller.byobRequest.view.byteOffset === 1
// controller.byobRequest.view.byteLength === 1
reader1.releaseLock();
// BYOB request becomes detached from request, but we cannot invalidate it yet
// since the underlying byte source might still be using it
controller.enqueue(new Uint8Array([0xbb]));
// At this point, we must move the bytes from the BYOB request ([0xaa]) into the stream's queue,
// and then push the new chunk ([0xbb]) onto the queue.
// However, moving those bytes means allocating a new ArrayBuffer containing that sub-slice,
// which might fail... and then what do we do? ๐คทโโ๏ธ
```
What should the stream do in that case?
* We must not drop any data, so the `[0xaa]` byte has to somehow end up in the queue. We do have ownership over the original `ArrayBuffer`, so it would be nice if we could just "shrink" that buffer somehow without reallocating...
* If we can't prevent data loss, should we error the stream instead? It's kinda weird though.
> @@ -3196,6 +3255,20 @@ The following abstract operations support the implementation of the
|controller|.[=ReadableByteStreamController/[[queueTotalSize]]=] + |byteLength|.
</div>
+<div algorithm>
+ <dfn abstract-op lt="ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue">ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue(|controller|,
Better name suggestions are welcome. ๐
> + 1. Set [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=] to the [=list=]
+ ยซ |firstPendingPullInto| ยป.
Alternatively, we could write:
> Remove all pull-into descriptors after *firstPendingPullInto* from this.\[[pendingPullIntos]].
or:
> Remove all pull-into descriptors whose index is not 0 from this.\[[pendingPullIntos]].
but I don't know if that's a correct usage of [remove](https://infra.spec.whatwg.org/#list-remove). ๐
> + 1. Perform ? [$ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue$](|controller|,
+ |firstPendingPullInto|).
We could also make `ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue` *not* copy the buffer and instead do:
```javascript
ReadableByteStreamControllerEnqueueChunkToQueue(
controller,
firstDescriptor.buffer,
firstDescriptor.byteOffset,
firstDescriptor.bytesFilled
);
```
But then there's the risk that when a default reader receives this chunk, we could "leak" data before `byteOffset` or after `byteOffset + bytesFilled` which came from a previous BYOB reader. ๐
Or perhaps we could fix that leak by doing a copy inside `ReadableByteStreamControllerFillReadRequestFromQueue` instead? But then again, *that* could throw an OOM error too... ๐
--
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/pull/1168#pullrequestreview-844884731
You are receiving this because you are subscribed to this thread.
Message ID: <whatwg/streams/pull/1168/review/844884731@github.com>
Received on Wednesday, 5 January 2022 17:55:32 UTC