weak-collection.js 4.11 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
(function(global, utils) {
6

7
"use strict";
8

9
%CheckIsBootstrapping();
10

11 12 13
// -------------------------------------------------------------------
// Imports

14
var hashCodeSymbol = utils.ImportNow("hash_code_symbol");
15 16
var GlobalWeakMap = global.WeakMap;
var GlobalWeakSet = global.WeakSet;
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
var MathRandom = global.Math.random;

// -------------------------------------------------------------------

function GetExistingHash(key) {
  if (IS_RECEIVER(key) && !IS_PROXY(key) && !IS_GLOBAL(key)) {
    var hash = GET_PRIVATE(key, hashCodeSymbol);
    return hash;
  }
  return %GenericHash(key);
}
%SetForceInlineFlag(GetExistingHash);


function GetHash(key) {
  var hash = GetExistingHash(key);
  if (IS_UNDEFINED(hash)) {
    hash = (MathRandom() * 0x40000000) | 0;
    if (hash === 0) hash = 1;
    SET_PRIVATE(key, hashCodeSymbol, hash);
  }
  return hash;
}
%SetForceInlineFlag(GetHash);
41

42

43
// -------------------------------------------------------------------
44
// Harmony WeakMap
45

46
function WeakMapConstructor(iterable) {
47
  if (IS_UNDEFINED(new.target)) {
48
    throw %make_type_error(kConstructorNotFunction, "WeakMap");
49
  }
50

51
  %WeakCollectionInitialize(this);
52 53

  if (!IS_NULL_OR_UNDEFINED(iterable)) {
54
    var adder = this.set;
55
    if (!IS_CALLABLE(adder)) {
56
      throw %make_type_error(kPropertyNotFunction, adder, 'set', this);
57
    }
58
    for (var nextItem of iterable) {
59
      if (!IS_RECEIVER(nextItem)) {
60
        throw %make_type_error(kIteratorValueNotAnObject, nextItem);
61
      }
62
      %_Call(adder, this, nextItem[0], nextItem[1]);
63 64
    }
  }
65 66
}

67

68 69 70 71 72 73 74 75 76 77 78 79
// Set up the non-enumerable functions on the WeakMap prototype object.
DEFINE_METHODS(
  GlobalWeakMap.prototype,
  {
    set(key, value) {
      if (!IS_WEAKMAP(this)) {
        throw %make_type_error(kIncompatibleMethodReceiver,
                            'WeakMap.prototype.set', this);
      }
      if (!IS_RECEIVER(key)) throw %make_type_error(kInvalidWeakMapKey);
      return %WeakCollectionSet(this, key, value, GetHash(key));
    }
80

81 82 83 84 85 86 87 88 89 90
    delete(key) {
      if (!IS_WEAKMAP(this)) {
        throw %make_type_error(kIncompatibleMethodReceiver,
                            'WeakMap.prototype.delete', this);
      }
      if (!IS_RECEIVER(key)) return false;
      var hash = GetExistingHash(key);
      if (IS_UNDEFINED(hash)) return false;
      return %WeakCollectionDelete(this, key, hash);
    }
91
  }
92
);
93 94 95

// -------------------------------------------------------------------

96 97
%SetCode(GlobalWeakMap, WeakMapConstructor);
%FunctionSetLength(GlobalWeakMap, 0);
98 99

// -------------------------------------------------------------------
100
// Harmony WeakSet
101

102
function WeakSetConstructor(iterable) {
103
  if (IS_UNDEFINED(new.target)) {
104
    throw %make_type_error(kConstructorNotFunction, "WeakSet");
105
  }
106

107
  %WeakCollectionInitialize(this);
108 109

  if (!IS_NULL_OR_UNDEFINED(iterable)) {
110
    var adder = this.add;
111
    if (!IS_CALLABLE(adder)) {
112
      throw %make_type_error(kPropertyNotFunction, adder, 'add', this);
113
    }
114
    for (var value of iterable) {
115
      %_Call(adder, this, value);
116 117
    }
  }
118 119
}

120

121 122 123 124 125 126 127 128 129 130 131 132
// Set up the non-enumerable functions on the WeakSet prototype object.
DEFINE_METHODS(
  GlobalWeakSet.prototype,
  {
    add(value) {
      if (!IS_WEAKSET(this)) {
        throw %make_type_error(kIncompatibleMethodReceiver,
                            'WeakSet.prototype.add', this);
      }
      if (!IS_RECEIVER(value)) throw %make_type_error(kInvalidWeakSetValue);
      return %WeakCollectionSet(this, value, true, GetHash(value));
    }
133

134 135 136 137 138 139 140 141 142 143
    delete(value) {
      if (!IS_WEAKSET(this)) {
        throw %make_type_error(kIncompatibleMethodReceiver,
                            'WeakSet.prototype.delete', this);
      }
      if (!IS_RECEIVER(value)) return false;
      var hash = GetExistingHash(value);
      if (IS_UNDEFINED(hash)) return false;
      return %WeakCollectionDelete(this, value, hash);
    }
144
  }
145
);
146

147 148
// -------------------------------------------------------------------

149 150 151
%SetCode(GlobalWeakSet, WeakSetConstructor);
%FunctionSetLength(GlobalWeakSet, 0);

152
})