~webapps/unity-js-scopes/node.js

« back to all changes in this revision

Viewing changes to deps/v8/src/collection.js

  • Committer: Marcus Tomlinson
  • Date: 2015-11-13 07:59:04 UTC
  • Revision ID: marcus.tomlinson@canonical.com-20151113075904-h0swczmoq1rvstfc
Node v4 (stable)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
3
// found in the LICENSE file.
 
4
 
 
5
var $getHash;
 
6
var $getExistingHash;
 
7
var $mapSet;
 
8
var $mapHas;
 
9
var $mapDelete;
 
10
var $setAdd;
 
11
var $setHas;
 
12
var $setDelete;
 
13
var $mapFromArray;
 
14
var $setFromArray;
 
15
 
 
16
(function(global, utils) {
 
17
"use strict";
 
18
 
 
19
%CheckIsBootstrapping();
 
20
 
 
21
// -------------------------------------------------------------------
 
22
// Imports
 
23
 
 
24
var GlobalMap = global.Map;
 
25
var GlobalObject = global.Object;
 
26
var GlobalSet = global.Set;
 
27
var IntRandom;
 
28
 
 
29
utils.Import(function(from) {
 
30
  IntRandom = from.IntRandom;
 
31
});
 
32
 
 
33
var NumberIsNaN;
 
34
 
 
35
utils.Import(function(from) {
 
36
  NumberIsNaN = from.NumberIsNaN;
 
37
});
 
38
 
 
39
// -------------------------------------------------------------------
 
40
 
 
41
function HashToEntry(table, hash, numBuckets) {
 
42
  var bucket = ORDERED_HASH_TABLE_HASH_TO_BUCKET(hash, numBuckets);
 
43
  return ORDERED_HASH_TABLE_BUCKET_AT(table, bucket);
 
44
}
 
45
%SetForceInlineFlag(HashToEntry);
 
46
 
 
47
 
 
48
function SetFindEntry(table, numBuckets, key, hash) {
 
49
  var entry = HashToEntry(table, hash, numBuckets);
 
50
  if (entry === NOT_FOUND) return entry;
 
51
  var candidate = ORDERED_HASH_SET_KEY_AT(table, entry, numBuckets);
 
52
  if (key === candidate) return entry;
 
53
  var keyIsNaN = NumberIsNaN(key);
 
54
  while (true) {
 
55
    if (keyIsNaN && NumberIsNaN(candidate)) {
 
56
      return entry;
 
57
    }
 
58
    entry = ORDERED_HASH_SET_CHAIN_AT(table, entry, numBuckets);
 
59
    if (entry === NOT_FOUND) return entry;
 
60
    candidate = ORDERED_HASH_SET_KEY_AT(table, entry, numBuckets);
 
61
    if (key === candidate) return entry;
 
62
  }
 
63
  return NOT_FOUND;
 
64
}
 
65
%SetForceInlineFlag(SetFindEntry);
 
66
 
 
67
 
 
68
function MapFindEntry(table, numBuckets, key, hash) {
 
69
  var entry = HashToEntry(table, hash, numBuckets);
 
70
  if (entry === NOT_FOUND) return entry;
 
71
  var candidate = ORDERED_HASH_MAP_KEY_AT(table, entry, numBuckets);
 
72
  if (key === candidate) return entry;
 
73
  var keyIsNaN = NumberIsNaN(key);
 
74
  while (true) {
 
75
    if (keyIsNaN && NumberIsNaN(candidate)) {
 
76
      return entry;
 
77
    }
 
78
    entry = ORDERED_HASH_MAP_CHAIN_AT(table, entry, numBuckets);
 
79
    if (entry === NOT_FOUND) return entry;
 
80
    candidate = ORDERED_HASH_MAP_KEY_AT(table, entry, numBuckets);
 
81
    if (key === candidate) return entry;
 
82
  }
 
83
  return NOT_FOUND;
 
84
}
 
85
%SetForceInlineFlag(MapFindEntry);
 
86
 
 
87
 
 
88
function ComputeIntegerHash(key, seed) {
 
89
  var hash = key;
 
90
  hash = hash ^ seed;
 
91
  hash = ~hash + (hash << 15);  // hash = (hash << 15) - hash - 1;
 
92
  hash = hash ^ (hash >>> 12);
 
93
  hash = hash + (hash << 2);
 
94
  hash = hash ^ (hash >>> 4);
 
95
  hash = (hash * 2057) | 0;  // hash = (hash + (hash << 3)) + (hash << 11);
 
96
  hash = hash ^ (hash >>> 16);
 
97
  return hash & 0x3fffffff;
 
98
}
 
99
%SetForceInlineFlag(ComputeIntegerHash);
 
100
 
 
101
var hashCodeSymbol = GLOBAL_PRIVATE("hash_code_symbol");
 
102
 
 
103
function GetExistingHash(key) {
 
104
  if (%_IsSmi(key)) {
 
105
    return ComputeIntegerHash(key, 0);
 
106
  }
 
107
  if (IS_STRING(key)) {
 
108
    var field = %_StringGetRawHashField(key);
 
109
    if ((field & 1 /* Name::kHashNotComputedMask */) === 0) {
 
110
      return field >>> 2 /* Name::kHashShift */;
 
111
    }
 
112
  } else if (IS_SPEC_OBJECT(key) && !%_IsJSProxy(key) && !IS_GLOBAL(key)) {
 
113
    var hash = GET_PRIVATE(key, hashCodeSymbol);
 
114
    return hash;
 
115
  }
 
116
  return %GenericHash(key);
 
117
}
 
118
%SetForceInlineFlag(GetExistingHash);
 
119
 
 
120
 
 
121
function GetHash(key) {
 
122
  var hash = GetExistingHash(key);
 
123
  if (IS_UNDEFINED(hash)) {
 
124
    hash = IntRandom() | 0;
 
125
    if (hash === 0) hash = 1;
 
126
    SET_PRIVATE(key, hashCodeSymbol, hash);
 
127
  }
 
128
  return hash;
 
129
}
 
130
%SetForceInlineFlag(GetHash);
 
131
 
 
132
 
 
133
// -------------------------------------------------------------------
 
134
// Harmony Set
 
135
 
 
136
function SetConstructor(iterable) {
 
137
  if (!%_IsConstructCall()) {
 
138
    throw MakeTypeError(kConstructorNotFunction, "Set");
 
139
  }
 
140
 
 
141
  %_SetInitialize(this);
 
142
 
 
143
  if (!IS_NULL_OR_UNDEFINED(iterable)) {
 
144
    var adder = this.add;
 
145
    if (!IS_SPEC_FUNCTION(adder)) {
 
146
      throw MakeTypeError(kPropertyNotFunction, 'add', this);
 
147
    }
 
148
 
 
149
    for (var value of iterable) {
 
150
      %_CallFunction(this, value, adder);
 
151
    }
 
152
  }
 
153
}
 
154
 
 
155
 
 
156
function SetAdd(key) {
 
157
  if (!IS_SET(this)) {
 
158
    throw MakeTypeError(kIncompatibleMethodReceiver, 'Set.prototype.add', this);
 
159
  }
 
160
  // Normalize -0 to +0 as required by the spec.
 
161
  // Even though we use SameValueZero as the comparison for the keys we don't
 
162
  // want to ever store -0 as the key since the key is directly exposed when
 
163
  // doing iteration.
 
164
  if (key === 0) {
 
165
    key = 0;
 
166
  }
 
167
  var table = %_JSCollectionGetTable(this);
 
168
  var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
169
  var hash = GetHash(key);
 
170
  if (SetFindEntry(table, numBuckets, key, hash) !== NOT_FOUND) return this;
 
171
 
 
172
  var nof = ORDERED_HASH_TABLE_ELEMENT_COUNT(table);
 
173
  var nod = ORDERED_HASH_TABLE_DELETED_COUNT(table);
 
174
  var capacity = numBuckets << 1;
 
175
  if ((nof + nod) >= capacity) {
 
176
    // Need to grow, bail out to runtime.
 
177
    %SetGrow(this);
 
178
    // Re-load state from the grown backing store.
 
179
    table = %_JSCollectionGetTable(this);
 
180
    numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
181
    nof = ORDERED_HASH_TABLE_ELEMENT_COUNT(table);
 
182
    nod = ORDERED_HASH_TABLE_DELETED_COUNT(table);
 
183
  }
 
184
  var entry = nof + nod;
 
185
  var index = ORDERED_HASH_SET_ENTRY_TO_INDEX(entry, numBuckets);
 
186
  var bucket = ORDERED_HASH_TABLE_HASH_TO_BUCKET(hash, numBuckets);
 
187
  var chainEntry = ORDERED_HASH_TABLE_BUCKET_AT(table, bucket);
 
188
  ORDERED_HASH_TABLE_SET_BUCKET_AT(table, bucket, entry);
 
189
  ORDERED_HASH_TABLE_SET_ELEMENT_COUNT(table, nof + 1);
 
190
  FIXED_ARRAY_SET(table, index, key);
 
191
  FIXED_ARRAY_SET_SMI(table, index + 1, chainEntry);
 
192
  return this;
 
193
}
 
194
 
 
195
 
 
196
function SetHas(key) {
 
197
  if (!IS_SET(this)) {
 
198
    throw MakeTypeError(kIncompatibleMethodReceiver, 'Set.prototype.has', this);
 
199
  }
 
200
  var table = %_JSCollectionGetTable(this);
 
201
  var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
202
  var hash = GetExistingHash(key);
 
203
  if (IS_UNDEFINED(hash)) return false;
 
204
  return SetFindEntry(table, numBuckets, key, hash) !== NOT_FOUND;
 
205
}
 
206
 
 
207
 
 
208
function SetDelete(key) {
 
209
  if (!IS_SET(this)) {
 
210
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
211
                        'Set.prototype.delete', this);
 
212
  }
 
213
  var table = %_JSCollectionGetTable(this);
 
214
  var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
215
  var hash = GetExistingHash(key);
 
216
  if (IS_UNDEFINED(hash)) return false;
 
217
  var entry = SetFindEntry(table, numBuckets, key, hash);
 
218
  if (entry === NOT_FOUND) return false;
 
219
 
 
220
  var nof = ORDERED_HASH_TABLE_ELEMENT_COUNT(table) - 1;
 
221
  var nod = ORDERED_HASH_TABLE_DELETED_COUNT(table) + 1;
 
222
  var index = ORDERED_HASH_SET_ENTRY_TO_INDEX(entry, numBuckets);
 
223
  FIXED_ARRAY_SET(table, index, %_TheHole());
 
224
  ORDERED_HASH_TABLE_SET_ELEMENT_COUNT(table, nof);
 
225
  ORDERED_HASH_TABLE_SET_DELETED_COUNT(table, nod);
 
226
  if (nof < (numBuckets >>> 1)) %SetShrink(this);
 
227
  return true;
 
228
}
 
229
 
 
230
 
 
231
function SetGetSize() {
 
232
  if (!IS_SET(this)) {
 
233
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
234
                        'Set.prototype.size', this);
 
235
  }
 
236
  var table = %_JSCollectionGetTable(this);
 
237
  return ORDERED_HASH_TABLE_ELEMENT_COUNT(table);
 
238
}
 
