diff --git a/README.md b/README.md index d12d515..bcedf7a 100644 --- a/README.md +++ b/README.md @@ -335,6 +335,17 @@ const wrapper = Iterator.from(iter); wrapper.next() // { value: 1, done: false } ``` +## Iterator helpers and the generator protocol + +The generator protocol facilitates coordination between a producer and a +consumer, which is necessarily broken by iteration-based transforms. There is +no way to properly preserve or re-establish this coordination. We've taken the +philosophy that any iterators produced by the helpers this proposal adds only +implement the iterator protocol and make no attempt to support generators which +use the remainder of the generator protocol. Specifically, such iterators do +not implement `.throw` and do not forward the parameter of `.next` or `.return` +to an underlying or "source" iterator. + ## More Example Usage ### Lazy Iteration over sets diff --git a/spec.html b/spec.html index 9a267b6..7e52e6b 100644 --- a/spec.html +++ b/spec.html @@ -149,27 +149,6 @@

1. Return _iteratorRecord_. - - -

- IteratorStep ( - _iteratorRecord_: an Iterator Record, - optional _value_: an ECMAScript language value, - ): either a normal completion containing either an Object or *false*, or a throw completion -

-
-
- - 1. Let _result_ be ? IteratorNext(_iteratorRecord_). - 1. If _value_ is present, then - 1. Let _result_ be ? IteratorNext(_iteratorRecord_, _value_). - 1. Else, - 1. Let _result_ be ? IteratorNext(_iteratorRecord_). - 1. Let _done_ be ? IteratorComplete(_result_). - 1. If _done_ is *true*, return *false*. - 1. Return _result_. - -
@@ -252,38 +231,23 @@

The %WrapForValidIteratorPrototype% Object

-

%WrapForValidIteratorPrototype%.next ( _value_ )

+

%WrapForValidIteratorPrototype%.next ( )

1. Let _O_ be *this* value. 1. Perform ? RequireInternalSlot(_O_, [[Iterated]]). - 1. If _value_ is not present, then - 1. Return ? IteratorNext(_O_.[[Iterated]]). - 1. Else, - 1. Return ? IteratorNext(_O_.[[Iterated]], _value_). + 1. Return ? IteratorNext(_O_.[[Iterated]]).
-

%WrapForValidIteratorPrototype%.return ( _v_ )

+

%WrapForValidIteratorPrototype%.return ( )

1. Let _O_ be *this* value. 1. Perform ? RequireInternalSlot(_O_, [[Iterated]]). - 1. Let _result_ be ? IteratorClose(_O_.[[Iterated]], NormalCompletion(_v_)). + 1. Let _result_ be ? IteratorClose(_O_.[[Iterated]], NormalCompletion(*undefined*)). 1. Return CreateIterResultObject(_result_, true).
- - -

%WrapForValidIteratorPrototype%.throw ( _v_ )

- - 1. Let _O_ be *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[Iterated]]). - 1. Let _iterator_ be _O_.[[Iterated]].[[Iterator]]. - 1. Let _throw_ be ? GetMethod(_iterator_, *"throw"*). - 1. If _throw_ is *undefined*, return ThrowCompletion(_v_). - 1. Otherwise, return ? Call(_throw_, _iterator_, « _v_ »). - -
@@ -352,16 +316,13 @@

The %WrapForValidAsyncIteratorPrototype% Object

-

%WrapForValidAsyncIteratorPrototype%.next ( _value_ )

+

%WrapForValidAsyncIteratorPrototype%.next ( )

1. Let _O_ be *this* value. 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). 1. Let _check_ be Completion(RequireInternalSlot(_O_, [[AsyncIterated]])). 1. IfAbruptRejectPromise(_check_, _promiseCapability_). - 1. If _value_ is not present, then - 1. Let _result_ be Completion(IteratorNext(_O_.[[AsyncIterated]])). - 1. Else, - 1. Let _result_ be Completion(IteratorNext(_O_.[[AsyncIterated]], _value_)). + 1. Let _result_ be Completion(IteratorNext(_O_.[[AsyncIterated]])). 1. IfAbruptRejectPromise(_result_, _promiseCapability_). 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _result_ »). 1. Return _promiseCapability_.[[Promise]]. @@ -369,39 +330,19 @@

%WrapForValidAsyncIteratorPrototype%.next ( _value_ )

-

%WrapForValidAsyncIteratorPrototype%.return ( _v_ )

+

%WrapForValidAsyncIteratorPrototype%.return ( )

