Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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 | (function(global, utils) { |
| 6 | |
| 7 | "use strict"; |
| 8 | |
| 9 | %CheckIsBootstrapping(); |
| 10 | |
| 11 | // ------------------------------------------------------------------- |
| 12 | // Imports |
| 13 | |
| 14 | var GetExistingHash; |
| 15 | var GetHash; |
| 16 | var GlobalObject = global.Object; |
| 17 | var GlobalWeakMap = global.WeakMap; |
| 18 | var GlobalWeakSet = global.WeakSet; |
| 19 | var MakeTypeError; |
| 20 | var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); |
| 21 | |
| 22 | utils.Import(function(from) { |
| 23 | GetExistingHash = from.GetExistingHash; |
| 24 | GetHash = from.GetHash; |
| 25 | MakeTypeError = from.MakeTypeError; |
| 26 | }); |
| 27 | |
| 28 | // ------------------------------------------------------------------- |
| 29 | // Harmony WeakMap |
| 30 | |
| 31 | function WeakMapConstructor(iterable) { |
| 32 | if (IS_UNDEFINED(new.target)) { |
| 33 | throw MakeTypeError(kConstructorNotFunction, "WeakMap"); |
| 34 | } |
| 35 | |
| 36 | %WeakCollectionInitialize(this); |
| 37 | |
| 38 | if (!IS_NULL_OR_UNDEFINED(iterable)) { |
| 39 | var adder = this.set; |
| 40 | if (!IS_CALLABLE(adder)) { |
| 41 | throw MakeTypeError(kPropertyNotFunction, adder, 'set', this); |
| 42 | } |
| 43 | for (var nextItem of iterable) { |
| 44 | if (!IS_RECEIVER(nextItem)) { |
| 45 | throw MakeTypeError(kIteratorValueNotAnObject, nextItem); |
| 46 | } |
| 47 | %_Call(adder, this, nextItem[0], nextItem[1]); |
| 48 | } |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | |
| 53 | function WeakMapGet(key) { |
| 54 | if (!IS_WEAKMAP(this)) { |
| 55 | throw MakeTypeError(kIncompatibleMethodReceiver, |
| 56 | 'WeakMap.prototype.get', this); |
| 57 | } |
| 58 | if (!IS_RECEIVER(key)) return UNDEFINED; |
| 59 | var hash = GetExistingHash(key); |
| 60 | if (IS_UNDEFINED(hash)) return UNDEFINED; |
| 61 | return %WeakCollectionGet(this, key, hash); |
| 62 | } |
| 63 | |
| 64 | |
| 65 | function WeakMapSet(key, value) { |
| 66 | if (!IS_WEAKMAP(this)) { |
| 67 | throw MakeTypeError(kIncompatibleMethodReceiver, |
| 68 | 'WeakMap.prototype.set', this); |
| 69 | } |
| 70 | if (!IS_RECEIVER(key)) throw MakeTypeError(kInvalidWeakMapKey); |
| 71 | return %WeakCollectionSet(this, key, value, GetHash(key)); |
| 72 | } |
| 73 | |
| 74 | |
| 75 | function WeakMapHas(key) { |
| 76 | if (!IS_WEAKMAP(this)) { |
| 77 | throw MakeTypeError(kIncompatibleMethodReceiver, |
| 78 | 'WeakMap.prototype.has', this); |
| 79 | } |
| 80 | if (!IS_RECEIVER(key)) return false; |
| 81 | var hash = GetExistingHash(key); |
| 82 | if (IS_UNDEFINED(hash)) return false; |
| 83 | return %WeakCollectionHas(this, key, hash); |
| 84 | } |
| 85 | |
| 86 | |
| 87 | function WeakMapDelete(key) { |
| 88 | if (!IS_WEAKMAP(this)) { |
| 89 | throw MakeTypeError(kIncompatibleMethodReceiver, |
| 90 | 'WeakMap.prototype.delete', this); |
| 91 | } |
| 92 | if (!IS_RECEIVER(key)) return false; |
| 93 | var hash = GetExistingHash(key); |
| 94 | if (IS_UNDEFINED(hash)) return false; |
| 95 | return %WeakCollectionDelete(this, key, hash); |
| 96 | } |
| 97 | |
| 98 | |
| 99 | // ------------------------------------------------------------------- |
| 100 | |
| 101 | %SetCode(GlobalWeakMap, WeakMapConstructor); |
| 102 | %FunctionSetLength(GlobalWeakMap, 0); |
| 103 | %FunctionSetPrototype(GlobalWeakMap, new GlobalObject()); |
| 104 | %AddNamedProperty(GlobalWeakMap.prototype, "constructor", GlobalWeakMap, |
| 105 | DONT_ENUM); |
| 106 | %AddNamedProperty(GlobalWeakMap.prototype, toStringTagSymbol, "WeakMap", |
| 107 | DONT_ENUM | READ_ONLY); |
| 108 | |
| 109 | // Set up the non-enumerable functions on the WeakMap prototype object. |
| 110 | utils.InstallFunctions(GlobalWeakMap.prototype, DONT_ENUM, [ |
| 111 | "get", WeakMapGet, |
| 112 | "set", WeakMapSet, |
| 113 | "has", WeakMapHas, |
| 114 | "delete", WeakMapDelete |
| 115 | ]); |
| 116 | |
| 117 | // ------------------------------------------------------------------- |
| 118 | // Harmony WeakSet |
| 119 | |
| 120 | function WeakSetConstructor(iterable) { |
| 121 | if (IS_UNDEFINED(new.target)) { |
| 122 | throw MakeTypeError(kConstructorNotFunction, "WeakSet"); |
| 123 | } |
| 124 | |
| 125 | %WeakCollectionInitialize(this); |
| 126 | |
| 127 | if (!IS_NULL_OR_UNDEFINED(iterable)) { |
| 128 | var adder = this.add; |
| 129 | if (!IS_CALLABLE(adder)) { |
| 130 | throw MakeTypeError(kPropertyNotFunction, adder, 'add', this); |
| 131 | } |
| 132 | for (var value of iterable) { |
| 133 | %_Call(adder, this, value); |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | |
| 139 | function WeakSetAdd(value) { |
| 140 | if (!IS_WEAKSET(this)) { |
| 141 | throw MakeTypeError(kIncompatibleMethodReceiver, |
| 142 | 'WeakSet.prototype.add', this); |
| 143 | } |
| 144 | if (!IS_RECEIVER(value)) throw MakeTypeError(kInvalidWeakSetValue); |
| 145 | return %WeakCollectionSet(this, value, true, GetHash(value)); |
| 146 | } |
| 147 | |
| 148 | |
| 149 | function WeakSetHas(value) { |
| 150 | if (!IS_WEAKSET(this)) { |
| 151 | throw MakeTypeError(kIncompatibleMethodReceiver, |
| 152 | 'WeakSet.prototype.has', this); |
| 153 | } |
| 154 | if (!IS_RECEIVER(value)) return false; |
| 155 | var hash = GetExistingHash(value); |
| 156 | if (IS_UNDEFINED(hash)) return false; |
| 157 | return %WeakCollectionHas(this, value, hash); |
| 158 | } |
| 159 | |
| 160 | |
| 161 | function WeakSetDelete(value) { |
| 162 | if (!IS_WEAKSET(this)) { |
| 163 | throw MakeTypeError(kIncompatibleMethodReceiver, |
| 164 | 'WeakSet.prototype.delete', this); |
| 165 | } |
| 166 | if (!IS_RECEIVER(value)) return false; |
| 167 | var hash = GetExistingHash(value); |
| 168 | if (IS_UNDEFINED(hash)) return false; |
| 169 | return %WeakCollectionDelete(this, value, hash); |
| 170 | } |
| 171 | |
| 172 | |
| 173 | // ------------------------------------------------------------------- |
| 174 | |
| 175 | %SetCode(GlobalWeakSet, WeakSetConstructor); |
| 176 | %FunctionSetLength(GlobalWeakSet, 0); |
| 177 | %FunctionSetPrototype(GlobalWeakSet, new GlobalObject()); |
| 178 | %AddNamedProperty(GlobalWeakSet.prototype, "constructor", GlobalWeakSet, |
| 179 | DONT_ENUM); |
| 180 | %AddNamedProperty(GlobalWeakSet.prototype, toStringTagSymbol, "WeakSet", |
| 181 | DONT_ENUM | READ_ONLY); |
| 182 | |
| 183 | // Set up the non-enumerable functions on the WeakSet prototype object. |
| 184 | utils.InstallFunctions(GlobalWeakSet.prototype, DONT_ENUM, [ |
| 185 | "add", WeakSetAdd, |
| 186 | "has", WeakSetHas, |
| 187 | "delete", WeakSetDelete |
| 188 | ]); |
| 189 | |
| 190 | }) |