├── .gitignore ├── deploy_key.enc ├── .editorconfig ├── .travis.yml ├── spec ├── properties-of-symbol-patch.html ├── introduction.html ├── method-definitions-patch.html ├── well-known-symbols-patch.html ├── es-function-objects-patch.html ├── return-statement-patch.html ├── well-known-intrinsics-patch.html ├── generator-abstract-ops-patch.html ├── iterator-operations.html ├── misc-patches.html ├── async-generator-objects.html ├── completion-records-patch.html ├── generator-definitions-patch.html ├── create-dynamic-function-patch.html ├── index.html ├── async-generator-function-objects.html ├── abstract-operations.html ├── definitions.html ├── iteration.html └── iteration-statements-patch.html ├── package.json ├── LICENSE.txt ├── deploy.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /out/ 3 | /npm-debug.log 4 | 5 | deploy_key 6 | -------------------------------------------------------------------------------- /deploy_key.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc39/proposal-async-iteration/HEAD/deploy_key.enc -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | indent_style = space 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | script: 5 | - bash ./deploy.sh 6 | env: 7 | global: 8 | - ENCRYPTION_LABEL: "a99c6f361492" 9 | - COMMIT_AUTHOR_EMAIL: "d@domenic.me" 10 | -------------------------------------------------------------------------------- /spec/properties-of-symbol-patch.html: -------------------------------------------------------------------------------- 1 | 2 |

Symbol.asyncIterator

3 |

The initial value of `Symbol.asyncIterator` is the well known symbol @@asyncIterator ().

4 |

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

5 |
6 | -------------------------------------------------------------------------------- /spec/introduction.html: -------------------------------------------------------------------------------- 1 |

This proposal adds syntactic support for asynchronous iteration using the AsyncIterable and AsyncIterator protocols. It introduces a new IterationStatement, `for`-`await`-`of`, and adds syntax for creating async generator functions and methods.

2 | 3 |

See the proposal repository for background material and discussion.

4 | 5 | 6 |

This proposal depends upon the async functions proposal.

