tor-browser

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

iterator-zip-iteration-iterator-step-value-abrupt-completion.js (3951B)


      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 completion from IteratorStepValue in IteratorZip.
      8 info: |
      9  Iterator.zipKeyed ( iterables [ , options ] )
     10    ...
     11    16. Return IteratorZip(iters, mode, padding, finishResults).
     12 
     13  IteratorZip ( iters, mode, padding, finishResults )
     14    3. Let closure be a new Abstract Closure with no parameters that captures
     15       iters, iterCount, openIters, mode, padding, and finishResults, and
     16       performs the following steps when called:
     17      ...
     18      b. Repeat,
     19        ...
     20        iii. For each integer i such that 0 ≤ i < iterCount, in ascending order, do
     21          ...
     22          3. Else,
     23            a. Let result be Completion(IteratorStepValue(iter)).
     24            b. If result is an abrupt completion, then
     25              i. Remove iter from openIters.
     26              ii. Return ? IteratorCloseAll(openIters, result).
     27            ...
     28            d. If result is done, then
     29              i. Remove iter from openIters.
     30              ...
     31 
     32  IteratorCloseAll ( iters, completion )
     33    1. For each element iter of iters, in reverse List order, do
     34       a. Set completion to Completion(IteratorClose(iter, completion)).
     35    2. Return ? completion.
     36 
     37  IteratorClose ( iteratorRecord, completion )
     38    1. Assert: iteratorRecord.[[Iterator]] is an Object.
     39    2. Let iterator be iteratorRecord.[[Iterator]].
     40    3. Let innerResult be Completion(GetMethod(iterator, "return")).
     41    4. If innerResult is a normal completion, then
     42      a. Let return be innerResult.[[Value]].
     43      b. If return is undefined, return ? completion.
     44      c. Set innerResult to Completion(Call(return, iterator)).
     45    5. If completion is a throw completion, return ? completion.
     46    ...
     47 includes: [compareArray.js]
     48 features: [joint-iteration]
     49 ---*/
     50 
     51 var modes = [
     52  "shortest",
     53  "longest",
     54  "strict",
     55 ];
     56 
     57 function ExpectedError() {}
     58 
     59 var log = [];
     60 
     61 var first = {
     62  next() {
     63    log.push("call first next");
     64    throw new ExpectedError();
     65  },
     66  return() {
     67    log.push("unexpected call first return");
     68  }
     69 };
     70 
     71 var second = {
     72  next() {
     73    log.push("unexpected call second next");
     74  },
     75  return() {
     76    // Called with the correct receiver and no arguments.
     77    assert.sameValue(this, second);
     78    assert.sameValue(arguments.length, 0);
     79 
     80    // NB: Log after above asserts, because failures aren't propagated.
     81    log.push("call second return");
     82 
     83    // IteratorClose ignores new exceptions when called with a Throw completion.
     84    throw new Test262Error();
     85  }
     86 };
     87 
     88 var third = {
     89  next() {
     90    log.push("unexpected call third next");
     91  },
     92  return() {
     93    // Called with the correct receiver and no arguments.
     94    assert.sameValue(this, third);
     95    assert.sameValue(arguments.length, 0);
     96 
     97    // NB: Log after above asserts, because failures aren't propagated.
     98    log.push("call third return");
     99 
    100    // IteratorClose ignores new exceptions when called with a Throw completion.
    101    throw new Test262Error();
    102  }
    103 };
    104 
    105 // Empty iterator to ensure |return| is not called for closed iterators.
    106 var empty = {
    107  next() {
    108    log.push("call empty next");
    109    return {done: true};
    110  },
    111  return() {
    112    log.push("unexpected call empty return");
    113  }
    114 };
    115 
    116 for (var mode of modes) {
    117  var it = Iterator.zipKeyed({first, second, third}, {mode});
    118 
    119  assert.throws(ExpectedError, function() {
    120    it.next();
    121  });
    122 
    123  assert.compareArray(log, [
    124    "call first next",
    125    "call third return",
    126    "call second return",
    127  ]);
    128 
    129  // Clear log.
    130  log.length = 0;
    131 }
    132 
    133 // This case applies only when mode is "longest".
    134 var it = Iterator.zipKeyed({empty, first, second, third}, {mode: "longest"});
    135 
    136 assert.throws(ExpectedError, function() {
    137  it.next();
    138 });
    139 
    140 assert.compareArray(log, [
    141  "call empty next",
    142  "call first next",
    143  "call third return",
    144  "call second return",
    145 ]);
    146 
    147 reportCompare(0, 0);