tor-browser

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

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