tor-browser

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

Map.js (6712B)


      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 // ES2017 draft rev 0e10c9f29fca1385980c08a7d5e7bb3eb775e2e4
      6 // 23.1.1.1 Map, steps 6-8
      7 function MapConstructorInit(iterable) {
      8  var map = this;
      9 
     10  // Step 6.a.
     11  var adder = map.set;
     12 
     13  // Step 6.b.
     14  if (!IsCallable(adder)) {
     15    ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
     16  }
     17 
     18  // Steps 6.c-8.
     19  for (var nextItem of allowContentIter(iterable)) {
     20    // Step 8.d.
     21    if (!IsObject(nextItem)) {
     22      ThrowTypeError(JSMSG_INVALID_MAP_ITERABLE, "Map");
     23    }
     24 
     25    // Steps 8.e-j.
     26    callContentFunction(adder, map, nextItem[0], nextItem[1]);
     27  }
     28 }
     29 
     30 // ES2018 draft rev f83aa38282c2a60c6916ebc410bfdf105a0f6a54
     31 // 23.1.3.5 Map.prototype.forEach ( callbackfn [ , thisArg ] )
     32 function MapForEach(callbackfn, thisArg = undefined) {
     33  // Step 1.
     34  var M = this;
     35 
     36  // Steps 2-3.
     37  if (!IsObject(M) || (M = GuardToMapObject(M)) === null) {
     38    return callFunction(
     39      CallMapMethodIfWrapped,
     40      this,
     41      callbackfn,
     42      thisArg,
     43      "MapForEach"
     44    );
     45  }
     46 
     47  // Step 4.
     48  if (!IsCallable(callbackfn)) {
     49    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
     50  }
     51 
     52  // Steps 5-8.
     53  var entries = callFunction(std_Map_entries, M);
     54 
     55  // Inlined: MapIteratorNext
     56  var mapIterationResultPair = globalMapIterationResultPair;
     57 
     58  while (true) {
     59    var done = GetNextMapEntryForIterator(entries, mapIterationResultPair);
     60    if (done) {
     61      break;
     62    }
     63 
     64    var key = mapIterationResultPair[0];
     65    var value = mapIterationResultPair[1];
     66    mapIterationResultPair[0] = null;
     67    mapIterationResultPair[1] = null;
     68 
     69    callContentFunction(callbackfn, thisArg, value, key, M);
     70  }
     71 }
     72 
     73 var globalMapIterationResultPair = CreateMapIterationResultPair();
     74 
     75 function MapIteratorNext() {
     76  // Step 1.
     77  var O = this;
     78 
     79  // Steps 2-3.
     80  if (!IsObject(O) || (O = GuardToMapIterator(O)) === null) {
     81    return callFunction(
     82      CallMapIteratorMethodIfWrapped,
     83      this,
     84      "MapIteratorNext"
     85    );
     86  }
     87 
     88  // Steps 4-5 (implemented in GetNextMapEntryForIterator).
     89  // Steps 8-9 (omitted).
     90 
     91  var mapIterationResultPair = globalMapIterationResultPair;
     92 
     93  var retVal = { value: undefined, done: true };
     94 
     95  // Step 10.a, 11.
     96  var done = GetNextMapEntryForIterator(O, mapIterationResultPair);
     97  if (!done) {
     98    // Steps 10.b-c (omitted).
     99 
    100    // Step 6.
    101    var itemKind = UnsafeGetInt32FromReservedSlot(O, MAP_SET_ITERATOR_SLOT_ITEM_KIND);
    102 
    103    var result;
    104    if (itemKind === ITEM_KIND_KEY) {
    105      // Step 10.d.i.
    106      result = mapIterationResultPair[0];
    107    } else if (itemKind === ITEM_KIND_VALUE) {
    108      // Step 10.d.ii.
    109      result = mapIterationResultPair[1];
    110    } else {
    111      // Step 10.d.iii.
    112      assert(itemKind === ITEM_KIND_KEY_AND_VALUE, itemKind);
    113      result = [mapIterationResultPair[0], mapIterationResultPair[1]];
    114    }
    115 
    116    mapIterationResultPair[0] = null;
    117    mapIterationResultPair[1] = null;
    118    retVal.value = result;
    119    retVal.done = false;
    120  }
    121 
    122  // Steps 7, 12.
    123  return retVal;
    124 }
    125 
    126 // ES6 final draft 23.1.2.2.
    127 // Uncloned functions with `$` prefix are allocated as extended function
    128 // to store the original name in `SetCanonicalName`.
    129 function $MapSpecies() {
    130  // Step 1.
    131  return this;
    132 }
    133 SetCanonicalName($MapSpecies, "get [Symbol.species]");
    134 
    135 // Array Grouping proposal
    136 //
    137 // Map.groupBy ( items, callbackfn )
    138 //
    139 // https://tc39.es/proposal-array-grouping/#sec-map.groupby
    140 function MapGroupBy(items, callbackfn) {
    141  // Step 1. (Call to GroupBy is inlined.)
    142 
    143  // GroupBy, step 1.
    144  if (IsNullOrUndefined(items)) {
    145    ThrowTypeError(
    146      JSMSG_UNEXPECTED_TYPE,
    147      DecompileArg(0, items),
    148      items === null ? "null" : "undefined"
    149    );
    150  }
    151 
    152  // GroupBy, step 2.
    153  if (!IsCallable(callbackfn)) {
    154    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn));
    155  }
    156 
    157  // Step 2.
    158  var C = GetBuiltinConstructor("Map");
    159  var map = new C();
    160 
    161  // GroupBy, step 3. (Not applicable in our implementation.)
    162 
    163  // GroupBy, step 4.
    164  var k = 0;
    165 
    166  // GroupBy, steps 4 and 6.
    167  for (var value of allowContentIter(items)) {
    168    // GroupBy, step 6.a. (Not applicable)
    169    assert(k < 2 ** 53 - 1, "out-of-memory happens before k exceeds 2^53 - 1");
    170 
    171    // GroupBy, steps 6.b-d. (Implicit through for-of loop.)
    172 
    173    // GroupBy, step 6.e.
    174    var key = callContentFunction(callbackfn, undefined, value, k);
    175 
    176    // GroupBy, step 6.f. (Implicit through for-of loop.)
    177 
    178    // GroupBy, step 6.g. (Not applicable)
    179 
    180    // GroupBy, step 6.h. (Implicit through std_Map_get.)
    181 
    182    // GroupBy, step 6.i. (Inlined call to AddValueToKeyedGroup.)
    183    var elements = callFunction(std_Map_get, map, key);
    184    if (elements === undefined) {
    185      callFunction(std_Map_set, map, key, [value]);
    186    } else {
    187      DefineDataProperty(elements, elements.length, value);
    188    }
    189 
    190    // GroupBy, step 6.j.
    191    k += 1;
    192  }
    193 
    194  // Step 3. (Result map already populated in the previous loop.)
    195 
    196  // Step 4.
    197  return map;
    198 }
    199 
    200 /**
    201 * Upsert proposal
    202 *
    203 * Map.prototype.getOrInsertComputed ( key, callbackfn )
    204 *
    205 * https://tc39.es/proposal-upsert/
    206 */
    207 function MapGetOrInsertComputed(key, callbackfn) {
    208  // Step 1.  Let M be the this value.
    209  var M = this;
    210 
    211  // Step 2.  Perform ? RequireInternalSlot(M, [[MapData]]).
    212  if (!IsObject(M) || (M = GuardToMapObject(M)) === null) {
    213    return callFunction(
    214      CallMapMethodIfWrapped,
    215      this,
    216      key,
    217      callbackfn,
    218      "MapGetOrInsertComputed"
    219    );
    220  }
    221 
    222  // Step 3.  If IsCallable(callbackfn) is false, throw a TypeError exception.
    223  if (!IsCallable(callbackfn)) {
    224    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn));
    225  }
    226 
    227  // Step 4.  Set key to CanonicalizeKeyedCollectionKey(key).
    228  // key === 0 is true for both -0 and +0
    229  if (key === 0) {
    230    key = 0;
    231  }
    232  // Step 5.  For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
    233  // Step 5.a.  If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, return p.[[Value]].
    234  if (callFunction(std_Map_has, M, key)) {
    235    return callFunction(std_Map_get, M, key);
    236  }
    237 
    238  // Step 6.  Let value be ? Call(callbackfn, undefined, « key »).
    239  var value = callContentFunction(callbackfn, undefined, key);
    240 
    241  // Step 7.  For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
    242  // Step 7.a.  If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, then
    243  // Step 7.a.i.  Set p.[[Value]] to value.
    244  // Step 8.  Let p be the Record { [[Key]]: key, [[Value]]: value }.
    245  // Step 9.  Append p to M.[[MapData]].
    246  callFunction(std_Map_set, M, key, value);
    247 
    248  // Step 7.a.ii, 10. Return value.
    249  return value;
    250 }