Skip to content
This repository has been archived by the owner on Aug 29, 2021. It is now read-only.

Promisify up through source text module record's Evaluate() #15

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 110 additions & 61 deletions spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,77 +40,126 @@ <h1><ins>AsyncBlockStart ( _promiseCapability_, _asyncBody_, _asyncContext_ )</i
</emu-alg>
</emu-clause>

<emu-clause id="sec-innermoduleevaluation" aoid="InnerModuleEvaluation">
<h1>InnerModuleEvaluation( _module_, _stack_, _index_ )</h1>
<emu-clause id="sec-moduleevaluation">
<h1>Evaluate( ) Concrete Method</h1>

<p>The InnerModuleEvaluation abstract operation is used by Evaluate to perform the actual evaluation process for the Source Text 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 InnerModuleInstantiation.</p>
<p>The Evaluate concrete method of a Source Text Module Record implements the corresponding Module Record abstract method.</p>
<p><ins>By the time the promise returned by Evaluate settles, </ins>Evaluate transitions this module's [[Status]] from `"instantiated"` to `"evaluated"`.</p>

<p>This abstract operation performs the following steps:</p>
<p><del>If execution results in an exception, that exception is recorded in the [[EvaluationError]] field and rethrown by future invocations of Evaluate.</del></p>

<p><ins>If execution results in a rejected promise, the promise's rejection reason is recorded in the [[EvaluationError]] field. Future invocations of Evaluate will then return a new promise rejected with that same rejection reason.</ins></p>

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

<emu-alg>
1. If _module_ is not a Source Text Module Record, then
1. Perform ? _module_.Evaluate().
1. Return _index_.
1. If _module_.[[Status]] is `"evaluated"`, then
1. If _module_.[[EvaluationError]] is *undefined*, return _index_.
1. Otherwise return _module_.[[EvaluationError]].
1. If _module_.[[Status]] is `"evaluating"`, return _index_.
1. Assert: _module_.[[Status]] is `"instantiated"`.
1. Set _module_.[[Status]] to `"evaluating"`.
1. Set _module_.[[DFSIndex]] to _index_.
1. Set _module_.[[DFSAncestorIndex]] to _index_.
1. Set _index_ to _index_ + 1.
1. Append _module_ to _stack_.
1. For each String _required_ that is an element of _module_.[[RequestedModules]], do
1. Let _requiredModule_ be ! HostResolveImportedModule(_module_, _required_).
1. NOTE: Instantiate must be completed successfully prior to invoking this method, so every requested module is guaranteed to resolve successfully.
1. Set _index_ to ? InnerModuleEvaluation(_requiredModule_, _stack_, _index_).
1. Assert: _requiredModule_.[[Status]] is either `"evaluating"` or `"evaluated"`.
1. Assert: _requiredModule_.[[Status]] is `"evaluating"` if and only if _requiredModule_ is in _stack_.
1. If _requiredModule_.[[Status]] is `"evaluating"`, then
1. Assert: _requiredModule_ is a Source Text Module Record.
1. Set _module_.[[DFSAncestorIndex]] to min(_module_.[[DFSAncestorIndex]], _requiredModule_.[[DFSAncestorIndex]]).
1. Perform ? ModuleExecution(_module_).
1. Assert: _module_ occurs exactly once in _stack_.
1. Assert: _module_.[[DFSAncestorIndex]] is less than or equal to _module_.[[DFSIndex]].
1. If _module_.[[DFSAncestorIndex]] equals _module_.[[DFSIndex]], then
1. Let _done_ be *false*.
1. Repeat, while _done_ is *false*,
1. Let _requiredModule_ be the last element in _stack_.
1. Remove the last element of _stack_.
1. Set _requiredModule_.[[Status]] to `"evaluated"`.
1. If _requiredModule_ and _module_ are the same Module Record, set _done_ to *true*.
1. Return _index_.
1. Let _module_ be this Source Text Module Record.
1. Assert: _module_.[[Status]] is `"instantiated"` or `"evaluated"`.
1. <ins>Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).</ins>
1. Let _stack_ be a new empty List.
1. Let _result_ be <ins>Await(</ins>InnerModuleEvaluation(_module_, _stack_, 0)<ins>)</ins>.
1. If _result_ is an abrupt completion, then
1. For each module _m_ in _stack_, do
1. Assert: _m_.[[Status]] is `"evaluating"`.
1. Set _m_.[[Status]] to `"evaluated"`.
1. Set _m_.[[EvaluationError]] to _result_.
1. Assert: _module_.[[Status]] is `"evaluated"` and _module_.[[EvaluationError]] is _result_.
1. <del>Return _result_.</del>
1. <ins>Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, &laquo;_result_.[[Value]]&raquo;).</ins>
1. <ins>Return _promiseCapability_.[[Promise]].</ins>
1. Assert: _module_.[[Status]] is `"evaluated"` and _module_.[[EvaluationError]] is *undefined*.
1. Assert: _stack_ is empty.
1. <del>Return *undefined*.</del>
1. <ins>Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, &laquo;*undefined*&raquo;).</ins>
1. <ins>Return _promiseCapability_.[[Promise]].</ins>
</emu-alg>
</emu-clause>

