Stage 2 Draft / September 26, 2022

Iterator Helpers

Contributing to this Proposal

This proposal is developed on GitHub with the help of the ECMAScript community. There are a number of ways to contribute to the development of this specification:

1 Well-Known Intrinsic Objects

Table 1: Well-Known Intrinsic Objects
Intrinsic Name Global Name ECMAScript Language Association
%AsyncIterator% AsyncIterator The AsyncIterator constructor (5.1.3.1)
%AsyncIteratorPrototype% AsyncIterator.prototype An object that all standard built-in async iterator objects indirectly inherit from

The initial value of the "prototype" data property of %AsyncIterator%; i.e., %AsyncIterator.prototype%

%Iterator% Iterator The Iterator constructor (5.1.2.1)
%IteratorPrototype% Iterator.prototype An object that all standard built-in iterator objects indirectly inherit from

The initial value of the "prototype" data property of %Iterator%; i.e., %Iterator.prototype%

2 Built-in Function Objects

If a built-in function object is not implemented as an ECMAScript function it must provide [[Call]] and [[Construct]] internal methods that conform to the following definitions: Unless otherwise specified, a built-in function object must provide [[Call]] and [[Construct]] internal methods that conform to the following definitions:

2.1 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , prototype [ , prefix ] ] ] )

