-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Editorial: do not use "Return" to transfer control between execution contexts #2429
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4048,23 +4048,25 @@ <h1>Await</h1> | |
1. Let _prevContext_ be the running execution context. | ||
1. Suspend _prevContext_. | ||
1. Push _asyncContext_ onto the execution context stack; _asyncContext_ is now the running execution context. | ||
1. Resume the suspended evaluation of _asyncContext_ using NormalCompletion(_value_) as the result of the operation that suspended it. | ||
1. Resume the suspended evaluation of _asyncContext_ with NormalCompletion(_value_). | ||
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. | ||
1. Return *undefined*. | ||
1. Let _onFulfilled_ be ! CreateBuiltinFunction(_fulfilledClosure_, 1, *""*, « »). | ||
1. Let _rejectedClosure_ be a new Abstract Closure with parameters (_reason_) that captures _asyncContext_ and performs the following steps when called: | ||
1. Let _prevContext_ be the running execution context. | ||
1. Suspend _prevContext_. | ||
1. Push _asyncContext_ onto the execution context stack; _asyncContext_ is now the running execution context. | ||
1. Resume the suspended evaluation of _asyncContext_ using ThrowCompletion(_reason_) as the result of the operation that suspended it. | ||
1. Resume the suspended evaluation of _asyncContext_ with ThrowCompletion(_reason_). | ||
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. | ||
1. Return *undefined*. | ||
1. Let _onRejected_ be ! CreateBuiltinFunction(_rejectedClosure_, 1, *""*, « »). | ||
1. Perform ! PerformPromiseThen(_promise_, _onFulfilled_, _onRejected_). | ||
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. 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. | ||
1. Return. | ||
1. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of _asyncContext_. | ||
1. Let _outerContext_ be the running execution context. | ||
1. NOTE: _outerContext_ is the execution context for the evaluation of the operation that had most previously resumed evaluation of _asyncContext_. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's unclear what "most previously" is supposed to mean. If it means "the longest ago", then that's wrong, because the execution context that first resumed evaluation of asyncContext isn't even necessarily on the stack, let alone in that position on the stack. And if it means "most recently", then that got a problem too. It's true that, in the status quo, the most recent So unless you want to introduce terminology that distinguishes the two 'directions' of resumes, I think it might be hard to describe how outerContext relates to asyncContext (other than being directly below it on the stack, of course, but that isn't really NOTE-worthy). |
||
1. Resume _outerContext_. | ||
1. Assert: If control reaches here, then _asyncContext_ is once again the running execution context. | ||
1. Let _completion_ be the Completion Record with which _asyncContext_ was resumed. | ||
</emu-alg> | ||
|
||
<p>where all aliases in the above steps, with the exception of _completion_, are ephemeral and visible only in the steps pertaining to Await.</p> | ||
|
@@ -44624,13 +44626,20 @@ <h1> | |
1. Assert: If we return here, the generator either threw an exception or performed either an implicit or explicit return. | ||
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. | ||
1. Set _generator_.[[GeneratorState]] to ~completed~. | ||
1. Once a generator enters the ~completed~ state it never leaves it and its associated execution context is never resumed. Any execution state associated with _generator_ can be discarded at this point. | ||
1. If _result_.[[Type]] is ~normal~, let _resultValue_ be *undefined*. | ||
1. Else if _result_.[[Type]] is ~return~, let _resultValue_ be _result_.[[Value]]. | ||
1. NOTE: Once a generator enters the ~completed~ state it never leaves it and its associated execution context is never resumed. Any execution state associated with _generator_ can be discarded at this point. | ||
1. If _result_.[[Type]] is ~normal~, then | ||
1. Let _resultValue_ be CreateIterResultObject(*undefined*, *true*). | ||
1. Let _resultCompletion_ be NormalCompletion(_resultValue_). | ||
1. Else if _result_.[[Type]] is ~return~, then | ||
1. Let _resultValue_ be CreateIterResultObject(_result_.[[Value]], *true*). | ||
1. Let _resultCompletion_ be NormalCompletion(_resultValue_). | ||
1. Else, | ||
1. Assert: _result_.[[Type]] is ~throw~. | ||
1. Return Completion(_result_). | ||
1. Return CreateIterResultObject(_resultValue_, *true*). | ||
1. Let _resultCompletion_ be _result_. | ||
1. Let _outerContext_ be the running execution context. | ||
1. NOTE: _outerContext_ is the execution context for the evaluation of the operation that had most previously resumed evaluation of _genContext_. | ||
1. Resume _outerContext_ passing _resultCompletion_. | ||
1. Assert: Control does not reach here. | ||
1. Set _generator_.[[GeneratorContext]] to _genContext_. | ||
1. Set _generator_.[[GeneratorState]] to ~suspendedStart~. | ||
1. Return NormalCompletion(*undefined*). | ||
|
@@ -44676,7 +44685,7 @@ <h1> | |
1. Suspend _methodContext_. | ||
1. Set _generator_.[[GeneratorState]] to ~executing~. | ||
1. Push _genContext_ onto the execution context stack; _genContext_ is now the running execution context. | ||
1. Resume the suspended evaluation of _genContext_ using NormalCompletion(_value_) as the result of the operation that suspended it. Let _result_ be the value returned by the resumed computation. | ||
1. Resume the suspended evaluation of _genContext_ with NormalCompletion(_value_). Let _result_ be the Completion Record returned by the resumed computation. | ||
1. Assert: When we return here, _genContext_ has already been removed from the execution context stack and _methodContext_ is the currently running execution context. | ||
1. Return Completion(_result_). | ||
</emu-alg> | ||
|
@@ -44708,7 +44717,7 @@ <h1> | |
1. Suspend _methodContext_. | ||
1. Set _generator_.[[GeneratorState]] to ~executing~. | ||
1. Push _genContext_ onto the execution context stack; _genContext_ is now the running execution context. | ||
1. Resume the suspended evaluation of _genContext_ using _abruptCompletion_ as the result of the operation that suspended it. Let _result_ be the completion record returned by the resumed computation. | ||
1. Resume the suspended evaluation of _genContext_ with _abruptCompletion_. Let _result_ be the Completion Record returned by the resumed computation. | ||
1. Assert: When we return here, _genContext_ has already been removed from the execution context stack and _methodContext_ is the currently running execution context. | ||
1. Return Completion(_result_). | ||
</emu-alg> | ||
|
@@ -44742,11 +44751,13 @@ <h1> | |
1. Assert: GetGeneratorKind() is ~sync~. | ||
1. Set _generator_.[[GeneratorState]] to ~suspendedYield~. | ||
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. | ||
1. Set the code evaluation state of _genContext_ such that when evaluation is resumed with a Completion _resumptionValue_ the following steps will be performed: | ||
1. Return _resumptionValue_. | ||
1. NOTE: This returns to the evaluation of the |YieldExpression| that originally called this abstract operation. | ||
1. Return NormalCompletion(_iterNextObj_). | ||
1. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of _genContext_. | ||
1. Let _outerContext_ be the running execution context. | ||
1. NOTE: _outerContext_ is the execution context for the evaluation of the operation that had most previously resumed evaluation of _genContext_. | ||
1. Resume _outerContext_ passing NormalCompletion(_iterNextObj_). | ||
1. Assert: If control reaches here, then _genContext_ is once again the running execution context. | ||
1. Let _resumptionValue_ be the Completion Record with which _genContext_ was resumed. | ||
1. Return _resumptionValue_. | ||
1. NOTE: This returns to the evaluation of the |YieldExpression| that originally called this abstract operation. | ||
</emu-alg> | ||
</emu-clause> | ||
|
||
|
@@ -44979,11 +44990,13 @@ <h1> | |
1. If _result_.[[Type]] is ~return~, set _result_ to NormalCompletion(_result_.[[Value]]). | ||
1. Perform ! AsyncGeneratorCompleteStep(_generator_, _result_, *true*). | ||
1. Perform ! AsyncGeneratorDrainQueue(_generator_). | ||
1. Return *undefined*. | ||
1. Let _outerContext_ be the running execution context. | ||
1. NOTE: _outerContext_ is the execution context for the evaluation of the operation that had most previously resumed evaluation of _genContext_. | ||
1. Resume _outerContext_. | ||
1. Assert: Control does not reach here. | ||
1. Set _generator_.[[AsyncGeneratorContext]] to _genContext_. | ||
1. Set _generator_.[[AsyncGeneratorState]] to ~suspendedStart~. | ||
1. Set _generator_.[[AsyncGeneratorQueue]] to a new empty List. | ||
1. Return *undefined*. | ||
</emu-alg> | ||
</emu-clause> | ||
|
||
|
@@ -45069,8 +45082,7 @@ <h1> | |
1. Suspend _callerContext_. | ||
1. Set _generator_.[[AsyncGeneratorState]] to ~executing~. | ||
1. Push _genContext_ onto the execution context stack; _genContext_ is now the running execution context. | ||
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. | ||
1. Assert: _result_ is never an abrupt completion. | ||
1. Resume the suspended evaluation of _genContext_ with _completion_. | ||
1. Assert: When we return here, _genContext_ has already been removed from the execution context stack and _callerContext_ is the currently running execution context. | ||
</emu-alg> | ||
</emu-clause> | ||
|
@@ -45120,11 +45132,13 @@ <h1> | |
1. Else, | ||
1. Set _generator_.[[AsyncGeneratorState]] to ~suspendedYield~. | ||
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. | ||
1. Set the code evaluation state of _genContext_ such that when evaluation is resumed with a Completion _resumptionValue_ the following steps will be performed: | ||
1. Return AsyncGeneratorUnwrapYieldResumption(_resumptionValue_). | ||
1. NOTE: When the above step returns, it returns to the evaluation of the |YieldExpression| production that originally called this abstract operation. | ||
1. Return *undefined*. | ||
1. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of _genContext_. | ||
1. Let _outerContext_ be the running execution context. | ||
1. NOTE: _outerContext_ is the execution context for the evaluation of the operation that had most previously resumed evaluation of _genContext_. | ||
1. Resume _outerContext_. | ||
1. Assert: If control reaches here, then _genContext_ is once again the running execution context. | ||
1. Let _resumptionValue_ be the Completion Record with which _genContext_ was resumed. | ||
1. Return AsyncGeneratorUnwrapYieldResumption(_resumptionValue_). | ||
1. NOTE: When the above step returns, it returns to the evaluation of the |YieldExpression| production that originally called this abstract operation. | ||
</emu-alg> | ||
</emu-clause> | ||
|
||
|
@@ -45362,12 +45376,13 @@ <h1> | |
1. Else, | ||
1. Assert: _result_.[[Type]] is ~throw~. | ||
1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _result_.[[Value]] »). | ||
1. [id="step-asyncblockstart-return-undefined"] Return. | ||
1. Let _outerContext_ be the running execution context. | ||
1. NOTE: _outerContext_ is the execution context for the evaluation of the operation that had most previously resumed evaluation of _asyncContext_. | ||
1. Resume _outerContext_. | ||
1. Assert: Control does not reach here. | ||
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. Resume the suspended evaluation of _asyncContext_. | ||
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, step <emu-xref href="#step-asyncblockstart-return-undefined"></emu-xref> above. | ||
1. Return. | ||
</emu-alg> | ||
</emu-clause> | ||
</emu-clause> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the spec only uses "outer" when talking about environments, which is appropriate because we think of outer and inner scopes. But for these execution contexts, outer/inner doesn't seem like the right metaphor. Elsewhere, the spec calls them "caller" + "callee". (Which makes sense, though the fact that they only differ by one letter makes them a bit hard to distinguish visually.)