From bf36f72409105f91ed3ffade14bfe40522a85040 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Wed, 6 Dec 2017 18:40:58 -0500 Subject: [PATCH] Align with the base spec in caching "next" methods Closes #116. See https://github.com/tc39/ecma262/pull/1021. --- spec/generator-definitions-patch.html | 11 ++++---- spec/iteration-statements-patch.html | 19 +++++++------- spec/iteration.html | 25 +++++++++--------- spec/iterator-operations.html | 38 ++++++++++++++------------- 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/spec/generator-definitions-patch.html b/spec/generator-definitions-patch.html index a05d9d1..5ca5cc4 100644 --- a/spec/generator-definitions-patch.html +++ b/spec/generator-definitions-patch.html @@ -24,12 +24,13 @@

Runtime Semantics: Evaluation

1. Let _generatorKind_ be ! GetGeneratorKind(). 1. Let _exprRef_ be the result of evaluating |AssignmentExpression|. 1. Let _value_ be ? GetValue(_exprRef_). - 1. Let _iterator_ be ? GetIterator(_value_, _generatorKind_). + 1. Let _iteratorRecord_ be ? GetIterator(_value_, _generatorKind_). + 1. Let _iterator_ be _iteratorRecord_.[[Iterator]]. 1. Let _received_ be NormalCompletion(*undefined*). 1. Repeat 1. If _received_.[[Type]] is ~normal~, then - 1. Let _innerResult_ be ? IteratorNext(_iterator_, _received_.[[Value]]). - 1. Let _innerResult_ be ? Invoke(_iterator_, `"next"`, « _received_.[[Value]] »). + 1. Let _innerResult_ be ? IteratorNext(_iteratorRecord_, _received_.[[Value]]). + 1. Let _innerResult_ be ? Call(_iteratorRecord_.[[NextMethod]], _iteratorRecord_.[[Iterator]], « _received_.[[Value]] »). 1. If _generatorKind_ is ~async~, then set _innerResult_ to ? Await(_innerResult_). 1. If Type(_innerResult_) is not Object, throw a *TypeError* exception. 1. Let _done_ be ? IteratorComplete(_innerResult_). @@ -52,8 +53,8 @@

Runtime Semantics: Evaluation

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. Let _closeCompletion_ be Completion{[[Type]]: ~normal~, [[Value]]: ~empty~, [[Target]]: ~empty~}. - 1. If _generatorKind_ is ~async~, perform ? AsyncIteratorClose(_iterator_, _closeCompletion_). - 1. Else, pPerform ? IteratorClose(_iterator_, Completion{[[Type]]: ~normal~, [[Value]]: ~empty~, [[Target]]: ~empty~}_closeCompletion_). + 1. If _generatorKind_ is ~async~, perform ? AsyncIteratorClose(_iteratorRecord_, _closeCompletion_). + 1. Else, pPerform ? IteratorClose(_iteratorRecord_, Completion{[[Type]]: ~normal~, [[Value]]: ~empty~, [[Target]]: ~empty~}_closeCompletion_). 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, diff --git a/spec/iteration-statements-patch.html b/spec/iteration-statements-patch.html index 19b8935..7b940cb 100644 --- a/spec/iteration-statements-patch.html +++ b/spec/iteration-statements-patch.html @@ -367,8 +367,8 @@

Runtime Semantics: ForIn/OfHeadEvaluation ( _TDZnames_, _expr_, _iterationKi -

Runtime Semantics: ForIn/OfBodyEvaluation ( _lhs_, _stmt_, _iterator_, _lhsKind_, _labelSet_ [ , _iteratorKind_ ] )

-

The abstract operation ForIn/OfBodyEvaluation is called with arguments _lhs_, _stmt_, _iterator_, _lhsKind_, and _labelSet_, and optional argument _iteratorKind_. The value of _lhsKind_ is either ~assignment~, ~varBinding~ or ~lexicalBinding~. The value of _iteratorKind_ is either ~normal~ or ~async~.

+

Runtime Semantics: ForIn/OfBodyEvaluation ( _lhs_, _stmt_, _iteratorRecord_, _lhsKind_, _labelSet_ [ , _iteratorKind_ ] )

+

The abstract operation ForIn/OfBodyEvaluation is called with arguments _lhs_, _stmt_, _iteratorRecord_, _lhsKind_, and _labelSet_, and optional argument _iteratorKind_. The value of _lhsKind_ is either ~assignment~, ~varBinding~ or ~lexicalBinding~. The value of _iteratorKind_ is either ~normal~ or ~async~.

1. If _iteratorKind_ was not passed, let _iteratorKind_ be ~normal~. 1. Let _oldEnv_ be the running execution context's LexicalEnvironment. @@ -378,8 +378,9 @@

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. Let _nextResult_ be ? IteratorNext(_iterator_). - 1. Let _nextResult_ be ? Invoke(_iterator_, `"next"`, « »). + 1. Let _nextResult_ be ? IteratorStep(_iteratorRecord_). + 1. If _nextResult_ is *false*, return NormalCompletion(_V_). + 1. Let _nextResult_ be ? Call(_iteratorRecord_.[[NextMethod]], _iteratorRecord_.[[Iterator]], « »). 1. If _iteratorKind_ is ~async~, then set _nextResult_ to ? Await(_nextResult_). 1. If Type(_nextResult_) is not Object, throw a *TypeError* exception. 1. Let _done_ be ? IteratorComplete(_nextResult_). @@ -418,14 +419,14 @@

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. If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iterator_, _status_). - 1. Return ? IteratorClose(_iterator_, _status_). + 1. If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iteratorRecord_, _status_). + 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*, return ? IteratorClose(_iterator_, UpdateEmpty(_result_, _V_))then + 1. If ! LoopContinues(_result_, _labelSet_) is *false*, return ? IteratorClose(_iteratorRecord_, UpdateEmpty(_result_, _V_))then 1. Let _status_ be UpdateEmpty(_result_, _V_). - 1. If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iterator_, _status_). - 1. Return ? IteratorClose(_iterator_, _status_). + 1. If _iteratorKind_ is ~async~, return ? AsyncIteratorClose(_iteratorRecord_, _status_). + 1. Return ? IteratorClose(_iteratorRecord_, _status_). 1. If _result_.[[Value]] is not ~empty~, let _V_ be _result_.[[Value]]. diff --git a/spec/iteration.html b/spec/iteration.html index 2e86ce7..106e05f 100644 --- a/spec/iteration.html +++ b/spec/iteration.html @@ -105,12 +105,11 @@

