27.6 AsyncGenerator Objects

An AsyncGenerator object is an instance of an async generator function and conforms to both the AsyncIterator and AsyncIterable interfaces.

AsyncGenerator instances directly inherit properties from the object that is the initial value of the "prototype" property of the AsyncGenerator function that created the instance. AsyncGenerator instances indirectly inherit properties from the AsyncGenerator Prototype intrinsic, %AsyncGeneratorFunction.prototype.prototype%.

27.6.1 Properties of the AsyncGenerator Prototype Object

The AsyncGenerator prototype object:

  • is %AsyncGeneratorFunction.prototype.prototype%.
  • is an ordinary object.
  • is not an AsyncGenerator instance and does not have an [[AsyncGeneratorState]] internal slot.
  • has a [[Prototype]] internal slot whose value is %AsyncIteratorPrototype%.
  • has properties that are indirectly inherited by all AsyncGenerator instances.

27.6.1.1 AsyncGenerator.prototype.constructor

The initial value of AsyncGenerator.prototype.constructor is %AsyncGeneratorFunction.prototype%.

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

27.6.1.2 AsyncGenerator.prototype.next ( value )

  1. Let generator be the this value.
  2. Let completion be NormalCompletion(value).
  3. Return ! AsyncGeneratorEnqueue(generator, completion, empty).

27.6.1.3 AsyncGenerator.prototype.return ( value )

  1. Let generator be the this value.
  2. Let completion be Completion { [[Type]]: return, [[Value]]: value, [[Target]]: empty }.
  3. Return ! AsyncGeneratorEnqueue(generator, completion, empty).

27.6.1.4 AsyncGenerator.prototype.throw ( exception )

  1. Let generator be the this value.
  2. Let completion be ThrowCompletion(exception).
  3. Return ! AsyncGeneratorEnqueue(generator, completion, empty).

27.6.1.5 AsyncGenerator.prototype [ @@toStringTag ]

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

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

27.6.2 Properties of AsyncGenerator Instances

AsyncGenerator instances are initially created with the internal slots described below:

Table 74: Internal Slots of AsyncGenerator Instances
Internal Slot Description
[[AsyncGeneratorState]] The current execution state of the async generator. The possible values are: undefined, suspendedStart, suspendedYield, executing, awaiting-return, and completed.
[[AsyncGeneratorContext]] The execution context that is used when executing the code of this async generator.
[[AsyncGeneratorQueue]] A List of AsyncGeneratorRequest records which represent requests to resume the async generator.
[[GeneratorBrand]] A brand used to distinguish different kinds of async generators. The [[GeneratorBrand]] of async generators declared by ECMAScript source text is always empty.

27.6.3 AsyncGenerator Abstract Operations

27.6.3.1 AsyncGeneratorRequest Records

The AsyncGeneratorRequest is a Record value used to store information about how an async generator should be resumed and contains capabilities for fulfilling or rejecting the corresponding promise.

They have the following fields:

Table 75: AsyncGeneratorRequest Record Fields
Field Name Value Meaning
[[Completion]] A Completion record The completion which should be used to resume the async generator.
[[Capability]] A PromiseCapability Record The promise capabilities associated with this request.

27.6.3.2 AsyncGeneratorStart ( generator, generatorBody )

The abstract operation AsyncGeneratorStart takes arguments generator and generatorBody (a Parse Node or an Abstract Closure with no parameters). It performs the following steps when called:

  1. Assert: generator is an AsyncGenerator instance.
  2. Assert: generator.[[AsyncGeneratorState]] is undefined.
  3. Let genContext be the running execution context.
  4. Set the Generator component of genContext to generator.
  5. Set the code evaluation state of genContext such that when evaluation is resumed for that execution context the following steps will be performed:
    1. If generatorBody is a Parse Node, then
      1. Let result be the result of evaluating generatorBody.
    2. Else,
      1. Assert: generatorBody is an Abstract Closure with no parameters.
      2. Let result be generatorBody().
    3. Assert: If we return here, the async generator either threw an exception or performed either an implicit or explicit return.
    4. Remove genContext 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.
    5. Set generator.[[AsyncGeneratorState]] to completed.
    6. If result is a normal completion, let resultValue be undefined.
    7. Else,
      1. Let resultValue be result.[[Value]].
      2. If result.[[Type]] is not return, then
        1. Return ! AsyncGeneratorReject(generator, resultValue).
    8. Return ! AsyncGeneratorResolve(generator, resultValue, true).
  6. Set generator.[[AsyncGeneratorContext]] to genContext.
  7. Set generator.[[AsyncGeneratorState]] to suspendedStart.
  8. Set generator.[[AsyncGeneratorQueue]] to a new empty List.
  9. Return undefined.