The abstract operation CreateBuiltinFunction takes arguments behaviour (an Abstract Closure, a set of algorithm steps, or some other definition of a function's behaviour provided in this specification), length (a non-negative integer or +∞), name (a property key or a Private Name), and additionalInternalSlotsList (a List of names of internal slots) and optional arguments realm (a Realm Record), prototype (an Object or null), and prefix (a String) and returns a function object. additionalInternalSlotsList contains the names of additional internal slots that must be defined as part of the object. This operation creates a built-in function object. It performs the following steps when called:

  1. If realm is not present, set realm to the current Realm Record.
  2. If prototype is not present, set prototype to realm.[[Intrinsics]].[[%Function.prototype%]].
  3. Let internalSlotsList be a List containing the names of all the internal slots that 2 requires for the built-in function object that is about to be created.
  4. Append to internalSlotsList the elements of additionalInternalSlotsList.
  5. If behaviour is described as async, then
    1. Let func be a new built-in async function object that, when called, performs the action described by behaviour using the provided arguments as the values of the corresponding parameters specified by behaviour. The new function object has internal slots whose names are the elements of internalSlotsList, and an [[InitialName]] internal slot.
  6. Else,
    1. Let func be a new built-in function object that, when called, performs the action described by behaviour using the provided arguments as the values of the corresponding parameters specified by behaviour. The new function object has internal slots whose names are the elements of internalSlotsList, and an [[InitialName]] internal slot.
  7. Set func.[[Prototype]] to prototype.
  8. Set func.[[Extensible]] to true.
  9. Set func.[[Realm]] to realm.
  10. Set func.[[InitialName]] to null.
  11. Perform SetFunctionLength(func, length).
  12. If prefix is not present, then
    1. Perform SetFunctionName(func, name).
  13. Else,
    1. Perform SetFunctionName(func, name, prefix).
  14. Return func.

Each built-in function defined in this specification is created by calling the CreateBuiltinFunction abstract operation.

3 Built-in Async Function Objects

Built-in async function objects are built-in function objects that provide alternative [[Call]] and [[Construct]] internal methods that conform to the following definitions:

3.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of a built-in async function object F takes arguments thisArgument (an ECMAScript language value) and argumentsList (a List of ECMAScript language values) and returns a normal completion containing an ECMAScript language value. It performs the following steps when called:

  1. Let callerContext be the running execution context.
  2. If callerContext is not already suspended, suspend callerContext.
  3. Let calleeContext be a new execution context.
  4. Set the Function of calleeContext to F.
  5. Let calleeRealm be F.[[Realm]].
  6. Set the Realm of calleeContext to calleeRealm.
  7. Set the ScriptOrModule of calleeContext to null.
  8. Perform any necessary implementation-defined initialization of calleeContext.
  9. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  10. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  11. Let resultsClosure be a new Abstract Closure that captures F, thisArgument, and argumentsList and performs the following steps when called:
    1. Return the result of evaluating F in a manner that conforms to the specification of F. thisArgument is the this value, argumentsList provides the named parameters, and the NewTarget value is undefined.
  12. Perform AsyncFunctionStart(promiseCapability, resultsClosure).
  13. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  14. Return promiseCapability.

3.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of a built-in async function object F takes arguments argumentsList (a List of ECMAScript language values) and newTarget (a constructor) and returns either a normal completion containing an Object or a throw completion. It performs the following steps when called:

  1. Throw a TypeError exception.

4 Abstract Operations

4.1 Operations on Iterator Objects

4.1.1 GetIteratorDirect ( obj )

The abstract operation GetIteratorDirect takes argument obj (an ECMAScript language value) and returns either a normal completion containing an Iterator Record or a throw completion. It performs the following steps when called:

  1. If obj is not an Object, throw a TypeError exception.
  2. Let nextMethod be ? Get(obj, "next").
  3. If IsCallable(nextMethod) is false, throw a TypeError exception.
  4. Let iteratorRecord be Record { [[Iterator]]: obj, [[NextMethod]]: nextMethod, [[Done]]: false }.
  5. Return iteratorRecord.

5 Control Abstraction Objects

5.1 Iteration

5.1.1 Iterator Abstract Operations

5.1.1.1 IfAbruptCloseAsyncIterator ( value, iteratorRecord )

IfAbruptCloseAsyncIterator is a shorthand for a sequence of algorithm steps that use an Iterator Record. An algorithm step of the form:

  1. IfAbruptCloseAsyncIterator(value, iteratorRecord).

means the same thing as:

  1. If value is an abrupt completion, then
    1. Perform ? AsyncIteratorClose(iteratorRecord, value).
    2. Return value.
  2. Else if value is a Completion Record, set value to value.[[Value]].

5.1.2 Iterator Objects

5.1.2.1 The Iterator Constructor

The Iterator constructor:

  • is %Iterator%.
  • is the initial value of the Iterator property of the global object.
  • is designed to be subclassable. It may be used as the value of an extends clause of a class definition.

5.1.2.1.1 Iterator ( )

When the Iterator function is called, the following steps are taken:

  1. If NewTarget is undefined or the active function object, throw a TypeError exception.
  2. Return ? OrdinaryCreateFromConstructor(NewTarget, "%Iterator.prototype%").

5.1.2.2 Properties of the Iterator Constructor

5.1.2.2.1 Iterator.prototype

The initial value of Iterator.prototype is %Iterator.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

5.1.2.2.2 Iterator.from ( O )

  1. Let usingIterator be ? GetMethod(O, @@iterator).
  2. If usingIterator is not undefined, then
    1. Let iteratorRecord be ? GetIterator(O, sync, usingIterator).
    2. If IsCallable(iteratorRecord.[[NextMethod]]) is false, throw a TypeError exception.
    3. Let hasInstance be ? OrdinaryHasInstance(%Iterator%, iteratorRecord.[[Iterator]]).
    4. If hasInstance is true, then
      1. Return iteratorRecord.[[Iterator]].
  3. Else, Let iteratorRecord be ? GetIteratorDirect(O).
  4. Let wrapper be OrdinaryObjectCreate(%WrapForValidIteratorPrototype%, « [[Iterated]] »).
  5. Set wrapper.[[Iterated]] to iteratorRecord.
  6. Return wrapper.

5.1.2.2.2.1 The %WrapForValidIteratorPrototype% Object

The %WrapForValidIteratorPrototype% object:

5.1.2.2.2.1.1 %WrapForValidIteratorPrototype%.next ( )

  1. Let O be this value.
  2. Perform ? RequireInternalSlot(O, [[Iterated]]).
  3. Let iteratorRecord be O.[[Iterated]].
  4. Return ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

5.1.2.2.2.1.2 %WrapForValidIteratorPrototype%.return ( )

  1. Let O be this value.
  2. Perform ? RequireInternalSlot(O, [[Iterated]]).
  3. Let iterator be O.[[Iterated]].[[Iterator]].
  4. Assert: iterator is an Object.
  5. Let returnMethod be ? GetMethod(iterator, "return").
  6. If returnMethod is undefined, then
    1. Return CreateIterResultObject(undefined, true).
  7. Return ? Call(returnMethod, iterator).

5.1.3 AsyncIterator Objects

5.1.3.1 The AsyncIterator Constructor

The AsyncIterator constructor:

  • is %AsyncIterator%.
  • is the initial value of the AsyncIterator property of the global object.
  • is designed to be subclassable. It may be used as the value of an extends clause of a class definition.

5.1.3.1.1 AsyncIterator ( )

When the AsyncIterator function is called, the following steps are taken:

  1. If NewTarget is undefined or the active function object, throw a TypeError exception.
  2. Return ? OrdinaryCreateFromConstructor(NewTarget, "%AsyncIterator.prototype%").

5.1.3.2 Properties of the AsyncIterator Constructor

5.1.3.2.1 AsyncIterator.prototype

The initial value of AsyncIterator.prototype is %AsyncIterator.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

5.1.3.2.2 AsyncIterator.from ( O )

  1. Let usingIterator be ? GetMethod(O, @@asyncIterator).
  2. Let iteratorRecord be undefined.
  3. If usingIterator is not undefined, then
    1. Set iteratorRecord to ? GetIterator(O, async, usingIterator).
    2. If IsCallable(iteratorRecord.[[NextMethod]]) is false, throw a TypeError exception.
    3. Let hasInstance be ? OrdinaryHasInstance(%AsyncIterator%, iteratorRecord.[[Iterator]]).
    4. If hasInstance is true, then
      1. Return iteratorRecord.[[Iterator]].
  4. If iteratorRecord is undefined, then
    1. Set usingIterator to ? GetMethod(O, @@iterator).
    2. If usingIterator is not undefined, then
      1. Let syncIteratorRecord be ? GetIterator(O, sync, usingIterator).
      2. If IsCallable(syncIteratorRecord.[[NextMethod]]) is false, throw a TypeError exception.
      3. Set iteratorRecord to CreateAsyncFromSyncIterator(syncIteratorRecord).
  5. If iteratorRecord is undefined, set iteratorRecord to ? GetIteratorDirect(O).
  6. Let wrapper be OrdinaryObjectCreate(%WrapForValidAsyncIteratorPrototype%, « [[AsyncIterated]] »).
  7. Set wrapper.[[AsyncIterated]] to iteratorRecord.
  8. Return wrapper.

5.1.3.2.2.1 The %WrapForValidAsyncIteratorPrototype% Object

The %WrapForValidAsyncIteratorPrototype% object:

5.1.3.2.2.1.1 %WrapForValidAsyncIteratorPrototype%.next ( )

  1. Let O be this value.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. Let check be Completion(RequireInternalSlot(O, [[AsyncIterated]])).
  4. IfAbruptRejectPromise(check, promiseCapability).
  5. Let result be Completion(IteratorNext(O.[[AsyncIterated]])).
  6. IfAbruptRejectPromise(result, promiseCapability).
  7. Return ? PromiseResolve(%Promise%, result).

5.1.3.2.2.1.2 %WrapForValidAsyncIteratorPrototype%.return ( )

  1. Let O be this value.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. Let check be Completion(RequireInternalSlot(O, [[AsyncIterated]])).
  4. IfAbruptRejectPromise(check, promiseCapability).
  5. Let iterator be O.[[AsyncIterated]].[[Iterator]].
  6. Assert: iterator is an Object.
  7. Let returnMethod be Completion(GetMethod(iterator, "return")).
  8. IfAbruptRejectPromise(returnMethod, promiseCapability).
  9. If returnMethod is undefined, then
    1. Return ! PromiseResolve(%Promise%, CreateIterResultObject(undefined, true)).
  10. Let result be Completion(Call(returnMethod, iterator)).
  11. IfAbruptRejectPromise(result, promiseCapability).
  12. Return ? PromiseResolve(%Promise%, result).

5.1.4 Iterator Helper Objects

An Iterator Helper object is an ordinary object that represents a lazy transformation of some specific source iterator object. There is not a named constructor for Iterator Helper objects. Instead, Iterator Helper objects are created by calling certain methods of Iterator instance objects.

5.1.4.1 The %IteratorHelperPrototype% Object

The %IteratorHelperPrototype% object:

5.1.4.1.1 %IteratorHelperPrototype%.next ( )

  1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").

5.1.4.1.2 %IteratorHelperPrototype%.return ( )

  1. Let C be Completion { [[Type]]: return, [[Value]]: undefined, [[Target]]: empty }.
  2. Return ? GeneratorResumeAbrupt(this value, C, "Iterator Helper").

5.1.4.1.3 %IteratorHelperPrototype% [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Iterator Helper".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

5.1.5 Async Iterator Helper Objects

An Async Iterator Helper object is an ordinary object that represents a lazy transformation of some specific source async iterator object. There is not a named constructor for Async Iterator Helper objects. Instead, Async Iterator Helper objects are created by calling certain methods of AsyncIterator instance objects.

5.1.5.1 The %AsyncIteratorHelperPrototype% Object

The %AsyncIteratorHelperPrototype% object:

5.1.5.1.1 %AsyncIteratorHelperPrototype%.next ( )

  1. Return AsyncGeneratorNext(this value, "Async Iterator Helper", undefined).

5.1.5.1.2 %AsyncIteratorHelperPrototype%.return ( )

  1. Return AsyncGeneratorReturn(this value, "Async Iterator Helper", undefined).

5.1.5.1.3 %AsyncIteratorHelperPrototype% [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Async Iterator Helper".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

5.1.6 Iterator.prototype

The Iterator prototype object:

5.1.6.1 Iterator.prototype.constructor

The initial value of %Iterator.prototype%.constructor is %Iterator%.

5.1.6.2 Iterator.prototype.map ( mapper )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(mapper) is false, throw a TypeError exception.
  3. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
    1. Repeat,
      1. Let next be ? IteratorStep(iterated).
      2. If next is false, return undefined.
      3. Let value be ? IteratorValue(next).
      4. Let mapped be Completion(Call(mapper, undefined, « value »)).
      5. IfAbruptCloseIterator(mapped, iterated).
      6. Let completion be Completion(Yield(mapped)).
      7. IfAbruptCloseIterator(completion, iterated).
  4. Return CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%).

5.1.6.3 Iterator.prototype.filter ( filterer )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(filterer) is false, throw a TypeError exception.
  3. Let closure be a new Abstract Closure with no parameters that captures iterated and filterer and performs the following steps when called:
    1. Repeat,
      1. Let next be ? IteratorStep(iterated).
      2. If next is false, return undefined.
      3. Let value be ? IteratorValue(next).
      4. Let selected be Completion(Call(filterer, undefined, « value »)).
      5. IfAbruptCloseIterator(selected, iterated).
      6. If ToBoolean(selected) is true, then
        1. Let completion be Completion(Yield(value)).
        2. IfAbruptCloseIterator(completion, iterated).
  4. Return CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%).

5.1.6.4 Iterator.prototype.take ( limit )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. Let numLimit be ? ToNumber(limit).
  3. If numLimit is NaN, throw a RangeError exception.
  4. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
  5. If integerLimit < 0, throw a RangeError exception.
  6. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
    1. Let remaining be integerLimit.
    2. Repeat,
      1. If remaining is 0, then
        1. Return ? IteratorClose(iterated, NormalCompletion(undefined)).
      2. If remaining is not +∞, then
        1. Set remaining to remaining - 1.
      3. Let next be ? IteratorStep(iterated).
      4. If next is false, return undefined.
      5. Let completion be Completion(Yield(? IteratorValue(next))).
      6. IfAbruptCloseIterator(completion, iterated).
  7. Return CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%).