<emu-clause id="sec-moduleexecution" aoid="ModuleExecution">
<h1>ModuleExecution( _module_ )</h1>
<emu-clause id="sec-innermoduleevaluation" aoid="InnerModuleEvaluation">
<h1>InnerModuleEvaluation( _module_, _stack_, _index_ )</h1>

<p>The ModuleExecution abstract operation is used by InnerModuleEvaluation to initialize the execution context of the module and evaluate the module's code within it.</p>
<p>The InnerModuleEvaluation abstract operation is used by Evaluate to perform the actual evaluation process for the Source Text 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 InnerModuleInstantiation.</p>

<p>This abstract operation performs the following steps:</p>
<p>This abstract operation performs the following steps:</p>

<emu-alg>
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 instantiated.
1. Set the VariableEnvironment of _moduleCxt_ to _module_.[[Environment]].
1. Set the LexicalEnvironment of _moduleCxt_ to _module_.[[Environment]].
1. <ins>Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).</ins>
1. Suspend the currently running execution context.
1. <ins>Perform ! AsyncBlockStart(_promiseCapability_, _module_.[[ECMAScriptCode]], _moduleCxt_).</ins>
1. <del>Push _moduleCxt_ on to the execution context stack; _moduleCxt_ is now the running execution context.</del>
1. <del>Let _result_ be the result of evaluating _module_.[[ECMAScriptCode]].</del>
1. <del>Suspend _moduleCxt_ and remove it from the execution context stack.</del>
1. Resume the context that is now on the top of the execution context stack as the running execution context.
1. Return Completion(<del>_result_</del><ins>_promiseCapability_.[[Promise]]</ins>).
</emu-alg>
</emu-clause>
<emu-alg>
1. <ins>Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).</ins>
1. If _module_ is not a Source Text Module Record, then
1. <del>Perform _module_.Evaluate()</del>.
1. <del>Return _index_.</del>
1. <ins>Let _evaluateResult_ be Await(! _module_.Evaluate())</ins>
1. <ins>If _evaluateResult_ is an abrupt completion, perform ! Call(_promiseCapability_.[[Reject]], *undefined*, &laquo;_evaluateResult_.[[Value]]&raquo;).</ins>
1. <ins>Otherwise, perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, &laquo;_index_&raquo;).</ins>
1. <ins>Return _promiseCapability_.[[Promise]].</ins>
1. If _module_.[[Status]] is `"evaluated"`, then
1. <del>If _module_.[[EvaluationError]] is *undefined*, return _index_.</del>
1. <del>Otherwise return _module_.[[EvaluationError]].</del>
1. <ins>If _module_.[[EvaluationError]] is an abrupt completion, perform ! Call(_promiseCapability_.[[Reject]], *undefined*, &laquo;_module_.[[EvaluationError]].[[Value]]&raquo;).</ins>
1. <ins>Otherwise, perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, &laquo;_index_&raquo;).</ins>
1. <ins>Return _promiseCapability_.[[Promise]]</ins>
1. If _module_.[[Status]] is `"evaluating"`, return _index_.
1. Assert: _module_.[[Status]] is `"instantiated"`.
1. Set _module_.[[Status]] to `"evaluating"`.
1. Set _module_.[[DFSIndex]] to _index_.
1. Set _module_.[[DFSAncestorIndex]] to _index_.
1. Set _index_ to _index_ + 1.
1. Append _module_ to _stack_.
1. For each String _required_ that is an element of _module_.[[RequestedModules]], do
1. Let _requiredModule_ be ! HostResolveImportedModule(_module_, _required_).
1. NOTE: Instantiate must be completed successfully prior to invoking this method, so every requested module is guaranteed to resolve successfully.
1. <del>Set _index_ to ? InnerModuleEvaluation(_requiredModule_, _stack_, _index_).</del>
1. <ins>Let _childResult_ be Await(! InnerModuleEvaluation(_requiredModule_, _stack_, _index_).</ins>
1. <ins>IfAbruptRejectPromise(_childResult_, _promiseCapability_).
1. Assert: _requiredModule_.[[Status]] is either `"evaluating"` or `"evaluated"`.
1. Assert: _requiredModule_.[[Status]] is `"evaluating"` if and only if _requiredModule_ is in _stack_.
1. If _requiredModule_.[[Status]] is `"evaluating"`, then
1. Assert: _requiredModule_ is a Source Text Module Record.
1. Set _module_.[[DFSAncestorIndex]] to min(_module_.[[DFSAncestorIndex]], _requiredModule_.[[DFSAncestorIndex]]).
1. <del>Perform ? ModuleExecution(_module_).</del>
1. <ins>Let _executionResult_ be Await(! ModuleExecution(_module_)).</ins>
1. <ins>IfAbruptRejectPromise(_executionResult_, _promiseCapability_).
1. Assert: _module_ occurs exactly once in _stack_.
1. Assert: _module_.[[DFSAncestorIndex]] is less than or equal to _module_.[[DFSIndex]].
1. If _module_.[[DFSAncestorIndex]] equals _module_.[[DFSIndex]], then
1. Let _done_ be *false*.
1. Repeat, while _done_ is *false*,
1. Let _requiredModule_ be the last element in _stack_.
1. Remove the last element of _stack_.
1. Set _requiredModule_.[[Status]] to `"evaluated"`.
1. If _requiredModule_ and _module_ are the same Module Record, set _done_ to *true*.
1. <del>Return _index_.</del>
1. <ins>Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, &laquo;_index_&raquo;).</ins>
1. <ins>Return _promiseCapability_.[[Promise]]</ins>
</emu-alg>
</emu-clause>

