diff --git a/spec.html b/spec.html index 275cd37..ea77a89 100644 --- a/spec.html +++ b/spec.html @@ -23,22 +23,6 @@

AsyncFunctionStart ( _promiseCapability_, _asyncFunctionBody_ )

1. Let _runningContext_ be the running execution context. 1. Let _asyncContext_ be a copy of _runningContext_. 1. Perform ! AsyncBlockStart(_promiseCapability_, _asyncFunctionBody_, _asyncContext_). - 1. Set the code evaluation state of _asyncContext_ such that when evaluation is resumed for that execution context the following steps will be performed: - 1. Let _result_ be the result of evaluating _asyncFunctionBody_. - 1. Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done. - 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. - 1. If _result_.[[Type]] is ~normal~, then - 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, «*undefined*»). - 1. Else if _result_.[[Type]] is ~return~, then - 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, «_result_.[[Value]]»). - 1. Else, - 1. Assert: _result_.[[Type]] is ~throw~. - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, «_result_.[[Value]]»). - 1. Return. - 1. Push _asyncContext_ onto the execution context stack; _asyncContext_ is now the running execution context. - 1. Resume the suspended evaluation of _asyncContext_. Let _result_ be the value returned by the resumed computation. - 1. Assert: When we return here, _asyncContext_ has already been removed from the execution context stack and _runningContext_ is the currently running execution context. - 1. Assert: _result_ is a normal completion with a value of *undefined*. The possible sources of completion values are Await or, if the async function doesn't await anything, the step 3.g above. 1. Return. @@ -46,10 +30,10 @@

AsyncFunctionStart ( _promiseCapability_, _asyncFunctionBody_ )

AsyncBlockStart ( _promiseCapability_, _asyncBody_, _asyncContext_ )

- 1. Assert: _promiseCapability_ is a PromiseCapability Record. - 1. Let _runningContext_ be the running execution context. + 1. Assert: _promiseCapability_ is a PromiseCapability Record. + 1. Let _runningContext_ be the running execution context. 1. Set the code evaluation state of _asyncContext_ such that when evaluation is resumed for that execution context the following steps will be performed: - 1. Let _result_ be the result of evaluating _asyncBody_. + 1. Let _result_ be the result of evaluating _asyncFunctionBody__asyncBody_. 1. Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done. 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. 1. If _result_.[[Type]] is ~normal~, then @@ -63,7 +47,7 @@

AsyncBlockStart ( _promiseCapability_, _asyncBody_, _asyncContext_ )3.g2.g above. @@ -101,10 +85,12 @@

Abstract Module Records

[[Environment]] - Lexical Environment | *undefined* + module Environment Record()Lexical Environment | *undefined* - The Lexical Environment containing the top level bindings for this module. This field is set when the module is linked. + The Environment Record containing the top level bindings for this module. This field is set when the module is linked. + The Lexical Environment containing the top level bindings for this module. This field is + set when the module is linked. @@ -157,8 +143,11 @@

Abstract Module Records

ResolveExport(_exportName_, _resolveSet_) -

Return the binding of a name exported by this module. Bindings are represented by a ResolvedBinding Record, of the form { [[Module]]: Module Record, [[BindingName]]: String }. Return *null* if the name cannot be resolved, or `"ambiguous"` if multiple bindings were found.

+

Return the binding of a name exported by this module. Bindings are represented by a ResolvedBinding Record, of the form { [[Module]]: Module Record, [[BindingName]]: String }. If the export is a Module Namespace Object without a direct binding in any module, [[BindingName]] will be set to "*namespace*". Return null if the name cannot be resolved, or "ambiguous" if multiple bindings were found.

+ Each time this operation is called with a specific exportName, resolveSet pair as arguments it must return the same result if it completes normally. +

This operation must be idempotent if it completes normally. Each time it is called with a specific _exportName_, _resolveSet_ pair as arguments it must return the same result.

