- From: Mattias Buelens <notifications@github.com>
- Date: Mon, 12 Jul 2021 15:15:44 -0700
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1143@github.com>
As suggested in [#1019 (comment)](https://github.com/whatwg/streams/issues/1019#issuecomment-565499158), developers may want to read into a BYOB buffer until it is *completely filled* (instead of only *partially* filling it with however many bytes the underlying source provides). We already have [an example for this](https://streams.spec.whatwg.org/commit-snapshots/cada8129edcc4803b2878a7a3f5e1d8325dc0c23/#example-manual-read-bytes) with a `readInto()` helper function, but it may be worth integrating this into the standard itself for better ergonomics and/or optimization opportunities. Concretely, I suggest we extend `ReadableStreamBYOBReader`: ``` interface ReadableStreamBYOBReader { Promise<ReadableStreamBYOBReadResult> readFully(ArrayBufferView view); }; ``` This method performs a BYOB read into `view`: * If the underlying source responds with `n` bytes where `n < view.byteLength`, then the stream will immediately start pulling again with the "remainder" of `view` (i.e. `view.subarray(n)`, assuming `view` is a `Uint8Array`). * If the underlying source responds with `n` bytes where `n === view.byteLength`, then the method fulfills with `{ done: false, value }` where `value` is the completely filled view. * If the underlying source closes before the view is completely filled, then the method fulfills with `{ done: true, value }` where `value` is the (partially) filled view. * If the underlying source cancels, then the method returns with `{ done: true, value: undefined }`, like with regular BYOB reads. Some remarks: * We can't return a `Promise<ArrayBufferView>`, because then you wouldn't know if the stream is closed. Also, this wouldn't work if the stream is cancelled... unless we're okay with returning `Promise<undefined>` in that case (which I personally don't find very pretty). * We have to be very careful with how we create a pull-into descriptor for the remainder. There may already be *other* pull-into descriptors into the queue, for example a user could do this: ```javascript let pullCount = 0; const rs = new ReadableStream({ type: 'bytes', pull(c) { ++pullCount; c.byobRequest.view[0] = pullCount; c.byobRequest.respond(1); } }); const reader = rs.getReader({ mode: 'byob' }); const read1 = reader.readFully(new Uint8Array(3)); const read2 = reader.read(new Uint8Array(1)); await read1; // should be [1, 2, 3], NOT [1, 3, 4] await read2; // should be [4], NOT [2] ``` One solution would be to have a "special type" for `readFully()` pull-into descriptors. Or another (simpler?) solution might be to always put the pull-into descriptor for the remainder *at the front of the `[[pendingPullIntos]]` queue* (rather than at the back). * Should we also have a shorthand `ReadableStream.readFully(view)`? Would it have the same signature, i.e. returning `Promise<ReadableStreamBYOBReadResult>`? -- 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/issues/1143
Received on Monday, 12 July 2021 22:15:58 UTC