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 // Flags: --harmony-collections --expose-gc 29 30 31 // Test valid getter and setter calls on Sets. 32 function TestValidSetCalls(m) { 33 assertDoesNotThrow(function () { m.add(new Object) }); 34 assertDoesNotThrow(function () { m.has(new Object) }); 35 assertDoesNotThrow(function () { m.delete(new Object) }); 36 } 37 TestValidSetCalls(new Set); 38 39 40 // Test valid getter and setter calls on Maps and WeakMaps 41 function TestValidMapCalls(m) { 42 assertDoesNotThrow(function () { m.get(new Object) }); 43 assertDoesNotThrow(function () { m.set(new Object) }); 44 assertDoesNotThrow(function () { m.has(new Object) }); 45 assertDoesNotThrow(function () { m.delete(new Object) }); 46 } 47 TestValidMapCalls(new Map); 48 TestValidMapCalls(new WeakMap); 49 50 51 // Test invalid getter and setter calls for WeakMap only 52 function TestInvalidCalls(m) { 53 assertThrows(function () { m.get(undefined) }, TypeError); 54 assertThrows(function () { m.set(undefined, 0) }, TypeError); 55 assertThrows(function () { m.get(null) }, TypeError); 56 assertThrows(function () { m.set(null, 0) }, TypeError); 57 assertThrows(function () { m.get(0) }, TypeError); 58 assertThrows(function () { m.set(0, 0) }, TypeError); 59 assertThrows(function () { m.get('a-key') }, TypeError); 60 assertThrows(function () { m.set('a-key', 0) }, TypeError); 61 } 62 TestInvalidCalls(new WeakMap); 63 64 65 // Test expected behavior for Sets 66 function TestSet(set, key) { 67 assertFalse(set.has(key)); 68 set.add(key); 69 assertTrue(set.has(key)); 70 set.delete(key); 71 assertFalse(set.has(key)); 72 } 73 function TestSetBehavior(set) { 74 for (var i = 0; i < 20; i++) { 75 TestSet(set, new Object); 76 TestSet(set, i); 77 TestSet(set, i / 100); 78 TestSet(set, 'key-' + i); 79 } 80 var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined ]; 81 for (var i = 0; i < keys.length; i++) { 82 TestSet(set, keys[i]); 83 } 84 } 85 TestSetBehavior(new Set); 86 87 88 // Test expected mapping behavior for Maps and WeakMaps 89 function TestMapping(map, key, value) { 90 map.set(key, value); 91 assertSame(value, map.get(key)); 92 } 93 function TestMapBehavior1(m) { 94 TestMapping(m, new Object, 23); 95 TestMapping(m, new Object, 'the-value'); 96 TestMapping(m, new Object, new Object); 97 } 98 TestMapBehavior1(new Map); 99 TestMapBehavior1(new WeakMap); 100 101 102 // Test expected mapping behavior for Maps only 103 function TestMapBehavior2(m) { 104 for (var i = 0; i < 20; i++) { 105 TestMapping(m, i, new Object); 106 TestMapping(m, i / 10, new Object); 107 TestMapping(m, 'key-' + i, new Object); 108 } 109 var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined ]; 110 for (var i = 0; i < keys.length; i++) { 111 TestMapping(m, keys[i], new Object); 112 } 113 } 114 TestMapBehavior2(new Map); 115 116 117 // Test expected querying behavior of Maps and WeakMaps 118 function TestQuery(m) { 119 var key = new Object; 120 TestMapping(m, key, 'to-be-present'); 121 assertTrue(m.has(key)); 122 assertFalse(m.has(new Object)); 123 TestMapping(m, key, undefined); 124 assertFalse(m.has(key)); 125 assertFalse(m.has(new Object)); 126 } 127 TestQuery(new Map); 128 TestQuery(new WeakMap); 129 130 131 // Test expected deletion behavior of Maps and WeakMaps 132 function TestDelete(m) { 133 var key = new Object; 134 TestMapping(m, key, 'to-be-deleted'); 135 assertTrue(m.delete(key)); 136 assertFalse(m.delete(key)); 137 assertFalse(m.delete(new Object)); 138 assertSame(m.get(key), undefined); 139 } 140 TestDelete(new Map); 141 TestDelete(new WeakMap); 142 143 144 // Test GC of Maps and WeakMaps with entry 145 function TestGC1(m) { 146 var key = new Object; 147 m.set(key, 'not-collected'); 148 gc(); 149 assertSame('not-collected', m.get(key)); 150 } 151 TestGC1(new Map); 152 TestGC1(new WeakMap); 153 154 155 // Test GC of Maps and WeakMaps with chained entries 156 function TestGC2(m) { 157 var head = new Object; 158 for (key = head, i = 0; i < 10; i++, key = m.get(key)) { 159 m.set(key, new Object); 160 } 161 gc(); 162 var count = 0; 163 for (key = head; key != undefined; key = m.get(key)) { 164 count++; 165 } 166 assertEquals(11, count); 167 } 168 TestGC2(new Map); 169 TestGC2(new WeakMap); 170 171 172 // Test property attribute [[Enumerable]] 173 function TestEnumerable(func) { 174 function props(x) { 175 var array = []; 176 for (var p in x) array.push(p); 177 return array.sort(); 178 } 179 assertArrayEquals([], props(func)); 180 assertArrayEquals([], props(func.prototype)); 181 assertArrayEquals([], props(new func())); 182 } 183 TestEnumerable(Set); 184 TestEnumerable(Map); 185 TestEnumerable(WeakMap); 186 187 188 // Test arbitrary properties on Maps and WeakMaps 189 function TestArbitrary(m) { 190 function TestProperty(map, property, value) { 191 map[property] = value; 192 assertEquals(value, map[property]); 193 } 194 for (var i = 0; i < 20; i++) { 195 TestProperty(m, i, 'val' + i); 196 TestProperty(m, 'foo' + i, 'bar' + i); 197 } 198 TestMapping(m, new Object, 'foobar'); 199 } 200 TestArbitrary(new Map); 201 TestArbitrary(new WeakMap); 202 203 204 // Test direct constructor call 205 assertTrue(Set() instanceof Set); 206 assertTrue(Map() instanceof Map); 207 assertTrue(WeakMap() instanceof WeakMap); 208 209 210 // Test whether NaN values as keys are treated correctly. 211 var s = new Set; 212 assertFalse(s.has(NaN)); 213 assertFalse(s.has(NaN + 1)); 214 assertFalse(s.has(23)); 215 s.add(NaN); 216 assertTrue(s.has(NaN)); 217 assertTrue(s.has(NaN + 1)); 218 assertFalse(s.has(23)); 219 var m = new Map; 220 assertFalse(m.has(NaN)); 221 assertFalse(m.has(NaN + 1)); 222 assertFalse(m.has(23)); 223 m.set(NaN, 'a-value'); 224 assertTrue(m.has(NaN)); 225 assertTrue(m.has(NaN + 1)); 226 assertFalse(m.has(23)); 227 228 229 // Test some common JavaScript idioms for Sets 230 var s = new Set; 231 assertTrue(s instanceof Set); 232 assertTrue(Set.prototype.add instanceof Function) 233 assertTrue(Set.prototype.has instanceof Function) 234 assertTrue(Set.prototype.delete instanceof Function) 235 236 237 // Test some common JavaScript idioms for Maps 238 var m = new Map; 239 assertTrue(m instanceof Map); 240 assertTrue(Map.prototype.set instanceof Function) 241 assertTrue(Map.prototype.get instanceof Function) 242 assertTrue(Map.prototype.has instanceof Function) 243 assertTrue(Map.prototype.delete instanceof Function) 244 245 246 // Test some common JavaScript idioms for WeakMaps 247 var m = new WeakMap; 248 assertTrue(m instanceof WeakMap); 249 assertTrue(WeakMap.prototype.set instanceof Function) 250 assertTrue(WeakMap.prototype.get instanceof Function) 251 assertTrue(WeakMap.prototype.has instanceof Function) 252 assertTrue(WeakMap.prototype.delete instanceof Function) 253 254 255 // Regression test for WeakMap prototype. 256 assertTrue(WeakMap.prototype.constructor === WeakMap) 257 assertTrue(Object.getPrototypeOf(WeakMap.prototype) === Object.prototype) 258 259 260 // Regression test for issue 1617: The prototype of the WeakMap constructor 261 // needs to be unique (i.e. different from the one of the Object constructor). 262 assertFalse(WeakMap.prototype === Object.prototype); 263 var o = Object.create({}); 264 assertFalse("get" in o); 265 assertFalse("set" in o); 266 assertEquals(undefined, o.get); 267 assertEquals(undefined, o.set); 268 var o = Object.create({}, { myValue: { 269 value: 10, 270 enumerable: false, 271 configurable: true, 272 writable: true 273 }}); 274 assertEquals(10, o.myValue); 275 276 277 // Regression test for issue 1884: Invoking any of the methods for Harmony 278 // maps, sets, or weak maps, with a wrong type of receiver should be throwing 279 // a proper TypeError. 280 var alwaysBogus = [ undefined, null, true, "x", 23, {} ]; 281 var bogusReceiversTestSet = [ 282 { proto: Set.prototype, 283 funcs: [ 'add', 'has', 'delete' ], 284 receivers: alwaysBogus.concat([ new Map, new WeakMap ]), 285 }, 286 { proto: Map.prototype, 287 funcs: [ 'get', 'set', 'has', 'delete' ], 288 receivers: alwaysBogus.concat([ new Set, new WeakMap ]), 289 }, 290 { proto: WeakMap.prototype, 291 funcs: [ 'get', 'set', 'has', 'delete' ], 292 receivers: alwaysBogus.concat([ new Set, new Map ]), 293 }, 294 ]; 295 function TestBogusReceivers(testSet) { 296 for (var i = 0; i < testSet.length; i++) { 297 var proto = testSet[i].proto; 298 var funcs = testSet[i].funcs; 299 var receivers = testSet[i].receivers; 300 for (var j = 0; j < funcs.length; j++) { 301 var func = proto[funcs[j]]; 302 for (var k = 0; k < receivers.length; k++) { 303 assertThrows(function () { func.call(receivers[k], {}) }, TypeError); 304 } 305 } 306 } 307 } 308 TestBogusReceivers(bogusReceiversTestSet); 309 310 311 // Stress Test 312 // There is a proposed stress-test available at the es-discuss mailing list 313 // which cannot be reasonably automated. Check it out by hand if you like: 314 // https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html