Skip to content
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

Merged
merged 43 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
db1985e
Add ReadableStreamBYOBReader.readFully() (first attempt)
MattiasBuelens Jul 12, 2021
13d5794
Revert "Add ReadableStreamBYOBReader.readFully() (first attempt)"
MattiasBuelens Jul 15, 2021
cce92e2
Add ReadableStreamBYOBReader.readFully()
MattiasBuelens Jul 15, 2021
0326e95
Use dual asserts
MattiasBuelens Jul 19, 2021
864e010
Remove unused default value
MattiasBuelens Jul 19, 2021
09a199b
Explain why we keep the readFully() pull-into descriptor at the head …
MattiasBuelens Jul 19, 2021
5730f08
Roll WPT
MattiasBuelens Jul 20, 2021
8ab2bbc
Fix typos
MattiasBuelens Jul 21, 2021
78d2711
Add spec text for readFully()
MattiasBuelens Jul 21, 2021
101fa7f
Tweak note
MattiasBuelens Jul 21, 2021
405cfb1
Add note about readFully() in readInto() example
MattiasBuelens Jul 21, 2021
345eb40
Always copy all queued bytes if readFully descriptor is not yet full
MattiasBuelens Jul 22, 2021
3201762
Roll WPT
MattiasBuelens Jul 22, 2021
b7c89fb
Simplify
MattiasBuelens Jul 22, 2021
9725a70
Roll WPT
MattiasBuelens Aug 1, 2021
d3bc471
Replace "theChunk" and "theView" with "newView"
MattiasBuelens Aug 19, 2021
0d968aa
Fix extra space
MattiasBuelens Aug 19, 2021
e9efa23
Explain newView.byteLength
MattiasBuelens Aug 19, 2021
c8a4dfc
Rename readFully() to fill()
MattiasBuelens Aug 19, 2021
51dc85b
Roll WPT
MattiasBuelens Aug 19, 2021
e6b1218
Generalize fill(view)
MattiasBuelens Oct 13, 2021
5d967c9
Rename
MattiasBuelens Oct 14, 2021
511b3ae
Update spec text
MattiasBuelens Jan 18, 2022
66dd27b
Add atLeast option to byobReader.read()
MattiasBuelens Oct 14, 2021
3f1f12f
Remove fill(view)
MattiasBuelens Jan 18, 2022
d7ae44e
Roll WPT
MattiasBuelens Jan 18, 2022
1e1d6c6
Fix note
MattiasBuelens Jan 18, 2022
15409a3
Reject with a TypeError if atLeast is 0
MattiasBuelens Apr 12, 2022
2b11471
Roll WPT
MattiasBuelens Apr 12, 2022
1f3d73f
Rename "atLeast" to "min"
MattiasBuelens Apr 28, 2022
3bc1283
Roll WPT
MattiasBuelens Apr 28, 2022
f1572e5
Roll WPT
MattiasBuelens Apr 28, 2022
78f7adc
Fix typo
MattiasBuelens Jun 9, 2023
6f5196a
Set ReadableStreamBYOBReaderReadOptions.min = 1 by default
MattiasBuelens Sep 16, 2023
8f2e4a4
Roll WPT
MattiasBuelens Sep 16, 2023
d17aeca
Rename minimumFill to min in ReadableStreamBYOBReaderRead, and make r…
MattiasBuelens Sep 16, 2023
e381f25
Move readIntoRequest to last argument
MattiasBuelens Sep 16, 2023
c39be05
Fix lint error
MattiasBuelens Sep 16, 2023
9351f13
Small improvements
domenic Sep 28, 2023
c09f1c7
Merge branch 'main' into rs-byob-read-fully
MattiasBuelens Sep 30, 2023
99b7f42
Roll WPT
MattiasBuelens Sep 30, 2023
547805f
Replace "x mod y" with "the remainder after dividing x by y"
MattiasBuelens Nov 10, 2023
b938532
Roll WPT
MattiasBuelens Nov 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 132 additions & 39 deletions index.bs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ exports.implementation = class ReadableByteStreamControllerImpl {
byteOffset: 0,
byteLength: autoAllocateChunkSize,
bytesFilled: 0,
minimumFill: 1,
elementSize: 1,
viewConstructor: Uint8Array,
readerType: 'default'
Expand Down
21 changes: 19 additions & 2 deletions reference-implementation/lib/ReadableStreamBYOBReader-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ReadableStreamBYOBReaderImpl {
aos.SetUpReadableStreamBYOBReader(this, stream);
}

read(view) {
read(view, options) {
if (view.byteLength === 0) {
return promiseRejectedWith(new TypeError('view must have non-zero byteLength'));
}
Expand All @@ -22,6 +22,23 @@ class ReadableStreamBYOBReaderImpl {
return promiseRejectedWith(new TypeError('view\'s buffer has been detached'));
}

if (options.min === 0) {
return promiseRejectedWith(
new TypeError('options.min must be greater than 0')
);
}
if (view.constructor !== DataView) {
if (options.min > view.length) {
return promiseRejectedWith(
new RangeError('options.min must be less than or equal to view\'s length')
);
}
} else if (options.min > view.byteLength) {
return promiseRejectedWith(
new RangeError('options.min must be less than or equal to view\'s byteLength')
);
}

if (this._stream === undefined) {
return promiseRejectedWith(readerLockException('read'));
}
Expand All @@ -32,7 +49,7 @@ class ReadableStreamBYOBReaderImpl {
closeSteps: chunk => resolvePromise(promise, { value: chunk, done: true }),
errorSteps: e => rejectPromise(promise, e)
};
aos.ReadableStreamBYOBReaderRead(this, view, readIntoRequest);
aos.ReadableStreamBYOBReaderRead(this, view, options.min, readIntoRequest);
return promise;
}

Expand Down
6 changes: 5 additions & 1 deletion reference-implementation/lib/ReadableStreamBYOBReader.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
interface ReadableStreamBYOBReader {
constructor(ReadableStream stream);

Promise<ReadableStreamReadResult> read(ArrayBufferView view);
Promise<ReadableStreamReadResult> read(ArrayBufferView view, optional ReadableStreamBYOBReaderReadOptions options = {});
undefined releaseLock();
};
ReadableStreamBYOBReader includes ReadableStreamGenericReader;

dictionary ReadableStreamBYOBReaderReadOptions {
[EnforceRange] unsigned long long min = 1;
};
37 changes: 22 additions & 15 deletions reference-implementation/lib/abstract-ops/readable-streams.js
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ function ReadableByteStreamTee(stream) {
reading = false;
}
};
ReadableStreamBYOBReaderRead(reader, view, readIntoRequest);
ReadableStreamBYOBReaderRead(reader, view, 1, readIntoRequest);
}

