Closed mgaudet closed 10 months ago
Good catch. The fix is a little more complicated than your suggestion, though. IteratorStep isn't usable at all with async iterators; it performs IteratorComplete on the result of the next method, which assumes the return value of that method is an iterator result, not a promise for one.
I think instead we want to invoke the next method directly, like for await does (which is currently one of the only consumers of the async iteration protocol):
1. Let nextResult be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).
1. Set nextResult to ? Await(nextResult).
1. If nextResult is not an Object, throw a TypeError exception.
1. Let done be ? IteratorComplete(nextResult).
1. If done is true,
1. Perform ? Set(A, "length", 𝔽(k), true).
1. Return Completion Record { [[Type]]: return, [[Value]]: A, [[Target]]: empty }.
1. Let nextValue be ? IteratorValue(nextResult).
[etc]
Alternatively, I suppose we could have IteratorStep
take an option "async" flag which would cause it to do the awaiting itself. Something to worry about during the stage 4 PR, possibly.
Note: I'm preparing to ship Array.fromAsync. It will ship using the above spec-patch semantics.
In the published spec, Step 3.j.ii.3 and 4 are the termination condition of the iteration:
The problem is that
IteratorStep
doesn't properly flag termination on an async iterator; the return value of theIteratorNext
in async iteration is a Promise, which doesn't have a "done" property, and so we always get the promise object fromIteratorStep
.I think the patch is actually relatively simple; Step 3.j.ii.4 should be expanded into the steps which have the effect of "if
next.done
is false:"