7 |
8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "proposal-async-iteration", 4 | "description": "Async iteration proposal for JavaScript (build setup only)", 5 | "license": "MIT", 6 | "repository": "tc39/proposal-async-iteration", 7 | "scripts": { 8 | "spec": "ecmarkup spec/index.html out/index.html --js out/ecmarkup.js --css out/ecmarkup.css", 9 | "watch": "ecmarkup --watch spec/index.html out/index.html --js out/ecmarkup.js --css out/ecmarkup.css" 10 | }, 11 | "devDependencies": { 12 | "ecmarkup": "^3.11.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /spec/method-definitions-patch.html: -------------------------------------------------------------------------------- 1 | 2 |

Static Semantics: SpecialMethod

3 | MethodDefinition : PropertyName `(` UniqueFormalParameters `)` `{` FunctionBody `}` 4 | 5 | 1. Return *false*. 6 | 7 | 8 | MethodDefinition : 9 | GeneratorMethod 10 | AsyncGeneratorMethod 11 | `get` PropertyName `(` `)` `{` FunctionBody `}` 12 | `set` PropertyName `(` PropertySetParameterList `)` `{` FunctionBody `}` 13 | 14 | 15 | 1. Return *true*. 16 | 17 |
18 | -------------------------------------------------------------------------------- /spec/well-known-symbols-patch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 11 | 14 | 15 | 16 | 17 | 20 | 23 | 26 | 27 | 28 |
6 | Specification Name 7 | 9 | [[Description]] 10 | 12 | Value and Purpose 13 |
18 | @@asyncIterator 19 | 21 | `"Symbol.asyncIterator"` 22 | 24 | A method that returns the default AsyncIterator for an object. Called by the semantics of the `for`-`await`-`of` statement. 25 |
29 |
30 | -------------------------------------------------------------------------------- /spec/es-function-objects-patch.html: -------------------------------------------------------------------------------- 1 | 2 |

AsyncGeneratorFunctionCreate (_kind_, _ParameterList_, _Body_, _Scope_, _Strict_)

3 |

The abstract operation AsyncGeneratorFunctionCreate requires the arguments: _kind_ which is one of (~Normal~, ~Method~), a parameter list production specified by _ParameterList_, a body production specified by _Body_, a Lexical Environment specified by _Scope_, and a Boolean flag _Strict_. AsyncGeneratorFunctionCreate performs the following steps:

4 | 5 | 1. Let _functionPrototype_ be the intrinsic object %AsyncGenerator%. 6 | 1. Let _F_ be ! FunctionAllocate(_functionPrototype_, _Strict_, `"generator"`). 7 | 1. Return ! FunctionInitialize(_F_, _kind_, _ParameterList_, _Body_, _Scope_). 8 | 9 |
10 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright © 2015–2016 Kevin Smith and Domenic Denicola 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /spec/return-statement-patch.html: -------------------------------------------------------------------------------- 1 |

Syntax

2 | 3 | ReturnStatement[Yield, Await] : 4 | `return` `;` 5 | `return` [no LineTerminator here] Expression[+In, ?Yield, ?Await] `;` 6 | 7 | 8 |

A `return` statement causes a function to cease execution and return a value to the caller. If |Expression| is omitted, the return value is *undefined*. Otherwise, the return value is the value of |Expression|.

9 |
10 | 11 | 12 | 13 |

Runtime Semantics: Evaluation

14 | ReturnStatement : `return` `;` 15 | 16 | 1. Return Completion{[[Type]]: ~return~, [[Value]]: *undefined*, [[Target]]: ~empty~}. 17 | 18 | ReturnStatement : `return` Expression `;` 19 | 20 | 1. Let _exprRef_ be the result of evaluating |Expression|. 21 | 1. Let _exprValue_ be ? GetValue(_exprRef_). 22 | 1. If ! GetGeneratorKind() is ~async~, set _exprValue_ to ? Await(_exprValue_). 23 | 1. Return Completion{[[Type]]: ~return~, [[Value]]: _exprValue_, [[Target]]: ~empty~}. 24 | 25 |
26 | -------------------------------------------------------------------------------- /spec/well-known-intrinsics-patch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 11 | 14 | 15 | 16 | 19 | 22 | 25 | 26 | 27 | 30 | 33 | 36 | 37 | 38 | 41 | 44 | 47 | 48 | 49 | 52 | 54 | 57 | 58 | 59 | 62 | 64 | 67 | 68 | 69 |
6 | Intrinsic Name 7 | 9 | Global Name 10 | 12 | ECMAScript Language Association 13 |
17 | %AsyncGenerator% 18 | 20 | 21 | 23 | The initial value of the `prototype` property of %AsyncGeneratorFunction% 24 |
28 | %AsyncGeneratorFunction% 29 | 31 | 32 | 34 | The constructor of async iterator objects () 35 |
39 | %AsyncGeneratorPrototype% 40 | 42 | 43 | 45 | The initial value of the `prototype` property of %AsyncGenerator% 46 |
50 | %AsyncIteratorPrototype% 51 | 53 | 55 | An object that all standard built-in async iterator objects indirectly inherit from 56 |
60 | %AsyncFromSyncIteratorPrototype% 61 | 63 | 65 | The prototype of async-from-sync iterator objects () 66 |
70 | -------------------------------------------------------------------------------- /spec/generator-abstract-ops-patch.html: -------------------------------------------------------------------------------- 1 | 2 |

GetGeneratorKind ( )

3 | 4 | 1. Let _genContext_ be the running execution context. 5 | 1. If _genContext_ does not have a Generator component, return ~non-generator~. 6 | 1. Let _generator_ be the Generator component of _genContext_. 7 | 1. If _generator_ has an [[AsyncGeneratorState]] internal slot, return ~async~. 8 | 1. Else, return ~normal~. 9 | 10 |
11 | 12 | 13 |

GeneratorYield ( _iterNextObj_ )

14 |

The abstract operation GeneratorYield with argument _iterNextObj_ performs the following steps:

15 | 16 | 1. Assert: _iterNextObj_ is an Object that implements the IteratorResult interface. 17 | 1. Let _genContext_ be the running execution context. 18 | 1. Assert: _genContext_ is the execution context of a generator. 19 | 1. Let _generator_ be the value of the Generator component of _genContext_. 20 | 1. Assert: GetGeneratorKind() is ~normal~. 21 | 1. Set _generator_.[[GeneratorState]] to `"suspendedYield"`. 22 | 1. 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. 23 | 1. Set the code evaluation state of _genContext_ such that when evaluation is resumed with a Completion _resumptionValue_ the following steps will be performed: 24 | 1. Return _resumptionValue_. 25 | 1. NOTE: This returns to the evaluation of the |YieldExpression| that originally called this abstract operation. 26 | 1. Return NormalCompletion(_iterNextObj_). 27 | 1. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of _genContext_. 28 | 29 |
30 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e # Exit with nonzero exit code if anything fails 3 | 4 | SOURCE_BRANCH="master" 5 | TARGET_BRANCH="gh-pages" 6 | 7 | function doCompile { 8 | npm run spec 9 | } 10 | 11 | # Pull requests and commits to other branches shouldn't try to deploy, just build to verify 12 | if [[ "$TRAVIS_PULL_REQUEST" != "false" || "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]]; then 13 | echo "Skipping deploy; just doing a build." 14 | doCompile 15 | exit 0 16 | fi 17 | 18 | # Save some useful information 19 | REPO=`git config remote.origin.url` 20 | SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:} 21 | SHA=`git rev-parse --verify HEAD` 22 | 23 | # Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc 24 | ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key" 25 | ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv" 26 | ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR} 27 | ENCRYPTED_IV=${!ENCRYPTED_IV_VAR} 28 | openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy_key.enc -out deploy_key -d 29 | chmod 600 deploy_key 30 | eval `ssh-agent -s` 31 | ssh-add deploy_key 32 | 33 | # Clone the existing gh-pages for this repo into out/ 34 | # Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply) 35 | git clone $REPO out 36 | cd out 37 | git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH 38 | 39 | # Clean out existing contents 40 | git reset --hard 41 | 42 | # Run our compile script 43 | cd .. 44 | doCompile 45 | 46 | # Now let's go have some fun with the cloned repo 47 | cd out 48 | git config user.name "Travis CI" 49 | git config user.email "$COMMIT_AUTHOR_EMAIL" 50 | 51 | # If there are no changes to the compiled out (e.g. this is a README update) then just bail. 52 | if [[ -z "$(git status --porcelain)" ]]; then 53 | echo "No changes to the output on this push; exiting." 54 | exit 0 55 | fi 56 | 57 | # Commit the "changes", i.e. the new version. 58 | # The delta will show diffs between new and old versions. 59 | git add --all . 60 | git commit -m "Deploy to GitHub Pages: ${SHA}" 61 | 62 | # Now that we're all set up, we can push. 63 | git push $SSH_REPO $TARGET_BRANCH 64 | -------------------------------------------------------------------------------- /spec/iterator-operations.html: -------------------------------------------------------------------------------- 1 | 2 |

GetIterator ( _obj_ [ , _hint_ ][ , _method_ ] )

3 | 4 |

This abstract operation has been modified to accept an optional parameter _hint_ which indicates whether we should attempt to find an async iterator for the object. Existing call sites which use the optional _method_ parameter (`Array.from` and IterableToArrayLike) must be updated to pass the ~normal~ hint.

5 |
6 |

The abstract operation GetIterator with argument _obj_ and optional arguments _hint_ and _method_ performs the following steps:

7 | 8 | 1. If _hint_ was not passed, let _hint_ be ~normal~. 9 | 1. If _method_ is not present, then 10 | 1. Set _method_ to ? GetMethod(_obj_, @@iterator). 11 | 1. If _hint_ is ~async~, 12 | 1. Set _method_ to ? GetMethod(_obj_, @@asyncIterator). 13 | 1. If _method_ is *undefined*, 14 | 1. Let _syncMethod_ be ? GetMethod(_obj_, @@iterator). 15 | 1. Let _syncIteratorRecord_ be ? GetIterator(_obj_, ~normal~, _syncMethod_). 16 | 1. Return ? CreateAsyncFromSyncIterator(_syncIteratorRecord_). 17 | 1. Otherwise, set _method_ to ? GetMethod(_obj_, @@iterator). 18 | 1. Let _iterator_ be ? Call(_method_, _obj_). 19 | 1. If Type(_iterator_) is not Object, throw a *TypeError* exception. 20 | 1. Let _nextMethod_ be ? GetV(_iterator_, `"next"`). 21 | 1. Let _iteratorRecord_ be Record {[[Iterator]]: _iterator_, [[NextMethod]]: _nextMethod_, [[Done]]: *false*}. 22 | 1. Return _iteratorRecord_. 23 | 24 |
25 | 26 | 27 |

AsyncIteratorClose ( _iteratorRecord_, _completion_ )

28 |

The abstract operation AsyncIteratorClose with arguments _iteratorRecord_ and _completion_ is used to notify an async iterator that it should perform any actions it would normally perform when it has reached its completed state:

29 | 30 | 1. Assert: Type(_iteratorRecord_.[[Iterator]]) is Object. 31 | 1. Assert: _completion_ is a Completion Record. 32 | 1. Let _iterator_ be _iteratorRecord_.[[Iterator]]. 33 | 1. Let _return_ be ? GetMethod(_iterator_, `"return"`). 34 | 1. If _return_ is *undefined*, return Completion(_completion_). 35 | 1. Let _innerResult_ be Call(_return_, _iterator_, « »). 36 | 1. If _innerResult_.[[Type]] is ~normal~, set _innerResult_ to Await(_innerResult_.[[Value]]). 37 | 1. If _completion_.[[Type]] is ~throw~, return Completion(_completion_). 38 | 1. If _innerResult_.[[Type]] is ~throw~, return Completion(_innerResult_). 39 | 1. If Type(_innerResult_.[[Value]]) is not Object, throw a *TypeError* exception. 40 | 1. Return Completion(_completion_). 41 | 42 |
43 | -------------------------------------------------------------------------------- /spec/misc-patches.html: -------------------------------------------------------------------------------- 1 |

The specification contains many locations which mention generators that also should be updated to mention async generators. The ones with significant normative impact have been patched above. Here we attempt to enumerate all other places that will need minor updates.

2 | 3 | 25 | -------------------------------------------------------------------------------- /spec/async-generator-objects.html: -------------------------------------------------------------------------------- 1 |

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

2 | 3 |

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

4 | 5 | 6 |

Properties of AsyncGenerator Prototype

7 |

The AsyncGenerator prototype object is the %AsyncGeneratorPrototype% intrinsic. It is also the initial value of the `prototype` property of the %AsyncGenerator% intrinsic (the AsyncGeneratorFunction.prototype).

8 |

The AsyncGenerator prototype is an ordinary object. It is not an AsyncGenerator instance and does not have an [[AsyncGeneratorState]] internal slot.

9 |

The value of the [[Prototype]] internal slot of the AsyncGenerator prototype object is the intrinsic object %AsyncIteratorPrototype%. The initial value of the [[Extensible]] internal slot of the AsyncGenerator prototype object is *true*.

10 |

All AsyncGenerator instances indirectly inherit properties of the AsyncGenerator prototype object.

11 | 12 | 13 |

AsyncGenerator.prototype.constructor

14 |

The initial value of `AsyncGenerator.prototype.constructor` is the intrinsic object %AsyncGenerator%.

15 |

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

16 |
17 | 18 | 19 |

AsyncGenerator.prototype.next ( _value_ )

20 | 21 | 1. Let _generator_ be the `this` value. 22 | 1. Let _completion_ be NormalCompletion(_value_). 23 | 1. Return ! AsyncGeneratorEnqueue(_generator_, _completion_). 24 | 25 |
26 | 27 | 28 |

AsyncGenerator.prototype.return ( _value_ )

29 | 30 | 1. Let _generator_ be the `this` value. 31 | 1. Let _completion_ be Completion{[[Type]]: ~return~, [[Value]]: _value_, [[Target]]: ~empty~}. 32 | 1. Return ! AsyncGeneratorEnqueue(_generator_, _completion_). 33 | 34 |
35 | 36 | 37 |

AsyncGenerator.prototype.throw ( _exception_ )

38 | 39 | 1. Let _generator_ be the `this` value. 40 | 1. Let _completion_ be Completion{[[Type]]: ~throw~, [[Value]]: _exception_, [[Target]]: ~empty~}. 41 | 1. Return ! AsyncGeneratorEnqueue(_generator_, _completion_). 42 | 43 |
44 | 45 | 46 |

AsyncGenerator.prototype [ @@toStringTag ]

47 |

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

48 |

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

49 |
50 | 51 |
52 | 53 | 54 |

Properties of AsyncGenerator Instances

55 |

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

56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 |
Internal SlotDescription
[[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.
77 |
78 |
79 | 80 | 81 |

AsyncGenerator Abstract Operations

82 | 83 |
84 | -------------------------------------------------------------------------------- /spec/completion-records-patch.html: -------------------------------------------------------------------------------- 1 | 2 |

Await

3 | 4 | 5 |

The AsyncFunctionAwait abstract operation could probably be refactored in terms of this primitive.

6 |
7 | 8 |

Algorithm steps that say

9 | 10 | 11 | 1. Let _completion_ be Await(_promise_). 12 | 13 | 14 |

mean the same thing as:

15 | 16 | 17 | 1. Let _asyncContext_ be the running execution context. 18 | 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). 19 | 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _promise_ »). 20 | 1. Let _onFulfilled_ be a new built-in function object as defined in . 21 | 1. Let _onRejected_ be a new built-in function object as defined in . 22 | 1. Set _onFulfilled_ and _onRejected_'s [[AsyncContext]] internal slots to _asyncContext_. 23 | 1. Let _throwawayCapability_ be NewPromiseCapability(%Promise%). 24 | 1. Set _throwawayCapability_.[[Promise]].[[PromiseIsHandled]] to *true*. 25 | 1. Perform ! PerformPromiseThen(_promiseCapability_.[[Promise]], _onFulfilled_, _onRejected_, _throwawayCapability_). 26 | 1. 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. 27 | 1. Set the code evaluation state of _asyncContext_ such that when evaluation is resumed with a Completion _completion_, the following steps of the algorithm that invoked Await will be performed, with _completion_ available. 28 | 29 | 30 |

where all variables in the above steps, with the exception of _completion_, are ephemeral and visible only in the steps pertaining to Await.

31 | 32 | 33 |

Await can be combined with the `?` and `!` prefixes, so that for example

34 | 35 | 36 | 1. Let _value_ be ? Await(_promise_). 37 | 38 | 39 |

means the same thing as:

40 | 41 | 42 | 1. Let _value_ be Await(_promise_). 43 | 1. ReturnIfAbrupt(_value_). 44 | 45 |
46 | 47 | 48 |

Await Fulfilled Functions

49 | 50 |

An Await fulfilled function is an anonymous built-in function that is used as part of the Await specification device to deliver the promise fulfillment value to the caller as a normal completion. Each Await fulfilled function has an [[AsyncContext]] internal slot.

51 | 52 |

When an Await fulfilled function _F_ is called with argument _value_, the following steps are taken:

53 | 54 | 55 | 1. Let _asyncContext_ be _F_.[[AsyncContext]]. 56 | 1. Let _prevContext_ be the running execution context. 57 | 1. Suspend _prevContext_. 58 | 1. Push _asyncContext_ onto the execution context stack; _asyncContext_ is now the running execution context. 59 | 1. Resume the suspended evaluation of _asyncContext_ using NormalCompletion(_value_) as the result of the operation that suspended it. 60 | 1. Assert: When we reach this step, _asyncContext_ has already been removed from the execution context stack and _prevContext_ is the currently running execution context. 61 | 1. Return *undefined*. 62 | 63 | 64 |

The `length` property of an Await fulfilled function is 1.

65 |
66 | 67 | 68 |

Await Rejected Functions

69 | 70 |

An Await rejected function is an anonymous built-in function that is used as part of the Await specification device to deliver the promise rejection reason to the caller as an abrupt throw completion. Each Await rejected function has an [[AsyncContext]] internal slot.

71 | 72 |

When an Await rejected function _F_ is called with argument _reason_, the following steps are taken:

73 | 74 | 75 | 1. Let _asyncContext_ be _F_.[[AsyncContext]]. 76 | 1. Let _prevContext_ be the running execution context. 77 | 1. Suspend _prevContext_. 78 | 1. Push _asyncContext_ onto the execution context stack; _asyncContext_ is now the running execution context. 79 | 1. Resume the suspended evaluation of _asyncContext_ using Completion{[[Type]]: ~throw~, [[Value]]: _reason_, [[Target]]: ~empty~} as the result of the operation that suspended it. 80 | 1. Assert: When we reach this step, _asyncContext_ has already been removed from the execution context stack and _prevContext_ is the currently running execution context. 81 | 1. Return *undefined*. 82 | 83 | 84 |

The `length` property of an Await rejected function is 1.

85 |
86 |
87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Asynchronous Iterators for JavaScript 2 | 3 | ## Overview and motivation 4 | 5 | The iterator interface (introduced in ECMAScript 2015) is a sequential data access protocol which enables the development of generic and composable data consumers and transformers. Their primary interface is a `next()` method which returns a `{ value, done }` tuple, where `done` is a boolean indicating whether the end of the iterator has been reached, and `value` is the yielded value in the sequence. 6 | 7 | Since both the next value in the sequence and the "done" state of the data source must be known at the time that the iterator method returns, iterators are only suitable for representing *synchronous* data sources. While many data sources encountered by the JavaScript programmer are synchronous (such as in-memory lists and other data structures), many others are not. For instance, any data source which requires I/O access will be typically represented using an event-based or streaming *asynchronous* API. Unfortunately, iterators cannot be used to represent such data sources. 8 | 9 | (Even an iterator of promises is not sufficient, since that only allows asynchronous determination of the value, but requires synchronous determination of the "done" state.) 10 | 11 | In order to provide a generic data access protocol for asynchronous data sources, we introduce the **AsyncIterator** interface, an asynchronous iteration statement (`for`-`await`-`of`), and async generator functions. 12 | 13 | ## Async iterators and async iterables 14 | 15 | An async iterator is much like an iterator, except that its `next()` method returns a promise for a `{ value, done }` pair. As noted above, we must return a promise for the iterator result pair because both the next value and the "done" state of the iterator are potentially unknown at the time the iterator method returns. 16 | 17 | ```js 18 | const { value, done } = syncIterator.next(); 19 | 20 | asyncIterator.next().then(({ value, done }) => /* ... */); 21 | ``` 22 | 23 | Furthermore, we introduce a new symbol used for obtaining an async iterator from a given object, `Symbol.asyncIterator`. This allows arbitrary objects to advertise that they are _async iterables_, similar to how `Symbol.iterator` allows you to advertise being a normal, synchronous iterable. An example of a class that might use this is a [readable stream](https://streams.spec.whatwg.org/#rs-class). 24 | 25 | Implicit in the concept of the async iterator is the concept of a **request queue**. Since iterator methods may be called many times before the result of a prior request is resolved, each method call must be queued internally until all previous request operations have completed. 26 | 27 | ## The async iteration statement: `for`-`await`-`of` 28 | 29 | We introduce a variation of the `for-of` iteration statement which iterates over async iterable objects. An example usage would be: 30 | 31 | ```js 32 | for await (const line of readLines(filePath)) { 33 | console.log(line); 34 | } 35 | ``` 36 | 37 | Async for-of statements are only allowed within async functions and async generator functions (see below for the latter). 38 | 39 | During execution, an async iterator is created from the data source using the `[Symbol.asyncIterator]()` method. 40 | 41 | Each time we access the next value in the sequence, we implicitly `await` the promise returned from the iterator method. 42 | 43 | ## Async generator functions 44 | 45 | Async generator functions are similar to generator functions, with the following differences: 46 | 47 | - When called, async generator functions return an object, an _async generator_ whose methods (`next`, `throw`, and `return`) return promises for `{ value, done }`, instead of directly returning `{ value, done }`. This automatically makes the returned async generator objects _async iterators_. 48 | - `await` expressions and `for`-`await`-`of` statements are allowed. 49 | - The behavior of `yield*` is modified to support delegation to async iterables. 50 | 51 | For example: 52 | 53 | ```js 54 | async function* readLines(path) { 55 | let file = await fileOpen(path); 56 | 57 | try { 58 | while (!file.EOF) { 59 | yield await file.readLine(); 60 | } 61 | } finally { 62 | await file.close(); 63 | } 64 | } 65 | ``` 66 | 67 | This function then returns an async generator object, which can be consumed with `for`-`await`-`of` as shown in the previous example. 68 | 69 | ## Implementation Status 70 | 71 | ### Native implementations 72 | 73 | - Chakra: [outstanding issue](https://github.com/Microsoft/ChakraCore/issues/2720) 74 | - JavaScriptCore: [shipping in Safari Tech Preview 40](https://github.com/tc39/proposal-async-iteration/issues/63#issuecomment-330929480) 75 | - SpiderMonkey: [shipping in Firefox 57](https://github.com/tc39/proposal-async-iteration/issues/63#issuecomment-330978069); [launch bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1352312) 76 | - V8: [shipping in Chrome 63](https://blog.chromium.org/2017/10/chrome-63-beta-dynamic-module-imports_27.html); [launch bug](https://crbug.com/v8/5855) 77 | -------------------------------------------------------------------------------- /spec/generator-definitions-patch.html: -------------------------------------------------------------------------------- 1 | 2 |

Runtime Semantics: Evaluation

3 | 4 | YieldExpression : `yield` 5 | 6 | 1. Let _generatorKind_ be ! GetGeneratorKind(). 7 | 1. If _generatorKind_ is ~async~, then return ? AsyncGeneratorYield(*undefined*). 8 | 1. Otherwise, rReturn ? GeneratorYield(CreateIterResultObject(*undefined*, *false*)). 9 | 10 | 11 | YieldExpression : `yield` AssignmentExpression 12 | 13 | 1. Let _generatorKind_ be ! GetGeneratorKind(). 14 | 1. Let _exprRef_ be the result of evaluating |AssignmentExpression|. 15 | 1. Let _value_ be ? GetValue(_exprRef_). 16 | 1. If _generatorKind_ is ~async~, then return ? AsyncGeneratorYield(_value_). 17 | 1. Otherwise, rReturn ? GeneratorYield(CreateIterResultObject(_value_, *false*)). 18 | 19 | 20 | 21 | YieldExpression : `yield` `*` AssignmentExpression 22 | 23 | 24 | 1. Let _generatorKind_ be ! GetGeneratorKind(). 25 | 1. Let _exprRef_ be the result of evaluating |AssignmentExpression|. 26 | 1. Let _value_ be ? GetValue(_exprRef_). 27 | 1. Let _iteratorRecord_ be ? GetIterator(_value_, _generatorKind_). 28 | 1. Let _iterator_ be _iteratorRecord_.[[Iterator]]. 29 | 1. Let _received_ be NormalCompletion(*undefined*). 30 | 1. Repeat 31 | 1. If _received_.[[Type]] is ~normal~, then 32 | 1. Let _innerResult_ be ? IteratorNext(_iteratorRecord_, _received_.[[Value]]). 33 | 1. Let _innerResult_ be ? Call(_iteratorRecord_.[[NextMethod]], _iteratorRecord_.[[Iterator]], « _received_.[[Value]] »). 34 | 1. If _generatorKind_ is ~async~, then set _innerResult_ to ? Await(_innerResult_). 35 | 1. If Type(_innerResult_) is not Object, throw a *TypeError* exception. 36 | 1. Let _done_ be ? IteratorComplete(_innerResult_). 37 | 1. If _done_ is *true*, then 38 | 1. Return ? IteratorValue(_innerResult_). 39 | 1. If _generatorKind_ is ~async~, then let _received_ be AsyncGeneratorYield(? IteratorValue(_innerResult_)). 40 | 1. Else, lLet _received_ be GeneratorYield(_innerResult_). 41 | 1. Else if _received_.[[Type]] is ~throw~, then 42 | 1. Let _throw_ be ? GetMethod(_iterator_, `"throw"`). 43 | 1. If _throw_ is not *undefined*, then 44 | 1. Let _innerResult_ be ? Call(_throw_, _iterator_, « _received_.[[Value]] »). 45 | 1. If _generatorKind_ is ~async~, then set _innerResult_ to ? Await(_innerResult_). 46 | 1. NOTE: Exceptions from the inner iterator `throw` method are propagated. Normal completions from an inner `throw` method are processed similarly to an inner `next`. 47 | 1. If Type(_innerResult_) is not Object, throw a *TypeError* exception. 48 | 1. Let _done_ be ? IteratorComplete(_innerResult_). 49 | 1. If _done_ is *true*, then 50 | 1. Return ? IteratorValue(_innerResult_). 51 | 1. If _generatorKind_ is ~async~, then let _received_ be AsyncGeneratorYield(? IteratorValue(_innerResult_)). 52 | 1. Else, lLet _received_ be GeneratorYield(_innerResult_). 53 | 1. Else, 54 | 1. NOTE: If _iterator_ does not have a `throw` method, this throw is going to terminate the `yield*` loop. But first we need to give _iterator_ a chance to clean up. 55 | 1. Let _closeCompletion_ be Completion{[[Type]]: ~normal~, [[Value]]: ~empty~, [[Target]]: ~empty~}. 56 | 1. If _generatorKind_ is ~async~, perform ? AsyncIteratorClose(_iteratorRecord_, _closeCompletion_). 57 | 1. Else, pPerform ? IteratorClose(_iteratorRecord_, Completion{[[Type]]: ~normal~, [[Value]]: ~empty~, [[Target]]: ~empty~}_closeCompletion_). 58 | 1. NOTE: The next step throws a *TypeError* to indicate that there was a `yield*` protocol violation: _iterator_ does not have a `throw` method. 59 | 1. Throw a *TypeError* exception. 60 | 1. Else, 61 | 1. Assert: _received_.[[Type]] is ~return~. 62 | 1. Let _return_ be ? GetMethod(_iterator_, `"return"`). 63 | 1. If _return_ is *undefined*, return Completion(_received_).then: 64 | 1. If _generatorKind_ is ~async~, then set _received_.[[Value]] to ? Await(_received_.[[Value]]). 65 | 1. Return Completion(_received_). 66 | 1. Let _innerReturnResult_ be ? Call(_return_, _iterator_, « _received_.[[Value]] »). 67 | 1. If _generatorKind_ is ~async~, then set _innerReturnResult_ to ? Await(_innerReturnResult_). 68 | 1. If Type(_innerReturnResult_) is not Object, throw a *TypeError* exception. 69 | 1. Let _done_ be ? IteratorComplete(_innerReturnResult_). 70 | 1. If _done_ is *true*, then 71 | 1. Let _value_ be ? IteratorValue(_innerReturnResult_). 72 | 1. Return Completion{[[Type]]: ~return~, [[Value]]: _value_, [[Target]]: ~empty~}. 73 | 1. If _generatorKind_ is ~async~, then let _received_ be AsyncGeneratorYield(? IteratorValue(_innerResult_)). 74 | 1. Else, lLet _received_ be GeneratorYield(_innerResult_). 75 | 76 |
77 | -------------------------------------------------------------------------------- /spec/create-dynamic-function-patch.html: -------------------------------------------------------------------------------- 1 |

The abstract operation CreateDynamicFunction is called with arguments _constructor_, _newTarget_, _kind_, and _args_. _constructor_ is the constructor function that is performing this action, _newTarget_ is the constructor that `new` was initially applied to, _kind_ is either `"normal"`, `"generator"`, or `"async"`, or `"async generator"`, and _args_ is a List containing the actual argument values that were passed to _constructor_. The following steps are taken:

2 | 3 | 4 | 1. Assert: The execution context stack has at least two elements. 5 | 1. Let _callerContext_ be the second to top element of the execution context stack. 6 | 1. Let _callerRealm_ be _callerContext_'s Realm. 7 | 1. Let _calleeRealm_ be the current Realm Record. 8 | 1. Perform ? HostEnsureCanCompileStrings(_callerRealm_, _calleeRealm_). 9 | 1. If _newTarget_ is *undefined*, let _newTarget_ be _constructor_. 10 | 1. If _kind_ is `"normal"`, then 11 | 1. Let _goal_ be the grammar symbol |FunctionBody[~Yield, ~Await]|. 12 | 1. Let _parameterGoal_ be the grammar symbol |FormalParameters[~Yield, ~Await]|. 13 | 1. Let _fallbackProto_ be `"%FunctionPrototype%"`. 14 | 1. Else if _kind_ is `"generator"`, then 15 | 1. Let _goal_ be the grammar symbol |GeneratorBody|. 16 | 1. Let _parameterGoal_ be the grammar symbol |FormalParameters[+Yield, ~Await]|. 17 | 1. Let _fallbackProto_ be `"%Generator%"`. 18 | 1. Else, 19 | 1. Else if _kind_ is `"async"`, 20 | 1. Assert: _kind_ is `"async"` 21 | 1. Let _goal_ be the grammar symbol |AsyncFunctionBody|. 22 | 1. Let _parameterGoal_ be the grammar symbol |FormalParameters[~Yield, +Await]|. 23 | 1. Let _fallbackProto_ be `"%AsyncFunctionPrototype%"`. 24 | 1. Else, 25 | 1. Assert: _kind_ is `"async generator"` 26 | 1. Let _goal_ be the grammar symbol |AsyncGeneratorBody|. 27 | 1. Let _parameterGoal_ be the grammar symbol |FormalParameters[+Yield, +Await]|. 28 | 1. Let _fallbackProto_ be `"%AsyncGenerator%"`. 29 | 1. Let _argCount_ be the number of elements in _args_. 30 | 1. Let _P_ be the empty String. 31 | 1. If _argCount_ = 0, let _bodyText_ be the empty String. 32 | 1. Else if _argCount_ = 1, let _bodyText_ be _args_[0]. 33 | 1. Else _argCount_ > 1, 34 | 1. Let _firstArg_ be _args_[0]. 35 | 1. Let _P_ be ? ToString(_firstArg_). 36 | 1. Let _k_ be 1. 37 | 1. Repeat, while _k_ < _argCount_-1 38 | 1. Let _nextArg_ be _args_[_k_]. 39 | 1. Let _nextArgString_ be ? ToString(_nextArg_). 40 | 1. Let _P_ be the result of concatenating the previous value of _P_, the String `","` (a comma), and _nextArgString_. 41 | 1. Increase _k_ by 1. 42 | 1. Let _bodyText_ be _args_[_k_]. 43 | 1. Let _bodyText_ be ? ToString(_bodyText_). 44 | 1. Let _parameters_ be the result of parsing _P_, interpreted as UTF-16 encoded Unicode text as described in , using _parameterGoal_ as the goal symbol. Throw a *SyntaxError* exception if the parse fails. 45 | 1. Let _body_ be the result of parsing _bodyText_, interpreted as UTF-16 encoded Unicode text as described in , using _goal_ as the goal symbol. Throw a *SyntaxError* exception if the parse fails. 46 | 1. If _bodyText_ is strict mode code, let _strict_ be *true*, else let _strict_ be *false*. 47 | 1. If any static semantics errors are detected for _parameters_ or _body_, throw a *SyntaxError* or a *ReferenceError* exception, depending on the type of the error. If _strict_ is *true*, the Early Error rules for UniqueFormalParameters : FormalParameters are applied. Parsing and early error detection may be interweaved in an implementation-dependent manner. 48 | 1. If ContainsUseStrict of _body_ is *true* and IsSimpleParameterList of _parameters_ is *false*, throw a *SyntaxError* exception. 49 | 1. If any element of the BoundNames of _parameters_ also occurs in the LexicallyDeclaredNames of _body_, throw a *SyntaxError* exception. 50 | 1. If _body_ Contains |SuperCall| is *true*, throw a *SyntaxError* exception. 51 | 1. If _parameters_ Contains |SuperCall| is *true*, throw a *SyntaxError* exception. 52 | 1. If _body_ Contains |SuperProperty| is *true*, throw a *SyntaxError* exception. 53 | 1. If _parameters_ Contains |SuperProperty| is *true*, throw a *SyntaxError* exception. 54 | 1. If _kind_ is `"generator"` or `"async generator"`, then 55 | 1. If _parameters_ Contains |YieldExpression| is *true*, throw a *SyntaxError* exception. 56 | 1. If _kind_ is `"async"` or `"async generator"`, then 57 | 1. If _parameters_ Contains |AwaitExpression| is *true*, throw a *SyntaxError* exception. 58 | 1. If _strict_ is *true*, then 59 | 1. If BoundNames of _parameters_ contains any duplicate elements, throw a *SyntaxError* exception. 60 | 1. Let _proto_ be ? GetPrototypeFromConstructor(_newTarget_, _fallbackProto_). 61 | 1. Let _F_ be FunctionAllocate(_proto_, _strict_, _kind_). 62 | 1. Let _realmF_ be _F_.[[Realm]]. 63 | 1. Let _scope_ be _realmF_.[[GlobalEnv]]. 64 | 1. Perform FunctionInitialize(_F_, ~Normal~, _parameters_, _body_, _scope_). 65 | 1. If _kind_ is `"generator"`, then 66 | 1. Let _prototype_ be ObjectCreate(%GeneratorPrototype%). 67 | 1. Perform DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}). 68 | 1. Else if _kind_ is `"async generator"`, then 69 | 1. Let _prototype_ be ObjectCreate(%AsyncGeneratorPrototype%). 70 | 1. Perform DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}). 71 | 1. Else if _kind_ is `"normal"`, perform MakeConstructor(_F_). 72 | 1. NOTE: Async functions are not constructable and do not have a [[Construct]] internal method or a `"prototype"` property. 73 | 1. Perform SetFunctionName(_F_, `"anonymous"`). 74 | 1. Return _F_. 75 | 76 | 77 |

A `prototype` property is created for every non-async function created using CreateDynamicFunction to provide for the possibility that the function will be used as a constructor.

78 |
79 | -------------------------------------------------------------------------------- /spec/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
  4 | title: Async Iteration
  5 | status: proposal
  6 | stage: 3
  7 | location: https://tc39.github.io/proposal-async-iteration/
  8 | copyright: false
  9 | contributors: Kevin Smith, Domenic Denicola
 10 | 
11 | 12 | 13 | 14 | 15 | 16 |

Introduction

17 | 18 |
19 | 20 | 21 |

Well-Known Symbols

22 | 23 |

The spec's existing in should be expanded with the following rows:

24 |
25 | 26 | 27 |
28 | 29 | 30 |

Well-Known Intrinsic Objects

31 | 32 |

The spec's existing in should be expanded with the following rows:

33 |
34 | 35 | 36 |
37 | 38 | 39 |

The Completion Record Specification Type

40 | 41 | This patch adds clauses to . 42 | 43 | 44 | 45 |
46 | 47 | 48 |

Operations on Iterator Objects

49 | 50 | These patches modify clauses of and add clauses to . 51 | 52 | 53 | 54 |
55 | 56 | 57 |

ECMAScript Function Objects

58 | 59 | This patch adds a clause to . 60 | 61 | 62 | 63 |
64 | 65 | 66 |

ECMAScript Language: Statements and Declarations

67 | 68 | These patches modify clauses of and add clauses to . 69 | 70 | 71 | 72 |

The `return` Statement

73 | 74 |
75 | 76 | 77 |

Iteration Statements

78 | 79 |
80 |
81 | 82 | 83 |

ECMAScript Language: Functions and Classes

84 | 85 | These patches modify clauses of and add clauses to . 86 | 87 | 88 | 89 |

Method Definitions

90 | 91 |
92 | 93 | 94 |

Generator Definitions

95 | 96 |
97 | 98 | 99 |

Async Generator Function Definitions

100 | 101 |
102 |
103 | 104 | 105 |

Runtime Semantics: CreateDynamicFunction(_constructor_, _newTarget_, _kind_, _args_)

106 | 107 | This patch modifies . 108 | 109 | 110 | 111 |
112 | 113 | 114 |

Properties of the Symbol Constructor

115 | 116 | This patch add a clause to . 117 | 118 | 119 | 120 |
121 | 122 | 123 |

Control Abstraction Objects

124 | 125 | These patches modify clauses of and add clauses to . 126 | 127 | 128 | 129 |

Iteration

130 | 131 |
132 | 133 | 134 |

Generator Objects

135 | 136 |

Generator Abstract Operations

137 | 138 |
139 |
140 | 141 | 142 |

AsyncGeneratorFunction Objects

143 | 144 |
145 | 146 | 147 |

AsyncGenerator Objects

148 | 149 |
150 |
151 | 152 | 153 |

Miscellaneous Patches

154 | 155 |
156 | -------------------------------------------------------------------------------- /spec/async-generator-function-objects.html: -------------------------------------------------------------------------------- 1 |

AsyncGenerator Function objects are functions that are usually created by evaluating |AsyncGeneratorDeclaration|, |AsyncGeneratorExpression|, and |AsyncGeneratorMethod| syntactic productions. They may also be created by calling the %AsyncGeneratorFunction% intrinsic.

2 | 3 | 4 |

The AsyncGeneratorFunction Constructor

5 |

The `AsyncGeneratorFunction` constructor is the %AsyncGeneratorFunction% intrinsic. When `AsyncGeneratorFunction` is called as a function rather than as a constructor, it creates and initializes a new AsyncGeneratorFunction object. Thus the function call `AsyncGeneratorFunction (...)` is equivalent to the object creation expression `new AsyncGeneratorFunction (...)` with the same arguments.

6 |

`AsyncGeneratorFunction` is designed to be subclassable. It may be used as the value of an `extends` clause of a class definition. Subclass constructors that intend to inherit the specified `AsyncGeneratorFunction` behaviour must include a `super` call to the `AsyncGeneratorFunction` constructor to create and initialize subclass instances with the internal slots necessary for built-in AsyncGeneratorFunction behaviour. All ECMAScript syntactic forms for defining async generator function objects create direct instances of `AsyncGeneratorFunction`. There is no syntactic means to create instances of `AsyncGeneratorFunction` subclasses.

7 | 8 | 9 |

AsyncGeneratorFunction ( _p1_, _p2_, ..., _pn_, _body_ )

10 |

The last argument specifies the body (executable code) of an async generator function; any preceding arguments specify formal parameters.

11 |

When the `AsyncGeneratorFunction` function is called with some arguments _p1_, _p2_, … , _pn_, _body_ (where _n_ might be 0, that is, there are no "_p_" arguments, and where _body_ might also not be provided), the following steps are taken:

12 | 13 | 1. Let _C_ be the active function object. 14 | 1. Let _args_ be the _argumentsList_ that was passed to this function by [[Call]] or [[Construct]]. 15 | 1. Return ? CreateDynamicFunction(_C_, NewTarget, `"async generator"`, _args_). 16 | 17 | 18 |

See NOTE for .

19 |
20 |
21 |
22 | 23 | 24 |

Properties of the AsyncGeneratorFunction Constructor

25 |

The `AsyncGeneratorFunction` constructor is a standard built-in function object that inherits from the `Function` constructor. The value of the [[Prototype]] internal slot of the `AsyncGeneratorFunction` constructor is the intrinsic object %Function%.

26 |

The value of the [[Extensible]] internal slot of the AsyncGeneratorFunction constructor is *true*.

27 |

The value of the `name` property of the AsyncGeneratorFunction is `"AsyncGeneratorFunction"`.

28 |

The `AsyncGeneratorFunction` constructor has the following properties:

29 | 30 | 31 |

AsyncGeneratorFunction.length

32 |

This is a data property with a value of 1. This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }.

