diff --git a/README.md b/README.md index 9181864..b7df8c2 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,20 @@ will also reject with that error.) `thisArg` is an optional value with which to call `mapfn` (or `undefined` by default). -Like `Array.from`, `Array.fromAsync` is a **generic factory method**. +Like `for await`, when `Array.fromAsync` receives a **sync-iterable object** +(and that object is not async iterable), +then it creates a sync iterator for that object and adds its items to an array. +When **any yielded item is a promise**, then that promise will **block** the iteration +until it **resolves** to a value (in which case that value is what is added to the array) +or until it **rejects** with an error (in which case +the promise returned by `Array.fromAsync` itself will reject with that error). + +Like `Array.from`, `Array.fromAsync` also works on non-iterable **array-like objects** +(i.e., objects with a length property and indexed elements). +As with sync-iterable objects, any element that is a promise must settle first, +and the value to which it resolves (if any) will be what is added to the resulting array. + +Also like `Array.from`, `Array.fromAsync` is a **generic factory method**. It does not require that its `this` value be the `Array` constructor, and it can be transferred to or inherited by any other constructors that may be called with a single numeric argument. diff --git a/spec.html b/spec.html index 0c06bd5..7b97601 100644 --- a/spec.html +++ b/spec.html @@ -48,42 +48,96 @@

Array.fromAsync ( _asyncItems_ [ , _mapfn_ [ , _thisArg_ ] ] )53 - 1, then + 1. Let _error_ be ThrowCompletion(a newly created *TypeError* object). + 1. Return ? AsyncIteratorClose(_iteratorRecord_, _error_). + 1. Let _Pk_ be ! ToString(𝔽(_k_)). + 1. Let _next_ be ? Await(IteratorStep(_iteratorRecord_)). + 1. If _next_ is *false*, then + 1. Perform ? Set(_A_, *"length"*, 𝔽(_k_), *true*). + 1. Return _A_. + 1. Let _nextValue_ be ? IteratorValue(_next_). + 1. If _mapping_ is *true*, then + 1. Let _mappedValue_ be Call(_mapfn_, _thisArg_, « _nextValue_, 𝔽(_k_) »). + 1. IfAbruptCloseAsyncIterator(_iteratorRecord_, _mappedValue_). + 1. Let _mappedValue_ to Await(_mappedValue_). + 1. IfAbruptCloseAsyncIterator(_iteratorRecord_, _mappedValue_). + 1. Set _mappedValue_ to _mappedValue_.[[Value]]. + 1. Else, let _mappedValue_ be _nextValue_. + 1. Let _defineStatus_ be CreateDataPropertyOrThrow(_A_, _Pk_, _mappedValue_). + 1. If _defineStatus_ is an abrupt completion, return ? AsyncIteratorClose(_iteratorRecord_, _defineStatus_). + 1. Set _k_ to _k_ + 1. + 1. Perform AsyncFunctionStart(promiseCapability, _fromAsyncClosure_). + 1. Return Completion { [[Type]]: ~return~, [[Value]]: _promiseCapability_.[[Promise]], [[Target]]: ~empty~ }. + + +

The `fromAsync` function is an intentionally generic factory method; it does not require that its *this* value be the Array constructor. Therefore it can be transferred to or inherited by any other constructors that may be called with a single numeric argument.

+
+ + + + + +

TypedArray Objects

+ + +

Properties of the %TypedArray% Intrinsic Object

+ + +

%TypedArray%.fromAsync ( _source_ [ , _mapfn_ [ , _thisArg_ ] ] )

+ + +

This section is a wholly new subsection of the original + Properties of the %TypedArray% Intrinsic Object clause, to be inserted before the %TypedArray%.from + clause.

+
+ +

When the `fromAsync` method is called, the following steps are taken:

