blob: eb4e51e9666a455dbea716701d6390ef0c88321e [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdochc5610432016-08-08 18:44:38 +01005// Flags: --ignition-generators --harmony-do-expressions
6// Flags: --allow-natives-syntax
7
8
9function MaybeOptimizeOrDeoptimize(f) {
10 let x = Math.random(); // --random-seed makes this deterministic
11 if (x <= 0.33) {
12 %OptimizeFunctionOnNextCall(f);
13 } else if (x <= 0.66) {
14 %DeoptimizeFunction(f);
15 }
16}
17
18function Next(generator, ...args) {
19 MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
20 return generator.next(...args);
21}
22
23function Return(generator, ...args) {
24 MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
25 return generator.return(...args);
26}
27
28function Throw(generator, ...args) {
29 MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
30 return generator.throw(...args);
31}
32
Ben Murdoch097c5b22016-05-18 11:27:45 +010033
34{ // yield in try-catch
35
36 let g = function*() {
37 try {yield 1} catch (error) {assertEquals("caught", error)}
38 };
39
Ben Murdochc5610432016-08-08 18:44:38 +010040 assertThrowsEquals(() => Throw(g(), "not caught"), "not caught");
Ben Murdoch097c5b22016-05-18 11:27:45 +010041
42 {
43 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +010044 assertEquals({value: 1, done: false}, Next(x));
45 assertEquals({value: undefined, done: true}, Throw(x, "caught"));
Ben Murdoch097c5b22016-05-18 11:27:45 +010046 }
47
48 {
49 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +010050 assertEquals({value: 1, done: false}, Next(x));
51 assertEquals({value: undefined, done: true}, Next(x));
52 assertThrowsEquals(() => Throw(x, "not caught"), "not caught");
Ben Murdoch097c5b22016-05-18 11:27:45 +010053 }
54}
55
56
57{ // return that doesn't close
58 let g = function*() { try {return 42} finally {yield 43} };
59
60 {
61 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +010062 assertEquals({value: 43, done: false}, Next(x));
63 assertEquals({value: 42, done: true}, Next(x));
Ben Murdoch097c5b22016-05-18 11:27:45 +010064 }
65}
66
67
68{ // return that doesn't close
69 let x;
Ben Murdochc5610432016-08-08 18:44:38 +010070 let g = function*() { try {return 42} finally {Throw(x, 666)} };
Ben Murdoch097c5b22016-05-18 11:27:45 +010071
72 {
73 x = g();
Ben Murdochc5610432016-08-08 18:44:38 +010074 assertThrows(() => Next(x), TypeError); // still executing
Ben Murdoch097c5b22016-05-18 11:27:45 +010075 }
76}
77
78
79{ // yield in try-finally, finally clause performs return
80
81 let g = function*() { try {yield 42} finally {return 13} };
82
83 { // "return" closes at suspendedStart
84 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +010085 assertEquals({value: 666, done: true}, Return(x, 666));
86 assertEquals({value: undefined, done: true}, Next(x, 42));
87 assertThrowsEquals(() => Throw(x, 43), 43);
88 assertEquals({value: 42, done: true}, Return(x, 42));
Ben Murdoch097c5b22016-05-18 11:27:45 +010089 }
90
91 { // "throw" closes at suspendedStart
92 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +010093 assertThrowsEquals(() => Throw(x, 666), 666);
94 assertEquals({value: undefined, done: true}, Next(x, 42));
95 assertEquals({value: 43, done: true}, Return(x, 43));
96 assertThrowsEquals(() => Throw(x, 44), 44);
Ben Murdoch097c5b22016-05-18 11:27:45 +010097 }
98
99 { // "next" closes at suspendedYield
100 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100101 assertEquals({value: 42, done: false}, Next(x));
102 assertEquals({value: 13, done: true}, Next(x, 666));
103 assertEquals({value: undefined, done: true}, Next(x, 666));
104 assertThrowsEquals(() => Throw(x, 666), 666);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100105 }
106
107 { // "return" closes at suspendedYield
108 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100109 assertEquals({value: 42, done: false}, Next(x));
110 assertEquals({value: 13, done: true}, Return(x, 666));
111 assertEquals({value: undefined, done: true}, Next(x, 666));
112 assertEquals({value: 666, done: true}, Return(x, 666));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100113 }
114
115 { // "throw" closes at suspendedYield
116 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100117 assertEquals({value: 42, done: false}, Next(x));
118 assertEquals({value: 13, done: true}, Throw(x, 666));
119 assertThrowsEquals(() => Throw(x, 666), 666);
120 assertEquals({value: undefined, done: true}, Next(x, 666));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100121 }
122}
123
124
125{ // yield in try-finally, finally clause doesn't perform return
126
127 let g = function*() { try {yield 42} finally {13} };
128
129 { // "return" closes at suspendedStart
130 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100131 assertEquals({value: 666, done: true}, Return(x, 666));
132 assertEquals({value: undefined, done: true}, Next(x, 42));
133 assertThrowsEquals(() => Throw(x, 43), 43);
134 assertEquals({value: 42, done: true}, Return(x, 42));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100135 }
136
137 { // "throw" closes at suspendedStart
138 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100139 assertThrowsEquals(() => Throw(x, 666), 666);
140 assertEquals({value: undefined, done: true}, Next(x, 42));
141 assertEquals({value: 43, done: true}, Return(x, 43));
142 assertThrowsEquals(() => Throw(x, 44), 44);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100143 }
144
145 { // "next" closes at suspendedYield
146 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100147 assertEquals({value: 42, done: false}, Next(x));
148 assertEquals({value: undefined, done: true}, Next(x, 666));
149 assertEquals({value: undefined, done: true}, Next(x, 666));
150 assertThrowsEquals(() => Throw(x, 666), 666);
151 assertEquals({value: 42, done: true}, Return(x, 42));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100152 }
153
154 { // "return" closes at suspendedYield
155 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100156 assertEquals({value: 42, done: false}, Next(x));
157 assertEquals({value: 666, done: true}, Return(x, 666));
158 assertEquals({value: undefined, done: true}, Next(x, 666));
159 assertThrowsEquals(() => Throw(x, 44), 44);
160 assertEquals({value: 42, done: true}, Return(x, 42));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100161 }
162
163 { // "throw" closes at suspendedYield
164 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100165 assertEquals({value: 42, done: false}, Next(x));
166 assertThrowsEquals(() => Throw(x, 666), 666);
167 assertEquals({value: undefined, done: true}, Next(x, 666));
168 assertThrowsEquals(() => Throw(x, 666), 666);
169 assertEquals({value: 42, done: true}, Return(x, 42));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100170 }
171}
172
173
174{ // yield in try-finally, finally clause yields and performs return
175
176 let g = function*() { try {yield 42} finally {yield 43; return 13} };
177
178 {
179 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100180 assertEquals({value: 42, done: false}, Next(x));
181 assertEquals({value: 43, done: false}, Return(x, 666));
182 assertEquals({value: 13, done: true}, Next(x));
183 assertEquals({value: 666, done: true}, Return(x, 666));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100184 }
185
186 {
187 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100188 assertEquals({value: 666, done: true}, Return(x, 666));
189 assertEquals({value: undefined, done: true}, Next(x));
190 assertEquals({value: 666, done: true}, Return(x, 666));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100191 }
192}
193
194
195{ // yield in try-finally, finally clause yields and doesn't perform return
196
197 let g = function*() { try {yield 42} finally {yield 43; 13} };
198
199 {
200 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100201 assertEquals({value: 42, done: false}, Next(x));
202 assertEquals({value: 43, done: false}, Return(x, 666));
203 assertEquals({value: 666, done: true}, Next(x));
204 assertEquals({value: 5, done: true}, Return(x, 5));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100205 }
206
207 {
208 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100209 assertEquals({value: 666, done: true}, Return(x, 666));
210 assertEquals({value: undefined, done: true}, Next(x));
211 assertEquals({value: 666, done: true}, Return(x, 666));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100212 }
213}
214
215
216{ // yield*, finally clause performs return
217
218 let h = function*() { try {yield 42} finally {yield 43; return 13} };
219 let g = function*() { yield 1; yield yield* h(); };
220
221 {
222 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100223 assertEquals({value: 1, done: false}, Next(x));
224 assertEquals({value: 42, done: false}, Next(x));
225 assertEquals({value: 43, done: false}, Next(x, 666));
226 assertEquals({value: 13, done: false}, Next(x));
227 assertEquals({value: undefined, done: true}, Next(x));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100228 }
229
230 {
231 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100232 assertEquals({value: 1, done: false}, Next(x));
233 assertEquals({value: 42, done: false}, Next(x));
234 assertEquals({value: 43, done: false}, Return(x, 666));
235 assertEquals({value: 13, done: false}, Next(x));
236 assertEquals({value: undefined, done: true}, Next(x));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100237 }
238
239 {
240 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100241 assertEquals({value: 1, done: false}, Next(x));
242 assertEquals({value: 42, done: false}, Next(x));
243 assertEquals({value: 43, done: false}, Throw(x, 666));
244 assertEquals({value: 13, done: false}, Next(x));
245 assertEquals({value: undefined, done: true}, Next(x));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100246 }
247}
248
249
250{ // yield*, finally clause does not perform return
251
252 let h = function*() { try {yield 42} finally {yield 43; 13} };
253 let g = function*() { yield 1; yield yield* h(); };
254
255 {
256 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100257 assertEquals({value: 1, done: false}, Next(x));
258 assertEquals({value: 42, done: false}, Next(x));
259 assertEquals({value: 43, done: false}, Next(x, 666));
260 assertEquals({value: undefined, done: false}, Next(x));
261 assertEquals({value: undefined, done: true}, Next(x));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100262 }
263
264 {
265 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100266 assertEquals({value: 1, done: false}, Next(x));
267 assertEquals({value: 42, done: false}, Next(x));
268 assertEquals({value: 43, done: false}, Return(x, 44));
269 assertEquals({value: 44, done: false}, Next(x));
270 assertEquals({value: undefined, done: true}, Next(x));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100271 }
272
273 {
274 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100275 assertEquals({value: 1, done: false}, Next(x));
276 assertEquals({value: 42, done: false}, Next(x));
277 assertEquals({value: 43, done: false}, Throw(x, 666));
278 assertThrowsEquals(() => Next(x), 666);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100279 }
280}
Ben Murdochda12d292016-06-02 14:46:10 +0100281
282
283{ // yield*, .return argument is final result
284
285 function* inner() {
286 yield 2;
287 }
288
289 function* g() {
290 yield 1;
291 return yield* inner();
292 }
293
294 {
295 let x = g();
Ben Murdochc5610432016-08-08 18:44:38 +0100296 assertEquals({value: 1, done: false}, Next(x));
297 assertEquals({value: 2, done: false}, Next(x));
298 assertEquals({value: 42, done: true}, Return(x, 42));
Ben Murdochda12d292016-06-02 14:46:10 +0100299 }
300}
Ben Murdochc5610432016-08-08 18:44:38 +0100301
302
303// More or less random tests from here on.
304
305
306{
307 function* foo() { }
308 let g = foo();
309 assertEquals({value: undefined, done: true}, Next(g));
310 assertEquals({value: undefined, done: true}, Next(g));
311}
312
313{
314 function* foo() { return new.target }
315 let g = foo();
316 assertEquals({value: undefined, done: true}, Next(g));
317 assertEquals({value: undefined, done: true}, Next(g));
318}
319
320{
321 function* foo() { throw 666; return 42}
322 let g = foo();
323 assertThrowsEquals(() => Next(g), 666);
324 assertEquals({value: undefined, done: true}, Next(g));
325}
326
327{
328 function* foo(a) { return a; }
329 let g = foo(42);
330 assertEquals({value: 42, done: true}, Next(g));
331 assertEquals({value: undefined, done: true}, Next(g));
332}
333
334{
335 function* foo(a) { a.iwashere = true; return a; }
336 let x = {};
337 let g = foo(x);
338 assertEquals({value: {iwashere: true}, done: true}, Next(g));
339 assertEquals({value: undefined, done: true}, Next(g));
340}
341
342{
343 let a = 42;
344 function* foo() { return a; }
345 let g = foo();
346 assertEquals({value: 42, done: true}, Next(g));
347 assertEquals({value: undefined, done: true}, Next(g));
348}
349
350{
351 let a = 40;
352 function* foo(b) { return a + b; }
353 let g = foo(2);
354 assertEquals({value: 42, done: true}, Next(g));
355 assertEquals({value: undefined, done: true}, Next(g));
356}
357
358{
359 let a = 40;
360 function* foo(b) { a--; b++; return a + b; }
361 let g = foo(2);
362 assertEquals({value: 42, done: true}, Next(g));
363 assertEquals({value: undefined, done: true}, Next(g));
364}
365
366{
367 let g;
368 function* foo() { Next(g) }
369 g = foo();
370 assertThrows(() => Next(g), TypeError);
371 assertEquals({value: undefined, done: true}, Next(g));
372}
373
374{
375 function* foo() { yield 2; yield 3; yield 4 }
376 g = foo();
377 assertEquals({value: 2, done: false}, Next(g));
378 assertEquals({value: 3, done: false}, Next(g));
379 assertEquals({value: 4, done: false}, Next(g));
380 assertEquals({value: undefined, done: true}, Next(g));
381 assertEquals({value: undefined, done: true}, Next(g));
382}
383
384
385{
386 function* foo() { yield 2; if (true) { yield 3 }; yield 4 }
387 g = foo();
388 assertEquals({value: 2, done: false}, Next(g));
389 assertEquals({value: 3, done: false}, Next(g));
390 assertEquals({value: 4, done: false}, Next(g));
391 assertEquals({value: undefined, done: true}, Next(g));
392 assertEquals({value: undefined, done: true}, Next(g));
393}
394
395{
396 function* foo() { yield 2; if (true) { yield 3; yield 4 } }
397 g = foo();
398 assertEquals({value: 2, done: false}, Next(g));
399 assertEquals({value: 3, done: false}, Next(g));
400 assertEquals({value: 4, done: false}, Next(g));
401 assertEquals({value: undefined, done: true}, Next(g));
402 assertEquals({value: undefined, done: true}, Next(g));
403}
404
405{
406 function* foo() { yield 2; if (false) { yield 3 }; yield 4 }
407 g = foo();
408 assertEquals({value: 2, done: false}, Next(g));
409 assertEquals({value: 4, done: false}, Next(g));
410 assertEquals({value: undefined, done: true}, Next(g));
411 assertEquals({value: undefined, done: true}, Next(g));
412}
413
414{
415 function* foo() { yield 2; while (true) { yield 3 }; yield 4 }
416 g = foo();
417 assertEquals({value: 2, done: false}, Next(g));
418 assertEquals({value: 3, done: false}, Next(g));
419 assertEquals({value: 3, done: false}, Next(g));
420 assertEquals({value: 3, done: false}, Next(g));
421 assertEquals({value: 3, done: false}, Next(g));
422}
423
424{
425 function* foo() { yield 2; (yield 3) + 42; yield 4 }
426 g = foo();
427 assertEquals({value: 2, done: false}, Next(g));
428 assertEquals({value: 3, done: false}, Next(g));
429 assertEquals({value: 4, done: false}, Next(g));
430}
431
432{
433 function* foo() { yield 2; (do {yield 3}) + 42; yield 4 }
434 g = foo();
435 assertEquals({value: 2, done: false}, Next(g));
436 assertEquals({value: 3, done: false}, Next(g));
437 assertEquals({value: 4, done: false}, Next(g));
438}
439
440{
441 function* foo() { yield 2; return (yield 3) + 42; yield 4 }
442 g = foo();
443 assertEquals({value: 2, done: false}, Next(g));
444 assertEquals({value: 3, done: false}, Next(g));
445 assertEquals({value: 42, done: true}, Next(g, 0));
446 assertEquals({value: undefined, done: true}, Next(g));
447}
448
449{
450 let x = 42;
451 function* foo() {
452 yield x;
453 for (let x in {a: 1, b: 2}) {
454 let i = 2;
455 yield x;
456 yield i;
457 do {
458 yield i;
459 } while (i-- > 0);
460 }
461 yield x;
462 return 5;
463 }
464 g = foo();
465 assertEquals({value: 42, done: false}, Next(g));
466 assertEquals({value: 'a', done: false}, Next(g));
467 assertEquals({value: 2, done: false}, Next(g));
468 assertEquals({value: 2, done: false}, Next(g));
469 assertEquals({value: 1, done: false}, Next(g));
470 assertEquals({value: 0, done: false}, Next(g));
471 assertEquals({value: 'b', done: false}, Next(g));
472 assertEquals({value: 2, done: false}, Next(g));
473 assertEquals({value: 2, done: false}, Next(g));
474 assertEquals({value: 1, done: false}, Next(g));
475 assertEquals({value: 0, done: false}, Next(g));
476 assertEquals({value: 42, done: false}, Next(g));
477 assertEquals({value: 5, done: true}, Next(g));
478}
479
480{
481 let a = 3;
482 function* foo() {
483 let b = 4;
484 yield 1;
485 { let c = 5; yield 2; yield a; yield b; yield c; }
486 }
487 g = foo();
488 assertEquals({value: 1, done: false}, Next(g));
489 assertEquals({value: 2, done: false}, Next(g));
490 assertEquals({value: 3, done: false}, Next(g));
491 assertEquals({value: 4, done: false}, Next(g));
492 assertEquals({value: 5, done: false}, Next(g));
493 assertEquals({value: undefined, done: true}, Next(g));
494}
495
496{
497 function* foo() {
498 yield 42;
499 yield 42;
500 yield 42;
501 yield 42;
502 yield 42;
503 yield 42;
504 yield 42;
505 yield 42;
506 yield 42;
507 yield 42;
508 yield 42;
509 yield 42;
510 yield 42;
511 yield 42;
512 yield 42;
513 yield 42;
514 yield 42;
515 yield 42;
516 yield 42;
517 yield 42;
518 yield 42;
519 yield 42;
520 yield 42;
521 yield 42;
522 yield 42;
523 yield 42;
524 yield 42;
525 yield 42;
526 yield 42;
527 yield 42;
528 yield 42;
529 yield 42;
530 yield 42;
531 yield 42;
532 yield 42;
533 yield 42;
534 yield 42;
535 yield 42;
536 yield 42;
537 yield 42;
538 yield 42;
539 yield 42;
540 yield 42;
541 yield 42;
542 yield 42;
543 yield 42;
544 yield 42;
545 yield 42;
546 yield 42;
547 yield 42;
548 yield 42;
549 yield 42;
550 yield 42;
551 yield 42;
552 yield 42;
553 yield 42;
554 yield 42;
555 yield 42;
556 yield 42;
557 yield 42;
558 yield 42;
559 yield 42;
560 yield 42;
561 yield 42;
562 yield 42;
563 yield 42;
564 yield 42;
565 yield 42;
566 yield 42;
567 yield 42;
568 yield 42;
569 yield 42;
570 yield 42;
571 yield 42;
572 yield 42;
573 yield 42;
574 yield 42;
575 yield 42;
576 yield 42;
577 yield 42;
578 yield 42;
579 yield 42;
580 yield 42;
581 yield 42;
582 yield 42;
583 yield 42;
584 yield 42;
585 yield 42;
586 yield 42;
587 yield 42;
588 yield 42;
589 yield 42;
590 yield 42;
591 yield 42;
592 yield 42;
593 yield 42;
594 yield 42;
595 yield 42;
596 yield 42;
597 yield 42;
598 }
599 g = foo();
600 for (let i = 0; i < 100; ++i) {
601 assertEquals({value: 42, done: false}, i%25 === 0 ? Next(g) : g.next());
602 }
603 assertEquals({value: undefined, done: true}, Next(g));
604}
605
606{
607 function* foo() {
608 for (let i = 0; i < 3; ++i) {
609 let j = 0
610 yield i;
611 do {
612 yield (i + 10);
613 } while (++j < 2);
614 }
615 }
616 g = foo();
617 assertEquals({value: 0, done: false}, Next(g));
618 assertEquals({value: 10, done: false}, Next(g));
619 assertEquals({value: 10, done: false}, Next(g));
620 assertEquals({value: 1, done: false}, Next(g));
621 assertEquals({value: 11, done: false}, Next(g));
622 assertEquals({value: 11, done: false}, Next(g));
623 assertEquals({value: 2, done: false}, Next(g));
624 assertEquals({value: 12, done: false}, Next(g));
625 assertEquals({value: 12, done: false}, Next(g));
626 assertEquals({value: undefined, done: true}, Next(g));
627}
628
629{
630 let foo = function*() {
631 while (true) {
632 if (true || false) yield 42;
633 continue;
634 }
635 }
636 g = foo();
637 assertEquals({value: 42, done: false}, Next(g));
638 assertEquals({value: 42, done: false}, Next(g));
639 assertEquals({value: 42, done: false}, Next(g));
640}
641
642{
643 let foo = function*() {
644 yield* (function*() { yield 42; }());
645 assertUnreachable();
646 }
647 g = foo();
648 assertEquals({value: 42, done: false}, Next(g));
649 assertEquals({value: 23, done: true}, Return(g, 23));
650}