33 |
34 | 35 | 36 |

AsyncGeneratorFunction.prototype

37 |

The initial value of `AsyncGeneratorFunction.prototype` is the intrinsic object %AsyncGenerator%.

38 |

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

39 |
40 |
41 | 42 | 43 |

Properties of the AsyncGeneratorFunction Prototype Object

44 |

The AsyncGeneratorFunction prototype object is an ordinary object. It is not a function object and does not have an [[ECMAScriptCode]] internal slot or any other of the internal slots listed in or . In addition to being the value of the prototype property of the %AsyncGeneratorFunction% intrinsic, it is the %AsyncGenerator% intrinsic.

45 |

The value of the [[Prototype]] internal slot of the AsyncGeneratorFunction prototype object is the %FunctionPrototype% intrinsic object. The initial value of the [[Extensible]] internal slot of the AsyncGeneratorFunction prototype object is *true*.

46 | 47 | 48 |

AsyncGeneratorFunction.prototype.constructor

49 |

The initial value of `AsyncGeneratorFunction.prototype.constructor` is the intrinsic object %AsyncGeneratorFunction%.

50 |

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

51 |
52 | 53 | 54 |

AsyncGeneratorFunction.prototype.prototype

55 |

The value of `AsyncGeneratorFunction.prototype.prototype` is the %AsyncGeneratorPrototype% intrinsic object.

