-
Notifications
You must be signed in to change notification settings - Fork 2
/
spec.emu
262 lines (252 loc) · 12.4 KB
/
spec.emu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
<!doctype html>
<meta charset="utf8">
<pre class="metadata">
title: Joint Iteration
status: proposal
stage: 2.7
contributors: Michael Ficarra
location: https://tc39.es/proposal-joint-iteration/
copyright: false
</pre>
<emu-clause id="sec-iterator.zip">
<h1>Iterator.zip ( _iterables_ [ , _options_ ] )</h1>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. If _iterables_ is not an Object, throw a *TypeError* exception.
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _mode_ be ? Get(_options_, *"mode"*).
1. If _mode_ is *undefined*, set _mode_ to *"shortest"*.
1. If _mode_ is not one of *"shortest"*, *"longest"*, or *"strict"*, throw a *TypeError* exception.
1. Let _paddingOption_ be *undefined*.
1. If _mode_ is *"longest"*, then
1. Set _paddingOption_ to ? Get(_options_, *"padding"*).
1. If _paddingOption_ is not *undefined* and _paddingOption_ is not an Object, throw a *TypeError* exception.
1. Let _iters_ be a new empty List.
1. Let _padding_ be a new empty List.
1. Let _inputIter_ be ? GetIterator(_iterables_, ~sync~).
1. Let _next_ be ~not-started~.
1. Repeat, while _next_ is not ~done~,
1. Set _next_ to Completion(IteratorStepValue(_inputIter_)).
1. IfAbruptCloseIterators(_next_, _iters_).
1. If _next_ is not ~done~, then
1. Let _iter_ be Completion(GetIteratorFlattenable(_next_, ~reject-strings~)).
1. IfAbruptCloseIterators(_iter_, the list-concatenation of « _inputIter_ » and _iters_).
1. Append _iter_ to _iters_.
1. Let _iterCount_ be the number of elements in _iters_.
1. If _mode_ is *"longest"*, then
1. If _paddingOption_ is *undefined*, then
1. Perform the following steps _iterCount_ times:
1. Append *undefined* to _padding_.
1. Else,
1. Let _paddingIter_ be Completion(GetIterator(_paddingOption_, ~sync~)).
1. IfAbruptCloseIterators(_paddingIter_, _iters_).
1. Let _usingIterator_ be *true*.
1. Perform the following steps _iterCount_ times:
1. If _usingIterator_ is *true*, then
1. Set _next_ to Completion(IteratorStepValue(_paddingIter_)).
1. IfAbruptCloseIterators(_next_, _iters_).
1. If _next_ is ~done~, then
1. Set _usingIterator_ to *false*.
1. Else,
1. Append _next_ to _padding_.
1. If _usingIterator_ is *false*, append *undefined* to _padding_.
1. If _usingIterator_ is *true*, then
1. Let _completion_ be Completion(IteratorClose(_paddingIter_, NormalCompletion(~unused~))).
1. IfAbruptCloseIterators(_completion_, _iters_).
1. Let _finishResults_ be a new Abstract Closure with parameters (_results_) that captures nothing and performs the following steps when called:
1. Return CreateArrayFromList(_results_).
1. Return IteratorZip(_iters_, _mode_, _padding_, _finishResults_).
</emu-alg>
</emu-clause>
<emu-clause id="sec-iterator.zipkeyed">
<h1>Iterator.zipKeyed ( _iterables_ [ , _options_ ] )</h1>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. If _iterables_ is not an Object, throw a *TypeError* exception.
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _mode_ be ? Get(_options_, *"mode"*).
1. If _mode_ is *undefined*, set _mode_ to *"shortest"*.
1. If _mode_ is not one of *"shortest"*, *"longest"*, or *"strict"*, throw a *TypeError* exception.
1. Let _paddingOption_ be *undefined*.
1. If _mode_ is *"longest"*, then
1. Set _paddingOption_ to ? Get(_options_, *"padding"*).
1. If _paddingOption_ is not *undefined* and _paddingOption_ is not an Object, throw a *TypeError* exception.
1. Let _iters_ be a new empty List.
1. Let _padding_ be a new empty List.
1. Let _allKeys_ be ? _iterables_.[[OwnPropertyKeys]]().
1. Let _keys_ be a new empty List.
1. For each element _key_ of _allKeys_, do
1. Let _desc_ be Completion(_iterables_.[[GetOwnProperty]](_key_)).
1. IfAbruptCloseIterators(_desc_, _iters_).
1. If _desc_ is not *undefined* and _desc_.[[Enumerable]] is *true*, then
1. Let _value_ be *undefined*.
1. If IsDataDescriptor(_desc_) is *true*, then
1. Set _value_ to _desc_.[[Value]].
1. Else,
1. Assert: IsAccessorDescriptor(_desc_) is *true*.
1. Let _getter_ be _desc_.[[Get]].
1. If _getter_ is not *undefined*, then
1. Let _getterResult_ be Completion(Call(_getter_, _iterables_)).
1. IfAbruptCloseIterators(_getterResult_, _iters_).
1. Set _value_ to _getterResult_.
1. If _value_ is not *undefined*, then
1. Append _key_ to _keys_.
1. Let _iter_ be Completion(GetIteratorFlattenable(_value_, ~reject-strings~)).
1. IfAbruptCloseIterators(_iter_, _iters_).
1. Append _iter_ to _iters_.
1. Let _iterCount_ be the number of elements in _iters_.
1. If _mode_ is *"longest"*, then
1. If _paddingOption_ is *undefined*, then
1. Perform the following steps _iterCount_ times:
1. Append *undefined* to _padding_.
1. Else,
1. For each element _key_ of _keys_, do
1. Let _value_ be Completion(Get(_paddingOption_, _key_)).
1. IfAbruptCloseIterators(_value_, _iters_).
1. Append _value_ to _padding_.
1. Let _finishResults_ be a new Abstract Closure with parameters (_results_) that captures _keys_ and _iterCount_ and performs the following steps when called:
1. Let _obj_ be OrdinaryObjectCreate(*null*).
1. For each integer _i_ such that 0 ≤ _i_ < _iterCount_, in ascending order, do
1. Perform ! CreateDataPropertyOrThrow(_obj_, _keys_[_i_], _results_[_i_]).
1. Return _obj_.
1. Return IteratorZip(_iters_, _mode_, _padding_, _finishResults_).
</emu-alg>
</emu-clause>
<emu-clause id="sec-IteratorZip" type="abstract operation">
<h1>
IteratorZip (
_iters_: a List of Iterator Records,
_mode_: either *"shortest"*, *"longest"*, or *"strict"*,
_padding_: a List of ECMAScript language values,
_finishResults_: an Abstract Closure that takes a List of ECMAScript values and returns an ECMAScript value,
): a Generator
</h1>
<dl class="header">
</dl>
<emu-alg>
1. Let _iterCount_ be the number of elements in _iters_.
1. Let _openIters_ be a copy of _iters_.
1. Let _closure_ be a new Abstract Closure with no parameters that captures _iters_, _iterCount_, _openIters_, _mode_, _padding_, and _finishResults_, and performs the following steps when called:
1. If _iterCount_ = 0, return ReturnCompletion(*undefined*).
1. Repeat,
1. Let _results_ be a new empty List.
1. Assert: _openIters_ is not empty.
1. For each integer _i_ such that 0 ≤ _i_ < _iterCount_, in ascending order, do
1. Let _iter_ be _iters_[_i_].
1. If _iter_ is *null*, then
1. Assert: _mode_ is *"longest"*.
1. Let _result_ be _padding_[_i_].
1. Else,
1. Let _result_ be Completion(IteratorStepValue(_iter_)).
1. If _result_ is an abrupt completion, then
1. Remove _iter_ from _openIters_.
1. Return ? IteratorCloseAll(_openIters_, _result_).
1. Set _result_ to ! _result_.
1. If _result_ is ~done~, then
1. Remove _iter_ from _openIters_.
1. If _mode_ is *"shortest"*, then
1. Return ? IteratorCloseAll(_openIters_, ReturnCompletion(*undefined*)).
1. Else if _mode_ is *"strict"*, then
1. If _i_ ≠ 0, then
1. Return ? IteratorCloseAll(_openIters_, ThrowCompletion(a newly created *TypeError* object)).
1. For each integer _k_ such that 1 ≤ _k_ < _iterCount_, in ascending order, do
1. Assert: _iters_[_k_] is not *null*.
1. Let _open_ be Completion(IteratorStep(_iters_[_k_])).
1. If _open_ is an abrupt completion, then
1. Remove _iters_[_k_] from _openIters_.
1. Return ? IteratorCloseAll(_openIters_, _open_).
1. Set _open_ to ! _open_.
1. If _open_ is ~done~, then
1. Remove _iters_[_k_] from _openIters_.
1. Else,
1. Return ? IteratorCloseAll(_openIters_, ThrowCompletion(a newly created *TypeError* object)).
1. Return ReturnCompletion(*undefined*).
1. Else,
1. Assert: _mode_ is *"longest"*.
1. If _openIters_ is empty, return ReturnCompletion(*undefined*).
1. Set _iters_[_i_] to *null*.
1. Set _result_ to _padding_[_i_].
1. Append _result_ to _results_.
1. Set _results_ to _finishResults_(_results_).
1. Let _completion_ be Completion(Yield(_results_)).
1. If _completion_ is an abrupt completion, then
1. Return ? IteratorCloseAll(_openIters_, _completion_).
1. Let _gen_ be CreateIteratorFromClosure(_closure_, *"Iterator Helper"*, %IteratorHelperPrototype%, « [[UnderlyingIterators]] »).
1. Set _gen_.[[UnderlyingIterators]] to _openIters_.
1. Return _gen_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-closeall" type="abstract operation">
<h1>
IteratorCloseAll (
_iters_: a List of Iterator Records,
_completion_: a Completion Record,
): a Completion Record
</h1>
<dl class="header">
</dl>
<emu-alg>
1. For each element _iter_ of _iters_, in reverse List order, do
1. Set _completion_ to Completion(IteratorClose(_iter_, _completion_)).
1. Return ? _completion_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-ifabruptcloseiterators" aoid="IfAbruptCloseIterators">
<h1>IfAbruptCloseIterators ( _value_, _iteratorRecords_ )</h1>
<p>IfAbruptCloseIterators is a shorthand for a sequence of algorithm steps that use a list of Iterator Records. An algorithm step of the form:</p>
<emu-alg>
1. IfAbruptCloseIterators(_value_, _iteratorRecords_).
</emu-alg>
<p>means the same thing as:</p>
<emu-alg>
1. Assert: _value_ is a Completion Record.
1. If _value_ is an abrupt completion, return ? IteratorCloseAll(_iteratorRecords_, _value_).
1. Else, set _value_ to _value_.[[Value]].
</emu-alg>
</emu-clause>
<emu-clause id="sec-%iteratorhelperprototype%.return">
<h1>%IteratorHelperPrototype%.return ( )</h1>
<emu-alg>
1. Let _O_ be *this* value.
1. <del>Perform ? RequireInternalSlot(_O_, [[UnderlyingIterator]]).</del>
1. <ins>Perform ? RequireInternalSlot(_O_, [[UnderlyingIterators]]).</ins>
1. Assert: _O_ has a [[GeneratorState]] slot.
1. If _O_.[[GeneratorState]] is ~suspended-start~, 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. <del>Perform ? IteratorClose(_O_.[[UnderlyingIterator]], ReturnCompletion(*undefined*)).</del>
1. <ins>Perform ? IteratorCloseAll(_O_.[[UnderlyingIterators]], ReturnCompletion(*undefined*)).</ins>
1. Return CreateIteratorResultObject(*undefined*, *true*).
1. Let _C_ be Completion { [[Type]]: ~return~, [[Value]]: *undefined*, [[Target]]: ~empty~ }.
1. Return ? GeneratorResumeAbrupt(_O_, _C_, *"Iterator Helper"*).
</emu-alg>
</emu-clause>
<emu-clause id="stolen-infra">
<h1>Infra</h1>
<emu-note>
<p>
These AOs are taken from ecma402 and are listed here because they will need to move to ecma262. This is the first API in ecma262 that will take an options bag.
</p>
</emu-note>
<emu-clause id="sec-getoptionsobject" type="abstract operation">
<h1>
GetOptionsObject (
_options_: an ECMAScript language value,
): either a normal completion containing an Object or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>
It returns an Object suitable for use with GetOption, either _options_ itself or a default empty Object.
It throws a *TypeError* if _options_ is not *undefined* and not an Object.
</dd>
</dl>
<emu-alg>
1. If _options_ is *undefined*, then
1. Return OrdinaryObjectCreate(*null*).
1. If _options_ is an Object, then
1. Return _options_.
1. Throw a *TypeError* exception.
</emu-alg>
</emu-clause>
</emu-clause>