From 173af93b61a91032c1d270f2215c0683c95d3857 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 7 Sep 2018 13:32:53 -0500 Subject: [PATCH 01/18] add @@asyncIterator to ReadableStream --- index.bs | 97 +++++++++++++++++++ .../lib/readable-stream.js | 64 ++++++++++++ 2 files changed, 161 insertions(+) diff --git a/index.bs b/index.bs index 8944441c0..fb87932a9 100644 --- a/index.bs +++ b/index.bs @@ -18,6 +18,8 @@ spec:promises-guide; type:dfn;
 urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT
     text: %Uint8Array%; url: #sec-typedarray-objects; type: constructor
+    text: %AsyncIteratorPrototype%; url: #sec-asynciteratorprototype; type: interface
+    text: AsyncIterator; url: #sec-asynciterator-interface; type: interface
     text: ArrayBuffer; url: #sec-arraybuffer-objects; type: interface
     text: DataView; url: #sec-dataview-objects; type: interface
     text: Number; url: #sec-ecmascript-language-types-number-type; type: interface
@@ -404,6 +406,8 @@ like
                 { preventClose, preventAbort, preventCancel, signal } = {})
     pipeTo(dest, { preventClose, preventAbort, preventCancel, signal } = {})
     tee()
+
+    [@@asyncIterator]({ preventCancel } = {})
   }
 
@@ -792,6 +796,90 @@ option. If type is set to unde +
getIterator({ preventCancel = false } = {})
+ +
+ The getIterator method returns an async iterator which can be used to consume the stream. The + {{ReadableStreamDefaultReaderAsyncIteratorPrototype/return()}} method of this iterator object will, by default, + cancel the stream; it will also release the reader. +
+ + + 1. If ! IsReadableStream(*this*) is *false*, throw a *TypeError* exception. + 1. Let _reader_ be ? AcquireReadableStreamDefaultReader(*this*). + 1. Let _iterator_ be ! ObjectCreate(`ReadableStreamAsyncIteratorPrototype`). + 1. Set _iterator_.[[asyncIteratorReader]] to _reader_. + 1. Set _iterator_.[[preventCancel]] to ! ToBoolean(_preventCancel_). + 1. Return _iterator_. + + + +
[@@asyncIterator]()
+ +

+ The @@asyncIterator method is an alias of {{ReadableStreamDefaultReader/getIterator()}}. +

+ +The initial value of the @@asyncIterator method is the same function object as the initial value of the +{{ReadableStream/getIterator()}} method. + +

ReadableStreamAsyncIteratorPrototype

+ +{{ReadableStreamAsyncIteratorPrototype}} is an ordinary object that is used by {{ReadableStream/[@@asyncIterator]()}} to +construct the objects it returns. Instances of {{ReadableStreamAsyncIteratorPrototype}} implement the {{AsyncIterator}} +abstract interface from the JavaScript specification. [[!ECMASCRIPT]] + +The {{ReadableStreamAsyncIteratorPrototype}} object must have its \[[Prototype]] internal slot set to +{{%AsyncIteratorPrototype%}}. + +

Internal slots

+Objects created by {{ReadableStream/[@@asyncIterator]()}}, using {{ReadableStreamAsyncIteratorPrototype}} as their +prototype, are created with the internal slots described in the following table: + + + + + + + + + + + +
Internal SlotDescription (non-normative)
\[[asyncIteratorReader]] + A {{ReadableStreamDefaultReader}} instance +
\[[preventCancel]] + A boolean value indicating if the stream will be canceled when the async iterator's {{ReadableStreamAsyncIteratorPrototype/return()}} method is called +
+ +

next()

+ + + 1. If ! IsReadableStreamAsyncIterator(*this*) is *false*, return a promise rejected with *TypeError* exception. + 1. Let _reader_ be *this*.[[asyncIteratorReader]]. + 1. If _reader_.[[ownerReadableStream]] is *undefined*, return a promise rejected with a *TypeError* exception. + 1. Return ! ReadableStreamDefaultReaderRead(_reader_, *true*). + + +

return( value )