56 |

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

57 |
58 | 59 | 60 |

AsyncGeneratorFunction.prototype [ @@toStringTag ]

61 |

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

62 |

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

63 |
64 |
65 | 66 | 67 |

AsyncGeneratorFunction Instances

68 |

Every AsyncGeneratorFunction instance is an ECMAScript function object and has the internal slots listed in . The value of the [[FunctionKind]] internal slot for all such instances is `"generator"`.

69 |

Each AsyncGeneratorFunction instance has the following own properties:

70 | 71 | 72 |

length

73 |

The value of the `length` property is an integer that indicates the typical number of arguments expected by the AsyncGeneratorFunction. However, the language permits the function to be invoked with some other number of arguments. The behaviour of an AsyncGeneratorFunction when invoked on a number of arguments other than the number specified by its `length` property depends on the function.

74 |

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

75 |
76 | 77 | 78 |

name

79 |

The specification for the `name` property of Function instances given in also applies to AsyncGeneratorFunction instances.

80 |
81 | 82 | 83 |

prototype

84 |

Whenever an AsyncGeneratorFunction instance is created another ordinary object is also created and is the initial value of the async generator function's `prototype` property. The value of the prototype property is used to initialize the [[Prototype]] internal slot of a newly created AsyncGenerator object when the generator function object is invoked using [[Call]].

85 |

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

86 | 87 |

Unlike function instances, the object that is the value of the an AsyncGeneratorFunction's `prototype` property does not have a `constructor` property whose value is the AsyncGeneratorFunction instance.

88 |
89 |
90 |
91 | -------------------------------------------------------------------------------- /spec/abstract-operations.html: -------------------------------------------------------------------------------- 1 | 2 |

AsyncGeneratorRequest Records

3 |

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.

4 |

They have the following fields:

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
Field NameValueMeaning
[[Completion]]A Completion recordThe completion which should be used to resume the async generator.
[[Capability]]A PromiseCapability recordThe promise capabilities associated with this request.
25 |
26 |
27 | 28 | 29 |

AsyncGeneratorStart ( _generator_, _generatorBody_ )

30 | 31 | 1. Assert: _generator_ is an AsyncGenerator instance. 32 | 1. Assert: _generator_.[[AsyncGeneratorState]] is *undefined*. 33 | 1. Let _genContext_ be the running execution context. 34 | 1. Set the Generator component of _genContext_ to _generator_. 35 | 1. Set the code evaluation state of _genContext_ such that when evaluation is resumed for that execution context the following steps will be performed: 36 | 1. Let _result_ be the result of evaluating _generatorBody_. 37 | 1. Assert: If we return here, the async generator either threw an exception or performed either an implicit or explicit return. 38 | 1. 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. 39 | 1. Set _generator_.[[AsyncGeneratorState]] to `"completed"`. 40 | 1. If _result_ is a normal completion, let _resultValue_ be *undefined*. 41 | 1. Else, 42 | 1. Let _resultValue_ be _result_.[[Value]]. 43 | 1. If _result_.[[Type]] is not ~return~, then 44 | 1. Return ! AsyncGeneratorReject(_generator_, _resultValue_). 45 | 1. Return ! AsyncGeneratorResolve(_generator_, _resultValue_, *true*). 46 | 1. Set _generator_.[[AsyncGeneratorContext]] to _genContext_. 47 | 1. Set _generator_.[[AsyncGeneratorState]] to `"suspendedStart"`. 48 | 1. Set _generator_.[[AsyncGeneratorQueue]] to a new empty List. 49 | 1. Return *undefined*. 50 | 51 |
52 | 53 | 54 |

AsyncGeneratorResolve ( _generator_, _value_, _done_ )

55 | 56 | 1. Assert: _generator_ is an AsyncGenerator instance. 57 | 1. Let _queue_ be _generator_.[[AsyncGeneratorQueue]]. 58 | 1. Assert: _queue_ is not an empty List. 59 | 1. Remove the first element from _queue_ and let _next_ be the value of that element. 60 | 1. Let _promiseCapability_ be _next_.[[Capability]]. 61 | 1. Let _iteratorResult_ be ! CreateIterResultObject(_value_, _done_). 62 | 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _iteratorResult_ »). 63 | 1. Perform ! AsyncGeneratorResumeNext(_generator_). 64 | 1. Return *undefined*. 65 |
66 | 67 | 68 | 69 |

