Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Move the awaiting (back) into yield #102

Merged
merged 4 commits into from
Jun 28, 2017
Merged
Show file tree
Hide file tree
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
64 changes: 55 additions & 9 deletions spec/abstract-operations.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,8 @@ <h1>AsyncGeneratorResolve ( _generator_, _value_, _done_ )</h1>
1. Assert: _queue_ is not an empty List.
1. Remove the first element from _queue_ and let _next_ be the value of that element.
1. Let _promiseCapability_ be _next_.[[Capability]].
1. Let _valueWrapperCapability_ be ! NewPromiseCapability(%Promise%).
1. Perform ! Call(_valueWrapperCapability_.[[Resolve]], *undefined*, &laquo; _value_ &raquo;).
1. Let _onFulfilled_ be a new built-in function object as defined in <emu-xref href="#sec-async-iterator-value-unwrap-functions" title></emu-xref>.
1. Set _onFulfilled_.[[Done]] to _done_.
1. Perform ! PerformPromiseThen(_valueWrapperCapability_.[[Promise]], _onFulfilled_, *undefined*, _promiseCapability_).
1. Let _iteratorResult_ be ! CreateIterResultObject(_value_, _done_).
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, &laquo; _iteratorResult_ &raquo;).
1. Perform ! AsyncGeneratorResumeNext(_generator_).
1. Return *undefined*.
</emu-clause>
Expand All @@ -88,6 +85,7 @@ <h1>AsyncGeneratorResumeNext ( _generator_ )</h1>
1. Assert: _generator_ is an AsyncGenerator instance.
1. Let _state_ be _generator_.[[AsyncGeneratorState]].
1. Assert: _state_ is not `"executing"`.
1. If _state_ is `"awaiting-return"`, return *undefined*.
1. Let _queue_ be _generator_.[[AsyncGeneratorQueue]].
1. If _queue_ is an empty List, return *undefined*.
1. Let _next_ be the value of the first element of _queue_.
Expand All @@ -98,8 +96,21 @@ <h1>AsyncGeneratorResumeNext ( _generator_ )</h1>
1. Set _generator_.[[AsyncGeneratorState]] to `"completed"`.
1. Set _state_ to `"completed"`.
1. If _state_ is `"completed"`, then
1. If _completion_.[[Type]] is ~return~, then return ! AsyncGeneratorResolve(_generator_, _completion_.[[Value]], *true*).
1. Else, return ! AsyncGeneratorReject(_generator_, _completion_.[[Value]]).
1. If _completion_.[[Type]] is ~return~:
1. Set _generator_.[[AsyncGeneratorState]] to `"awaiting-return"`.
1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).
1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _completion_.[[Value]] »).
1. Let _onFulfilled_ be a new built-in function object as defined in <emu-xref href="#async-generator-resume-next-return-processor-fulfilled" title></emu-xref>.
1. Let _onRejected_ be a new built-in function object as defined in <emu-xref href="#async-generator-resume-next-return-processor-rejected" title></emu-xref>.
1. Set _onFulfilled_ and _onRejected_'s [[Generator]] internal slots to _generator_.
1. Let _throwawayCapability_ be NewPromiseCapability(%Promise%).
1. Set _throwawayCapability_.[[Promise]].[[PromiseIsHandled]] to *true*.
1. Perform ! PerformPromiseThen(_promiseCapability_.[[Promise]], _onFulfilled_, _onRejected_, _throwawayCapability_).
1. Return *undefined*.
1. Else,
1. Assert: _completion_.[[Type]] is ~throw~.
1. Perform ! AsyncGeneratorReject(_generator_, _completion_.[[Value]]).
1. Return *undefined*.
1. Else if _state_ is `"completed"`, then return ! AsyncGeneratorResolve(_generator_, *undefined*, *true*).
1. Assert: _state_ is either `"suspendedStart"` or `"suspendedYield"`.
1. Let _genContext_ be _generator_.[[AsyncGeneratorContext]].
Expand All @@ -112,6 +123,36 @@ <h1>AsyncGeneratorResumeNext ( _generator_ )</h1>
1. Assert: When we return here, _genContext_ has already been removed from the execution context stack and _callerContext_ is the currently running execution context.
1. Return *undefined*.
</emu-alg>

