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