27.1 Iteration

27.1.1 Common Iteration Interfaces

An interface is a set of property keys whose associated values match a specific specification. Any object that provides all the properties as described by an interface's specification conforms to that interface. An interface is not represented by a distinct object. There may be many separately implemented objects that conform to any interface. An individual object may conform to multiple interfaces.

27.1.1.1 The Iterable Interface

The Iterable interface includes the property described in Table 62:

Table 62: Iterable Interface Required Properties
Property Value Requirements
@@iterator A function that returns an Iterator object. The returned object must conform to the Iterator interface.

27.1.1.2 The Iterator Interface

An object that implements the Iterator interface must include the property in Table 63. Such objects may also implement the properties in Table 64.

Table 63: Iterator Interface Required Properties
Property Value Requirements
"next" A function that returns an IteratorResult object. The returned object must conform to the IteratorResult interface. If a previous call to the next method of an Iterator has returned an IteratorResult object whose "done" property is true, then all subsequent calls to the next method of that object should also return an IteratorResult object whose "done" property is true. However, this requirement is not enforced.
Note 1

Arguments may be passed to the next function but their interpretation and validity is dependent upon the target Iterator. The for-of statement and other common users of Iterators do not pass any arguments, so Iterator objects that expect to be used in such a manner must be prepared to deal with being called with no arguments.

Table 64: Iterator Interface Optional Properties
Property Value Requirements
"return" A function that returns an IteratorResult object. The returned object must conform to the IteratorResult interface. Invoking this method notifies the Iterator object that the caller does not intend to make any more next method calls to the Iterator. The returned IteratorResult object will typically have a "done" property whose value is true, and a "value" property with the value passed as the argument of the return method. However, this requirement is not enforced.
"throw" A function that returns an IteratorResult object. The returned object must conform to the IteratorResult interface. Invoking this method notifies the Iterator object that the caller has detected an error condition. The argument may be used to identify the error condition and typically will be an exception object. A typical response is to throw the value passed as the argument. If the method does not throw, the returned IteratorResult object will typically have a "done" property whose value is true.
Note 2

Typically callers of these methods should check for their existence before invoking them. Certain ECMAScript language features including for-of, yield*, and array destructuring call these methods after performing an existence check. Most ECMAScript library functions that accept Iterable objects as arguments also conditionally call them.

27.1.1.3 The AsyncIterable Interface

The AsyncIterable interface includes the properties described in Table 65:

Table 65: AsyncIterable Interface Required Properties
Property Value Requirements
@@asyncIterator A function that returns an AsyncIterator object. The returned object must conform to the AsyncIterator interface.

27.1.1.4 The AsyncIterator Interface

An object that implements the AsyncIterator interface must include the properties in Table 66. Such objects may also implement the properties in Table 67.

Table 66: AsyncIterator Interface Required Properties
Property Value Requirements
"next" A function that returns a promise for an IteratorResult object.

The returned promise, when fulfilled, must fulfill with an object which conforms to the IteratorResult interface. If a previous call to the next method of an AsyncIterator has returned a promise for an IteratorResult object whose "done" property is true, then all subsequent calls to the next method of that object should also return a promise for an IteratorResult object whose "done" property is true. However, this requirement is not enforced.

Additionally, the IteratorResult object that serves as a fulfillment value should have a "value" property whose value is not a promise (or "thenable"). However, this requirement is also not enforced.

Note 1

Arguments may be passed to the next function but their interpretation and validity is dependent upon the target AsyncIterator. The for-await-of statement and other common users of AsyncIterators do not pass any arguments, so AsyncIterator objects that expect to be used in such a manner must be prepared to deal with being called with no arguments.

Table 67: AsyncIterator Interface Optional Properties
Property Value Requirements
"return" A function that returns a promise for an IteratorResult object.

The returned promise, when fulfilled, must fulfill with an object which conforms to the IteratorResult interface. Invoking this method notifies the AsyncIterator object that the caller does not intend to make any more next method calls to the AsyncIterator. The returned promise will fulfill with an IteratorResult object which will typically have a "done" property whose value is true, and a "value" property with the value passed as the argument of the return method. However, this requirement is not enforced.

Additionally, the IteratorResult object that serves as a fulfillment value should have a "value" property whose value is not a promise (or "thenable"). If the argument value is used in the typical manner, then if it is a rejected promise, a promise rejected with the same reason should be returned; if it is a fulfilled promise, then its fulfillment value should be used as the "value" property of the returned promise's IteratorResult object fulfillment value. However, these requirements are also not enforced.