1. Let _O_ be *this* value. 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). 1. Let _check_ be Completion(RequireInternalSlot(_O_, [[AsyncIterated]])). 1. IfAbruptRejectPromise(_check_, _promiseCapability_). - 1. Let _result_ be Completion(AsyncIteratorClose(_O_.[[AsyncIterated]], NormalCompletion(_v_))). + 1. Let _result_ be Completion(AsyncIteratorClose(_O_.[[AsyncIterated]], NormalCompletion(*undefined*))). 1. IfAbruptRejectPromise(_result_, _promiseCapability_). 1. Let _iterResult_ be CreateIterResultObject(_result_, *true*). 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _iterResult_ »). 1. Return _promiseCapability_.[[Promise]].
- - -

%WrapForValidAsyncIteratorPrototype%.throw ( _v_ )

- - 1. Let _O_ be *this* value. - 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). - 1. Let _check_ be Completion(RequireInternalSlot(_O_, [[AsyncIterated]])). - 1. IfAbruptRejectPromise(_check_, _promiseCapability_). - 1. Let _iterator_ be _O_.[[AsyncIterated]].[[Iterator]]. - 1. Let _throw_ be Completion(GetMethod(_iterator_, *"throw"*)). - 1. IfAbruptRejectPromise(_throw_, _promiseCapability_). - 1. If _throw_ is *undefined*, then - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _v_ »). - 1. Return _promiseCapability_.[[Promise]]. - 1. Let _result_ be Completion(Call(_throw_, _iterator_, « _v_ »)). - 1. IfAbruptRejectPromise(_result_, _promiseCapability_). - 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _result_ »). - 1. Return _promiseCapability_.[[Promise]]. - -
@@ -422,24 +363,16 @@

The %IteratorHelperPrototype% Object

-

%IteratorHelperPrototype%.next ( _value_ )

+

%IteratorHelperPrototype%.next ( )

- 1. Return ? GeneratorResume(*this* value, _value_, ~Iterator Helper~). + 1. Return ? GeneratorResume(*this* value, *undefined*, ~Iterator Helper~).
-

%IteratorHelperPrototype%.return ( _value_ )

- - 1. Let _C_ be Completion { [[Type]]: ~return~, [[Value]]: _value_, [[Target]]: ~empty~ }. - 1. Return ? GeneratorResumeAbrupt(*this* value, _C_, ~Iterator Helper~). - -
- - -

%IteratorHelperPrototype%.throw ( _exception_ )

+

%IteratorHelperPrototype%.return ( )

- 1. Let _C_ be ThrowCompletion(_exception_). + 1. Let _C_ be Completion { [[Type]]: ~return~, [[Value]]: *undefined*, [[Target]]: ~empty~ }. 1. Return ? GeneratorResumeAbrupt(*this* value, _C_, ~Iterator Helper~).
@@ -467,25 +400,17 @@

The %AsyncIteratorHelperPrototype% Object

-

%AsyncIteratorHelperPrototype%.next ( _value_ )

+

%AsyncIteratorHelperPrototype%.next ( )

- 1. Let _C_ be NormalCompletion(_value_). + 1. Let _C_ be NormalCompletion(*undefined*). 1. Return ! AsyncGeneratorEnqueue(*this* value, _C_, ~Async Iterator Helper~).
-

%AsyncIteratorHelperPrototype%.return ( _value_ )

+

%AsyncIteratorHelperPrototype%.return ( )

- 1. Let _C_ be Completion { [[Type]]: ~return~, [[Value]]: _value_, [[Target]]: ~empty~ }. - 1. Return ! AsyncGeneratorEnqueue(*this* value, _C_, ~Async Iterator Helper~). - -
- - -

%AsyncIteratorHelperPrototype%.throw ( _exception_ )

- - 1. Let _C_ be ThrowCompletion(_exception_). + 1. Let _C_ be Completion { [[Type]]: ~return~, [[Value]]: *undefined*, [[Target]]: ~empty~ }. 1. Return ! AsyncGeneratorEnqueue(*this* value, _C_, ~Async Iterator Helper~).
@@ -518,15 +443,14 @@

