tor-browser

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

iterables-iteration-iterator-step-value-abrupt-completion.js (3244B)


      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  Handle abrupt completions during iterables iteration.
      8 info: |
      9  Iterator.zip ( iterables [ , options ] )
     10    ...
     11    12. Repeat, while next is not done,
     12      a. Set next to Completion(IteratorStepValue(inputIter)).
     13      b. IfAbruptCloseIterators(next, 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 elements = [first, second];
     79 var elementsIter = elements.values();
     80 
     81 var iterables = {
     82  [Symbol.iterator]() {
     83    return this;
     84  },
     85  next() {
     86    log.push("call next");
     87    var result = elementsIter.next();
     88    if (result.done) {
     89      throw new ExpectedError();
     90    }
     91    return result;
     92  },
     93  return() {
     94    // This method shouldn't be called.
     95    log.push("UNEXPECTED - close iterables iterator");
     96 
     97    // IteratorClose ignores new exceptions when called with a Throw completion.
     98    throw new Test262Error();
     99  },
    100 };
    101 
    102 assert.throws(ExpectedError, function() {
    103  Iterator.zip(iterables);
    104 });
    105 
    106 // Ensure iterators are closed in the correct order.
    107 assert.compareArray(log, [
    108  "call next",
    109  "call next",
    110  "call next",
    111  "close second iterator",
    112  "close first iterator",
    113 ]);
    114 
    115 reportCompare(0, 0);