mirror of
https://github.com/tc39/test262.git
synced 2025-11-30 02:23:10 +01:00
Test IteratorZip iteration for zip
This commit is contained in:
parent
7b03494c04
commit
4f3a15bdb4
@ -0,0 +1,116 @@
|
||||
// Copyright (C) 2025 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-iterator.zip
|
||||
description: >
|
||||
Handle abrupt completion from IteratorStep in IteratorZip.
|
||||
info: |
|
||||
Iterator.zip ( iterables [ , options ] )
|
||||
...
|
||||
16. Return IteratorZip(iters, mode, padding, finishResults).
|
||||
|
||||
IteratorZip ( iters, mode, padding, finishResults )
|
||||
3. 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:
|
||||
...
|
||||
b. Repeat,
|
||||
...
|
||||
v. Let completion be Completion(Yield(results)).
|
||||
vi. If completion is an abrupt completion, then
|
||||
1. Return ? IteratorCloseAll(openIters, completion).
|
||||
...
|
||||
|
||||
IteratorCloseAll ( iters, completion )
|
||||
1. For each element iter of iters, in reverse List order, do
|
||||
a. Set completion to Completion(IteratorClose(iter, completion)).
|
||||
2. Return ? completion.
|
||||
|
||||
IteratorClose ( iteratorRecord, completion )
|
||||
1. Assert: iteratorRecord.[[Iterator]] is an Object.
|
||||
2. Let iterator be iteratorRecord.[[Iterator]].
|
||||
3. Let innerResult be Completion(GetMethod(iterator, "return")).
|
||||
4. If innerResult is a normal completion, then
|
||||
a. Let return be innerResult.[[Value]].
|
||||
b. If return is undefined, return ? completion.
|
||||
c. Set innerResult to Completion(Call(return, iterator)).
|
||||
5. If completion is a throw completion, return ? completion.
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
features: [joint-iteration]
|
||||
---*/
|
||||
|
||||
function ExpectedError() {}
|
||||
|
||||
var log = [];
|
||||
|
||||
var first = {
|
||||
next() {
|
||||
log.push("call first next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, first);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call first return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var second = {
|
||||
next() {
|
||||
log.push("call second next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, second);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call second return");
|
||||
|
||||
throw new ExpectedError();
|
||||
}
|
||||
};
|
||||
|
||||
var third = {
|
||||
next() {
|
||||
log.push("call third next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, third);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call third return");
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
var it = Iterator.zip([first, second, third]);
|
||||
|
||||
it.next();
|
||||
|
||||
assert.throws(ExpectedError, function() {
|
||||
it.return();
|
||||
});
|
||||
|
||||
assert.compareArray(log, [
|
||||
"call first next",
|
||||
"call second next",
|
||||
"call third next",
|
||||
|
||||
"call third return",
|
||||
"call second return",
|
||||
"call first return",
|
||||
]);
|
||||
@ -0,0 +1,145 @@
|
||||
// Copyright (C) 2025 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-iterator.zip
|
||||
description: >
|
||||
Handle abrupt completion from IteratorStepValue in IteratorZip.
|
||||
info: |
|
||||
Iterator.zip ( iterables [ , options ] )
|
||||
...
|
||||
16. Return IteratorZip(iters, mode, padding, finishResults).
|
||||
|
||||
IteratorZip ( iters, mode, padding, finishResults )
|
||||
3. 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:
|
||||
...
|
||||
b. Repeat,
|
||||
...
|
||||
iii. For each integer i such that 0 ≤ i < iterCount, in ascending order, do
|
||||
...
|
||||
3. Else,
|
||||
a. Let result be Completion(IteratorStepValue(iter)).
|
||||
b. If result is an abrupt completion, then
|
||||
i. Remove iter from openIters.
|
||||
ii. Return ? IteratorCloseAll(openIters, result).
|
||||
...
|
||||
d. If result is done, then
|
||||
i. Remove iter from openIters.
|
||||
...
|
||||
|
||||
IteratorCloseAll ( iters, completion )
|
||||
1. For each element iter of iters, in reverse List order, do
|
||||
a. Set completion to Completion(IteratorClose(iter, completion)).
|
||||
2. Return ? completion.
|
||||
|
||||
IteratorClose ( iteratorRecord, completion )
|
||||
1. Assert: iteratorRecord.[[Iterator]] is an Object.
|
||||
2. Let iterator be iteratorRecord.[[Iterator]].
|
||||
3. Let innerResult be Completion(GetMethod(iterator, "return")).
|
||||
4. If innerResult is a normal completion, then
|
||||
a. Let return be innerResult.[[Value]].
|
||||
b. If return is undefined, return ? completion.
|
||||
c. Set innerResult to Completion(Call(return, iterator)).
|
||||
5. If completion is a throw completion, return ? completion.
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
features: [joint-iteration]
|
||||
---*/
|
||||
|
||||
var modes = [
|
||||
"shortest",
|
||||
"longest",
|
||||
"strict",
|
||||
];
|
||||
|
||||
function ExpectedError() {}
|
||||
|
||||
var log = [];
|
||||
|
||||
var first = {
|
||||
next() {
|
||||
log.push("call first next");
|
||||
throw new ExpectedError();
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call first return");
|
||||
}
|
||||
};
|
||||
|
||||
var second = {
|
||||
next() {
|
||||
log.push("unexpected call second next");
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, second);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call second return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var third = {
|
||||
next() {
|
||||
log.push("unexpected call third next");
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, third);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call third return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
// Empty iterator to ensure |return| is not called for closed iterators.
|
||||
var empty = {
|
||||
next() {
|
||||
log.push("call empty next");
|
||||
return {done: true};
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call empty return");
|
||||
}
|
||||
};
|
||||
|
||||
for (var mode of modes) {
|
||||
var it = Iterator.zip([first, second, third], {mode});
|
||||
|
||||
assert.throws(ExpectedError, function() {
|
||||
it.next();
|
||||
});
|
||||
|
||||
assert.compareArray(log, [
|
||||
"call first next",
|
||||
"call third return",
|
||||
"call second return",
|
||||
]);
|
||||
|
||||
// Clear log.
|
||||
log.length = 0;
|
||||
}
|
||||
|
||||
// This case applies only when mode is "longest".
|
||||
var it = Iterator.zip([empty, first, second, third], {mode: "longest"});
|
||||
|
||||
assert.throws(ExpectedError, function() {
|
||||
it.next();
|
||||
});
|
||||
|
||||
assert.compareArray(log, [
|
||||
"call empty next",
|
||||
"call first next",
|
||||
"call third return",
|
||||
"call second return",
|
||||
]);
|
||||
@ -0,0 +1,127 @@
|
||||
// Copyright (C) 2025 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-iterator.zip
|
||||
description: >
|
||||
Handle abrupt completion from IteratorStep in IteratorZip.
|
||||
info: |
|
||||
Iterator.zip ( iterables [ , options ] )
|
||||
...
|
||||
16. Return IteratorZip(iters, mode, padding, finishResults).
|
||||
|
||||
IteratorZip ( iters, mode, padding, finishResults )
|
||||
3. 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:
|
||||
...
|
||||
b. Repeat,
|
||||
...
|
||||
v. Let completion be Completion(Yield(results)).
|
||||
vi. If completion is an abrupt completion, then
|
||||
1. Return ? IteratorCloseAll(openIters, completion).
|
||||
...
|
||||
|
||||
IteratorCloseAll ( iters, completion )
|
||||
1. For each element iter of iters, in reverse List order, do
|
||||
a. Set completion to Completion(IteratorClose(iter, completion)).
|
||||
2. Return ? completion.
|
||||
|
||||
IteratorClose ( iteratorRecord, completion )
|
||||
1. Assert: iteratorRecord.[[Iterator]] is an Object.
|
||||
2. Let iterator be iteratorRecord.[[Iterator]].
|
||||
3. Let innerResult be Completion(GetMethod(iterator, "return")).
|
||||
4. If innerResult is a normal completion, then
|
||||
a. Let return be innerResult.[[Value]].
|
||||
b. If return is undefined, return ? completion.
|
||||
c. Set innerResult to Completion(Call(return, iterator)).
|
||||
5. If completion is a throw completion, return ? completion.
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
features: [joint-iteration]
|
||||
---*/
|
||||
|
||||
function ExpectedError() {}
|
||||
|
||||
var log = [];
|
||||
|
||||
var first = {
|
||||
next() {
|
||||
log.push("call first next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, first);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call first return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var second = {
|
||||
next() {
|
||||
log.push("call second next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, second);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call second return");
|
||||
|
||||
throw new ExpectedError();
|
||||
}
|
||||
};
|
||||
|
||||
var third = {
|
||||
next() {
|
||||
log.push("call third next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, third);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call third return");
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
var fourth = {
|
||||
next() {
|
||||
log.push("call fourth next");
|
||||
return {done: true};
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call fourth return");
|
||||
}
|
||||
};
|
||||
|
||||
var it = Iterator.zip([first, second, third, fourth], {mode: "longest"});
|
||||
|
||||
it.next();
|
||||
|
||||
assert.throws(ExpectedError, function() {
|
||||
it.return();
|
||||
});
|
||||
|
||||
assert.compareArray(log, [
|
||||
"call first next",
|
||||
"call second next",
|
||||
"call third next",
|
||||
"call fourth next",
|
||||
|
||||
"call third return",
|
||||
"call second return",
|
||||
"call first return",
|
||||
]);
|
||||
@ -0,0 +1,125 @@
|
||||
// Copyright (C) 2025 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-iterator.zip
|
||||
description: >
|
||||
Handle abrupt completion from IteratorCloseAll in IteratorZip.
|
||||
info: |
|
||||
Iterator.zip ( iterables [ , options ] )
|
||||
...
|
||||
16. Return IteratorZip(iters, mode, padding, finishResults).
|
||||
|
||||
IteratorZip ( iters, mode, padding, finishResults )
|
||||
3. 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:
|
||||
...
|
||||
b. Repeat,
|
||||
...
|
||||
iii. For each integer i such that 0 ≤ i < iterCount, in ascending order, do
|
||||
...
|
||||
3. Else,
|
||||
...
|
||||
d. If result is done, then
|
||||
i. Remove iter from openIters.
|
||||
ii. If mode is "shortest", then
|
||||
i. Return ? IteratorCloseAll(openIters, ReturnCompletion(undefined)).
|
||||
...
|
||||
|
||||
IteratorCloseAll ( iters, completion )
|
||||
1. For each element iter of iters, in reverse List order, do
|
||||
a. Set completion to Completion(IteratorClose(iter, completion)).
|
||||
2. Return ? completion.
|
||||
|
||||
IteratorClose ( iteratorRecord, completion )
|
||||
1. Assert: iteratorRecord.[[Iterator]] is an Object.
|
||||
2. Let iterator be iteratorRecord.[[Iterator]].
|
||||
3. Let innerResult be Completion(GetMethod(iterator, "return")).
|
||||
4. If innerResult is a normal completion, then
|
||||
a. Let return be innerResult.[[Value]].
|
||||
b. If return is undefined, return ? completion.
|
||||
c. Set innerResult to Completion(Call(return, iterator)).
|
||||
5. If completion is a throw completion, return ? completion.
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
features: [joint-iteration]
|
||||
---*/
|
||||
|
||||
function ExpectedError() {}
|
||||
|
||||
var log = [];
|
||||
|
||||
var first = {
|
||||
next() {
|
||||
log.push("call first next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, first);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call first return");
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
var second = {
|
||||
next() {
|
||||
log.push("call second next");
|
||||
return {done: true};
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call second return");
|
||||
}
|
||||
};
|
||||
|
||||
var third = {
|
||||
next() {
|
||||
log.push("unexpected call third next");
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, third);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call third return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var fourth = {
|
||||
next() {
|
||||
log.push("unexpected call fourth next");
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, fourth);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call fourth return");
|
||||
|
||||
throw new ExpectedError();
|
||||
}
|
||||
};
|
||||
|
||||
var it = Iterator.zip([first, second, third, fourth], {mode: "shortest"});
|
||||
|
||||
assert.throws(ExpectedError, function() {
|
||||
it.next();
|
||||
});
|
||||
|
||||
assert.compareArray(log, [
|
||||
"call first next",
|
||||
"call second next",
|
||||
"call fourth return",
|
||||
"call third return",
|
||||
"call first return",
|
||||
]);
|
||||
@ -0,0 +1,108 @@
|
||||
// Copyright (C) 2025 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-iterator.zip
|
||||
description: >
|
||||
Handle abrupt completion from IteratorCloseAll in IteratorZip.
|
||||
info: |
|
||||
Iterator.zip ( iterables [ , options ] )
|
||||
...
|
||||
16. Return IteratorZip(iters, mode, padding, finishResults).
|
||||
|
||||
IteratorZip ( iters, mode, padding, finishResults )
|
||||
3. 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:
|
||||
...
|
||||
b. Repeat,
|
||||
...
|
||||
iii. For each integer i such that 0 ≤ i < iterCount, in ascending order, do
|
||||
...
|
||||
3. Else,
|
||||
...
|
||||
d. If result is done, then
|
||||
i. Remove iter from openIters.
|
||||
...
|
||||
iii. Else if mode is "strict", then
|
||||
i. If i ≠ 0, then
|
||||
i. Return ? IteratorCloseAll(openIters, ThrowCompletion(a newly created TypeError object)).
|
||||
...
|
||||
|
||||
IteratorCloseAll ( iters, completion )
|
||||
1. For each element iter of iters, in reverse List order, do
|
||||
a. Set completion to Completion(IteratorClose(iter, completion)).
|
||||
2. Return ? completion.
|
||||
|
||||
IteratorClose ( iteratorRecord, completion )
|
||||
1. Assert: iteratorRecord.[[Iterator]] is an Object.
|
||||
2. Let iterator be iteratorRecord.[[Iterator]].
|
||||
3. Let innerResult be Completion(GetMethod(iterator, "return")).
|
||||
4. If innerResult is a normal completion, then
|
||||
a. Let return be innerResult.[[Value]].
|
||||
b. If return is undefined, return ? completion.
|
||||
c. Set innerResult to Completion(Call(return, iterator)).
|
||||
5. If completion is a throw completion, return ? completion.
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
features: [joint-iteration]
|
||||
---*/
|
||||
|
||||
var log = [];
|
||||
|
||||
var first = {
|
||||
next() {
|
||||
log.push("call first next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, first);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call first return");
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
var second = {
|
||||
next() {
|
||||
log.push("call second next");
|
||||
return {done: true};
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call second return");
|
||||
}
|
||||
};
|
||||
|
||||
var third = {
|
||||
next() {
|
||||
log.push("unexpected call third next");
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, third);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call third return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var it = Iterator.zip([first, second, third], {mode: "strict"});
|
||||
|
||||
assert.throws(TypeError, function() {
|
||||
it.next();
|
||||
});
|
||||
|
||||
assert.compareArray(log, [
|
||||
"call first next",
|
||||
"call second next",
|
||||
"call third return",
|
||||
"call first return",
|
||||
]);
|
||||
@ -0,0 +1,123 @@
|
||||
// Copyright (C) 2025 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-iterator.zip
|
||||
description: >
|
||||
Handle abrupt completion from IteratorCloseAll in IteratorZip.
|
||||
info: |
|
||||
Iterator.zip ( iterables [ , options ] )
|
||||
...
|
||||
16. Return IteratorZip(iters, mode, padding, finishResults).
|
||||
|
||||
IteratorZip ( iters, mode, padding, finishResults )
|
||||
3. 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:
|
||||
...
|
||||
b. Repeat,
|
||||
...
|
||||
iii. For each integer i such that 0 ≤ i < iterCount, in ascending order, do
|
||||
...
|
||||
3. Else,
|
||||
...
|
||||
d. If result is done, then
|
||||
i. Remove iter from openIters.
|
||||
...
|
||||
iii. Else if mode is "strict", then
|
||||
...
|
||||
ii. For each integer k such that 1 ≤ k < iterCount, in ascending order, do
|
||||
...
|
||||
iv. Else,
|
||||
i. Return ? IteratorCloseAll(openIters, ThrowCompletion(a newly created TypeError object)).
|
||||
...
|
||||
|
||||
IteratorCloseAll ( iters, completion )
|
||||
1. For each element iter of iters, in reverse List order, do
|
||||
a. Set completion to Completion(IteratorClose(iter, completion)).
|
||||
2. Return ? completion.
|
||||
|
||||
IteratorClose ( iteratorRecord, completion )
|
||||
1. Assert: iteratorRecord.[[Iterator]] is an Object.
|
||||
2. Let iterator be iteratorRecord.[[Iterator]].
|
||||
3. Let innerResult be Completion(GetMethod(iterator, "return")).
|
||||
4. If innerResult is a normal completion, then
|
||||
a. Let return be innerResult.[[Value]].
|
||||
b. If return is undefined, return ? completion.
|
||||
c. Set innerResult to Completion(Call(return, iterator)).
|
||||
5. If completion is a throw completion, return ? completion.
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
features: [joint-iteration]
|
||||
---*/
|
||||
|
||||
var log = [];
|
||||
|
||||
var first = {
|
||||
next() {
|
||||
log.push("call first next");
|
||||
return {done: true};
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call first return");
|
||||
}
|
||||
};
|
||||
|
||||
var second = {
|
||||
next() {
|
||||
log.push("call second next");
|
||||
return {done: true};
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call second return");
|
||||
}
|
||||
};
|
||||
|
||||
var third = {
|
||||
next() {
|
||||
log.push("call third next");
|
||||
return {done: false};
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, third);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call third return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var fourth = {
|
||||
next() {
|
||||
log.push("unexpected call fourth next");
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, fourth);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call fourth return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var it = Iterator.zip([first, second, third, fourth], {mode: "strict"});
|
||||
|
||||
assert.throws(TypeError, function() {
|
||||
it.next();
|
||||
});
|
||||
|
||||
assert.compareArray(log, [
|
||||
"call first next",
|
||||
"call second next",
|
||||
"call third next",
|
||||
"call fourth return",
|
||||
"call third return",
|
||||
]);
|
||||
@ -0,0 +1,125 @@
|
||||
// Copyright (C) 2025 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-iterator.zip
|
||||
description: >
|
||||
Handle abrupt completion from IteratorStep in IteratorZip.
|
||||
info: |
|
||||
Iterator.zip ( iterables [ , options ] )
|
||||
...
|
||||
16. Return IteratorZip(iters, mode, padding, finishResults).
|
||||
|
||||
IteratorZip ( iters, mode, padding, finishResults )
|
||||
3. 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:
|
||||
...
|
||||
b. Repeat,
|
||||
...
|
||||
iii. For each integer i such that 0 ≤ i < iterCount, in ascending order, do
|
||||
...
|
||||
3. Else,
|
||||
...
|
||||
d. If result is done, then
|
||||
i. Remove iter from openIters.
|
||||
...
|
||||
iii. Else if mode is "strict", then
|
||||
...
|
||||
ii. For each integer k such that 1 ≤ k < iterCount, in ascending order, do
|
||||
...
|
||||
ii. Let open be Completion(IteratorStep(iters[k])).
|
||||
iii. If open is an abrupt completion, then
|
||||
i. Remove iters[k] from openIters.
|
||||
ii. Return ? IteratorCloseAll(openIters, open).
|
||||
...
|
||||
|
||||
IteratorCloseAll ( iters, completion )
|
||||
1. For each element iter of iters, in reverse List order, do
|
||||
a. Set completion to Completion(IteratorClose(iter, completion)).
|
||||
2. Return ? completion.
|
||||
|
||||
IteratorClose ( iteratorRecord, completion )
|
||||
1. Assert: iteratorRecord.[[Iterator]] is an Object.
|
||||
2. Let iterator be iteratorRecord.[[Iterator]].
|
||||
3. Let innerResult be Completion(GetMethod(iterator, "return")).
|
||||
4. If innerResult is a normal completion, then
|
||||
a. Let return be innerResult.[[Value]].
|
||||
b. If return is undefined, return ? completion.
|
||||
c. Set innerResult to Completion(Call(return, iterator)).
|
||||
5. If completion is a throw completion, return ? completion.
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
features: [joint-iteration]
|
||||
---*/
|
||||
|
||||
function ExpectedError() {}
|
||||
|
||||
var log = [];
|
||||
|
||||
var first = {
|
||||
next() {
|
||||
log.push("call first next");
|
||||
return {done: true};
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call first return");
|
||||
}
|
||||
};
|
||||
|
||||
var second = {
|
||||
next() {
|
||||
log.push("call second next");
|
||||
throw new ExpectedError();
|
||||
},
|
||||
return() {
|
||||
log.push("unexpected call second return");
|
||||
}
|
||||
};
|
||||
|
||||
var third = {
|
||||
next() {
|
||||
log.push("unexpected call third next");
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, third);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call third return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var fourth = {
|
||||
next() {
|
||||
log.push("unexpected call fourth next");
|
||||
},
|
||||
return() {
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, fourth);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
// NB: Log after above asserts, because failures aren't propagated.
|
||||
log.push("call fourth return");
|
||||
|
||||
// IteratorClose ignores new exceptions when called with a Throw completion.
|
||||
throw new Test262Error();
|
||||
}
|
||||
};
|
||||
|
||||
var it = Iterator.zip([first, second, third, fourth], {mode: "strict"});
|
||||
|
||||
assert.throws(ExpectedError, function() {
|
||||
it.next();
|
||||
});
|
||||
|
||||
assert.compareArray(log, [
|
||||
"call first next",
|
||||
"call second next",
|
||||
"call fourth return",
|
||||
"call third return",
|
||||
]);
|
||||
155
test/built-ins/Iterator/zip/iterator-zip-iteration.js
Normal file
155
test/built-ins/Iterator/zip/iterator-zip-iteration.js
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright (C) 2025 André Bargull. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-iterator.zip
|
||||
description: >
|
||||
Perform iteration in IteratorZip.
|
||||
info: |
|
||||
Iterator.zip ( iterables [ , options ] )
|
||||
...
|
||||
16. Return IteratorZip(iters, mode, padding, finishResults).
|
||||
|
||||
IteratorZip ( iters, mode, padding, finishResults )
|
||||
3. 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:
|
||||
...
|
||||
b. Repeat,
|
||||
...
|
||||
iii. For each integer i such that 0 ≤ i < iterCount, in ascending order, do
|
||||
...
|
||||
3. Else,
|
||||
a. Let result be Completion(IteratorStepValue(iter)).
|
||||
...
|
||||
includes: [compareArray.js]
|
||||
features: [joint-iteration]
|
||||
---*/
|
||||
|
||||
var modes = [
|
||||
"shortest",
|
||||
"longest",
|
||||
"strict",
|
||||
];
|
||||
|
||||
function makeIterator(log, name, elements) {
|
||||
var elementsIter = elements.values();
|
||||
var iterator = {
|
||||
next() {
|
||||
log.push(`call ${name} next`);
|
||||
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, iterator);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
var result = elementsIter.next();
|
||||
return {
|
||||
get done() {
|
||||
log.push(`get ${name}.result.done`);
|
||||
return result.done;
|
||||
},
|
||||
get value() {
|
||||
log.push(`get ${name}.result.value`);
|
||||
return result.value;
|
||||
},
|
||||
};
|
||||
},
|
||||
return() {
|
||||
log.push(`call ${name} return`);
|
||||
|
||||
// Called with the correct receiver and no arguments.
|
||||
assert.sameValue(this, iterator);
|
||||
assert.sameValue(arguments.length, 0);
|
||||
|
||||
return {
|
||||
get done() {
|
||||
log.push(`unexpected get ${name}.result.done`);
|
||||
return result.done;
|
||||
},
|
||||
get value() {
|
||||
log.push(`unexpected get ${name}.result.value`);
|
||||
return result.value;
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
return iterator;
|
||||
}
|
||||
|
||||
for (var mode of modes) {
|
||||
var log = [];
|
||||
var iterables = [
|
||||
makeIterator(log, "first", [1, 2, 3]),
|
||||
makeIterator(log, "second", [4, 5, 6]),
|
||||
makeIterator(log, "third", [7, 8, 9]),
|
||||
];
|
||||
var it = Iterator.zip(iterables, {mode});
|
||||
|
||||
log.push("start");
|
||||
for (var v of it) {
|
||||
log.push("loop");
|
||||
}
|
||||
|
||||
var expected = [
|
||||
"start",
|
||||
|
||||
"call first next",
|
||||
"get first.result.done",
|
||||
"get first.result.value",
|
||||
"call second next",
|
||||
"get second.result.done",
|
||||
"get second.result.value",
|
||||
"call third next",
|
||||
"get third.result.done",
|
||||
"get third.result.value",
|
||||
"loop",
|
||||
|
||||
"call first next",
|
||||
"get first.result.done",
|
||||
"get first.result.value",
|
||||
"call second next",
|
||||
"get second.result.done",
|
||||
"get second.result.value",
|
||||
"call third next",
|
||||
"get third.result.done",
|
||||
"get third.result.value",
|
||||
"loop",
|
||||
|
||||
"call first next",
|
||||
"get first.result.done",
|
||||
"get first.result.value",
|
||||
"call second next",
|
||||
"get second.result.done",
|
||||
"get second.result.value",
|
||||
"call third next",
|
||||
"get third.result.done",
|
||||
"get third.result.value",
|
||||
"loop",
|
||||
];
|
||||
|
||||
switch (mode) {
|
||||
case "shortest": {
|
||||
expected.push(
|
||||
"call first next",
|
||||
"get first.result.done",
|
||||
"call third return",
|
||||
"call second return",
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "longest":
|
||||
case "strict": {
|
||||
expected.push(
|
||||
"call first next",
|
||||
"get first.result.done",
|
||||
"call second next",
|
||||
"get second.result.done",
|
||||
"call third next",
|
||||
"get third.result.done",
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert.compareArray(log, expected);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user