Iterator.prototype.map ( _mapper_ )

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception. 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and _mapper_ and performs the following steps when called: - 1. Let _lastValue_ be *undefined*. 1. Repeat, - 1. Let _next_ be ? IteratorStep(_iterated_, _lastValue_). + 1. Let _next_ be ? IteratorStep(_iterated_). 1. If _next_ is *false*, return *undefined*. 1. Let _value_ be ? IteratorValue(_next_). 1. Let _mapped_ be Completion(Call(_mapper_, *undefined*, « _value_ »)). 1. IfAbruptCloseIterator(_mapped_, _iterated_). - 1. Set _lastValue_ to Completion(Yield(_mapped_)). - 1. IfAbruptCloseIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(_mapped_)). + 1. IfAbruptCloseIterator(_completion_, _iterated_). 1. Return CreateIteratorFromClosure(_closure_, ~Iterator Helper~, %IteratorHelperPrototype%). @@ -537,16 +461,15 @@

Iterator.prototype.filter ( _filterer_ )

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_filterer_) is *false*, throw a *TypeError* exception. 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and _filterer_ and performs the following steps when called: - 1. Let _lastValue_ be *undefined*. 1. Repeat, - 1. Let _next_ be ? IteratorStep(_iterated_, _lastValue_). + 1. Let _next_ be ? IteratorStep(_iterated_). 1. If _next_ is *false*, return *undefined*. 1. Let _value_ be ? IteratorValue(_next_). 1. Let _selected_ be Completion(Call(_filterer_, *undefined*, « _value_ »)). 1. IfAbruptCloseIterator(_selected_, _iterated_). 1. If ToBoolean(_selected_) is *true*, then - 1. Set _lastValue_ to Completion(Yield(_value_)). - 1. IfAbruptCloseIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(_value_)). + 1. IfAbruptCloseIterator(_completion_, _iterated_). 1. Return CreateIteratorFromClosure(_closure_, ~Iterator Helper~, %IteratorHelperPrototype%). @@ -561,16 +484,15 @@

Iterator.prototype.take ( _limit_ )

1. If _integerLimit_ < 0, throw a *RangeError* exception. 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and _integerLimit_ and performs the following steps when called: 1. Let _remaining_ be _integerLimit_. - 1. Let _lastValue_ be *undefined*. 1. Repeat, 1. If _remaining_ is 0, then 1. Return ? IteratorClose(_iterated_, NormalCompletion(*undefined*)). 1. If _remaining_ is not +∞, then 1. Set _remaining_ to _remaining_ - 1. - 1. Let _next_ be ? IteratorStep(_iterated_, _lastValue_). + 1. Let _next_ be ? IteratorStep(_iterated_). 1. If _next_ is *false*, return *undefined*. - 1. Set _lastValue_ to Completion(Yield(? IteratorValue(_next_))). - 1. IfAbruptCloseIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(? IteratorValue(_next_))). + 1. IfAbruptCloseIterator(_completion_, _iterated_). 1. Return CreateIteratorFromClosure(_closure_, ~Iterator Helper~, %IteratorHelperPrototype%). @@ -590,12 +512,11 @@

Iterator.prototype.drop ( _limit_ )

1. Set _remaining_ to _remaining_ - 1. 1. Let _next_ be ? IteratorStep(_iterated_). 1. If _next_ is *false*, return *undefined*. - 1. Let _lastValue_ be *undefined*. 1. Repeat, - 1. Let _next_ be ? IteratorStep(_iterated_, _lastValue_). + 1. Let _next_ be ? IteratorStep(_iterated_). 1. If _next_ is *false*, return *undefined*. - 1. Set _lastValue_ to Completion(Yield(? IteratorValue(_next_))). - 1. IfAbruptCloseIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(? IteratorValue(_next_))). + 1. IfAbruptCloseIterator(_completion_, _iterated_). 1. Return CreateIteratorFromClosure(_closure_, ~Iterator Helper~, %IteratorHelperPrototype%). @@ -606,15 +527,14 @@

Iterator.prototype.indexed ( )

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and performs the following steps when called: 1. Let _index_ be 0. - 1. Let _lastValue_ be *undefined*. 1. Repeat, - 1. Let _next_ be ? IteratorStep(_iterated_, _lastValue_). + 1. Let _next_ be ? IteratorStep(_iterated_). 1. If _next_ is *false*, return *undefined*. 1. Let _value_ be ? IteratorValue(_next_). 1. Let _pair_ be CreateArrayFromList(« _index_, _value_ »). 1. Set _index_ to _index_ + 1. - 1. Set _lastValue_ to Completion(Yield(_pair_)). - 1. IfAbruptCloseIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(_pair_)). + 1. IfAbruptCloseIterator(_completion_, _iterated_). 1. Return CreateIteratorFromClosure(_closure_, ~Iterator Helper~, %IteratorHelperPrototype%). @@ -635,11 +555,10 @@

