diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index 94592cdf01258c..ed08e1fd9025e9 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -24,6 +24,7 @@ const { Symbol, SymbolAsyncIterator, SymbolDispose, + SymbolIterator, SymbolToStringTag, TypedArrayPrototypeGetLength, Uint8Array, @@ -32,6 +33,7 @@ const { const { AbortError, codes: { + ERR_ARG_NOT_ITERABLE, ERR_ILLEGAL_CONSTRUCTOR, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, @@ -110,8 +112,6 @@ const { nonOpCancel, nonOpPull, nonOpStart, - getIterator, - iteratorNext, kType, kState, } = require('internal/webstreams/util'); @@ -1341,41 +1341,36 @@ function createReadableStreamState() { function readableStreamFromIterable(iterable) { let stream; - const iteratorRecord = getIterator(iterable, 'async'); - + const iteratorGetter = iterable[SymbolAsyncIterator] ?? iterable[SymbolIterator]; + if (iteratorGetter == null || typeof iteratorGetter !== 'function') { + throw new ERR_ARG_NOT_ITERABLE(iterable); + } + const iterator = FunctionPrototypeCall(iteratorGetter, iterable); const startAlgorithm = nonOpStart; async function pullAlgorithm() { - const nextResult = iteratorNext(iteratorRecord); - const nextPromise = PromiseResolve(nextResult); - return PromisePrototypeThen(nextPromise, (iterResult) => { - if (typeof iterResult !== 'object' || iterResult === null) { - throw new ERR_INVALID_STATE.TypeError( - 'The promise returned by the iterator.next() method must fulfill with an object'); - } - if (iterResult.done) { - readableStreamDefaultControllerClose(stream[kState].controller); - } else { - readableStreamDefaultControllerEnqueue(stream[kState].controller, iterResult.value); - } - }); + const iterResult = await iterator.next(); + if (typeof iterResult !== 'object' || iterResult === null) { + throw new ERR_INVALID_STATE.TypeError( + 'The promise returned by the iterator.next() method must fulfill with an object'); + } + if (iterResult.done) { + readableStreamDefaultControllerClose(stream[kState].controller); + } else { + readableStreamDefaultControllerEnqueue(stream[kState].controller, await iterResult.value); + } } async function cancelAlgorithm(reason) { - const iterator = iteratorRecord.iterator; const returnMethod = iterator.return; if (returnMethod === undefined) { - return PromiseResolve(); + return; + } + const iterResult = await FunctionPrototypeCall(returnMethod, iterator, reason); + if (typeof iterResult !== 'object' || iterResult === null) { + throw new ERR_INVALID_STATE.TypeError( + 'The promise returned by the iterator.return() method must fulfill with an object'); } - const returnResult = FunctionPrototypeCall(returnMethod, iterator, reason); - const returnPromise = PromiseResolve(returnResult); - return PromisePrototypeThen(returnPromise, (iterResult) => { - if (typeof iterResult !== 'object' || iterResult === null) { - throw new ERR_INVALID_STATE.TypeError( - 'The promise returned by the iterator.return() method must fulfill with an object'); - } - return undefined; - }); } stream = createReadableStream( diff --git a/lib/internal/webstreams/util.js b/lib/internal/webstreams/util.js index 5bf016f73b7af5..95c20b914dfa96 100644 --- a/lib/internal/webstreams/util.js +++ b/lib/internal/webstreams/util.js @@ -13,16 +13,12 @@ const { PromisePrototypeThen, ReflectGet, Symbol, - SymbolAsyncIterator, - SymbolIterator, Uint8Array, } = primordials; const { codes: { - ERR_ARG_NOT_ITERABLE, ERR_INVALID_ARG_VALUE, - ERR_INVALID_STATE, }, } = require('internal/errors'); @@ -208,64 +204,6 @@ function lazyTransfer() { return transfer; } -function createAsyncFromSyncIterator(syncIteratorRecord) { - const syncIterable = { - [SymbolIterator]: () => syncIteratorRecord.iterator, - }; - - const asyncIterator = (async function* () { - return yield* syncIterable; - }()); - - const nextMethod = asyncIterator.next; - return { iterator: asyncIterator, nextMethod, done: false }; -} - -// Refs: https://tc39.es/ecma262/#sec-getiterator -function getIterator(obj, kind = 'sync', method) { - if (method === undefined) { - if (kind === 'async') { - method = obj[SymbolAsyncIterator]; - if (method == null) { - const syncMethod = obj[SymbolIterator]; - - if (syncMethod === undefined) { - throw new ERR_ARG_NOT_ITERABLE(obj); - } - - const syncIteratorRecord = getIterator(obj, 'sync', syncMethod); - return createAsyncFromSyncIterator(syncIteratorRecord); - } - } else { - method = obj[SymbolIterator]; - } - } - - if (method === undefined) { - throw new ERR_ARG_NOT_ITERABLE(obj); - } - - const iterator = FunctionPrototypeCall(method, obj); - if (typeof iterator !== 'object' || iterator === null) { - throw new ERR_INVALID_STATE.TypeError('The iterator method must return an object'); - } - const nextMethod = iterator.next; - return { iterator, nextMethod, done: false }; -} - -function iteratorNext(iteratorRecord, value) { - let result; - if (value === undefined) { - result = FunctionPrototypeCall(iteratorRecord.nextMethod, iteratorRecord.iterator); - } else { - result = FunctionPrototypeCall(iteratorRecord.nextMethod, iteratorRecord.iterator, [value]); - } - if (typeof result !== 'object' || result === null) { - throw new ERR_INVALID_STATE.TypeError('The iterator.next() method must return an object'); - } - return result; -} - module.exports = { ArrayBufferViewGetBuffer, ArrayBufferViewGetByteLength, @@ -292,8 +230,6 @@ module.exports = { nonOpPull, nonOpStart, nonOpWrite, - getIterator, - iteratorNext, kType, kState, };