iterables-iteration-get-own-property-abrupt-completion.js (2954B)
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 completions during iterables iteration. 8 info: | 9 Iterator.zipKeyed ( iterables [ , options ] ) 10 ... 11 12. For each element key of allKeys, do 12 a. Let desc be Completion(iterables.[[GetOwnProperty]](key)). 13 b. IfAbruptCloseIterators(desc, iters). 14 ... 15 16 IfAbruptCloseIterators ( value, iteratorRecords ) 17 1. Assert: value is a Completion Record. 18 2. If value is an abrupt completion, return ? IteratorCloseAll(iteratorRecords, value). 19 3. Else, set value to value.[[Value]]. 20 21 IteratorCloseAll ( iters, completion ) 22 1. For each element iter of iters, in reverse List order, do 23 a. Set completion to Completion(IteratorClose(iter, completion)). 24 2. Return ? completion. 25 26 IteratorClose ( iteratorRecord, completion ) 27 1. Assert: iteratorRecord.[[Iterator]] is an Object. 28 2. Let iterator be iteratorRecord.[[Iterator]]. 29 3. Let innerResult be Completion(GetMethod(iterator, "return")). 30 4. If innerResult is a normal completion, then 31 a. Let return be innerResult.[[Value]]. 32 b. If return is undefined, return ? completion. 33 c. Set innerResult to Completion(Call(return, iterator)). 34 5. If completion is a throw completion, return ? completion. 35 ... 36 includes: [compareArray.js] 37 features: [joint-iteration] 38 ---*/ 39 40 class ExpectedError extends Error {} 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("close first iterator"); 55 56 // IteratorClose ignores new exceptions when called with a Throw completion. 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("close second iterator"); 72 73 // IteratorClose ignores new exceptions when called with a Throw completion. 74 throw new Test262Error(); 75 }, 76 }; 77 78 var iterables = new Proxy({first, second, third: null}, { 79 getOwnPropertyDescriptor(target, propertyKey) { 80 if (propertyKey === "third") { 81 throw new ExpectedError(); 82 } 83 return Reflect.getOwnPropertyDescriptor(target, propertyKey); 84 } 85 }); 86 87 assert.throws(ExpectedError, function() { 88 Iterator.zipKeyed(iterables); 89 }); 90 91 // Ensure iterators are closed in the correct order. 92 assert.compareArray(log, [ 93 "close second iterator", 94 "close first iterator", 95 ]); 96 97 reportCompare(0, 0);