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

Commit

Permalink
Align with the base spec in caching "next" methods
Browse files Browse the repository at this point in the history
Closes #116. See tc39/ecma262#1021.
  • Loading branch information
domenic authored Dec 6, 2017
1 parent d240d2e commit bf36f72
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 45 deletions.
11 changes: 6 additions & 5 deletions spec/generator-definitions-patch.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ <h1>Runtime Semantics: Evaluation</h1>
1. <ins>Let _generatorKind_ be ! GetGeneratorKind().</ins>
1. Let _exprRef_ be the result of evaluating |AssignmentExpression|.
1. Let _value_ be ? GetValue(_exprRef_).
1. Let _iterator_ be ? GetIterator(_value_<ins>, _generatorKind_</ins>).
1. Let _iteratorRecord_ be ? GetIterator(_value_<ins>, _generatorKind_</ins>).
1. Let _iterator_ be _iteratorRecord_.[[Iterator]].
1. Let _received_ be NormalCompletion(*undefined*).
1. Repeat
1. If _received_.[[Type]] is ~normal~, then
1. <del>Let _innerResult_ be ? IteratorNext(_iterator_, _received_.[[Value]]).</del>
1. <ins>Let _innerResult_ be ? Invoke(_iterator_, `"next"`, &laquo; _received_.[[Value]] &raquo;).</ins>
1. <del>Let _innerResult_ be ? IteratorNext(_iteratorRecord_, _received_.[[Value]]).</del>
1. <ins>Let _innerResult_ be ? Call(_iteratorRecord_.[[NextMethod]], _iteratorRecord_.[[Iterator]], &laquo; _received_.[[Value]] &raquo;).</ins>
1. <ins>If _generatorKind_ is ~async~, then set _innerResult_ to ? Await(_innerResult_).</ins>
1. <ins>If Type(_innerResult_) is not Object, throw a *TypeError* exception.</ins>
1. Let _done_ be ? IteratorComplete(_innerResult_).
Expand All @@ -52,8 +53,8 @@ <h1>Runtime Semantics: Evaluation</h1>
1. Else,
1. NOTE: If _iterator_ does not have a `throw` method, this throw is going to terminate the `yield*` loop. But first we need to give _iterator_ a chance to clean up.
1. <ins>Let _closeCompletion_ be Completion{[[Type]]: ~normal~, [[Value]]: ~empty~, [[Target]]: ~empty~}.</ins>
1. <ins>If _generatorKind_ is ~async~, perform ? AsyncIteratorClose(_iterator_, _closeCompletion_).</ins>
1. <ins>Else, p</ins><del>P</del>erform ? IteratorClose(_iterator_, <del>Completion{[[Type]]: ~normal~, [[Value]]: ~empty~, [[Target]]: ~empty~}</del><ins>_closeCompletion_</ins>).
1. <ins>If _generatorKind_ is ~async~, perform ? AsyncIteratorClose(_iteratorRecord_, _closeCompletion_).</ins>
1. <ins>Else, p</ins><del>P</del>erform ? IteratorClose(_iteratorRecord_, <del>Completion{[[Type]]: ~normal~, [[Value]]: ~empty~, [[Target]]: ~empty~}</del><ins>_closeCompletion_</ins>).
1. NOTE: The next step throws a *TypeError* to indicate that there was a `yield*` protocol violation: _iterator_ does not have a `throw` method.
1. Throw a *TypeError* exception.
1. Else,
Expand Down
19 changes: 10 additions & 9 deletions spec/iteration-statements-patch.html
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,8 @@ <h1>Runtime Semantics: ForIn/OfHeadEvaluation ( _TDZnames_, _expr_, _iterationKi
</emu-clause>

<emu-clause id="sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset" aoid="ForIn/OfBodyEvaluation">
<h1>Runtime Semantics: ForIn/OfBodyEvaluation ( _lhs_, _stmt_, _iterator_, _lhsKind_, _labelSet_<ins> [ , _iteratorKind_ ]</ins> )</h1>
<p>The abstract operation ForIn/OfBodyEvaluation is called with arguments _lhs_, _stmt_, _iterator_, _lhsKind_, <del>and </del>_labelSet_<ins>, and optional argument _iteratorKind_</ins>. The value of _lhsKind_ is either ~assignment~, ~varBinding~ or ~lexicalBinding~. <ins>The value of _iteratorKind_ is either ~normal~ or ~async~.</ins></p>
<h1>Runtime Semantics: ForIn/OfBodyEvaluation ( _lhs_, _stmt_, _iteratorRecord_, _lhsKind_, _labelSet_<ins> [ , _iteratorKind_ ]</ins> )</h1>
<p>The abstract operation ForIn/OfBodyEvaluation is called with arguments _lhs_, _stmt_, _iteratorRecord_, _lhsKind_, <del>and </del>_labelSet_<ins>, and optional argument _iteratorKind_</ins>. The value of _lhsKind_ is either ~assignment~, ~varBinding~ or ~lexicalBinding~. <ins>The value of _iteratorKind_ is either ~normal~ or ~async~.</ins></p>
<emu-alg>
1. <ins>If _iteratorKind_ was not passed, let _iteratorKind_ be ~normal~.</ins>
1. Let _oldEnv_ be the running execution context's LexicalEnvironment.
Expand All @@ -378,8 +378,9 @@ <h1>Runtime Semantics: ForIn/OfBodyEvaluation ( _lhs_, _stmt_, _iterator_, _lhsK
1. Assert: _lhs_ is a |LeftHandSideExpression|.
1. Let _assignmentPattern_ be the parse of the source text corresponding to _lhs_ using |AssignmentPattern| as the goal symbol.
1. Repeat
1. <del>Let _nextResult_ be ? IteratorNext(_iterator_).</del>
1. <ins>Let _nextResult_ be ? Invoke(_iterator_, `"next"`, &laquo; &raquo;).</ins>
1. <del>Let _nextResult_ be ? IteratorStep(_iteratorRecord_).</del>
1. <del>If _nextResult_ is *false*, return NormalCompletion(_V_).</del>
1. <ins>Let _nextResult_ be ? Call(_iteratorRecord_.[[NextMethod]], _iteratorRecord_.[[Iterator]], &laquo; &raquo;).</ins>
1. <ins>If _iteratorKind_ is ~async~, then set _nextResult_ to ? Await(_nextResult_).</ins>
1. <ins>If Type(_nextResult_) is not Object, throw a *TypeError* exception.</ins>
1. Let _done_ be ? IteratorComplete(_nextResult_).
Expand Down Expand Up @@ -418,14 +419,14 @@ <h1>Runtime Semantics: ForIn/OfBodyEvaluation ( _lhs_, _stmt_, _iterator_, _lhsK
1. Let _status_ be the result of performing BindingInitialization for _lhs_ passing _nextValue_ and _iterationEnv_ as arguments.
1. If _status_ is an abrupt completion, then
1. Set the running execution context's LexicalEnvironment to _oldEnv_.
1. <ins>If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iterator_, _status_).</ins>
1. Return ? IteratorClose(_iterator_, _status_).
1. <ins>If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iteratorRecord_, _status_).</ins>
1. Return ? IteratorClose(_iteratorRecord_, _status_).
1. Let _result_ be the result of evaluating _stmt_.
1. Set the running execution context's LexicalEnvironment to _oldEnv_.
1. If ! LoopContinues(_result_, _labelSet_) is *false*, <del>return ? IteratorClose(_iterator_, UpdateEmpty(_result_, _V_))</del><ins>then</ins>
1. If ! LoopContinues(_result_, _labelSet_) is *false*, <del>return ? IteratorClose(_iteratorRecord_, UpdateEmpty(_result_, _V_))</del><ins>then</ins>
1. <ins>Let _status_ be UpdateEmpty(_result_, _V_).</ins>
1. <ins>If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iterator_, _status_).</ins>
1. <ins>Return ? IteratorClose(_iterator_, _status_).</ins>
1. <ins>If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iteratorRecord_, _status_).</ins>
1. <ins>Return ? IteratorClose(_iteratorRecord_, _status_).</ins>
1. If _result_.[[Value]] is not ~empty~, let _V_ be _result_.[[Value]].
</emu-alg>
</emu-clause>
Expand Down
25 changes: 12 additions & 13 deletions spec/iteration.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,11 @@ <h1><ins>Async-from-Sync Iterator Objects</ins></h1>
<p>An Async-from-Sync Iterator object is an async iterator that adapts a specific synchronous iterator. There is not a named constructor for Async-from-Sync Iterator objects. Instead, Async-from-Sync iterator objects are created by the CreateAsyncFromSyncIterator abstract operation as needed.</p>