<emu-clause id="sec-moduleexecution" aoid="ModuleExecution">
<h1>ModuleExecution( _module_ )</h1>

<p>The ModuleExecution abstract operation is used by InnerModuleEvaluation to initialize the execution context of the module and evaluate the module's code within it.</p>

<p>This abstract operation performs the following steps:</p>

<emu-alg>
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 instantiated.
1. Set the VariableEnvironment of _moduleCxt_ to _module_.[[Environment]].
1. Set the LexicalEnvironment of _moduleCxt_ to _module_.[[Environment]].
1. <ins>Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).</ins>
1. Suspend the currently running execution context.
1. <ins>Perform ! AsyncBlockStart(_promiseCapability_, _module_.[[ECMAScriptCode]], _moduleCxt_).</ins>
1. <del>Push _moduleCxt_ on to the execution context stack; _moduleCxt_ is now the running execution context.</del>
1. <del>Let _result_ be the result of evaluating _module_.[[ECMAScriptCode]].</del>
1. <del>Suspend _moduleCxt_ and remove it from the execution context stack.</del>
1. Resume the context that is now on the top of the execution context stack as the running execution context.
1. <del>Return Completion(_result_).</del>
1. <ins>Return _promiseCapability_.[[Promise]].</ins>
</emu-alg>
</emu-clause>
</emu-clause>

<emu-clause id="sec-async-functions-abstract-operations-async-function-start" aoid="AsyncFunctionStart">
<h1>AsyncFunctionStart ( _promiseCapability_, _asyncFunctionBody_ )</h1>
Expand Down