Iterator.prototype.flatMap ( _mapper_ )

1. IfAbruptCloseIterator(_innerIterator_, _iterated_). 1. Let _innerAlive_ be *true*. 1. Repeat, while _innerAlive_ is *true*, - 1. Let _innerNext_ be Completion(IteratorNext(_innerIterator_)). + 1. Let _innerNext_ be Completion(IteratorStep(_innerIterator_)). 1. IfAbruptCloseIterator(_innerNext_, _iterated_). - 1. Let _innerComplete_ be Completion(IteratorComplete(_innerNext_)). - 1. IfAbruptCloseIterator(_innerComplete_, _iterated_). - 1. If _innerComplete_ is *true*, set _innerAlive_ to *false*. + 1. If _innerNext_ is *false*, then + 1. Set _innerAlive_ to *false*. 1. Else, 1. Let _innerValue_ be Completion(IteratorValue(_innerNext_)). 1. IfAbruptCloseIterator(_innerValue_, _iterated_). @@ -772,17 +691,16 @@

AsyncIterator.prototype.map ( _mapper_ )

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception. 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and _mapper_ and performs the following steps when called: - 1. Let _lastValue_ be *undefined*. 1. Repeat, - 1. Let _next_ be ? Await(? IteratorNext(_value_, _lastValue_)). + 1. Let _next_ be ? Await(? IteratorNext(_value_)). 1. If ? IteratorComplete(_next_) is *true*, return *undefined*. 1. Let _value_ be ? IteratorValue(_next_). 1. Let _mapped_ be Completion(Call(_mapper_, *undefined*, « _value_ »)). 1. IfAbruptCloseAsyncIterator(_mapped_, _iterated_). - 1. Set _mapped_ to Await(_mapped_). + 1. Set _mapped_ to Completion(Await(_mapped_)). 1. IfAbruptCloseAsyncIterator(_mapped_, _iterated_). - 1. Set _lastValue_ to Completion(Yield(_mapped_)). - 1. IfAbruptCloseAsyncIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(_mapped_)). + 1. IfAbruptCloseAsyncIterator(_completion_, _iterated_). 1. Return CreateAsyncIteratorFromClosure(_closure_, ~Async Iterator Helper~, %AsyncIteratorHelperPrototype%). @@ -793,18 +711,17 @@

AsyncIterator.prototype.filter ( _filterer_ )

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. If IsCallable(_filterer_) is *false*, throw a *TypeError* exception. 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and _filterer_ and performs the following steps when called: - 1. Let _lastValue_ be *undefined*. 1. Repeat, - 1. Let _next_ be ? Await(? IteratorNext(_value_, _lastValue_)). + 1. Let _next_ be ? Await(? IteratorNext(_value_)). 1. If ? IteratorComplete(_next_) is *true*, return *undefined*. 1. Let _value_ be ? IteratorValue(_next_). 1. Let _selected_ be Completion(Call(_filterer_, *undefined*, « _value_ »)). 1. IfAbruptCloseAsyncIterator(_selected_, _iterated_). - 1. Set _selected_ to Await(_selected_). + 1. Set _selected_ to Completion(Await(_selected_)). 1. IfAbruptCloseAsyncIterator(_selected_, _iterated_). 1. If ToBoolean(_selected_) is *true*, then - 1. Set _lastValue_ to Completion(Yield(_value_)). - 1. IfAbruptCloseAsyncIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(_value_)). + 1. IfAbruptCloseAsyncIterator(_completion_, _iterated_). 1. Return CreateAsyncIteratorFromClosure(_closure_, ~Async Iterator Helper~, %AsyncIteratorHelperPrototype%). @@ -819,16 +736,15 @@

AsyncIterator.prototype.take ( _limit_ )

1. If _integerLimit_ < 0, throw a *RangeError* exception. 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and _integerLimit_ and performs the following steps when called: 1. Let _remaining_ be _integerLimit_. - 1. Let _lastValue_ be *undefined*. 1. Repeat, 1. If _remaining_ is 0, then 1. Return ? AsyncIteratorClose(_iterated_, NormalCompletion(*undefined*)). 1. If _remaining_ is not +∞, then 1. Set _remaining_ to _remaining_ - 1. - 1. Let _next_ be ? Await(? IteratorNext(_iterated_, _lastValue_)). + 1. Let _next_ be ? Await(? IteratorNext(_iterated_)). 1. If ? IteratorComplete(_next_) is *true*, return *undefined*. - 1. Set _lastValue_ to Completion(Yield(? IteratorValue(_next_))). - 1. IfAbruptCloseAsyncIterator(_lastValue_, _iterated_). + 1. Set _completion_ to Completion(Yield(? IteratorValue(_next_))). + 1. IfAbruptCloseAsyncIterator(_completion_, _iterated_). 1. Return CreateAsyncIteratorFromClosure(_closure_, ~Async Iterator Helper~, %AsyncIteratorHelperPrototype%). @@ -848,12 +764,11 @@

