padding-iteration-iterator-step-value-abrupt-completion.js (4525B)
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 Abrupt completion for IteratorStepValue in "padding" option iteration. 8 info: | 9 Iterator.zip ( iterables [ , options ] ) 10 ... 11 14. If mode is "longest", then 12 ... 13 b. Else, 14 i. Let paddingIter be Completion(GetIterator(paddingOption, sync)). 15 ... 16 iv. Perform the following steps iterCount times: 17 1. If usingIterator is true, then 18 a. Set next to Completion(IteratorStepValue(paddingIter)). 19 b. IfAbruptCloseIterators(next, iters). 20 ... 21 22 IfAbruptCloseIterators ( value, iteratorRecords ) 23 1. Assert: value is a Completion Record. 24 2. If value is an abrupt completion, return ? IteratorCloseAll(iteratorRecords, value). 25 3. Else, set value to value.[[Value]]. 26 27 IteratorCloseAll ( iters, completion ) 28 1. For each element iter of iters, in reverse List order, do 29 a. Set completion to Completion(IteratorClose(iter, completion)). 30 2. Return ? completion. 31 32 IteratorClose ( iteratorRecord, completion ) 33 1. Assert: iteratorRecord.[[Iterator]] is an Object. 34 2. Let iterator be iteratorRecord.[[Iterator]]. 35 3. Let innerResult be Completion(GetMethod(iterator, "return")). 36 4. If innerResult is a normal completion, then 37 a. Let return be innerResult.[[Value]]. 38 b. If return is undefined, return ? completion. 39 c. Set innerResult to Completion(Call(return, iterator)). 40 5. If completion is a throw completion, return ? completion. 41 ... 42 includes: [compareArray.js] 43 features: [joint-iteration] 44 ---*/ 45 46 var log = []; 47 48 var first = { 49 next() { 50 log.push("unexpected call to next method"); 51 }, 52 return() { 53 // Called with the correct receiver and no arguments. 54 assert.sameValue(this, first); 55 assert.sameValue(arguments.length, 0); 56 57 // NB: Log after above asserts, because failures aren't propagated. 58 log.push("first return"); 59 60 // This exception is ignored. 61 throw new Test262Error(); 62 } 63 }; 64 65 var second = { 66 next() { 67 log.push("unexpected call to next method"); 68 }, 69 return() { 70 // Called with the correct receiver and no arguments. 71 assert.sameValue(this, second); 72 assert.sameValue(arguments.length, 0); 73 74 // NB: Log after above asserts, because failures aren't propagated. 75 log.push("second return"); 76 77 // This exception is ignored. 78 throw new Test262Error(); 79 } 80 }; 81 82 var third = { 83 next() { 84 log.push("unexpected call to next method"); 85 }, 86 get return() { 87 // Called with the correct receiver and no arguments. 88 assert.sameValue(this, third); 89 assert.sameValue(arguments.length, 0); 90 91 // NB: Log after above asserts, because failures aren't propagated. 92 log.push("third return"); 93 94 // This exception is ignored. 95 throw new Test262Error(); 96 } 97 }; 98 99 function ExpectedError() {} 100 101 // Padding iterator throws from |next|. 102 var padding = { 103 [Symbol.iterator]() { 104 return this; 105 }, 106 next() { 107 throw new ExpectedError(); 108 }, 109 return() { 110 log.push("unexpected call to return method"); 111 }, 112 }; 113 114 assert.throws(ExpectedError, function() { 115 Iterator.zip([first, second, third], {mode: "longest", padding}); 116 }); 117 118 assert.compareArray(log, [ 119 "third return", 120 "second return", 121 "first return", 122 ]); 123 124 // Clear log 125 log.length = 0; 126 127 // Padding iterator throws from |done|. 128 var padding = { 129 [Symbol.iterator]() { 130 return this; 131 }, 132 next() { 133 return { 134 get done() { 135 throw new ExpectedError(); 136 }, 137 get value() { 138 log.push("unexpected access to value"); 139 }, 140 }; 141 }, 142 return() { 143 log.push("unexpected call to return method"); 144 }, 145 }; 146 147 assert.throws(ExpectedError, function() { 148 Iterator.zip([first, second, third], {mode: "longest", padding}); 149 }); 150 151 assert.compareArray(log, [ 152 "third return", 153 "second return", 154 "first return", 155 ]); 156 157 158 // Clear log 159 log.length = 0; 160 161 // Padding iterator throws from |value|. 162 var padding = { 163 [Symbol.iterator]() { 164 return this; 165 }, 166 next() { 167 return { 168 done: false, 169 get value() { 170 throw new ExpectedError(); 171 }, 172 }; 173 }, 174 return() { 175 log.push("unexpected call to return method"); 176 }, 177 }; 178 179 assert.throws(ExpectedError, function() { 180 Iterator.zip([first, second, third], {mode: "longest", padding}); 181 }); 182 183 assert.compareArray(log, [ 184 "third return", 185 "second return", 186 "first return", 187 ]); 188 189 reportCompare(0, 0);