diff --git a/index.bs b/index.bs
index 730af3731..458a09f59 100644
--- a/index.bs
+++ b/index.bs
@@ -1322,8 +1322,8 @@ the following [=struct/items=]:
: chunk steps
:: An algorithm taking a [=chunk=], called when a chunk is available for reading
: close steps
-:: An algorithm taking a [=chunk=], called when no chunks are available because the stream is
- closed
+:: An algorithm taking a [=chunk=] or undefined, called when no chunks are available because
+ the stream is closed
: error steps
:: An algorithm taking a JavaScript value, called when no [=chunks=] are available because the
stream is errored
@@ -1331,8 +1331,10 @@ the following [=struct/items=]:
The [=read-into request/close steps=] take a [=chunk=] so that it can return the
backing memory to the caller if possible. For example,
{{ReadableStreamBYOBReader/read()|byobReader.read(chunk)}} will fulfill with {
-value: newViewOnSameMemory, done: true }
for closed streams, instead of the more traditional
-{ value: undefined, done: true }
.
+value: newViewOnSameMemory, done: true } for closed streams. If the stream is
+[=cancel a readable stream|canceled=], the backing memory is discarded and
+{{ReadableStreamBYOBReader/read()|byobReader.read(chunk)}} fulfills with the more traditional
+{ value: undefined, done: true }
instead.
Constructor, methods, and properties
@@ -1369,6 +1371,10 @@ value: newViewOnSameMemory, done: true } for closed streams, instead of t
the same type) onto the same backing memory region, with no modifications, to ensure the memory
is returned to the caller.
+ If the reader is [=cancel a readable stream|canceled=], the promise will be fulfilled with
+ an object of the form { value: undefined, done: true }
. In this case,
+ the backing memory region of |view| is discarded and not returned to the caller.
+
If the stream becomes errored, the promise will be rejected with the relevant error.
@@ -1849,10 +1855,7 @@ counterparts for default controllers, as discussed in [[#rs-abstract-ops-used-by
id="rbs-controller-private-cancel">\[[CancelSteps]](|reason|) implements the
[$ReadableStreamController/[[CancelSteps]]$] contract. It performs the following steps:
- 1. If [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=] is not [=list/is
- empty|empty=],
- 1. Let |firstDescriptor| be [=this=].[=ReadableByteStreamController/[[pendingPullIntos]]=][0].
- 1. Set |firstDescriptor|'s [=pull-into descriptor/bytes filled=] to 0.
+ 1. Perform ! [$ReadableByteStreamControllerClearPendingPullIntos$]([=this=]).
1. Perform ! [$ResetQueue$]([=this=]).
1. Let |result| be the result of performing
[=this=].[=ReadableByteStreamController/[[cancelAlgorithm]]=], passing in |reason|.
@@ -2361,6 +2364,11 @@ the {{ReadableStream}}'s public API.
1. If |stream|.[=ReadableStream/[[state]]=] is "`errored`", return [=a promise rejected with=]
|stream|.[=ReadableStream/[[storedError]]=].
1. Perform ! [$ReadableStreamClose$](|stream|).
+ 1. Let |reader| be |stream|.[=ReadableStream/[[reader]]=].
+ 1. If |reader| is not undefined and |reader| [=implements=] {{ReadableStreamBYOBReader}},
+ 1. [=list/For each=] |readIntoRequest| of |reader|.[=ReadableStreamBYOBReader/[[readIntoRequests]]=],
+ 1. Perform |readIntoRequest|'s [=read-into request/close steps=], given undefined.
+ 1. Set |reader|.[=ReadableStreamBYOBReader/[[readIntoRequests]]=] to an empty [=list=].
1. Let |sourceCancelPromise| be !
|stream|.[=ReadableStream/[[controller]]=].[$ReadableStreamController/[[CancelSteps]]$](|reason|).
1. Return the result of [=reacting=] to |sourceCancelPromise| with a fulfillment step that returns
diff --git a/reference-implementation/lib/ReadableByteStreamController-impl.js b/reference-implementation/lib/ReadableByteStreamController-impl.js
index 799ea3799..c0ab7182a 100644
--- a/reference-implementation/lib/ReadableByteStreamController-impl.js
+++ b/reference-implementation/lib/ReadableByteStreamController-impl.js
@@ -66,10 +66,7 @@ exports.implementation = class ReadableByteStreamControllerImpl {
}
[CancelSteps](reason) {
- if (this._pendingPullIntos.length > 0) {
- const firstDescriptor = this._pendingPullIntos[0];
- firstDescriptor.bytesFilled = 0;
- }
+ aos.ReadableByteStreamControllerClearPendingPullIntos(this);
ResetQueue(this);
diff --git a/reference-implementation/lib/abstract-ops/readable-streams.js b/reference-implementation/lib/abstract-ops/readable-streams.js
index 988519581..e8aa76ad5 100644
--- a/reference-implementation/lib/abstract-ops/readable-streams.js
+++ b/reference-implementation/lib/abstract-ops/readable-streams.js
@@ -28,6 +28,7 @@ Object.assign(exports, {
IsReadableStreamLocked,
ReadableByteStreamControllerCallPullIfNeeded,
ReadableByteStreamControllerClearAlgorithms,
+ ReadableByteStreamControllerClearPendingPullIntos,
ReadableByteStreamControllerClose,
ReadableByteStreamControllerEnqueue,
ReadableByteStreamControllerError,
@@ -453,6 +454,14 @@ function ReadableStreamCancel(stream, reason) {
ReadableStreamClose(stream);
+ const reader = stream._reader;
+ if (reader !== undefined && ReadableStreamBYOBReader.isImpl(reader)) {
+ for (const readIntoRequest of reader._readIntoRequests) {
+ readIntoRequest.closeSteps(undefined);
+ }
+ reader._readIntoRequests = [];
+ }
+
const sourceCancelPromise = stream._controller[CancelSteps](reason);
return transformPromiseWith(sourceCancelPromise, () => undefined);
}
diff --git a/reference-implementation/web-platform-tests b/reference-implementation/web-platform-tests
index 7b29ee36c..b869e60df 160000
--- a/reference-implementation/web-platform-tests
+++ b/reference-implementation/web-platform-tests
@@ -1 +1 @@
-Subproject commit 7b29ee36cc22bdad06b4f98df73358ca959fe0a7
+Subproject commit b869e60df1b8d3840e09b41c5e987c7e23f6856c