239
 
 
240
 
 
241
function SetClearJS() {
 
242
  if (!IS_SET(this)) {
 
243
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
244
                        'Set.prototype.clear', this);
 
245
  }
 
246
  %_SetClear(this);
 
247
}
 
248
 
 
249
 
 
250
function SetForEach(f, receiver) {
 
251
  if (!IS_SET(this)) {
 
252
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
253
                        'Set.prototype.forEach', this);
 
254
  }
 
255
 
 
256
  if (!IS_SPEC_FUNCTION(f)) throw MakeTypeError(kCalledNonCallable, f);
 
257
  var needs_wrapper = false;
 
258
  if (IS_NULL(receiver)) {
 
259
    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
 
260
  } else if (!IS_UNDEFINED(receiver)) {
 
261
    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
 
262
  }
 
263
 
 
264
  var iterator = new SetIterator(this, ITERATOR_KIND_VALUES);
 
265
  var key;
 
266
  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
 
267
  var value_array = [UNDEFINED];
 
268
  while (%SetIteratorNext(iterator, value_array)) {
 
269
    if (stepping) %DebugPrepareStepInIfStepping(f);
 
270
    key = value_array[0];
 
271
    var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
 
272
    %_CallFunction(new_receiver, key, key, this, f);
 
273
  }
 
