tor-browser

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

iterables-iteration-get-abrupt-completion.js (3568B)


      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      ...
     13      3. If desc is not undefined and desc.[[Enumerable]] is true, then
     14        i. Let value be Completion(Get(iterables, key)).
     15        ii. IfAbruptCloseIterators(value, 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 class ExpectedError extends Error {}
     43 
     44 var log = [];
     45 
     46 var first = {
     47  next() {
     48    log.push("unexpected call to next method");
     49  },
     50  return() {
     51    // Called with the correct receiver and no arguments.
     52    assert.sameValue(this, first);
     53    assert.sameValue(arguments.length, 0);
     54 
     55    // NB: Log after above asserts, because failures aren't propagated.
     56    log.push("close first iterator");
     57 
     58    // IteratorClose ignores new exceptions when called with a Throw completion.
     59    throw new Test262Error();
     60  },
     61 };
     62 
     63 var second = {
     64  next() {
     65    log.push("unexpected call to next method");
     66  },
     67  return() {
     68    // Called with the correct receiver and no arguments.
     69    assert.sameValue(this, second);
     70    assert.sameValue(arguments.length, 0);
     71 
     72    // NB: Log after above asserts, because failures aren't propagated.
     73    log.push("close second iterator");
     74 
     75    // IteratorClose ignores new exceptions when called with a Throw completion.
     76    throw new Test262Error();
     77  },
     78 };
     79 
     80 var symbol = {
     81  next() {
     82    log.push("unexpected call to next method");
     83  },
     84  return() {
     85    log.push("unexpected call to return method");
     86  },
     87 };
     88 
     89 var arrayIndex = {
     90  next() {
     91    log.push("unexpected call to next method");
     92  },
     93  return() {
     94    // Called with the correct receiver and no arguments.
     95    assert.sameValue(this, arrayIndex);
     96    assert.sameValue(arguments.length, 0);
     97 
     98    // NB: Log after above asserts, because failures aren't propagated.
     99    log.push("close array-indexed iterator");
    100 
    101    // IteratorClose ignores new exceptions when called with a Throw completion.
    102    throw new Test262Error();
    103  },
    104 };
    105 
    106 var iterables = {
    107  [Symbol()]: symbol,
    108  first,
    109  second,
    110  get third() {
    111    throw new ExpectedError();
    112  },
    113  5: arrayIndex,
    114 };
    115 
    116 assert.throws(ExpectedError, function() {
    117  Iterator.zipKeyed(iterables);
    118 });
    119 
    120 // Ensure iterators are closed in the correct order.
    121 assert.compareArray(log, [
    122  "close second iterator",
    123  "close first iterator",
    124  "close array-indexed iterator",
    125 ]);
    126 
    127 reportCompare(0, 0);