diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index 551b347bf1e194..597135778a1e0f 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -1365,6 +1365,9 @@ function readableStreamFromIterable(iterable) { throw new ERR_ARG_NOT_ITERABLE(iterable); } const iterator = FunctionPrototypeCall(iteratorGetter, iterable); + if (iterator === null || (typeof iterator !== 'object' && typeof iterator !== 'function')) { + throw new ERR_INVALID_STATE.TypeError('The iterator method must return an object'); + } const startAlgorithm = nonOpStart; async function pullAlgorithm() { diff --git a/test/parallel/test-webstream-readable-from.js b/test/parallel/test-webstream-readable-from.js index 470ee5d60d76e2..0a0c6943c72556 100644 --- a/test/parallel/test-webstream-readable-from.js +++ b/test/parallel/test-webstream-readable-from.js @@ -7,3 +7,22 @@ assert.throws( () => ReadableStream.from({}), { code: 'ERR_ARG_NOT_ITERABLE', name: 'TypeError' }, ); + +const invalidIterators = [ + { [Symbol.iterator]: () => 42 }, + { [Symbol.asyncIterator]: () => 42 }, +]; + +for (const iterable of invalidIterators) { + assert.throws( + () => ReadableStream.from(iterable), + { code: 'ERR_INVALID_STATE', name: 'TypeError' }, + ); +} + +function functionIterator() {} + +// doesNotThrow +ReadableStream.from({ + [Symbol.iterator]: () => functionIterator, +}); diff --git a/test/wpt/status/streams.json b/test/wpt/status/streams.json index ffa7e9d65f2338..2268ffcc87ac91 100644 --- a/test/wpt/status/streams.json +++ b/test/wpt/status/streams.json @@ -8,15 +8,6 @@ "readable-streams/cross-realm-crash.window.js": { "skip": "Browser-specific test" }, - "readable-streams/from.any.js": { - "fail": { - "note": "does not synchronously validate that the value returned by @@iterator/@@asyncIterator is an object", - "expected": [ - "ReadableStream.from throws on invalid iterables; specifically an object with an @@iterator method returning a non-object", - "ReadableStream.from throws on invalid iterables; specifically an object with an @@asyncIterator method returning a non-object" - ] - } - }, "readable-streams/owning-type-message-port.any.js": { "fail": { "note": "Readable streams with type owning are not yet supported",