+ + 1. Let _C_ be the *this* value. + 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). + 1. Let _fromAsyncClosure_ be a new Abstract Closure with no parameters that captures _C_ and _mapfn_ and performs the following steps when called: + 1. If IsConstructor(_C_) is *false*, throw a *TypeError* exception. + 1. If _mapfn_ is *undefined*, let _mapping_ be *false*. + 1. Else, + 1. If IsCallable(_mapfn_) is *false*, throw a *TypeError* exception. + 1. Let _mapping_ be *true*. + 1. Let _usingIterator_ be ? GetMethod(_source_, @@iterator). + 1. If _usingIterator_ is not *undefined*, then + 1. Let _values_ be ? IterableToList(_source_, _usingIterator_). + 1. Let _len_ be the number of elements in _values_. + 1. Let _targetObj_ be ? TypedArrayCreate(_C_, « 𝔽(_len_) »). 1. Let _k_ be 0. - 1. Repeat, - 1. If _k_ ≥ 253 - 1, then - 1. Let _error_ be ThrowCompletion(a newly created *TypeError* object). - 1. Return ? AsyncIteratorClose(_iteratorRecord_, _error_). + 1. Repeat, while _k_ < _len_, 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _next_ be ? Await(IteratorStep(_iteratorRecord_)). - 1. If _next_ is *false*, then - 1. Perform ? Set(_A_, *"length"*, 𝔽(_k_), *true*). - 1. Return _A_. - 1. Let _nextValue_ be ? IteratorValue(_next_). + 1. Let _kValue_ be the first element of _values_ and remove that element from _values_. 1. If _mapping_ is *true*, then - 1. Let _mappedValue_ be Call(_mapfn_, _thisArg_, « _nextValue_, 𝔽(_k_) »). - 1. IfAbruptCloseAsyncIterator(_iteratorRecord_, _mappedValue_). - 1. Let _mappedValue_ to Await(_mappedValue_). - 1. IfAbruptCloseAsyncIterator(_iteratorRecord_, _mappedValue_). - 1. Set _mappedValue_ to _mappedValue_.[[Value]]. - 1. Else, let _mappedValue_ be _nextValue_. - 1. Let _defineStatus_ be CreateDataPropertyOrThrow(_A_, _Pk_, _mappedValue_). - 1. If _defineStatus_ is an abrupt completion, return ? AsyncIteratorClose(_iteratorRecord_, _defineStatus_). + 1. Let _mappedValue_ be ? Call(_mapfn_, _thisArg_, « _kValue_, 𝔽(_k_) »). + 1. Else, let _mappedValue_ be _kValue_. + 1. Perform ? Set(_targetObj_, _Pk_, _mappedValue_, *true*). 1. Set _k_ to _k_ + 1. - 1. NOTE: _items_ is not an AsyncIterable or Iterable so assume it is an array-like object. - 1. Let _arrayLike_ be ! ToObject(_items_). + 1. Assert: _values_ is now an empty List. + 1. Return _targetObj_. + 1. NOTE: _source_ is not an Iterable so assume it is already an array-like object. + 1. Let _arrayLike_ be ! ToObject(_source_). 1. Let _len_ be ? LengthOfArrayLike(_arrayLike_). - 1. If IsConstructor(_C_) is *true*, then - 1. Let _A_ be ? Construct(_C_, « 𝔽(_len_) »). - 1. Else, - 1. Let _A_ be ? ArrayCreate(_len_). + 1. Let _targetObj_ be ? TypedArrayCreate(_C_, « 𝔽(_len_) »). 1. Let _k_ be 0. 1. Repeat, while _k_ < _len_, 1. Let _Pk_ be ! ToString(𝔽(_k_)). @@ -91,16 +145,12 @@

Array.fromAsync ( _asyncItems_ [ , _mapfn_ [ , _thisArg_ ] ] ) - -

The `fromAsync` function is an intentionally generic factory method; it does not require that its *this* value be the Array constructor. Therefore it can be transferred to or inherited by any other constructors that may be called with a single numeric argument.

-