iterator-zip-iteration-longest-iterator-close-abrupt-completion.js (3426B)
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.zipkeyed 6 description: > 7 Handle abrupt completion from IteratorStep in IteratorZip. 8 info: | 9 Iterator.zipKeyed ( iterables [ , options ] ) 10 ... 11 16. Return IteratorZip(iters, mode, padding, finishResults). 12 13 IteratorZip ( iters, mode, padding, finishResults ) 14 3. Let closure be a new Abstract Closure with no parameters that captures 15 iters, iterCount, openIters, mode, padding, and finishResults, and 16 performs the following steps when called: 17 ... 18 b. Repeat, 19 ... 20 v. Let completion be Completion(Yield(results)). 21 vi. If completion is an abrupt completion, then 22 1. Return ? IteratorCloseAll(openIters, completion). 23 ... 24 25 IteratorCloseAll ( iters, completion ) 26 1. For each element iter of iters, in reverse List order, do 27 a. Set completion to Completion(IteratorClose(iter, completion)). 28 2. Return ? completion. 29 30 IteratorClose ( iteratorRecord, completion ) 31 1. Assert: iteratorRecord.[[Iterator]] is an Object. 32 2. Let iterator be iteratorRecord.[[Iterator]]. 33 3. Let innerResult be Completion(GetMethod(iterator, "return")). 34 4. If innerResult is a normal completion, then 35 a. Let return be innerResult.[[Value]]. 36 b. If return is undefined, return ? completion. 37 c. Set innerResult to Completion(Call(return, iterator)). 38 5. If completion is a throw completion, return ? completion. 39 ... 40 includes: [compareArray.js] 41 features: [joint-iteration] 42 ---*/ 43 44 function ExpectedError() {} 45 46 var log = []; 47 48 var first = { 49 next() { 50 log.push("call first next"); 51 return {done: false}; 52 }, 53 return() { 54 // Called with the correct receiver and no arguments. 55 assert.sameValue(this, first); 56 assert.sameValue(arguments.length, 0); 57 58 // NB: Log after above asserts, because failures aren't propagated. 59 log.push("call first return"); 60 61 // IteratorClose ignores new exceptions when called with a Throw completion. 62 throw new Test262Error(); 63 } 64 }; 65 66 var second = { 67 next() { 68 log.push("call second next"); 69 return {done: false}; 70 }, 71 return() { 72 // Called with the correct receiver and no arguments. 73 assert.sameValue(this, second); 74 assert.sameValue(arguments.length, 0); 75 76 // NB: Log after above asserts, because failures aren't propagated. 77 log.push("call second return"); 78 79 throw new ExpectedError(); 80 } 81 }; 82 83 var third = { 84 next() { 85 log.push("call third next"); 86 return {done: false}; 87 }, 88 return() { 89 // Called with the correct receiver and no arguments. 90 assert.sameValue(this, third); 91 assert.sameValue(arguments.length, 0); 92 93 // NB: Log after above asserts, because failures aren't propagated. 94 log.push("call third return"); 95 96 return {}; 97 } 98 }; 99 100 var fourth = { 101 next() { 102 log.push("call fourth next"); 103 return {done: true}; 104 }, 105 return() { 106 log.push("unexpected call fourth return"); 107 } 108 }; 109 110 var it = Iterator.zipKeyed({first, second, third, fourth}, {mode: "longest"}); 111 112 it.next(); 113 114 assert.throws(ExpectedError, function() { 115 it.return(); 116 }); 117 118 assert.compareArray(log, [ 119 "call first next", 120 "call second next", 121 "call third next", 122 "call fourth next", 123 124 "call third return", 125 "call second return", 126 "call first return", 127 ]); 128 129 reportCompare(0, 0);