+ + + 1. If ! IsReadableStreamAsyncIterator(*this*) is *false*, return a promise rejected with *TypeError* exception. + 1. Let _reader_ be *this*.[[asyncIteratorReader]]. + 1. If _reader_.[[ownerReadableStream]] is *undefined*, return a promise rejected with a *TypeError* exception. + 1. If _reader_.[[readRequests]] is not empty, return a promise rejected with a *TypeError* exception. + 1. If *this*.[[preventCancel]] is *false*, then: + 1. Let _result_ be ! ReadableStreamReaderGenericCancel(_reader_, _value_). + 1. Perform ! ReadableStreamReaderGenericRelease(_reader_). + 1. Return the result of transforming _result_ by a fulfillment handler that returns ! + ReadableStreamCreateReadResult(_value_, *true*, *true*). + 1. Perform ! ReadableStreamReaderGenericRelease(_reader_). + 1. Return a promise resolved with ! ReadableStreamCreateReadResult(_value_, *true*, *true*). + +

General readable stream abstract operations

The following abstract operations, unlike most in this specification, are meant to be generally useful by other @@ -910,6 +998,15 @@ readable stream is locked to a reader. 1. Return *true*. +

IsReadableStreamAsyncIterator ( x )

+ + + 1. If Type(_x_) is not Object, return *false*. + 1. If _x_ does not have a [[asyncIteratorReader]] internal slot, return *false*. + 1. Return *true*. + +

ReadableStreamTee ( stream, cloneForBranch2 )

