Skip to content

Commit

Permalink
Merge commit from fork
Browse files Browse the repository at this point in the history
* Editorial: mark various side-effecting Promise resolutions

* Editorial: more precise type for EnqueueResolveInAgentJob

* Normative: guard against reentrancy in AsyncGenerator.prototype.return

* Editorial: rename ~awaiting-return~ state to ~draining-queue~

---------

Co-authored-by: Kevin Gibbons <[email protected]>
  • Loading branch information
ctcpip and bakkot authored Aug 13, 2024
1 parent 32fe924 commit 9e885de
Showing 1 changed file with 23 additions and 20 deletions.
43 changes: 23 additions & 20 deletions spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -19612,7 +19612,7 @@ <h1>
1. Let _evaluatePromise_ be _module_.Evaluate().
1. Let _fulfilledClosure_ be a new Abstract Closure with no parameters that captures _module_ and _promiseCapability_ and performs the following steps when called:
1. Let _namespace_ be GetModuleNamespace(_module_).
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _namespace_ »).
1. Perform ! <emu-meta effects="user-code">Call</emu-meta>(_promiseCapability_.[[Resolve]], *undefined*, « _namespace_ »).
1. Return ~unused~.
1. Let _onFulfilled_ be CreateBuiltinFunction(_fulfilledClosure_, 0, *""*, « »).
1. Perform PerformPromiseThen(_evaluatePromise_, _onFulfilled_, _onRejected_).
Expand Down Expand Up @@ -44993,7 +44993,7 @@ <h1>
EnqueueResolveInAgentJob (
_agentSignifier_: an agent signifier,
_promiseCapability_: a PromiseCapability Record,
_resolution_: an ECMAScript language value,
_resolution_: *"ok"* or *"timed-out"*,
): ~unused~
</h1>
<dl class="header">
Expand Down Expand Up @@ -46539,7 +46539,7 @@ <h1>%AsyncFromSyncIteratorPrototype%.return ( [ _value_ ] )</h1>
1. IfAbruptRejectPromise(_return_, _promiseCapability_).
1. If _return_ is *undefined*, then
1. Let _iteratorResult_ be CreateIteratorResultObject(_value_, *true*).
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _iteratorResult_ »).
1. Perform ! <emu-meta effects="user-code">Call</emu-meta>(_promiseCapability_.[[Resolve]], *undefined*, « _iteratorResult_ »).
1. Return _promiseCapability_.[[Promise]].
1. If _value_ is present, then
1. Let _result_ be Completion(Call(_return_, _syncIterator_, « _value_ »)).
Expand Down Expand Up @@ -48308,14 +48308,14 @@ <h1>%AsyncGeneratorPrototype%.next ( _value_ )</h1>
1. Let _state_ be _generator_.[[AsyncGeneratorState]].
1. If _state_ is ~completed~, then
1. Let _iteratorResult_ be CreateIteratorResultObject(*undefined*, *true*).
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _iteratorResult_ »).
1. Perform ! <emu-meta effects="user-code">Call</emu-meta>(_promiseCapability_.[[Resolve]], *undefined*, « _iteratorResult_ »).
1. Return _promiseCapability_.[[Promise]].
1. Let _completion_ be NormalCompletion(_value_).
1. Perform AsyncGeneratorEnqueue(_generator_, _completion_, _promiseCapability_).
1. If _state_ is either ~suspended-start~ or ~suspended-yield~, then
1. Perform AsyncGeneratorResume(_generator_, _completion_).
1. Else,
1. Assert: _state_ is either ~executing~ or ~awaiting-return~.
1. Assert: _state_ is either ~executing~ or ~draining-queue~.
1. Return _promiseCapability_.[[Promise]].
</emu-alg>
</emu-clause>
Expand All @@ -48331,12 +48331,12 @@ <h1>%AsyncGeneratorPrototype%.return ( _value_ )</h1>
1. Perform AsyncGeneratorEnqueue(_generator_, _completion_, _promiseCapability_).
1. Let _state_ be _generator_.[[AsyncGeneratorState]].
1. If _state_ is either ~suspended-start~ or ~completed~, then
1. Set _generator_.[[AsyncGeneratorState]] to ~awaiting-return~.
1. Set _generator_.[[AsyncGeneratorState]] to ~draining-queue~.
1. Perform AsyncGeneratorAwaitReturn(_generator_).
1. Else if _state_ is ~suspended-yield~, then
1. Perform AsyncGeneratorResume(_generator_, _completion_).
1. Else,
1. Assert: _state_ is either ~executing~ or ~awaiting-return~.
1. Assert: _state_ is either ~executing~ or ~draining-queue~.
1. Return _promiseCapability_.[[Promise]].
</emu-alg>
</emu-clause>
Expand All @@ -48360,7 +48360,7 @@ <h1>%AsyncGeneratorPrototype%.throw ( _exception_ )</h1>
1. If _state_ is ~suspended-yield~, then
1. Perform AsyncGeneratorResume(_generator_, _completion_).
1. Else,
1. Assert: _state_ is either ~executing~ or ~awaiting-return~.
1. Assert: _state_ is either ~executing~ or ~draining-queue~.
1. Return _promiseCapability_.[[Promise]].
</emu-alg>
</emu-clause>
Expand All @@ -48386,7 +48386,7 @@ <h1>Properties of AsyncGenerator Instances</h1>
</thead>
<tr>
<td>[[AsyncGeneratorState]]</td>
<td>*undefined*, ~suspended-start~, ~suspended-yield~, ~executing~, ~awaiting-return~, or ~completed~</td>
<td>*undefined*, ~suspended-start~, ~suspended-yield~, ~executing~, ~draining-queue~, or ~completed~</td>
<td>The current execution state of the async generator.</td>
</tr>
<tr>
Expand All @@ -48397,7 +48397,7 @@ <h1>Properties of AsyncGenerator Instances</h1>
<tr>
<td>[[AsyncGeneratorQueue]]</td>
<td>a List of AsyncGeneratorRequest Records</td>
<td>Records which represent requests to resume the async generator. Except during state transitions, it is non-empty if and only if [[AsyncGeneratorState]] is either ~executing~ or ~awaiting-return~.</td>
<td>Records which represent requests to resume the async generator. Except during state transitions, it is non-empty if and only if [[AsyncGeneratorState]] is either ~executing~ or ~draining-queue~.</td>
</tr>
<tr>
<td>[[GeneratorBrand]]</td>
Expand Down Expand Up @@ -48461,7 +48461,7 @@ <h1>
1. Let _result_ be Completion(_generatorBody_()).
1. Assert: If we return here, the async generator either threw an exception or performed either an implicit or explicit return.
1. Remove _acGenContext_ 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 _acGenerator_.[[AsyncGeneratorState]] to ~completed~.
1. Set _acGenerator_.[[AsyncGeneratorState]] to ~draining-queue~.
1. If _result_ is a normal completion, set _result_ to NormalCompletion(*undefined*).
1. If _result_ is a return completion, set _result_ to NormalCompletion(_result_.[[Value]]).
1. Perform AsyncGeneratorCompleteStep(_acGenerator_, _result_, *true*).
Expand Down Expand Up @@ -48538,7 +48538,7 @@ <h1>
1. Set the running execution context's Realm to _oldRealm_.
1. Else,
1. Let _iteratorResult_ be CreateIteratorResultObject(_value_, _done_).
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _iteratorResult_ »).
1. Perform ! <emu-meta effects="user-code">Call</emu-meta>(_promiseCapability_.[[Resolve]], *undefined*, « _iteratorResult_ »).
1. Return ~unused~.
</emu-alg>
</emu-clause>
Expand Down Expand Up @@ -48626,28 +48626,28 @@ <h1>
<dl class="header">
</dl>
<emu-alg>
1. Assert: _generator_.[[AsyncGeneratorState]] is ~draining-queue~.
1. Let _queue_ be _generator_.[[AsyncGeneratorQueue]].
1. Assert: _queue_ is not empty.
1. Let _next_ be the first element of _queue_.
1. Let _completion_ be Completion(_next_.[[Completion]]).
1. Assert: _completion_ is a return completion.
1. Let _promiseCompletion_ be Completion(PromiseResolve(%Promise%, _completion_.[[Value]])).
1. If _promiseCompletion_ is an abrupt completion, then
1. Set _generator_.[[AsyncGeneratorState]] to ~completed~.
1. Perform AsyncGeneratorCompleteStep(_generator_, _promiseCompletion_, *true*).
1. Perform AsyncGeneratorDrainQueue(_generator_).
1. Return ~unused~.
1. Assert: _promiseCompletion_ is a normal completion.
1. Let _promise_ be _promiseCompletion_.[[Value]].
1. Let _fulfilledClosure_ be a new Abstract Closure with parameters (_value_) that captures _generator_ and performs the following steps when called:
1. Set _generator_.[[AsyncGeneratorState]] to ~completed~.
1. Assert: _generator_.[[AsyncGeneratorState]] is ~draining-queue~.
1. Let _result_ be NormalCompletion(_value_).
1. Perform AsyncGeneratorCompleteStep(_generator_, _result_, *true*).
1. Perform AsyncGeneratorDrainQueue(_generator_).
1. Return *undefined*.
1. Let _onFulfilled_ be CreateBuiltinFunction(_fulfilledClosure_, 1, *""*, « »).
1. Let _rejectedClosure_ be a new Abstract Closure with parameters (_reason_) that captures _generator_ and performs the following steps when called:
1. Set _generator_.[[AsyncGeneratorState]] to ~completed~.
1. Assert: _generator_.[[AsyncGeneratorState]] is ~draining-queue~.
1. Let _result_ be ThrowCompletion(_reason_).
1. Perform AsyncGeneratorCompleteStep(_generator_, _result_, *true*).
1. Perform AsyncGeneratorDrainQueue(_generator_).
Expand All @@ -48669,22 +48669,25 @@ <h1>
<dd>It drains the generator's AsyncGeneratorQueue until it encounters an AsyncGeneratorRequest which holds a return completion.</dd>
</dl>
<emu-alg>
1. Assert: _generator_.[[AsyncGeneratorState]] is ~completed~.
1. Assert: _generator_.[[AsyncGeneratorState]] is ~draining-queue~.
1. Let _queue_ be _generator_.[[AsyncGeneratorQueue]].
1. If _queue_ is empty, return ~unused~.
1. If _queue_ is empty, then
1. Set _generator_.[[AsyncGeneratorState]] to ~completed~.
1. Return ~unused~.
1. Let _done_ be *false*.
1. Repeat, while _done_ is *false*,
1. Let _next_ be the first element of _queue_.
1. Let _completion_ be Completion(_next_.[[Completion]]).
1. If _completion_ is a return completion, then
1. Set _generator_.[[AsyncGeneratorState]] to ~awaiting-return~.
1. Perform AsyncGeneratorAwaitReturn(_generator_).
1. Set _done_ to *true*.
1. Else,
1. If _completion_ is a normal completion, then
1. Set _completion_ to NormalCompletion(*undefined*).
1. Perform AsyncGeneratorCompleteStep(_generator_, _completion_, *true*).
1. If _queue_ is empty, set _done_ to *true*.
1. If _queue_ is empty, then
1. Set _generator_.[[AsyncGeneratorState]] to ~completed~.
1. Set _done_ to *true*.
1. Return ~unused~.
</emu-alg>
</emu-clause>
Expand Down Expand Up @@ -48855,7 +48858,7 @@ <h1>
1. If _result_ is a normal completion, then
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « *undefined* »).
1. Else if _result_ is a return completion, then
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _result_.[[Value]] »).
1. Perform ! <emu-meta effects="user-code">Call</emu-meta>(_promiseCapability_.[[Resolve]], *undefined*, « _result_.[[Value]] »).
1. Else,
1. Assert: _result_ is a throw completion.
1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _result_.[[Value]] »).
Expand Down

0 comments on commit 9e885de

Please sign in to comment.