AsyncIterator.prototype.drop ( _limit_ )

1. Set _remaining_ to _remaining_ - 1. 1. Let _next_ be ? Await(? IteratorNext(_iterated_)). 1. If ? IteratorComplete(_next_) is *true*, return *undefined*. - 1. Let _lastValue_ be *undefined*. 1. Repeat, - 1. Let _next_ be ? Await(? IteratorNext(_iterated_, _lastValue_)). + 1. Let _next_ be ? Await(? IteratorNext(_iterated_)). 1. If ? IteratorComplete(_next_) is *true*, return *undefined*. - 1. Set _lastValue_ to Completion(Yield(? IteratorValue(_next_))). - 1. IfAbruptCloseAsyncIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(? IteratorValue(_next_))). + 1. IfAbruptCloseAsyncIterator(_completion_, _iterated_). 1. Return CreateAsyncIteratorFromClosure(_closure_, ~Async Iterator Helper~, %AsyncIteratorHelperPrototype%). @@ -864,15 +779,14 @@

AsyncIterator.prototype.indexed ( )

1. Let _iterated_ be ? GetIteratorDirect(*this* value). 1. Let _closure_ be a new Abstract Closure with no parameters that captures _iterated_ and performs the following steps when called: 1. Let _index_ be 0. - 1. Let _lastValue_ be *undefined*. 1. Repeat, - 1. Let _next_ be ? Await(? IteratorNext(_iterated_, _lastValue_)). + 1. Let _next_ be ? Await(? IteratorNext(_iterated_)). 1. If ? IteratorComplete(_next_) is *true*, return *undefined*. 1. Let _value_ be ? IteratorValue(_next_). 1. Let _pair_ be CreateArrayFromList(« _index_, _value_ »). 1. Set _index_ to _index_ + 1. - 1. Set _lastValue_ to Completion(Yield(_pair_)). - 1. IfAbruptCloseAsyncIterator(_lastValue_, _iterated_). + 1. Let _completion_ be Completion(Yield(_pair_)). + 1. IfAbruptCloseAsyncIterator(_completion_, _iterated_). 1. Return CreateAsyncIteratorFromClosure(_closure_, ~Async Iterator Helper~, %AsyncIteratorHelperPrototype%). @@ -890,7 +804,7 @@

AsyncIterator.prototype.flatMap ( _mapper_ )

1. Let _value_ be ? IteratorValue(_next_). 1. Let _mapped_ be Completion(Call(_mapper_, *undefined*, « _value_ »)). 1. IfAbruptCloseAsyncIterator(_mapped_, _iterated_). - 1. Set _mapped_ to Await(_mapped_). + 1. Set _mapped_ to Completion(Await(_mapped_)). 1. IfAbruptCloseAsyncIterator(_mapped_, _iterated_). 1. Let _innerIterator_ be Completion(GetIterator(_mapped_, ~async~)). 1. IfAbruptCloseAsyncIterator(_innerIterator_, _iterated_). @@ -898,11 +812,12 @@

AsyncIterator.prototype.flatMap ( _mapper_ )

1. Repeat, while _innerAlive_ is *true*, 1. Let _innerNextPromise_ be Completion(IteratorNext(_innerIterator_)). 1. IfAbruptCloseAsyncIterator(_innerNextPromise_, _iterated_). - 1. Let _innerNext_ be Await(_innerNextPromise_). + 1. Let _innerNext_ be Completion(Await(_innerNextPromise_)). 1. IfAbruptCloseAsyncIterator(_innerNext_, _iterated_). 1. Let _innerComplete_ be Completion(IteratorComplete(_innerNext_)). 1. IfAbruptCloseAsyncIterator(_innerComplete_, _iterated_). - 1. If _innerComplete_ is *true*, set _innerAlive_ to *false*. + 1. If _innerComplete_ is *true*, then + 1. Set _innerAlive_ to *false*. 1. Else, 1. Let _innerValue_ be Completion(IteratorValue(_innerNext_)). 1. IfAbruptCloseAsyncIterator(_innerValue_, _iterated_).