1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 "use strict"; 29 30 var $Set = global.Set; 31 var $Map = global.Map; 32 var $WeakMap = global.WeakMap; 33 34 //------------------------------------------------------------------- 35 36 // Global sentinel to be used instead of undefined keys, which are not 37 // supported internally but required for Harmony sets and maps. 38 var undefined_sentinel = {}; 39 40 41 function SetConstructor() { 42 if (%_IsConstructCall()) { 43 %SetInitialize(this); 44 } else { 45 return new $Set(); 46 } 47 } 48 49 50 function SetAdd(key) { 51 if (!IS_SET(this)) { 52 throw MakeTypeError('incompatible_method_receiver', 53 ['Set.prototype.add', this]); 54 } 55 if (IS_UNDEFINED(key)) { 56 key = undefined_sentinel; 57 } 58 return %SetAdd(this, key); 59 } 60 61 62 function SetHas(key) { 63 if (!IS_SET(this)) { 64 throw MakeTypeError('incompatible_method_receiver', 65 ['Set.prototype.has', this]); 66 } 67 if (IS_UNDEFINED(key)) { 68 key = undefined_sentinel; 69 } 70 return %SetHas(this, key); 71 } 72 73 74 function SetDelete(key) { 75 if (!IS_SET(this)) { 76 throw MakeTypeError('incompatible_method_receiver', 77 ['Set.prototype.delete', this]); 78 } 79 if (IS_UNDEFINED(key)) { 80 key = undefined_sentinel; 81 } 82 return %SetDelete(this, key); 83 } 84 85 86 function MapConstructor() { 87 if (%_IsConstructCall()) { 88 %MapInitialize(this); 89 } else { 90 return new $Map(); 91 } 92 } 93 94 95 function MapGet(key) { 96 if (!IS_MAP(this)) { 97 throw MakeTypeError('incompatible_method_receiver', 98 ['Map.prototype.get', this]); 99 } 100 if (IS_UNDEFINED(key)) { 101 key = undefined_sentinel; 102 } 103 return %MapGet(this, key); 104 } 105 106 107 function MapSet(key, value) { 108 if (!IS_MAP(this)) { 109 throw MakeTypeError('incompatible_method_receiver', 110 ['Map.prototype.set', this]); 111 } 112 if (IS_UNDEFINED(key)) { 113 key = undefined_sentinel; 114 } 115 return %MapSet(this, key, value); 116 } 117 118 119 function MapHas(key) { 120 if (!IS_MAP(this)) { 121 throw MakeTypeError('incompatible_method_receiver', 122 ['Map.prototype.has', this]); 123 } 124 if (IS_UNDEFINED(key)) { 125 key = undefined_sentinel; 126 } 127 return !IS_UNDEFINED(%MapGet(this, key)); 128 } 129 130 131 function MapDelete(key) { 132 if (!IS_MAP(this)) { 133 throw MakeTypeError('incompatible_method_receiver', 134 ['Map.prototype.delete', this]); 135 } 136 if (IS_UNDEFINED(key)) { 137 key = undefined_sentinel; 138 } 139 if (!IS_UNDEFINED(%MapGet(this, key))) { 140 %MapSet(this, key, void 0); 141 return true; 142 } else { 143 return false; 144 } 145 } 146 147 148 function WeakMapConstructor() { 149 if (%_IsConstructCall()) { 150 %WeakMapInitialize(this); 151 } else { 152 return new $WeakMap(); 153 } 154 } 155 156 157 function WeakMapGet(key) { 158 if (!IS_WEAKMAP(this)) { 159 throw MakeTypeError('incompatible_method_receiver', 160 ['WeakMap.prototype.get', this]); 161 } 162 if (!IS_SPEC_OBJECT(key)) { 163 throw %MakeTypeError('invalid_weakmap_key', [this, key]); 164 } 165 return %WeakMapGet(this, key); 166 } 167 168 169 function WeakMapSet(key, value) { 170 if (!IS_WEAKMAP(this)) { 171 throw MakeTypeError('incompatible_method_receiver', 172 ['WeakMap.prototype.set', this]); 173 } 174 if (!IS_SPEC_OBJECT(key)) { 175 throw %MakeTypeError('invalid_weakmap_key', [this, key]); 176 } 177 return %WeakMapSet(this, key, value); 178 } 179 180 181 function WeakMapHas(key) { 182 if (!IS_WEAKMAP(this)) { 183 throw MakeTypeError('incompatible_method_receiver', 184 ['WeakMap.prototype.has', this]); 185 } 186 if (!IS_SPEC_OBJECT(key)) { 187 throw %MakeTypeError('invalid_weakmap_key', [this, key]); 188 } 189 return !IS_UNDEFINED(%WeakMapGet(this, key)); 190 } 191 192 193 function WeakMapDelete(key) { 194 if (!IS_WEAKMAP(this)) { 195 throw MakeTypeError('incompatible_method_receiver', 196 ['WeakMap.prototype.delete', this]); 197 } 198 if (!IS_SPEC_OBJECT(key)) { 199 throw %MakeTypeError('invalid_weakmap_key', [this, key]); 200 } 201 if (!IS_UNDEFINED(%WeakMapGet(this, key))) { 202 %WeakMapSet(this, key, void 0); 203 return true; 204 } else { 205 return false; 206 } 207 } 208 209 // ------------------------------------------------------------------- 210 211 (function () { 212 %CheckIsBootstrapping(); 213 214 // Set up the Set and Map constructor function. 215 %SetCode($Set, SetConstructor); 216 %SetCode($Map, MapConstructor); 217 218 // Set up the constructor property on the Set and Map prototype object. 219 %SetProperty($Set.prototype, "constructor", $Set, DONT_ENUM); 220 %SetProperty($Map.prototype, "constructor", $Map, DONT_ENUM); 221 222 // Set up the non-enumerable functions on the Set prototype object. 223 InstallFunctions($Set.prototype, DONT_ENUM, $Array( 224 "add", SetAdd, 225 "has", SetHas, 226 "delete", SetDelete 227 )); 228 229 // Set up the non-enumerable functions on the Map prototype object. 230 InstallFunctions($Map.prototype, DONT_ENUM, $Array( 231 "get", MapGet, 232 "set", MapSet, 233 "has", MapHas, 234 "delete", MapDelete 235 )); 236 237 // Set up the WeakMap constructor function. 238 %SetCode($WeakMap, WeakMapConstructor); 239 240 // Set up the constructor property on the WeakMap prototype object. 241 %SetProperty($WeakMap.prototype, "constructor", $WeakMap, DONT_ENUM); 242 243 // Set up the non-enumerable functions on the WeakMap prototype object. 244 InstallFunctions($WeakMap.prototype, DONT_ENUM, $Array( 245 "get", WeakMapGet, 246 "set", WeakMapSet, 247 "has", WeakMapHas, 248 "delete", WeakMapDelete 249 )); 250 })(); 251