Skip to content

Commit

Permalink
fix(ext/web): ReadableStream.from() allows Iterable <Milly>
Browse files Browse the repository at this point in the history
  • Loading branch information
Milly committed May 24, 2024
1 parent 214cdaa commit 8b8d1ab
Showing 1 changed file with 26 additions and 22 deletions.
48 changes: 26 additions & 22 deletions ext/web/06_streams.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
} 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]]");
Expand Down Expand Up @@ -5204,12 +5208,12 @@ 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) {
Expand All @@ -5218,12 +5222,12 @@ class ReadableStream {
readableStreamDefaultControllerEnqueue(stream[_controller], 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;
Expand Down

0 comments on commit 8b8d1ab

Please sign in to comment.