<emu-clause id="async-generator-resume-next-return-processor-fulfilled">
<h1>AsyncGeneratorResumeNext Return Processor Fulfilled Functions</h1>

<p>An AsyncGeneratorResumeNext return processor fulfilled function is an anonymous built-in function that is used as part of the AsyncGeneratorResumeNext specification device to unwrap promises passed in to the <emu-xref href="#sec-asyncgenerator-prototype-return" title></emu-xref> method. Each AsyncGeneratorResumeNext return processor fulfilled function has a [[Generator]] internal slot.</p>

<p>When an AsyncGeneratorResumeNext return processor fulfilled function _F_ is called with argument _value_, the following steps are taken:</p>

<emu-alg>
1. Set _F_.[[Generator]].[[AsyncGeneratorState]] to `"completed"`.
1. Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *true*).
</emu-alg>

<p>The `length` property of an AsyncGeneratorResumeNext return processor fulfilled function is 1.</p>
</emu-clause>

<emu-clause id="async-generator-resume-next-return-processor-rejected">
<h1>AsyncGeneratorResumeNext Return Processor Rejected Functions</h1>

<p>An AsyncGeneratorResumeNext return processor rejected function is an anonymous built-in function that is used as part of the AsyncGeneratorResumeNext specification device to unwrap promises passed in to the <emu-xref href="#sec-asyncgenerator-prototype-return" title></emu-xref> method. Each AsyncGeneratorResumeNext return processor rejected function has a [[Generator]] internal slot.</p>

<p>When an AsyncGeneratorResumeNext return processor rejected function _F_ is called with argument _reason_, the following steps are taken:</p>

<emu-alg>
1. Set _F_.[[Generator]].[[AsyncGeneratorState]] to `"completed"`.
1. Return ! AsyncGeneratorReject(_F_.[[Generator]], _reason_).
</emu-alg>

<p>The `length` property of an AsyncGeneratorResumeNext return processor rejected function is 1.</p>
</emu-clause>
</emu-clause>

