Skip to content

Fix Array.fromAsync iterator close semantics - #1596

Open
littledivy wants to merge 1 commit into
quickjs-ng:masterfrom
littledivy:fix/fromasync-iterator-close
Open

Fix Array.fromAsync iterator close semantics#1596
littledivy wants to merge 1 commit into
quickjs-ng:masterfrom
littledivy:fix/fromasync-iterator-close

Conversation

@littledivy

Copy link
Copy Markdown
Contributor

Array.fromAsync closed its async iterator in a finally block, which calls return() even when the iterator completed normally, and never awaits the result. The spec only closes the iterator on an abrupt completion (IfAbruptCloseAsyncIterator, from the element await or the mapper), leaves an exhausted iterator alone, and awaits the return() result before the returned promise settles.

const iter = {
  [Symbol.asyncIterator]() {
    let i = 0;
    return {
      async next() { return { value: i, done: i++ > 0 }; },
      async return() { console.log("return()"); return { done: true }; },
    };
  },
};
await Array.fromAsync(iter);   // before: logs "return()"   after: no close
case before after
iterator exhausted (done: true) return() called not called
mapper throws return() fire-and-forget awaited before rejection
return() rejects after mapper throws unhandled rejection original error kept

Disclaimer: This is an AI-assisted patch from the v8x project.

Array.fromAsync closed its async iterator in a finally block, which
calls return() even when the iterator completed normally, and does not
await the result. The spec only closes the iterator on an abrupt
completion (IfAbruptCloseAsyncIterator, from the element await or the
mapper), leaves an exhausted iterator alone, and awaits the return()
result before the returned promise settles.

Close the iterator from a per-element catch instead: await return() on
failure, rethrow the original error even if return() itself throws, and
skip the close entirely on normal completion.
@bnoordhuis

Copy link
Copy Markdown
Contributor

Can you upstream the test to test262? Then we can be sure all engines implement identical behavior.

@littledivy

Copy link
Copy Markdown
Contributor Author

Can you upstream the test to test262? Then we can be sure all engines implement identical behavior.

Opened PR tc39/test262#5095 and V8 CL https://chromium-review.googlesource.com/c/v8/v8/+/8140683

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants