-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ReadableStreamBYOBReader.prototype.read(view, { min }) #1145
Add ReadableStreamBYOBReader.prototype.read(view, { min }) #1145
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems way too easy! I expected something more like the manual loop you would have to do if writing this in userspace.
If it works, I definitely like this approach. I imagine tests will let us know if it does...
I looked at a few other languages to see what their API looks like:
It looks like most other languages throw an error if they encounter EOF before completely filling the buffer. That said, the Streams standard already takes a different approach for "regular" reads too: instead of returning the number of bytes read into the given buffer, we transfer the given buffer and return a If we want to bikeshed a bit on the name, here are some ideas:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose we should update (or remove) the readInto()
example too? Since that can be now replaced with a single readFully()
call.
I've been thinking about whether we want to expose
So yeah, it might be an optimization opportunity, but it might also be a footgun. At least for now, I'll leave |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay. This LGTM with the minor potential improvement of combining the boolean with reader type. @ricea do you think we could implement this? Shouldn't take long...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With regards to the spec, this looks good.
Sorry to show up late with a bikeshed, but I like the name fill()
. reader.fill(view)
feels good to me. Disadvantages: no precedent for the name, and it would a nuisance to change all the tests and everything now. It may be to harder to find (but the reader doesn't have so many methods that it would be lost in the noise). I'm just suggesting it to see how others feel.
Regarding implementation in Blink, I think this clearly fixes an ergonomic problem. Some people expect read()
to work this way already. Implementation is stuck behind #1123 and other things that are higher priority.
Sure, If we still don't like it, it's pretty easy to change/revert that last commit. Bikeshed away! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm. I like this very much.
I take it that means Chrome is interested in implementing this? (Gotta tick those checkboxes! 😁) |
Yes, you can tick the checkbox for Chrome. |
d21b423
to
3e897a3
Compare
3e897a3
to
dbd60c1
Compare
1e427ce
to
86b6982
Compare
Updated to use We can still introduce Currently, the tests only cover the |
Thanks! I am happy not to have |
Deno is interested in implementing this. |
559eea4
to
bd9b335
Compare
1abba02
to
b8a96d7
Compare
A little bikeshedding: how do we feel about the name const { done, value } = byobReader.read(view, { min: 8 });
// value is minimum 8 elements long |
Oh, and while merging, please change the title to avoid my pet peeve of using |
Woo! super happy to see this land. Thanks for the work all. |
…BReader.read(view, { min }), a=testonly Automatic update from web-platform-tests Streams: add tests for ReadableStreamBYOBReader read(view, { min }) Follows whatwg/streams#1145. -- wpt-commits: 7eaf605c38d80377c717828376deabad86b702b2 wpt-pr: 29723
…BReader.read(view, { min }), a=testonly Automatic update from web-platform-tests Streams: add tests for ReadableStreamBYOBReader read(view, { min }) Follows whatwg/streams#1145. -- wpt-commits: 7eaf605c38d80377c717828376deabad86b702b2 wpt-pr: 29723
…BReader.read(view, { min }), a=testonly Automatic update from web-platform-tests Streams: add tests for ReadableStreamBYOBReader read(view, { min }) Follows whatwg/streams#1145. -- wpt-commits: 7eaf605c38d80377c717828376deabad86b702b2 wpt-pr: 29723
…BReader.read(view, { min }), a=testonly Automatic update from web-platform-tests Streams: add tests for ReadableStreamBYOBReader read(view, { min }) Follows whatwg/streams#1145. -- wpt-commits: 7eaf605c38d80377c717828376deabad86b702b2 wpt-pr: 29723
…BReader.read(view, { min }), a=testonly Automatic update from web-platform-tests Streams: add tests for ReadableStreamBYOBReader read(view, { min }) Follows whatwg/streams#1145. -- wpt-commits: 7eaf605c38d80377c717828376deabad86b702b2 wpt-pr: 29723 UltraBlame original commit: 820875020074b1b3ca04fde919a52f2fd580bbbb
…BReader.read(view, { min }), a=testonly Automatic update from web-platform-tests Streams: add tests for ReadableStreamBYOBReader read(view, { min }) Follows whatwg/streams#1145. -- wpt-commits: 7eaf605c38d80377c717828376deabad86b702b2 wpt-pr: 29723 UltraBlame original commit: 820875020074b1b3ca04fde919a52f2fd580bbbb
…BReader.read(view, { min }), a=testonly Automatic update from web-platform-tests Streams: add tests for ReadableStreamBYOBReader read(view, { min }) Follows whatwg/streams#1145. -- wpt-commits: 7eaf605c38d80377c717828376deabad86b702b2 wpt-pr: 29723 UltraBlame original commit: 820875020074b1b3ca04fde919a52f2fd580bbbb
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225 UltraBlame original commit: df7878660191f4991ce6a5898629c963b38a6e50
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225 UltraBlame original commit: 56a71d42ee3220891aa1cb2dfae5df8f544865f9
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225 UltraBlame original commit: df7878660191f4991ce6a5898629c963b38a6e50
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225 UltraBlame original commit: 56a71d42ee3220891aa1cb2dfae5df8f544865f9
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225 UltraBlame original commit: df7878660191f4991ce6a5898629c963b38a6e50
… }). r=saschanaz,webidl,smaug Implements whatwg/streams#1145 Differential Revision: https://phabricator.services.mozilla.com/D226225 UltraBlame original commit: 56a71d42ee3220891aa1cb2dfae5df8f544865f9
Implements #1143 and #1175.
In my first attempt, I did most of the heavy lifting in a
ReadableStreamBYOBReaderReadFully()
helper that callsread(view)
. If the first read didn't fill the entire view yet, it immediately callsread(view)
again but with a special "addToFront" flag so that the new read-into request goes to the front of the queue rather than the back. This works fine, but it's not very pretty. It also means we're possibly callingread(view)
re-entrantly from withinReadIntoRequest.chunkSteps()
, which is somewhat pushing the boundaries of what you can reasonably expect from the spec. 😬 (I've kept this attempt in the commit history, so you can judge for yourselves.)I then realized that we already have logic that keeps a read-into request in the queue after a
respond()
. When the user performs a BYOB read with a multi-byte typed array, the stream only fulfills the request when at leastelementSize
have been written into the pull-into descriptor. If not, the request stays pending and the pull-into descriptor remains at the head of the queue. Therefore, in my second attempt, I add a special type of pull-into descriptor which must stay in the queue as long asbytesFilled < byteLength
, rather than the usualbytesFilled < elementSize
. This also works very well, but requires changes across multiple parts of the code.In #1175, we realized that it would be more powerful to allow reading at least a given number of bytes, rather than reading an exact number of bytes. Thus, in my third attempt, every pull-into descriptor now has a "minimum fill" slot that tracks how many bytes must be filled before this descriptor can fulfill its associated
read(view)
request. As a result, thebytesFilled < elementSize
andbytesFilled < byteLength
conditions from the previous solution are now replaced with a singlebytesFilled < minimumFill
condition. This greatly simplifies the logic.To do:
byobReader.read(view, { min })
Do we still wantbyobReader.fill(view)
too? This would basically be a shorthand forread()
wheremin = view.length
@ricea
, per comment)@annevk
, per comment)ReadableStreamBYOBReader.prototype.read(view, { min })
nodejs/node#50706(See WHATWG Working Mode: Changes for more details.)
Preview | Diff