diff --git a/reference-implementation/lib/readable-stream.js b/reference-implementation/lib/readable-stream.js index 6187fc40b..6264b753b 100644 --- a/reference-implementation/lib/readable-stream.js +++ b/reference-implementation/lib/readable-stream.js @@ -158,8 +158,56 @@ class ReadableStream { const branches = ReadableStreamTee(this, false); return createArrayFromList(branches); } + + getIterator({ preventCancel = false } = {}) { + if (IsReadableStream(this) === false) { + throw streamBrandCheckException('getIterator'); + } + const reader = AcquireReadableStreamDefaultReader(this); + const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); + iterator._asyncIteratorReader = reader; + iterator._preventCancel = Boolean(preventCancel); + return iterator; + } } +const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () {}).prototype); +const ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf({ + next() { + if (IsReadableStreamAsyncIterator(this) === false) { + return Promise.reject(streamAsyncIteratorBrandCheckException('next')); + } + const reader = this._asyncIteratorReader; + if (reader._ownerReadableStream === undefined) { + return Promise.reject(readerLockException('iterate')); + } + return ReadableStreamDefaultReaderRead(reader, true); + }, + + return(value) { + if (IsReadableStreamAsyncIterator(this) === false) { + return Promise.reject(streamAsyncIteratorBrandCheckException('next')); + } + const reader = this._asyncIteratorReader; + if (reader._ownerReadableStream === undefined) { + return Promise.reject(readerLockException('finish iterating')); + } + if (reader._readRequests.length > 0) { + return Promise.reject(new TypeError( + 'Tried to release a reader lock when that reader has pending read() calls un-settled')); + } + if (this._preventCancel === false) { + const result = ReadableStreamReaderGenericCancel(reader, value); + ReadableStreamReaderGenericRelease(reader); + return result.then(() => ReadableStreamCreateReadResult(value, true, true)); + } + ReadableStreamReaderGenericRelease(reader); + return Promise.resolve(ReadableStreamCreateReadResult(value, true, true)); + } +}, AsyncIteratorPrototype); + +ReadableStream.prototype[Symbol.asyncIterator] = ReadableStream.prototype.getIterator; + module.exports = { CreateReadableByteStream, CreateReadableStream, @@ -255,6 +303,18 @@ function IsReadableStreamLocked(stream) { return true; } +function IsReadableStreamAsyncIterator(x) { + if (!typeIsObject(x)) { + return false; + } + + if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorReader')) { + return false; + } + + return true; +} + function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { assert(IsReadableStream(source) === true); assert(IsWritableStream(dest) === true); @@ -2063,6 +2123,10 @@ function streamBrandCheckException(name) { return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); } +function streamAsyncIteratorBrandCheckException(name) { + return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); +} + // Helper functions for the readers. function readerLockException(name) { From 1b48b73740634d37c6f1b30b11e521e2d8b3fb8c Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Sun, 27 Jan 2019 17:45:47 +0100 Subject: [PATCH 02/18] Release lock when async iterator completes normally --- index.bs | 9 ++++++++- reference-implementation/lib/readable-stream.js | 11 ++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index fb87932a9..ce0d975da 100644 --- a/index.bs +++ b/index.bs @@ -860,7 +860,14 @@ prototype, are created with the internal slots described in the following table: 1. If ! IsReadableStreamAsyncIterator(*this*) is *false*, return a promise rejected with *TypeError* exception. 1. Let _reader_ be *this*.[[asyncIteratorReader]]. 1. If _reader_.[[ownerReadableStream]] is *undefined*, return a promise rejected with a *TypeError* exception. - 1. Return ! ReadableStreamDefaultReaderRead(_reader_, *true*). + 1. Return the result of transforming ! ReadableStreamDefaultReaderRead(_reader_) with a fulfillment handler + which takes the argument _result_ and performs the following steps: + 1. Assert: Type(_result_) is Object. + 1. Let _value_ be ? Get(_result_, `"value"`). + 1. Let _done_ be ? Get(_result_, `"done"`). + 1. Assert: Type(_done_) is Boolean. + 1. If _done_ is *true*, perform ! ReadableStreamReaderGenericRelease(_reader_). + 1. Return ! ReadableStreamCreateReadResult(_value_, _done_, *true*).

{ + assert(typeIsObject(result)); + const value = result.value; + const done = result.done; + assert(typeof done === 'boolean'); + if (done) { + ReadableStreamReaderGenericRelease(reader); + } + return ReadableStreamCreateReadResult(value, done, true); + }); }, return(value) { From 949540a4a3a533812f9740c1621bd623506c5fbc Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Tue, 29 Jan 2019 22:35:08 +0100 Subject: [PATCH 03/18] Fix spec links --- index.bs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index ce0d975da..a63feb643 100644 --- a/index.bs +++ b/index.bs @@ -796,11 +796,11 @@ option. If type is set to unde -
getIterator({ preventCancel = false } = {})
+
getIterator({ preventCancel = false } = {})
The getIterator method returns an async iterator which can be used to consume the stream. The - {{ReadableStreamDefaultReaderAsyncIteratorPrototype/return()}} method of this iterator object will, by default, + {{ReadableStreamAsyncIteratorPrototype/return()}} method of this iterator object will, by default, cancel the stream; it will also release the reader.
@@ -817,7 +817,7 @@ option. If type is set to unde
[@@asyncIterator]()

- The @@asyncIterator method is an alias of {{ReadableStreamDefaultReader/getIterator()}}. + The @@asyncIterator method is an alias of {{ReadableStream/getIterator()}}.

The initial value of the @@asyncIterator method is the same function object as the initial value of the From a904fb24d94fe993d518ee72fbd4ee7ebbc66cec Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Tue, 29 Jan 2019 22:35:39 +0100 Subject: [PATCH 04/18] Add getIterator to class definition --- index.bs | 1 + 1 file changed, 1 insertion(+) diff --git a/index.bs b/index.bs index a63feb643..358068a50 100644 --- a/index.bs +++ b/index.bs @@ -407,6 +407,7 @@ like pipeTo(dest, { preventClose, preventAbort, preventCancel, signal } = {}) tee() + getIterator({ preventCancel } = {}) [@@asyncIterator]({ preventCancel } = {}) }
From 3e77ea5b66276474de71afb5cffe332fbf037057 Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Tue, 29 Jan 2019 22:46:34 +0100 Subject: [PATCH 05/18] Fix arguments in method titles --- index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index 358068a50..e65f4d915 100644 --- a/index.bs +++ b/index.bs @@ -797,7 +797,7 @@ option. If type is set to unde -
getIterator({ preventCancel = false } = {})
+
getIterator({ preventCancel } = {})
The getIterator method returns an async iterator which can be used to consume the stream. The @@ -815,7 +815,7 @@ option. If type is set to unde -
[@@asyncIterator]()
+
[@@asyncIterator]({ preventCancel } = {})