<emu-clause id="sec-asyncgeneratorenqueue" aoid="AsyncGeneratorEnqueue">
Expand Down Expand Up @@ -141,11 +182,16 @@ <h1><ins>AsyncGeneratorYield ( _value_ )</ins></h1>
1. Assert: _genContext_ is the execution context of a generator.
1. Let _generator_ be the value of the Generator component of _genContext_.
1. Assert: GetGeneratorKind() is ~async~.
1. Set _value_ to ? Await(_value_).
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 _resumptionValue_.
1. NOTE: This returns to the evaluation of the |YieldExpression| production that originally called this abstract operation.
1. If _resumptionValue_.[[Type]] is not ~return~, return Completion(_resumptionValue_).
1. Let _awaited_ be Await(_resumptionValue_.[[Value]]).
1. If _awaited_.[[Type]] is ~throw~, return Completion(_awaited_).
1. Assert: _awaited_.[[Type]] is ~normal~.
1. Return Completion{[[Type]]: ~return~, [[Value]]: _awaited_.[[Value]], [[Target]]: ~empty~}.
1. NOTE: When one of the above steps returns, it returns to the evaluation of the |YieldExpression| production that originally called this abstract operation.
1. Return ! AsyncGeneratorResolve(_generator_, _value_, *false*).
1. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of _genContext_.
</emu-alg>
Expand Down
2 changes: 1 addition & 1 deletion spec/async-generator-objects.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ <h1>Properties of AsyncGenerator Instances</h1>
</tr>
<tr>
<td>[[AsyncGeneratorState]]</td>
<td>The current execution state of the async generator. The possible values are: *undefined*, `"suspendedStart"`, `"suspendedYield"`, `"executing"`, and `"completed"`.</td>
<td>The current execution state of the async generator. The possible values are: *undefined*, `"suspendedStart"`, `"suspendedYield"`, `"executing"`, `"awaiting-return"`, and `"completed"`.</td>
</tr>
<tr>
<td>[[AsyncGeneratorContext]]</td>
Expand Down
2 changes: 1 addition & 1 deletion spec/generator-abstract-ops-patch.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<h1><ins>GetGeneratorKind ( )</ins></h1>
<emu-alg>
1. Let _genContext_ be the running execution context.
1. Assert: _genContext_ has a Generator component.
1. If _genContext_ does not have a Generator component, return ~non-generator~.
1. Let _generator_ be the Generator component of _genContext_.
1. If _generator_ has an [[AsyncGeneratorState]] internal slot, return ~async~.
1. Else, return ~normal~.
Expand Down
9 changes: 2 additions & 7 deletions spec/generator-definitions-patch.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ <h1>Runtime Semantics: Evaluation</h1>
1. <ins>If Type(_innerResult_) is not Object, throw a *TypeError* exception.</ins>
1. Let _done_ be ? IteratorComplete(_innerResult_).
1. If _done_ is *true*, then
1. <ins>Let _resultValue_ be </ins><del>Return </del>? IteratorValue(_innerResult_).
1. <ins>If _generatorKind_ is ~async~, then set _resultValue_ to ? Await(_resultValue_).</ins>
1. <ins>Return _resultValue_.</ins>
1. Return ? IteratorValue(_innerResult_).
1. <ins>If _generatorKind_ is ~async~, then let _received_ be AsyncGeneratorYield(? IteratorValue(_innerResult_)).</ins>
1. <ins>Else, l</ins><del>L</del>et _received_ be GeneratorYield(_innerResult_).
1. Else if _received_.[[Type]] is ~throw~, then
Expand All @@ -48,9 +46,7 @@ <h1>Runtime Semantics: Evaluation</h1>
1. If Type(_innerResult_) is not Object, throw a *TypeError* exception.
1. Let _done_ be ? IteratorComplete(_innerResult_).
1. If _done_ is *true*, then
1. <ins>Let _resultValue_ be </ins><del>Return </del>? IteratorValue(_innerResult_).
1. <ins>If _generatorKind_ is ~async~, then set _resultValue_ to ? Await(_resultValue_).</ins>
1. <ins>Return _resultValue_.</ins>
1. Return ? IteratorValue(_innerResult_).
1. <ins>If _generatorKind_ is ~async~, then let _received_ be AsyncGeneratorYield(? IteratorValue(_innerResult_)).</ins>
1. <ins>Else, l</ins><del>L</del>et _received_ be GeneratorYield(_innerResult_).
1. Else,
Expand All @@ -70,7 +66,6 @@ <h1>Runtime Semantics: Evaluation</h1>
1. Let _done_ be ? IteratorComplete(_innerReturnResult_).
1. If _done_ is *true*, then
1. Let _value_ be ? IteratorValue(_innerReturnResult_).
1. <ins>If _generatorKind_ is ~async~, then set _value_ to ? Await(_value_).</ins>
1. Return Completion{[[Type]]: ~return~, [[Value]]: _value_, [[Target]]: ~empty~}.
1. <ins>If _generatorKind_ is ~async~, then let _received_ be AsyncGeneratorYield(? IteratorValue(_innerResult_)).</ins>
1. <ins>Else, l</ins><del>L</del>et _received_ be GeneratorYield(_innerResult_).
Expand Down
16 changes: 12 additions & 4 deletions spec/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,21 @@ <h1>ECMAScript Function Objects</h1>
<emu-import href="./es-function-objects-patch.html"></emu-import>
</emu-clause>

