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

Various fixes for readable byte streams #1123

Merged
merged 44 commits into from
May 26, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c11ed1c
Throw when trying to enqueue/close after the BYOB request has been de…
MattiasBuelens Apr 9, 2021
be2cc14
Fix some links
MattiasBuelens Apr 9, 2021
858bebc
Ensure new view's buffer has same capacity as BYOB request's initial …
MattiasBuelens Apr 9, 2021
933db51
Allow passing a smaller view to BYOBRequest.respondWithNewView
MattiasBuelens Mar 20, 2021
b27f364
Allow passing an empty view to respondWithNewView() in closed state
MattiasBuelens Apr 9, 2021
01b6e78
Restrict pull-into descriptor's byte length to be non-zero
MattiasBuelens Apr 9, 2021
ec2af19
Fix check to match ReadableByteStreamControllerRespondInReadableState
MattiasBuelens Apr 16, 2021
7fdb8a5
Roll WPT
MattiasBuelens Apr 16, 2021
c475de8
Remove redundant check
MattiasBuelens Apr 17, 2021
98415ae
Fix missing ! before calls
MattiasBuelens Apr 19, 2021
22c5aa8
Add CanTransferArrayBuffer helper
MattiasBuelens Apr 19, 2021
882fc7c
Check [[ArrayBufferDetachKey]] in CanTransferArrayBuffer
MattiasBuelens Apr 19, 2021
afd3e81
Remove detached check from ReadableByteStreamController.close()
MattiasBuelens Apr 19, 2021
3d13462
Move detached pull-into buffer check to ReadableByteStreamControllerE…
MattiasBuelens Apr 19, 2021
2e55eda
Assert that pull-into descriptor is transferable in ReadableByteStrea…
MattiasBuelens Apr 19, 2021
ec48c0d
Check that respondWithNewView() is called with a transferable buffer
MattiasBuelens Apr 19, 2021
6608188
Check that enqueue() is called with a transferable buffer
MattiasBuelens Apr 19, 2021
6d4ea40
Remove redundant assert
MattiasBuelens Apr 19, 2021
63e4ced
Move checks for bytesWritten from RespondInternal() to Respond() and …
MattiasBuelens Apr 19, 2021
098889f
Don't error the stream if enqueue() fails because of a transferred BY…
MattiasBuelens Apr 19, 2021
efed1f5
Roll WPT
MattiasBuelens Apr 19, 2021
326ec81
Fix error message
MattiasBuelens Apr 19, 2021
7dad495
Check that view passed to byobReader.read() is transferable
MattiasBuelens Apr 19, 2021
e7b82bd
Always transfer the buffer when committing a pull-into descriptor
MattiasBuelens Apr 21, 2021
1b28987
Roll WPT
MattiasBuelens Apr 21, 2021
1002710
Always transfer first pull-into descriptor after enqueue() or respond()
MattiasBuelens Apr 23, 2021
458f95c
Move check up a bit
MattiasBuelens Apr 23, 2021
ea2aa01
Invalidate BYOB request on every enqueue(), respond() or respondWithN…
MattiasBuelens Apr 23, 2021
5da8d5c
Roll WPT
MattiasBuelens Apr 23, 2021
9382dc3
Make TransferArrayBuffer throw if the given buffer is non-transferable
MattiasBuelens May 17, 2021
5d2c90a
Add note about transferring WebAssembly.Memory buffers
MattiasBuelens May 17, 2021
c0f3a2d
Propagate transfer errors in ReadableByteStreamControllerEnqueue
MattiasBuelens May 18, 2021
1a20a27
Propagate transfer errors in ReadableByteStreamControllerRespond
MattiasBuelens May 18, 2021
0b7850c
Propagate transfer errors in ReadableByteStreamControllerRespondWithN…
MattiasBuelens May 18, 2021
17d1c2d
Relax check in ReadableByteStreamControllerEnqueue
MattiasBuelens May 18, 2021
78d4a1a
Propagate transfer errors in ReadableByteStreamControllerPullInto
MattiasBuelens May 18, 2021
0ab00d1
Use ≤ instead of <=
MattiasBuelens May 19, 2021
01b7779
Fix link to WebAssembly.Memory
MattiasBuelens May 19, 2021
bf4e8a3
Roll WPT
MattiasBuelens May 19, 2021
fb8d710
Ignore tests with non-transferable buffers
MattiasBuelens May 19, 2021
5d0f3ab
Roll WPT
MattiasBuelens May 20, 2021
c50c9bc
Fix typo
MattiasBuelens May 20, 2021
30b3f50
Add note about respondWithNewView
MattiasBuelens May 21, 2021
b22d61f
Roll WPT
MattiasBuelens May 26, 2021
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
39 changes: 26 additions & 13 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1587,7 +1587,7 @@ counterparts for BYOB controllers, as discussed in [[#rs-abstract-ops-used-by-co
id="rs-default-controller-private-pull">\[[PullSteps]](|readRequest|)</dfn> implements the
[$ReadableStreamController/[[PullSteps]]$] contract. It performs the following steps:

1. Let |stream| be [=this=].[=ReadableStreamGenericReader/[[stream]]=].
1. Let |stream| be [=this=].[=ReadableStreamDefaultController/[[stream]]=].
1. If [=this=].[=ReadableStreamDefaultController/[[queue]]=] is not [=list/is empty|empty=],
1. Let |chunk| be ! [$DequeueValue$]([=this=]).
1. If [=this=].[=ReadableStreamDefaultController/[[closeRequested]]=] is true and
Expand Down Expand Up @@ -1721,12 +1721,13 @@ has the following [=struct/items=]:

: <dfn for="pull-into descriptor">buffer</dfn>
:: An {{ArrayBuffer}}
: <dfn for="pull-into descriptor">buffer byte length</dfn>
:: A positive integer representing the initial byte length of [=pull-into descriptor/buffer=]
: <dfn for="pull-into descriptor">byte offset</dfn>
:: A nonnegative integer byte offset into the [=pull-into descriptor/buffer=] where the
[=underlying byte source=] will start writing
: <dfn for="pull-into descriptor">byte length</dfn>
:: A nonnegative integer number of bytes which can be written into the [=pull-into
descriptor/buffer=]
:: A positive integer number of bytes which can be written into the [=pull-into descriptor/buffer=]
: <dfn for="pull-into descriptor">bytes filled</dfn>
:: A nonnegative integer number of bytes that have been written into the [=pull-into
descriptor/buffer=] so far
Expand Down Expand Up @@ -1803,8 +1804,12 @@ has the following [=struct/items=]:

1. If [=this=].[=ReadableByteStreamController/[[closeRequested]]=] is true, throw a {{TypeError}}
exception.
1. If [=this=].[=ReadableStreamGenericReader/[[stream]]=].[=ReadableStream/[[state]]=] is not
1. If [=this=].[=ReadableByteStreamController/[[stream]]=].[=ReadableStream/[[state]]=] is not
"`readable`", throw a {{TypeError}} exception.
1. If [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=] is not [=list/is empty|empty=],
1. Let |firstDescriptor| be [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=][0].
1. If [$IsDetachedBuffer$](|firstDescriptor|'s [=pull-into descriptor/buffer=]) is true,
throw a {{TypeError}} exception.
1. Perform ? [$ReadableByteStreamControllerClose$]([=this=]).
</div>

Expand All @@ -1817,8 +1822,12 @@ for="ReadableByteStreamController">enqueue(|chunk|)</dfn> method steps are:
exception.
1. If [=this=].[=ReadableByteStreamController/[[closeRequested]]=] is true, throw a {{TypeError}}
exception.
1. If [=this=].[=ReadableStreamGenericReader/[[stream]]=].[=ReadableStream/[[state]]=] is not
1. If [=this=].[=ReadableByteStreamController/[[stream]]=].[=ReadableStream/[[state]]=] is not
"`readable`", throw a {{TypeError}} exception.
1. If [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=] is not [=list/is empty|empty=],
1. Let |firstDescriptor| be [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=][0].
1. If [$IsDetachedBuffer$](|firstDescriptor|'s [=pull-into descriptor/buffer=]) is true,
throw a {{TypeError}} exception.
1. Return ! [$ReadableByteStreamControllerEnqueue$]([=this=], |chunk|).
</div>

Expand Down Expand Up @@ -1879,8 +1888,9 @@ counterparts for default controllers, as discussed in [[#rs-abstract-ops-used-by
1. Perform |readRequest|'s [=read request/error steps=], given |buffer|.\[[Value]].
1. Return.
1. Let |pullIntoDescriptor| be a new [=pull-into descriptor=] with [=pull-into descriptor/buffer=]
|buffer|.\[[Value]], [=pull-into descriptor/byte offset=] 0, [=pull-into descriptor/byte
length=] |autoAllocateChunkSize|, [=pull-into descriptor/bytes filled=] 0, [=pull-into
|buffer|.\[[Value]], [=pull-into descriptor/buffer byte length=] |autoAllocateChunkSize|,
[=pull-into descriptor/byte offset=] 0, [=pull-into descriptor/byte length=]
|autoAllocateChunkSize|, [=pull-into descriptor/bytes filled=] 0, [=pull-into
descriptor/element size=] 1, [=pull-into descriptor/view constructor=] {{%Uint8Array%}}, and
[=pull-into descriptor/reader type=] "`default`".
1. [=list/Append=] |pullIntoDescriptor| to
Expand Down Expand Up @@ -1981,7 +1991,6 @@ following table:
The <dfn id="rs-byob-request-respond-with-new-view" method
for="ReadableStreamBYOBRequest">respondWithNewView(|view|)</dfn> method steps are:

1. If |view|.\[[ByteLength]] is 0, throw a {{TypeError}} exception.
1. If |view|.\[[ViewedArrayBuffer]].\[[ArrayBufferByteLength]] is 0, throw a {{TypeError}}
exception.
1. If [=this=].[=ReadableStreamBYOBRequest/[[controller]]=] is undefined, throw a {{TypeError}}
Expand Down Expand Up @@ -3087,9 +3096,10 @@ The following abstract operations support the implementation of the
1. Let |byteLength| be |view|.\[[ByteLength]].
1. Let |buffer| be ! [$TransferArrayBuffer$](|view|.\[[ViewedArrayBuffer]]).
1. Let |pullIntoDescriptor| be a new [=pull-into descriptor=] with [=pull-into descriptor/buffer=]
|buffer|, [=pull-into descriptor/byte offset=] |byteOffset|, [=pull-into descriptor/byte
length=] |byteLength|, [=pull-into descriptor/bytes filled=] 0, [=pull-into descriptor/element
size=] |elementSize|, [=pull-into descriptor/view constructor=] |ctor|, and [=pull-into
|buffer|, [=pull-into descriptor/buffer byte length=] |buffer|.\[[ArrayBufferByteLength]],
[=pull-into descriptor/byte offset=] |byteOffset|, [=pull-into descriptor/byte length=]
|byteLength|, [=pull-into descriptor/bytes filled=] 0, [=pull-into descriptor/element size=]
|elementSize|, [=pull-into descriptor/view constructor=] |ctor|, and [=pull-into
descriptor/reader type=] "`byob`".
1. If |controller|.[=ReadableByteStreamController/[[pendingPullIntos]]=] is not empty,
1. [=list/Append=] |pullIntoDescriptor| to
Expand Down Expand Up @@ -3191,6 +3201,7 @@ The following abstract operations support the implementation of the
|firstDescriptor|).
1. Otherwise,
1. Assert: |state| is "`readable`".
1. If |bytesWritten| is 0, throw a {{TypeError}} exception.
1. Perform ? [$ReadableByteStreamControllerRespondInReadableState$](|controller|, |bytesWritten|,
|firstDescriptor|).
1. Perform ! [$ReadableByteStreamControllerCallPullIfNeeded$](|controller|).
Expand All @@ -3206,8 +3217,10 @@ 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
a {{RangeError}} exception.
1. If |firstDescriptor|'s [=pull-into descriptor/buffer byte length=] is not
|view|.\[[ViewedArrayBuffer]].\[[ByteLength]], throw a {{RangeError}} exception.
1. If |firstDescriptor|'s [=pull-into descriptor/bytes filled=] + |view|.\[[ByteLength]] >
|firstDescriptor|'s [=pull-into descriptor/byte length=], throw a {{RangeError}} exception.
1. Set |firstDescriptor|'s [=pull-into descriptor/buffer=] to |view|.\[[ViewedArrayBuffer]].
1. Perform ? [$ReadableByteStreamControllerRespondInternal$](|controller|, |view|.\[[ByteLength]]).
</div>
Expand Down
16 changes: 16 additions & 0 deletions reference-implementation/lib/ReadableByteStreamController-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const assert = require('assert');

const { CancelSteps, PullSteps } = require('./abstract-ops/internal-methods.js');
const { ResetQueue } = require('./abstract-ops/queue-with-sizes.js');
const { IsDetachedBuffer } = require('./abstract-ops/ecmascript.js');
const aos = require('./abstract-ops/readable-streams.js');

const ReadableStreamBYOBRequest = require('../generated/ReadableStreamBYOBRequest.js');
Expand Down Expand Up @@ -38,6 +39,13 @@ exports.implementation = class ReadableByteStreamControllerImpl {
throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`);
}

if (this._pendingPullIntos.length > 0) {
const firstDescriptor = this._pendingPullIntos[0];
if (IsDetachedBuffer(firstDescriptor.buffer) === true) {
throw new TypeError('The BYOB request\'s buffer has been detached');
}
}

aos.ReadableByteStreamControllerClose(this);
}

Expand All @@ -58,6 +66,13 @@ exports.implementation = class ReadableByteStreamControllerImpl {
throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`);
}

if (this._pendingPullIntos.length > 0) {
const firstDescriptor = this._pendingPullIntos[0];
if (IsDetachedBuffer(firstDescriptor.buffer) === true) {
throw new TypeError('The BYOB request\'s buffer has been detached');
}
}

aos.ReadableByteStreamControllerEnqueue(this, chunk);
}

Expand Down Expand Up @@ -108,6 +123,7 @@ exports.implementation = class ReadableByteStreamControllerImpl {

const pullIntoDescriptor = {
buffer,
bufferByteLength: autoAllocateChunkSize,
byteOffset: 0,
byteLength: autoAllocateChunkSize,
bytesFilled: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ exports.implementation = class ReadableStreamBYOBRequestImpl {
}

respondWithNewView(view) {
if (view.byteLength === 0) {
throw new TypeError('chunk must have non-zero byteLength');
}
if (view.buffer.byteLength === 0) {
throw new TypeError('chunk\'s buffer must have non-zero byteLength');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,7 @@ function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest)
const buffer = TransferArrayBuffer(view.buffer);
const pullIntoDescriptor = {
buffer,
bufferByteLength: buffer.byteLength,
byteOffset: view.byteOffset,
byteLength: view.byteLength,
bytesFilled: 0,
Expand Down Expand Up @@ -1274,6 +1275,9 @@ function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) {
ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor);
} else {
assert(state === 'readable');
if (bytesWritten === 0) {
throw new TypeError('bytesWritten must be greater than 0 when calling respond() on a readable stream');
}

ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor);
}
Expand All @@ -1289,9 +1293,12 @@ function ReadableByteStreamControllerRespondWithNewView(controller, view) {
if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) {
throw new RangeError('The region specified by view does not match byobRequest');
}
if (firstDescriptor.byteLength !== view.byteLength) {
if (firstDescriptor.bufferByteLength !== view.buffer.byteLength) {
throw new RangeError('The buffer of view has different capacity than byobRequest');
}
if (firstDescriptor.bytesFilled + view.byteLength > firstDescriptor.byteLength) {
throw new RangeError('The region specified by view is larger than byobRequest');
}

firstDescriptor.buffer = view.buffer;

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