mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -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:
parent
e44c538f37
commit
35e5159c8d
2 changed files with 32 additions and 31 deletions
|
@ -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) {
|
||||
iterator = obj[SymbolIterator]();
|
||||
if (!isObject(iterator)) {
|
||||
throw new TypeError("[Symbol.iterator] returned a non-object value");
|
||||
}
|
||||
} else {
|
||||
if (obj[SymbolIterator] == null) {
|
||||
throw new TypeError("No iterator found");
|
||||
}
|
||||
return obj[SymbolIterator]();
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue