Skip to content

Commit 8c0a889

Browse files
authored
explainer/spec: Sync inputs must await each item (#11)
Fixes #9. See also #7.
1 parent c096610 commit 8c0a889

File tree

2 files changed

+41
-42
lines changed

2 files changed

+41
-42
lines changed

README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,20 @@ will also reject with that error.)
7575
`thisArg` is an optional value with which to call `mapfn`
7676
(or `undefined` by default).
7777

78-
Like `Array.from`, `Array.fromAsync` is a **generic factory method**.
78+
Like `for await`, when `Array.fromAsync` receives a **sync-iterable object**
79+
(and that object is not async iterable),
80+
then it creates a sync iterator for that object and adds its items to an array.
81+
When **any yielded item is a promise**, then that promise will **block** the iteration
82+
until it **resolves** to a value (in which case that value is what is added to the array)
83+
or until it **rejects** with an error (in which case
84+
the promise returned by `Array.fromAsync` itself will reject with that error).
85+
86+
Like `Array.from`, `Array.fromAsync` also works on non-iterable **array-like objects**
87+
(i.e., objects with a length property and indexed elements).
88+
As with sync-iterable objects, any element that is a promise must settle first,
89+
and the value to which it resolves (if any) will be what is added to the resulting array.
90+
91+
Also like `Array.from`, `Array.fromAsync` is a **generic factory method**.
7992
It does not require that its `this` value be the `Array` constructor,
8093
and it can be transferred to or inherited by any other constructors
8194
that may be called with a single numeric argument.

spec.html

+27-41
Original file line numberDiff line numberDiff line change
@@ -48,53 +48,39 @@ <h1><ins>Array.fromAsync ( _asyncItems_ [ , _mapfn_ [ , _thisArg_ ] ] )</ins></h
4848
1. Else,
4949
1. If IsCallable(_mapfn_) is *false*, throw a *TypeError* exception.
5050
1. Let _mapping_ be *true*.
51-
1. Let _usingAsyncOrSyncIterator_ be ? GetMethod(_asyncItems_, @@asyncIterator).
52-
1. If _usingAsyncOrSyncIterator_ is *undefined*, let _usingAsyncOrSyncIterator_ be ? GetMethod(_asyncItems_, @@iterator).
53-
1. If _usingAsyncOrSyncIterator_ is not *undefined*, then
54-
1. If IsConstructor(_C_) is *true*, then
55-
1. Let _A_ be ? Construct(_C_).
56-
1. Else,
57-
1. Let _A_ be ! ArrayCreate(0).
58-
1. Let _iteratorRecord_ be ? GetIterator(_asyncItems_, ~async~, _usingAsyncOrSyncIterator_).
59-
1. Let _k_ be 0.
60-
1. Repeat,
61-
1. If _k_ &ge; 2<sup>53</sup> - 1, then
62-
1. Let _error_ be ThrowCompletion(a newly created *TypeError* object).
63-
1. Return ? AsyncIteratorClose(_iteratorRecord_, _error_).
64-
1. Let _Pk_ be ! ToString(𝔽(_k_)).
65-
1. Let _next_ be ? Await(IteratorStep(_iteratorRecord_)).
66-
1. If _next_ is *false*, then
67-
1. Perform ? Set(_A_, *"length"*, 𝔽(_k_), *true*).
68-
1. Return _A_.
69-
1. Let _nextValue_ be ? IteratorValue(_next_).
70-
1. If _mapping_ is *true*, then
71-
1. Let _mappedValue_ be Call(_mapfn_, _thisArg_, &laquo; _nextValue_, 𝔽(_k_) &raquo;).
72-
1. IfAbruptCloseAsyncIterator(_iteratorRecord_, _mappedValue_).
73-
1. Let _mappedValue_ to Await(_mappedValue_).
74-
1. IfAbruptCloseAsyncIterator(_iteratorRecord_, _mappedValue_).
75-
1. Set _mappedValue_ to _mappedValue_.[[Value]].
76-
1. Else, let _mappedValue_ be _nextValue_.
77-
1. Let _defineStatus_ be CreateDataPropertyOrThrow(_A_, _Pk_, _mappedValue_).
78-
1. If _defineStatus_ is an abrupt completion, return ? AsyncIteratorClose(_iteratorRecord_, _defineStatus_).
79-
1. Set _k_ to _k_ + 1.
80-
1. NOTE: _items_ is not an AsyncIterable or Iterable so assume it is an array-like object.
81-
1. Let _arrayLike_ be ! ToObject(_items_).
82-
1. Let _len_ be ? LengthOfArrayLike(_arrayLike_).
51+
1. Let _usingAsyncIterator_ be ? GetMethod(_asyncItems_, @@asyncIterator).
52+
1. If _usingAsyncIterator_ is *undefined*,
53+
1. Let _usingSyncIterator_ be ? GetMethod(_asyncItems_, @@iterator).
54+
1. If _usingSyncIterator_ is *undefined*, set _usingSyncIterator_ to %Array.prototype.values%.
8355
1. If IsConstructor(_C_) is *true*, then
84-
1. Let _A_ be ? Construct(_C_, &laquo; 𝔽(_len_) &raquo;).
56+
1. Let _A_ be ? Construct(_C_).
8557
1. Else,
86-
1. Let _A_ be ? ArrayCreate(_len_).
58+
1. Let _A_ be ! ArrayCreate(0).
59+
1. If _usingAsyncIterator_ is not *undefined*, then
60+
1. Let _iteratorRecord_ be ? GetIterator(_asyncItems_, ~async~, _usingAsyncIterator_).
61+
1. Else,
62+
1. Let _iteratorRecord_ be ? CreateAsyncFromSyncIterator(GetIterator(_syncItems_, ~sync~, _usingSyncIterator_)).
8763
1. Let _k_ be 0.
88-
1. Repeat, while _k_ &lt; _len_,
64+
1. Repeat,
65+
1. If _k_ &ge; 2<sup>53</sup> - 1, then
66+
1. Let _error_ be ThrowCompletion(a newly created *TypeError* object).
67+
1. Return ? AsyncIteratorClose(_iteratorRecord_, _error_).
8968
1. Let _Pk_ be ! ToString(𝔽(_k_)).
90-
1. Let _kValue_ be ? Get(_arrayLike_, _Pk_).
69+
1. Let _next_ be ? Await(IteratorStep(_iteratorRecord_)).
70+
1. If _next_ is *false*, then
71+
1. Perform ? Set(_A_, *"length"*, 𝔽(_k_), *true*).
72+
1. Return _A_.
73+
1. Let _nextValue_ be ? IteratorValue(_next_).
9174
1. If _mapping_ is *true*, then
92-
1. Let _mappedValue_ be ? Call(_mapfn_, _thisArg_, &laquo; _kValue_, 𝔽(_k_) &raquo;).
93-
1. Else, let _mappedValue_ be _kValue_.
94-
1. Perform ? CreateDataPropertyOrThrow(_A_, _Pk_, _mappedValue_).
75+
1. Let _mappedValue_ be Call(_mapfn_, _thisArg_, &laquo; _nextValue_, 𝔽(_k_) &raquo;).
76+
1. IfAbruptCloseAsyncIterator(_iteratorRecord_, _mappedValue_).
77+
1. Let _mappedValue_ to Await(_mappedValue_).
78+
1. IfAbruptCloseAsyncIterator(_iteratorRecord_, _mappedValue_).
79+
1. Set _mappedValue_ to _mappedValue_.[[Value]].
80+
1. Else, let _mappedValue_ be _nextValue_.
81+
1. Let _defineStatus_ be CreateDataPropertyOrThrow(_A_, _Pk_, _mappedValue_).
82+
1. If _defineStatus_ is an abrupt completion, return ? AsyncIteratorClose(_iteratorRecord_, _defineStatus_).
9583
1. Set _k_ to _k_ + 1.
96-
1. Perform ? Set(_A_, *"length"*, 𝔽(_len_), *true*).
97-
1. Return _A_.
9884
1. Perform AsyncFunctionStart(promiseCapability, _fromAsyncClosure_).
9985
1. Return Completion { [[Type]]: ~return~, [[Value]]: _promiseCapability_.[[Promise]], [[Target]]: ~empty~ }.
10086
</emu-alg>

0 commit comments

Comments
 (0)