5.1.6.5 Iterator.prototype.drop ( limit )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. Let numLimit be ? ToNumber(limit).
  3. If numLimit is NaN, throw a RangeError exception.
  4. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
  5. If integerLimit < 0, throw a RangeError exception.
  6. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
    1. Let remaining be integerLimit.
    2. Repeat, while remaining > 0,
      1. If remaining is not +∞, then
        1. Set remaining to remaining - 1.
      2. Let next be ? IteratorStep(iterated).
      3. If next is false, return undefined.
    3. Repeat,
      1. Let next be ? IteratorStep(iterated).
      2. If next is false, return undefined.
      3. Let completion be Completion(Yield(? IteratorValue(next))).
      4. IfAbruptCloseIterator(completion, iterated).
  7. Return CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%).

5.1.6.6 Iterator.prototype.indexed ( )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. Let closure be a new Abstract Closure with no parameters that captures iterated and performs the following steps when called:
    1. Let index be 0.
    2. Repeat,
      1. Let next be ? IteratorStep(iterated).
      2. If next is false, return undefined.
      3. Let value be ? IteratorValue(next).
      4. Let pair be CreateArrayFromList𝔽(index), value »).
      5. Set index to index + 1.
      6. Let completion be Completion(Yield(pair)).
      7. IfAbruptCloseIterator(completion, iterated).
  3. Return CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%).

