diff --git a/ext/web/06_streams.js b/ext/web/06_streams.js index 0192a54c67552b..4ab1c3b5b0a511 100644 --- a/ext/web/06_streams.js +++ b/ext/web/06_streams.js @@ -5088,28 +5088,32 @@ function initializeCountSizeFunction(globalObject) { WeakMapPrototypeSet(countSizeFunctionWeakMap, globalObject, size); } -async function* createAsyncFromSyncIterator(syncIterator) { - // deno-lint-ignore prefer-primordials - yield* syncIterator; -} - // Ref: https://tc39.es/ecma262/#sec-getiterator -function getIterator(obj, async = false) { - if (async) { - if (obj[SymbolAsyncIterator] == null) { - if (obj[SymbolIterator] == null) { - throw new TypeError("No iterator found"); - } - return createAsyncFromSyncIterator(obj[SymbolIterator]()); - } else { - return obj[SymbolAsyncIterator](); +function getAsyncOrSyncIterator(obj) { + let iterator; + if (obj[SymbolAsyncIterator] != null) { + iterator = obj[SymbolAsyncIterator](); + if (!isObject(iterator)) { + throw new TypeError( + "[Symbol.asyncIterator] returned a non-object value", + ); } - } else { - if (obj[SymbolIterator] == null) { - throw new TypeError("No iterator found"); + } else if (obj[SymbolIterator] != null) { + iterator = obj[SymbolIterator](); + if (!isObject(iterator)) { + throw new TypeError("[Symbol.iterator] returned a non-object value"); } - return obj[SymbolIterator](); + } else { + throw new TypeError("No iterator found"); + } + if (typeof iterator.next !== "function") { + throw new TypeError("iterator.next is not a function"); } + return iterator; +} + +function isObject(x) { + return (typeof x === "object" && x != null) || typeof x === "function"; } const _resourceBacking = Symbol("[[resourceBacking]]"); @@ -5204,26 +5208,29 @@ class ReadableStream { ); asyncIterable = webidl.converters.any(asyncIterable); - const iterator = getIterator(asyncIterable, true); + const iterator = getAsyncOrSyncIterator(asyncIterable); const stream = createReadableStream(noop, async () => { // deno-lint-ignore prefer-primordials const res = await iterator.next(); - if (typeof res !== "object") { + if (!isObject(res)) { throw new TypeError("iterator.next value is not an object"); } if (res.done) { readableStreamDefaultControllerClose(stream[_controller]); } else { - readableStreamDefaultControllerEnqueue(stream[_controller], res.value); + readableStreamDefaultControllerEnqueue( + stream[_controller], + await res.value, + ); } }, async (reason) => { - if (typeof iterator.return === "undefined") { + if (iterator.return == null) { return undefined; } else { // deno-lint-ignore prefer-primordials const res = await iterator.return(reason); - if (typeof res !== "object") { + if (!isObject(res)) { throw new TypeError("iterator.return value is not an object"); } else { return undefined; diff --git a/tests/wpt/runner/expectation.json b/tests/wpt/runner/expectation.json index 78a33badf644e2..30c9d692eabcb1 100644 --- a/tests/wpt/runner/expectation.json +++ b/tests/wpt/runner/expectation.json @@ -3170,14 +3170,8 @@ "owning-type-message-port.any.worker.html": false, "owning-type.any.html": false, "owning-type.any.worker.html": false, - "from.any.html": [ - "ReadableStream.from accepts a sync iterable of values", - "ReadableStream.from accepts a sync iterable of promises" - ], - "from.any.worker.html": [ - "ReadableStream.from accepts a sync iterable of values", - "ReadableStream.from accepts a sync iterable of promises" - ] + "from.any.html": true, + "from.any.worker.html": true }, "transform-streams": { "backpressure.any.html": true,