tor-browser

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

Array.js (34402B)


      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 /* ES5 15.4.4.16. */
      6 function ArrayEvery(callbackfn /*, thisArg*/) {
      7  /* Step 1. */
      8  var O = ToObject(this);
      9 
     10  /* Steps 2-3. */
     11  var len = ToLength(O.length);
     12 
     13  /* Step 4. */
     14  if (ArgumentsLength() === 0) {
     15    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.every");
     16  }
     17  if (!IsCallable(callbackfn)) {
     18    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
     19  }
     20 
     21  /* Step 5. */
     22  var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
     23 
     24  /* Steps 6-7. */
     25  /* Steps a (implicit), and d. */
     26  for (var k = 0; k < len; k++) {
     27    /* Step b */
     28    if (k in O) {
     29      /* Step c. */
     30      if (!callContentFunction(callbackfn, T, O[k], k, O)) {
     31        return false;
     32      }
     33    }
     34  }
     35 
     36  /* Step 8. */
     37  return true;
     38 }
     39 // Inlining this enables inlining of the callback function.
     40 SetIsInlinableLargeFunction(ArrayEvery);
     41 
     42 /* ES5 15.4.4.17. */
     43 function ArraySome(callbackfn /*, thisArg*/) {
     44  /* Step 1. */
     45  var O = ToObject(this);
     46 
     47  /* Steps 2-3. */
     48  var len = ToLength(O.length);
     49 
     50  /* Step 4. */
     51  if (ArgumentsLength() === 0) {
     52    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.some");
     53  }
     54  if (!IsCallable(callbackfn)) {
     55    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
     56  }
     57 
     58  /* Step 5. */
     59  var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
     60 
     61  /* Steps 6-7. */
     62  /* Steps a (implicit), and d. */
     63  for (var k = 0; k < len; k++) {
     64    /* Step b */
     65    if (k in O) {
     66      /* Step c. */
     67      if (callContentFunction(callbackfn, T, O[k], k, O)) {
     68        return true;
     69      }
     70    }
     71  }
     72 
     73  /* Step 8. */
     74  return false;
     75 }
     76 // Inlining this enables inlining of the callback function.
     77 SetIsInlinableLargeFunction(ArraySome);
     78 
     79 /* ES5 15.4.4.18. */
     80 function ArrayForEach(callbackfn /*, thisArg*/) {
     81  /* Step 1. */
     82  var O = ToObject(this);
     83 
     84  /* Steps 2-3. */
     85  var len = ToLength(O.length);
     86 
     87  /* Step 4. */
     88  if (ArgumentsLength() === 0) {
     89    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.forEach");
     90  }
     91  if (!IsCallable(callbackfn)) {
     92    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
     93  }
     94 
     95  /* Step 5. */
     96  var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
     97 
     98  /* Steps 6-7. */
     99  /* Steps a (implicit), and d. */
    100  for (var k = 0; k < len; k++) {
    101    /* Step b */
    102    if (k in O) {
    103      /* Step c. */
    104      callContentFunction(callbackfn, T, O[k], k, O);
    105    }
    106  }
    107 
    108  /* Step 8. */
    109  return undefined;
    110 }
    111 // Inlining this enables inlining of the callback function.
    112 SetIsInlinableLargeFunction(ArrayForEach);
    113 
    114 /* ES 2016 draft Mar 25, 2016 22.1.3.15. */
    115 function ArrayMap(callbackfn /*, thisArg*/) {
    116  /* Step 1. */
    117  var O = ToObject(this);
    118 
    119  /* Step 2. */
    120  var len = ToLength(O.length);
    121 
    122  /* Step 3. */
    123  if (ArgumentsLength() === 0) {
    124    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.map");
    125  }
    126  if (!IsCallable(callbackfn)) {
    127    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
    128  }
    129 
    130  /* Step 4. */
    131  var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
    132 
    133  /* Steps 5. */
    134  var A = CanOptimizeArraySpecies(O) ? std_Array(len) : ArraySpeciesCreate(O, len);
    135 
    136  /* Steps 6-7. */
    137  /* Steps 7.a (implicit), and 7.d. */
    138  for (var k = 0; k < len; k++) {
    139    /* Steps 7.b-c. */
    140    if (k in O) {
    141      /* Steps 7.c.i-iii. */
    142      var mappedValue = callContentFunction(callbackfn, T, O[k], k, O);
    143      DefineDataProperty(A, k, mappedValue);
    144    }
    145  }
    146 
    147  /* Step 8. */
    148  return A;
    149 }
    150 // Inlining this enables inlining of the callback function.
    151 SetIsInlinableLargeFunction(ArrayMap);
    152 
    153 /* ES 2016 draft Mar 25, 2016 22.1.3.7 Array.prototype.filter. */
    154 function ArrayFilter(callbackfn /*, thisArg*/) {
    155  /* Step 1. */
    156  var O = ToObject(this);
    157 
    158  /* Step 2. */
    159  var len = ToLength(O.length);
    160 
    161  /* Step 3. */
    162  if (ArgumentsLength() === 0) {
    163    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.filter");
    164  }
    165  if (!IsCallable(callbackfn)) {
    166    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
    167  }
    168 
    169  /* Step 4. */
    170  var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
    171 
    172  /* Step 5. */
    173  var A = CanOptimizeArraySpecies(O) ? [] : ArraySpeciesCreate(O, 0);
    174 
    175  /* Steps 6-8. */
    176  /* Steps 8.a (implicit), and 8.d. */
    177  for (var k = 0, to = 0; k < len; k++) {
    178    /* Steps 8.b-c. */
    179    if (k in O) {
    180      /* Step 8.c.i. */
    181      var kValue = O[k];
    182      /* Steps 8.c.ii-iii. */
    183      if (callContentFunction(callbackfn, T, kValue, k, O)) {
    184        DefineDataProperty(A, to++, kValue);
    185      }
    186    }
    187  }
    188 
    189  /* Step 9. */
    190  return A;
    191 }
    192 // Inlining this enables inlining of the callback function.
    193 SetIsInlinableLargeFunction(ArrayFilter);
    194 
    195 /* ES5 15.4.4.21. */
    196 function ArrayReduce(callbackfn /*, initialValue*/) {
    197  /* Step 1. */
    198  var O = ToObject(this);
    199 
    200  /* Steps 2-3. */
    201  var len = ToLength(O.length);
    202 
    203  /* Step 4. */
    204  if (ArgumentsLength() === 0) {
    205    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.reduce");
    206  }
    207  if (!IsCallable(callbackfn)) {
    208    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
    209  }
    210 
    211  /* Step 6. */
    212  var k = 0;
    213 
    214  /* Steps 5, 7-8. */
    215  var accumulator;
    216  if (ArgumentsLength() > 1) {
    217    accumulator = GetArgument(1);
    218  } else {
    219    /* Step 5. */
    220    // Add an explicit |throw| here and below to inform Ion that the
    221    // ThrowTypeError calls exit this function.
    222    if (len === 0) {
    223      throw ThrowTypeError(JSMSG_EMPTY_ARRAY_REDUCE);
    224    }
    225 
    226    // Use a |do-while| loop to let Ion know that the loop will definitely
    227    // be entered at least once. When Ion is then also able to inline the
    228    // |in| operator, it can optimize away the whole loop.
    229    var kPresent = false;
    230    do {
    231      if (k in O) {
    232        kPresent = true;
    233        break;
    234      }
    235    } while (++k < len);
    236    if (!kPresent) {
    237      throw ThrowTypeError(JSMSG_EMPTY_ARRAY_REDUCE);
    238    }
    239 
    240    // Moved outside of the loop to ensure the assignment is non-conditional.
    241    accumulator = O[k++];
    242  }
    243 
    244  /* Step 9. */
    245  /* Steps a (implicit), and d. */
    246  for (; k < len; k++) {
    247    /* Step b */
    248    if (k in O) {
    249      /* Step c. */
    250      accumulator = callContentFunction(
    251        callbackfn,
    252        undefined,
    253        accumulator,
    254        O[k],
    255        k,
    256        O
    257      );
    258    }
    259  }
    260 
    261  /* Step 10. */
    262  return accumulator;
    263 }
    264 
    265 /* ES5 15.4.4.22. */
    266 function ArrayReduceRight(callbackfn /*, initialValue*/) {
    267  /* Step 1. */
    268  var O = ToObject(this);
    269 
    270  /* Steps 2-3. */
    271  var len = ToLength(O.length);
    272 
    273  /* Step 4. */
    274  if (ArgumentsLength() === 0) {
    275    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.reduce");
    276  }
    277  if (!IsCallable(callbackfn)) {
    278    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
    279  }
    280 
    281  /* Step 6. */
    282  var k = len - 1;
    283 
    284  /* Steps 5, 7-8. */
    285  var accumulator;
    286  if (ArgumentsLength() > 1) {
    287    accumulator = GetArgument(1);
    288  } else {
    289    /* Step 5. */
    290    // Add an explicit |throw| here and below to inform Ion that the
    291    // ThrowTypeError calls exit this function.
    292    if (len === 0) {
    293      throw ThrowTypeError(JSMSG_EMPTY_ARRAY_REDUCE);
    294    }
    295 
    296    // Use a |do-while| loop to let Ion know that the loop will definitely
    297    // be entered at least once. When Ion is then also able to inline the
    298    // |in| operator, it can optimize away the whole loop.
    299    var kPresent = false;
    300    do {
    301      if (k in O) {
    302        kPresent = true;
    303        break;
    304      }
    305    } while (--k >= 0);
    306    if (!kPresent) {
    307      throw ThrowTypeError(JSMSG_EMPTY_ARRAY_REDUCE);
    308    }
    309 
    310    // Moved outside of the loop to ensure the assignment is non-conditional.
    311    accumulator = O[k--];
    312  }
    313 
    314  /* Step 9. */
    315  /* Steps a (implicit), and d. */
    316  for (; k >= 0; k--) {
    317    /* Step b */
    318    if (k in O) {
    319      /* Step c. */
    320      accumulator = callContentFunction(
    321        callbackfn,
    322        undefined,
    323        accumulator,
    324        O[k],
    325        k,
    326        O
    327      );
    328    }
    329  }
    330 
    331  /* Step 10. */
    332  return accumulator;
    333 }
    334 
    335 /* ES6 draft 2013-05-14 15.4.3.23. */
    336 function ArrayFind(predicate /*, thisArg*/) {
    337  /* Steps 1-2. */
    338  var O = ToObject(this);
    339 
    340  /* Steps 3-5. */
    341  var len = ToLength(O.length);
    342 
    343  /* Step 6. */
    344  if (ArgumentsLength() === 0) {
    345    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.find");
    346  }
    347  if (!IsCallable(predicate)) {
    348    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
    349  }
    350 
    351  /* Step 7. */
    352  var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
    353 
    354  /* Steps 8-9. */
    355  /* Steps a (implicit), and g. */
    356  for (var k = 0; k < len; k++) {
    357    /* Steps a-c. */
    358    var kValue = O[k];
    359    /* Steps d-f. */
    360    if (callContentFunction(predicate, T, kValue, k, O)) {
    361      return kValue;
    362    }
    363  }
    364 
    365  /* Step 10. */
    366  return undefined;
    367 }
    368 // Inlining this enables inlining of the callback function.
    369 SetIsInlinableLargeFunction(ArrayFind);
    370 
    371 /* ES6 draft 2013-05-14 15.4.3.23. */
    372 function ArrayFindIndex(predicate /*, thisArg*/) {
    373  /* Steps 1-2. */
    374  var O = ToObject(this);
    375 
    376  /* Steps 3-5. */
    377  var len = ToLength(O.length);
    378 
    379  /* Step 6. */
    380  if (ArgumentsLength() === 0) {
    381    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.find");
    382  }
    383  if (!IsCallable(predicate)) {
    384    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
    385  }
    386 
    387  /* Step 7. */
    388  var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
    389 
    390  /* Steps 8-9. */
    391  /* Steps a (implicit), and g. */
    392  for (var k = 0; k < len; k++) {
    393    /* Steps a-f. */
    394    if (callContentFunction(predicate, T, O[k], k, O)) {
    395      return k;
    396    }
    397  }
    398 
    399  /* Step 10. */
    400  return -1;
    401 }
    402 // Inlining this enables inlining of the callback function.
    403 SetIsInlinableLargeFunction(ArrayFindIndex);
    404 
    405 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
    406 // 22.1.3.3 Array.prototype.copyWithin ( target, start [ , end ] )
    407 function ArrayCopyWithin(target, start, end = undefined) {
    408  // Step 1.
    409  var O = ToObject(this);
    410 
    411  // Step 2.
    412  var len = ToLength(O.length);
    413 
    414  // Step 3.
    415  var relativeTarget = ToInteger(target);
    416 
    417  // Step 4.
    418  var to =
    419    relativeTarget < 0
    420      ? std_Math_max(len + relativeTarget, 0)
    421      : std_Math_min(relativeTarget, len);
    422 
    423  // Step 5.
    424  var relativeStart = ToInteger(start);
    425 
    426  // Step 6.
    427  var from =
    428    relativeStart < 0
    429      ? std_Math_max(len + relativeStart, 0)
    430      : std_Math_min(relativeStart, len);
    431 
    432  // Step 7.
    433  var relativeEnd = end === undefined ? len : ToInteger(end);
    434 
    435  // Step 8.
    436  var final =
    437    relativeEnd < 0
    438      ? std_Math_max(len + relativeEnd, 0)
    439      : std_Math_min(relativeEnd, len);
    440 
    441  // Step 9.
    442  var count = std_Math_min(final - from, len - to);
    443 
    444  // Steps 10-12.
    445  if (from < to && to < from + count) {
    446    // Steps 10.b-c.
    447    from = from + count - 1;
    448    to = to + count - 1;
    449 
    450    // Step 12.
    451    while (count > 0) {
    452      if (from in O) {
    453        O[to] = O[from];
    454      } else {
    455        delete O[to];
    456      }
    457 
    458      from--;
    459      to--;
    460      count--;
    461    }
    462  } else {
    463    // Step 12.
    464    while (count > 0) {
    465      if (from in O) {
    466        O[to] = O[from];
    467      } else {
    468        delete O[to];
    469      }
    470 
    471      from++;
    472      to++;
    473      count--;
    474    }
    475  }
    476 
    477  // Step 13.
    478  return O;
    479 }
    480 
    481 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
    482 // 22.1.3.6 Array.prototype.fill ( value [ , start [ , end ] ] )
    483 function ArrayFill(value, start = 0, end = undefined) {
    484  // Step 1.
    485  var O = ToObject(this);
    486 
    487  // Step 2.
    488  var len = ToLength(O.length);
    489 
    490  // Step 3.
    491  var relativeStart = ToInteger(start);
    492 
    493  // Step 4.
    494  var k =
    495    relativeStart < 0
    496      ? std_Math_max(len + relativeStart, 0)
    497      : std_Math_min(relativeStart, len);
    498 
    499  // Step 5.
    500  var relativeEnd = end === undefined ? len : ToInteger(end);
    501 
    502  // Step 6.
    503  var final =
    504    relativeEnd < 0
    505      ? std_Math_max(len + relativeEnd, 0)
    506      : std_Math_min(relativeEnd, len);
    507 
    508  // Step 7.
    509  for (; k < final; k++) {
    510    O[k] = value;
    511  }
    512 
    513  // Step 8.
    514  return O;
    515 }
    516 
    517 // ES6, 22.1.5.2.1
    518 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%.next
    519 function ArrayIteratorNext() {
    520  // Step 1-3.
    521  var obj = this;
    522  if (!IsObject(obj) || (obj = GuardToArrayIterator(obj)) === null) {
    523    return callFunction(
    524      CallArrayIteratorMethodIfWrapped,
    525      this,
    526      "ArrayIteratorNext"
    527    );
    528  }
    529 
    530  // Step 4.
    531  var a = UnsafeGetReservedSlot(obj, ITERATOR_SLOT_TARGET);
    532  var result = { value: undefined, done: false };
    533 
    534  // Step 5.
    535  if (a === null) {
    536    result.done = true;
    537    return result;
    538  }
    539 
    540  // Step 6.
    541  // The index might not be an integer, so we have to do a generic get here.
    542  var index = UnsafeGetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX);
    543 
    544  // Step 7.
    545  var itemKind = UnsafeGetInt32FromReservedSlot(obj, ARRAY_ITERATOR_SLOT_ITEM_KIND);
    546 
    547  // Step 8-9.
    548  var len;
    549  if (IsPossiblyWrappedTypedArray(a)) {
    550    len = PossiblyWrappedTypedArrayLength(a);
    551 
    552    // If the length is non-zero, the buffer can't be detached.
    553    if (len === 0) {
    554      if (PossiblyWrappedTypedArrayHasDetachedBuffer(a)) {
    555        ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
    556      }
    557    }
    558  } else {
    559    len = ToLength(a.length);
    560  }
    561 
    562  // Step 10.
    563  if (index >= len) {
    564    UnsafeSetReservedSlot(obj, ITERATOR_SLOT_TARGET, null);
    565    result.done = true;
    566    return result;
    567  }
    568 
    569  // Step 11.
    570  UnsafeSetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX, index + 1);
    571 
    572  // Step 16.
    573  if (itemKind === ITEM_KIND_VALUE) {
    574    result.value = a[index];
    575    return result;
    576  }
    577 
    578  // Step 13.
    579  if (itemKind === ITEM_KIND_KEY_AND_VALUE) {
    580    var pair = [index, a[index]];
    581    result.value = pair;
    582    return result;
    583  }
    584 
    585  // Step 12.
    586  assert(itemKind === ITEM_KIND_KEY, itemKind);
    587  result.value = index;
    588  return result;
    589 }
    590 // We want to inline this to do scalar replacement of the result object.
    591 SetIsInlinableLargeFunction(ArrayIteratorNext);
    592 
    593 // Uncloned functions with `$` prefix are allocated as extended function
    594 // to store the original name in `SetCanonicalName`.
    595 function $ArrayValues() {
    596  RETURN_ARRAY_ITERATOR(this, ITEM_KIND_VALUE);
    597 }
    598 SetCanonicalName($ArrayValues, "values");
    599 
    600 function ArrayEntries() {
    601  RETURN_ARRAY_ITERATOR(this, ITEM_KIND_KEY_AND_VALUE);
    602 }
    603 
    604 function ArrayKeys() {
    605  RETURN_ARRAY_ITERATOR(this, ITEM_KIND_KEY);
    606 }
    607 
    608 // https://tc39.es/proposal-array-from-async/
    609 // TODO: Bug 1834560 The step numbers in this will need updating when this is merged
    610 // into the main spec.
    611 function ArrayFromAsync(asyncItems, mapfn = undefined, thisArg = undefined) {
    612  // Step 1. Let C be the this value.
    613  var C = this;
    614 
    615  // Step 2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
    616  // Step 3. Let fromAsyncClosure be a new Abstract Closure with no parameters that captures C, mapfn, and thisArg and performs the following steps when called:
    617  var fromAsyncClosure = async () => {
    618    // Step 3.a. If mapfn is undefined, let mapping be false.
    619    // Step 3.b. Else,
    620    //     Step 3.b.i. If IsCallable(mapfn) is false, throw a TypeError exception.
    621    //     Step 3.b.ii. Let mapping be true.
    622    var mapping = mapfn !== undefined;
    623    if (mapping && !IsCallable(mapfn)) {
    624      ThrowTypeError(JSMSG_NOT_FUNCTION, ToSource(mapfn));
    625    }
    626 
    627    // Step 3.c. Let usingAsyncIterator be ? GetMethod(asyncItems, @@asyncIterator).
    628    var usingAsyncIterator = asyncItems[GetBuiltinSymbol("asyncIterator")];
    629    if (usingAsyncIterator === null) {
    630      usingAsyncIterator = undefined;
    631    }
    632 
    633    var usingSyncIterator = undefined;
    634    if (usingAsyncIterator !== undefined) {
    635      if (!IsCallable(usingAsyncIterator)) {
    636        ThrowTypeError(JSMSG_NOT_ITERABLE, ToSource(asyncItems));
    637      }
    638    } else {
    639      // Step 3.d. If usingAsyncIterator is undefined, then
    640 
    641      // Step 3.d.i. Let usingSyncIterator be ? GetMethod(asyncItems, @@iterator).
    642      usingSyncIterator = asyncItems[GetBuiltinSymbol("iterator")];
    643      if (usingSyncIterator === null) {
    644        usingSyncIterator = undefined;
    645      }
    646 
    647      if (usingSyncIterator !== undefined) {
    648        if (!IsCallable(usingSyncIterator)) {
    649          ThrowTypeError(JSMSG_NOT_ITERABLE, ToSource(asyncItems));
    650        }
    651      }
    652    }
    653 
    654    // Step 3.g. Let iteratorRecord be undefined.
    655    // Step 3.j. If iteratorRecord is not undefined, then ...
    656    if (usingAsyncIterator !== undefined || usingSyncIterator !== undefined) {
    657      // Note: The published spec as of f6acfc4f0277e625f13fd22068138aec61a12df3
    658      //       is incorrect. See https://github.com/tc39/proposal-array-from-async/issues/33
    659      //       Here we use the implementation provided by @bakkot in that bug
    660      //       in lieu for now; This allows to use a for-await loop below.
    661 
    662      // Steps 3.h-i are implicit through the for-await loop.
    663 
    664      // Step 3.h. If usingAsyncIterator is not undefined, then
    665      //     Step 3.h.i. Set iteratorRecord to ? GetIterator(asyncItems, async, usingAsyncIterator).
    666      // Step 3.i. Else if usingSyncIterator is not undefined, then
    667      //     Set iteratorRecord to ? CreateAsyncFromSyncIterator(GetIterator(asyncItems, sync, usingSyncIterator)).
    668 
    669      // https://github.com/tc39/proposal-array-from-async/pull/41
    670      // Step 3.e. If IsConstructor(C) is true, then
    671      //     Step 3.e.i. Let A be ? Construct(C).
    672      // Step 3.f. Else,
    673      //     Step 3.f.i. Let A be ! ArrayCreate(0).
    674      var A = IsConstructor(C) ? constructContentFunction(C, C) : [];
    675 
    676      // Step 3.j.i. Let k be 0.
    677      var k = 0;
    678 
    679      // Step 3.j.ii. Repeat,
    680      for await (var nextValue of allowContentIterWith(
    681        asyncItems,
    682        usingAsyncIterator,
    683        usingSyncIterator
    684      )) {
    685        // Following in the steps of Array.from, we don't actually implement 3.j.ii.1.
    686        // The comment in Array.from also applies here; we should only encounter this
    687        // after a huge loop around a proxy
    688        // Step 3.j.ii.1. If k ≥ 2**53 - 1, then
    689        //     Step 3.j.ii.1.a. Let error be ThrowCompletion(a newly created TypeError object).
    690        //     Step 3.j.ii.1.b. Return ? AsyncIteratorClose(iteratorRecord, error).
    691        // Step 3.j.ii.2. Let Pk be ! ToString(𝔽(k)).
    692 
    693        // Step 3.j.ii.3. Let next be ? Await(IteratorStep(iteratorRecord)).
    694 
    695        // Step 3.j.ii.5. Let nextValue be ? IteratorValue(next). (Implicit through the for-await loop).
    696 
    697        // Step 3.j.ii.7. Else, let mappedValue be nextValue. (Reordered)
    698        var mappedValue = nextValue;
    699 
    700        // Step 3.j.ii.6. If mapping is true, then
    701        if (mapping) {
    702          // Step 3.j.ii.6.a. Let mappedValue be Call(mapfn, thisArg, « nextValue, 𝔽(k) »).
    703          // Step 3.j.ii.6.b. IfAbruptCloseAsyncIterator(mappedValue, iteratorRecord).
    704          //   Abrupt completion will be handled by the for-await loop.
    705          mappedValue = callContentFunction(mapfn, thisArg, nextValue, k);
    706 
    707          // Step 3.j.ii.6.c. Set mappedValue to Await(mappedValue).
    708          // Step 3.j.ii.6.d. IfAbruptCloseAsyncIterator(mappedValue, iteratorRecord).
    709          mappedValue = await mappedValue;
    710        }
    711 
    712        // Step 3.j.ii.8. Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue).
    713        // Step 3.j.ii.9. If defineStatus is an abrupt completion, return ? AsyncIteratorClose(iteratorRecord, defineStatus).
    714        DefineDataProperty(A, k, mappedValue);
    715 
    716        // Step 3.j.ii.10. Set k to k + 1.
    717        k = k + 1;
    718      }
    719 
    720      // Step 3.j.ii.4. If next is false, then (Reordered)
    721 
    722      // Step 3.j.ii.4.a. Perform ? Set(A, "length", 𝔽(k), true).
    723      A.length = k;
    724 
    725      // Step 3.j.ii.4.b. Return Completion Record { [[Type]]: return, [[Value]]: A, [[Target]]: empty }.
    726      return A;
    727    }
    728 
    729    // Step 3.k. Else,
    730 
    731    // Step 3.k.i. NOTE: asyncItems is neither an AsyncIterable nor an Iterable so assume it is an array-like object.
    732    // Step 3.k.ii. Let arrayLike be ! ToObject(asyncItems).
    733    var arrayLike = ToObject(asyncItems);
    734 
    735    // Step 3.k.iii. Let len be ? LengthOfArrayLike(arrayLike).
    736    var len = ToLength(arrayLike.length);
    737 
    738    // Step 3.k.iv. If IsConstructor(C) is true, then
    739    //     Step 3.k.iv.1. Let A be ? Construct(C, « 𝔽(len) »).
    740    // Step 3.k.v. Else,
    741    //     Step 3.k.v.1. Let A be ? ArrayCreate(len).
    742    var A = IsConstructor(C) ? constructContentFunction(C, C, len) : std_Array(len);
    743 
    744    // Step 3.k.vi. Let k be 0.
    745    var k = 0;
    746 
    747    // Step 3.k.vii. Repeat, while k < len,
    748    while (k < len) {
    749      // Step 3.k.vii.1. Let Pk be ! ToString(𝔽(k)).
    750      // Step 3.k.vii.2. Let kValue be ? Get(arrayLike, Pk).
    751      // Step 3.k.vii.3. Let kValue be ? Await(kValue).
    752      var kValue = await arrayLike[k];
    753 
    754      // Step 3.k.vii.4. If mapping is true, then
    755      //     Step 3.k.vii.4.a. Let mappedValue be ? Call(mapfn, thisArg, « kValue, 𝔽(k) »).
    756      //     Step 3.k.vii.4.b. Let mappedValue be ? Await(mappedValue).
    757      // Step 3.k.vii.5. Else, let mappedValue be kValue.
    758      var mappedValue = mapping
    759        ? await callContentFunction(mapfn, thisArg, kValue, k)
    760        : kValue;
    761 
    762      // Step 3.k.vii.6. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
    763      DefineDataProperty(A, k, mappedValue);
    764 
    765      // Step 3.k.vii.7. Set k to k + 1.
    766      k = k + 1;
    767    }
    768 
    769    // Step 3.k.viii. Perform ? Set(A, "length", 𝔽(len), true).
    770    A.length = len;
    771 
    772    // Step 3.k.ix. Return Completion Record { [[Type]]: return, [[Value]]: A, [[Target]]: empty }.
    773    return A;
    774  };
    775 
    776  // Step 4. Perform AsyncFunctionStart(promiseCapability, fromAsyncClosure).
    777  // Step 5. Return promiseCapability.[[Promise]].
    778  return fromAsyncClosure();
    779 }
    780 
    781 // ES 2017 draft 0f10dba4ad18de92d47d421f378233a2eae8f077 22.1.2.1
    782 function ArrayFrom(items, mapfn = undefined, thisArg = undefined) {
    783  // Step 1.
    784  var C = this;
    785 
    786  // Steps 2-3.
    787  var mapping = mapfn !== undefined;
    788  if (mapping && !IsCallable(mapfn)) {
    789    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, mapfn));
    790  }
    791  var T = thisArg;
    792 
    793  // Step 4.
    794  // Inlined: GetMethod, steps 1-2.
    795  var usingIterator = items[GetBuiltinSymbol("iterator")];
    796 
    797  // Step 5.
    798  // Inlined: GetMethod, step 3.
    799  if (!IsNullOrUndefined(usingIterator)) {
    800    // Inlined: GetMethod, step 4.
    801    if (!IsCallable(usingIterator)) {
    802      ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, items));
    803    }
    804 
    805    // Steps 5.a-b.
    806    var A = IsConstructor(C) ? constructContentFunction(C, C) : [];
    807 
    808    // Step 5.d.
    809    var k = 0;
    810 
    811    // Steps 5.c, 5.e
    812    for (var nextValue of allowContentIterWith(items, usingIterator)) {
    813      // Step 5.e.i.
    814      // Disabled for performance reason.  We won't hit this case on
    815      // normal array, since DefineDataProperty will throw before it.
    816      // We could hit this when |A| is a proxy and it ignores
    817      // |DefineDataProperty|, but it happens only after too long loop.
    818      /*
    819      if (k >= 0x1fffffffffffff) {
    820          ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
    821      }
    822      */
    823 
    824      // Steps 5.e.vi-vii.
    825      var mappedValue = mapping
    826        ? callContentFunction(mapfn, T, nextValue, k)
    827        : nextValue;
    828 
    829      // Steps 5.e.ii (reordered), 5.e.viii.
    830      DefineDataProperty(A, k++, mappedValue);
    831    }
    832 
    833    // Step 5.e.iv.
    834    A.length = k;
    835    return A;
    836  }
    837 
    838  // Step 7 is an assertion: items is not an Iterator. Testing this is
    839  // literally the very last thing we did, so we don't assert here.
    840 
    841  // Steps 8-9.
    842  var arrayLike = ToObject(items);
    843 
    844  // Steps 10-11.
    845  var len = ToLength(arrayLike.length);
    846 
    847  // Steps 12-14.
    848  var A = IsConstructor(C)
    849    ? constructContentFunction(C, C, len)
    850    : std_Array(len);
    851 
    852  // Steps 15-16.
    853  for (var k = 0; k < len; k++) {
    854    // Steps 16.a-c.
    855    var kValue = items[k];
    856 
    857    // Steps 16.d-e.
    858    var mappedValue = mapping
    859      ? callContentFunction(mapfn, T, kValue, k)
    860      : kValue;
    861 
    862    // Steps 16.f-g.
    863    DefineDataProperty(A, k, mappedValue);
    864  }
    865 
    866  // Steps 17-18.
    867  A.length = len;
    868 
    869  // Step 19.
    870  return A;
    871 }
    872 
    873 // ES2015 22.1.3.27 Array.prototype.toString.
    874 function ArrayToString() {
    875  // Steps 1-2.
    876  var array = ToObject(this);
    877 
    878  // Steps 3-4.
    879  var func = array.join;
    880 
    881  // Steps 5-6.
    882  if (!IsCallable(func)) {
    883    return callFunction(std_Object_toString, array);
    884  }
    885  return callContentFunction(func, array);
    886 }
    887 
    888 // ES2017 draft rev f8a9be8ea4bd97237d176907a1e3080dce20c68f
    889 // 22.1.3.27 Array.prototype.toLocaleString ([ reserved1 [ , reserved2 ] ])
    890 // ES2017 Intl draft rev 78bbe7d1095f5ff3760ac4017ed366026e4cb276
    891 // 13.4.1 Array.prototype.toLocaleString ([ locales [ , options ]])
    892 function ArrayToLocaleString(locales, options) {
    893  // Step 1 (ToObject already performed in native code).
    894  assert(IsObject(this), "|this| should be an object");
    895  var array = this;
    896 
    897  // Step 2.
    898  var len = ToLength(array.length);
    899 
    900  // Step 4.
    901  if (len === 0) {
    902    return "";
    903  }
    904 
    905  // Step 5.
    906  var firstElement = array[0];
    907 
    908  // Steps 6-7.
    909  var R;
    910  if (IsNullOrUndefined(firstElement)) {
    911    R = "";
    912  } else {
    913    #if JS_HAS_INTL_API
    914    R = ToString(
    915      callContentFunction(
    916        firstElement.toLocaleString,
    917        firstElement,
    918        locales,
    919        options
    920      )
    921    );
    922    #else
    923    R = ToString(
    924      callContentFunction(firstElement.toLocaleString, firstElement)
    925    );
    926    #endif
    927  }
    928 
    929  // Step 3 (reordered).
    930  // We don't (yet?) implement locale-dependent separators.
    931  var separator = ",";
    932 
    933  // Steps 8-9.
    934  for (var k = 1; k < len; k++) {
    935    // Step 9.b.
    936    var nextElement = array[k];
    937 
    938    // Steps 9.a, 9.c-e.
    939    R += separator;
    940    if (!IsNullOrUndefined(nextElement)) {
    941      #if JS_HAS_INTL_API
    942      R += ToString(
    943        callContentFunction(
    944          nextElement.toLocaleString,
    945          nextElement,
    946          locales,
    947          options
    948        )
    949      );
    950      #else
    951      R += ToString(
    952        callContentFunction(nextElement.toLocaleString, nextElement)
    953      );
    954      #endif
    955    }
    956  }
    957 
    958  // Step 10.
    959  return R;
    960 }
    961 
    962 // ES 2016 draft Mar 25, 2016 22.1.2.5.
    963 function $ArraySpecies() {
    964  // Step 1.
    965  return this;
    966 }
    967 SetCanonicalName($ArraySpecies, "get [Symbol.species]");
    968 
    969 // ES 2016 draft Mar 25, 2016 9.4.2.3.
    970 function ArraySpeciesCreate(originalArray, length) {
    971  // Step 1.
    972  assert(typeof length === "number", "length should be a number");
    973  assert(length >= 0, "length should be a non-negative number");
    974 
    975  // Step 2.
    976  // eslint-disable-next-line no-compare-neg-zero
    977  if (length === -0) {
    978    length = 0;
    979  }
    980 
    981  // Step 4, 6.
    982  if (!IsArray(originalArray)) {
    983    return std_Array(length);
    984  }
    985 
    986  // Step 5.a.
    987  var originalConstructor = originalArray.constructor;
    988  var C = originalConstructor;
    989 
    990  // Step 5.b.
    991  if (IsConstructor(C) && IsCrossRealmArrayConstructor(C)) {
    992    return std_Array(length);
    993  }
    994 
    995  // Step 5.c.
    996  if (IsObject(C)) {
    997    // Step 5.c.i.
    998    C = C[GetBuiltinSymbol("species")];
    999 
   1000    // Optimized path for an ordinary Array.
   1001    if (C === GetBuiltinConstructor("Array")) {
   1002      return std_Array(length);
   1003    }
   1004 
   1005    // Step 5.c.ii.
   1006    if (C === null) {
   1007      return std_Array(length);
   1008    }
   1009 
   1010  }
   1011 
   1012  // Step 6.
   1013  if (C === undefined) {
   1014    return std_Array(length);
   1015  }
   1016 
   1017  // Step 7.
   1018  if (!IsConstructor(C)) {
   1019    ThrowTypeError(JSMSG_NOT_CONSTRUCTOR, "constructor property");
   1020  }
   1021 
   1022  // Step 8.
   1023  return constructContentFunction(C, C, length);
   1024 }
   1025 
   1026 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
   1027 // 22.1.3.11 Array.prototype.flatMap ( mapperFunction [ , thisArg ] )
   1028 function ArrayFlatMap(mapperFunction /*, thisArg*/) {
   1029  // Step 1.
   1030  var O = ToObject(this);
   1031 
   1032  // Step 2.
   1033  var sourceLen = ToLength(O.length);
   1034 
   1035  // Step 3.
   1036  if (!IsCallable(mapperFunction)) {
   1037    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, mapperFunction));
   1038  }
   1039 
   1040  // Step 4.
   1041  var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
   1042 
   1043  // Step 5.
   1044  var A = CanOptimizeArraySpecies(O) ? [] : ArraySpeciesCreate(O, 0);
   1045 
   1046  // Step 6.
   1047  FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T);
   1048 
   1049  // Step 7.
   1050  return A;
   1051 }
   1052 
   1053 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
   1054 // 22.1.3.10 Array.prototype.flat ( [ depth ] )
   1055 function ArrayFlat(/* depth */) {
   1056  // Step 1.
   1057  var O = ToObject(this);
   1058 
   1059  // Step 2.
   1060  var sourceLen = ToLength(O.length);
   1061 
   1062  // Step 3.
   1063  var depthNum = 1;
   1064 
   1065  // Step 4.
   1066  if (ArgumentsLength() && GetArgument(0) !== undefined) {
   1067    depthNum = ToInteger(GetArgument(0));
   1068  }
   1069 
   1070  // Step 5.
   1071  var A = CanOptimizeArraySpecies(O) ? [] : ArraySpeciesCreate(O, 0);
   1072 
   1073  // Step 6.
   1074  FlattenIntoArray(A, O, sourceLen, 0, depthNum);
   1075 
   1076  // Step 7.
   1077  return A;
   1078 }
   1079 
   1080 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
   1081 // 22.1.3.10.1 FlattenIntoArray ( target, source, sourceLen, start, depth [ , mapperFunction, thisArg ] )
   1082 function FlattenIntoArray(
   1083  target,
   1084  source,
   1085  sourceLen,
   1086  start,
   1087  depth,
   1088  mapperFunction,
   1089  thisArg
   1090 ) {
   1091  // Step 1.
   1092  var targetIndex = start;
   1093 
   1094  // Steps 2-3.
   1095  for (var sourceIndex = 0; sourceIndex < sourceLen; sourceIndex++) {
   1096    // Steps 3.a-c.
   1097    if (sourceIndex in source) {
   1098      // Step 3.c.i.
   1099      var element = source[sourceIndex];
   1100 
   1101      if (mapperFunction) {
   1102        // Step 3.c.ii.1.
   1103        assert(ArgumentsLength() === 7, "thisArg is present");
   1104 
   1105        // Step 3.c.ii.2.
   1106        element = callContentFunction(
   1107          mapperFunction,
   1108          thisArg,
   1109          element,
   1110          sourceIndex,
   1111          source
   1112        );
   1113      }
   1114 
   1115      // Step 3.c.iii.
   1116      var shouldFlatten = false;
   1117 
   1118      // Step 3.c.iv.
   1119      if (depth > 0) {
   1120        // Step 3.c.iv.1.
   1121        shouldFlatten = IsArray(element);
   1122      }
   1123 
   1124      // Step 3.c.v.
   1125      if (shouldFlatten) {
   1126        // Step 3.c.v.1.
   1127        var elementLen = ToLength(element.length);
   1128 
   1129        // Step 3.c.v.2.
   1130        targetIndex = FlattenIntoArray(
   1131          target,
   1132          element,
   1133          elementLen,
   1134          targetIndex,
   1135          depth - 1
   1136        );
   1137      } else {
   1138        // Step 3.c.vi.1.
   1139        if (targetIndex >= MAX_NUMERIC_INDEX) {
   1140          ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
   1141        }
   1142 
   1143        // Step 3.c.vi.2.
   1144        DefineDataProperty(target, targetIndex, element);
   1145 
   1146        // Step 3.c.vi.3.
   1147        targetIndex++;
   1148      }
   1149    }
   1150  }
   1151 
   1152  // Step 4.
   1153  return targetIndex;
   1154 }
   1155 
   1156 // https://github.com/tc39/proposal-relative-indexing-method
   1157 // Array.prototype.at ( index )
   1158 function ArrayAt(index) {
   1159  // Step 1.
   1160  var O = ToObject(this);
   1161 
   1162  // Step 2.
   1163  var len = ToLength(O.length);
   1164 
   1165  // Step 3.
   1166  var relativeIndex = ToInteger(index);
   1167 
   1168  // Steps 4-5.
   1169  var k;
   1170  if (relativeIndex >= 0) {
   1171    k = relativeIndex;
   1172  } else {
   1173    k = len + relativeIndex;
   1174  }
   1175 
   1176  // Step 6.
   1177  if (k < 0 || k >= len) {
   1178    return undefined;
   1179  }
   1180 
   1181  // Step 7.
   1182  return O[k];
   1183 }
   1184 // This function is only barely too long for normal inlining.
   1185 SetIsInlinableLargeFunction(ArrayAt);
   1186 
   1187 // https://github.com/tc39/proposal-change-array-by-copy
   1188 // Array.prototype.toReversed()
   1189 function ArrayToReversed() {
   1190  // Step 1. Let O be ? ToObject(this value).
   1191  var O = ToObject(this);
   1192 
   1193  // Step 2. Let len be ? LengthOfArrayLike(O).
   1194  var len = ToLength(O.length);
   1195 
   1196  // Step 3. Let A be ArrayCreate(𝔽(len)).
   1197  var A = std_Array(len);
   1198 
   1199  // Step 4. Let k be 0.
   1200  // Step 5. Repeat, while k < len,
   1201  for (var k = 0; k < len; k++) {
   1202    // Step 5.a. Let from be ! ToString(𝔽(len - k - 1)).
   1203    var from = len - k - 1;
   1204 
   1205    // Skip Step 5.b. Let Pk be ToString(𝔽(k)).
   1206    // k is coerced into a string through the property access.
   1207 
   1208    // Step 5.c. Let fromValue be ? Get(O, from).
   1209    var fromValue = O[from];
   1210 
   1211    // Step 5.d. Perform ! CreateDataPropertyOrThrow(A, 𝔽(k), fromValue).
   1212    DefineDataProperty(A, k, fromValue);
   1213  }
   1214 
   1215  // Step 6. Return A.
   1216  return A;
   1217 }
   1218 
   1219 // https://github.com/tc39/proposal-change-array-by-copy
   1220 // Array.prototype.toSorted()
   1221 function ArrayToSorted(comparefn) {
   1222  // Step 1.  If comparefn is not undefined and IsCallable(comparefn) is
   1223  // false, throw a TypeError exception.
   1224  if (comparefn !== undefined && !IsCallable(comparefn)) {
   1225    ThrowTypeError(JSMSG_BAD_TOSORTED_ARG);
   1226  }
   1227 
   1228  // Step 2. Let O be ? ToObject(this value).
   1229  var O = ToObject(this);
   1230 
   1231  // Step 3. Let len be ? LengthOfArrayLike(O).
   1232  var len = ToLength(O.length);
   1233 
   1234  // Step 4. Let A be ? ArrayCreate(𝔽(len)).
   1235  var items = std_Array(len);
   1236 
   1237  // We depart from steps 5-8 of the spec for performance reasons, as
   1238  // following the spec would require copying the input array twice.
   1239  // Instead, we create a new array that replaces holes with undefined,
   1240  // and sort this array.
   1241  for (var k = 0; k < len; k++) {
   1242    DefineDataProperty(items, k, O[k]);
   1243  }
   1244 
   1245  // Arrays with less than two elements remain unchanged when sorted.
   1246  if (len <= 1) {
   1247    return items;
   1248  }
   1249 
   1250  // Steps 5-9.
   1251  return callFunction(std_Array_sort, items, comparefn);
   1252 }
   1253 
   1254 // https://github.com/tc39/proposal-array-find-from-last
   1255 // Array.prototype.findLast ( predicate, thisArg )
   1256 function ArrayFindLast(predicate /*, thisArg*/) {
   1257  // Step 1.
   1258  var O = ToObject(this);
   1259 
   1260  // Step 2.
   1261  var len = ToLength(O.length);
   1262 
   1263  // Step 3.
   1264  if (ArgumentsLength() === 0) {
   1265    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.findLast");
   1266  }
   1267  if (!IsCallable(predicate)) {
   1268    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
   1269  }
   1270 
   1271  var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
   1272 
   1273  // Steps 4-5.
   1274  for (var k = len - 1; k >= 0; k--) {
   1275    // Steps 5.a-b.
   1276    var kValue = O[k];
   1277 
   1278    // Steps 5.c-d.
   1279    if (callContentFunction(predicate, thisArg, kValue, k, O)) {
   1280      return kValue;
   1281    }
   1282  }
   1283 
   1284  // Step 6.
   1285  return undefined;
   1286 }
   1287 // Inlining this enables inlining of the callback function.
   1288 SetIsInlinableLargeFunction(ArrayFindLast);
   1289 
   1290 // https://github.com/tc39/proposal-array-find-from-last
   1291 // Array.prototype.findLastIndex ( predicate, thisArg )
   1292 function ArrayFindLastIndex(predicate /*, thisArg*/) {
   1293  // Step 1.
   1294  var O = ToObject(this);
   1295 
   1296  // Steps 2.
   1297  var len = ToLength(O.length);
   1298 
   1299  // Step 3.
   1300  if (ArgumentsLength() === 0) {
   1301    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.findLastIndex");
   1302  }
   1303  if (!IsCallable(predicate)) {
   1304    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
   1305  }
   1306 
   1307  var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined;
   1308 
   1309  // Steps 4-5.
   1310  for (var k = len - 1; k >= 0; k--) {
   1311    // Steps 5.a-d.
   1312    if (callContentFunction(predicate, thisArg, O[k], k, O)) {
   1313      return k;
   1314    }
   1315  }
   1316 
   1317  // Step 6.
   1318  return -1;
   1319 }
   1320 // Inlining this enables inlining of the callback function.
   1321 SetIsInlinableLargeFunction(ArrayFindLastIndex);