tor-browser

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

padding-iteration-iterator-step-value-abrupt-completion.js (4525B)


      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 IteratorStepValue 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        ...
     16        iv. Perform the following steps iterCount times:
     17          1. If usingIterator is true, then
     18            a. Set next to Completion(IteratorStepValue(paddingIter)).
     19            b. IfAbruptCloseIterators(next, iters).
     20            ...
     21 
     22  IfAbruptCloseIterators ( value, iteratorRecords )
     23    1. Assert: value is a Completion Record.
     24    2. If value is an abrupt completion, return ? IteratorCloseAll(iteratorRecords, value).
     25    3. Else, set value to value.[[Value]].
     26 
     27  IteratorCloseAll ( iters, completion )
     28    1. For each element iter of iters, in reverse List order, do
     29      a. Set completion to Completion(IteratorClose(iter, completion)).
     30    2. Return ? completion.
     31 
     32  IteratorClose ( iteratorRecord, completion )
     33    1. Assert: iteratorRecord.[[Iterator]] is an Object.
     34    2. Let iterator be iteratorRecord.[[Iterator]].
     35    3. Let innerResult be Completion(GetMethod(iterator, "return")).
     36    4. If innerResult is a normal completion, then
     37      a. Let return be innerResult.[[Value]].
     38      b. If return is undefined, return ? completion.
     39      c. Set innerResult to Completion(Call(return, iterator)).
     40    5. If completion is a throw completion, return ? completion.
     41    ...
     42 includes: [compareArray.js]
     43 features: [joint-iteration]
     44 ---*/
     45 
     46 var log = [];
     47 
     48 var first = {
     49  next() {
     50    log.push("unexpected call to next method");
     51  },
     52  return() {
     53    // Called with the correct receiver and no arguments.
     54    assert.sameValue(this, first);
     55    assert.sameValue(arguments.length, 0);
     56 
     57    // NB: Log after above asserts, because failures aren't propagated.
     58    log.push("first return");
     59 
     60    // This exception is ignored.
     61    throw new Test262Error();
     62  }
     63 };
     64 
     65 var second = {
     66  next() {
     67    log.push("unexpected call to next method");
     68  },
     69  return() {
     70    // Called with the correct receiver and no arguments.
     71    assert.sameValue(this, second);
     72    assert.sameValue(arguments.length, 0);
     73 
     74    // NB: Log after above asserts, because failures aren't propagated.
     75    log.push("second return");
     76 
     77    // This exception is ignored.
     78    throw new Test262Error();
     79  }
     80 };
     81 
     82 var third = {
     83  next() {
     84    log.push("unexpected call to next method");
     85  },
     86  get return() {
     87    // Called with the correct receiver and no arguments.
     88    assert.sameValue(this, third);
     89    assert.sameValue(arguments.length, 0);
     90 
     91    // NB: Log after above asserts, because failures aren't propagated.
     92    log.push("third return");
     93 
     94    // This exception is ignored.
     95    throw new Test262Error();
     96  }
     97 };
     98 
     99 function ExpectedError() {}
    100 
    101 // Padding iterator throws from |next|.
    102 var padding = {
    103  [Symbol.iterator]() {
    104    return this;
    105  },
    106  next() {
    107    throw new ExpectedError();
    108  },
    109  return() {
    110    log.push("unexpected call to return method");
    111  },
    112 };
    113 
    114 assert.throws(ExpectedError, function() {
    115  Iterator.zip([first, second, third], {mode: "longest", padding});
    116 });
    117 
    118 assert.compareArray(log, [
    119  "third return",
    120  "second return",
    121  "first return",
    122 ]);
    123 
    124 // Clear log
    125 log.length = 0;
    126 
    127 // Padding iterator throws from |done|.
    128 var padding = {
    129  [Symbol.iterator]() {
    130    return this;
    131  },
    132  next() {
    133    return {
    134      get done() {
    135        throw new ExpectedError();
    136      },
    137      get value() {
    138        log.push("unexpected access to value");
    139      },
    140    };
    141  },
    142  return() {
    143    log.push("unexpected call to return method");
    144  },
    145 };
    146 
    147 assert.throws(ExpectedError, function() {
    148  Iterator.zip([first, second, third], {mode: "longest", padding});
    149 });
    150 
    151 assert.compareArray(log, [
    152  "third return",
    153  "second return",
    154  "first return",
    155 ]);
    156 
    157 
    158 // Clear log
    159 log.length = 0;
    160 
    161 // Padding iterator throws from |value|.
    162 var padding = {
    163  [Symbol.iterator]() {
    164    return this;
    165  },
    166  next() {
    167    return {
    168      done: false,
    169      get value() {
    170        throw new ExpectedError();
    171      },
    172    };
    173  },
    174  return() {
    175    log.push("unexpected call to return method");
    176  },
    177 };
    178 
    179 assert.throws(ExpectedError, function() {
    180  Iterator.zip([first, second, third], {mode: "longest", padding});
    181 });
    182 
    183 assert.compareArray(log, [
    184  "third return",
    185  "second return",
    186  "first return",
    187 ]);
    188 
    189 reportCompare(0, 0);