"throw" A function that returns a promise for an IteratorResult object.

The returned promise, when fulfilled, must fulfill with an object which conforms to the IteratorResult interface. Invoking this method notifies the AsyncIterator object that the caller has detected an error condition. The argument may be used to identify the error condition and typically will be an exception object. A typical response is to return a rejected promise which rejects with the value passed as the argument.

If the returned promise is fulfilled, the IteratorResult fulfillment value will typically have a "done" property whose value is true. Additionally, it should have a "value" property whose value is not a promise (or "thenable"), but this requirement is not enforced.

Note 2

Typically callers of these methods should check for their existence before invoking them. Certain ECMAScript language features including for-await-of and yield* call these methods after performing an existence check.

27.1.1.5 The IteratorResult Interface

The IteratorResult interface includes the properties listed in Table 68:

Table 68: IteratorResult Interface Properties
Property Value Requirements
"done" Either true or false. This is the result status of an iterator next method call. If the end of the iterator was reached "done" is true. If the end was not reached "done" is false and a value is available. If a "done" property (either own or inherited) does not exist, it is consider to have the value false.
"value" Any ECMAScript language value. If done is false, this is the current iteration element value. If done is true, this is the return value of the iterator, if it supplied one. If the iterator does not have a return value, "value" is undefined. In that case, the "value" property may be absent from the conforming object if it does not inherit an explicit "value" property.

27.1.2 The %IteratorPrototype% Object

The %IteratorPrototype% object:

Note

All objects defined in this specification that implement the Iterator interface also inherit from %IteratorPrototype%. ECMAScript code may also define objects that inherit from %IteratorPrototype%. The %IteratorPrototype% object provides a place where additional methods that are applicable to all iterator objects may be added.

The following expression is one way that ECMAScript code can access the %IteratorPrototype% object:

Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

27.1.2.1 %IteratorPrototype% [ @@iterator ] ( )

The following steps are taken:

  1. Return the this value.

The value of the "name" property of this function is "[Symbol.iterator]".

27.1.3 The %AsyncIteratorPrototype% Object

The %AsyncIteratorPrototype% object:

Note

All objects defined in this specification that implement the AsyncIterator interface also inherit from %AsyncIteratorPrototype%. ECMAScript code may also define objects that inherit from %AsyncIteratorPrototype%. The %AsyncIteratorPrototype% object provides a place where additional methods that are applicable to all async iterator objects may be added.

27.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( )

The following steps are taken:

  1. Return the this value.

The value of the "name" property of this function is "[Symbol.asyncIterator]".

27.1.4 Async-from-Sync Iterator Objects

An Async-from-Sync Iterator object is an async iterator that adapts a specific synchronous iterator. There is not a named constructor for Async-from-Sync Iterator objects. Instead, Async-from-Sync iterator objects are created by the CreateAsyncFromSyncIterator abstract operation as needed.

27.1.4.1 CreateAsyncFromSyncIterator ( syncIteratorRecord )

The abstract operation CreateAsyncFromSyncIterator takes argument syncIteratorRecord. It is used to create an async iterator Record from a synchronous iterator Record. It performs the following steps when called:

  1. Let asyncIterator be ! OrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »).
  2. Set asyncIterator.[[SyncIteratorRecord]] to syncIteratorRecord.
  3. Let nextMethod be ! Get(asyncIterator, "next").
  4. Let iteratorRecord be the Record { [[Iterator]]: asyncIterator, [[NextMethod]]: nextMethod, [[Done]]: false }.
  5. Return iteratorRecord.

27.1.4.2 The %AsyncFromSyncIteratorPrototype% Object

The %AsyncFromSyncIteratorPrototype% object:

  • has properties that are inherited by all Async-from-Sync Iterator Objects.
  • is an ordinary object.
  • has a [[Prototype]] internal slot whose value is %AsyncIteratorPrototype%.
  • has the following properties:

27.1.4.2.1 %AsyncFromSyncIteratorPrototype%.next ( [ value ] )

  1. Let O be the this value.
  2. Assert: Type(O) is Object and O has a [[SyncIteratorRecord]] internal slot.
  3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  4. Let syncIteratorRecord be O.[[SyncIteratorRecord]].
  5. If value is present, then
    1. Let result be IteratorNext(syncIteratorRecord, value).
  6. Else,
    1. Let result be IteratorNext(syncIteratorRecord).
  7. IfAbruptRejectPromise(result, promiseCapability).
  8. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).

