1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

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>
This commit is contained in:
Milly 2024-05-28 06:29:54 +09:00 committed by GitHub
parent e44c538f37
commit 35e5159c8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 31 deletions

View file

@ -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 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) {
iterator = obj[SymbolIterator]();
if (!isObject(iterator)) {
throw new TypeError("[Symbol.iterator] returned a non-object value");
}
} else {
throw new TypeError("No iterator found");
}
if (typeof iterator.next !== "function") {
throw new TypeError("iterator.next is not a function");
}
return iterator;
}
// 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]();
}
} else {
if (obj[SymbolIterator] == null) {
throw new TypeError("No iterator found");
}
return obj[SymbolIterator]();
}
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;

View file

@ -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,