Async-from-Sync Iterator Objects

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.

-

CreateAsyncFromSyncIterator(_syncIterator_) Abstract Operation

+

CreateAsyncFromSyncIterator(_syncIteratorRecord_) Abstract Operation

The abstract operation CreateAsyncFromSyncIterator is used to create an async iterator from a synchronous iterator. It performs the following steps:

- 1. If Type(_syncIterator_) is not Object, throw a *TypeError* exception. - 1. Let _asyncIterator_ be ! ObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIterator]] »). - 1. Set _asyncIterator_.[[SyncIterator]] to _syncIterator_. + 1. Let _asyncIterator_ be ! ObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »). + 1. Set _asyncIterator_.[[SyncIteratorRecord]] to _syncIteratorRecord_. 1. Return _asyncIterator_.
@@ -124,12 +123,12 @@

%AsyncFromSyncIteratorPrototype%.next ( _value_ )

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*, « _badIteratorError_ »). 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_). @@ -150,11 +149,11 @@

%AsyncFromSyncIteratorPrototype%.return ( _value_ )

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*, « _badIteratorError_ »). 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 @@ -185,11 +184,11 @@

%AsyncFromSyncIteratorPrototype%.throw ( _value_ )

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*, « _badIteratorError_ »). 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 @@ -250,10 +249,10 @@

Properties of Async-from-Sync Iterator Instances

- [[SyncIterator]] + [[SyncIteratorRecord]] - 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. diff --git a/spec/iterator-operations.html b/spec/iterator-operations.html index 0e1f374..a3f35a5 100644 --- a/spec/iterator-operations.html +++ b/spec/iterator-operations.html @@ -1,33 +1,35 @@ -

GetIterator ( _obj_ [ , _method_ ][ , _hint_ ] )

- -

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.

+

GetIterator ( _obj_ [ , _hint_ ][ , _method_ ] )

+ +

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.

-

The abstract operation GetIterator with argument _obj_ and optional argument _hint_ performs the following steps:

+

The abstract operation GetIterator with argument _obj_ and optional arguments _hint_ and _method_ performs the following steps:

1. If _hint_ was not passed, let _hint_ be ~normal~. - 1. Let _method_ be *undefined*. - 1. If _hint_ is ~async~, - 1. Set _method_ to ? GetMethod(_obj_, @@asyncIterator). - 1. If _method_ is *undefined*, - 1. Let _syncMethod_ be ? GetMethod(_obj_, @@iterator). - 1. Let _syncIterator_ be ? Call(_syncMethod_, _obj_). - 1. Return ? CreateAsyncFromSyncIterator(_syncIterator_). - 1. Otherwise, set _method_ to ? GetMethod(_obj_, @@iterator). - 1. If _method_ was not passed, then - 1. Let _method_ be ? GetMethod(_obj_, @@iterator). + 1. If _method_ is not present, then + 1. Set _method_ to ? GetMethod(_obj_, @@iterator). + 1. If _hint_ is ~async~, + 1. Set _method_ to ? GetMethod(_obj_, @@asyncIterator). + 1. If _method_ is *undefined*, + 1. Let _syncMethod_ be ? GetMethod(_obj_, @@iterator). + 1. Let _syncIteratorRecord_ be ? GetIterator(_obj_, ~normal~, _syncMethod_). + 1. Return ? CreateAsyncFromSyncIterator(_syncIteratorRecord_). + 1. Otherwise, set _method_ to ? GetMethod(_obj_, @@iterator). 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_.
-

AsyncIteratorClose ( _iterator_, _completion_ )

-

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:

+

AsyncIteratorClose ( _iteratorRecord_, _completion_ )

+

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:

- 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_, « »).