Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / test / mjsunit / harmony / generators-iteration.js
1 // Copyright 2013 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-generators --expose-gc
29
30 // Test generator iteration.
31
32 var GeneratorFunction = (function*(){yield 1;}).__proto__.constructor;
33
34 function assertIteratorResult(value, done, result) {
35   assertEquals({ value: value, done: done}, result);
36 }
37
38 function assertIteratorIsClosed(iter) {
39   assertIteratorResult(undefined, true, iter.next());
40   assertDoesNotThrow(function() { iter.next(); });
41 }
42
43 function assertThrownIteratorIsClosed(iter) {
44   // TODO(yusukesuzuki): Since status of a thrown generator is "executing",
45   // following tests are failed.
46   // https://code.google.com/p/v8/issues/detail?id=3096
47   // assertIteratorIsClosed(iter);
48 }
49
50 function TestGeneratorResultPrototype() {
51   function* g() { yield 1; }
52   var iter = g();
53   var result = iter.next();
54
55   assertSame(Object.prototype, Object.getPrototypeOf(result));
56   property_names = Object.getOwnPropertyNames(result);
57   property_names.sort();
58   assertEquals(["done", "value"], property_names);
59   assertIteratorResult(1, false, result);
60 }
61 TestGeneratorResultPrototype()
62
63 function TestGenerator(g, expected_values_for_next,
64                        send_val, expected_values_for_send) {
65   function testNext(thunk) {
66     var iter = thunk();
67     for (var i = 0; i < expected_values_for_next.length; i++) {
68       var v1 = expected_values_for_next[i];
69       var v2 = i == expected_values_for_next.length - 1;
70       // var v3 = iter.next();
71       assertIteratorResult(v1, v2, iter.next());
72     }
73     assertIteratorIsClosed(iter);
74   }
75   function testSend(thunk) {
76     var iter = thunk();
77     for (var i = 0; i < expected_values_for_send.length; i++) {
78       assertIteratorResult(expected_values_for_send[i],
79                            i == expected_values_for_send.length - 1,
80                            iter.next(send_val));
81     }
82     assertIteratorIsClosed(iter);
83   }
84   function testThrow(thunk) {
85     for (var i = 0; i < expected_values_for_next.length; i++) {
86       var iter = thunk();
87       for (var j = 0; j < i; j++) {
88         assertIteratorResult(expected_values_for_next[j],
89                              j == expected_values_for_next.length - 1,
90                              iter.next());
91       }
92       function Sentinel() {}
93       assertThrows(function () { iter.throw(new Sentinel); }, Sentinel);
94       assertThrownIteratorIsClosed(iter);
95     }
96   }
97
98   testNext(g);
99   testSend(g);
100   testThrow(g);
101
102   testNext(function*() { return yield* g(); });
103   testSend(function*() { return yield* g(); });
104   testThrow(function*() { return yield* g(); });
105
106   if (g instanceof GeneratorFunction) {
107     testNext(function() { return new g(); });
108     testSend(function() { return new g(); });
109     testThrow(function() { return new g(); });
110   }
111 }
112
113 TestGenerator(function* g1() { },
114               [undefined],
115               "foo",
116               [undefined]);
117
118 TestGenerator(function* g2() { yield 1; },
119               [1, undefined],
120               "foo",
121               [1, undefined]);
122
123 TestGenerator(function* g3() { yield 1; yield 2; },
124               [1, 2, undefined],
125               "foo",
126               [1, 2, undefined]);
127
128 TestGenerator(function* g4() { yield 1; yield 2; return 3; },
129               [1, 2, 3],
130               "foo",
131               [1, 2, 3]);
132
133 TestGenerator(function* g5() { return 1; },
134               [1],
135              "foo",
136               [1]);
137
138 TestGenerator(function* g6() { var x = yield 1; return x; },
139               [1, undefined],
140               "foo",
141               [1, "foo"]);
142
143 TestGenerator(function* g7() { var x = yield 1; yield 2; return x; },
144               [1, 2, undefined],
145               "foo",
146               [1, 2, "foo"]);
147
148 TestGenerator(function* g8() { for (var x = 0; x < 4; x++) { yield x; } },
149               [0, 1, 2, 3, undefined],
150               "foo",
151               [0, 1, 2, 3, undefined]);
152
153 // Generator with arguments.
154 TestGenerator(
155     function g9() {
156       return (function*(a, b, c, d) {
157         yield a; yield b; yield c; yield d;
158       })("fee", "fi", "fo", "fum");
159     },
160     ["fee", "fi", "fo", "fum", undefined],
161     "foo",
162     ["fee", "fi", "fo", "fum", undefined]);
163
164 // Too few arguments.
165 TestGenerator(
166     function g10() {
167       return (function*(a, b, c, d) {
168         yield a; yield b; yield c; yield d;
169       })("fee", "fi");
170     },
171     ["fee", "fi", undefined, undefined, undefined],
172     "foo",
173     ["fee", "fi", undefined, undefined, undefined]);
174
175 // Too many arguments.
176 TestGenerator(
177     function g11() {
178       return (function*(a, b, c, d) {
179         yield a; yield b; yield c; yield d;
180       })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman");
181     },
182     ["fee", "fi", "fo", "fum", undefined],
183     "foo",
184     ["fee", "fi", "fo", "fum", undefined]);
185
186 // The arguments object.
187 TestGenerator(
188     function g12() {
189       return (function*(a, b, c, d) {
190         for (var i = 0; i < arguments.length; i++) {
191           yield arguments[i];
192         }
193       })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman");
194     },
195     ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman",
196      undefined],
197     "foo",
198     ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman",
199      undefined]);
200
201 // Access to captured free variables.
202 TestGenerator(
203     function g13() {
204       return (function(a, b, c, d) {
205         return (function*() {
206           yield a; yield b; yield c; yield d;
207         })();
208       })("fee", "fi", "fo", "fum");
209     },
210     ["fee", "fi", "fo", "fum", undefined],
211     "foo",
212     ["fee", "fi", "fo", "fum", undefined]);
213
214 // Abusing the arguments object.
215 TestGenerator(
216     function g14() {
217       return (function*(a, b, c, d) {
218         arguments[0] = "Be he live";
219         arguments[1] = "or be he dead";
220         arguments[2] = "I'll grind his bones";
221         arguments[3] = "to make my bread";
222         yield a; yield b; yield c; yield d;
223       })("fee", "fi", "fo", "fum");
224     },
225     ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread",
226      undefined],
227     "foo",
228     ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread",
229      undefined]);
230
231 // Abusing the arguments object: strict mode.
232 TestGenerator(
233     function g15() {
234       return (function*(a, b, c, d) {
235         "use strict";
236         arguments[0] = "Be he live";
237         arguments[1] = "or be he dead";
238         arguments[2] = "I'll grind his bones";
239         arguments[3] = "to make my bread";
240         yield a; yield b; yield c; yield d;
241       })("fee", "fi", "fo", "fum");
242     },
243     ["fee", "fi", "fo", "fum", undefined],
244     "foo",
245     ["fee", "fi", "fo", "fum", undefined]);
246
247 // GC.
248 TestGenerator(function* g16() { yield "baz"; gc(); yield "qux"; },
249               ["baz", "qux", undefined],
250               "foo",
251               ["baz", "qux", undefined]);
252
253 // Receivers.
254 TestGenerator(
255     function g17() {
256       function* g() { yield this.x; yield this.y; }
257       var o = { start: g, x: 1, y: 2 };
258       return o.start();
259     },
260     [1, 2, undefined],
261     "foo",
262     [1, 2, undefined]);
263
264 TestGenerator(
265     function g18() {
266       function* g() { yield this.x; yield this.y; }
267       var iter = new g;
268       iter.x = 1;
269       iter.y = 2;
270       return iter;
271     },
272     [1, 2, undefined],
273     "foo",
274     [1, 2, undefined]);
275
276 TestGenerator(
277     function* g19() {
278       var x = 1;
279       yield x;
280       with({x:2}) { yield x; }
281       yield x;
282     },
283     [1, 2, 1, undefined],
284     "foo",
285     [1, 2, 1, undefined]);
286
287 TestGenerator(
288     function* g20() { yield (1 + (yield 2) + 3); },
289     [2, NaN, undefined],
290     "foo",
291     [2, "1foo3", undefined]);
292
293 TestGenerator(
294     function* g21() { return (1 + (yield 2) + 3); },
295     [2, NaN],
296     "foo",
297     [2, "1foo3"]);
298
299 TestGenerator(
300     function* g22() { yield (1 + (yield 2) + 3); yield (4 + (yield 5) + 6); },
301     [2, NaN, 5, NaN, undefined],
302     "foo",
303     [2, "1foo3", 5, "4foo6", undefined]);
304
305 TestGenerator(
306     function* g23() {
307       return (yield (1 + (yield 2) + 3)) + (yield (4 + (yield 5) + 6));
308     },
309     [2, NaN, 5, NaN, NaN],
310     "foo",
311     [2, "1foo3", 5, "4foo6", "foofoo"]);
312
313 // Rewind a try context with and without operands on the stack.
314 TestGenerator(
315     function* g24() {
316       try {
317         return (yield (1 + (yield 2) + 3)) + (yield (4 + (yield 5) + 6));
318       } catch (e) {
319         throw e;
320       }
321     },
322     [2, NaN, 5, NaN, NaN],
323     "foo",
324     [2, "1foo3", 5, "4foo6", "foofoo"]);
325
326 // Yielding in a catch context, with and without operands on the stack.
327 TestGenerator(
328     function* g25() {
329       try {
330         throw (yield (1 + (yield 2) + 3))
331       } catch (e) {
332         if (typeof e == 'object') throw e;
333         return e + (yield (4 + (yield 5) + 6));
334       }
335     },
336     [2, NaN, 5, NaN, NaN],
337     "foo",
338     [2, "1foo3", 5, "4foo6", "foofoo"]);
339
340 // Yield with no arguments yields undefined.
341 TestGenerator(
342     function* g26() { return yield yield },
343     [undefined, undefined, undefined],
344     "foo",
345     [undefined, "foo", "foo"]);
346
347 // A newline causes the parser to stop looking for an argument to yield.
348 TestGenerator(
349     function* g27() {
350       yield
351       3
352       return
353     },
354     [undefined, undefined],
355     "foo",
356     [undefined, undefined]);
357
358 // TODO(wingo): We should use TestGenerator for these, except that
359 // currently yield* will unconditionally propagate a throw() to the
360 // delegate iterator, which fails for these iterators that don't have
361 // throw().  See http://code.google.com/p/v8/issues/detail?id=3484.
362 (function() {
363     function* g28() {
364       yield* [1, 2, 3];
365     }
366     var iter = g28();
367     assertIteratorResult(1, false, iter.next());
368     assertIteratorResult(2, false, iter.next());
369     assertIteratorResult(3, false, iter.next());
370     assertIteratorResult(undefined, true, iter.next());
371 })();
372
373 (function() {
374     function* g29() {
375       yield* "abc";
376     }
377     var iter = g29();
378     assertIteratorResult("a", false, iter.next());
379     assertIteratorResult("b", false, iter.next());
380     assertIteratorResult("c", false, iter.next());
381     assertIteratorResult(undefined, true, iter.next());
382 })();
383
384 // Generator function instances.
385 TestGenerator(GeneratorFunction(),
386               [undefined],
387               "foo",
388               [undefined]);
389
390 TestGenerator(new GeneratorFunction(),
391               [undefined],
392               "foo",
393               [undefined]);
394
395 TestGenerator(GeneratorFunction('yield 1;'),
396               [1, undefined],
397               "foo",
398               [1, undefined]);
399
400 TestGenerator(
401     function() { return GeneratorFunction('x', 'y', 'yield x + y;')(1, 2) },
402     [3, undefined],
403     "foo",
404     [3, undefined]);
405
406 // Access to this with formal arguments.
407 TestGenerator(
408     function () {
409       return ({ x: 42, g: function* (a) { yield this.x } }).g(0);
410     },
411     [42, undefined],
412     "foo",
413     [42, undefined]);
414
415 // Test that yield* re-yields received results without re-boxing.
416 function TestDelegatingYield() {
417   function results(results) {
418     var i = 0;
419     function next() {
420       return results[i++];
421     }
422     var iter = { next: next };
423     var ret = {};
424     ret[Symbol.iterator] = function() { return iter; };
425     return ret;
426   }
427   function* yield_results(expected) {
428     return yield* results(expected);
429   }
430   function collect_results(iterable) {
431     var iter = iterable[Symbol.iterator]();
432     var ret = [];
433     var result;
434     do {
435       result = iter.next();
436       ret.push(result);
437     } while (!result.done);
438     return ret;
439   }
440   // We have to put a full result for the end, because the return will re-box.
441   var expected = [{value: 1}, 13, "foo", {value: 34, done: true}];
442
443   // Sanity check.
444   assertEquals(expected, collect_results(results(expected)));
445   assertEquals(expected, collect_results(yield_results(expected)));
446 }
447 TestDelegatingYield();
448
449 function TestTryCatch(instantiate) {
450   function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; }
451   function Sentinel() {}
452
453   function Test1(iter) {
454     assertIteratorResult(1, false, iter.next());
455     assertIteratorResult(2, false, iter.next());
456     assertIteratorResult(3, false, iter.next());
457     assertIteratorIsClosed(iter);
458   }
459   Test1(instantiate(g));
460
461   function Test2(iter) {
462     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
463     assertThrownIteratorIsClosed(iter);
464   }
465   Test2(instantiate(g));
466
467   function Test3(iter) {
468     assertIteratorResult(1, false, iter.next());
469     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
470     assertThrownIteratorIsClosed(iter);
471   }
472   Test3(instantiate(g));
473
474   function Test4(iter) {
475     assertIteratorResult(1, false, iter.next());
476     assertIteratorResult(2, false, iter.next());
477     var exn = new Sentinel;
478     assertIteratorResult(exn, false, iter.throw(exn));
479     assertIteratorResult(3, false, iter.next());
480     assertIteratorIsClosed(iter);
481   }
482   Test4(instantiate(g));
483
484   function Test5(iter) {
485     assertIteratorResult(1, false, iter.next());
486     assertIteratorResult(2, false, iter.next());
487     var exn = new Sentinel;
488     assertIteratorResult(exn, false, iter.throw(exn));
489     assertIteratorResult(3, false, iter.next());
490     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
491     assertThrownIteratorIsClosed(iter);
492   }
493   Test5(instantiate(g));
494
495   function Test6(iter) {
496     assertIteratorResult(1, false, iter.next());
497     assertIteratorResult(2, false, iter.next());
498     var exn = new Sentinel;
499     assertIteratorResult(exn, false, iter.throw(exn));
500     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
501     assertThrownIteratorIsClosed(iter);
502   }
503   Test6(instantiate(g));
504
505   function Test7(iter) {
506     assertIteratorResult(1, false, iter.next());
507     assertIteratorResult(2, false, iter.next());
508     assertIteratorResult(3, false, iter.next());
509     assertIteratorIsClosed(iter);
510   }
511   Test7(instantiate(g));
512 }
513 TestTryCatch(function (g) { return g(); });
514 TestTryCatch(function* (g) { return yield* g(); });
515
516 function TestTryFinally(instantiate) {
517   function* g() { yield 1; try { yield 2; } finally { yield 3; } yield 4; }
518   function Sentinel() {}
519   function Sentinel2() {}
520
521   function Test1(iter) {
522     assertIteratorResult(1, false, iter.next());
523     assertIteratorResult(2, false, iter.next());
524     assertIteratorResult(3, false, iter.next());
525     assertIteratorResult(4, false, iter.next());
526     assertIteratorIsClosed(iter);
527   }
528   Test1(instantiate(g));
529
530   function Test2(iter) {
531     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
532     assertThrownIteratorIsClosed(iter);
533   }
534   Test2(instantiate(g));
535
536   function Test3(iter) {
537     assertIteratorResult(1, false, iter.next());
538     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
539     assertThrownIteratorIsClosed(iter);
540   }
541   Test3(instantiate(g));
542
543   function Test4(iter) {
544     assertIteratorResult(1, false, iter.next());
545     assertIteratorResult(2, false, iter.next());
546     assertIteratorResult(3, false, iter.throw(new Sentinel));
547     assertThrows(function() { iter.next(); }, Sentinel);
548     assertThrownIteratorIsClosed(iter);
549   }
550   Test4(instantiate(g));
551
552   function Test5(iter) {
553     assertIteratorResult(1, false, iter.next());
554     assertIteratorResult(2, false, iter.next());
555     assertIteratorResult(3, false, iter.throw(new Sentinel));
556     assertThrows(function() { iter.throw(new Sentinel2); }, Sentinel2);
557     assertThrownIteratorIsClosed(iter);
558   }
559   Test5(instantiate(g));
560
561   function Test6(iter) {
562     assertIteratorResult(1, false, iter.next());
563     assertIteratorResult(2, false, iter.next());
564     assertIteratorResult(3, false, iter.next());
565     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
566     assertThrownIteratorIsClosed(iter);
567   }
568   Test6(instantiate(g));
569
570   function Test7(iter) {
571     assertIteratorResult(1, false, iter.next());
572     assertIteratorResult(2, false, iter.next());
573     assertIteratorResult(3, false, iter.next());
574     assertIteratorResult(4, false, iter.next());
575     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
576     assertThrownIteratorIsClosed(iter);
577   }
578   Test7(instantiate(g));
579
580   function Test8(iter) {
581     assertIteratorResult(1, false, iter.next());
582     assertIteratorResult(2, false, iter.next());
583     assertIteratorResult(3, false, iter.next());
584     assertIteratorResult(4, false, iter.next());
585     assertIteratorIsClosed(iter);
586   }
587   Test8(instantiate(g));
588 }
589 TestTryFinally(function (g) { return g(); });
590 TestTryFinally(function* (g) { return yield* g(); });
591
592 function TestNestedTry(instantiate) {
593   function* g() {
594     try {
595       yield 1;
596       try { yield 2; } catch (e) { yield e; }
597       yield 3;
598     } finally {
599       yield 4;
600     }
601     yield 5;
602   }
603   function Sentinel() {}
604   function Sentinel2() {}
605
606   function Test1(iter) {
607     assertIteratorResult(1, false, iter.next());
608     assertIteratorResult(2, false, iter.next());
609     assertIteratorResult(3, false, iter.next());
610     assertIteratorResult(4, false, iter.next());
611     assertIteratorResult(5, false, iter.next());
612     assertIteratorIsClosed(iter);
613   }
614   Test1(instantiate(g));
615
616   function Test2(iter) {
617     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
618     assertThrownIteratorIsClosed(iter);
619   }
620   Test2(instantiate(g));
621
622   function Test3(iter) {
623     assertIteratorResult(1, false, iter.next());
624     assertIteratorResult(4, false, iter.throw(new Sentinel));
625     assertThrows(function() { iter.next(); }, Sentinel);
626     assertThrownIteratorIsClosed(iter);
627   }
628   Test3(instantiate(g));
629
630   function Test4(iter) {
631     assertIteratorResult(1, false, iter.next());
632     assertIteratorResult(4, false, iter.throw(new Sentinel));
633     assertThrows(function() { iter.throw(new Sentinel2); }, Sentinel2);
634     assertThrownIteratorIsClosed(iter);
635   }
636   Test4(instantiate(g));
637
638   function Test5(iter) {
639     assertIteratorResult(1, false, iter.next());
640     assertIteratorResult(2, false, iter.next());
641     var exn = new Sentinel;
642     assertIteratorResult(exn, false, iter.throw(exn));
643     assertIteratorResult(3, false, iter.next());
644     assertIteratorResult(4, false, iter.next());
645     assertIteratorResult(5, false, iter.next());
646     assertIteratorIsClosed(iter);
647   }
648   Test5(instantiate(g));
649
650   function Test6(iter) {
651     assertIteratorResult(1, false, iter.next());
652     assertIteratorResult(2, false, iter.next());
653     var exn = new Sentinel;
654     assertIteratorResult(exn, false, iter.throw(exn));
655     assertIteratorResult(4, false, iter.throw(new Sentinel2));
656     assertThrows(function() { iter.next(); }, Sentinel2);
657     assertThrownIteratorIsClosed(iter);
658   }
659   Test6(instantiate(g));
660
661   function Test7(iter) {
662     assertIteratorResult(1, false, iter.next());
663     assertIteratorResult(2, false, iter.next());
664     var exn = new Sentinel;
665     assertIteratorResult(exn, false, iter.throw(exn));
666     assertIteratorResult(3, false, iter.next());
667     assertIteratorResult(4, false, iter.throw(new Sentinel2));
668     assertThrows(function() { iter.next(); }, Sentinel2);
669     assertThrownIteratorIsClosed(iter);
670   }
671   Test7(instantiate(g));
672
673   // That's probably enough.
674 }
675 TestNestedTry(function (g) { return g(); });
676 TestNestedTry(function* (g) { return yield* g(); });
677
678 function TestRecursion() {
679   function TestNextRecursion() {
680     function* g() { yield iter.next(); }
681     var iter = g();
682     return iter.next();
683   }
684   function TestSendRecursion() {
685     function* g() { yield iter.next(42); }
686     var iter = g();
687     return iter.next();
688   }
689   function TestThrowRecursion() {
690     function* g() { yield iter.throw(1); }
691     var iter = g();
692     return iter.next();
693   }
694   assertThrows(TestNextRecursion, Error);
695   assertThrows(TestSendRecursion, Error);
696   assertThrows(TestThrowRecursion, Error);
697 }
698 TestRecursion();