The @@asyncIterator method is an alias of {{ReadableStream/getIterator()}}. From f1d85b93e877d9e25a3f24748b2d4f12ecdb4ea4 Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Tue, 29 Jan 2019 23:07:22 +0100 Subject: [PATCH 06/18] Make @@asyncIterator non-enumerable --- reference-implementation/lib/readable-stream.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/reference-implementation/lib/readable-stream.js b/reference-implementation/lib/readable-stream.js index 35a047187..3cce9da1f 100644 --- a/reference-implementation/lib/readable-stream.js +++ b/reference-implementation/lib/readable-stream.js @@ -215,7 +215,12 @@ const ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf({ } }, AsyncIteratorPrototype); -ReadableStream.prototype[Symbol.asyncIterator] = ReadableStream.prototype.getIterator; +Object.defineProperty(ReadableStream.prototype, Symbol.asyncIterator, { + value: ReadableStream.prototype.getIterator, + enumerable: false, + writable: true, + configurable: true +}); module.exports = { CreateReadableByteStream, From b6ac6da73917a71cde088de00db6567d69af7a3e Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Tue, 29 Jan 2019 23:36:28 +0100 Subject: [PATCH 07/18] Update eslint to support parsing async generator functions --- reference-implementation/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference-implementation/package.json b/reference-implementation/package.json index 19dd1e6a2..bda74d15a 100644 --- a/reference-implementation/package.json +++ b/reference-implementation/package.json @@ -14,7 +14,7 @@ "better-assert": "^1.0.2", "browserify": "^16.2.3", "debug": "^4.1.0", - "eslint": "^3.2.2", + "eslint": "^5.12.1", "minimatch": "^3.0.4", "nyc": "^13.0.1", "opener": "^1.5.1", From ebac9c29cd6810cd9684364445c9a5716a6876c6 Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Wed, 30 Jan 2019 23:23:22 +0100 Subject: [PATCH 08/18] Move getIterator() before getReader() --- index.bs | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/index.bs b/index.bs index e65f4d915..10522edbb 100644 --- a/index.bs +++ b/index.bs @@ -401,13 +401,13 @@ like get locked() cancel(reason) + getIterator({ preventCancel } = {}) getReader() pipeThrough({ writable, readable }, { preventClose, preventAbort, preventCancel, signal } = {}) pipeTo(dest, { preventClose, preventAbort, preventCancel, signal } = {}) tee() - getIterator({ preventCancel } = {}) [@@asyncIterator]({ preventCancel } = {}) } @@ -607,6 +607,23 @@ option. If type is set to unde 1. Return ! ReadableStreamCancel(*this*, _reason_). +

