tor-browser

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

AsyncIteration.js (14743B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 function AsyncIteratorIdentity() {
      6  return this;
      7 }
      8 
      9 function AsyncGeneratorNext(val) {
     10  assert(
     11    IsAsyncGeneratorObject(this),
     12    "ThisArgument must be a generator object for async generators"
     13  );
     14  return resumeGenerator(this, val, "next");
     15 }
     16 
     17 function AsyncGeneratorThrow(val) {
     18  assert(
     19    IsAsyncGeneratorObject(this),
     20    "ThisArgument must be a generator object for async generators"
     21  );
     22  return resumeGenerator(this, val, "throw");
     23 }
     24 
     25 function AsyncGeneratorReturn(val) {
     26  assert(
     27    IsAsyncGeneratorObject(this),
     28    "ThisArgument must be a generator object for async generators"
     29  );
     30  return resumeGenerator(this, val, "return");
     31 }
     32 
     33 /* ECMA262 7.4.7 AsyncIteratorClose */
     34 async function AsyncIteratorClose(iteratorRecord, value) {
     35  // Step 3.
     36  var iterator = iteratorRecord.iterator;
     37  // Step 4.
     38  var returnMethod = iterator.return;
     39  // Step 5.
     40  if (!IsNullOrUndefined(returnMethod)) {
     41    var result = await callContentFunction(returnMethod, iterator);
     42    // Step 8.
     43    if (!IsObject(result)) {
     44      ThrowTypeError(JSMSG_OBJECT_REQUIRED, DecompileArg(0, result));
     45    }
     46  }
     47  // Step 5b & 9.
     48  return value;
     49 }
     50 
     51 /* Iterator Helpers proposal 1.1.1 */
     52 function GetIteratorDirect(obj) {
     53  // Step 1.
     54  if (!IsObject(obj)) {
     55    ThrowTypeError(JSMSG_OBJECT_REQUIRED, DecompileArg(0, obj));
     56  }
     57 
     58  // Step 2.
     59  var nextMethod = obj.next;
     60  // Step 3.
     61  if (!IsCallable(nextMethod)) {
     62    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, nextMethod));
     63  }
     64 
     65  // Steps 4-5.
     66  return {
     67    iterator: obj,
     68    nextMethod,
     69    done: false,
     70  };
     71 }
     72 
     73 /* Iterator Helpers proposal 1.1.1 */
     74 function GetAsyncIteratorDirectWrapper(obj) {
     75  // Step 1.
     76  if (!IsObject(obj)) {
     77    ThrowTypeError(JSMSG_OBJECT_REQUIRED, obj);
     78  }
     79 
     80  // Step 2.
     81  var nextMethod = obj.next;
     82  // Step 3.
     83  if (!IsCallable(nextMethod)) {
     84    ThrowTypeError(JSMSG_NOT_FUNCTION, nextMethod);
     85  }
     86 
     87  // Steps 4-5.
     88  return {
     89    // Use a named function expression instead of a method definition, so
     90    // we don't create an inferred name for this function at runtime.
     91    [GetBuiltinSymbol("asyncIterator")]: function AsyncIteratorMethod() {
     92      return this;
     93    },
     94    next(value) {
     95      return callContentFunction(nextMethod, obj, value);
     96    },
     97    async return(value) {
     98      var returnMethod = obj.return;
     99      if (!IsNullOrUndefined(returnMethod)) {
    100        return callContentFunction(returnMethod, obj, value);
    101      }
    102      return { done: true, value };
    103    },
    104  };
    105 }
    106 
    107 /* AsyncIteratorHelper object prototype methods. */
    108 function AsyncIteratorHelperNext(value) {
    109  var O = this;
    110  if (!IsObject(O) || (O = GuardToAsyncIteratorHelper(O)) === null) {
    111    return callFunction(
    112      CallAsyncIteratorHelperMethodIfWrapped,
    113      this,
    114      value,
    115      "AsyncIteratorHelperNext"
    116    );
    117  }
    118  var generator = UnsafeGetReservedSlot(
    119    O,
    120    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT
    121  );
    122  return callFunction(IntrinsicAsyncGeneratorNext, generator, value);
    123 }
    124 
    125 function AsyncIteratorHelperReturn(value) {
    126  var O = this;
    127  if (!IsObject(O) || (O = GuardToAsyncIteratorHelper(O)) === null) {
    128    return callFunction(
    129      CallAsyncIteratorHelperMethodIfWrapped,
    130      this,
    131      value,
    132      "AsyncIteratorHelperReturn"
    133    );
    134  }
    135  var generator = UnsafeGetReservedSlot(
    136    O,
    137    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT
    138  );
    139  return callFunction(IntrinsicAsyncGeneratorReturn, generator, value);
    140 }
    141 
    142 function AsyncIteratorHelperThrow(value) {
    143  var O = this;
    144  if (!IsObject(O) || (O = GuardToAsyncIteratorHelper(O)) === null) {
    145    return callFunction(
    146      CallAsyncIteratorHelperMethodIfWrapped,
    147      this,
    148      value,
    149      "AsyncIteratorHelperThrow"
    150    );
    151  }
    152  var generator = UnsafeGetReservedSlot(
    153    O,
    154    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT
    155  );
    156  return callFunction(IntrinsicAsyncGeneratorThrow, generator, value);
    157 }
    158 
    159 // AsyncIterator lazy Iterator Helper methods
    160 // Iterator Helpers proposal 2.1.6.2-2.1.6.7
    161 //
    162 // The AsyncIterator lazy methods are structured closely to how the Iterator
    163 // lazy methods are. See builtin/Iterator.js for the reasoning.
    164 
    165 /* Iterator Helpers proposal 2.1.6.2 Prelude */
    166 function AsyncIteratorMap(mapper) {
    167  // Step 1.
    168  var iterated = GetIteratorDirect(this);
    169 
    170  // Step 2.
    171  if (!IsCallable(mapper)) {
    172    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, mapper));
    173  }
    174 
    175  var iteratorHelper = NewAsyncIteratorHelper();
    176  var generator = AsyncIteratorMapGenerator(iterated, mapper);
    177  callFunction(IntrinsicAsyncGeneratorNext, generator);
    178  UnsafeSetReservedSlot(
    179    iteratorHelper,
    180    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT,
    181    generator
    182  );
    183  return iteratorHelper;
    184 }
    185 
    186 /* Iterator Helpers proposal 2.1.6.2 Body */
    187 async function* AsyncIteratorMapGenerator(iterated, mapper) {
    188  // Step 1.
    189  var lastValue;
    190  // Step 2.
    191  var needClose = true;
    192  try {
    193    yield;
    194    needClose = false;
    195 
    196    for (
    197      var next = await IteratorNext(iterated, lastValue);
    198      !next.done;
    199      next = await IteratorNext(iterated, lastValue)
    200    ) {
    201      // Step c.
    202      var value = next.value;
    203 
    204      // Steps d-i.
    205      needClose = true;
    206      lastValue = yield callContentFunction(mapper, undefined, value);
    207      needClose = false;
    208    }
    209  } finally {
    210    if (needClose) {
    211      AsyncIteratorClose(iterated);
    212    }
    213  }
    214 }
    215 
    216 /* Iterator Helpers proposal 2.1.6.3 Prelude */
    217 function AsyncIteratorFilter(filterer) {
    218  // Step 1.
    219  var iterated = GetIteratorDirect(this);
    220 
    221  // Step 2.
    222  if (!IsCallable(filterer)) {
    223    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, filterer));
    224  }
    225 
    226  var iteratorHelper = NewAsyncIteratorHelper();
    227  var generator = AsyncIteratorFilterGenerator(iterated, filterer);
    228  callFunction(IntrinsicAsyncGeneratorNext, generator);
    229  UnsafeSetReservedSlot(
    230    iteratorHelper,
    231    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT,
    232    generator
    233  );
    234  return iteratorHelper;
    235 }
    236 
    237 /* Iterator Helpers proposal 2.1.6.3 Body */
    238 async function* AsyncIteratorFilterGenerator(iterated, filterer) {
    239  // Step 1.
    240  var lastValue;
    241  // Step 2.
    242  var needClose = true;
    243  try {
    244    yield;
    245    needClose = false;
    246 
    247    for (
    248      var next = await IteratorNext(iterated, lastValue);
    249      !next.done;
    250      next = await IteratorNext(iterated, lastValue)
    251    ) {
    252      // Step c.
    253      var value = next.value;
    254 
    255      // Steps d-h.
    256      needClose = true;
    257      if (await callContentFunction(filterer, undefined, value)) {
    258        lastValue = yield value;
    259      }
    260      needClose = false;
    261    }
    262  } finally {
    263    if (needClose) {
    264      AsyncIteratorClose(iterated);
    265    }
    266  }
    267 }
    268 
    269 /* Iterator Helpers proposal 2.1.6.4 Prelude */
    270 function AsyncIteratorTake(limit) {
    271  // Step 1.
    272  var iterated = GetIteratorDirect(this);
    273 
    274  // Step 2.
    275  var remaining = ToInteger(limit);
    276  // Step 3.
    277  if (remaining < 0) {
    278    ThrowRangeError(JSMSG_NEGATIVE_LIMIT);
    279  }
    280 
    281  var iteratorHelper = NewAsyncIteratorHelper();
    282  var generator = AsyncIteratorTakeGenerator(iterated, remaining);
    283  callFunction(IntrinsicAsyncGeneratorNext, generator);
    284  UnsafeSetReservedSlot(
    285    iteratorHelper,
    286    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT,
    287    generator
    288  );
    289  return iteratorHelper;
    290 }
    291 
    292 /* Iterator Helpers proposal 2.1.6.4 Body */
    293 async function* AsyncIteratorTakeGenerator(iterated, remaining) {
    294  // Step 1.
    295  var lastValue;
    296  // Step 2.
    297  var needClose = true;
    298  try {
    299    yield;
    300    needClose = false;
    301 
    302    for (; remaining > 0; remaining--) {
    303      var next = await IteratorNext(iterated, lastValue);
    304      if (next.done) {
    305        return undefined;
    306      }
    307 
    308      var value = next.value;
    309 
    310      needClose = true;
    311      lastValue = yield value;
    312      needClose = false;
    313    }
    314  } finally {
    315    if (needClose) {
    316      AsyncIteratorClose(iterated, undefined);
    317    }
    318  }
    319 
    320  return AsyncIteratorClose(iterated, undefined);
    321 }
    322 
    323 /* Iterator Helpers proposal 2.1.6.5 Prelude */
    324 function AsyncIteratorDrop(limit) {
    325  // Step 1.
    326  var iterated = GetIteratorDirect(this);
    327 
    328  // Step 2.
    329  var remaining = ToInteger(limit);
    330  // Step 3.
    331  if (remaining < 0) {
    332    ThrowRangeError(JSMSG_NEGATIVE_LIMIT);
    333  }
    334 
    335  var iteratorHelper = NewAsyncIteratorHelper();
    336  var generator = AsyncIteratorDropGenerator(iterated, remaining);
    337  callFunction(IntrinsicAsyncGeneratorNext, generator);
    338  UnsafeSetReservedSlot(
    339    iteratorHelper,
    340    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT,
    341    generator
    342  );
    343  return iteratorHelper;
    344 }
    345 
    346 /* Iterator Helpers proposal 2.1.6.5 Body */
    347 async function* AsyncIteratorDropGenerator(iterated, remaining) {
    348  var needClose = true;
    349  try {
    350    yield;
    351    needClose = false;
    352 
    353    // Step 1.
    354    for (; remaining > 0; remaining--) {
    355      var next = await IteratorNext(iterated);
    356      if (next.done) {
    357        return;
    358      }
    359    }
    360 
    361    // Step 2.
    362    var lastValue;
    363    // Step 3.
    364    for (
    365      var next = await IteratorNext(iterated, lastValue);
    366      !next.done;
    367      next = await IteratorNext(iterated, lastValue)
    368    ) {
    369      // Steps c-d.
    370      var value = next.value;
    371 
    372      needClose = true;
    373      lastValue = yield value;
    374      needClose = false;
    375    }
    376  } finally {
    377    if (needClose) {
    378      AsyncIteratorClose(iterated);
    379    }
    380  }
    381 }
    382 
    383 /* Iterator Helpers proposal 2.1.6.6 Prelude */
    384 function AsyncIteratorAsIndexedPairs() {
    385  // Step 1.
    386  var iterated = GetIteratorDirect(this);
    387 
    388  var iteratorHelper = NewAsyncIteratorHelper();
    389  var generator = AsyncIteratorAsIndexedPairsGenerator(iterated);
    390  callFunction(IntrinsicAsyncGeneratorNext, generator);
    391  UnsafeSetReservedSlot(
    392    iteratorHelper,
    393    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT,
    394    generator
    395  );
    396  return iteratorHelper;
    397 }
    398 
    399 /* Iterator Helpers proposal 2.1.6.6 Body */
    400 async function* AsyncIteratorAsIndexedPairsGenerator(iterated) {
    401  var needClose = true;
    402  try {
    403    yield;
    404    needClose = false;
    405 
    406    // Step 2.
    407    var lastValue;
    408    // Step 3.
    409    for (
    410      var next = await IteratorNext(iterated, lastValue), index = 0;
    411      !next.done;
    412      next = await IteratorNext(iterated, lastValue), index++
    413    ) {
    414      // Steps c-g.
    415      var value = next.value;
    416 
    417      needClose = true;
    418      lastValue = yield [index, value];
    419      needClose = false;
    420    }
    421  } finally {
    422    if (needClose) {
    423      AsyncIteratorClose(iterated);
    424    }
    425  }
    426 }
    427 
    428 /* Iterator Helpers proposal 2.1.6.7 Prelude */
    429 function AsyncIteratorFlatMap(mapper) {
    430  // Step 1.
    431  var iterated = GetIteratorDirect(this);
    432 
    433  // Step 2.
    434  if (!IsCallable(mapper)) {
    435    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, mapper));
    436  }
    437 
    438  var iteratorHelper = NewAsyncIteratorHelper();
    439  var generator = AsyncIteratorFlatMapGenerator(iterated, mapper);
    440  callFunction(IntrinsicAsyncGeneratorNext, generator);
    441  UnsafeSetReservedSlot(
    442    iteratorHelper,
    443    ASYNC_ITERATOR_HELPER_GENERATOR_SLOT,
    444    generator
    445  );
    446  return iteratorHelper;
    447 }
    448 
    449 /* Iterator Helpers proposal 2.1.6.7 Body */
    450 async function* AsyncIteratorFlatMapGenerator(iterated, mapper) {
    451  var needClose = true;
    452  try {
    453    yield;
    454    needClose = false;
    455 
    456    // Step 1.
    457    for (
    458      var next = await IteratorNext(iterated);
    459      !next.done;
    460      next = await IteratorNext(iterated)
    461    ) {
    462      // Step c.
    463      var value = next.value;
    464 
    465      needClose = true;
    466      // Step d.
    467      var mapped = await callContentFunction(mapper, undefined, value);
    468      // Steps f-k.
    469      for await (var innerValue of allowContentIter(mapped)) {
    470        yield innerValue;
    471      }
    472      needClose = false;
    473    }
    474  } finally {
    475    if (needClose) {
    476      AsyncIteratorClose(iterated);
    477    }
    478  }
    479 }
    480 
    481 /* Iterator Helpers proposal 2.1.6.8 */
    482 async function AsyncIteratorReduce(reducer /*, initialValue*/) {
    483  // Step 1.
    484  var iterated = GetAsyncIteratorDirectWrapper(this);
    485 
    486  // Step 2.
    487  if (!IsCallable(reducer)) {
    488    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, reducer));
    489  }
    490 
    491  // Step 3.
    492  var accumulator;
    493  if (ArgumentsLength() === 1) {
    494    // Step a.
    495    var next = await callContentFunction(iterated.next, iterated);
    496    if (!IsObject(next)) {
    497      ThrowTypeError(JSMSG_OBJECT_REQUIRED, DecompileArg(0, next));
    498    }
    499    // Step b.
    500    if (next.done) {
    501      ThrowTypeError(JSMSG_EMPTY_ITERATOR_REDUCE);
    502    }
    503    // Step c.
    504    accumulator = next.value;
    505  } else {
    506    // Step 4.
    507    accumulator = GetArgument(1);
    508  }
    509 
    510  // Step 5.
    511  for await (var value of allowContentIter(iterated)) {
    512    // Steps d-h.
    513    accumulator = await callContentFunction(
    514      reducer,
    515      undefined,
    516      accumulator,
    517      value
    518    );
    519  }
    520  // Step 5b.
    521  return accumulator;
    522 }
    523 
    524 /* Iterator Helpers proposal 2.1.6.9 */
    525 async function AsyncIteratorToArray() {
    526  // Step 1.
    527  var iterated = { [GetBuiltinSymbol("asyncIterator")]: () => this };
    528  // Step 2.
    529  var items = [];
    530  var index = 0;
    531  // Step 3.
    532  for await (var value of allowContentIter(iterated)) {
    533    // Step d.
    534    DefineDataProperty(items, index++, value);
    535  }
    536  // Step 3b.
    537  return items;
    538 }
    539 
    540 /* Iterator Helpers proposal 2.1.6.10 */
    541 async function AsyncIteratorForEach(fn) {
    542  // Step 1.
    543  var iterated = GetAsyncIteratorDirectWrapper(this);
    544 
    545  // Step 2.
    546  if (!IsCallable(fn)) {
    547    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, fn));
    548  }
    549 
    550  // Step 3.
    551  for await (var value of allowContentIter(iterated)) {
    552    // Steps d-g.
    553    await callContentFunction(fn, undefined, value);
    554  }
    555 }
    556 
    557 /* Iterator Helpers proposal 2.1.6.11 */
    558 async function AsyncIteratorSome(fn) {
    559  // Step 1.
    560  var iterated = GetAsyncIteratorDirectWrapper(this);
    561 
    562  // Step 2.
    563  if (!IsCallable(fn)) {
    564    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, fn));
    565  }
    566 
    567  // Step 3.
    568  for await (var value of allowContentIter(iterated)) {
    569    // Steps d-h.
    570    if (await callContentFunction(fn, undefined, value)) {
    571      return true;
    572    }
    573  }
    574  // Step 3b.
    575  return false;
    576 }
    577 
    578 /* Iterator Helpers proposal 2.1.6.12 */
    579 async function AsyncIteratorEvery(fn) {
    580  // Step 1.
    581  var iterated = GetAsyncIteratorDirectWrapper(this);
    582 
    583  // Step 2.
    584  if (!IsCallable(fn)) {
    585    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, fn));
    586  }
    587 
    588  // Step 3.
    589  for await (var value of allowContentIter(iterated)) {
    590    // Steps d-h.
    591    if (!(await callContentFunction(fn, undefined, value))) {
    592      return false;
    593    }
    594  }
    595  // Step 3b.
    596  return true;
    597 }
    598 
    599 /* Iterator Helpers proposal 2.1.6.13 */
    600 async function AsyncIteratorFind(fn) {
    601  // Step 1.
    602  var iterated = GetAsyncIteratorDirectWrapper(this);
    603 
    604  // Step 2.
    605  if (!IsCallable(fn)) {
    606    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, fn));
    607  }
    608 
    609  // Step 3.
    610  for await (var value of allowContentIter(iterated)) {
    611    // Steps d-h.
    612    if (await callContentFunction(fn, undefined, value)) {
    613      return value;
    614    }
    615  }
    616 }