274
}
 
275
 
 
276
// -------------------------------------------------------------------
 
277
 
 
278
%SetCode(GlobalSet, SetConstructor);
 
279
%FunctionSetLength(GlobalSet, 0);
 
280
%FunctionSetPrototype(GlobalSet, new GlobalObject());
 
281
%AddNamedProperty(GlobalSet.prototype, "constructor", GlobalSet, DONT_ENUM);
 
282
%AddNamedProperty(GlobalSet.prototype, symbolToStringTag, "Set",
 
283
                  DONT_ENUM | READ_ONLY);
 
284
 
 
285
%FunctionSetLength(SetForEach, 1);
 
286
 
 
287
// Set up the non-enumerable functions on the Set prototype object.
 
288
utils.InstallGetter(GlobalSet.prototype, "size", SetGetSize);
 
289
utils.InstallFunctions(GlobalSet.prototype, DONT_ENUM, [
 
290
  "add", SetAdd,
 
291
  "has", SetHas,
 
292
  "delete", SetDelete,
 
293
  "clear", SetClearJS,
 
294
  "forEach", SetForEach
 
295
]);
 
296
 
 
297
 
 
298
// -------------------------------------------------------------------
 
299
// Harmony Map
 
300
 
 
301
function MapConstructor(iterable) {
 
302
  if (!%_IsConstructCall()) {
 
303
    throw MakeTypeError(kConstructorNotFunction, "Map");
 
304
  }
 
305
 
 
306
  %_MapInitialize(this);
 
307
 
 
308
  if (!IS_NULL_OR_UNDEFINED(iterable)) {
 
309
    var adder = this.set;
 
310
    if (!IS_SPEC_FUNCTION(adder)) {
 
311
      throw MakeTypeError(kPropertyNotFunction, 'set', this);
 
312
    }
 
313
 
 
314
    for (var nextItem of iterable) {
 
315
      if (!IS_SPEC_OBJECT(nextItem)) {
 
316
        throw MakeTypeError(kIteratorValueNotAnObject, nextItem);
 
317
      }
 
318
      %_CallFunction(this, nextItem[0], nextItem[1], adder);
 
319
    }
 
320
  }
 
321
}
 