getIterator({ preventCancel } = {})
+ +
+ The getIterator method returns an async iterator which can be used to consume the stream. The + {{ReadableStreamAsyncIteratorPrototype/return()}} method of this iterator object will, by default, + cancel the stream; it will also release the reader. +
+ + + 1. If ! IsReadableStream(*this*) is *false*, throw a *TypeError* exception. + 1. Let _reader_ be ? AcquireReadableStreamDefaultReader(*this*). + 1. Let _iterator_ be ! ObjectCreate(`ReadableStreamAsyncIteratorPrototype`). + 1. Set _iterator_.[[asyncIteratorReader]] to _reader_. + 1. Set _iterator_.[[preventCancel]] to ! ToBoolean(_preventCancel_). + 1. Return _iterator_. + +
getReader({ mode } = {})
@@ -797,23 +814,6 @@ option. If type is set to unde
-
getIterator({ preventCancel } = {})
- -
- The getIterator method returns an async iterator which can be used to consume the stream. The - {{ReadableStreamAsyncIteratorPrototype/return()}} method of this iterator object will, by default, - cancel the stream; it will also release the reader. -
- - - 1. If ! IsReadableStream(*this*) is *false*, throw a *TypeError* exception. - 1. Let _reader_ be ? AcquireReadableStreamDefaultReader(*this*). - 1. Let _iterator_ be ! ObjectCreate(`ReadableStreamAsyncIteratorPrototype`). - 1. Set _iterator_.[[asyncIteratorReader]] to _reader_. - 1. Set _iterator_.[[preventCancel]] to ! ToBoolean(_preventCancel_). - 1. Return _iterator_. - -
[@@asyncIterator]({ preventCancel } = {})
From 01f1b0b5160a20a99a9e6c591986f7697fa5dabd Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Wed, 30 Jan 2019 23:25:42 +0100 Subject: [PATCH 09/18] Add missing argument for getReader() in class definition --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 10522edbb..ec88e0046 100644 --- a/index.bs +++ b/index.bs @@ -402,7 +402,7 @@ like cancel(reason) getIterator({ preventCancel } = {}) - getReader() + getReader({ mode } = {}) pipeThrough({ writable, readable }, { preventClose, preventAbort, preventCancel, signal } = {}) pipeTo(dest, { preventClose, preventAbort, preventCancel, signal } = {}) From 762bb398b6f291c14fdf341e6fdc35780694bd53 Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Wed, 30 Jan 2019 23:31:51 +0100 Subject: [PATCH 10/18] Fix enumerability of async iterator methods --- reference-implementation/lib/readable-stream.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reference-implementation/lib/readable-stream.js b/reference-implementation/lib/readable-stream.js index 3cce9da1f..c95054146 100644 --- a/reference-implementation/lib/readable-stream.js +++ b/reference-implementation/lib/readable-stream.js @@ -214,6 +214,8 @@ const ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf({ return Promise.resolve(ReadableStreamCreateReadResult(value, true, true)); } }, AsyncIteratorPrototype); +Object.defineProperty(ReadableStreamAsyncIteratorPrototype, 'next', { enumerable: false }); +Object.defineProperty(ReadableStreamAsyncIteratorPrototype, 'return', { enumerable: false }); Object.defineProperty(ReadableStream.prototype, Symbol.asyncIterator, { value: ReadableStream.prototype.getIterator, From b03373e0d41efa31005e4e5b8a16a41b6f21306a Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Sun, 3 Feb 2019 17:17:45 +0100 Subject: [PATCH 11/18] Fix linter issues --- reference-implementation/.eslintrc.json | 11 ++++- .../lib/readable-stream.js | 42 +++++++++---------- .../lib/writable-stream.js | 42 +++++++++---------- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/reference-implementation/.eslintrc.json b/reference-implementation/.eslintrc.json index c09c1518a..db825221b 100644 --- a/reference-implementation/.eslintrc.json +++ b/reference-implementation/.eslintrc.json @@ -160,7 +160,16 @@ "id-blacklist": "off", "id-length": "off", "id-match": "off", - "indent": ["error", 2, { "SwitchCase": 1 }], + "indent": ["error", 2, { + "SwitchCase": 1, + "MemberExpression": 2, + "FunctionDeclaration": { "parameters": "first" }, + "FunctionExpression": { "parameters": "first" }, + "CallExpression": { "arguments": "first" }, + "ArrayExpression": "first", + "ObjectExpression": "first", + "ImportDeclaration": "first" + }], "jsx-quotes": "off", "key-spacing": ["error", { "beforeColon": false, "afterColon": true, "mode": "strict" }], "keyword-spacing": ["error", { "before": true, "after": true }], diff --git a/reference-implementation/lib/readable-stream.js b/reference-implementation/lib/readable-stream.js index c95054146..eb4605a37 100644 --- a/reference-implementation/lib/readable-stream.js +++ b/reference-implementation/lib/readable-stream.js @@ -129,7 +129,7 @@ class ReadableStream { } if (IsWritableStream(dest) === false) { return Promise.reject( - new TypeError('ReadableStream.prototype.pipeTo\'s first argument must be a WritableStream')); + new TypeError('ReadableStream.prototype.pipeTo\'s first argument must be a WritableStream')); } preventClose = Boolean(preventClose); @@ -258,7 +258,7 @@ function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, hi const controller = Object.create(ReadableStreamDefaultController.prototype); SetUpReadableStreamDefaultController( - stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm + stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm ); return stream; @@ -496,8 +496,8 @@ function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventC function doTheRest() { action().then( - () => finalize(originalIsError, originalError), - newError => finalize(true, newError) + () => finalize(originalIsError, originalError), + newError => finalize(true, newError) ) .catch(rethrowAssertionErrorRejection); } @@ -1007,12 +1007,12 @@ function ReadableStreamReaderGenericRelease(reader) { if (reader._ownerReadableStream._state === 'readable') { defaultReaderClosedPromiseReject( - reader, - new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness')); + reader, + new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness')); } else { defaultReaderClosedPromiseResetToRejected( - reader, - new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness')); + reader, + new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness')); } reader._closedPromise.catch(() => {}); @@ -1175,7 +1175,7 @@ function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { ReadableStreamDefaultControllerError(controller, e); } ) - .catch(rethrowAssertionErrorRejection); + .catch(rethrowAssertionErrorRejection); return undefined; } @@ -1337,7 +1337,7 @@ function SetUpReadableStreamDefaultController( ReadableStreamDefaultControllerError(controller, r); } ) - .catch(rethrowAssertionErrorRejection); + .catch(rethrowAssertionErrorRejection); } function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, @@ -1610,7 +1610,7 @@ function ReadableByteStreamControllerCallPullIfNeeded(controller) { ReadableByteStreamControllerError(controller, e); } ) - .catch(rethrowAssertionErrorRejection); + .catch(rethrowAssertionErrorRejection); return undefined; } @@ -1646,7 +1646,7 @@ function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescripto assert(bytesFilled % elementSize === 0); return new pullIntoDescriptor.ctor( - pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); + pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); } function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { @@ -2070,17 +2070,17 @@ function SetUpReadableByteStreamController(stream, controller, startAlgorithm, p const startResult = startAlgorithm(); Promise.resolve(startResult).then( - () => { - controller._started = true; + () => { + controller._started = true; - assert(controller._pulling === false); - assert(controller._pullAgain === false); + assert(controller._pulling === false); + assert(controller._pullAgain === false); - ReadableByteStreamControllerCallPullIfNeeded(controller); - }, - r => { - ReadableByteStreamControllerError(controller, r); - } + ReadableByteStreamControllerCallPullIfNeeded(controller); + }, + r => { + ReadableByteStreamControllerError(controller, r); + } ) .catch(rethrowAssertionErrorRejection); } diff --git a/reference-implementation/lib/writable-stream.js b/reference-implementation/lib/writable-stream.js index 661c4cf31..dddbbe585 100644 --- a/reference-implementation/lib/writable-stream.js +++ b/reference-implementation/lib/writable-stream.js @@ -272,14 +272,14 @@ function WritableStreamFinishErroring(stream) { const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); promise.then( - () => { - abortRequest._resolve(); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }, - reason => { - abortRequest._reject(reason); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }); + () => { + abortRequest._resolve(); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }, + reason => { + abortRequest._reject(reason); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }); } function WritableStreamFinishInFlightWrite(stream) { @@ -769,18 +769,18 @@ function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm const startResult = startAlgorithm(); const startPromise = Promise.resolve(startResult); startPromise.then( - () => { - assert(stream._state === 'writable' || stream._state === 'erroring'); - controller._started = true; - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, - r => { - assert(stream._state === 'writable' || stream._state === 'erroring'); - controller._started = true; - WritableStreamDealWithRejection(stream, r); - } + () => { + assert(stream._state === 'writable' || stream._state === 'erroring'); + controller._started = true; + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, + r => { + assert(stream._state === 'writable' || stream._state === 'erroring'); + controller._started = true; + WritableStreamDealWithRejection(stream, r); + } ) - .catch(rethrowAssertionErrorRejection); + .catch(rethrowAssertionErrorRejection); } function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { @@ -904,7 +904,7 @@ function WritableStreamDefaultControllerProcessClose(controller) { WritableStreamFinishInFlightCloseWithError(stream, reason); } ) - .catch(rethrowAssertionErrorRejection); + .catch(rethrowAssertionErrorRejection); } function WritableStreamDefaultControllerProcessWrite(controller, chunk) { @@ -936,7 +936,7 @@ function WritableStreamDefaultControllerProcessWrite(controller, chunk) { WritableStreamFinishInFlightWriteWithError(stream, reason); } ) - .catch(rethrowAssertionErrorRejection); + .catch(rethrowAssertionErrorRejection); } function WritableStreamDefaultControllerGetBackpressure(controller) { From d8c4415802033619f88adfcfaccab797a28b815e Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Mon, 4 Feb 2019 00:48:32 +0100 Subject: [PATCH 12/18] Work around linking issue for @@asyncIterator method --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index ec88e0046..65ab1095e 100644 --- a/index.bs +++ b/index.bs @@ -815,7 +815,7 @@ option. If type is set to unde
-
[@@asyncIterator]({ preventCancel } = {})
+
[@@asyncIterator]({ preventCancel } = {})

The @@asyncIterator method is an alias of {{ReadableStream/getIterator()}}. From f8a12d8988d45609378d7385c93b5264a967ac3c Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Mon, 4 Feb 2019 00:48:43 +0100 Subject: [PATCH 13/18] Roll WPT (WIP) --- reference-implementation/web-platform-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference-implementation/web-platform-tests b/reference-implementation/web-platform-tests index 4606e75ca..1ed4ac21d 160000 --- a/reference-implementation/web-platform-tests +++ b/reference-implementation/web-platform-tests @@ -1 +1 @@ -Subproject commit 4606e75ca8cd69830223f02e0fbd46fc160f431f +Subproject commit 1ed4ac21dae4b02bb02330cccc7ec34116df6f05 From afb9f52b3e892f44e270320034e223ca10a8778f Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Mon, 4 Feb 2019 11:27:36 +0100 Subject: [PATCH 14/18] Address review comments --- index.bs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index 65ab1095e..84a4e7c6b 100644 --- a/index.bs +++ b/index.bs @@ -827,7 +827,7 @@ The initial value of the @@asyncIterator method is the same functio

ReadableStreamAsyncIteratorPrototype

-{{ReadableStreamAsyncIteratorPrototype}} is an ordinary object that is used by {{ReadableStream/[@@asyncIterator]()}} to +{{ReadableStreamAsyncIteratorPrototype}} is an ordinary object that is used by {{ReadableStream/getIterator()}} to construct the objects it returns. Instances of {{ReadableStreamAsyncIteratorPrototype}} implement the {{AsyncIterator}} abstract interface from the JavaScript specification. [[!ECMASCRIPT]] @@ -835,7 +835,7 @@ The {{ReadableStreamAsyncIteratorPrototype}} object must have its \[[Prototype]] {{%AsyncIteratorPrototype%}}.

Internal slots

-Objects created by {{ReadableStream/[@@asyncIterator]()}}, using {{ReadableStreamAsyncIteratorPrototype}} as their +Objects created by {{ReadableStream/getIterator()}}, using {{ReadableStreamAsyncIteratorPrototype}} as their prototype, are created with the internal slots described in the following table: @@ -858,7 +858,7 @@ prototype, are created with the internal slots described in the following table:

next()

- 1. If ! IsReadableStreamAsyncIterator(*this*) is *false*, return a promise rejected with *TypeError* exception. + 1. If ! IsReadableStreamAsyncIterator(*this*) is *false*, return a promise rejected with a *TypeError* exception. 1. Let _reader_ be *this*.[[asyncIteratorReader]]. 1. If _reader_.[[ownerReadableStream]] is *undefined*, return a promise rejected with a *TypeError* exception. 1. Return the result of transforming ! ReadableStreamDefaultReaderRead(_reader_) with a fulfillment handler @@ -875,7 +875,7 @@ prototype, are created with the internal slots described in the following table: for="ReadableStreamAsyncIteratorPrototype">return( value ) - 1. If ! IsReadableStreamAsyncIterator(*this*) is *false*, return a promise rejected with *TypeError* exception. + 1. If ! IsReadableStreamAsyncIterator(*this*) is *false*, return a promise rejected with a *TypeError* exception. 1. Let _reader_ be *this*.[[asyncIteratorReader]]. 1. If _reader_.[[ownerReadableStream]] is *undefined*, return a promise rejected with a *TypeError* exception. 1. If _reader_.[[readRequests]] is not empty, return a promise rejected with a *TypeError* exception. From 1299de518732d4489c6cd82a58278b2201631105 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 5 Feb 2019 15:20:36 -0500 Subject: [PATCH 15/18] Add Gus to acks; add

around prelude sentence --- index.bs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.bs b/index.bs index 84a4e7c6b..e9acd02a7 100644 --- a/index.bs +++ b/index.bs @@ -835,8 +835,10 @@ The {{ReadableStreamAsyncIteratorPrototype}} object must have its \[[Prototype]] {{%AsyncIteratorPrototype%}}.

Internal slots

+ Objects created by {{ReadableStream/getIterator()}}, using {{ReadableStreamAsyncIteratorPrototype}} as their prototype, are created with the internal slots described in the following table: +
@@ -6090,6 +6092,7 @@ Forbes Lindesay, Forrest Norvell, Gary Blackwood, Gorgi Kosev, +Gus Caplan, 贺师俊 (hax), Isaac Schlueter, isonmad, From 0d0edfc199a52455e230c9532bf22603149d5101 Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Tue, 5 Feb 2019 22:08:01 +0100 Subject: [PATCH 16/18] Reformat chained method calls --- reference-implementation/.eslintrc.json | 1 - .../lib/readable-stream.js | 15 +++++---------- .../lib/transform-stream.js | 19 +++++++++---------- .../lib/writable-stream.js | 9 +++------ 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/reference-implementation/.eslintrc.json b/reference-implementation/.eslintrc.json index db825221b..f3486a456 100644 --- a/reference-implementation/.eslintrc.json +++ b/reference-implementation/.eslintrc.json @@ -162,7 +162,6 @@ "id-match": "off", "indent": ["error", 2, { "SwitchCase": 1, - "MemberExpression": 2, "FunctionDeclaration": { "parameters": "first" }, "FunctionExpression": { "parameters": "first" }, "CallExpression": { "arguments": "first" }, diff --git a/reference-implementation/lib/readable-stream.js b/reference-implementation/lib/readable-stream.js index eb4605a37..78be77a57 100644 --- a/reference-implementation/lib/readable-stream.js +++ b/reference-implementation/lib/readable-stream.js @@ -498,8 +498,7 @@ function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventC action().then( () => finalize(originalIsError, originalError), newError => finalize(true, newError) - ) - .catch(rethrowAssertionErrorRejection); + ).catch(rethrowAssertionErrorRejection); } } @@ -1174,8 +1173,7 @@ function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { e => { ReadableStreamDefaultControllerError(controller, e); } - ) - .catch(rethrowAssertionErrorRejection); + ).catch(rethrowAssertionErrorRejection); return undefined; } @@ -1336,8 +1334,7 @@ function SetUpReadableStreamDefaultController( r => { ReadableStreamDefaultControllerError(controller, r); } - ) - .catch(rethrowAssertionErrorRejection); + ).catch(rethrowAssertionErrorRejection); } function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, @@ -1609,8 +1606,7 @@ function ReadableByteStreamControllerCallPullIfNeeded(controller) { e => { ReadableByteStreamControllerError(controller, e); } - ) - .catch(rethrowAssertionErrorRejection); + ).catch(rethrowAssertionErrorRejection); return undefined; } @@ -2081,8 +2077,7 @@ function SetUpReadableByteStreamController(stream, controller, startAlgorithm, p r => { ReadableByteStreamControllerError(controller, r); } - ) - .catch(rethrowAssertionErrorRejection); + ).catch(rethrowAssertionErrorRejection); } function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { diff --git a/reference-implementation/lib/transform-stream.js b/reference-implementation/lib/transform-stream.js index 6c8608208..a5f14e90e 100644 --- a/reference-implementation/lib/transform-stream.js +++ b/reference-implementation/lib/transform-stream.js @@ -357,16 +357,15 @@ function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { if (stream._backpressure === true) { const backpressureChangePromise = stream._backpressureChangePromise; assert(backpressureChangePromise !== undefined); - return backpressureChangePromise - .then(() => { - const writable = stream._writable; - const state = writable._state; - if (state === 'erroring') { - throw writable._storedError; - } - assert(state === 'writable'); - return TransformStreamDefaultControllerPerformTransform(controller, chunk); - }); + return backpressureChangePromise.then(() => { + const writable = stream._writable; + const state = writable._state; + if (state === 'erroring') { + throw writable._storedError; + } + assert(state === 'writable'); + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + }); } return TransformStreamDefaultControllerPerformTransform(controller, chunk); diff --git a/reference-implementation/lib/writable-stream.js b/reference-implementation/lib/writable-stream.js index dddbbe585..ab3dc5c52 100644 --- a/reference-implementation/lib/writable-stream.js +++ b/reference-implementation/lib/writable-stream.js @@ -779,8 +779,7 @@ function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm controller._started = true; WritableStreamDealWithRejection(stream, r); } - ) - .catch(rethrowAssertionErrorRejection); + ).catch(rethrowAssertionErrorRejection); } function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { @@ -903,8 +902,7 @@ function WritableStreamDefaultControllerProcessClose(controller) { reason => { WritableStreamFinishInFlightCloseWithError(stream, reason); } - ) - .catch(rethrowAssertionErrorRejection); + ).catch(rethrowAssertionErrorRejection); } function WritableStreamDefaultControllerProcessWrite(controller, chunk) { @@ -935,8 +933,7 @@ function WritableStreamDefaultControllerProcessWrite(controller, chunk) { } WritableStreamFinishInFlightWriteWithError(stream, reason); } - ) - .catch(rethrowAssertionErrorRejection); + ).catch(rethrowAssertionErrorRejection); } function WritableStreamDefaultControllerGetBackpressure(controller) { From fee1dae8b4d2f0f315289e016a0d0b73bbd98409 Mon Sep 17 00:00:00 2001 From: Adam Rice Date: Wed, 6 Feb 2019 17:06:29 +0900 Subject: [PATCH 17/18] Update web-platform-tests pointer --- reference-implementation/web-platform-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference-implementation/web-platform-tests b/reference-implementation/web-platform-tests index 1ed4ac21d..de6f8fcf9 160000 --- a/reference-implementation/web-platform-tests +++ b/reference-implementation/web-platform-tests @@ -1 +1 @@ -Subproject commit 1ed4ac21dae4b02bb02330cccc7ec34116df6f05 +Subproject commit de6f8fcf9b87e80811e9267a886cf891f6f864e0 From e452684ef4333b3d6802db97f654bacb6910ab20 Mon Sep 17 00:00:00 2001 From: Adam Rice Date: Wed, 6 Feb 2019 17:30:46 +0900 Subject: [PATCH 18/18] Trigger travis CI.