Home | History | Annotate | Download | only in harmony
      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