Skip to content
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: enable built-in async and sync generator functions to be specified #1665

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
123 changes: 111 additions & 12 deletions spec.html
Expand Up @@ -371,6 +371,16 @@ <h1>built-in function</h1>
</emu-note>
</emu-clause>

<emu-clause id="sec-built-in-generator-function">
<h1>built-in generator function</h1>
<p>built-in object that is a generator function</p>
</emu-clause>

<emu-clause id="sec-built-in-async-generator-function">
<h1>built-in async generator function</h1>
<p>built-in object that is an async generator function</p>
</emu-clause>

<emu-clause id="sec-property">
<h1>property</h1>
<p>part of an object that associates a key (either a String value or a Symbol value) and a value</p>
Expand Down Expand Up @@ -3138,6 +3148,29 @@ <h1>Await Rejected Functions</h1>
</emu-clause>
</emu-clause>

<emu-clause id="yield" aoid="Yield">
<h1>Yield</h1>

<p>Algorithm steps that say</p>

<emu-alg>
1. Let _completion_ be Yield(_value_).
</emu-alg>

<p>mean the same thing as:</p>

<emu-alg>
1. Let _generatorKind_ be ! GetGeneratorKind().
1. If _generatorKind_ is ~async~, then
1. Let _completion_ be AsyncGeneratorYield(_value_).
ljharb marked this conversation as resolved.
Show resolved Hide resolved
1. Otherwise,
1. Let _completion_ be GeneratorYield(CreateIterResultObject(_value_, *false*)).
ljharb marked this conversation as resolved.
Show resolved Hide resolved
</emu-alg>

<p>where all variables in the above steps, with the exception of _completion_, are ephemeral and visible only in the steps pertaining to Yield.</p>

</emu-clause>

<emu-clause id="sec-normalcompletion" aoid="NormalCompletion">
<h1>NormalCompletion</h1>
<p>The abstract operation NormalCompletion with a single _argument_, such as:</p>
Expand Down Expand Up @@ -7793,9 +7826,63 @@ <h1>[[Call]] ( _thisArgument_, _argumentsList_ )</h1>
1. Set the ScriptOrModule of _calleeContext_ to _F_.[[ScriptOrModule]].
1. Perform any necessary implementation-defined initialization of _calleeContext_.
1. Push _calleeContext_ onto the execution context stack; _calleeContext_ is now the running execution context.
1. Let _result_ be the Completion Record that is the result of evaluating _F_ in an implementation-defined manner that conforms to the specification of _F_. _thisArgument_ is the *this* value, _argumentsList_ provides the named parameters, and the NewTarget value is *undefined*.
1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context.
1. Return _result_.
1. If _F_ is a built-in async function, then
1. Let _asyncContext_ be a copy of _calleeContext_.
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 Completion Record that is the result of evaluating _F_ in an implementation-defined manner that confirms to the specification of _F_. _thisArgument_ is the *this* value, _argumentsList_ provides the named parameters, and NewTarget is *undefined*.
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_ is an abrupt completion, then
1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, &laquo; _result.[[Value]] &raquo;).
1. Else,
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, &laquo; _result_.[[Value]] &raquo;).
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: _calleeContext_ is the running execution context.
1. Assert: _result_ is a normal completion with a value of *undefined*.
1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context.
1. Return _promiseCapability_.[[Promise]].
1. If _F_ is a built-in generator function, then
1. Let _result_ be the completion record that is the result of evaluating the prelude steps of _F_ in an implementation-defined manner that conforms to the specification of _F_. _thisArgument_ is the *this* value, _argumentsList_ provides the named parameters, and NewTarget is *undefined*.
1. If _result_ is an abrupt completion, return _result_.
1. Let _generator_ be ? OrdinaryCreateFromConstructor(_F_, "%GeneratorPrototype%", « [[GeneratorState]], [[GeneratorContext]] »).
1. Set the Generator component of _calleeContext_ to _generator_.
1. Set _generator_.[[GeneratorState]] to *"suspendedStart"*.
1. Set the code evaluation state of _calleeContext_ such that when evaluation is resumed for that execution context the following steps will be performed:
1. Let _result_ be the Completion Record that is the result of evaluating the body steps of _F_ in an implementaion-defined manner that confirms to the specification of _F_. _thisArgument_ is the *this* value, _argumentsList_ provides the named parameters, and NewTarget is *undefined*.
1. Remove _calleeContext_ 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. If _result_ is an abrupt completion, then
1. Return _result_.
1. Else,
1. Let _resultValue_ be _result_.[[Value]].
1. Return CreateIterResultObject(_resultValue_, *true*).
1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context.
1. Return _generator_.
1. Else if _F_ is a built-in async generator function, then
1. Let _result_ be the completion record that is the result of evaluating the prelude steps of _F_ in an implementation-defined manner that conforms to the specification of _F_. _thisArgument_ is the *this* value, _argumentsList_ provides the named parameters, and NewTarget is *undefined*.
1. If _result_ is an abrupt completion, return _result_.
1. Let _generator_ be ? OrdinaryCreateFromConstructor(_F_, "%AsyncGeneratorPrototype%", « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]] »).
1. Set the Generator component of _calleeContext_ to _generator_.
1. Set _generator_.[[AsyncGeneratorContext]] to _calleeContext_.
1. Set _generator_.[[AsyncGeneratorState]] to *"suspendedStart"*.
1. Set _generator_.[[AsyncGeneratorQueue]] to a new empty List.
1. Set the code evaluation state of _calleeContext_ such that when evaluation is resumed for that execution context the following steps are performed:
1. Let _result_ be the Completion Record that is the result of evaluating the body steps of _F_ in an implementaion-defined manner that confirms to the specification of _F_. _thisArgument_ is the *this* value, _argumentsList_ provides the named parameters, and NewTarget is *undefined*.
1. Remove _calleeContext_ 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_.[[AsyncGeneratorState]] to *"completed"*.
1. If _result_ is an abrupt completion, then
1. Let _resultValue_ be _result_.[[Value]].
1. Return ! AsyncGeneratorReject(_generator_, _resultValue_).
1. Else,
1. Set _resultValue_ to _result_.[[Value]].
1. Return ! AsyncGeneratorResolve(_generator_, _resultValue_).
1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context.
1. Return _generator_.
1. Otherwise,
1. Let _result_ be the Completion Record that is the result of evaluating _F_ in an implementation-defined manner that conforms to the specification of _F_. _thisArgument_ is the *this* value, _argumentsList_ provides the named parameters, and the NewTarget value is *undefined*.
1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context.
1. Return _result_.
</emu-alg>
<emu-note>
<p>When _calleeContext_ is removed from the execution context stack it must not be destroyed if it has been suspended and retained by an accessible generator object for later resumption.</p>
Expand All @@ -7804,9 +7891,21 @@ <h1>[[Call]] ( _thisArgument_, _argumentsList_ )</h1>