27.6.3.3 AsyncGeneratorValidate ( generator, generatorBrand )

The abstract operation AsyncGeneratorValidate takes arguments generator and generatorBrand. It performs the following steps when called:

  1. Perform ? RequireInternalSlot(generator, [[AsyncGeneratorContext]]).
  2. Perform ? RequireInternalSlot(generator, [[AsyncGeneratorState]]).
  3. Perform ? RequireInternalSlot(generator, [[AsyncGeneratorQueue]]).
  4. If generator.[[GeneratorBrand]] is not the same value as generatorBrand, throw a TypeError exception.

27.6.3.4 AsyncGeneratorResolve ( generator, value, done )

The abstract operation AsyncGeneratorResolve takes arguments generator, value, and done (a Boolean). It performs the following steps when called:

  1. Assert: generator is an AsyncGenerator instance.
  2. Let queue be generator.[[AsyncGeneratorQueue]].
  3. Assert: queue is not an empty List.
  4. Let next be the first element of queue.
  5. Remove the first element from queue.
  6. Let promiseCapability be next.[[Capability]].
  7. Let iteratorResult be ! CreateIterResultObject(value, done).
  8. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »).
  9. Perform ! AsyncGeneratorResumeNext(generator).
  10. Return undefined.

27.6.3.5 AsyncGeneratorReject ( generator, exception )

The abstract operation AsyncGeneratorReject takes arguments generator and exception. It performs the following steps when called:

  1. Assert: generator is an AsyncGenerator instance.
  2. Let queue be generator.[[AsyncGeneratorQueue]].
  3. Assert: queue is not an empty List.
  4. Let next be the first element of queue.
  5. Remove the first element from queue.
  6. Let promiseCapability be next.[[Capability]].
  7. Perform ! Call(promiseCapability.[[Reject]], undefined, « exception »).
  8. Perform ! AsyncGeneratorResumeNext(generator).
  9. Return undefined.

27.6.3.6 AsyncGeneratorResumeNext ( generator )

The abstract operation AsyncGeneratorResumeNext takes argument generator. It performs the following steps when called:

  1. Assert: generator is an AsyncGenerator instance.
  2. Let state be generator.[[AsyncGeneratorState]].
  3. Assert: state is not executing.
  4. If state is awaiting-return, return undefined.
  5. Let queue be generator.[[AsyncGeneratorQueue]].
  6. If queue is an empty List, return undefined.
  7. Let next be the value of the first element of queue.
  8. Assert: next is an AsyncGeneratorRequest record.
  9. Let completion be next.[[Completion]].
  10. If completion is an abrupt completion, then
    1. If state is suspendedStart, then
      1. Set generator.[[AsyncGeneratorState]] to completed.
      2. Set state to completed.
    2. If state is completed, then
      1. If completion.[[Type]] is return, then
        1. Set generator.[[AsyncGeneratorState]] to awaiting-return.
        2. Let promise be ? PromiseResolve(%Promise%, completion.[[Value]]).
        3. Let stepsFulfilled be the algorithm steps defined in AsyncGeneratorResumeNext Return Processor Fulfilled Functions.
        4. Let lengthFulfilled be the number of non-optional parameters of the function definition in AsyncGeneratorResumeNext Return Processor Fulfilled Functions.
        5. Let onFulfilled be ! CreateBuiltinFunction(stepsFulfilled, lengthFulfilled, "", « [[Generator]] »).
        6. Set onFulfilled.[[Generator]] to generator.
        7. Let stepsRejected be the algorithm steps defined in AsyncGeneratorResumeNext Return Processor Rejected Functions.
        8. Let lengthRejected be the number of non-optional parameters of the function definition in AsyncGeneratorResumeNext Return Processor Rejected Functions.
        9. Let onRejected be ! CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[Generator]] »).
        10. Set onRejected.[[Generator]] to generator.
        11. Perform ! PerformPromiseThen(promise, onFulfilled, onRejected).
        12. Return undefined.
      2. Else,
        1. Assert: completion.[[Type]] is throw.
        2. Perform ! AsyncGeneratorReject(generator, completion.[[Value]]).
        3. Return undefined.
  11. Else if state is completed, return ! AsyncGeneratorResolve(generator, undefined, true).
  12. Assert: state is either suspendedStart or suspendedYield.
  13. Let genContext be generator.[[AsyncGeneratorContext]].
  14. Let callerContext be the running execution context.
  15. Suspend callerContext.
  16. Set generator.[[AsyncGeneratorState]] to executing.
  17. Push genContext onto the execution context stack; genContext is now the running execution context.
  18. Resume the suspended evaluation of genContext using completion as the result of the operation that suspended it. Let result be the completion record returned by the resumed computation.
  19. Assert: result is never an abrupt completion.
  20. Assert: When we return here, genContext has already been removed from the execution context stack and callerContext is the currently running execution context.
  21. Return undefined.

