tor-browser

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

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