Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / test / mjsunit / es6 / collections.js
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 --harmony-tostring
29
30
31 function assertSize(expected, collection) {
32   if (collection instanceof Map || collection instanceof Set) {
33     assertEquals(expected, collection.size);
34   }
35 }
36
37
38 // Test valid getter and setter calls on Sets and WeakSets
39 function TestValidSetCalls(m) {
40   assertDoesNotThrow(function () { m.add(new Object) });
41   assertDoesNotThrow(function () { m.has(new Object) });
42   assertDoesNotThrow(function () { m.delete(new Object) });
43 }
44 TestValidSetCalls(new Set);
45 TestValidSetCalls(new WeakSet);
46
47
48 // Test valid getter and setter calls on Maps and WeakMaps
49 function TestValidMapCalls(m) {
50   assertDoesNotThrow(function () { m.get(new Object) });
51   assertDoesNotThrow(function () { m.set(new Object) });
52   assertDoesNotThrow(function () { m.has(new Object) });
53   assertDoesNotThrow(function () { m.delete(new Object) });
54 }
55 TestValidMapCalls(new Map);
56 TestValidMapCalls(new WeakMap);
57
58
59 // Test invalid getter and setter calls for WeakMap only
60 function TestInvalidCalls(m) {
61   assertThrows(function () { m.get(undefined) }, TypeError);
62   assertThrows(function () { m.set(undefined, 0) }, TypeError);
63   assertThrows(function () { m.get(null) }, TypeError);
64   assertThrows(function () { m.set(null, 0) }, TypeError);
65   assertThrows(function () { m.get(0) }, TypeError);
66   assertThrows(function () { m.set(0, 0) }, TypeError);
67   assertThrows(function () { m.get('a-key') }, TypeError);
68   assertThrows(function () { m.set('a-key', 0) }, TypeError);
69 }
70 TestInvalidCalls(new WeakMap);
71
72
73 // Test expected behavior for Sets and WeakSets
74 function TestSet(set, key) {
75   assertFalse(set.has(key));
76   assertSame(set, set.add(key));
77   assertTrue(set.has(key));
78   assertTrue(set.delete(key));
79   assertFalse(set.has(key));
80   assertFalse(set.delete(key));
81   assertFalse(set.has(key));
82 }
83 function TestSetBehavior(set) {
84   for (var i = 0; i < 20; i++) {
85     TestSet(set, new Object);
86     TestSet(set, i);
87     TestSet(set, i / 100);
88     TestSet(set, 'key-' + i);
89   }
90   var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined ];
91   for (var i = 0; i < keys.length; i++) {
92     TestSet(set, keys[i]);
93   }
94 }
95 TestSetBehavior(new Set);
96 TestSet(new WeakSet, new Object);
97
98
99 // Test expected mapping behavior for Maps and WeakMaps
100 function TestMapping(map, key, value) {
101   assertSame(map, map.set(key, value));
102   assertSame(value, map.get(key));
103 }
104 function TestMapBehavior1(m) {
105   TestMapping(m, new Object, 23);
106   TestMapping(m, new Object, 'the-value');
107   TestMapping(m, new Object, new Object);
108 }
109 TestMapBehavior1(new Map);
110 TestMapBehavior1(new WeakMap);
111
112
113 // Test expected mapping behavior for Maps only
114 function TestMapBehavior2(m) {
115   for (var i = 0; i < 20; i++) {
116     TestMapping(m, i, new Object);
117     TestMapping(m, i / 10, new Object);
118     TestMapping(m, 'key-' + i, new Object);
119   }
120   // -0 is handled in TestMinusZeroMap
121   var keys = [ 0, +Infinity, -Infinity, true, false, null, undefined ];
122   for (var i = 0; i < keys.length; i++) {
123     TestMapping(m, keys[i], new Object);
124   }
125 }
126 TestMapBehavior2(new Map);
127
128
129 // Test expected querying behavior of Maps and WeakMaps
130 function TestQuery(m) {
131   var key = new Object;
132   var values = [ 'x', 0, +Infinity, -Infinity, true, false, null, undefined ];
133   for (var i = 0; i < values.length; i++) {
134     TestMapping(m, key, values[i]);
135     assertTrue(m.has(key));
136     assertFalse(m.has(new Object));
137   }
138 }
139 TestQuery(new Map);
140 TestQuery(new WeakMap);
141
142
143 // Test expected deletion behavior of Maps and WeakMaps
144 function TestDelete(m) {
145   var key = new Object;
146   TestMapping(m, key, 'to-be-deleted');
147   assertTrue(m.delete(key));
148   assertFalse(m.delete(key));
149   assertFalse(m.delete(new Object));
150   assertSame(m.get(key), undefined);
151 }
152 TestDelete(new Map);
153 TestDelete(new WeakMap);
154
155
156 // Test GC of Maps and WeakMaps with entry
157 function TestGC1(m) {
158   var key = new Object;
159   m.set(key, 'not-collected');
160   gc();
161   assertSame('not-collected', m.get(key));
162 }
163 TestGC1(new Map);
164 TestGC1(new WeakMap);
165
166
167 // Test GC of Maps and WeakMaps with chained entries
168 function TestGC2(m) {
169   var head = new Object;
170   for (key = head, i = 0; i < 10; i++, key = m.get(key)) {
171     m.set(key, new Object);
172   }
173   gc();
174   var count = 0;
175   for (key = head; key != undefined; key = m.get(key)) {
176     count++;
177   }
178   assertEquals(11, count);
179 }
180 TestGC2(new Map);
181 TestGC2(new WeakMap);
182
183
184 // Test property attribute [[Enumerable]]
185 function TestEnumerable(func) {
186   function props(x) {
187     var array = [];
188     for (var p in x) array.push(p);
189     return array.sort();
190   }
191   assertArrayEquals([], props(func));
192   assertArrayEquals([], props(func.prototype));
193   assertArrayEquals([], props(new func()));
194 }
195 TestEnumerable(Set);
196 TestEnumerable(Map);
197 TestEnumerable(WeakMap);
198 TestEnumerable(WeakSet);
199
200
201 // Test arbitrary properties on Maps and WeakMaps
202 function TestArbitrary(m) {
203   function TestProperty(map, property, value) {
204     map[property] = value;
205     assertEquals(value, map[property]);
206   }
207   for (var i = 0; i < 20; i++) {
208     TestProperty(m, i, 'val' + i);
209     TestProperty(m, 'foo' + i, 'bar' + i);
210   }
211   TestMapping(m, new Object, 'foobar');
212 }
213 TestArbitrary(new Map);
214 TestArbitrary(new WeakMap);
215
216
217 // Test direct constructor call
218 assertThrows(function() { Set(); }, TypeError);
219 assertThrows(function() { Map(); }, TypeError);
220 assertThrows(function() { WeakMap(); }, TypeError);
221 assertThrows(function() { WeakSet(); }, TypeError);
222
223
224 // Test whether NaN values as keys are treated correctly.
225 var s = new Set;
226 assertFalse(s.has(NaN));
227 assertFalse(s.has(NaN + 1));
228 assertFalse(s.has(23));
229 s.add(NaN);
230 assertTrue(s.has(NaN));
231 assertTrue(s.has(NaN + 1));
232 assertFalse(s.has(23));
233 var m = new Map;
234 assertFalse(m.has(NaN));
235 assertFalse(m.has(NaN + 1));
236 assertFalse(m.has(23));
237 m.set(NaN, 'a-value');
238 assertTrue(m.has(NaN));
239 assertTrue(m.has(NaN + 1));
240 assertFalse(m.has(23));
241
242
243 // Test some common JavaScript idioms for Sets
244 var s = new Set;
245 assertTrue(s instanceof Set);
246 assertTrue(Set.prototype.add instanceof Function)
247 assertTrue(Set.prototype.has instanceof Function)
248 assertTrue(Set.prototype.delete instanceof Function)
249 assertTrue(Set.prototype.clear instanceof Function)
250
251
252 // Test some common JavaScript idioms for Maps
253 var m = new Map;
254 assertTrue(m instanceof Map);
255 assertTrue(Map.prototype.set instanceof Function)
256 assertTrue(Map.prototype.get instanceof Function)
257 assertTrue(Map.prototype.has instanceof Function)
258 assertTrue(Map.prototype.delete instanceof Function)
259 assertTrue(Map.prototype.clear instanceof Function)
260
261
262 // Test some common JavaScript idioms for WeakMaps
263 var m = new WeakMap;
264 assertTrue(m instanceof WeakMap);
265 assertTrue(WeakMap.prototype.set instanceof Function)
266 assertTrue(WeakMap.prototype.get instanceof Function)
267 assertTrue(WeakMap.prototype.has instanceof Function)
268 assertTrue(WeakMap.prototype.delete instanceof Function)
269 assertTrue(WeakMap.prototype.clear instanceof Function)
270
271
272 // Test some common JavaScript idioms for WeakSets
273 var s = new WeakSet;
274 assertTrue(s instanceof WeakSet);
275 assertTrue(WeakSet.prototype.add instanceof Function)
276 assertTrue(WeakSet.prototype.has instanceof Function)
277 assertTrue(WeakSet.prototype.delete instanceof Function)
278 assertTrue(WeakSet.prototype.clear instanceof Function)
279
280
281 // Test class of instance and prototype.
282 assertEquals("Set", %_ClassOf(new Set))
283 assertEquals("Object", %_ClassOf(Set.prototype))
284 assertEquals("Map", %_ClassOf(new Map))
285 assertEquals("Object", %_ClassOf(Map.prototype))
286 assertEquals("WeakMap", %_ClassOf(new WeakMap))
287 assertEquals("Object", %_ClassOf(WeakMap.prototype))
288 assertEquals("WeakSet", %_ClassOf(new WeakSet))
289 assertEquals("Object", %_ClassOf(WeakMap.prototype))
290
291
292 // Test name of constructor.
293 assertEquals("Set", Set.name);
294 assertEquals("Map", Map.name);
295 assertEquals("WeakMap", WeakMap.name);
296 assertEquals("WeakSet", WeakSet.name);
297
298
299 // Test prototype property of Set, Map, WeakMap and WeakSet.
300 function TestPrototype(C) {
301   assertTrue(C.prototype instanceof Object);
302   assertEquals({
303     value: C.prototype,
304     writable: false,
305     enumerable: false,
306     configurable: false
307   }, Object.getOwnPropertyDescriptor(C, "prototype"));
308 }
309 TestPrototype(Set);
310 TestPrototype(Map);
311 TestPrototype(WeakMap);
312 TestPrototype(WeakSet);
313
314
315 // Test constructor property of the Set, Map, WeakMap and WeakSet prototype.
316 function TestConstructor(C) {
317   assertFalse(C === Object.prototype.constructor);
318   assertSame(C, C.prototype.constructor);
319   assertSame(C, (new C).__proto__.constructor);
320   assertEquals(1, C.length);
321 }
322 TestConstructor(Set);
323 TestConstructor(Map);
324 TestConstructor(WeakMap);
325 TestConstructor(WeakSet);
326
327
328 // Test the Set, Map, WeakMap and WeakSet global properties themselves.
329 function TestDescriptor(global, C) {
330   assertEquals({
331     value: C,
332     writable: true,
333     enumerable: false,
334     configurable: true
335   }, Object.getOwnPropertyDescriptor(global, C.name));
336 }
337 TestDescriptor(this, Set);
338 TestDescriptor(this, Map);
339 TestDescriptor(this, WeakMap);
340 TestDescriptor(this, WeakSet);
341
342
343 // Regression test for WeakMap prototype.
344 assertTrue(WeakMap.prototype.constructor === WeakMap)
345 assertTrue(Object.getPrototypeOf(WeakMap.prototype) === Object.prototype)
346
347
348 // Regression test for issue 1617: The prototype of the WeakMap constructor
349 // needs to be unique (i.e. different from the one of the Object constructor).
350 assertFalse(WeakMap.prototype === Object.prototype);
351 var o = Object.create({});
352 assertFalse("get" in o);
353 assertFalse("set" in o);
354 assertEquals(undefined, o.get);
355 assertEquals(undefined, o.set);
356 var o = Object.create({}, { myValue: {
357   value: 10,
358   enumerable: false,
359   configurable: true,
360   writable: true
361 }});
362 assertEquals(10, o.myValue);
363
364
365 // Regression test for issue 1884: Invoking any of the methods for Harmony
366 // maps, sets, or weak maps, with a wrong type of receiver should be throwing
367 // a proper TypeError.
368 var alwaysBogus = [ undefined, null, true, "x", 23, {} ];
369 var bogusReceiversTestSet = [
370   { proto: Set.prototype,
371     funcs: [ 'add', 'has', 'delete' ],
372     receivers: alwaysBogus.concat([ new Map, new WeakMap, new WeakSet ]),
373   },
374   { proto: Map.prototype,
375     funcs: [ 'get', 'set', 'has', 'delete' ],
376     receivers: alwaysBogus.concat([ new Set, new WeakMap, new WeakSet ]),
377   },
378   { proto: WeakMap.prototype,
379     funcs: [ 'get', 'set', 'has', 'delete' ],
380     receivers: alwaysBogus.concat([ new Set, new Map, new WeakSet ]),
381   },
382   { proto: WeakSet.prototype,
383     funcs: [ 'add', 'has', 'delete' ],
384     receivers: alwaysBogus.concat([ new Set, new Map, new WeakMap ]),
385   },
386 ];
387 function TestBogusReceivers(testSet) {
388   for (var i = 0; i < testSet.length; i++) {
389     var proto = testSet[i].proto;
390     var funcs = testSet[i].funcs;
391     var receivers = testSet[i].receivers;
392     for (var j = 0; j < funcs.length; j++) {
393       var func = proto[funcs[j]];
394       for (var k = 0; k < receivers.length; k++) {
395         assertThrows(function () { func.call(receivers[k], {}) }, TypeError);
396       }
397     }
398   }
399 }
400 TestBogusReceivers(bogusReceiversTestSet);
401
402
403 // Stress Test
404 // There is a proposed stress-test available at the es-discuss mailing list
405 // which cannot be reasonably automated.  Check it out by hand if you like:
406 // https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html
407
408
409 // Set and Map size getters
410 var setSizeDescriptor = Object.getOwnPropertyDescriptor(Set.prototype, 'size');
411 assertEquals(undefined, setSizeDescriptor.value);
412 assertEquals(undefined, setSizeDescriptor.set);
413 assertTrue(setSizeDescriptor.get instanceof Function);
414 assertEquals(undefined, setSizeDescriptor.get.prototype);
415 assertFalse(setSizeDescriptor.enumerable);
416 assertTrue(setSizeDescriptor.configurable);
417
418 var s = new Set();
419 assertFalse(s.hasOwnProperty('size'));
420 for (var i = 0; i < 10; i++) {
421   assertEquals(i, s.size);
422   s.add(i);
423 }
424 for (var i = 9; i >= 0; i--) {
425   s.delete(i);
426   assertEquals(i, s.size);
427 }
428
429
430 var mapSizeDescriptor = Object.getOwnPropertyDescriptor(Map.prototype, 'size');
431 assertEquals(undefined, mapSizeDescriptor.value);
432 assertEquals(undefined, mapSizeDescriptor.set);
433 assertTrue(mapSizeDescriptor.get instanceof Function);
434 assertEquals(undefined, mapSizeDescriptor.get.prototype);
435 assertFalse(mapSizeDescriptor.enumerable);
436 assertTrue(mapSizeDescriptor.configurable);
437
438 var m = new Map();
439 assertFalse(m.hasOwnProperty('size'));
440 for (var i = 0; i < 10; i++) {
441   assertEquals(i, m.size);
442   m.set(i, i);
443 }
444 for (var i = 9; i >= 0; i--) {
445   m.delete(i);
446   assertEquals(i, m.size);
447 }
448
449
450 // Test Set clear
451 (function() {
452   var s = new Set();
453   s.add(42);
454   assertTrue(s.has(42));
455   assertEquals(1, s.size);
456   s.clear();
457   assertFalse(s.has(42));
458   assertEquals(0, s.size);
459 })();
460
461
462 // Test Map clear
463 (function() {
464   var m = new Map();
465   m.set(42, true);
466   assertTrue(m.has(42));
467   assertEquals(1, m.size);
468   m.clear();
469   assertFalse(m.has(42));
470   assertEquals(0, m.size);
471 })();
472
473
474 // Test WeakMap clear
475 (function() {
476   var k = new Object();
477   var w = new WeakMap();
478   w.set(k, 23);
479   assertTrue(w.has(k));
480   assertEquals(23, w.get(k));
481   w.clear();
482   assertFalse(w.has(k));
483   assertEquals(undefined, w.get(k));
484 })();
485
486
487 // Test WeakSet clear
488 (function() {
489   var k = new Object();
490   var w = new WeakSet();
491   w.add(k);
492   assertTrue(w.has(k));
493   w.clear();
494   assertFalse(w.has(k));
495 })();
496
497
498 (function TestMinusZeroSet() {
499   var s = new Set();
500   s.add(-0);
501   assertSame(0, s.values().next().value);
502   s.add(0);
503   assertEquals(1, s.size);
504   assertTrue(s.has(0));
505   assertTrue(s.has(-0));
506 })();
507
508
509 (function TestMinusZeroMap() {
510   var m = new Map();
511   m.set(-0, 'minus');
512   assertSame(0, m.keys().next().value);
513   m.set(0, 'plus');
514   assertEquals(1, m.size);
515   assertTrue(m.has(0));
516   assertTrue(m.has(-0));
517   assertEquals('plus', m.get(0));
518   assertEquals('plus', m.get(-0));
519 })();
520
521
522 (function TestSetForEachInvalidTypes() {
523   assertThrows(function() {
524     Set.prototype.set.forEach.call({});
525   }, TypeError);
526
527   var set = new Set();
528   assertThrows(function() {
529     set.forEach({});
530   }, TypeError);
531 })();
532
533
534 (function TestSetForEach() {
535   var set = new Set();
536   set.add('a');
537   set.add('b');
538   set.add('c');
539
540   var buffer = '';
541   var receiver = {};
542   set.forEach(function(v, k, s) {
543     assertSame(v, k);
544     assertSame(set, s);
545     assertSame(this, receiver);
546     buffer += v;
547     if (v === 'a') {
548       set.delete('b');
549       set.add('d');
550       set.add('e');
551       set.add('f');
552     } else if (v === 'c') {
553       set.add('b');
554       set.delete('e');
555     }
556   }, receiver);
557
558   assertEquals('acdfb', buffer);
559 })();
560
561
562 (function TestSetForEachAddAtEnd() {
563   var set = new Set();
564   set.add('a');
565   set.add('b');
566
567   var buffer = '';
568   set.forEach(function(v) {
569     buffer += v;
570     if (v === 'b') {
571       set.add('c');
572     }
573   });
574
575   assertEquals('abc', buffer);
576 })();
577
578
579 (function TestSetForEachDeleteNext() {
580   var set = new Set();
581   set.add('a');
582   set.add('b');
583   set.add('c');
584
585   var buffer = '';
586   set.forEach(function(v) {
587     buffer += v;
588     if (v === 'b') {
589       set.delete('c');
590     }
591   });
592
593   assertEquals('ab', buffer);
594 })();
595
596
597 (function TestSetForEachDeleteVisitedAndAddAgain() {
598   var set = new Set();
599   set.add('a');
600   set.add('b');
601   set.add('c');
602
603   var buffer = '';
604   set.forEach(function(v) {
605     buffer += v;
606     if (v === 'b') {
607       set.delete('a');
608     } else if (v === 'c') {
609       set.add('a');
610     }
611   });
612
613   assertEquals('abca', buffer);
614 })();
615
616
617 (function TestSetForEachClear() {
618   var set = new Set();
619   set.add('a');
620   set.add('b');
621   set.add('c');
622
623   var buffer = '';
624   set.forEach(function(v) {
625     buffer += v;
626     if (v === 'a') {
627       set.clear();
628       set.add('d');
629       set.add('e');
630     }
631   });
632
633   assertEquals('ade', buffer);
634 })();
635
636
637 (function TestSetForEachNested() {
638   var set = new Set();
639   set.add('a');
640   set.add('b');
641   set.add('c');
642
643   var buffer = '';
644   set.forEach(function(v) {
645     buffer += v;
646     set.forEach(function(v) {
647       buffer += v;
648       if (v === 'a') {
649         set.delete('b');
650       }
651     });
652   });
653
654   assertEquals('aaccac', buffer);
655 })();
656
657
658 (function TestSetForEachEarlyExit() {
659   var set = new Set();
660   set.add('a');
661   set.add('b');
662   set.add('c');
663
664   var buffer = '';
665   var ex = {};
666   try {
667     set.forEach(function(v) {
668       buffer += v;
669       throw ex;
670     });
671   } catch (e) {
672     assertEquals(ex, e);
673   }
674   assertEquals('a', buffer);
675 })();
676
677
678 (function TestSetForEachGC() {
679   var set = new Set();
680   for (var i = 0; i < 100; i++) {
681     set.add(i);
682   }
683
684   var accumulated = 0;
685   set.forEach(function(v) {
686     accumulated += v;
687     if (v % 10 === 0) {
688       gc();
689     }
690   });
691   assertEquals(4950, accumulated);
692 })();
693
694
695 (function TestSetForEachReceiverAsObject() {
696   var set = new Set(["1", "2"]);
697
698   // Create a new object in each function call when receiver is a
699   // primitive value. See ECMA-262, Annex C.
700   var a = [];
701   set.forEach(function() { a.push(this) }, "");
702   assertTrue(a[0] !== a[1]);
703
704   // Do not create a new object otherwise.
705   a = [];
706   set.forEach(function() { a.push(this); }, {});
707   assertEquals(a[0], a[1]);
708 })();
709
710
711 (function TestSetForEachReceiverAsObjectInStrictMode() {
712   var set = new Set(["1", "2"]);
713
714   // In strict mode primitive values should not be coerced to an object.
715   var a = [];
716   set.forEach(function() { 'use strict'; a.push(this); }, "");
717   assertTrue(a[0] === "" && a[0] === a[1]);
718 })();
719
720
721 (function TestMapForEachInvalidTypes() {
722   assertThrows(function() {
723     Map.prototype.map.forEach.call({});
724   }, TypeError);
725
726   var map = new Map();
727   assertThrows(function() {
728     map.forEach({});
729   }, TypeError);
730 })();
731
732
733 (function TestMapForEach() {
734   var map = new Map();
735   map.set(0, 'a');
736   map.set(1, 'b');
737   map.set(2, 'c');
738
739   var buffer = [];
740   var receiver = {};
741   map.forEach(function(v, k, m) {
742     assertEquals(map, m);
743     assertEquals(this, receiver);
744     buffer.push(k, v);
745     if (k === 0) {
746       map.delete(1);
747       map.set(3, 'd');
748       map.set(4, 'e');
749       map.set(5, 'f');
750     } else if (k === 2) {
751       map.set(1, 'B');
752       map.delete(4);
753     }
754   }, receiver);
755
756   assertArrayEquals([0, 'a', 2, 'c', 3, 'd', 5, 'f', 1, 'B'], buffer);
757 })();
758
759
760 (function TestMapForEachAddAtEnd() {
761   var map = new Map();
762   map.set(0, 'a');
763   map.set(1, 'b');
764
765   var buffer = [];
766   map.forEach(function(v, k) {
767     buffer.push(k, v);
768     if (k === 1) {
769       map.set(2, 'c');
770     }
771   });
772
773   assertArrayEquals([0, 'a', 1, 'b', 2, 'c'], buffer);
774 })();
775
776
777 (function TestMapForEachDeleteNext() {
778   var map = new Map();
779   map.set(0, 'a');
780   map.set(1, 'b');
781   map.set(2, 'c');
782
783   var buffer = [];
784   map.forEach(function(v, k) {
785     buffer.push(k, v);
786     if (k === 1) {
787       map.delete(2);
788     }
789   });
790
791   assertArrayEquals([0, 'a', 1, 'b'], buffer);
792 })();
793
794
795 (function TestSetForEachDeleteVisitedAndAddAgain() {
796   var map = new Map();
797   map.set(0, 'a');
798   map.set(1, 'b');
799   map.set(2, 'c');
800
801   var buffer = [];
802   map.forEach(function(v, k) {
803     buffer.push(k, v);
804     if (k === 1) {
805       map.delete(0);
806     } else if (k === 2) {
807       map.set(0, 'a');
808     }
809   });
810
811   assertArrayEquals([0, 'a', 1, 'b', 2, 'c', 0, 'a'], buffer);
812 })();
813
814
815 (function TestMapForEachClear() {
816   var map = new Map();
817   map.set(0, 'a');
818   map.set(1, 'b');
819   map.set(2, 'c');
820
821   var buffer = [];
822   map.forEach(function(v, k) {
823     buffer.push(k, v);
824     if (k === 0) {
825       map.clear();
826       map.set(3, 'd');
827       map.set(4, 'e');
828     }
829   });
830
831   assertArrayEquals([0, 'a', 3, 'd', 4, 'e'], buffer);
832 })();
833
834
835 (function TestMapForEachNested() {
836   var map = new Map();
837   map.set(0, 'a');
838   map.set(1, 'b');
839   map.set(2, 'c');
840
841   var buffer = [];
842   map.forEach(function(v, k) {
843     buffer.push(k, v);
844     map.forEach(function(v, k) {
845       buffer.push(k, v);
846       if (k === 0) {
847         map.delete(1);
848       }
849     });
850   });
851
852   assertArrayEquals([0, 'a', 0, 'a', 2, 'c', 2, 'c', 0, 'a', 2, 'c'], buffer);
853 })();
854
855
856 (function TestMapForEachEarlyExit() {
857   var map = new Map();
858   map.set(0, 'a');
859   map.set(1, 'b');
860   map.set(2, 'c');
861
862   var buffer = [];
863   var ex = {};
864   try {
865     map.forEach(function(v, k) {
866       buffer.push(k, v);
867       throw ex;
868     });
869   } catch (e) {
870     assertEquals(ex, e);
871   }
872   assertArrayEquals([0, 'a'], buffer);
873 })();
874
875
876 (function TestMapForEachGC() {
877   var map = new Map();
878   for (var i = 0; i < 100; i++) {
879     map.set(i, i);
880   }
881
882   var accumulated = 0;
883   map.forEach(function(v) {
884     accumulated += v;
885     if (v % 10 === 0) {
886       gc();
887     }
888   });
889   assertEquals(4950, accumulated);
890 })();
891
892
893 (function TestMapForEachAllRemovedTransition() {
894   var map = new Map;
895   map.set(0, 0);
896
897   var buffer = [];
898   map.forEach(function(v) {
899     buffer.push(v);
900     if (v === 0) {
901       for (var i = 1; i < 4; i++) {
902         map.set(i, i);
903       }
904     }
905
906     if (v === 3) {
907       for (var i = 0; i < 4; i++) {
908         map.delete(i);
909       }
910       for (var i = 4; i < 8; i++) {
911         map.set(i, i);
912       }
913     }
914   });
915
916   assertArrayEquals([0, 1, 2, 3, 4, 5, 6, 7], buffer);
917 })();
918
919
920 (function TestMapForEachClearTransition() {
921   var map = new Map;
922   map.set(0, 0);
923
924   var i = 0;
925   var buffer = [];
926   map.forEach(function(v) {
927     buffer.push(v);
928     if (++i < 5) {
929       for (var j = 0; j < 5; j++) {
930         map.clear();
931         map.set(i, i);
932       }
933     }
934   });
935
936   assertArrayEquals([0, 1, 2, 3, 4], buffer);
937 })();
938
939
940 (function TestMapForEachNestedNonTrivialTransition() {
941   var map = new Map;
942   map.set(0, 0);
943   map.set(1, 1);
944   map.set(2, 2);
945   map.set(3, 3);
946   map.delete(0);
947
948   var i = 0;
949   var buffer = [];
950   map.forEach(function(v) {
951     if (++i > 10) return;
952
953     buffer.push(v);
954
955     if (v == 3) {
956       map.delete(1);
957       for (var j = 4; j < 10; j++) {
958         map.set(j, j);
959       }
960       for (var j = 4; j < 10; j += 2) {
961         map.delete(j);
962       }
963       map.delete(2);
964
965       for (var j = 10; j < 20; j++) {
966         map.set(j, j);
967       }
968       for (var j = 10; j < 20; j += 2) {
969         map.delete(j);
970       }
971
972       map.delete(3);
973     }
974   });
975
976   assertArrayEquals([1, 2, 3, 5, 7, 9, 11, 13, 15, 17], buffer);
977 })();
978
979
980 (function TestMapForEachAllRemovedTransitionNoClear() {
981   var map = new Map;
982   map.set(0, 0);
983
984   var buffer = [];
985   map.forEach(function(v) {
986     buffer.push(v);
987     if (v === 0) {
988       for (var i = 1; i < 8; i++) {
989         map.set(i, i);
990       }
991     }
992
993     if (v === 4) {
994       for (var i = 0; i < 8; i++) {
995         map.delete(i);
996       }
997     }
998   });
999
1000   assertArrayEquals([0, 1, 2, 3, 4], buffer);
1001 })();
1002
1003
1004 (function TestMapForEachNoMoreElementsAfterTransition() {
1005   var map = new Map;
1006   map.set(0, 0);
1007
1008   var buffer = [];
1009   map.forEach(function(v) {
1010     buffer.push(v);
1011     if (v === 0) {
1012       for (var i = 1; i < 16; i++) {
1013         map.set(i, i);
1014       }
1015     }
1016
1017     if (v === 4) {
1018       for (var i = 5; i < 16; i++) {
1019         map.delete(i);
1020       }
1021     }
1022   });
1023
1024   assertArrayEquals([0, 1, 2, 3, 4], buffer);
1025 })();
1026
1027
1028 (function TestMapForEachReceiverAsObject() {
1029   var map = new Map();
1030   map.set("key1", "value1");
1031   map.set("key2", "value2");
1032
1033   // Create a new object in each function call when receiver is a
1034   // primitive value. See ECMA-262, Annex C.
1035   var a = [];
1036   map.forEach(function() { a.push(this) }, "");
1037   assertTrue(a[0] !== a[1]);
1038
1039   // Do not create a new object otherwise.
1040   a = [];
1041   map.forEach(function() { a.push(this); }, {});
1042   assertEquals(a[0], a[1]);
1043 })();
1044
1045
1046 (function TestMapForEachReceiverAsObjectInStrictMode() {
1047   var map = new Map();
1048   map.set("key1", "value1");
1049   map.set("key2", "value2");
1050
1051   // In strict mode primitive values should not be coerced to an object.
1052   var a = [];
1053   map.forEach(function() { 'use strict'; a.push(this); }, "");
1054   assertTrue(a[0] === "" && a[0] === a[1]);
1055 })();
1056
1057
1058 // Allows testing iterator-based constructors easily.
1059 var oneAndTwo = new Map();
1060 var k0 = {key: 0};
1061 var k1 = {key: 1};
1062 var k2 = {key: 2};
1063 oneAndTwo.set(k1, 1);
1064 oneAndTwo.set(k2, 2);
1065
1066
1067 function TestSetConstructor(ctor) {
1068   var s = new ctor(null);
1069   assertSize(0, s);
1070
1071   s = new ctor(undefined);
1072   assertSize(0, s);
1073
1074   // No @@iterator
1075   assertThrows(function() {
1076     new ctor({});
1077   }, TypeError);
1078   assertThrows(function() {
1079     new ctor(true);
1080   }, TypeError);
1081
1082   // @@iterator not callable
1083   assertThrows(function() {
1084     var object = {};
1085     object[Symbol.iterator] = 42;
1086     new ctor(object);
1087   }, TypeError);
1088
1089   // @@iterator result not object
1090   assertThrows(function() {
1091     var object = {};
1092     object[Symbol.iterator] = function() {
1093       return 42;
1094     };
1095     new ctor(object);
1096   }, TypeError);
1097
1098   var s2 = new Set();
1099   s2.add(k0);
1100   s2.add(k1);
1101   s2.add(k2);
1102   s = new ctor(s2.values());
1103   assertSize(3, s);
1104   assertTrue(s.has(k0));
1105   assertTrue(s.has(k1));
1106   assertTrue(s.has(k2));
1107 }
1108 TestSetConstructor(Set);
1109 TestSetConstructor(WeakSet);
1110
1111
1112 function TestSetConstructorAddNotCallable(ctor) {
1113   var originalPrototypeAdd = ctor.prototype.add;
1114   assertThrows(function() {
1115     ctor.prototype.add = 42;
1116     new ctor(oneAndTwo.values());
1117   }, TypeError);
1118   ctor.prototype.add = originalPrototypeAdd;
1119 }
1120 TestSetConstructorAddNotCallable(Set);
1121 TestSetConstructorAddNotCallable(WeakSet);
1122
1123
1124 function TestSetConstructorGetAddOnce(ctor) {
1125   var originalPrototypeAdd = ctor.prototype.add;
1126   var getAddCount = 0;
1127   Object.defineProperty(ctor.prototype, 'add', {
1128     get: function() {
1129       getAddCount++;
1130       return function() {};
1131     }
1132   });
1133   var s = new ctor(oneAndTwo.values());
1134   assertEquals(1, getAddCount);
1135   assertSize(0, s);
1136   Object.defineProperty(ctor.prototype, 'add', {
1137     value: originalPrototypeAdd,
1138     writable: true
1139   });
1140 }
1141 TestSetConstructorGetAddOnce(Set);
1142 TestSetConstructorGetAddOnce(WeakSet);
1143
1144
1145 function TestSetConstructorAddReplaced(ctor) {
1146   var originalPrototypeAdd = ctor.prototype.add;
1147   var addCount = 0;
1148   ctor.prototype.add = function(value) {
1149     addCount++;
1150     originalPrototypeAdd.call(this, value);
1151     ctor.prototype.add = null;
1152   };
1153   var s = new ctor(oneAndTwo.keys());
1154   assertEquals(2, addCount);
1155   assertSize(2, s);
1156   ctor.prototype.add = originalPrototypeAdd;
1157 }
1158 TestSetConstructorAddReplaced(Set);
1159 TestSetConstructorAddReplaced(WeakSet);
1160
1161
1162 function TestSetConstructorOrderOfDoneValue(ctor) {
1163   var valueCount = 0, doneCount = 0;
1164   var iterator = {
1165     next: function() {
1166       return {
1167         get value() {
1168           valueCount++;
1169         },
1170         get done() {
1171           doneCount++;
1172           throw new Error();
1173         }
1174       };
1175     }
1176   };
1177   iterator[Symbol.iterator] = function() {
1178     return this;
1179   };
1180   assertThrows(function() {
1181     new ctor(iterator);
1182   });
1183   assertEquals(1, doneCount);
1184   assertEquals(0, valueCount);
1185 }
1186 TestSetConstructorOrderOfDoneValue(Set);
1187 TestSetConstructorOrderOfDoneValue(WeakSet);
1188
1189
1190 function TestSetConstructorNextNotAnObject(ctor) {
1191   var iterator = {
1192     next: function() {
1193       return 'abc';
1194     }
1195   };
1196   iterator[Symbol.iterator] = function() {
1197     return this;
1198   };
1199   assertThrows(function() {
1200     new ctor(iterator);
1201   }, TypeError);
1202 }
1203 TestSetConstructorNextNotAnObject(Set);
1204 TestSetConstructorNextNotAnObject(WeakSet);
1205
1206
1207 (function TestWeakSetConstructorNonObjectKeys() {
1208   assertThrows(function() {
1209     new WeakSet([1]);
1210   }, TypeError);
1211 })();
1212
1213
1214 function TestSetConstructorIterableValue(ctor) {
1215   'use strict';
1216   // Strict mode is required to prevent implicit wrapping in the getter.
1217   Object.defineProperty(Number.prototype, Symbol.iterator, {
1218     get: function() {
1219       assertEquals('object', typeof this);
1220       return function() {
1221         return oneAndTwo.keys();
1222       };
1223     },
1224     configurable: true
1225   });
1226
1227   var set = new ctor(42);
1228   assertSize(2, set);
1229   assertTrue(set.has(k1));
1230   assertTrue(set.has(k2));
1231
1232   delete Number.prototype[Symbol.iterator];
1233 }
1234 TestSetConstructorIterableValue(Set);
1235 TestSetConstructorIterableValue(WeakSet);
1236
1237
1238 (function TestSetConstructorStringValue() {
1239   var s = new Set('abc');
1240   assertSize(3, s);
1241   assertTrue(s.has('a'));
1242   assertTrue(s.has('b'));
1243   assertTrue(s.has('c'));
1244 })();
1245
1246
1247 function TestMapConstructor(ctor) {
1248   var m = new ctor(null);
1249   assertSize(0, m);
1250
1251   m = new ctor(undefined);
1252   assertSize(0, m);
1253
1254   // No @@iterator
1255   assertThrows(function() {
1256     new ctor({});
1257   }, TypeError);
1258   assertThrows(function() {
1259     new ctor(true);
1260   }, TypeError);
1261
1262   // @@iterator not callable
1263   assertThrows(function() {
1264     var object = {};
1265     object[Symbol.iterator] = 42;
1266     new ctor(object);
1267   }, TypeError);
1268
1269   // @@iterator result not object
1270   assertThrows(function() {
1271     var object = {};
1272     object[Symbol.iterator] = function() {
1273       return 42;
1274     };
1275     new ctor(object);
1276   }, TypeError);
1277
1278   var m2 = new Map();
1279   m2.set(k0, 'a');
1280   m2.set(k1, 'b');
1281   m2.set(k2, 'c');
1282   m = new ctor(m2.entries());
1283   assertSize(3, m);
1284   assertEquals('a', m.get(k0));
1285   assertEquals('b', m.get(k1));
1286   assertEquals('c', m.get(k2));
1287 }
1288 TestMapConstructor(Map);
1289 TestMapConstructor(WeakMap);
1290
1291
1292 function TestMapConstructorSetNotCallable(ctor) {
1293   var originalPrototypeSet = ctor.prototype.set;
1294   assertThrows(function() {
1295     ctor.prototype.set = 42;
1296     new ctor(oneAndTwo.entries());
1297   }, TypeError);
1298   ctor.prototype.set = originalPrototypeSet;
1299 }
1300 TestMapConstructorSetNotCallable(Map);
1301 TestMapConstructorSetNotCallable(WeakMap);
1302
1303
1304 function TestMapConstructorGetAddOnce(ctor) {
1305   var originalPrototypeSet = ctor.prototype.set;
1306   var getSetCount = 0;
1307   Object.defineProperty(ctor.prototype, 'set', {
1308     get: function() {
1309       getSetCount++;
1310       return function() {};
1311     }
1312   });
1313   var m = new ctor(oneAndTwo.entries());
1314   assertEquals(1, getSetCount);
1315   assertSize(0, m);
1316   Object.defineProperty(ctor.prototype, 'set', {
1317     value: originalPrototypeSet,
1318     writable: true
1319   });
1320 }
1321 TestMapConstructorGetAddOnce(Map);
1322 TestMapConstructorGetAddOnce(WeakMap);
1323
1324
1325 function TestMapConstructorSetReplaced(ctor) {
1326   var originalPrototypeSet = ctor.prototype.set;
1327   var setCount = 0;
1328   ctor.prototype.set = function(key, value) {
1329     setCount++;
1330     originalPrototypeSet.call(this, key, value);
1331     ctor.prototype.set = null;
1332   };
1333   var m = new ctor(oneAndTwo.entries());
1334   assertEquals(2, setCount);
1335   assertSize(2, m);
1336   ctor.prototype.set = originalPrototypeSet;
1337 }
1338 TestMapConstructorSetReplaced(Map);
1339 TestMapConstructorSetReplaced(WeakMap);
1340
1341
1342 function TestMapConstructorOrderOfDoneValue(ctor) {
1343   var valueCount = 0, doneCount = 0;
1344   function FakeError() {}
1345   var iterator = {
1346     next: function() {
1347       return {
1348         get value() {
1349           valueCount++;
1350         },
1351         get done() {
1352           doneCount++;
1353           throw new FakeError();
1354         }
1355       };
1356     }
1357   };
1358   iterator[Symbol.iterator] = function() {
1359     return this;
1360   };
1361   assertThrows(function() {
1362     new ctor(iterator);
1363   }, FakeError);
1364   assertEquals(1, doneCount);
1365   assertEquals(0, valueCount);
1366 }
1367 TestMapConstructorOrderOfDoneValue(Map);
1368 TestMapConstructorOrderOfDoneValue(WeakMap);
1369
1370
1371 function TestMapConstructorNextNotAnObject(ctor) {
1372   var iterator = {
1373     next: function() {
1374       return 'abc';
1375     }
1376   };
1377   iterator[Symbol.iterator] = function() {
1378     return this;
1379   };
1380   assertThrows(function() {
1381     new ctor(iterator);
1382   }, TypeError);
1383 }
1384 TestMapConstructorNextNotAnObject(Map);
1385 TestMapConstructorNextNotAnObject(WeakMap);
1386
1387
1388 function TestMapConstructorIteratorNotObjectValues(ctor) {
1389   assertThrows(function() {
1390     new ctor(oneAndTwo.values());
1391   }, TypeError);
1392 }
1393 TestMapConstructorIteratorNotObjectValues(Map);
1394 TestMapConstructorIteratorNotObjectValues(WeakMap);
1395
1396
1397 (function TestWeakMapConstructorNonObjectKeys() {
1398   assertThrows(function() {
1399     new WeakMap([[1, 2]])
1400   }, TypeError);
1401 })();
1402
1403
1404 function TestMapConstructorIterableValue(ctor) {
1405   'use strict';
1406   // Strict mode is required to prevent implicit wrapping in the getter.
1407   Object.defineProperty(Number.prototype, Symbol.iterator, {
1408     get: function() {
1409       assertEquals('object', typeof this);
1410       return function() {
1411         return oneAndTwo.entries();
1412       };
1413     },
1414     configurable: true
1415   });
1416
1417   var map = new ctor(42);
1418   assertSize(2, map);
1419   assertEquals(1, map.get(k1));
1420   assertEquals(2, map.get(k2));
1421
1422   delete Number.prototype[Symbol.iterator];
1423 }
1424 TestMapConstructorIterableValue(Map);
1425 TestMapConstructorIterableValue(WeakMap);
1426
1427 function TestCollectionToString(C) {
1428   assertEquals("[object " + C.name + "]",
1429       Object.prototype.toString.call(new C()));
1430 }
1431 TestCollectionToString(Map);
1432 TestCollectionToString(Set);
1433 TestCollectionToString(WeakMap);
1434 TestCollectionToString(WeakSet);