322
 
 
323
 
 
324
function MapGet(key) {
 
325
  if (!IS_MAP(this)) {
 
326
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
327
                        'Map.prototype.get', this);
 
328
  }
 
329
  var table = %_JSCollectionGetTable(this);
 
330
  var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
331
  var hash = GetExistingHash(key);
 
332
  if (IS_UNDEFINED(hash)) return UNDEFINED;
 
333
  var entry = MapFindEntry(table, numBuckets, key, hash);
 
334
  if (entry === NOT_FOUND) return UNDEFINED;
 
335
  return ORDERED_HASH_MAP_VALUE_AT(table, entry, numBuckets);
 
336
}
 
337
 
 
338
 
 
339
function MapSet(key, value) {
 
340
  if (!IS_MAP(this)) {
 
341
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
342
                        'Map.prototype.set', this);
 
343
  }
 
344
  // Normalize -0 to +0 as required by the spec.
 
345
  // Even though we use SameValueZero as the comparison for the keys we don't
 
346
  // want to ever store -0 as the key since the key is directly exposed when
 
347
  // doing iteration.
 
348
  if (key === 0) {
 
349
    key = 0;
 
350
  }
 
351
 
 
352
  var table = %_JSCollectionGetTable(this);
 
353
  var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
354
  var hash = GetHash(key);
 
