tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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);