From 5ec9f6351ee7a4375b9bb7881d497009d96aceaf Mon Sep 17 00:00:00 2001 From: Kevin Gibbons Date: Wed, 15 Feb 2023 22:17:15 -0800 Subject: [PATCH 1/2] Normative: close underlying iterators when return is called before next --- spec.html | 64 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/spec.html b/spec.html index 42001c5..f0f2a73 100644 --- a/spec.html +++ b/spec.html @@ -272,8 +272,15 @@

%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. 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"*).
@@ -316,7 +323,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_. @@ -338,7 +347,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_. @@ -362,7 +373,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_. @@ -387,7 +400,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_. @@ -422,7 +437,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_. @@ -546,3 +563,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_. + +
+
From 817afa865496bb3c3c616ac5414c07e9d6fc6bb1 Mon Sep 17 00:00:00 2001 From: Michael Ficarra Date: Wed, 29 Mar 2023 19:39:38 -0600 Subject: [PATCH 2/2] Update spec.html --- spec.html | 1 + 1 file changed, 1 insertion(+) diff --git a/spec.html b/spec.html index f0f2a73..a94a0c4 100644 --- a/spec.html +++ b/spec.html @@ -277,6 +277,7 @@

%IteratorHelperPrototype%.return ( )

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~ }.