<emu-clause id="sec-iteration-statements-patch">
<h1>Iteration Statements</h1>
<emu-clause id="sec-ecmascript-language-statements-and-declarations-patch">
<h1>ECMAScript Language: Statements and Declarations</h1>
<emu-note type="editor">
These patches modify clauses of and add clauses to <emu-xref href="#sec-iteration-statements"></emu-xref>.
These patches modify clauses of and add clauses to <emu-xref href="#sec-ecmascript-language-statements-and-declarations"></emu-xref>.
</emu-note>

<emu-import href="./iteration-statements-patch.html"></emu-import>
<emu-clause id="sec-return-statement">
<h1>The `return` Statement</h1>
<emu-import href="./return-statement-patch.html"></emu-import>
</emu-clause>

<emu-clause id="sec-iteration-statements">
<h1>Iteration Statements</h1>
<emu-import href="./iteration-statements-patch.html"></emu-import>
</emu-clause>
</emu-clause>

<emu-clause id="sec-ecmascript-language-functions-and-classes-patch">
Expand Down
30 changes: 15 additions & 15 deletions spec/iteration.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,6 @@ <h1><ins>The <i>AsyncIterator</i> Interface</ins></h1>
<emu-note>
<p>Typically callers of these methods should check for their existence before invoking them. Certain ECMAScript language features including `for`-`await`-`of` and `yield*` call these methods after performing an existence check.</p>
</emu-note>

<emu-clause id="sec-async-iterator-value-unwrap-functions">
<h1>Async Iterator Value Unwrap Functions</h1>

<p>An async iterator value unwrap function is an anonymous built-in function that is used when processing the `value` field of an <i>IteratorResult</i> object, in order to wait for its value if it is a promise and re-package the result in a new "unwrapped" <i>IteratorResult</i> object. Each async iterator value unwrap function has a [[Done]] internal slot.</p>

<p>When an async iterator unwrap function _F_ is called with argument _value_, the following steps are taken:</p>

<emu-alg>
1. Return ! CreateIterResultObject(_value_, _F_.[[Done]]).
</emu-alg>
</emu-clause>
</emu-clause>
</emu-clause>

Expand Down Expand Up @@ -149,7 +137,7 @@ <h1>%AsyncFromSyncIteratorPrototype%.next ( _value_ )</h1>
1. IfAbruptRejectPromise(_nextValue_, _promiseCapability_).
1. Let _valueWrapperCapability_ be ! NewPromiseCapability(%Promise%).
1. Perform ! Call(_valueWrapperCapability_.[[Resolve]], *undefined*, &laquo; _nextValue_ &raquo;).
1. Let _onFulfilled_ be a new built-in function object as defined in <emu-xref href="#sec-async-iterator-value-unwrap-functions" title></emu-xref>.
1. Let _onFulfilled_ be a new built-in function object as defined in <emu-xref href="#sec-async-from-sync-iterator-value-unwrap-functions" title></emu-xref>.
1. Set _onFulfilled_.[[Done]] to _nextDone_.
1. Perform ! PerformPromiseThen(_valueWrapperCapability_.[[Promise]], _onFulfilled_, *undefined*, _promiseCapability_).
1. Return _promiseCapability_.[[Promise]].
Expand Down Expand Up @@ -184,7 +172,7 @@ <h1>%AsyncFromSyncIteratorPrototype%.return ( _value_ )</h1>
1. IfAbruptRejectPromise(_returnValue_, _promiseCapability_).
1. Let _valueWrapperCapability_ be ! NewPromiseCapability(%Promise%).
1. Perform ! Call(_valueWrapperCapability_.[[Resolve]], *undefined*, &laquo; _returnValue_ &raquo;).
1. Let _onFulfilled_ be a new built-in function object as defined in <emu-xref href="#sec-async-iterator-value-unwrap-functions" title></emu-xref>.
1. Let _onFulfilled_ be a new built-in function object as defined in <emu-xref href="#sec-async-from-sync-iterator-value-unwrap-functions" title></emu-xref>.
1. Set _onFulfilled_.[[Done]] to _returnDone_.
1. Perform ! PerformPromiseThen(_valueWrapperCapability_.[[Promise]], _onFulfilled_, *undefined*, _promiseCapability_).
1. Return _promiseCapability_.[[Promise]].
Expand Down Expand Up @@ -218,7 +206,7 @@ <h1>%AsyncFromSyncIteratorPrototype%.throw ( _value_ )</h1>
1. IfAbruptRejectPromise(_throwValue_, _promiseCapability_).
1. Let _valueWrapperCapability_ be ! NewPromiseCapability(%Promise%).
1. Perform ! Call(_valueWrapperCapability_.[[Resolve]], *undefined*, &laquo; _throwValue_ &raquo;).
1. Let _onFulfilled_ be a new built-in function object as defined in <emu-xref href="#sec-async-iterator-value-unwrap-functions" title></emu-xref>.
1. Let _onFulfilled_ be a new built-in function object as defined in <emu-xref href="#sec-async-from-sync-iterator-value-unwrap-functions" title></emu-xref>.
1. Set _onFulfilled_.[[Done]] to _throwDone_.
1. Perform ! PerformPromiseThen(_valueWrapperCapability_.[[Promise]], _onFulfilled_, *undefined*, _promiseCapability_).
1. Return _promiseCapability_.[[Promise]].
Expand All @@ -230,6 +218,18 @@ <h1>%AsyncFromSyncIteratorPrototype% [ @@toStringTag ]</h1>
<p>The initial value of the @@toStringTag property is the String value `"Async-from-Sync Iterator"`.</p>
<p>This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }.</p>
</emu-clause>