355
  var entry = MapFindEntry(table, numBuckets, key, hash);
 
356
  if (entry !== NOT_FOUND) {
 
357
    var existingIndex = ORDERED_HASH_MAP_ENTRY_TO_INDEX(entry, numBuckets);
 
358
    FIXED_ARRAY_SET(table, existingIndex + 1, value);
 
359
    return this;
 
360
  }
 
361
 
 
362
  var nof = ORDERED_HASH_TABLE_ELEMENT_COUNT(table);
 
363
  var nod = ORDERED_HASH_TABLE_DELETED_COUNT(table);
 
364
  var capacity = numBuckets << 1;
 
365
  if ((nof + nod) >= capacity) {
 
366
    // Need to grow, bail out to runtime.
 
367
    %MapGrow(this);
 
368
    // Re-load state from the grown backing store.
 
369
    table = %_JSCollectionGetTable(this);
 
370
    numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
371
    nof = ORDERED_HASH_TABLE_ELEMENT_COUNT(table);
 
372
    nod = ORDERED_HASH_TABLE_DELETED_COUNT(table);
 
373
  }
 
374
  entry = nof + nod;
 
375
  var index = ORDERED_HASH_MAP_ENTRY_TO_INDEX(entry, numBuckets);
 
376
  var bucket = ORDERED_HASH_TABLE_HASH_TO_BUCKET(hash, numBuckets);
 
377
  var chainEntry = ORDERED_HASH_TABLE_BUCKET_AT(table, bucket);
 
378
  ORDERED_HASH_TABLE_SET_BUCKET_AT(table, bucket, entry);
 
379
  ORDERED_HASH_TABLE_SET_ELEMENT_COUNT(table, nof + 1);
 
380
  FIXED_ARRAY_SET(table, index, key);
 
381
  FIXED_ARRAY_SET(table, index + 1, value);
 
382
  FIXED_ARRAY_SET(table, index + 2, chainEntry);
 
383
  return this;
 
384
}
 
385
 
 
386
 
 
387
function MapHas(key) {
 
388
  if (!IS_MAP(this)) {
 
389
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
390
                        'Map.prototype.has', this);
 
391
  }
 
392
  var table = %_JSCollectionGetTable(this);
 
393
  var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
394
  var hash = GetHash(key);
 
395
  return MapFindEntry(table, numBuckets, key, hash) !== NOT_FOUND;
 
396
}
 
397
 
 
398
 
 
399
function MapDelete(key) {
 
400
  if (!IS_MAP(this)) {
 
401
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
402
                        'Map.prototype.delete', this);
 
403
  }
 
404
  var table = %_JSCollectionGetTable(this);
 
405
  var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
 
406
  var hash = GetHash(key);
 
407
  var entry = MapFindEntry(table, numBuckets, key, hash);
 
408
  if (entry === NOT_FOUND) return false;
 
409
 
 
410
  var nof = ORDERED_HASH_TABLE_ELEMENT_COUNT(table) - 1;
 
411
  var nod = ORDERED_HASH_TABLE_DELETED_COUNT(table) + 1;
 
412
  var index = ORDERED_HASH_MAP_ENTRY_TO_INDEX(entry, numBuckets);
 
413
  FIXED_ARRAY_SET(table, index, %_TheHole());
 
414
  FIXED_ARRAY_SET(table, index + 1, %_TheHole());
 
415
  ORDERED_HASH_TABLE_SET_ELEMENT_COUNT(table, nof);
 
416
  ORDERED_HASH_TABLE_SET_DELETED_COUNT(table, nod);
 
417
  if (nof < (numBuckets >>> 1)) %MapShrink(this);
 
418
  return true;
 