<emu-clause id="sec-built-in-function-objects-construct-argumentslist-newtarget">
<h1>[[Construct]] ( _argumentsList_, _newTarget_ )</h1>
<p>The [[Construct]] internal method for built-in function object _F_ is called with parameters _argumentsList_ and _newTarget_. The steps performed are the same as [[Call]] (see <emu-xref href="#sec-built-in-function-objects-call-thisargument-argumentslist"></emu-xref>) except that step 10 is replaced by:</p>
<p>The [[Construct]] internal method for built-in function object _F_ is called with parameters _argumentsList_ and _newTarget_.</p>
<emu-alg>
10. Let _result_ be the Completion Record that is the result of evaluating _F_ in an implementation-defined manner that conforms to the specification of _F_. The *this* value is uninitialized, _argumentsList_ provides the named parameters, and _newTarget_ provides the NewTarget value.
1. If _F_ is a built-in async function, built-in generator function, or a built-in async generator function, throw a *TypeError* exception.
1. Let _callerContext_ be the running execution context.
1. If _callerContext_ is not already suspended, suspend _callerContext_.
1. Let _calleeContext_ be a new execution context.
1. Set the Function of _calleeContext_ to _F_.
1. Let _calleeRealm_ be _F_.[[Realm]].
1. Set the Realm of _calleeContext_ to _calleeRealm_.
1. Set the ScriptOrModule of _calleeContext_ to _F_.[[ScriptOrModule]].
1. Perform any necessary implementation-defined initialization of _calleeContext_.
1. Push _calleeContext_ onto the execution context stack; _calleeContext_ is now the running execution context.
1. Let _result_ be the Completion Record that is the result of evaluating _F_ in an implementation-defined manner that conforms to the specification of _F_. The *this* value is uninitialized, _argumentsList_ provides the named parameters, and _newTarget_ provides the NewTarget value.
1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context.
1. Return _result_.
</emu-alg>
</emu-clause>

Expand All @@ -7817,7 +7916,11 @@ <h1>CreateBuiltinFunction ( _steps_, _internalSlotsList_ [ , _realm_ [ , _protot
1. Assert: _steps_ is either a set of algorithm steps or other definition of a function's behaviour provided in this specification.
1. If _realm_ is not present, set _realm_ to the current Realm Record.
1. Assert: _realm_ is a Realm Record.
1. If _prototype_ is not present, set _prototype_ to _realm_.[[Intrinsics]].[[%Function.prototype%]].
1. If _prototype_ is not present, then
1. If _steps_ refers to the steps of a built-in async function, set _prototype_ to _realm_.[[Intrinsics]].[[%AsyncFunction.prototype%]].
1. Else if _steps_ refers to the steps of a built-in generator function, set _prototype_ to _realm_.[[Intrinsics]].[[%Generator%]].
1. Else if _steps_ refers to the steps of a built-in async generator function, set _prototype_ to _realm_.[[Intrinsics]].[[%AsyncGenerator%]].
1. Otherwise, set _prototype_ to _realm_.[[Intrinsics]].[[%Function.prototype%]].
1. Let _func_ be a new built-in function object that when called performs the action described by _steps_. The new function object has internal slots whose names are the elements of _internalSlotsList_.
1. Set _func_.[[Realm]] to _realm_.
1. Set _func_.[[Prototype]] to _prototype_.
Expand Down Expand Up @@ -19337,17 +19440,13 @@ <h1>Runtime Semantics: Evaluation</h1>
</emu-note>
<emu-grammar>YieldExpression : `yield`</emu-grammar>
<emu-alg>
1. Let _generatorKind_ be ! GetGeneratorKind().
1. If _generatorKind_ is ~async~, then return ? AsyncGeneratorYield(*undefined*).
1. Otherwise, return ? GeneratorYield(CreateIterResultObject(*undefined*, *false*)).
1. Return Yield(*undefined*).
</emu-alg>
<emu-grammar>YieldExpression : `yield` AssignmentExpression</emu-grammar>
<emu-alg>
1. Let _generatorKind_ be ! GetGeneratorKind().
1. Let _exprRef_ be the result of evaluating |AssignmentExpression|.
1. Let _value_ be ? GetValue(_exprRef_).
1. If _generatorKind_ is ~async~, then return ? AsyncGeneratorYield(_value_).
1. Otherwise, return ? GeneratorYield(CreateIterResultObject(_value_, *false*)).
1. Return Yield(_value_).
</emu-alg>
<emu-grammar>YieldExpression : `yield` `*` AssignmentExpression</emu-grammar>
<emu-alg>
Expand Down