5.1.6.7 Iterator.prototype.flatMap ( mapper )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(mapper) is false, throw a TypeError exception.
  3. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
    1. Repeat,
      1. Let next be ? IteratorStep(iterated).
      2. If next is false, return undefined.
      3. Let value be ? IteratorValue(next).
      4. Let mapped be Completion(Call(mapper, undefined, « value »)).
      5. IfAbruptCloseIterator(mapped, iterated).
      6. Let innerIterator be Completion(GetIterator(mapped, sync)).
      7. IfAbruptCloseIterator(innerIterator, iterated).
      8. Let innerAlive be true.
      9. Repeat, while innerAlive is true,
        1. Let innerNext be Completion(IteratorStep(innerIterator)).
        2. IfAbruptCloseIterator(innerNext, iterated).
        3. If innerNext is false, then
          1. Set innerAlive to false.
        4. Else,
          1. Let innerValue be Completion(IteratorValue(innerNext)).
          2. IfAbruptCloseIterator(innerValue, iterated).
          3. Let completion be Completion(Yield(innerValue)).
          4. If completion is an abrupt completion, then
            1. Let backupCompletion be Completion(IteratorClose(innerIterator, completion)).
            2. IfAbruptCloseIterator(backupCompletion, iterated).
            3. Return ? IteratorClose(completion, iterated).
  4. Return CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%).