419
}
 
420
 
 
421
 
 
422
function MapGetSize() {
 
423
  if (!IS_MAP(this)) {
 
424
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
425
                        'Map.prototype.size', this);
 
426
  }
 
427
  var table = %_JSCollectionGetTable(this);
 
428
  return ORDERED_HASH_TABLE_ELEMENT_COUNT(table);
 
429
}
 
430
 
 
431
 
 
432
function MapClearJS() {
 
433
  if (!IS_MAP(this)) {
 
434
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
435
                        'Map.prototype.clear', this);
 
436
  }
 
437
  %_MapClear(this);
 
438
}
 
439
 
 
440
 
 
441
function MapForEach(f, receiver) {
 
442
  if (!IS_MAP(this)) {
 
443
    throw MakeTypeError(kIncompatibleMethodReceiver,
 
444
                        'Map.prototype.forEach', this);
 
445
  }
 
446
 
 
447
  if (!IS_SPEC_FUNCTION(f)) throw MakeTypeError(kCalledNonCallable, f);
 
448
  var needs_wrapper = false;
 
449
  if (IS_NULL(receiver)) {
 
450
    if (%IsSloppyModeFunction(f)) receiver = UNDEFINED;
 
451
  } else if (!IS_UNDEFINED(receiver)) {
 
452
    needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
 
453
  }
 
454
 
 
455
  var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES);
 
456
  var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
 
457
  var value_array = [UNDEFINED, UNDEFINED];
 
458
  while (%MapIteratorNext(iterator, value_array)) {
 
459
    if (stepping) %DebugPrepareStepInIfStepping(f);
 
460
    var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
 
461
    %_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
 
462
  }
 
463
}
 
464
 
 
465
// -------------------------------------------------------------------
 
466
 
 
467
%SetCode(GlobalMap, MapConstructor);
 
468
%FunctionSetLength(GlobalMap, 0);
 
469
%FunctionSetPrototype(GlobalMap, new GlobalObject());
 
470
%AddNamedProperty(GlobalMap.prototype, "constructor", GlobalMap, DONT_ENUM);
 
471
%AddNamedProperty(
 
472
    GlobalMap.prototype, symbolToStringTag, "Map", DONT_ENUM | READ_ONLY);
 
473
 
 
474
%FunctionSetLength(MapForEach, 1);
 
475
 
 
476
// Set up the non-enumerable functions on the Map prototype object.
 
477
utils.InstallGetter(GlobalMap.prototype, "size", MapGetSize);
 
478
utils.InstallFunctions(GlobalMap.prototype, DONT_ENUM, [
 
479
  "get", MapGet,
 
480
  "set", MapSet,
 
481
  "has", MapHas,
 
482
  "delete", MapDelete,
 
483
  "clear", MapClearJS,
 
484
  "forEach", MapForEach
 
485
]);
 
486
 
 
487
// Expose to the global scope.
 
488
$getHash = GetHash;
 
489
$getExistingHash = GetExistingHash;
 
490
$mapGet = MapGet;
 
491
$mapSet = MapSet;
 
492
$mapHas = MapHas;
 
493
$mapDelete = MapDelete;
 
494
$setAdd = SetAdd;
 
495
$setHas = SetHas;
 
496
$setDelete = SetDelete;
 
497
 
 
498
$mapFromArray = function(array) {
 
499
  var map = new GlobalMap;
 
500
  var length = array.length;
 
501
  for (var i = 0; i < length; i += 2) {
 
502
    var key = array[i];
 
503
    var value = array[i + 1];
 
504
    %_CallFunction(map, key, value, MapSet);
 
505
  }
 
506
  return map;
 
507
};
 
508
 
 
509
$setFromArray = function(array) {
 
510
  var set = new GlobalSet;
 
511
  var length = array.length;
 
512
  for (var i = 0; i < length; ++i) {
 
513
    %_CallFunction(set, array[i], SetAdd);
 
514
  }
 
515
  return set;
 
516
};
 
517
 
 
518
})