27.6.3.6.1 AsyncGeneratorResumeNext Return Processor Fulfilled Functions

An AsyncGeneratorResumeNext return processor fulfilled function is an anonymous built-in function that is used as part of the AsyncGeneratorResumeNext specification device to unwrap promises passed in to the AsyncGenerator.prototype.return ( value ) method. Each AsyncGeneratorResumeNext return processor fulfilled function has a [[Generator]] internal slot.

When an AsyncGeneratorResumeNext return processor fulfilled function is called with argument value, the following steps are taken:

  1. Let F be the active function object.
  2. Set F.[[Generator]].[[AsyncGeneratorState]] to completed.
  3. Return ! AsyncGeneratorResolve(F.[[Generator]], value, true).

The "length" property of an AsyncGeneratorResumeNext return processor fulfilled function is 1𝔽.

27.6.3.6.2 AsyncGeneratorResumeNext Return Processor Rejected Functions

An AsyncGeneratorResumeNext return processor rejected function is an anonymous built-in function that is used as part of the AsyncGeneratorResumeNext specification device to unwrap promises passed in to the AsyncGenerator.prototype.return ( value ) method. Each AsyncGeneratorResumeNext return processor rejected function has a [[Generator]] internal slot.

When an AsyncGeneratorResumeNext return processor rejected function is called with argument reason, the following steps are taken:

  1. Let F be the active function object.
  2. Set F.[[Generator]].[[AsyncGeneratorState]] to completed.
  3. Return ! AsyncGeneratorReject(F.[[Generator]], reason).

The "length" property of an AsyncGeneratorResumeNext return processor rejected function is 1𝔽.

27.6.3.7 AsyncGeneratorEnqueue ( generator, completion, generatorBrand )

The abstract operation AsyncGeneratorEnqueue takes arguments generator, completion (a Completion Record), and generatorBrand. It performs the following steps when called:

  1. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  2. Let check be AsyncGeneratorValidate(generator, generatorBrand).
  3. If check is an abrupt completion, then
    1. Let badGeneratorError be a newly created TypeError object.
    2. Perform ! Call(promiseCapability.[[Reject]], undefined, « badGeneratorError »).
    3. Return promiseCapability.[[Promise]].
  4. Let queue be generator.[[AsyncGeneratorQueue]].
  5. Let request be AsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }.
  6. Append request to the end of queue.
  7. Let state be generator.[[AsyncGeneratorState]].
  8. If state is not executing, then
    1. Perform ! AsyncGeneratorResumeNext(generator).
  9. Return promiseCapability.[[Promise]].

27.6.3.8 AsyncGeneratorYield ( value )

The abstract operation AsyncGeneratorYield takes argument value. It performs the following steps when called:

  1. Let genContext be the running execution context.
  2. Assert: genContext is the execution context of a generator.
  3. Let generator be the value of the Generator component of genContext.
  4. Assert: GetGeneratorKind() is async.
  5. Set value to ? Await(value).
  6. Set generator.[[AsyncGeneratorState]] to suspendedYield.
  7. Remove genContext 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.
  8. Set the code evaluation state of genContext such that when evaluation is resumed with a Completion resumptionValue the following steps will be performed:
    1. If resumptionValue.[[Type]] is not return, return Completion(resumptionValue).
    2. Let awaited be Await(resumptionValue.[[Value]]).
    3. If awaited.[[Type]] is throw, return Completion(awaited).
    4. Assert: awaited.[[Type]] is normal.
    5. Return Completion { [[Type]]: return, [[Value]]: awaited.[[Value]], [[Target]]: empty }.
    6. NOTE: When one of the above steps returns, it returns to the evaluation of the YieldExpression production that originally called this abstract operation.
  9. Return ! AsyncGeneratorResolve(generator, value, false).
  10. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of genContext.

27.6.3.9 CreateAsyncIteratorFromClosure ( closure, generatorBrand, generatorPrototype )

The abstract operation CreateAsyncIteratorFromClosure takes arguments closure (an Abstract Closure with no parameters), generatorBrand, and generatorPrototype (an Object). It performs the following steps when called:

  1. NOTE: closure can contain uses of the Await shorthand and uses of the Yield shorthand to yield an IteratorResult object.
  2. Let internalSlotsList be « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]], [[GeneratorBrand]] ».
  3. Let generator be ! OrdinaryObjectCreate(generatorPrototype, internalSlotsList).
  4. Set generator.[[GeneratorBrand]] to generatorBrand.
  5. Set generator.[[AsyncGeneratorState]] to undefined.
  6. Perform ! AsyncGeneratorStart(generator, closure).
  7. Return generator.