5.1.6.8 Iterator.prototype.reduce ( reducer [ , initialValue ] )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(reducer) is false, throw a TypeError exception.
  3. If initialValue is not present, then
    1. Let next be ? IteratorStep(iterated).
    2. If next is false, throw a TypeError exception.
    3. Let accumulator be ? IteratorValue(next).
  4. Else,
    1. Let accumulator be initialValue.
  5. Repeat,
    1. Let next be ? IteratorStep(iterated).
    2. If next is false, return accumulator.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(reducer, undefined, « accumulator, value »)).
    5. IfAbruptCloseIterator(result, iterated).
    6. Set accumulator to result.[[Value]].

5.1.6.9 Iterator.prototype.toArray ( )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. Let items be a new empty List.
  3. Repeat,
    1. Let next be ? IteratorStep(iterated).
    2. If next is false, return CreateArrayFromList(items).
    3. Let value be ? IteratorValue(next).
    4. Append value to items.

5.1.6.10 Iterator.prototype.toAsync ( )

This method performs the following steps when called:

  1. Let syncIteratorRecord be ? GetIteratorDirect(this value).
  2. Let asyncIteratorRecord be CreateAsyncFromSyncIterator(syncIteratorRecord).
  3. Let wrapper be OrdinaryObjectCreate(%WrapForValidAsyncIteratorPrototype%, « [[AsyncIterated]] »).
  4. Set wrapper.[[AsyncIterated]] to asyncIteratorRecord.
  5. Return wrapper.

5.1.6.11 Iterator.prototype.forEach ( fn )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(fn) is false, throw a TypeError exception.
  3. Repeat,
    1. Let next be ? IteratorStep(iterated).
    2. If next is false, return undefined.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(fn, undefined, « value »)).
    5. IfAbruptCloseIterator(result, iterated).

5.1.6.12 Iterator.prototype.some ( fn )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(fn) is false, throw a TypeError exception.
  3. Repeat,
    1. Let next be ? IteratorStep(iterated).
    2. If next is false, return false.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(fn, undefined, « value »)).
    5. IfAbruptCloseIterator(result, iterated).
    6. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(true)).

5.1.6.13 Iterator.prototype.every ( fn )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(fn) is false, throw a TypeError exception.
  3. Repeat,
    1. Let next be ? IteratorStep(iterated).
    2. If next is false, return true.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(fn, undefined, « value »)).
    5. IfAbruptCloseIterator(result, iterated).
    6. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).

5.1.6.14 Iterator.prototype.find ( fn )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(fn) is false, throw a TypeError exception.
  3. Repeat,
    1. Let next be ? IteratorStep(iterated).
    2. If next is false, return undefined.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(fn, undefined, « value »)).
    5. IfAbruptCloseIterator(result, iterated).
    6. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(value)).

5.1.6.15 Iterator.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Iterator".

Note

Unlike the @@toStringTag on most built-in classes, for web-compatibility reasons this property must be writable.

5.1.7 AsyncIterator.prototype

The AsyncIterator prototype object:

5.1.7.1 AsyncIterator.prototype.constructor

The initial value of AsyncIterator.prototype.constructor is %AsyncIterator%.

5.1.7.2 AsyncIterator.prototype.map ( mapper )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(mapper) is false, throw a TypeError exception.
  3. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
    1. Repeat,
      1. Let next be ? Await(? IteratorNext(iterated)).
      2. If ? IteratorComplete(next) is true, return undefined.
      3. Let value be ? IteratorValue(next).
      4. Let mapped be Completion(Call(mapper, undefined, « value »)).
      5. IfAbruptCloseAsyncIterator(mapped, iterated).
      6. Set mapped to Completion(Await(mapped)).
      7. IfAbruptCloseAsyncIterator(mapped, iterated).
      8. Let completion be Completion(Yield(mapped)).
      9. IfAbruptCloseAsyncIterator(completion, iterated).
  4. Return CreateAsyncIteratorFromClosure(closure, "Async Iterator Helper", %AsyncIteratorHelperPrototype%).

