Skip to content

Commit 31e846b

Browse files
committed
Add tests from tc39#4496 for zip
1 parent 986de0b commit 31e846b

4 files changed

+357
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright (C) 2025 André Bargull. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-iterator.zip
6+
description: >
7+
Generator is closed from suspended-start state and IteratorClose calls next.
8+
info: |
9+
%IteratorHelperPrototype%.return ( )
10+
...
11+
4. If O.[[GeneratorState]] is suspended-start, then
12+
a. Set O.[[GeneratorState]] to completed.
13+
...
14+
c. Perform ? IteratorCloseAll(O.[[UnderlyingIterators]], ReturnCompletion(undefined)).
15+
d. Return CreateIteratorResultObject(undefined, true).
16+
...
17+
18+
IteratorCloseAll ( iters, completion )
19+
1. For each element iter of iters, in reverse List order, do
20+
a. Set completion to Completion(IteratorClose(iter, completion)).
21+
2. Return ? completion.
22+
23+
IteratorClose ( iteratorRecord, completion )
24+
...
25+
3. Let innerResult be Completion(GetMethod(iterator, "return")).
26+
4. If innerResult is a normal completion, then
27+
a. Let return be innerResult.[[Value]].
28+
b. If return is undefined, return ? completion.
29+
c. Set innerResult to Completion(Call(return, iterator)).
30+
...
31+
32+
%IteratorHelperPrototype%.next ( )
33+
1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").
34+
35+
GeneratorResume ( generator, value, generatorBrand )
36+
1. Let state be ? GeneratorValidate(generator, generatorBrand).
37+
2. If state is completed, return CreateIteratorResultObject(undefined, true).
38+
...
39+
40+
GeneratorValidate ( generator, generatorBrand )
41+
...
42+
5. Let state be generator.[[GeneratorState]].
43+
6. If state is executing, throw a TypeError exception.
44+
7. Return state.
45+
features: [joint-iteration]
46+
---*/
47+
48+
var returnCallCount = 0;
49+
50+
var underlying = {
51+
next() {
52+
throw new Test262Error("Unexpected call to next");
53+
},
54+
return() {
55+
returnCallCount += 1;
56+
57+
// The generator state is already set to "completed". The generator state is
58+
// not "executing", so `GeneratorValidate` succeeds and `GeneratorResume`
59+
// returns with `CreateIteratorResultObject()`.
60+
var result = it.next();
61+
assert.sameValue(result.value, undefined);
62+
assert.sameValue(result.done, true);
63+
64+
return {};
65+
},
66+
};
67+
68+
var it = Iterator.zip([underlying]);
69+
70+
assert.sameValue(returnCallCount, 0);
71+
72+
// This `return()` call sets the generator state to "completed" and then calls
73+
// `IteratorClose()`.
74+
var result = it.return();
75+
assert.sameValue(result.value, undefined);
76+
assert.sameValue(result.done, true);
77+
78+
assert.sameValue(returnCallCount, 1);
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (C) 2025 André Bargull. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-iterator.zip
6+
description: >
7+
Generator is closed from suspended-start state and IteratorClose calls return.
8+
info: |
9+
%IteratorHelperPrototype%.return ( )
10+
...
11+
4. If O.[[GeneratorState]] is suspended-start, then
12+
a. Set O.[[GeneratorState]] to completed.
13+
...
14+
c. Perform ? IteratorCloseAll(O.[[UnderlyingIterators]], ReturnCompletion(undefined)).
15+
d. Return CreateIteratorResultObject(undefined, true).
16+
5. Let C be ReturnCompletion(undefined).
17+
6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper").
18+
19+
IteratorCloseAll ( iters, completion )
20+
1. For each element iter of iters, in reverse List order, do
21+
a. Set completion to Completion(IteratorClose(iter, completion)).
22+
2. Return ? completion.
23+
24+
IteratorClose ( iteratorRecord, completion )
25+
...
26+
3. Let innerResult be Completion(GetMethod(iterator, "return")).
27+
4. If innerResult is a normal completion, then
28+
a. Let return be innerResult.[[Value]].
29+
b. If return is undefined, return ? completion.
30+
c. Set innerResult to Completion(Call(return, iterator)).
31+
...
32+
8. Return ? completion.
33+
34+
GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand )
35+
1. Let state be ? GeneratorValidate(generator, generatorBrand).
36+
2. If state is suspended-start, then
37+
...
38+
3. If state is completed, then
39+
a. If abruptCompletion is a return completion, then
40+
i. Return CreateIteratorResultObject(abruptCompletion.[[Value]], true).
41+
...
42+
43+
GeneratorValidate ( generator, generatorBrand )
44+
...
45+
5. Let state be generator.[[GeneratorState]].
46+
6. If state is executing, throw a TypeError exception.
47+
7. Return state.
48+
features: [joint-iteration]
49+
---*/
50+
51+
var returnCallCount = 0;
52+
53+
var underlying = {
54+
next() {
55+
throw new Test262Error("Unexpected call to next");
56+
},
57+
return() {
58+
returnCallCount += 1;
59+
60+
// The generator state is already set to "completed", so this `return()`
61+
// call proceeds to `GeneratorResumeAbrupt`. The generator state is not
62+
// "executing", so `GeneratorValidate` succeeds and `GeneratorResumeAbrupt`
63+
// returns with `CreateIteratorResultObject()`.
64+
var result = it.return();
65+
assert.sameValue(result.value, undefined);
66+
assert.sameValue(result.done, true);
67+
68+
return {};
69+
},
70+
};
71+
72+
var it = Iterator.zip([underlying]);
73+
74+
assert.sameValue(returnCallCount, 0);
75+
76+
// This `return()` call sets the generator state to "completed" and then calls
77+
// `IteratorClose()`.
78+
var result = it.return();
79+
assert.sameValue(result.value, undefined);
80+
assert.sameValue(result.done, true);
81+
82+
assert.sameValue(returnCallCount, 1);
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright (C) 2025 André Bargull. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-iterator.zip
6+
description: >
7+
Generator is closed from suspended-yield state and IteratorClose calls next.
8+
info: |
9+
%IteratorHelperPrototype%.return ( )
10+
...
11+
5. Let C be ReturnCompletion(undefined).
12+
6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper").
13+
14+
GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand )
15+
1. Let state be ? GeneratorValidate(generator, generatorBrand).
16+
...
17+
4. Assert: state is suspended-yield.
18+
...
19+
8. Set generator.[[GeneratorState]] to executing.
20+
...
21+
10. Resume the suspended evaluation of genContext using abruptCompletion as
22+
the result of the operation that suspended it. Let result be the
23+
Completion Record returned by the resumed computation.
24+
...
25+
26+
GeneratorValidate ( generator, generatorBrand )
27+
...
28+
5. Let state be generator.[[GeneratorState]].
29+
6. If state is executing, throw a TypeError exception.
30+
7. Return state.
31+
32+
IteratorZip ( iters, mode, padding, finishResults )
33+
...
34+
3. Let closure be a new Abstract Closure with no parameters that captures
35+
iters, iterCount, openIters, mode, padding, and finishResults, and
36+
performs the following steps when called:
37+
...
38+
b. Repeat,
39+
...
40+
v. Let completion be Completion(Yield(results)).
41+
vi. If completion is an abrupt completion, then
42+
1. Return ? IteratorCloseAll(openIters, completion).
43+
...
44+
45+
IteratorCloseAll ( iters, completion )
46+
1. For each element iter of iters, in reverse List order, do
47+
a. Set completion to Completion(IteratorClose(iter, completion)).
48+
2. Return ? completion.
49+
50+
IteratorClose ( iteratorRecord, completion )
51+
...
52+
3. Let innerResult be Completion(GetMethod(iterator, "return")).
53+
4. If innerResult is a normal completion, then
54+
a. Let return be innerResult.[[Value]].
55+
b. If return is undefined, return ? completion.
56+
c. Set innerResult to Completion(Call(return, iterator)).
57+
...
58+
59+
%IteratorHelperPrototype%.next ( )
60+
1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").
61+
62+
GeneratorResume ( generator, value, generatorBrand )
63+
1. Let state be ? GeneratorValidate(generator, generatorBrand).
64+
...
65+
includes: [compareArray.js]
66+
features: [joint-iteration]
67+
---*/
68+
69+
var returnCallCount = 0;
70+
71+
var underlying = {
72+
next() {
73+
return {value: 123, done: false};
74+
},
75+
return() {
76+
returnCallCount += 1;
77+
78+
// The generator state is set to "executing", so this `next()` call throws
79+
// a TypeError when `GeneratorResume` performs `GeneratorValidate`.
80+
assert.throws(TypeError, function() {
81+
it.next();
82+
});
83+
84+
return {};
85+
},
86+
};
87+
88+
var it = Iterator.zip([underlying]);
89+
90+
// Move generator into "suspended-yield" state.
91+
var result = it.next();
92+
assert.compareArray(result.value, [123]);
93+
assert.sameValue(result.done, false);
94+
95+
assert.sameValue(returnCallCount, 0);
96+
97+
// This `return()` call continues execution in the suspended generator.
98+
var result = it.return();
99+
assert.sameValue(result.value, undefined);
100+
assert.sameValue(result.done, true);
101+
102+
assert.sameValue(returnCallCount, 1);
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright (C) 2025 André Bargull. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-iterator.zip
6+
description: >
7+
Generator is closed from suspended-yield state and IteratorClose calls return.
8+
info: |
9+
%IteratorHelperPrototype%.return ( )
10+
...
11+
5. Let C be ReturnCompletion(undefined).
12+
6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper").
13+
14+
GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand )
15+
1. Let state be ? GeneratorValidate(generator, generatorBrand).
16+
...
17+
4. Assert: state is suspended-yield.
18+
...
19+
8. Set generator.[[GeneratorState]] to executing.
20+
...
21+
10. Resume the suspended evaluation of genContext using abruptCompletion as
22+
the result of the operation that suspended it. Let result be the
23+
Completion Record returned by the resumed computation.
24+
...
25+
26+
GeneratorValidate ( generator, generatorBrand )
27+
...
28+
5. Let state be generator.[[GeneratorState]].
29+
6. If state is executing, throw a TypeError exception.
30+
7. Return state.
31+
32+
IteratorZip ( iters, mode, padding, finishResults )
33+
...
34+
3. Let closure be a new Abstract Closure with no parameters that captures
35+
iters, iterCount, openIters, mode, padding, and finishResults, and
36+
performs the following steps when called:
37+
...
38+
b. Repeat,
39+
...
40+
v. Let completion be Completion(Yield(results)).
41+
vi. If completion is an abrupt completion, then
42+
1. Return ? IteratorCloseAll(openIters, completion).
43+
...
44+
45+
IteratorCloseAll ( iters, completion )
46+
1. For each element iter of iters, in reverse List order, do
47+
a. Set completion to Completion(IteratorClose(iter, completion)).
48+
2. Return ? completion.
49+
50+
IteratorClose ( iteratorRecord, completion )
51+
...
52+
3. Let innerResult be Completion(GetMethod(iterator, "return")).
53+
4. If innerResult is a normal completion, then
54+
a. Let return be innerResult.[[Value]].
55+
b. If return is undefined, return ? completion.
56+
c. Set innerResult to Completion(Call(return, iterator)).
57+
...
58+
includes: [compareArray.js]
59+
features: [joint-iteration]
60+
---*/
61+
62+
var returnCallCount = 0;
63+
64+
var underlying = {
65+
next() {
66+
return {value: 123, done: false};
67+
},
68+
return() {
69+
returnCallCount += 1;
70+
71+
// The generator state is set to "executing", so this `return()` call throws
72+
// a TypeError when `GeneratorResumeAbrupt` performs `GeneratorValidate`.
73+
assert.throws(TypeError, function() {
74+
it.return();
75+
});
76+
77+
return {};
78+
},
79+
};
80+
81+
var it = Iterator.zip([underlying]);
82+
83+
// Move generator into "suspended-yield" state.
84+
var result = it.next();
85+
assert.compareArray(result.value, [123]);
86+
assert.sameValue(result.done, false);
87+
88+
assert.sameValue(returnCallCount, 0);
89+
90+
// This `return()` call continues execution in the suspended generator.
91+
var result = it.return();
92+
assert.sameValue(result.value, undefined);
93+
assert.sameValue(result.done, true);
94+
95+
assert.sameValue(returnCallCount, 1);

0 commit comments

Comments
 (0)