+
@@ -186,7 +175,16 @@

Abstract Module Records

Cyclic Module Records

+ The abstract operation InnerModuleLinking takes arguments module (a Cyclic Module Record), + stack, and index. It is used by Link to perform the actual linking process for module, as well + as recursively on all other modules in the dependency graph. The stack and index parameters, as + well as a module's [[DFSIndex]] and [[DFSAncestorIndex]] fields, keep track of the depth-first + search (DFS) traversal. In particular, [[DFSAncestorIndex]] is used to discover strongly + connected components (SCCs), such that all modules in an SCC transition to linked together. It + performs the following steps when called: +

A Cyclic Module Record is used to represent information about a module that can participate in dependency cycles with other modules that are subclasses of the Cyclic Module Record type. Module Records that are not subclasses of the Cyclic Module Record type must not participate in dependency cycles with Source Text Module Records.

+
@@ -441,6 +439,9 @@

Evaluate ( ) Concrete Method

This abstract method performs the following steps (most of the work is done by the auxiliary function InnerModuleEvaluation):

+ + 1. Assert: This call to Evaluate is not happening at the same time as another call to + Evaluate within the surrounding agent. 1. Let _module_ be this Cyclic Module Record. 1. Assert: _module_.[[Status]] is `"linked"` or `"evaluated"`. 1. If _module_.[[Status]] is `"evaluated"`, set _module_ to GetAsyncCycleRoot(_module_). @@ -469,9 +470,17 @@

Evaluate ( ) Concrete Method

InnerModuleEvaluation( _module_, _stack_, _index_ )

+ The abstract operation InnerModuleEvaluation takes arguments module (a Source Text Module + Record), stack, and index. It is used by Evaluate to perform the actual evaluation process + for module, as well as recursively on all other modules in the dependency graph. The stack + and index parameters, as well as module's [[DFSIndex]] and [[DFSAncestorIndex]] fields, are + used the same way as in InnerModuleLinking. It performs the following steps when + called: +

The InnerModuleEvaluation abstract operation is used by Evaluate to perform the actual evaluation process for the Cyclic Module Record _module_, as well as recursively on all other modules in the dependency graph. The _stack_ and _index_ parameters, as well as _module_'s [[DFSIndex]] and [[DFSAncestoreIndex]] fields, are used the same way as in InnerModuleLinking.

This abstract operation performs the following steps:

+
1. If _module_ is not a Cyclic Module Record, then @@ -531,7 +540,7 @@

InnerModuleEvaluation( _module_, _stack_, _index_ )

ExecuteAsyncModule ( _module_ )

- + 1. Assert: _module_.[[Status]] is `"evaluating"` or `"evaluated"`. 1. Assert: _module_.[[Async]] is *true*. 1. Set _module_.[[AsyncEvaluating]] to *true*. @@ -545,28 +554,38 @@

ExecuteAsyncModule ( _module_ )

1. Perform ! PerformPromiseThen(_capability_.[[Promise]], _onFulfilled_, _onRejected_). 1. Perform ! _module_.ExecuteModule(_capability_). 1. Return. +
+

A CallAsyncModuleFulfilled function is an anonymous built-in function with a [[Module]] internal slot. When a CallAsyncModuleFulfilled function is called that expects no arguments it performs the following steps:

+
+ 1. Let _f_ be the active function object. 1. Let _module_ be _f_.[[Module]]. 1. Perform ! AsyncModuleExecutionFulfilled(_module_). 1. Return. + +

A CallAsyncModuleRejected function is an anonymous built-in function with a [[Module]] internal slot. When a CallAsyncModuleRejected function is called with argument _error_ it performs the following steps:

+
+ 1. Let _f_ be the active function object. 1. Let _module_ be _f_.[[Module]]. 1. Perform ! AsyncModuleExecutionRejected(_module_, _error_). 1. Return. +

GetAsyncCycleRoot ( _module_ )