AsyncGeneratorReject ( _generator_, _exception_ )

70 | 71 | 1. Assert: _generator_ is an AsyncGenerator instance. 72 | 1. Let _queue_ be _generator_.[[AsyncGeneratorQueue]]. 73 | 1. Assert: _queue_ is not an empty List. 74 | 1. Remove the first element from _queue_ and let _next_ be the value of that element. 75 | 1. Let _promiseCapability_ be _next_.[[Capability]]. 76 | 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _exception_ »). 77 | 1. Perform ! AsyncGeneratorResumeNext(_generator_). 78 | 1. Return *undefined*. 79 | 80 |
81 | 82 | 83 |

AsyncGeneratorResumeNext ( _generator_ )

84 | 85 | 1. Assert: _generator_ is an AsyncGenerator instance. 86 | 1. Let _state_ be _generator_.[[AsyncGeneratorState]]. 87 | 1. Assert: _state_ is not `"executing"`. 88 | 1. If _state_ is `"awaiting-return"`, return *undefined*. 89 | 1. Let _queue_ be _generator_.[[AsyncGeneratorQueue]]. 90 | 1. If _queue_ is an empty List, return *undefined*. 91 | 1. Let _next_ be the value of the first element of _queue_. 92 | 1. Assert: _next_ is an AsyncGeneratorRequest record. 93 | 1. Let _completion_ be _next_.[[Completion]]. 94 | 1. If _completion_ is an abrupt completion, then 95 | 1. If _state_ is `"suspendedStart"`, then 96 | 1. Set _generator_.[[AsyncGeneratorState]] to `"completed"`. 97 | 1. Set _state_ to `"completed"`. 98 | 1. If _state_ is `"completed"`, then 99 | 1. If _completion_.[[Type]] is ~return~: 100 | 1. Set _generator_.[[AsyncGeneratorState]] to `"awaiting-return"`. 101 | 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). 102 | 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _completion_.[[Value]] »). 103 | 1. Let _onFulfilled_ be a new built-in function object as defined in . 104 | 1. Let _onRejected_ be a new built-in function object as defined in . 105 | 1. Set _onFulfilled_ and _onRejected_'s [[Generator]] internal slots to _generator_. 106 | 1. Let _throwawayCapability_ be NewPromiseCapability(%Promise%). 107 | 1. Set _throwawayCapability_.[[Promise]].[[PromiseIsHandled]] to *true*. 108 | 1. Perform ! PerformPromiseThen(_promiseCapability_.[[Promise]], _onFulfilled_, _onRejected_, _throwawayCapability_). 109 | 1. Return *undefined*. 110 | 1. Else, 111 | 1. Assert: _completion_.[[Type]] is ~throw~. 112 | 1. Perform ! AsyncGeneratorReject(_generator_, _completion_.[[Value]]). 113 | 1. Return *undefined*. 114 | 1. Else if _state_ is `"completed"`, then return ! AsyncGeneratorResolve(_generator_, *undefined*, *true*). 115 | 1. Assert: _state_ is either `"suspendedStart"` or `"suspendedYield"`. 116 | 1. Let _genContext_ be _generator_.[[AsyncGeneratorContext]]. 117 | 1. Let _callerContext_ be the running execution context. 118 | 1. Suspend _callerContext_. 119 | 1. Set _generator_.[[AsyncGeneratorState]] to `"executing"`. 120 | 1. Push _genContext_ onto the execution context stack; _genContext_ is now the running execution context. 121 | 1. 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. 122 | 1. Assert: _result_ is never an abrupt completion. 123 | 1. Assert: When we return here, _genContext_ has already been removed from the execution context stack and _callerContext_ is the currently running execution context. 124 | 1. Return *undefined*. 125 | 126 | 127 | 128 |

AsyncGeneratorResumeNext Return Processor Fulfilled Functions

129 | 130 |

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 method. Each AsyncGeneratorResumeNext return processor fulfilled function has a [[Generator]] internal slot.

131 | 132 |

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

133 | 134 | 135 | 1. Set _F_.[[Generator]].[[AsyncGeneratorState]] to `"completed"`. 136 | 1. Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *true*). 137 | 138 | 139 |

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

140 |
141 | 142 | 143 |

AsyncGeneratorResumeNext Return Processor Rejected Functions

144 | 145 |

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 method. Each AsyncGeneratorResumeNext return processor rejected function has a [[Generator]] internal slot.

146 | 147 |

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

148 | 149 | 150 | 1. Set _F_.[[Generator]].[[AsyncGeneratorState]] to `"completed"`. 151 | 1. Return ! AsyncGeneratorReject(_F_.[[Generator]], _reason_). 152 | 153 | 154 |

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

155 |
156 |
157 | 158 | 159 |

AsyncGeneratorEnqueue ( _generator_, _completion_ )

160 | 161 | 1. Assert: _completion_ is a Completion Record. 162 | 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). 163 | 1. If Type(_generator_) is not Object, or if _generator_ does not have an [[AsyncGeneratorState]] internal slot, then 164 | 1. Let _badGeneratorError_ be a new *TypeError* exception. 165 | 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _badGeneratorError_ »). 166 | 1. Return _promiseCapability_.[[Promise]]. 167 | 1. Let _queue_ be _generator_.[[AsyncGeneratorQueue]]. 168 | 1. Let _request_ be AsyncGeneratorRequest{[[Completion]]: _completion_, [[Capability]]: _promiseCapability_}. 169 | 1. Append _request_ to the end of _queue_. 170 | 1. Let _state_ be _generator_.[[AsyncGeneratorState]]. 171 | 1. If _state_ is not `"executing"`, then 172 | 1. Perform ! AsyncGeneratorResumeNext(_generator_). 173 | 1. Return _promiseCapability_.[[Promise]]. 174 | 175 |
176 | 177 | 178 |

AsyncGeneratorYield ( _value_ )

179 |

The abstract operation AsyncGeneratorYield with argument _value_ performs the following steps:

180 | 181 | 1. Let _genContext_ be the running execution context. 182 | 1. Assert: _genContext_ is the execution context of a generator. 183 | 1. Let _generator_ be the value of the Generator component of _genContext_. 184 | 1. Assert: GetGeneratorKind() is ~async~. 185 | 1. Set _value_ to ? Await(_value_). 186 | 1. Set _generator_.[[AsyncGeneratorState]] to `"suspendedYield"`. 187 | 1. 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. 188 | 1. Set the code evaluation state of _genContext_ such that when evaluation is resumed with a Completion _resumptionValue_ the following steps will be performed: 189 | 1. If _resumptionValue_.[[Type]] is not ~return~, return Completion(_resumptionValue_). 190 | 1. Let _awaited_ be Await(_resumptionValue_.[[Value]]). 191 | 1. If _awaited_.[[Type]] is ~throw~, return Completion(_awaited_). 192 | 1. Assert: _awaited_.[[Type]] is ~normal~. 193 | 1. Return Completion{[[Type]]: ~return~, [[Value]]: _awaited_.[[Value]], [[Target]]: ~empty~}. 194 | 1. NOTE: When one of the above steps returns, it returns to the evaluation of the |YieldExpression| production that originally called this abstract operation. 195 | 1. Return ! AsyncGeneratorResolve(_generator_, _value_, *false*). 196 | 1. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of _genContext_. 197 | 198 |
199 | -------------------------------------------------------------------------------- /spec/definitions.html: -------------------------------------------------------------------------------- 1 |

Syntax

2 | 3 | AsyncGeneratorMethod[Yield, Await] : 4 | `async` [no LineTerminator here] `*` PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` 5 | 6 | AsyncGeneratorDeclaration[Yield, Await, Default] : 7 | `async` [no LineTerminator here] `function` `*` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` 8 | [+Default] `async` [no LineTerminator here] `function` `*` `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` 9 | 10 | AsyncGeneratorExpression : 11 | `async` [no LineTerminator here] `function` `*` BindingIdentifier[+Yield, +Await]? `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` 12 | 13 | AsyncGeneratorBody : 14 | FunctionBody[+Yield, +Await] 15 | 16 | 17 |

|YieldExpression| and |AwaitExpression| cannot be used within the |FormalParameters| of an async generator function because any expressions that are part of |FormalParameters| are evaluated before the resulting async generator object is in a resumable state.

18 |
19 | 20 |

Abstract operations relating to async generator objects are defined in .

21 |
22 | 23 | 24 |

Static Semantics: Early Errors

25 | AsyncGeneratorMethod : `*` PropertyName `(` UniqueFormalParameters `)` `{` AsyncGeneratorBody `}` 26 | 33 | 34 | AsyncGeneratorDeclaration : `function` `*` BindingIdentifier `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 35 | 36 | AsyncGeneratorDeclaration : `function` `*` `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 37 | 38 | AsyncGeneratorDeclaration : `function` `*` BindingIdentifier? `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 39 | 40 | 52 |
53 | 54 | 55 |

Static Semantics: BoundNames

56 | 57 | AsyncGeneratorDeclaration : `function` `*` BindingIdentifier `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 58 | 59 | 1. Return the BoundNames of |BindingIdentifier|. 60 | 61 | AsyncGeneratorDeclaration : `function` `*` `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 62 | 63 | 1. Return « `"*default*"` ». 64 | 65 | 66 |

`"*default*"` is used within this specification as a synthetic name for hoistable anonymous functions that are defined using export declarations.

67 |
68 |
69 | 70 | 71 |

Static Semantics: ComputedPropertyContains

72 |

With parameter _symbol_.

73 | 74 | AsyncGeneratorMethod : `*` PropertyName `(` UniqueFormalParameters `)` `{` AsyncGeneratorBody `}` 75 | 76 | 1. Return the result of ComputedPropertyContains for |PropertyName| with argument _symbol_. 77 | 78 |
79 | 80 | 81 |

Static Semantics: Contains

82 |

With parameter _symbol_.

83 | 84 | 85 | AsyncGeneratorDeclaration : `function` `*` BindingIdentifier `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 86 | 87 | AsyncGeneratorDeclaration : `function` `*` `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 88 | 89 | AsyncGeneratorExpression : `function` `*` BindingIdentifier? `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 90 | 91 | 92 | 1. Return *false*. 93 | 94 | 95 |

Static semantic rules that depend upon substructure generally do not look into function definitions.

96 |
97 |
98 | 99 | 100 |

Static Semantics: HasDirectSuper

101 | 102 | AsyncGeneratorMethod : `*` PropertyName `(` UniqueFormalParameters `)` `{` AsyncGeneratorBody `}` 103 | 104 | 1. If |UniqueFormalParameters| Contains |SuperCall| is *true*, return *true*. 105 | 1. Return |AsyncGeneratorBody| Contains |SuperCall|. 106 | 107 |
108 | 109 | 110 |

Static Semantics: HasName

111 | 112 | AsyncGeneratorExpression : `function` `*` `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 113 | 114 | 1. Return *false*. 115 | 116 | AsyncGeneratorExpression : `function` `*` BindingIdentifier `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 117 | 118 | 1. Return *true*. 119 | 120 |
121 | 122 | 123 |

Static Semantics: IsConstantDeclaration

124 | 125 | 126 | AsyncGeneratorDeclaration : `function` `*` BindingIdentifier `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 127 | 128 | AsyncGeneratorDeclaration : `function` `*` `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 129 | 130 | 131 | 1. Return *false*. 132 | 133 |
134 | 135 | 136 |

Static Semantics: IsFunctionDefinition

