iterables-iteration.js (3237B)
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 Perform iteration of the "iterables" argument. 8 info: | 9 Iterator.zipKeyed ( iterables [ , options ] ) 10 ... 11 10. Let allKeys be ? iterables.[[OwnPropertyKeys]](). 12 11. Let keys be a new empty List. 13 12. For each element key of allKeys, do 14 a. Let desc be Completion(iterables.[[GetOwnProperty]](key)). 15 ... 16 c. If desc is not undefined and desc.[[Enumerable]] is true, then 17 i. Let value be Completion(Get(iterables, key)). 18 ... 19 iii. If value is not undefined, then 20 1. Append key to keys. 21 2. Let iter be Completion(GetIteratorFlattenable(value, reject-strings)). 22 ... 23 4. Append iter to iters. 24 ... 25 includes: [proxyTrapsHelper.js, compareArray.js] 26 features: [joint-iteration] 27 ---*/ 28 29 // Object implementing Iterator protocol, but throws when calling any Iterator methods. 30 var throwingIterator = { 31 next() { 32 throw new Test262Error(); 33 }, 34 return() { 35 throw new Test262Error(); 36 } 37 }; 38 39 var iterableReturningThrowingIterator = { 40 [Symbol.iterator]() { 41 return throwingIterator; 42 } 43 }; 44 45 // GetIteratorFlattenable accepts both iterables and iterators. 46 Iterator.zipKeyed({ 47 a: throwingIterator, 48 b: iterableReturningThrowingIterator, 49 }); 50 51 // GetIteratorFlattenable rejects non-objects. 52 var badIterators = [ 53 null, 54 true, 55 "", 56 Symbol(), 57 0, 58 0n, 59 // undefined is handled separately 60 ]; 61 62 for (var iterator of badIterators) { 63 assert.throws(TypeError, function() { 64 Iterator.zipKeyed({a: iterator}); 65 }); 66 } 67 68 // [[OwnPropertyKeys]], [[GetOwnProperty]], [[Get]], and GetIteratorFlattenable 69 // read properties in the correct order. 70 var log = []; 71 72 function makeProxyWithGetHandler(name, obj) { 73 return new Proxy(obj, allowProxyTraps({ 74 ownKeys(target) { 75 log.push(`${name}::[[OwnPropertyKeys]]}`); 76 return Reflect.ownKeys(target); 77 }, 78 getOwnPropertyDescriptor(target, propertyKey) { 79 log.push(`${name}::[[GetOwnProperty]](${String(propertyKey)})`); 80 return Reflect.getOwnPropertyDescriptor(target, propertyKey); 81 }, 82 get(target, propertyKey, receiver) { 83 log.push(`${name}::[[Get]](${String(propertyKey)})`); 84 return Reflect.get(target, propertyKey, receiver); 85 }, 86 })); 87 } 88 89 var iterables = makeProxyWithGetHandler("iterables", { 90 // An iterator. 91 a: makeProxyWithGetHandler("first", throwingIterator), 92 93 // An iterable. 94 b: makeProxyWithGetHandler("second", iterableReturningThrowingIterator), 95 96 // An object without any iteration methods. 97 c: makeProxyWithGetHandler("third", {}), 98 }); 99 100 Iterator.zipKeyed(iterables); 101 102 assert.compareArray(log, [ 103 "iterables::[[OwnPropertyKeys]]}", 104 105 "iterables::[[GetOwnProperty]](a)", 106 "iterables::[[Get]](a)", 107 "first::[[Get]](Symbol(Symbol.iterator))", 108 "first::[[Get]](next)", 109 110 "iterables::[[GetOwnProperty]](b)", 111 "iterables::[[Get]](b)", 112 "second::[[Get]](Symbol(Symbol.iterator))", 113 114 "iterables::[[GetOwnProperty]](c)", 115 "iterables::[[Get]](c)", 116 "third::[[Get]](Symbol(Symbol.iterator))", 117 "third::[[Get]](next)", 118 ]); 119 120 reportCompare(0, 0);