OLD | NEW |
| (Empty) |
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. | |
36 function TestValidSetCalls(m) { | |
37 assertDoesNotThrow(function () { m.add(new Object) }); | |
38 assertDoesNotThrow(function () { m.has(new Object) }); | |
39 assertDoesNotThrow(function () { m.delete(new Object) }); | |
40 } | |
41 TestValidSetCalls(new WeakSet); | |
42 | |
43 | |
44 // Test valid getter and setter calls on WeakMaps | |
45 function 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 } | |
51 TestValidMapCalls(new WeakMap); | |
52 | |
53 | |
54 // Test invalid getter and setter calls for WeakMap | |
55 function 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 } | |
65 TestInvalidCalls(new WeakMap); | |
66 | |
67 | |
68 // Test expected behavior for WeakSets | |
69 function TestSet(set, key) { | |
70 assertFalse(set.has(key)); | |
71 assertSame(set, 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 } | |
78 function 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 } | |
90 TestSet(new WeakSet, new Object); | |
91 | |
92 | |
93 // Test expected mapping behavior for WeakMaps | |
94 function TestMapping(map, key, value) { | |
95 assertSame(map, map.set(key, value)); | |
96 assertSame(value, map.get(key)); | |
97 } | |
98 function TestMapBehavior1(m) { | |
99 TestMapping(m, new Object, 23); | |
100 TestMapping(m, new Object, 'the-value'); | |
101 TestMapping(m, new Object, new Object); | |
102 } | |
103 TestMapBehavior1(new WeakMap); | |
104 | |
105 | |
106 // Test expected querying behavior of WeakMaps | |
107 function 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 } | |
116 TestQuery(new WeakMap); | |
117 | |
118 | |
119 // Test expected deletion behavior of WeakMaps | |
120 function 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 } | |
128 TestDelete(new WeakMap); | |
129 | |
130 | |
131 // Test GC of WeakMaps with entry | |
132 function TestGC1(m) { | |
133 var key = new Object; | |
134 m.set(key, 'not-collected'); | |
135 gc(); | |
136 assertSame('not-collected', m.get(key)); | |
137 } | |
138 TestGC1(new WeakMap); | |
139 | |
140 | |
141 // Test GC of WeakMaps with chained entries | |
142 function 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 } | |
154 TestGC2(new WeakMap); | |
155 | |
156 | |
157 // Test property attribute [[Enumerable]] | |
158 function 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 } | |
168 TestEnumerable(WeakMap); | |
169 TestEnumerable(WeakSet); | |
170 | |
171 | |
172 // Test arbitrary properties on WeakMaps | |
173 function 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 } | |
184 TestArbitrary(new WeakMap); | |
185 | |
186 | |
187 // Test direct constructor call | |
188 assertThrows(function() { WeakMap(); }, TypeError); | |
189 assertThrows(function() { WeakSet(); }, TypeError); | |
190 | |
191 | |
192 // Test some common JavaScript idioms for WeakMaps | |
193 var m = new WeakMap; | |
194 assertTrue(m instanceof WeakMap); | |
195 assertTrue(WeakMap.prototype.set instanceof Function) | |
196 assertTrue(WeakMap.prototype.get instanceof Function) | |
197 assertTrue(WeakMap.prototype.has instanceof Function) | |
198 assertTrue(WeakMap.prototype.delete instanceof Function) | |
199 assertTrue(WeakMap.prototype.clear instanceof Function) | |
200 | |
201 | |
202 // Test some common JavaScript idioms for WeakSets | |
203 var s = new WeakSet; | |
204 assertTrue(s instanceof WeakSet); | |
205 assertTrue(WeakSet.prototype.add instanceof Function) | |
206 assertTrue(WeakSet.prototype.has instanceof Function) | |
207 assertTrue(WeakSet.prototype.delete instanceof Function) | |
208 assertTrue(WeakSet.prototype.clear instanceof Function) | |
209 | |
210 | |
211 // Test class of instance and prototype. | |
212 assertEquals("WeakMap", %_ClassOf(new WeakMap)) | |
213 assertEquals("Object", %_ClassOf(WeakMap.prototype)) | |
214 assertEquals("WeakSet", %_ClassOf(new WeakSet)) | |
215 assertEquals("Object", %_ClassOf(WeakMap.prototype)) | |
216 | |
217 | |
218 // Test name of constructor. | |
219 assertEquals("WeakMap", WeakMap.name); | |
220 assertEquals("WeakSet", WeakSet.name); | |
221 | |
222 | |
223 // Test prototype property of WeakMap and WeakSet. | |
224 function 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 } | |
233 TestPrototype(WeakMap); | |
234 TestPrototype(WeakSet); | |
235 | |
236 | |
237 // Test constructor property of the WeakMap and WeakSet prototype. | |
238 function TestConstructor(C) { | |
239 assertFalse(C === Object.prototype.constructor); | |
240 assertSame(C, C.prototype.constructor); | |
241 assertSame(C, (new C).__proto__.constructor); | |
242 } | |
243 TestConstructor(WeakMap); | |
244 TestConstructor(WeakSet); | |
245 | |
246 | |
247 // Test the WeakMap and WeakSet global properties themselves. | |
248 function TestDescriptor(global, C) { | |
249 assertEquals({ | |
250 value: C, | |
251 writable: true, | |
252 enumerable: false, | |
253 configurable: true | |
254 }, Object.getOwnPropertyDescriptor(global, C.name)); | |
255 } | |
256 TestDescriptor(this, WeakMap); | |
257 TestDescriptor(this, WeakSet); | |
258 | |
259 | |
260 // Regression test for WeakMap prototype. | |
261 assertTrue(WeakMap.prototype.constructor === WeakMap) | |
262 assertTrue(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). | |
267 assertFalse(WeakMap.prototype === Object.prototype); | |
268 var o = Object.create({}); | |
269 assertFalse("get" in o); | |
270 assertFalse("set" in o); | |
271 assertEquals(undefined, o.get); | |
272 assertEquals(undefined, o.set); | |
273 var o = Object.create({}, { myValue: { | |
274 value: 10, | |
275 enumerable: false, | |
276 configurable: true, | |
277 writable: true | |
278 }}); | |
279 assertEquals(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. | |
285 var alwaysBogus = [ undefined, null, true, "x", 23, {} ]; | |
286 var 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 ]; | |
296 function 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 } | |
309 TestBogusReceivers(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 })(); | |
OLD | NEW |