padding-iteration-get-iterator-abrupt-completion.js (3721B)
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 GetIterator 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 ii. IfAbruptCloseIterators(paddingIter, iters). 16 ... 17 18 IfAbruptCloseIterators ( value, iteratorRecords ) 19 1. Assert: value is a Completion Record. 20 2. If value is an abrupt completion, return ? IteratorCloseAll(iteratorRecords, value). 21 3. Else, set value to value.[[Value]]. 22 23 IteratorCloseAll ( iters, completion ) 24 1. For each element iter of iters, in reverse List order, do 25 a. Set completion to Completion(IteratorClose(iter, completion)). 26 2. Return ? completion. 27 28 IteratorClose ( iteratorRecord, completion ) 29 1. Assert: iteratorRecord.[[Iterator]] is an Object. 30 2. Let iterator be iteratorRecord.[[Iterator]]. 31 3. Let innerResult be Completion(GetMethod(iterator, "return")). 32 4. If innerResult is a normal completion, then 33 a. Let return be innerResult.[[Value]]. 34 b. If return is undefined, return ? completion. 35 c. Set innerResult to Completion(Call(return, iterator)). 36 5. If completion is a throw completion, return ? completion. 37 ... 38 includes: [compareArray.js] 39 features: [joint-iteration] 40 ---*/ 41 42 var log = []; 43 44 var first = { 45 next() { 46 log.push("unexpected call to next method"); 47 }, 48 return() { 49 // Called with the correct receiver and no arguments. 50 assert.sameValue(this, first); 51 assert.sameValue(arguments.length, 0); 52 53 // NB: Log after above asserts, because failures aren't propagated. 54 log.push("first return"); 55 56 // This exception is ignored. 57 throw new Test262Error(); 58 } 59 }; 60 61 var second = { 62 next() { 63 log.push("unexpected call to next method"); 64 }, 65 return() { 66 // Called with the correct receiver and no arguments. 67 assert.sameValue(this, second); 68 assert.sameValue(arguments.length, 0); 69 70 // NB: Log after above asserts, because failures aren't propagated. 71 log.push("second return"); 72 73 // This exception is ignored. 74 throw new Test262Error(); 75 } 76 }; 77 78 var third = { 79 next() { 80 log.push("unexpected call to next method"); 81 }, 82 get return() { 83 // Called with the correct receiver and no arguments. 84 assert.sameValue(this, third); 85 assert.sameValue(arguments.length, 0); 86 87 // NB: Log after above asserts, because failures aren't propagated. 88 log.push("third return"); 89 90 // This exception is ignored. 91 throw new Test262Error(); 92 } 93 }; 94 95 function ExpectedError() {} 96 97 // Padding iterator throws from |Symbol.iterator|. 98 var padding = { 99 [Symbol.iterator]() { 100 throw new ExpectedError(); 101 }, 102 next() { 103 log.push("unexpected call to next method"); 104 }, 105 return() { 106 log.push("unexpected call to return method"); 107 }, 108 }; 109 110 assert.throws(ExpectedError, function() { 111 Iterator.zip([first, second, third], {mode: "longest", padding}); 112 }); 113 114 assert.compareArray(log, [ 115 "third return", 116 "second return", 117 "first return", 118 ]); 119 120 // Clear log 121 log.length = 0; 122 123 // Padding iterator throws from |next|. 124 var padding = { 125 [Symbol.iterator]() { 126 return this; 127 }, 128 next() { 129 throw new ExpectedError(); 130 }, 131 return() { 132 log.push("unexpected call to return method"); 133 }, 134 }; 135 136 assert.throws(ExpectedError, function() { 137 Iterator.zip([first, second, third], {mode: "longest", padding}); 138 }); 139 140 assert.compareArray(log, [ 141 "third return", 142 "second return", 143 "first return", 144 ]); 145 146 reportCompare(0, 0);