137 | 138 | AsyncGeneratorExpression : `function` `*` BindingIdentifier? `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 139 | 140 | 1. Return *true*. 141 | 142 |
143 | 144 | 145 |

Static Semantics: PropName

146 | 147 | AsyncGeneratorMethod : `*` PropertyName `(` UniqueFormalParameters `)` `{` AsyncGeneratorBody `}` 148 | 149 | 1. Return PropName of |PropertyName|. 150 | 151 |
152 | 153 | 154 |

Runtime Semantics: EvaluateBody

155 |

With parameters _functionObject_ and List _argumentsList_.

156 | 157 | AsyncGeneratorBody : FunctionBody 158 | 159 | 160 | 1. Perform ? FunctionDeclarationInstantiation(_functionObject_, _argumentsList_). 161 | 1. Let _generator_ be ? OrdinaryCreateFromConstructor(_functionObject_, `"%AsyncGeneratorPrototype%"`, « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]] »). 162 | 1. Perform ! AsyncGeneratorStart(_generator_, _FunctionBody_). 163 | 1. Return Completion{[[Type]]: ~return~, [[Value]]: _generator_, [[Target]]: ~empty~}. 164 | 165 |
166 | 167 | 168 |

Runtime Semantics: InstantiateFunctionObject

169 |

With parameter _scope_.

170 | 171 | AsyncGeneratorDeclaration : `async` [no LineTerminator here] `function` `*` BindingIdentifier `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 172 | 173 | 174 | 1. If the function code for |AsyncGeneratorDeclaration| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*. 175 | 1. Let _name_ be StringValue of |BindingIdentifier|. 176 | 1. Let _F_ be ! AsyncGeneratorFunctionCreate(~Normal~, |FormalParameters|, |AsyncGeneratorBody|, _scope_, _strict_). 177 | 1. Let _prototype_ be ! ObjectCreate(%AsyncGeneratorPrototype%). 178 | 1. Perform ! DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}). 179 | 1. Perform ! SetFunctionName(_F_, _name_). 180 | 1. Return _F_. 181 | 182 | 183 | 184 | AsyncGeneratorDeclaration : `async` [no LineTerminator here] `function` `*` `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 185 | 186 | 187 | 1. If the function code for |AsyncGeneratorDeclaration| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*. 188 | 1. Let _F_ be AsyncGeneratorFunctionCreate(~Normal~, |FormalParameters|, |AsyncGeneratorBody|, _scope_, _strict_). 189 | 1. Let _prototype_ be ObjectCreate(%AsyncGeneratorPrototype%). 190 | 1. Perform DefinePropertyOrThrow(_F_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}). 191 | 1. Perform SetFunctionName(_F_, `"default"`). 192 | 1. Return _F_. 193 | 194 | 195 |

An anonymous |AsyncGeneratorDeclaration| can only occur as part of an `export default` declaration.

196 |
197 |
198 | 199 | 200 |

Runtime Semantics: PropertyDefinitionEvaluation

201 |

With parameter _object_ and _enumerable_.

202 | 203 | AsyncGeneratorMethod : `async` [no LineTerminator here] `*` PropertyName `(` UniqueFormalParameters `)` `{` AsyncGeneratorBody `}` 204 | 205 | 206 | 1. Let _propKey_ be the result of evaluating |PropertyName|. 207 | 1. ReturnIfAbrupt(_propKey_). 208 | 1. If the function code for this |AsyncGeneratorMethod| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*. 209 | 1. Let _scope_ be the running execution context's LexicalEnvironment. 210 | 1. Let _closure_ be ! AsyncGeneratorFunctionCreate(~Method~, |UniqueFormalParameters|, |AsyncGeneratorBody|, _scope_, _strict_). 211 | 1. Perform ! MakeMethod(_closure_, _object_). 212 | 1. Let _prototype_ be ! ObjectCreate(%AsyncGeneratorPrototype%). 213 | 1. Perform ! DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}). 214 | 1. Perform ! SetFunctionName(_closure_, _propKey_). 215 | 1. Let _desc_ be PropertyDescriptor{[[Value]]: _closure_, [[Writable]]: *true*, [[Enumerable]]: _enumerable_, [[Configurable]]: *true*}. 216 | 1. Return ? DefinePropertyOrThrow(_object_, _propKey_, _desc_). 217 | 218 |
219 | 220 | 221 |

Runtime Semantics: Evaluation

222 | 223 | 224 | AsyncGeneratorExpression : `async` [no LineTerminator here] `function` `*` `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 225 | 226 | 227 | 1. If the function code for this |AsyncGeneratorExpression| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*. 228 | 1. Let _scope_ be the LexicalEnvironment of the running execution context. 229 | 1. Let _closure_ be ! AsyncGeneratorFunctionCreate(~Normal~, |FormalParameters|, |AsyncGeneratorBody|, _scope_, _strict_). 230 | 1. Let _prototype_ be ! ObjectCreate(%AsyncGeneratorPrototype%). 231 | 1. Perform ! DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}). 232 | 1. Return _closure_. 233 | 234 | 235 | 236 | AsyncGeneratorExpression : `async` [no LineTerminator here] `function` `*` BindingIdentifier `(` FormalParameters `)` `{` AsyncGeneratorBody `}` 237 | 238 | 239 | 1. If the function code for this |AsyncGeneratorExpression| is strict mode code, let _strict_ be *true*. Otherwise let _strict_ be *false*. 240 | 1. Let _scope_ be the running execution context's LexicalEnvironment. 241 | 1. Let _funcEnv_ be ! NewDeclarativeEnvironment(_scope_). 242 | 1. Let _envRec_ be _funcEnv_'s EnvironmentRecord. 243 | 1. Let _name_ be StringValue of |BindingIdentifier|. 244 | 1. Perform ! _envRec_.CreateImmutableBinding(_name_). 245 | 1. Let _closure_ be ! AsyncGeneratorFunctionCreate(~Normal~, |FormalParameters|, |AsyncGeneratorBody|, _funcEnv_, _strict_). 246 | 1. Let _prototype_ be ! ObjectCreate(%AsyncGeneratorPrototype%). 247 | 1. Perform ! DefinePropertyOrThrow(_closure_, `"prototype"`, PropertyDescriptor{[[Value]]: _prototype_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false*}). 248 | 1. Perform ! SetFunctionName(_closure_, _name_). 249 | 1. Perform ! _envRec_.InitializeBinding(_name_, _closure_). 250 | 1. Return _closure_. 251 | 252 | 253 |

The |BindingIdentifier| in an |AsyncGeneratorExpression| can be referenced from inside the |AsyncGeneratorExpression|'s |AsyncGeneratorBody| to allow the generator code to call itself recursively. However, unlike in an |AsyncGeneratorDeclaration|, the |BindingIdentifier| in an |AsyncGeneratorExpression| cannot be referenced from and does not affect the scope enclosing the |AsyncGeneratorExpression|.

254 |
255 |
256 | -------------------------------------------------------------------------------- /spec/iteration.html: -------------------------------------------------------------------------------- 1 | 2 |

Common Iteration Interfaces

3 | 4 | 5 |

The AsyncIterable Interface

6 |

The AsyncIterable interface includes the properties described in :

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
PropertyValueRequirements
`@@asyncIterator`A function that returns an AsyncIterator object.The returned object must conform to the AsyncIterator interface.
22 |
23 |
24 | 25 | 26 |

The AsyncIterator Interface

27 |

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

28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 |
PropertyValueRequirements
`next`A function that returns a promise for an IteratorResult object. 40 |

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.

41 | 42 |

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.

43 |
47 |
48 | 49 |

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.

50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 67 | 68 | 69 | 70 | 71 | 76 | 77 | 78 |
PropertyValueRequirements
`return`A function that returns a promise for an IteratorResult object. 63 |

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.

64 | 65 |

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.

66 |
`throw`A function that returns a promise for an IteratorResult object. 72 |

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.

73 | 74 |

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.

75 |
79 |
80 | 81 |

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.

82 |
83 |
84 |
85 | 86 | 87 |

The %AsyncIteratorPrototype% Object

88 |

The value of the [[Prototype]] internal slot of the %AsyncIteratorPrototype% object is the intrinsic object %ObjectPrototype%. The %AsyncIteratorPrototype% object is an ordinary object. The initial value of the [[Extensible]] internal slot of the %AsyncIteratorPrototype% object is *true*.

89 | 90 |

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.

91 |
92 | 93 | 94 |

%AsyncIteratorPrototype% [ @@asyncIterator ] ( )

95 |

The following steps are taken:

96 | 97 | 1. Return the *this* value. 98 | 99 |

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

100 |
101 |
102 | 103 | 104 |

Async-from-Sync Iterator Objects

105 |

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.

106 | 107 | 108 |

CreateAsyncFromSyncIterator(_syncIteratorRecord_) Abstract Operation

109 |

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

110 | 111 | 1. Let _asyncIterator_ be ! ObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »). 112 | 1. Set _asyncIterator_.[[SyncIteratorRecord]] to _syncIteratorRecord_. 113 | 1. Return ? GetIterator(_asyncIterator_, ~async~). 114 | 115 |
116 | 117 | 118 |

The %AsyncFromSyncIteratorPrototype% Object

119 |

All Async-from-Sync Iterator Objects inherit properties from the %AsyncFromSyncIteratorPrototype% intrinsic object. The %AsyncFromSyncIteratorPrototype% object is an ordinary object and its [[Prototype]] internal slot is the %AsyncIteratorPrototype% intrinsic object. In addition, %AsyncFromSyncIteratorPrototype% has the following properties:

120 | 121 | 122 |

%AsyncFromSyncIteratorPrototype%.next ( _value_ )

123 | 124 | 1. Let _O_ be the *this* value. 125 | 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). 126 | 1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIteratorRecord]] internal slot, then 127 | 1. Let _badIteratorError_ be a new *TypeError* exception. 128 | 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _badIteratorError_ »). 129 | 1. Return _promiseCapability_.[[Promise]]. 130 | 1. Let _syncIteratorRecord_ be _O_.[[SyncIteratorRecord]]. 131 | 1. Let _nextResult_ be IteratorNext(_syncIteratorRecord_, _value_). 132 | 1. IfAbruptRejectPromise(_nextResult_, _promiseCapability_). 133 | 1. Let _nextDone_ be IteratorComplete(_nextResult_). 134 | 1. IfAbruptRejectPromise(_nextDone_, _promiseCapability_). 135 | 1. Let _nextValue_ be IteratorValue(_nextResult_). 136 | 1. IfAbruptRejectPromise(_nextValue_, _promiseCapability_). 137 | 1. Let _valueWrapperCapability_ be ! NewPromiseCapability(%Promise%). 138 | 1. Perform ! Call(_valueWrapperCapability_.[[Resolve]], *undefined*, « _nextValue_ »). 139 | 1. Let _onFulfilled_ be a new built-in function object as defined in . 140 | 1. Set _onFulfilled_.[[Done]] to _nextDone_. 141 | 1. Perform ! PerformPromiseThen(_valueWrapperCapability_.[[Promise]], _onFulfilled_, *undefined*, _promiseCapability_). 142 | 1. Return _promiseCapability_.[[Promise]]. 143 | 144 |
145 | 146 | 147 |

%AsyncFromSyncIteratorPrototype%.return ( _value_ )

148 | 149 | 150 | 1. Let _O_ be the *this* value. 151 | 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). 152 | 1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIteratorRecord]] internal slot, then 153 | 1. Let _badIteratorError_ be a new *TypeError* exception. 154 | 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _badIteratorError_ »). 155 | 1. Return _promiseCapability_.[[Promise]]. 156 | 1. Let _syncIterator_ be _O_.[[SyncIteratorRecord]].[[Iterator]]. 157 | 1. Let _return_ be GetMethod(_syncIterator_, `"return"`). 158 | 1. IfAbruptRejectPromise(_return_, _promiseCapability_). 159 | 1. If _return_ is *undefined*, then 160 | 1. Let _iterResult_ be ! CreateIterResultObject(_value_, *true*). 161 | 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _iterResult_ »). 162 | 1. Return _promiseCapability_.[[Promise]]. 163 | 1. Let _returnResult_ be Call(_return_, _syncIterator_, « _value_ »). 164 | 1. IfAbruptRejectPromise(_returnResult_, _promiseCapability_). 165 | 1. If Type(_returnResult_) is not *Object*, 166 | 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « a *TypeError* exception »). 167 | 1. Return _promiseCapability_.[[Promise]]. 168 | 1. Let _returnDone_ be IteratorComplete(_returnResult_). 169 | 1. IfAbruptRejectPromise(_returnDone_, _promiseCapability_). 170 | 1. Let _returnValue_ be IteratorValue(_returnResult_). 171 | 1. IfAbruptRejectPromise(_returnValue_, _promiseCapability_). 172 | 1. Let _valueWrapperCapability_ be ! NewPromiseCapability(%Promise%). 173 | 1. Perform ! Call(_valueWrapperCapability_.[[Resolve]], *undefined*, « _returnValue_ »). 174 | 1. Let _onFulfilled_ be a new built-in function object as defined in . 175 | 1. Set _onFulfilled_.[[Done]] to _returnDone_. 176 | 1. Perform ! PerformPromiseThen(_valueWrapperCapability_.[[Promise]], _onFulfilled_, *undefined*, _promiseCapability_). 177 | 1. Return _promiseCapability_.[[Promise]]. 178 | 179 |
180 | 181 | 182 |