+ 1. Assert: _module_.[[Status]] is `"evaluated"`. 1. If _module_.[[AsyncParentModules]] is an empty List, return _module_. 1. Repeat, while _module_.[[DFSIndex]] is greater than _module_.[[DFSAncestorIndex]], @@ -576,11 +595,13 @@

GetAsyncCycleRoot ( _module_ )

1. Set _module_ to _nextCycleModule_. 1. Assert: _module_.[[DFSIndex]] is equal to _module_.[[DFSAncestorIndex]]. 1. Return _module_. +

AsyncModuleExecutionFulfilled ( _module_ )

+ 1. Assert: _module_.[[Status]] is `"evaluated"`. 1. If _module_.[[AsyncEvaluating]] is *false*, @@ -609,10 +630,12 @@

AsyncModuleExecutionFulfilled ( _module_ )

1. Perform ! Call(_module_.[[TopLevelCapability]].[[Resolve]], *undefined*, «*undefined*»). 1. Return *undefined*.
+

AsyncModuleExecutionRejected ( _module_, _error_ )

+ 1. Assert: _module_.[[Status]] is `"evaluated"`. 1. If _module_.[[AsyncEvaluating]] is *false*, @@ -630,6 +653,7 @@

AsyncModuleExecutionRejected ( _module_, _error_ )

1. Perform ! Call(_module_.[[TopLevelCapability]].[[Reject]], *undefined*, «_error_»). 1. Return *undefined*.
+
@@ -639,10 +663,15 @@

Source Text Module Records

ParseModule ( _sourceText_, _realm_, _hostDefined_ )

+ + The abstract operation ParseModule takes arguments sourceText (ECMAScript source text), realm, and hostDefined. It creates a Source Text Module Record based upon the result of parsing sourceText as a Module. It performs the following steps when called: + +

The abstract operation ParseModule with arguments _sourceText_, _realm_, and _hostDefined_ creates a Source Text Module Record based upon the result of parsing _sourceText_ as a |Module|. ParseModule performs the following steps:

+
1. Assert: _sourceText_ is an ECMAScript source text (see clause ). - 1. Parse _sourceText_ using |Module| as the goal symbol and analyse the parse result for any Early Error conditions. If the parse was successful and no early errors were found, let _body_ be the resulting parse tree. Otherwise, let _body_ be a List of one or more *SyntaxError* or *ReferenceError* objects representing the parsing errors and/or early errors. Parsing and early error detection may be interweaved in an implementation-dependent manner. If more than one parsing error or early error is present, the number and ordering of error objects in the list is implementation-dependent, but at least one must be present. + 1. Parse _sourceText_ using |Module| as the goal symbol and analyse the parse result for any Early Error conditions. If the parse was successful and no early errors were found, let _body_ be the resulting parse tree. Otherwise, let _body_ be a List of one or more *SyntaxError* or *ReferenceError* objects representing the parsing errors and/or early errors. Parsing and early error detection may be interweaved in an implementation-dependent manner. If more than one parsing error or early error is present, the number and ordering of error objects in the list is implementation-dependent, but at least one must be present. 1. If _body_ is a List of errors, return _body_. 1. Let _requestedModules_ be the ModuleRequests of _body_. 1. Let _importEntries_ be ImportEntries of _body_. @@ -658,9 +687,10 @@

ParseModule ( _sourceText_, _realm_, _hostDefined_ )

1. Else, 1. Let _ie_ be the element of _importEntries_ whose [[LocalName]] is the same as _ee_.[[LocalName]]. 1. If _ie_.[[ImportName]] is `"*"`, then - 1. Assert: This is a re-export of an imported module namespace object. + 1. NOTEAssert: This is a re-export of an imported module namespace object. 1. Append _ee_ to _localExportEntries_. 1. Else this is a re-export of a single name, + 1. NOTE: This is a re-export of a single name. 1. Append the ExportEntry Record { [[ModuleRequest]]: _ie_.[[ModuleRequest]], [[ImportName]]: _ie_.[[ImportName]], [[LocalName]]: *null*, [[ExportName]]: _ee_.[[ExportName]] } to _indirectExportEntries_. 1. Else if _ee_.[[ImportName]] is `"*"`, then 1. Append _ee_ to _starExportEntries_. @@ -676,7 +706,7 @@