function pull1Algorithm() {
Expand Down Expand Up @@ -913,7 +913,7 @@ function ReadableStreamReaderGenericRelease(reader) {
reader._stream = undefined;
}

function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) {
function ReadableStreamBYOBReaderRead(reader, view, min, readIntoRequest) {
const stream = reader._stream;

assert(stream !== undefined);
Expand All @@ -923,7 +923,7 @@ function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) {
if (stream._state === 'errored') {
readIntoRequest.errorSteps(stream._storedError);
} else {
ReadableByteStreamControllerPullInto(stream._controller, view, readIntoRequest);
ReadableByteStreamControllerPullInto(stream._controller, view, min, readIntoRequest);
}
}

Expand Down Expand Up @@ -1272,7 +1272,7 @@ function ReadableByteStreamControllerClose(controller) {

if (controller._pendingPullIntos.length > 0) {
const firstPendingPullInto = controller._pendingPullIntos[0];
if (firstPendingPullInto.bytesFilled > 0) {
if (firstPendingPullInto.bytesFilled % firstPendingPullInto.elementSize !== 0) {
const e = new TypeError('Insufficient bytes to fill elements in the given buffer');
ReadableByteStreamControllerError(controller, e);

Expand All @@ -1290,7 +1290,7 @@ function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDe

let done = false;
if (stream._state === 'closed') {
assert(pullIntoDescriptor.bytesFilled === 0);
assert(pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize === 0);
done = true;
}

Expand Down Expand Up @@ -1419,18 +1419,18 @@ function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size
}

function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) {
const elementSize = pullIntoDescriptor.elementSize;

const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize;

const maxBytesToCopy = Math.min(controller._queueTotalSize,
pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled);
const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize;

let totalBytesToCopyRemaining = maxBytesToCopy;
let ready = false;
if (maxAlignedBytes > currentAlignedBytes) {
assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.minimumFill);
const remainderBytes = maxBytesFilled % pullIntoDescriptor.elementSize;
const maxAlignedBytes = maxBytesFilled - remainderBytes;
// A descriptor for a read() request that is not yet filled up to its minimum length will stay at the head
// of the queue, so the underlying source can keep filling it.
if (maxAlignedBytes >= pullIntoDescriptor.minimumFill) {
totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled;
ready = true;
}
Expand Down Expand Up @@ -1461,7 +1461,7 @@ function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller,
if (ready === false) {
assert(controller._queueTotalSize === 0);
assert(pullIntoDescriptor.bytesFilled > 0);
assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize);
assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.minimumFill);
}

return ready;
Expand Down Expand Up @@ -1563,14 +1563,18 @@ function ReadableByteStreamControllerProcessReadRequestsUsingQueue(controller) {
}
}

function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) {
function ReadableByteStreamControllerPullInto(controller, view, min, readIntoRequest) {
const stream = controller._stream;

let elementSize = 1;
if (view.constructor !== DataView) {
elementSize = view.constructor.BYTES_PER_ELEMENT;
}

const minimumFill = min * elementSize;
assert(minimumFill >= elementSize && minimumFill <= view.byteLength);
assert(minimumFill % elementSize === 0);

const ctor = view.constructor;

let buffer;
Expand All @@ -1587,6 +1591,7 @@ function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest)
byteOffset: view.byteOffset,
byteLength: view.byteLength,
bytesFilled: 0,
minimumFill,
elementSize,
viewConstructor: ctor,
readerType: 'byob'
Expand Down Expand Up @@ -1660,7 +1665,7 @@ function ReadableByteStreamControllerRespond(controller, bytesWritten) {
}

function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) {
assert(firstDescriptor.bytesFilled === 0);
assert(firstDescriptor.bytesFilled % firstDescriptor.elementSize === 0);
MattiasBuelens marked this conversation as resolved.
Show resolved Hide resolved

if (firstDescriptor.readerType === 'none') {
ReadableByteStreamControllerShiftPendingPullInto(controller);
Expand All @@ -1686,7 +1691,9 @@ function ReadableByteStreamControllerRespondInReadableState(controller, bytesWri
return;
}

if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) {
if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.minimumFill) {
// A descriptor for a read() request that is not yet filled up to its minimum length will stay at the head
// of the queue, so the underlying source can keep filling it.
return;
MattiasBuelens marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
2 changes: 1 addition & 1 deletion reference-implementation/web-platform-tests
Loading