%AsyncFromSyncIteratorPrototype%.throw ( _value_ )

183 | 184 | 185 | 1. Let _O_ be the *this* value. 186 | 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). 187 | 1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIteratorRecord]] internal slot, then 188 | 1. Let _badIteratorError_ be a new *TypeError* exception. 189 | 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _badIteratorError_ »). 190 | 1. Return _promiseCapability_.[[Promise]]. 191 | 1. Let _syncIterator_ be _O_.[[SyncIteratorRecord]].[[Iterator]]. 192 | 1. Let _throw_ be GetMethod(_syncIterator_, `"throw"`). 193 | 1. IfAbruptRejectPromise(_throw_, _promiseCapability_). 194 | 1. If _throw_ is *undefined*, then 195 | 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _value_ »). 196 | 1. Return _promiseCapability_.[[Promise]]. 197 | 1. Let _throwResult_ be Call(_throw_, _syncIterator_, « _value_ »). 198 | 1. IfAbruptRejectPromise(_throwResult_, _promiseCapability_). 199 | 1. If Type(_throwResult_) is not *Object*, 200 | 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « a *TypeError* exception »). 201 | 1. Return _promiseCapability_.[[Promise]]. 202 | 1. Let _throwDone_ be IteratorComplete(_throwResult_). 203 | 1. IfAbruptRejectPromise(_throwDone_, _promiseCapability_). 204 | 1. Let _throwValue_ be IteratorValue(_throwResult_). 205 | 1. IfAbruptRejectPromise(_throwValue_, _promiseCapability_). 206 | 1. Let _valueWrapperCapability_ be ! NewPromiseCapability(%Promise%). 207 | 1. Perform ! Call(_valueWrapperCapability_.[[Resolve]], *undefined*, « _throwValue_ »). 208 | 1. Let _onFulfilled_ be a new built-in function object as defined in . 209 | 1. Set _onFulfilled_.[[Done]] to _throwDone_. 210 | 1. Perform ! PerformPromiseThen(_valueWrapperCapability_.[[Promise]], _onFulfilled_, *undefined*, _promiseCapability_). 211 | 1. Return _promiseCapability_.[[Promise]]. 212 | 213 |
214 | 215 | 216 |

%AsyncFromSyncIteratorPrototype% [ @@toStringTag ]

217 |

The initial value of the @@toStringTag property is the String value `"Async-from-Sync Iterator"`.

218 |

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

219 |
220 | 221 | 222 |

Async-from-Sync Iterator Value Unwrap Functions

223 | 224 |

An async-from-sync iterator value unwrap function is an anonymous built-in function that is used by methods of %AsyncFromSyncIteratorPrototype% when processing the `value` field 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 iterator value unwrap function has a [[Done]] internal slot.

225 | 226 |

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

227 | 228 | 229 | 1. Return ! CreateIterResultObject(_value_, _F_.[[Done]]). 230 | 231 |
232 |
233 | 234 | 235 |

Properties of Async-from-Sync Iterator Instances

236 |

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 .

237 | 238 | 239 | 240 | 241 | 244 | 247 | 248 | 249 | 250 | 251 | 254 | 257 | 258 | 259 |
242 | Internal Slot 243 | 245 | Description 246 |
252 | [[SyncIteratorRecord]] 253 | 255 | A Record, of the type returned by GetIterator, representing the original synchronous iterator which is being adapted. 256 |
260 |
261 |
262 |
263 | -------------------------------------------------------------------------------- /spec/iteration-statements-patch.html: -------------------------------------------------------------------------------- 1 |

Syntax