ParseModule ( _sourceText_, _realm_, _hostDefined_ )

-

ExecuteModule ( [ _capability_ ] )

+

ExecuteModule ( [ _capability_ ] ) Concrete Method

The ExecuteModule concrete method of a Source Text Module Record implements the corresponding Cyclic Module Record abstract method.

@@ -684,22 +714,28 @@

ExecuteModule ( [ _capability_ ] )

1. Let _module_ be this Source Text Module Record. - 1. Let _moduleCxt_ be a new ECMAScript code execution context. - 1. Set the Function of _moduleCxt_ to *null*. - 1. Assert: _module_.[[Realm]] is not *undefined*. - 1. Set the Realm of _moduleCxt_ to _module_.[[Realm]]. - 1. Set the ScriptOrModule of _moduleCxt_ to _module_. - 1. Assert: _module_ has been linked and declarations in its module environment have been linked. - 1. Set the VariableEnvironment of _moduleCxt_ to _module_.[[Environment]]. - 1. Set the LexicalEnvironment of _moduleCxt_ to _module_.[[Environment]]. + 1. Let _moduleCxt_ be a new ECMAScript code execution context. + 1. Set the Function of _moduleCxt_ to *null*. + 1. Assert: _module_.[[Realm]] is not *undefined*. + 1. Set the Realm of _moduleCxt_ to _module_.[[Realm]]. + 1. Set the ScriptOrModule of _moduleCxt_ to _module_. + 1. Assert: _module_ has been linked and declarations in its module environment have been linked. + 1. Set the VariableEnvironment of _moduleCxt_ to _module_.[[Environment]]. + 1. Set the LexicalEnvironment of _moduleCxt_ to _module_.[[Environment]]. 1. Suspend the currently running execution context. + 1. Let moduleContext be module.[[Context]]. + 1. Push moduleContext onto the execution context stack; moduleContext is now the running execution context. + 1. Let result be the result of evaluating module.[[ECMAScriptCode]]. + 1. Suspend moduleContext and remove it from the execution context stack. + 1. Resume the context that is now on the top of the execution context stack as the running execution context. + 1. Return Completion(result). 1. If _module_.[[Async]] is *false*, then 1. Assert: _capability_ was not provided. - 1. Push _moduleCxt_ on to the execution context stack; _moduleCxt_ is now the running execution context. - 1. Let _result_ be the result of evaluating _module_.[[ECMAScriptCode]]. - 1. Suspend _moduleCxt_ and remove it from the execution context stack. - 1. Resume the context that is now on the top of the execution context stack as the running execution context. - 1. Return Completion(_result_). + 1. Push _moduleCxt_ on to the execution context stack; _moduleCxt_ is now the running execution context. + 1. Let _result_ be the result of evaluating _module_.[[ECMAScriptCode]]. + 1. Suspend _moduleCxt_ and remove it from the execution context stack. + 1. Resume the context that is now on the top of the execution context stack as the running execution context. + 1. Return Completion(_result_). 1. Otherwise, 1. Assert: _capability_ is a PromiseCapability Record. 1. Perform ! AsyncBlockStart(_capability_, _module_.[[ECMAScriptCode]], _moduleCxt_). @@ -709,7 +745,8 @@

ExecuteModule ( [ _capability_ ] )

-

Example Source Text Module Record Graphs

+

Example Cyclic Module Record GraphsExample Source Text Module Record + Graphs

This non-normative section gives a series of examples of the linking and evaluation of a few common module graphs, with a specific focus on how errors can occur.