<emu-clause id="sec-async-from-sync-iterator-value-unwrap-functions">
<h1>Async-from-Sync Iterator Value Unwrap Functions</h1>

<p>An async-from-sync iterator value unwrap function is an anonymous built-in function that is used by methods of %AsyncFromSyncIteratorPrototype% when processing the `value` field of an <i>IteratorResult</i> object, in order to wait for its value if it is a promise and re-package the result in a new "unwrapped" <i>IteratorResult</i> object. Each async iterator value unwrap function has a [[Done]] internal slot.</p>

<p>When an async-from-sync iterator value unwrap function _F_ is called with argument _value_, the following steps are taken:</p>

<emu-alg>
1. Return ! CreateIterResultObject(_value_, _F_.[[Done]]).
</emu-alg>
</emu-clause>
</emu-clause>

<emu-clause id="sec-properties-of-async-from-sync-iterator-instances">
Expand Down
25 changes: 25 additions & 0 deletions spec/return-statement-patch.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<h2>Syntax</h2>
<emu-grammar>
ReturnStatement[Yield, Await] :
`return` `;`
`return` [no LineTerminator here] Expression[+In, ?Yield, ?Await] `;`
</emu-grammar>
<emu-note>
<p>A `return` statement causes a function to cease execution and return a value to the caller. If |Expression| is omitted, the return value is *undefined*. Otherwise, the return value is the value of |Expression|.</p>
</emu-note>

<!-- es6num="13.10.1" -->
<emu-clause id="sec-return-statement-runtime-semantics-evaluation">
<h1>Runtime Semantics: Evaluation</h1>
<emu-grammar>ReturnStatement : `return` `;`</emu-grammar>
<emu-alg>
1. Return Completion{[[Type]]: ~return~, [[Value]]: *undefined*, [[Target]]: ~empty~}.
</emu-alg>
<emu-grammar>ReturnStatement : `return` Expression `;`</emu-grammar>
<emu-alg>
1. Let _exprRef_ be the result of evaluating |Expression|.
1. Let _exprValue_ be ? GetValue(_exprRef_).
1. <ins>If ! GetGeneratorKind() is ~async~, set _exprValue_ to ? Await(_exprValue_).</ins>
1. Return Completion{[[Type]]: ~return~, [[Value]]: _exprValue_, [[Target]]: ~empty~}.
</emu-alg>
</emu-clause>