summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilly <milly.ca@gmail.com>2024-05-28 06:29:54 +0900
committerGitHub <noreply@github.com>2024-05-27 21:29:54 +0000
commit35e5159c8d5987497b8980c1cf3996d241612957 (patch)
tree24056d26007f7bc477dabaabe166823249eafe96
parente44c538f37c48f738dea904cffe4cda67f689914 (diff)
fix(ext/web): `ReadableStream.from()` allows `Iterable` instead of `IterableIterator` (#23903)
`createAsyncFromSyncIterator(x)` which is used in `ReadableStream.from()` expects `x` as `Iterable` but, previous implements specify `Iterator` or `IterableIterator`. If it was `IterableIterator`, it would work, but if it was `Iterator`, an exception will occur. Tests have been merged into WPT. https://github.com/web-platform-tests/wpt/pull/46365 --------- Co-authored-by: Asher Gomez <ashersaupingomez@gmail.com>
-rw-r--r--ext/web/06_streams.js53
-rw-r--r--tests/wpt/runner/expectation.json10
2 files changed, 32 insertions, 31 deletions
diff --git a/ext/web/06_streams.js b/ext/web/06_streams.js
index 0192a54c6..4ab1c3b5b 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 78a33badf..30c9d692e 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,