| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 "use strict"; | 5 "use strict"; |
| 6 | 6 |
| 7 // This file relies on the fact that the following declaration has been made | 7 // This file relies on the fact that the following declaration has been made |
| 8 // in runtime.js: | 8 // in runtime.js: |
| 9 // var $Array = global.Array; | 9 // var $Array = global.Array; |
| 10 | 10 |
| 11 var $Set = global.Set; | 11 var $Set = global.Set; |
| 12 var $Map = global.Map; | 12 var $Map = global.Map; |
| 13 | 13 |
| 14 | 14 |
| 15 (function() { |
| 16 "use strict"; |
| 17 |
| 18 function HashToBucket(hash, numBuckets) { |
| 19 return hash & (numBuckets - 1); |
| 20 } |
| 21 %SetInlineBuiltinFlag(HashToBucket); |
| 22 |
| 23 |
| 24 function HashToEntry(table, hash, numBuckets) { |
| 25 var bucket = HashToBucket(hash, numBuckets); |
| 26 return %_FixedArrayGet(table, HASH_TABLE_START_INDEX + bucket); |
| 27 } |
| 28 %SetInlineBuiltinFlag(HashToEntry); |
| 29 |
| 30 |
| 31 function SetFindEntry(table, numBuckets, key, hash) { |
| 32 var keyIsNaN = IS_NUMBER(key) && NUMBER_IS_NAN(key); |
| 33 for (var entry = HashToEntry(table, hash, numBuckets); |
| 34 entry !== NOT_FOUND; |
| 35 entry = SET_CHAIN_AT(table, entry, numBuckets)) { |
| 36 var candidate = SET_KEY_AT(table, entry, numBuckets); |
| 37 if (key === candidate) { |
| 38 return entry; |
| 39 } |
| 40 if (keyIsNaN && IS_NUMBER(candidate) && NUMBER_IS_NAN(candidate)) { |
| 41 return entry; |
| 42 } |
| 43 } |
| 44 return NOT_FOUND; |
| 45 } |
| 46 %SetInlineBuiltinFlag(SetFindEntry); |
| 47 |
| 48 |
| 49 function MapFindEntry(table, numBuckets, key, hash) { |
| 50 var keyIsNaN = IS_NUMBER(key) && NUMBER_IS_NAN(key); |
| 51 for (var entry = HashToEntry(table, hash, numBuckets); |
| 52 entry !== NOT_FOUND; |
| 53 entry = MAP_CHAIN_AT(table, entry, numBuckets)) { |
| 54 var candidate = MAP_KEY_AT(table, entry, numBuckets); |
| 55 if (key === candidate) { |
| 56 return entry; |
| 57 } |
| 58 if (keyIsNaN && IS_NUMBER(candidate) && NUMBER_IS_NAN(candidate)) { |
| 59 return entry; |
| 60 } |
| 61 } |
| 62 return NOT_FOUND; |
| 63 } |
| 64 %SetInlineBuiltinFlag(MapFindEntry); |
| 65 |
| 66 |
| 67 function ComputeIntegerHash(key, seed) { |
| 68 var hash = key; |
| 69 hash = hash ^ seed; |
| 70 hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1; |
| 71 hash = hash ^ (hash >>> 12); |
| 72 hash = hash + (hash << 2); |
| 73 hash = hash ^ (hash >>> 4); |
| 74 hash = (hash * 2057) | 0; // hash = (hash + (hash << 3)) + (hash << 11); |
| 75 hash = hash ^ (hash >>> 16); |
| 76 return hash; |
| 77 } |
| 78 %SetInlineBuiltinFlag(ComputeIntegerHash); |
| 79 |
| 80 |
| 81 function GetHash(key) { |
| 82 if (%_IsSmi(key)) { |
| 83 return ComputeIntegerHash(key, 0); |
| 84 } |
| 85 if (IS_STRING(key)) { |
| 86 var field = %_StringGetRawHashField(key); |
| 87 if ((field & HASH_NOT_COMPUTED_MASK) === 0) { |
| 88 return (field >>> STRING_HASH_SHIFT); |
| 89 } |
| 90 } |
| 91 return %GenericHash(key); |
| 92 } |
| 93 %SetInlineBuiltinFlag(GetHash); |
| 94 |
| 95 |
| 15 // ------------------------------------------------------------------- | 96 // ------------------------------------------------------------------- |
| 16 // Harmony Set | 97 // Harmony Set |
| 17 | 98 |
| 18 function SetConstructor(iterable) { | 99 function SetConstructor(iterable) { |
| 19 if (!%_IsConstructCall()) { | 100 if (!%_IsConstructCall()) { |
| 20 throw MakeTypeError('constructor_not_function', ['Set']); | 101 throw MakeTypeError('constructor_not_function', ['Set']); |
| 21 } | 102 } |
| 22 | 103 |
| 23 %_SetInitialize(this); | 104 %_SetInitialize(this); |
| 24 | 105 |
| 25 if (!IS_NULL_OR_UNDEFINED(iterable)) { | 106 if (!IS_NULL_OR_UNDEFINED(iterable)) { |
| 26 var adder = this.add; | 107 var adder = this.add; |
| 27 if (!IS_SPEC_FUNCTION(adder)) { | 108 if (!IS_SPEC_FUNCTION(adder)) { |
| 28 throw MakeTypeError('property_not_function', ['add', this]); | 109 throw MakeTypeError('property_not_function', ['add', this]); |
| 29 } | 110 } |
| 30 | 111 |
| 31 for (var value of iterable) { | 112 for (var value of iterable) { |
| 32 %_CallFunction(this, value, adder); | 113 %_CallFunction(this, value, adder); |
| 33 } | 114 } |
| 34 } | 115 } |
| 35 } | 116 } |
| 36 | 117 |
| 37 | 118 |
| 38 function SetAddJS(key) { | 119 function SetAdd(key) { |
| 39 if (!IS_SET(this)) { | 120 if (!IS_SET(this)) { |
| 40 throw MakeTypeError('incompatible_method_receiver', | 121 throw MakeTypeError('incompatible_method_receiver', |
| 41 ['Set.prototype.add', this]); | 122 ['Set.prototype.add', this]); |
| 42 } | 123 } |
| 43 // Normalize -0 to +0 as required by the spec. | 124 // Normalize -0 to +0 as required by the spec. |
| 44 // Even though we use SameValueZero as the comparison for the keys we don't | 125 // Even though we use SameValueZero as the comparison for the keys we don't |
| 45 // want to ever store -0 as the key since the key is directly exposed when | 126 // want to ever store -0 as the key since the key is directly exposed when |
| 46 // doing iteration. | 127 // doing iteration. |
| 47 if (key === 0) { | 128 if (IS_NUMBER(key) && key === 0) { |
| 48 key = 0; | 129 key = 0; |
| 49 } | 130 } |
| 50 return %_SetAdd(this, key); | 131 var table = %_JSCollectionGetTable(this); |
| 132 var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX); |
| 133 var hash = GetHash(key); |
| 134 if (SetFindEntry(table, numBuckets, key, hash) !== NOT_FOUND) return this; |
| 135 |
| 136 var nof = %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX); |
| 137 var nod = %_FixedArrayGet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX); |
| 138 var capacity = numBuckets << 1; |
| 139 if ((nof + nod) >= capacity) { |
| 140 // Need to grow, bail out to runtime. |
| 141 %SetGrow(this); |
| 142 // Re-enter...TODO(adamk) Fix this |
| 143 return %_CallFunction(this, key, SetAdd); |
| 144 } |
| 145 var entry = nof + nod; |
| 146 var index = SET_ENTRY_TO_INDEX(entry, numBuckets); |
| 147 var bucket = HashToBucket(hash, numBuckets); |
| 148 var chainEntry = %_FixedArrayGet(table, HASH_TABLE_START_INDEX + bucket); |
| 149 %_FixedArraySet(table, HASH_TABLE_START_INDEX + bucket, entry | 0); |
| 150 %_FixedArraySet(table, index + SET_CHAIN_OFFSET, chainEntry | 0); |
| 151 %_FixedArraySet(table, NUMBER_OF_ELEMENTS_INDEX, (nof + 1) | 0); |
| 152 %_FixedArraySet(table, index, key); |
| 153 return this; |
| 51 } | 154 } |
| 52 | 155 |
| 53 | 156 |
| 54 function SetHasJS(key) { | 157 function SetHas(key) { |
| 55 if (!IS_SET(this)) { | 158 if (!IS_SET(this)) { |
| 56 throw MakeTypeError('incompatible_method_receiver', | 159 throw MakeTypeError('incompatible_method_receiver', |
| 57 ['Set.prototype.has', this]); | 160 ['Set.prototype.has', this]); |
| 58 } | 161 } |
| 59 return %_SetHas(this, key); | 162 var table = %_JSCollectionGetTable(this); |
| 163 var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX); |
| 164 var hash = GetHash(key); |
| 165 return SetFindEntry(table, numBuckets, key, hash) !== NOT_FOUND; |
| 60 } | 166 } |
| 61 | 167 |
| 62 | 168 |
| 63 function SetDeleteJS(key) { | 169 function SetDelete(key) { |
| 64 if (!IS_SET(this)) { | 170 if (!IS_SET(this)) { |
| 65 throw MakeTypeError('incompatible_method_receiver', | 171 throw MakeTypeError('incompatible_method_receiver', |
| 66 ['Set.prototype.delete', this]); | 172 ['Set.prototype.delete', this]); |
| 67 } | 173 } |
| 68 return %_SetDelete(this, key); | 174 var table = %_JSCollectionGetTable(this); |
| 175 var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX); |
| 176 var hash = GetHash(key); |
| 177 var entry = SetFindEntry(table, numBuckets, key, hash); |
| 178 if (entry === NOT_FOUND) return false; |
| 179 |
| 180 var nof = %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX) - 1; |
| 181 var nod = %_FixedArrayGet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX) + 1; |
| 182 var index = SET_ENTRY_TO_INDEX(entry, numBuckets); |
| 183 %_FixedArraySet(table, index, %_TheHole()); |
| 184 %_FixedArraySet(table, NUMBER_OF_ELEMENTS_INDEX, nof | 0); |
| 185 %_FixedArraySet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX, nod | 0); |
| 186 if (nof < (numBuckets >>> 1)) %SetShrink(this); |
| 187 return true; |
| 69 } | 188 } |
| 70 | 189 |
| 71 | 190 |
| 72 function SetGetSizeJS() { | 191 function SetGetSize() { |
| 73 if (!IS_SET(this)) { | 192 if (!IS_SET(this)) { |
| 74 throw MakeTypeError('incompatible_method_receiver', | 193 throw MakeTypeError('incompatible_method_receiver', |
| 75 ['Set.prototype.size', this]); | 194 ['Set.prototype.size', this]); |
| 76 } | 195 } |
| 77 return %_SetGetSize(this); | 196 var table = %_JSCollectionGetTable(this); |
| 197 return %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX); |
| 78 } | 198 } |
| 79 | 199 |
| 80 | 200 |
| 81 function SetClearJS() { | 201 function SetClearJS() { |
| 82 if (!IS_SET(this)) { | 202 if (!IS_SET(this)) { |
| 83 throw MakeTypeError('incompatible_method_receiver', | 203 throw MakeTypeError('incompatible_method_receiver', |
| 84 ['Set.prototype.clear', this]); | 204 ['Set.prototype.clear', this]); |
| 85 } | 205 } |
| 86 %_SetClear(this); | 206 %_SetClear(this); |
| 87 } | 207 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 | 243 |
| 124 %SetCode($Set, SetConstructor); | 244 %SetCode($Set, SetConstructor); |
| 125 %FunctionSetPrototype($Set, new $Object()); | 245 %FunctionSetPrototype($Set, new $Object()); |
| 126 %AddNamedProperty($Set.prototype, "constructor", $Set, DONT_ENUM); | 246 %AddNamedProperty($Set.prototype, "constructor", $Set, DONT_ENUM); |
| 127 %AddNamedProperty( | 247 %AddNamedProperty( |
| 128 $Set.prototype, symbolToStringTag, "Set", DONT_ENUM | READ_ONLY); | 248 $Set.prototype, symbolToStringTag, "Set", DONT_ENUM | READ_ONLY); |
| 129 | 249 |
| 130 %FunctionSetLength(SetForEach, 1); | 250 %FunctionSetLength(SetForEach, 1); |
| 131 | 251 |
| 132 // Set up the non-enumerable functions on the Set prototype object. | 252 // Set up the non-enumerable functions on the Set prototype object. |
| 133 InstallGetter($Set.prototype, "size", SetGetSizeJS); | 253 InstallGetter($Set.prototype, "size", SetGetSize); |
| 134 InstallFunctions($Set.prototype, DONT_ENUM, $Array( | 254 InstallFunctions($Set.prototype, DONT_ENUM, $Array( |
| 135 "add", SetAddJS, | 255 "add", SetAdd, |
| 136 "has", SetHasJS, | 256 "has", SetHas, |
| 137 "delete", SetDeleteJS, | 257 "delete", SetDelete, |
| 138 "clear", SetClearJS, | 258 "clear", SetClearJS, |
| 139 "forEach", SetForEach | 259 "forEach", SetForEach |
| 140 )); | 260 )); |
| 141 } | 261 } |
| 142 | 262 |
| 143 SetUpSet(); | 263 SetUpSet(); |
| 144 | 264 |
| 145 | 265 |
| 146 // ------------------------------------------------------------------- | 266 // ------------------------------------------------------------------- |
| 147 // Harmony Map | 267 // Harmony Map |
| (...skipping 14 matching lines...) Expand all Loading... |
| 162 for (var nextItem of iterable) { | 282 for (var nextItem of iterable) { |
| 163 if (!IS_SPEC_OBJECT(nextItem)) { | 283 if (!IS_SPEC_OBJECT(nextItem)) { |
| 164 throw MakeTypeError('iterator_value_not_an_object', [nextItem]); | 284 throw MakeTypeError('iterator_value_not_an_object', [nextItem]); |
| 165 } | 285 } |
| 166 %_CallFunction(this, nextItem[0], nextItem[1], adder); | 286 %_CallFunction(this, nextItem[0], nextItem[1], adder); |
| 167 } | 287 } |
| 168 } | 288 } |
| 169 } | 289 } |
| 170 | 290 |
| 171 | 291 |
| 172 function MapGetJS(key) { | 292 function MapGet(key) { |
| 173 if (!IS_MAP(this)) { | 293 if (!IS_MAP(this)) { |
| 174 throw MakeTypeError('incompatible_method_receiver', | 294 throw MakeTypeError('incompatible_method_receiver', |
| 175 ['Map.prototype.get', this]); | 295 ['Map.prototype.get', this]); |
| 176 } | 296 } |
| 177 return %_MapGet(this, key); | 297 var table = %_JSCollectionGetTable(this); |
| 298 var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX); |
| 299 var hash = GetHash(key); |
| 300 var entry = MapFindEntry(table, numBuckets, key, hash); |
| 301 if (entry === NOT_FOUND) return UNDEFINED; |
| 302 return MAP_VALUE_AT(table, entry, numBuckets); |
| 178 } | 303 } |
| 179 | 304 |
| 180 | 305 |
| 181 function MapSetJS(key, value) { | 306 function MapSet(key, value) { |
| 182 if (!IS_MAP(this)) { | 307 if (!IS_MAP(this)) { |
| 183 throw MakeTypeError('incompatible_method_receiver', | 308 throw MakeTypeError('incompatible_method_receiver', |
| 184 ['Map.prototype.set', this]); | 309 ['Map.prototype.set', this]); |
| 185 } | 310 } |
| 186 // Normalize -0 to +0 as required by the spec. | 311 // Normalize -0 to +0 as required by the spec. |
| 187 // Even though we use SameValueZero as the comparison for the keys we don't | 312 // Even though we use SameValueZero as the comparison for the keys we don't |
| 188 // want to ever store -0 as the key since the key is directly exposed when | 313 // want to ever store -0 as the key since the key is directly exposed when |
| 189 // doing iteration. | 314 // doing iteration. |
| 190 if (key === 0) { | 315 if (IS_NUMBER(key) && key === 0) { |
| 191 key = 0; | 316 key = 0; |
| 192 } | 317 } |
| 193 return %_MapSet(this, key, value); | 318 |
| 319 var table = %_JSCollectionGetTable(this); |
| 320 var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX); |
| 321 var hash = GetHash(key); |
| 322 var entry = MapFindEntry(table, numBuckets, key, hash); |
| 323 if (entry !== NOT_FOUND) { |
| 324 var existingIndex = MAP_ENTRY_TO_INDEX(entry, numBuckets); |
| 325 %_FixedArraySet(table, existingIndex + 1, value); |
| 326 return this; |
| 327 } |
| 328 |
| 329 var nof = %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX); |
| 330 var nod = %_FixedArrayGet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX); |
| 331 var capacity = numBuckets << 1; |
| 332 if ((nof + nod) >= capacity) { |
| 333 // Need to grow, bail out to runtime. |
| 334 %MapGrow(this); |
| 335 // Re-enter...TODO(adamk) Fix this |
| 336 return %_CallFunction(this, key, value, MapSet); |
| 337 } |
| 338 entry = nof + nod; |
| 339 var index = MAP_ENTRY_TO_INDEX(entry, numBuckets); |
| 340 var bucket = HashToBucket(hash, numBuckets); |
| 341 var chainEntry = %_FixedArrayGet(table, HASH_TABLE_START_INDEX + bucket); |
| 342 %_FixedArraySet(table, HASH_TABLE_START_INDEX + bucket, entry | 0); |
| 343 %_FixedArraySet(table, index + MAP_CHAIN_OFFSET, chainEntry | 0); |
| 344 %_FixedArraySet(table, NUMBER_OF_ELEMENTS_INDEX, (nof + 1) | 0); |
| 345 %_FixedArraySet(table, index, key); |
| 346 %_FixedArraySet(table, index + 1, value); |
| 347 return this; |
| 194 } | 348 } |
| 195 | 349 |
| 196 | 350 |
| 197 function MapHasJS(key) { | 351 function MapHas(key) { |
| 198 if (!IS_MAP(this)) { | 352 if (!IS_MAP(this)) { |
| 199 throw MakeTypeError('incompatible_method_receiver', | 353 throw MakeTypeError('incompatible_method_receiver', |
| 200 ['Map.prototype.has', this]); | 354 ['Map.prototype.has', this]); |
| 201 } | 355 } |
| 202 return %_MapHas(this, key); | 356 var table = %_JSCollectionGetTable(this); |
| 357 var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX); |
| 358 var hash = GetHash(key); |
| 359 return MapFindEntry(table, numBuckets, key, hash) !== NOT_FOUND; |
| 203 } | 360 } |
| 204 | 361 |
| 205 | 362 |
| 206 function MapDeleteJS(key) { | 363 function MapDelete(key) { |
| 207 if (!IS_MAP(this)) { | 364 if (!IS_MAP(this)) { |
| 208 throw MakeTypeError('incompatible_method_receiver', | 365 throw MakeTypeError('incompatible_method_receiver', |
| 209 ['Map.prototype.delete', this]); | 366 ['Map.prototype.delete', this]); |
| 210 } | 367 } |
| 211 return %_MapDelete(this, key); | 368 var table = %_JSCollectionGetTable(this); |
| 369 var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX); |
| 370 var hash = GetHash(key); |
| 371 var entry = MapFindEntry(table, numBuckets, key, hash); |
| 372 if (entry === NOT_FOUND) return false; |
| 373 |
| 374 var nof = %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX) - 1; |
| 375 var nod = %_FixedArrayGet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX) + 1; |
| 376 var index = MAP_ENTRY_TO_INDEX(entry, numBuckets); |
| 377 %_FixedArraySet(table, index, %_TheHole()); |
| 378 %_FixedArraySet(table, index + 1, %_TheHole()); |
| 379 %_FixedArraySet(table, NUMBER_OF_ELEMENTS_INDEX, nof | 0); |
| 380 %_FixedArraySet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX, nod | 0); |
| 381 if (nof < (numBuckets >>> 1)) %MapShrink(this); |
| 382 return true; |
| 212 } | 383 } |
| 213 | 384 |
| 214 | 385 |
| 215 function MapGetSizeJS() { | 386 function MapGetSize() { |
| 216 if (!IS_MAP(this)) { | 387 if (!IS_MAP(this)) { |
| 217 throw MakeTypeError('incompatible_method_receiver', | 388 throw MakeTypeError('incompatible_method_receiver', |
| 218 ['Map.prototype.size', this]); | 389 ['Map.prototype.size', this]); |
| 219 } | 390 } |
| 220 return %_MapGetSize(this); | 391 var table = %_JSCollectionGetTable(this); |
| 392 return %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX); |
| 221 } | 393 } |
| 222 | 394 |
| 223 | 395 |
| 224 function MapClearJS() { | 396 function MapClearJS() { |
| 225 if (!IS_MAP(this)) { | 397 if (!IS_MAP(this)) { |
| 226 throw MakeTypeError('incompatible_method_receiver', | 398 throw MakeTypeError('incompatible_method_receiver', |
| 227 ['Map.prototype.clear', this]); | 399 ['Map.prototype.clear', this]); |
| 228 } | 400 } |
| 229 %_MapClear(this); | 401 %_MapClear(this); |
| 230 } | 402 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 | 436 |
| 265 %SetCode($Map, MapConstructor); | 437 %SetCode($Map, MapConstructor); |
| 266 %FunctionSetPrototype($Map, new $Object()); | 438 %FunctionSetPrototype($Map, new $Object()); |
| 267 %AddNamedProperty($Map.prototype, "constructor", $Map, DONT_ENUM); | 439 %AddNamedProperty($Map.prototype, "constructor", $Map, DONT_ENUM); |
| 268 %AddNamedProperty( | 440 %AddNamedProperty( |
| 269 $Map.prototype, symbolToStringTag, "Map", DONT_ENUM | READ_ONLY); | 441 $Map.prototype, symbolToStringTag, "Map", DONT_ENUM | READ_ONLY); |
| 270 | 442 |
| 271 %FunctionSetLength(MapForEach, 1); | 443 %FunctionSetLength(MapForEach, 1); |
| 272 | 444 |
| 273 // Set up the non-enumerable functions on the Map prototype object. | 445 // Set up the non-enumerable functions on the Map prototype object. |
| 274 InstallGetter($Map.prototype, "size", MapGetSizeJS); | 446 InstallGetter($Map.prototype, "size", MapGetSize); |
| 275 InstallFunctions($Map.prototype, DONT_ENUM, $Array( | 447 InstallFunctions($Map.prototype, DONT_ENUM, $Array( |
| 276 "get", MapGetJS, | 448 "get", MapGet, |
| 277 "set", MapSetJS, | 449 "set", MapSet, |
| 278 "has", MapHasJS, | 450 "has", MapHas, |
| 279 "delete", MapDeleteJS, | 451 "delete", MapDelete, |
| 280 "clear", MapClearJS, | 452 "clear", MapClearJS, |
| 281 "forEach", MapForEach | 453 "forEach", MapForEach |
| 282 )); | 454 )); |
| 283 } | 455 } |
| 284 | 456 |
| 285 SetUpMap(); | 457 SetUpMap(); |
| 458 |
| 459 })(); |
| OLD | NEW |