5.1.7.3 AsyncIterator.prototype.filter ( filterer )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(filterer) is false, throw a TypeError exception.
  3. Let closure be a new Abstract Closure with no parameters that captures iterated and filterer and performs the following steps when called:
    1. Repeat,
      1. Let next be ? Await(? IteratorNext(iterated)).
      2. If ? IteratorComplete(next) is true, return undefined.
      3. Let value be ? IteratorValue(next).
      4. Let selected be Completion(Call(filterer, undefined, « value »)).
      5. IfAbruptCloseAsyncIterator(selected, iterated).
      6. Set selected to Completion(Await(selected)).
      7. IfAbruptCloseAsyncIterator(selected, iterated).
      8. If ToBoolean(selected) is true, then
        1. Let completion be Completion(Yield(value)).
        2. IfAbruptCloseAsyncIterator(completion, iterated).
  4. Return CreateAsyncIteratorFromClosure(closure, "Async Iterator Helper", %AsyncIteratorHelperPrototype%).

5.1.7.4 AsyncIterator.prototype.take ( limit )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. Let numLimit be ? ToNumber(limit).
  3. If numLimit is NaN, throw a RangeError exception.
  4. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
  5. If integerLimit < 0, throw a RangeError exception.
  6. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
    1. Let remaining be integerLimit.
    2. Repeat,
      1. If remaining is 0, then
        1. Return ? AsyncIteratorClose(iterated, NormalCompletion(undefined)).
      2. If remaining is not +∞, then
        1. Set remaining to remaining - 1.
      3. Let next be ? Await(? IteratorNext(iterated)).
      4. If ? IteratorComplete(next) is true, return undefined.
      5. Let completion be Completion(Yield(? IteratorValue(next))).
      6. IfAbruptCloseAsyncIterator(completion, iterated).
  7. Return CreateAsyncIteratorFromClosure(closure, "Async Iterator Helper", %AsyncIteratorHelperPrototype%).

5.1.7.5 AsyncIterator.prototype.drop ( limit )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. Let numLimit be ? ToNumber(limit).
  3. If numLimit is NaN, throw a RangeError exception.
  4. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
  5. If integerLimit < 0, throw a RangeError exception.
  6. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
    1. Let remaining be integerLimit.
    2. Repeat, while remaining > 0,
      1. If remaining is not +∞, then
        1. Set remaining to remaining - 1.
      2. Let next be ? Await(? IteratorNext(iterated)).
      3. If ? IteratorComplete(next) is true, return undefined.
    3. Repeat,
      1. Let next be ? Await(? IteratorNext(iterated)).
      2. If ? IteratorComplete(next) is true, return undefined.
      3. Let completion be Completion(Yield(? IteratorValue(next))).
      4. IfAbruptCloseAsyncIterator(completion, iterated).
  7. Return CreateAsyncIteratorFromClosure(closure, "Async Iterator Helper", %AsyncIteratorHelperPrototype%).

5.1.7.6 AsyncIterator.prototype.indexed ( )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. Let closure be a new Abstract Closure with no parameters that captures iterated and performs the following steps when called:
    1. Let index be 0.
    2. Repeat,
      1. Let next be ? Await(? IteratorNext(iterated)).
      2. If ? IteratorComplete(next) is true, return undefined.
      3. Let value be ? IteratorValue(next).
      4. Let pair be CreateArrayFromListindex, value »).
      5. Set index to index + 1.
      6. Let completion be Completion(Yield(pair)).
      7. IfAbruptCloseAsyncIterator(completion, iterated).
  3. Return CreateAsyncIteratorFromClosure(closure, "Async Iterator Helper", %AsyncIteratorHelperPrototype%).

5.1.7.7 AsyncIterator.prototype.flatMap ( mapper )

