From 5a57b6b55c187a4ecd2d7e7f46cb00d4d111315a Mon Sep 17 00:00:00 2001 From: Kevin Gibbons Date: Wed, 29 Mar 2023 18:41:37 -0700 Subject: [PATCH] Normative: close underlying iterators when return is called before next (#267) Co-authored-by: Michael Ficarra --- spec.html | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/spec.html b/spec.html index 738324d..67526f2 100644 --- a/spec.html +++ b/spec.html @@ -271,8 +271,16 @@

%IteratorHelperPrototype%.next ( )

%IteratorHelperPrototype%.return ( )

+ 1. Let _O_ be *this* value. + 1. Perform ? RequireInternalSlot(_O_, [[UnderlyingIterator]]). + 1. Assert: _O_ has a [[GeneratorState]] slot. + 1. If _O_.[[GeneratorState]] is ~suspendedStart~, then + 1. Set _O_.[[GeneratorState]] to ~completed~. + 1. NOTE: Once a generator enters the completed state it never leaves it and its associated execution context is never resumed. Any execution state associated with _O_ can be discarded at this point. + 1. Perform ? IteratorClose(_O_.[[UnderlyingIterator]], NormalCompletion(~unused~)). + 1. Return CreateIterResultObject(*undefined*, *true*). 1. Let _C_ be Completion { [[Type]]: ~return~, [[Value]]: *undefined*, [[Target]]: ~empty~ }. - 1. Return ? GeneratorResumeAbrupt(*this* value, _C_, *"Iterator Helper"*). + 1. Return ? GeneratorResumeAbrupt(_O_, _C_, *"Iterator Helper"*).
@@ -317,7 +325,9 @@

Iterator.prototype.map ( _mapper_ )

1. Let _completion_ be Completion(Yield(_mapped_)). 1. IfAbruptCloseIterator(_completion_, _iterated_). 1. Set _counter_ to _counter_ + 1. - 1. Return CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%). + 1. Let _result_ be CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%, « [[UnderlyingIterator]] »). + 1. Set _result_.[[UnderlyingIterator]] to _iterated_. + 1. Return _result_. @@ -341,7 +351,9 @@

Iterator.prototype.filter ( _predicate_ )

1. Let _completion_ be Completion(Yield(_value_)). 1. IfAbruptCloseIterator(_completion_, _iterated_). 1. Set _counter_ to _counter_ + 1. - 1. Return CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%). + 1. Let _result_ be CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%, « [[UnderlyingIterator]] »). + 1. Set _result_.[[UnderlyingIterator]] to _iterated_. + 1. Return _result_. @@ -367,7 +379,9 @@

Iterator.prototype.take ( _limit_ )

1. If _next_ is *false*, return *undefined*. 1. Let _completion_ be Completion(Yield(? IteratorValue(_next_))). 1. IfAbruptCloseIterator(_completion_, _iterated_). - 1. Return CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%). + 1. Let _result_ be CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%, « [[UnderlyingIterator]] »). + 1. Set _result_.[[UnderlyingIterator]] to _iterated_. + 1. Return _result_. @@ -394,7 +408,9 @@

Iterator.prototype.drop ( _limit_ )

1. If _next_ is *false*, return *undefined*. 1. Let _completion_ be Completion(Yield(? IteratorValue(_next_))). 1. IfAbruptCloseIterator(_completion_, _iterated_). - 1. Return CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%). + 1. Let _result_ be CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%, « [[UnderlyingIterator]] »). + 1. Set _result_.[[UnderlyingIterator]] to _iterated_. + 1. Return _result_. @@ -431,7 +447,9 @@

Iterator.prototype.flatMap ( _mapper_ )

1. IfAbruptCloseIterator(_backupCompletion_, _iterated_). 1. Return ? IteratorClose(_completion_, _iterated_). 1. Set _counter_ to _counter_ + 1. - 1. Return CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%). + 1. Let _result_ be CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%, « [[UnderlyingIterator]] »). + 1. Set _result_.[[UnderlyingIterator]] to _iterated_. + 1. Return _result_. @@ -567,3 +585,38 @@

Iterator.prototype [ @@toStringTag ]

+ + +

Updated Abstract Operations

+ + +

+ CreateIteratorFromClosure ( + _closure_: an Abstract Closure with no parameters, + _generatorBrand_: a String or ~empty~, + _generatorPrototype_: an Object, + optional _extraSlots_: a List of names of internal slots, + ): a Generator +

+
+
+ + 1. NOTE: _closure_ can contain uses of the Yield operation to yield an IteratorResult object. + 1. If _extraSlots_ is not present, set _extraSlots_ to a new empty List. + 1. Let _internalSlotsList_ be the list-concatenation of _extraSlots_ and « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] ». + 1. Let _generator_ be OrdinaryObjectCreate(_generatorPrototype_, _internalSlotsList_). + 1. Set _generator_.[[GeneratorBrand]] to _generatorBrand_. + 1. Set _generator_.[[GeneratorState]] to *undefined*. + 1. Let _callerContext_ be the running execution context. + 1. Let _calleeContext_ be a new execution context. + 1. Set the Function of _calleeContext_ to *null*. + 1. Set the Realm of _calleeContext_ to the current Realm Record. + 1. Set the ScriptOrModule of _calleeContext_ to _callerContext_'s ScriptOrModule. + 1. If _callerContext_ is not already suspended, suspend _callerContext_. + 1. Push _calleeContext_ onto the execution context stack; _calleeContext_ is now the running execution context. + 1. Perform GeneratorStart(_generator_, _closure_). + 1. Remove _calleeContext_ from the execution context stack and restore _callerContext_ as the running execution context. + 1. Return _generator_. + +
+