2 | 3 | IterationStatement[Yield, Await, Return] : 4 | `do` Statement[?Yield, ?Await, ?Return] `while` `(` Expression[+In, ?Yield, ?Await] `)` `;` 5 | `while` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 6 | `for` `(` [lookahead <! {`let [`}] Expression[~In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] 7 | `for` `(` `var` VariableDeclarationList[~In, ?Yield, ?Await] `;` Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] 8 | `for` `(` LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] 9 | `for` `(` [lookahead <! {`let [`}] LeftHandSideExpression[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 10 | `for` `(` `var` ForBinding[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 11 | `for` `(` ForDeclaration[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 12 | `for` `(` [lookahead != `let` ] LeftHandSideExpression[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 13 | `for` `(` `var` ForBinding[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 14 | `for` `(` ForDeclaration[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 15 | [+Await] `for` `await` `(` [lookahead != `let` ] LeftHandSideExpression[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 16 | [+Await] `for` `await` `(` `var` ForBinding[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 17 | [+Await] `for` `await` `(` ForDeclaration[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] 18 | 19 | ForDeclaration[Yield, Await] : 20 | LetOrConst ForBinding[?Yield, ?Await] 21 | 22 | ForBinding[Yield, Await] : 23 | BindingIdentifier[?Yield, ?Await] 24 | BindingPattern[?Yield, ?Await] 25 | 26 | 27 |

This section is extended by Annex .

28 |
29 | 30 | 31 |

Semantics

32 | 33 | 34 | 35 |

Static Semantics: Early Errors

36 | 37 | IterationStatement : 38 | `do` Statement `while` `(` Expression `)` `;` 39 | `while` `(` Expression `)` Statement 40 | `for` `(` Expression? `;` Expression? `;` Expression? `)` Statement 41 | `for` `(` `var` VariableDeclarationList `;` Expression? `;` Expression? `)` Statement 42 | `for` `(` LexicalDeclaration Expression? `;` Expression? `)` Statement 43 | `for` `(` LeftHandSideExpression `in` Expression `)` Statement 44 | `for` `(` `var` ForBinding `in` Expression `)` Statement 45 | `for` `(` ForDeclaration `in` Expression `)` Statement 46 | `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 47 | `for` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 48 | `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement 49 | `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 50 | `for` `await` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 51 | `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement 52 | 53 |
    54 |
  • 55 | It is a Syntax Error if IsLabelledFunction(|Statement|) is *true*. 56 |
  • 57 |
58 | 59 |

It is only necessary to apply this rule if the extension specified in is implemented.

60 |
61 |
62 |
63 | 64 | 65 |

The `for`-`in` and, `for`-`of`, and `for`-`await`-`of` Statements

66 | 67 | 68 |

Static Semantics: Early Errors

69 | 70 | IterationStatement : 71 | `for` `(` LeftHandSideExpression `in` Expression `)` Statement 72 | `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 73 | `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 74 | 75 |
    76 |
  • 77 | It is a Syntax Error if |LeftHandSideExpression| is either an |ObjectLiteral| or an |ArrayLiteral| and if the lexical token sequence matched by |LeftHandSideExpression| cannot be parsed with no tokens left over using |AssignmentPattern| as the goal symbol. 78 |
  • 79 |
80 |

If |LeftHandSideExpression| is either an |ObjectLiteral| or an |ArrayLiteral| and if the lexical token sequence matched by |LeftHandSideExpression| can be parsed with no tokens left over using |AssignmentPattern| as the goal symbol then the following rules are not applied. Instead, the Early Error rules for |AssignmentPattern| are used.

81 |
    82 |
  • 83 | It is a Syntax Error if IsValidSimpleAssignmentTarget of |LeftHandSideExpression| is *false*. 84 |
  • 85 |
  • 86 | It is a Syntax Error if the |LeftHandSideExpression| is CoverParenthesizedExpressionAndArrowParameterList : `(` Expression `)` and |Expression| derives a production that would produce a Syntax Error according to these rules if that production is substituted for |LeftHandSideExpression|. This rule is recursively applied. 87 |
  • 88 |
89 | 90 |

The last rule means that the other rules are applied even if parentheses surround |Expression|.

91 |
92 | 93 | IterationStatement : 94 | `for` `(` ForDeclaration `in` Expression `)` Statement 95 | `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement 96 | `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement 97 | 98 |
    99 |
  • 100 | It is a Syntax Error if the BoundNames of |ForDeclaration| contains `"let"`. 101 |
  • 102 |
  • 103 | It is a Syntax Error if any element of the BoundNames of |ForDeclaration| also occurs in the VarDeclaredNames of |Statement|. 104 |
  • 105 |
  • 106 | It is a Syntax Error if the BoundNames of |ForDeclaration| contains any duplicate entries. 107 |
  • 108 |
109 |
110 | 111 | 112 |

Static Semantics: ContainsDuplicateLabels

113 |

With argument _labelSet_.

114 | 115 | 116 | IterationStatement : 117 | `for` `(` LeftHandSideExpression `in` Expression `)` Statement 118 | `for` `(` `var` ForBinding `in` Expression `)` Statement 119 | `for` `(` ForDeclaration `in` Expression `)` Statement 120 | `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 121 | `for` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 122 | `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement 123 | `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 124 | `for` `await` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 125 | `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement 126 | 127 | 128 | 1. Return ContainsDuplicateLabels of |Statement| with argument _labelSet_. 129 | 130 | 131 |

This section is extended by Annex .

132 |
133 |
134 | 135 | 136 |

Static Semantics: ContainsUndefinedBreakTarget

137 |

With argument _labelSet_.

138 | 139 | 140 | IterationStatement : 141 | `for` `(` LeftHandSideExpression `in` Expression `)` Statement 142 | `for` `(` `var` ForBinding `in` Expression `)` Statement 143 | `for` `(` ForDeclaration `in` Expression `)` Statement 144 | `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 145 | `for` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 146 | `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement 147 | `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 148 | `for` `await` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 149 | `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement 150 | 151 | 152 | 1. Return ContainsUndefinedBreakTarget of |Statement| with argument _labelSet_. 153 | 154 | 155 |

This section is extended by Annex .

156 |
157 |
158 | 159 | 160 |

Static Semantics: ContainsUndefinedContinueTarget

161 |

With arguments _iterationSet_ and _labelSet_.

162 | 163 | 164 | IterationStatement : 165 | `for` `(` LeftHandSideExpression `in` Expression `)` Statement 166 | `for` `(` `var` ForBinding `in` Expression `)` Statement 167 | `for` `(` ForDeclaration `in` Expression `)` Statement 168 | `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 169 | `for` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 170 | `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement 171 | `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 172 | `for` `await` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 173 | `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement 174 | 175 | 176 | 1. Return ContainsUndefinedContinueTarget of |Statement| with arguments _iterationSet_ and « ». 177 | 178 | 179 |

This section is extended by Annex .

180 |
181 |
182 | 183 | 184 |

Static Semantics: VarDeclaredNames

185 | 186 | IterationStatement : `for` `(` LeftHandSideExpression `in` Expression `)` Statement 187 | 188 | 1. Return the VarDeclaredNames of |Statement|. 189 | 190 | IterationStatement : `for` `(` `var` ForBinding `in` Expression `)` Statement 191 | 192 | 1. Let _names_ be the BoundNames of |ForBinding|. 193 | 1. Append to _names_ the elements of the VarDeclaredNames of |Statement|. 194 | 1. Return _names_. 195 | 196 | IterationStatement : `for` `(` ForDeclaration `in` Expression `)` Statement 197 | 198 | 1. Return the VarDeclaredNames of |Statement|. 199 | 200 | 201 | IterationStatement : 202 | `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 203 | `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 204 | 205 | 206 | 1. Return the VarDeclaredNames of |Statement|. 207 | 208 | 209 | IterationStatement : 210 | `for` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 211 | `for` `await` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 212 | 213 | 214 | 1. Let _names_ be the BoundNames of |ForBinding|. 215 | 1. Append to _names_ the elements of the VarDeclaredNames of |Statement|. 216 | 1. Return _names_. 217 | 218 | 219 | IterationStatement : 220 | `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement 221 | `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement 222 | 223 | 224 | 1. Return the VarDeclaredNames of |Statement|. 225 | 226 | 227 |

This section is extended by Annex .

228 |
229 |
230 | 231 | 232 |

Static Semantics: VarScopedDeclarations

233 | 234 | IterationStatement : `for` `(` LeftHandSideExpression `in` Expression `)` Statement 235 | 236 | 1. Return the VarScopedDeclarations of |Statement|. 237 | 238 | IterationStatement : `for` `(` `var` ForBinding `in` Expression `)` Statement 239 | 240 | 1. Let _declarations_ be a List containing |ForBinding|. 241 | 1. Append to _declarations_ the elements of the VarScopedDeclarations of |Statement|. 242 | 1. Return _declarations_. 243 | 244 | IterationStatement : `for` `(` ForDeclaration `in` Expression `)` Statement 245 | 246 | 1. Return the VarScopedDeclarations of |Statement|. 247 | 248 | 249 | IterationStatement : 250 | `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 251 | `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 252 | 253 | 254 | 1. Return the VarScopedDeclarations of |Statement|. 255 | 256 | 257 | IterationStatement : 258 | `for` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 259 | `for` `await` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 260 | 261 | 262 | 1. Let _declarations_ be a List containing |ForBinding|. 263 | 1. Append to _declarations_ the elements of the VarScopedDeclarations of |Statement|. 264 | 1. Return _declarations_. 265 | 266 | 267 | IterationStatement : 268 | `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement 269 | `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement 270 | 271 | 272 | 1. Return the VarScopedDeclarations of |Statement|. 273 | 274 | 275 |

This section is extended by Annex .

276 |
277 |
278 | 279 | 280 |

Runtime Semantics: LabelledEvaluation

281 |

With argument _labelSet_.

282 | 283 | 284 | IterationStatement : `for` `(` LeftHandSideExpression `in` Expression `)` Statement 285 | 286 | 1. Let _keyResult_ be ? ForIn/OfHeadEvaluation(« », |Expression|, ~enumerate~). 287 | 1. Return ? ForIn/OfBodyEvaluation(|LeftHandSideExpression|, |Statement|, _keyResult_, ~assignment~, _labelSet_). 288 | 289 | IterationStatement : `for` `(` `var` ForBinding `in` Expression `)` Statement 290 | 291 | 1. Let _keyResult_ be ? ForIn/OfHeadEvaluation(« », |Expression|, ~enumerate~). 292 | 1. Return ? ForIn/OfBodyEvaluation(|ForBinding|, |Statement|, _keyResult_, ~varBinding~, _labelSet_). 293 | 294 | IterationStatement : `for` `(` ForDeclaration `in` Expression `)` Statement 295 | 296 | 1. Let _keyResult_ be the result of performing ? ForIn/OfHeadEvaluation(BoundNames of |ForDeclaration|, |Expression|, ~enumerate~). 297 | 1. Return ? ForIn/OfBodyEvaluation(|ForDeclaration|, |Statement|, _keyResult_, ~lexicalBinding~, _labelSet_). 298 | 299 | IterationStatement : `for` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 300 | 301 | 1. Let _keyResult_ be the result of performing ? ForIn/OfHeadEvaluation(« », |AssignmentExpression|, ~iterate~). 302 | 1. Return ? ForIn/OfBodyEvaluation(|LeftHandSideExpression|, |Statement|, _keyResult_, ~assignment~, _labelSet_). 303 | 304 | IterationStatement : `for` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 305 | 306 | 1. Let _keyResult_ be the result of performing ? ForIn/OfHeadEvaluation(« », |AssignmentExpression|, ~iterate~). 307 | 1. Return ? ForIn/OfBodyEvaluation(|ForBinding|, |Statement|, _keyResult_, ~varBinding~, _labelSet_). 308 | 309 | IterationStatement : `for` `(` ForDeclaration `of` AssignmentExpression `)` Statement 310 | 311 | 1. Let _keyResult_ be the result of performing ? ForIn/OfHeadEvaluation(BoundNames of |ForDeclaration|, |AssignmentExpression|, ~iterate~). 312 | 1. Return ? ForIn/OfBodyEvaluation(|ForDeclaration|, |Statement|, _keyResult_, ~lexicalBinding~, _labelSet_). 313 | 314 | 315 | 316 | IterationStatement : `for` `await` `(` LeftHandSideExpression `of` AssignmentExpression `)` Statement 317 | 318 | 319 | 1. Let _keyResult_ be the result of performing ? ForIn/OfHeadEvaluation(« », |AssignmentExpression|, ~async-iterate~). 320 | 1. Return ? ForIn/OfBodyEvaluation(|LeftHandSideExpression|, |Statement|, _keyResult_, ~assignment~, _labelSet_, ~async~). 321 | 322 | 323 | IterationStatement : `for` `await` `(` `var` ForBinding `of` AssignmentExpression `)` Statement 324 | 325 | 326 | 1. Let _keyResult_ be the result of performing ? ForIn/OfHeadEvaluation(« », |AssignmentExpression|, ~async-iterate~). 327 | 1. Return ? ForIn/OfBodyEvaluation(|ForBinding|, |Statement|, _keyResult_, ~varBinding~, _labelSet_, ~async~). 328 | 329 | 330 | IterationStatement : `for` `await` `(` ForDeclaration `of` AssignmentExpression `)` Statement 331 | 332 | 333 | 1. Let _keyResult_ be the result of performing ? ForIn/OfHeadEvaluation(BoundNames of |ForDeclaration|, |AssignmentExpression|, ~async-iterate~). 334 | 1. Return ? ForIn/OfBodyEvaluation(|ForDeclaration|, |Statement|, _keyResult_, ~lexicalBinding~, _labelSet_, ~async~). 335 | 336 | 337 | 338 |

This section is extended by Annex .

339 |
340 |
341 | 342 | 343 |

Runtime Semantics: ForIn/OfHeadEvaluation ( _TDZnames_, _expr_, _iterationKind_ )

344 |

The abstract operation ForIn/OfHeadEvaluation is called with arguments _TDZnames_, _expr_, and _iterationKind_. The value of _iterationKind_ is either ~enumerate~ or, ~iterate~, or ~async-iterate~.

345 | 346 | 1. Let _oldEnv_ be the running execution context's LexicalEnvironment. 347 | 1. If _TDZnames_ is not an empty List, then 348 | 1. Assert: _TDZnames_ has no duplicate entries. 349 | 1. Let _TDZ_ be ! NewDeclarativeEnvironment(_oldEnv_). 350 | 1. Let _TDZEnvRec_ be _TDZ_'s EnvironmentRecord. 351 | 1. For each string _name_ in _TDZnames_, do 352 | 1. Perform ! _TDZEnvRec_.CreateMutableBinding(_name_, *false*). 353 | 1. Set the running execution context's LexicalEnvironment to _TDZ_. 354 | 1. Let _exprRef_ be the result of evaluating the production that is _expr_. 355 | 1. Set the running execution context's LexicalEnvironment to _oldEnv_. 356 | 1. Let _exprValue_ be ? GetValue(_exprRef_). 357 | 1. If _iterationKind_ is ~enumerate~, then 358 | 1. If _exprValue_.[[Value]] is *null* or *undefined*, then 359 | 1. Return Completion{[[Type]]: ~break~, [[Value]]: ~empty~, [[Target]]: ~empty~}. 360 | 1. Let _obj_ be ? ToObject(_exprValue_). 361 | 1. Return ? _obj_.[[Enumerate]](). 362 | 1. Else, 363 | 1. If _iterationKind_ is ~async-iterate~, let _iteratorHint_ be ~async~. 364 | 1. Else, let _iteratorHint_ be ~normal~. 365 | 1. Return ? GetIterator(_exprValue_, _iteratorHint_). 366 | 367 |
368 | 369 | 370 |

Runtime Semantics: ForIn/OfBodyEvaluation ( _lhs_, _stmt_, _iteratorRecord_, _lhsKind_, _labelSet_ [ , _iteratorKind_ ] )

371 |

The abstract operation ForIn/OfBodyEvaluation is called with arguments _lhs_, _stmt_, _iteratorRecord_, _lhsKind_, and _labelSet_, and optional argument _iteratorKind_. The value of _lhsKind_ is either ~assignment~, ~varBinding~ or ~lexicalBinding~. The value of _iteratorKind_ is either ~normal~ or ~async~.

372 | 373 | 1. If _iteratorKind_ was not passed, let _iteratorKind_ be ~normal~. 374 | 1. Let _oldEnv_ be the running execution context's LexicalEnvironment. 375 | 1. Let _V_ be *undefined*. 376 | 1. Let _destructuring_ be IsDestructuring of _lhs_. 377 | 1. If _destructuring_ is *true* and if _lhsKind_ is ~assignment~, then 378 | 1. Assert: _lhs_ is a |LeftHandSideExpression|. 379 | 1. Let _assignmentPattern_ be the parse of the source text corresponding to _lhs_ using |AssignmentPattern| as the goal symbol. 380 | 1. Repeat 381 | 1. Let _nextResult_ be ? IteratorStep(_iteratorRecord_). 382 | 1. If _nextResult_ is *false*, return NormalCompletion(_V_). 383 | 1. Let _nextResult_ be ? Call(_iteratorRecord_.[[NextMethod]], _iteratorRecord_.[[Iterator]], « »). 384 | 1. If _iteratorKind_ is ~async~, then set _nextResult_ to ? Await(_nextResult_). 385 | 1. If Type(_nextResult_) is not Object, throw a *TypeError* exception. 386 | 1. Let _done_ be ? IteratorComplete(_nextResult_). 387 | 1. If _done_ is *true*, return NormalCompletion(_V_). 388 | 1. Let _nextValue_ be ? IteratorValue(_nextResult_). 389 | 1. If _lhsKind_ is either ~assignment~ or ~varBinding~, then 390 | 1. If _destructuring_ is *false*, then 391 | 1. Let _lhsRef_ be the result of evaluating _lhs_ (it may be evaluated repeatedly). 392 | 1. Else, 393 | 1. Assert: _lhsKind_ is ~lexicalBinding~. 394 | 1. Assert: _lhs_ is a |ForDeclaration|. 395 | 1. Let _iterationEnv_ be NewDeclarativeEnvironment(_oldEnv_). 396 | 1. Perform BindingInstantiation for _lhs_ passing _iterationEnv_ as the argument. 397 | 1. Set the running execution context's LexicalEnvironment to _iterationEnv_. 398 | 1. If _destructuring_ is *false*, then 399 | 1. Assert: _lhs_ binds a single name. 400 | 1. Let _lhsName_ be the sole element of BoundNames of _lhs_. 401 | 1. Let _lhsRef_ be ResolveBinding(_lhsName_). 402 | 1. Assert: _lhsRef_ is not an abrupt completion. 403 | 1. If _destructuring_ is *false*, then 404 | 1. If _lhsRef_ is an abrupt completion, then 405 | 1. Let _status_ be _lhsRef_. 406 | 1. Else if _lhsKind_ is ~lexicalBinding~, then 407 | 1. Let _status_ be InitializeReferencedBinding(_lhsRef_, _nextValue_). 408 | 1. Else, 409 | 1. Let _status_ be PutValue(_lhsRef_, _nextValue_). 410 | 1. Else, 411 | 1. If _lhsKind_ is ~assignment~, then 412 | 1. Let _status_ be the result of performing DestructuringAssignmentEvaluation of _assignmentPattern_ using _nextValue_ as the argument. 413 | 1. Else if _lhsKind_ is ~varBinding~, then 414 | 1. Assert: _lhs_ is a |ForBinding|. 415 | 1. Let _status_ be the result of performing BindingInitialization for _lhs_ passing _nextValue_ and *undefined* as the arguments. 416 | 1. Else, 417 | 1. Assert: _lhsKind_ is ~lexicalBinding~. 418 | 1. Assert: _lhs_ is a |ForDeclaration|. 419 | 1. Let _status_ be the result of performing BindingInitialization for _lhs_ passing _nextValue_ and _iterationEnv_ as arguments. 420 | 1. If _status_ is an abrupt completion, then 421 | 1. Set the running execution context's LexicalEnvironment to _oldEnv_. 422 | 1. If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iteratorRecord_, _status_). 423 | 1. Return ? IteratorClose(_iteratorRecord_, _status_). 424 | 1. Let _result_ be the result of evaluating _stmt_. 425 | 1. Set the running execution context's LexicalEnvironment to _oldEnv_. 426 | 1. If ! LoopContinues(_result_, _labelSet_) is *false*, return ? IteratorClose(_iteratorRecord_, UpdateEmpty(_result_, _V_))then 427 | 1. Let _status_ be UpdateEmpty(_result_, _V_). 428 | 1. If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iteratorRecord_, _status_). 429 | 1. Return ? IteratorClose(_iteratorRecord_, _status_). 430 | 1. If _result_.[[Value]] is not ~empty~, let _V_ be _result_.[[Value]]. 431 | 432 |
433 |
434 | --------------------------------------------------------------------------------