test262/test/built-ins/Iterator/zipKeyed/iterator-zip-iteration-iterator-close-abrupt-completion.js
2025-11-25 13:06:50 -08:00

117 lines
3.1 KiB
JavaScript

// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-iterator.zipkeyed
description: >
Handle abrupt completion from IteratorStep in IteratorZip.
info: |
Iterator.zipKeyed ( 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.zipKeyed({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",
]);