This method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(mapper) is false, throw a TypeError exception.
  3. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
    1. Repeat,
      1. Let next be ? Await(? IteratorNext(iterated)).
      2. If ? IteratorComplete(next) is true, return undefined.
      3. Let value be ? IteratorValue(next).
      4. Let mapped be Completion(Call(mapper, undefined, « value »)).
      5. IfAbruptCloseAsyncIterator(mapped, iterated).
      6. Set mapped to Completion(Await(mapped)).
      7. IfAbruptCloseAsyncIterator(mapped, iterated).
      8. Let innerIterator be Completion(GetIterator(mapped, async)).
      9. IfAbruptCloseAsyncIterator(innerIterator, iterated).
      10. Let innerAlive be true.
      11. Repeat, while innerAlive is true,
        1. Let innerNextPromise be Completion(IteratorNext(innerIterator)).
        2. IfAbruptCloseAsyncIterator(innerNextPromise, iterated).
        3. Let innerNext be Completion(Await(innerNextPromise)).
        4. IfAbruptCloseAsyncIterator(innerNext, iterated).
        5. Let innerComplete be Completion(IteratorComplete(innerNext)).
        6. IfAbruptCloseAsyncIterator(innerComplete, iterated).
        7. If innerComplete is true, then
          1. Set innerAlive to false.
        8. Else,
          1. Let innerValue be Completion(IteratorValue(innerNext)).
          2. IfAbruptCloseAsyncIterator(innerValue, iterated).
          3. Let completion be Completion(Yield(innerValue)).
          4. If completion is a return completion, then
            1. Let backupCompletion be Completion(IteratorClose(innerIterator, completion)).
            2. IfAbruptCloseIterator(backupCompletion, iterated).
            3. Return ? IteratorClose(completion, iterated).
          5. Else if completion is a throw completion, then
            1. Assert: Awaiting innerValue during the Yield on step 3.a.xi.8.c threw.
            2. Return ? IteratorClose(completion, iterated).
  4. Return CreateAsyncIteratorFromClosure(closure, "Async Iterator Helper", %AsyncIteratorHelperPrototype%).

5.1.7.8 AsyncIterator.prototype.reduce ( reducer [ , initialValue ] )

This async method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(reducer) is false, throw a TypeError exception.
  3. If initialValue is not present, then
    1. Let next be ? Await(? IteratorNext(iterated)).
    2. If ? IteratorComplete(next) is true, throw a TypeError exception.
    3. Let accumulator be ? IteratorValue(next).
  4. Else,
    1. Let accumulator be initialValue.
  5. Repeat,
    1. Let next be ? Await(? IteratorNext(iterated)).
    2. If ? IteratorComplete(next) is true, return accumulator.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(reducer, undefined, « accumulator, value »)).
    5. IfAbruptCloseAsyncIterator(result, iterated).
    6. Set result to Await(result).
    7. IfAbruptCloseAsyncIterator(result, iterated).
    8. Set accumulator to result.

5.1.7.9 AsyncIterator.prototype.toArray ( )

This async method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. Let items be a new empty List.
  3. Repeat,
    1. Let next be ? Await(? IteratorNext(iterated)).
    2. If ? IteratorComplete(next) is true, return CreateArrayFromList(items).
    3. Let value be ? IteratorValue(next).
    4. Append value to items.

5.1.7.10 AsyncIterator.prototype.forEach ( fn )

This async method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(fn) is false, throw a TypeError exception.
  3. Repeat,
    1. Let next be ? Await(? IteratorNext(iterated)).
    2. If ? IteratorComplete(next) is true, return undefined.
    3. Let value be ? IteratorValue(next).
    4. Let r be Completion(Call(fn, undefined, « value »)).
    5. IfAbruptCloseAsyncIterator(r, iterated).
    6. Set r to Await(r).
    7. IfAbruptCloseAsyncIterator(r, iterated).

5.1.7.11 AsyncIterator.prototype.some ( fn )

This async method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(fn) is false, throw a TypeError exception.
  3. Repeat,
    1. Let next be ? Await(? IteratorNext(iterated)).
    2. If ? IteratorComplete(next) is true, return false.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(fn, undefined, « value »)).
    5. IfAbruptCloseAsyncIterator(result, iterated).
    6. Set result to Await(result).
    7. IfAbruptCloseAsyncIterator(result, iterated).
    8. If ToBoolean(result) is true, return ? AsyncIteratorClose(iterated, NormalCompletion(true)).

5.1.7.12 AsyncIterator.prototype.every ( fn )

This async method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(fn) is false, throw a TypeError exception.
  3. Repeat,
    1. Let next be ? Await(? IteratorNext(iterated)).
    2. If ? IteratorComplete(next) is true, return true.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(fn, undefined, « value »)).
    5. IfAbruptCloseAsyncIterator(result, iterated).
    6. Set result to Await(result).
    7. IfAbruptCloseAsyncIterator(result, iterated).
    8. If ToBoolean(result) is false, return ? AsyncIteratorClose(iterated, NormalCompletion(false)).

5.1.7.13 AsyncIterator.prototype.find ( fn )

This async method performs the following steps when called:

  1. Let iterated be ? GetIteratorDirect(this value).
  2. If IsCallable(fn) is false, throw a TypeError exception.
  3. Repeat,
    1. Let next be ? Await(? IteratorNext(iterated)).
    2. If ? IteratorComplete(next) is true, return undefined.
    3. Let value be ? IteratorValue(next).
    4. Let result be Completion(Call(fn, undefined, « value »)).
    5. IfAbruptCloseAsyncIterator(result, iterated).
    6. Set result to Await(result).
    7. IfAbruptCloseAsyncIterator(result, iterated).
    8. If ToBoolean(result) is true, return ? AsyncIteratorClose(iterated, NormalCompletion(value)).