<emu-clause id="sec-createasyncfromsynciterator" aoid="CreateAsyncFromSyncIterator">
<h1>CreateAsyncFromSyncIterator(_syncIterator_) Abstract Operation</h1>
<h1>CreateAsyncFromSyncIterator(_syncIteratorRecord_) Abstract Operation</h1>
<p>The abstract operation CreateAsyncFromSyncIterator is used to create an async iterator from a synchronous iterator. It performs the following steps:</p>
<emu-alg>
1. If Type(_syncIterator_) is not Object, throw a *TypeError* exception.
1. Let _asyncIterator_ be ! ObjectCreate(%AsyncFromSyncIteratorPrototype%, &laquo; [[SyncIterator]] &raquo;).
1. Set _asyncIterator_.[[SyncIterator]] to _syncIterator_.
1. Let _asyncIterator_ be ! ObjectCreate(%AsyncFromSyncIteratorPrototype%, &laquo; [[SyncIteratorRecord]] &raquo;).
1. Set _asyncIterator_.[[SyncIteratorRecord]] to _syncIteratorRecord_.
1. Return _asyncIterator_.
</emu-alg>
</emu-clause>
Expand All @@ -124,12 +123,12 @@ <h1>%AsyncFromSyncIteratorPrototype%.next ( _value_ )</h1>
<emu-alg>
1. Let _O_ be the *this* value.
1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).
1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIterator]] internal slot, then
1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIteratorRecord]] internal slot, then
1. Let _badIteratorError_ be a new *TypeError* exception.
1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, &laquo; _badIteratorError_ &raquo;).
1. Return _promiseCapability_.[[Promise]].
1. Let _syncIterator_ be _O_.[[SyncIterator]].
1. Let _nextResult_ be IteratorNext(_syncIterator_, _value_).
1. Let _syncIteratorRecord_ be _O_.[[SyncIteratorRecord]].
1. Let _nextResult_ be IteratorNext(_syncIteratorRecord_, _value_).
1. IfAbruptRejectPromise(_nextResult_, _promiseCapability_).
1. Let _nextDone_ be IteratorComplete(_nextResult_).
1. IfAbruptRejectPromise(_nextDone_, _promiseCapability_).
Expand All @@ -150,11 +149,11 @@ <h1>%AsyncFromSyncIteratorPrototype%.return ( _value_ )</h1>
<emu-alg>
1. Let _O_ be the *this* value.
1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).
1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIterator]] internal slot, then
1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIteratorRecord]] internal slot, then
1. Let _badIteratorError_ be a new *TypeError* exception.
1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, &laquo; _badIteratorError_ &raquo;).
1. Return _promiseCapability_.[[Promise]].
1. Let _syncIterator_ be _O_.[[SyncIterator]].
1. Let _syncIterator_ be _O_.[[SyncIteratorRecord]].[[Iterator]].
1. Let _return_ be GetMethod(_syncIterator_, `"return"`).
1. IfAbruptRejectPromise(_return_, _promiseCapability_).
1. If _return_ is *undefined*, then
Expand Down Expand Up @@ -185,11 +184,11 @@ <h1>%AsyncFromSyncIteratorPrototype%.throw ( _value_ )</h1>
<emu-alg>
1. Let _O_ be the *this* value.
1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).
1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIterator]] internal slot, then
1. If Type(_O_) is not Object, or if _O_ does not have a [[SyncIteratorRecord]] internal slot, then
1. Let _badIteratorError_ be a new *TypeError* exception.
1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, &laquo; _badIteratorError_ &raquo;).
1. Return _promiseCapability_.[[Promise]].
1. Let _syncIterator_ be _O_.[[SyncIterator]].
1. Let _syncIterator_ be _O_.[[SyncIteratorRecord]].[[Iterator]].
1. Let _throw_ be GetMethod(_syncIterator_, `"throw"`).
1. IfAbruptRejectPromise(_throw_, _promiseCapability_).
1. If _throw_ is *undefined*, then
Expand Down Expand Up @@ -250,10 +249,10 @@ <h1>Properties of Async-from-Sync Iterator Instances</h1>
<tbody>
<tr>
<td>
[[SyncIterator]]
[[SyncIteratorRecord]]
</td>
<td>
The original synchronous iterator which is being adapted.
A Record, of the type returned by GetIterator, representing the original synchronous iterator which is being adapted.
</td>
</tr>
</tbody>
Expand Down
38 changes: 20 additions & 18 deletions spec/iterator-operations.html
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
<emu-clause id="sec-getiterator" aoid="GetIterator">
<h1>GetIterator ( _obj_ <del>[ , _method_ ]</del><ins>[ , _hint_ ]</ins> )</h1>
<emu-note>
<p>This method has been modified to accept an optional parameter _hint_ which indicates whether we should attempt to find an async iterator for the object. The _method_ parameter has been removed. Call sites which use the optional _method_ parameter (`Array.from` and IterableToArrayLike) must be updated to call the function directly instead.</p>
<h1>GetIterator ( _obj_ <ins>[ , _hint_ ]</ins>[ , _method_ ] )</h1>
<emu-note type="editor">
<p>This abstract operation has been modified to accept an optional parameter _hint_ which indicates whether we should attempt to find an async iterator for the object. Existing call sites which use the optional _method_ parameter (`Array.from` and IterableToArrayLike) must be updated to pass the ~normal~ hint.</p>
</emu-note>
<p>The abstract operation GetIterator with argument _obj_ and optional argument _hint_ performs the following steps:</p>
<p>The abstract operation GetIterator with argument _obj_ and optional arguments _hint_ and _method_ performs the following steps:</p>
<emu-alg>
1. <ins>If _hint_ was not passed, let _hint_ be ~normal~.</ins>
1. <ins>Let _method_ be *undefined*.</ins>
1. <ins>If _hint_ is ~async~,</ins>
1. <ins>Set _method_ to ? GetMethod(_obj_, @@asyncIterator).</ins>
1. <ins>If _method_ is *undefined*,
1. <ins>Let _syncMethod_ be ? GetMethod(_obj_, @@iterator).</ins>
1. <ins>Let _syncIterator_ be ? Call(_syncMethod_, _obj_).</ins>
1. <ins>Return ? CreateAsyncFromSyncIterator(_syncIterator_).</ins>
1. <ins>Otherwise, set _method_ to ? GetMethod(_obj_, @@iterator).</ins>
1. <del>If _method_ was not passed, then</del>
1. <del>Let _method_ be ? GetMethod(_obj_, @@iterator).</del>
1. If _method_ is not present, then
1. <del>Set _method_ to ? GetMethod(_obj_, @@iterator).</del>
1. <ins>If _hint_ is ~async~,</ins>
1. <ins>Set _method_ to ? GetMethod(_obj_, @@asyncIterator).</ins>
1. <ins>If _method_ is *undefined*,
1. <ins>Let _syncMethod_ be ? GetMethod(_obj_, @@iterator).</ins>
1. <ins>Let _syncIteratorRecord_ be ? GetIterator(_obj_, ~normal~, _syncMethod_).</ins>
1. <ins>Return ? CreateAsyncFromSyncIterator(_syncIteratorRecord_).</ins>
1. <ins>Otherwise, set _method_ to ? GetMethod(_obj_, @@iterator).</ins>
1. Let _iterator_ be ? Call(_method_, _obj_).
1. If Type(_iterator_) is not Object, throw a *TypeError* exception.
1. Return _iterator_.
1. Let _nextMethod_ be ? GetV(_iterator_, `"next"`).
1. Let _iteratorRecord_ be Record {[[Iterator]]: _iterator_, [[NextMethod]]: _nextMethod_, [[Done]]: *false*}.
1. Return _iteratorRecord_.
</emu-alg>
</emu-clause>

<emu-clause id="sec-asynciteratorclose" aoid="AsyncIteratorClose">
<h1><ins>AsyncIteratorClose ( _iterator_, _completion_ )</ins></h1>
<p>The abstract operation AsyncIteratorClose with arguments _iterator_ and _completion_ is used to notify an async iterator that it should perform any actions it would normally perform when it has reached its completed state:</p>
<h1><ins>AsyncIteratorClose ( _iteratorRecord_, _completion_ )</ins></h1>
<p>The abstract operation AsyncIteratorClose with arguments _iteratorRecord_ and _completion_ is used to notify an async iterator that it should perform any actions it would normally perform when it has reached its completed state:</p>
<emu-alg>
1. Assert: Type(_iterator_) is Object.
1. Assert: Type(_iteratorRecord_.[[Iterator]]) is Object.
1. Assert: _completion_ is a Completion Record.
1. Let _iterator_ be _iteratorRecord_.[[Iterator]].
1. Let _return_ be ? GetMethod(_iterator_, `"return"`).
1. If _return_ is *undefined*, return Completion(_completion_).
1. Let _innerResult_ be Call(_return_, _iterator_, &laquo; &raquo;).
Expand Down

0 comments on commit bf36f72

Please sign in to comment.