27.1.4.2.2 %AsyncFromSyncIteratorPrototype%.return ( [ value ] )

  1. Let O be the this value.
  2. Assert: Type(O) is Object and O has a [[SyncIteratorRecord]] internal slot.
  3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  4. Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
  5. Let return be GetMethod(syncIterator, "return").
  6. IfAbruptRejectPromise(return, promiseCapability).
  7. If return is undefined, then
    1. Let iterResult be ! CreateIterResultObject(value, true).
    2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »).
    3. Return promiseCapability.[[Promise]].
  8. If value is present, then
    1. Let result be Call(return, syncIterator, « value »).
  9. Else,
    1. Let result be Call(return, syncIterator).
  10. IfAbruptRejectPromise(result, promiseCapability).
  11. If Type(result) is not Object, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
    2. Return promiseCapability.[[Promise]].
  12. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).

27.1.4.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [ value ] )

Note
In this specification, value is always provided, but is left optional for consistency with %AsyncFromSyncIteratorPrototype%.return ( [ value ] ).
  1. Let O be the this value.
  2. Assert: Type(O) is Object and O has a [[SyncIteratorRecord]] internal slot.
  3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  4. Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
  5. Let throw be GetMethod(syncIterator, "throw").
  6. IfAbruptRejectPromise(throw, promiseCapability).
  7. If throw is undefined, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « value »).
    2. Return promiseCapability.[[Promise]].
  8. If value is present, then
    1. Let result be Call(throw, syncIterator, « value »).
  9. Else,
    1. Let result be Call(throw, syncIterator).
  10. IfAbruptRejectPromise(result, promiseCapability).
  11. If Type(result) is not Object, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
    2. Return promiseCapability.[[Promise]].
  12. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).

27.1.4.2.4 Async-from-Sync Iterator Value Unwrap Functions

An async-from-sync iterator value unwrap function is an anonymous built-in function that is used by AsyncFromSyncIteratorContinuation when processing the "value" property of an IteratorResult object, in order to wait for its value if it is a promise and re-package the result in a new "unwrapped" IteratorResult object. Each async-from-sync iterator value unwrap function has a [[Done]] internal slot.

When an async-from-sync iterator value unwrap function is called with argument value, the following steps are taken:

  1. Let F be the active function object.
  2. Return ! CreateIterResultObject(value, F.[[Done]]).

27.1.4.3 Properties of Async-from-Sync Iterator Instances

Async-from-Sync Iterator instances are ordinary objects that inherit properties from the %AsyncFromSyncIteratorPrototype% intrinsic object. Async-from-Sync Iterator instances are initially created with the internal slots listed in Table 69. Async-from-Sync Iterator instances are not directly observable from ECMAScript code.

Table 69: Internal Slots of Async-from-Sync Iterator Instances
Internal Slot Description
[[SyncIteratorRecord]] A Record, of the type returned by GetIterator, representing the original synchronous iterator which is being adapted.

27.1.4.4 AsyncFromSyncIteratorContinuation ( result, promiseCapability )

The abstract operation AsyncFromSyncIteratorContinuation takes arguments result and promiseCapability (a PromiseCapability Record). It performs the following steps when called:

  1. Let done be IteratorComplete(result).
  2. IfAbruptRejectPromise(done, promiseCapability).
  3. Let value be IteratorValue(result).
  4. IfAbruptRejectPromise(value, promiseCapability).
  5. Let valueWrapper be PromiseResolve(%Promise%, value).
  6. IfAbruptRejectPromise(valueWrapper, promiseCapability).
  7. Let steps be the algorithm steps defined in Async-from-Sync Iterator Value Unwrap Functions.
  8. Let length be the number of non-optional parameters of the function definition in Async-from-Sync Iterator Value Unwrap Functions.
  9. Let onFulfilled be ! CreateBuiltinFunction(steps, length, "", « [[Done]] »).
  10. Set onFulfilled.[[Done]] to done.
  11. Perform ! PerformPromiseThen(valueWrapper, onFulfilled, undefined, promiseCapability).
  12. Return promiseCapability.[[Promise]].