5.1.7.14 AsyncIterator.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Async Iterator".

Note

Unlike the @@toStringTag on most built-in classes, for web-compatibility reasons this property must be writable.

5.2 AsyncFunction Objects

5.2.1 Async Functions Abstract Operations

5.2.1.1 AsyncFunctionStart ( promiseCapability, asyncFunctionBody )

The abstract operation AsyncFunctionStart takes arguments promiseCapability (a PromiseCapability Record) and asyncFunctionBody (a FunctionBody Parse Node or an ExpressionBody Parse Node or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:

  1. Let runningContext be the running execution context.
  2. Let asyncContext be a copy of runningContext.
  3. NOTE: Copying the execution state is required for AsyncBlockStart to resume its execution. It is ill-defined to resume a currently executing context.
  4. Perform AsyncBlockStart(promiseCapability, asyncFunctionBody, asyncContext).
  5. Return unused.

5.2.1.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext )

The abstract operation AsyncBlockStart takes arguments promiseCapability (a PromiseCapability Record), asyncBody (a Parse Node or an Abstract Closure with no parameters), and asyncContext (an execution context). It performs the following steps when called:

  1. Assert: promiseCapability is a PromiseCapability Record.
  2. Let runningContext be the running execution context.
  3. Set the code evaluation state of asyncContext such that when evaluation is resumed for that execution context the following steps will be performed:
    1. If asyncBody is a Parse Node, then
      1. Let result be the result of evaluating asyncBody.
    2. Else,
      1. Assert: asyncBody is an Abstract Closure with no parameters.
      2. Let result be asyncBody().
    3. Let result be the result of evaluating asyncBody.
    4. Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done.
    5. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
    6. If result.[[Type]] is normal, then
      1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
    7. Else if result.[[Type]] is return, then
      1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »).
    8. Else,
      1. Assert: result.[[Type]] is throw.
      2. Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
    9. Return.
  4. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
  5. Resume the suspended evaluation of asyncContext. Let result be the value returned by the resumed computation.
  6. Assert: When we return here, asyncContext has already been removed from the execution context stack and runningContext is the currently running execution context.
  7. Assert: result is a normal completion with a value of undefined. The possible sources of completion values are Await or, if the async function doesn't await anything, step 3.i above.
  8. Return.

6 New AsyncGenerator AOs

These factor out functionality from AsyncGenerator.prototype.next and AsyncGenerator.prototype.return and should be used in those methods when this proposal lands in the main specification.

6.1 AsyncGeneratorNext ( generator, brand, value )

The abstract operation AsyncGeneratorNext takes arguments generator, brand, and value (an ECMAScript language value) and returns an ECMAScript language value. It performs the following steps when called:

  1. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  2. Let result be Completion(AsyncGeneratorValidate(generator, brand)).
  3. IfAbruptRejectPromise(result, promiseCapability).
  4. Let state be generator.[[AsyncGeneratorState]].
  5. If state is completed, then
    1. Let iteratorResult be CreateIterResultObject(undefined, true).
    2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »).
    3. Return promiseCapability.[[Promise]].
  6. Let completion be NormalCompletion(value).
  7. Perform AsyncGeneratorEnqueue(generator, completion, promiseCapability).
  8. If state is either suspendedStart or suspendedYield, then
    1. Perform AsyncGeneratorResume(generator, completion).
  9. Else,
    1. Assert: state is either executing or awaiting-return.
  10. Return promiseCapability.[[Promise]].

6.2 AsyncGeneratorReturn ( generator, brand, value )

The abstract operation AsyncGeneratorReturn takes arguments generator, brand, and value (an ECMAScript language value) and returns an ECMAScript language value. It performs the following steps when called:

  1. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  2. Let result be Completion(AsyncGeneratorValidate(generator, brand)).
  3. IfAbruptRejectPromise(result, promiseCapability).
  4. Let completion be Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }.
  5. Perform AsyncGeneratorEnqueue(generator, completion, promiseCapability).
  6. Let state be generator.[[AsyncGeneratorState]].
  7. If state is either suspendedStart or completed, then
    1. Set generator.[[AsyncGeneratorState]] to awaiting-return.
    2. Perform ! AsyncGeneratorAwaitReturn(generator).
  8. Else if state is suspendedYield, then
    1. Perform AsyncGeneratorResume(generator, completion).
  9. Else,
    1. Assert: state is either executing or awaiting-return.
  10. Return promiseCapability.[[Promise]].