blob: 23913e4229a227b58be0fd63d262413c33c7a53b [file] [log] [blame]
Ben Murdoch61f157c2016-09-16 13:49:30 +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
5// Flags: --ignition --ignition-generators --harmony-do-expressions
6// Flags: --allow-natives-syntax --turbo --turbo-from-bytecode
7
8
9// This file is identical to mjsunit/harmony/generators.js, except for its Flags
10// lines. The purpose is to explicitly mention --turbo-from-bytecode such that
11// Clusterfuzz can thoroughly test the new generators implementation.
12
13
14function MaybeOptimizeOrDeoptimize(f) {
15 let x = Math.random(); // --random-seed makes this deterministic
16 if (x <= 0.33) {
17 %OptimizeFunctionOnNextCall(f);
18 } else if (x <= 0.66) {
19 %DeoptimizeFunction(f);
20 }
21}
22
23function Next(generator, ...args) {
24 MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
25 return generator.next(...args);
26}
27
28function Return(generator, ...args) {
29 MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
30 return generator.return(...args);
31}
32
33function Throw(generator, ...args) {
34 MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
35 return generator.throw(...args);
36}
37
38
39{ // yield in try-catch
40
41 let g = function*() {
42 try {yield 1} catch (error) {assertEquals("caught", error)}
43 };
44
45 assertThrowsEquals(() => Throw(g(), "not caught"), "not caught");
46
47 {
48 let x = g();
49 assertEquals({value: 1, done: false}, Next(x));
50 assertEquals({value: undefined, done: true}, Throw(x, "caught"));
51 }
52
53 {
54 let x = g();
55 assertEquals({value: 1, done: false}, Next(x));
56 assertEquals({value: undefined, done: true}, Next(x));
57 assertThrowsEquals(() => Throw(x, "not caught"), "not caught");
58 }
59}
60
61
62{ // return that doesn't close
63 let g = function*() { try {return 42} finally {yield 43} };
64
65 {
66 let x = g();
67 assertEquals({value: 43, done: false}, Next(x));
68 assertEquals({value: 42, done: true}, Next(x));
69 }
70}
71
72
73{ // return that doesn't close
74 let x;
75 let g = function*() { try {return 42} finally {Throw(x, 666)} };
76
77 {
78 x = g();
79 assertThrows(() => Next(x), TypeError); // still executing
80 }
81}
82
83
84{ // yield in try-finally, finally clause performs return
85
86 let g = function*() { try {yield 42} finally {return 13} };
87
88 { // "return" closes at suspendedStart
89 let x = g();
90 assertEquals({value: 666, done: true}, Return(x, 666));
91 assertEquals({value: undefined, done: true}, Next(x, 42));
92 assertThrowsEquals(() => Throw(x, 43), 43);
93 assertEquals({value: 42, done: true}, Return(x, 42));
94 }
95
96 { // "throw" closes at suspendedStart
97 let x = g();
98 assertThrowsEquals(() => Throw(x, 666), 666);
99 assertEquals({value: undefined, done: true}, Next(x, 42));
100 assertEquals({value: 43, done: true}, Return(x, 43));
101 assertThrowsEquals(() => Throw(x, 44), 44);
102 }
103
104 { // "next" closes at suspendedYield
105 let x = g();
106 assertEquals({value: 42, done: false}, Next(x));
107 assertEquals({value: 13, done: true}, Next(x, 666));
108 assertEquals({value: undefined, done: true}, Next(x, 666));
109 assertThrowsEquals(() => Throw(x, 666), 666);
110 }
111
112 { // "return" closes at suspendedYield
113 let x = g();
114 assertEquals({value: 42, done: false}, Next(x));
115 assertEquals({value: 13, done: true}, Return(x, 666));
116 assertEquals({value: undefined, done: true}, Next(x, 666));
117 assertEquals({value: 666, done: true}, Return(x, 666));
118 }
119
120 { // "throw" closes at suspendedYield
121 let x = g();
122 assertEquals({value: 42, done: false}, Next(x));
123 assertEquals({value: 13, done: true}, Throw(x, 666));
124 assertThrowsEquals(() => Throw(x, 666), 666);
125 assertEquals({value: undefined, done: true}, Next(x, 666));
126 }
127}
128
129
130{ // yield in try-finally, finally clause doesn't perform return
131
132 let g = function*() { try {yield 42} finally {13} };
133
134 { // "return" closes at suspendedStart
135 let x = g();
136 assertEquals({value: 666, done: true}, Return(x, 666));
137 assertEquals({value: undefined, done: true}, Next(x, 42));
138 assertThrowsEquals(() => Throw(x, 43), 43);
139 assertEquals({value: 42, done: true}, Return(x, 42));
140 }
141
142 { // "throw" closes at suspendedStart
143 let x = g();
144 assertThrowsEquals(() => Throw(x, 666), 666);
145 assertEquals({value: undefined, done: true}, Next(x, 42));
146 assertEquals({value: 43, done: true}, Return(x, 43));
147 assertThrowsEquals(() => Throw(x, 44), 44);
148 }
149
150 { // "next" closes at suspendedYield
151 let x = g();
152 assertEquals({value: 42, done: false}, Next(x));
153 assertEquals({value: undefined, done: true}, Next(x, 666));
154 assertEquals({value: undefined, done: true}, Next(x, 666));
155 assertThrowsEquals(() => Throw(x, 666), 666);
156 assertEquals({value: 42, done: true}, Return(x, 42));
157 }
158
159 { // "return" closes at suspendedYield
160 let x = g();
161 assertEquals({value: 42, done: false}, Next(x));
162 assertEquals({value: 666, done: true}, Return(x, 666));
163 assertEquals({value: undefined, done: true}, Next(x, 666));
164 assertThrowsEquals(() => Throw(x, 44), 44);
165 assertEquals({value: 42, done: true}, Return(x, 42));
166 }
167
168 { // "throw" closes at suspendedYield
169 let x = g();
170 assertEquals({value: 42, done: false}, Next(x));
171 assertThrowsEquals(() => Throw(x, 666), 666);
172 assertEquals({value: undefined, done: true}, Next(x, 666));
173 assertThrowsEquals(() => Throw(x, 666), 666);
174 assertEquals({value: 42, done: true}, Return(x, 42));
175 }
176}
177
178
179{ // yield in try-finally, finally clause yields and performs return
180
181 let g = function*() { try {yield 42} finally {yield 43; return 13} };
182
183 {
184 let x = g();
185 assertEquals({value: 42, done: false}, Next(x));
186 assertEquals({value: 43, done: false}, Return(x, 666));
187 assertEquals({value: 13, done: true}, Next(x));
188 assertEquals({value: 666, done: true}, Return(x, 666));
189 }
190
191 {
192 let x = g();
193 assertEquals({value: 666, done: true}, Return(x, 666));
194 assertEquals({value: undefined, done: true}, Next(x));
195 assertEquals({value: 666, done: true}, Return(x, 666));
196 }
197}
198
199
200{ // yield in try-finally, finally clause yields and doesn't perform return
201
202 let g = function*() { try {yield 42} finally {yield 43; 13} };
203
204 {
205 let x = g();
206 assertEquals({value: 42, done: false}, Next(x));
207 assertEquals({value: 43, done: false}, Return(x, 666));
208 assertEquals({value: 666, done: true}, Next(x));
209 assertEquals({value: 5, done: true}, Return(x, 5));
210 }
211
212 {
213 let x = g();
214 assertEquals({value: 666, done: true}, Return(x, 666));
215 assertEquals({value: undefined, done: true}, Next(x));
216 assertEquals({value: 666, done: true}, Return(x, 666));
217 }
218}
219
220
221{ // yield*, finally clause performs return
222
223 let h = function*() { try {yield 42} finally {yield 43; return 13} };
224 let g = function*() { yield 1; yield yield* h(); };
225
226 {
227 let x = g();
228 assertEquals({value: 1, done: false}, Next(x));
229 assertEquals({value: 42, done: false}, Next(x));
230 assertEquals({value: 43, done: false}, Next(x, 666));
231 assertEquals({value: 13, done: false}, Next(x));
232 assertEquals({value: undefined, done: true}, Next(x));
233 }
234
235 {
236 let x = g();
237 assertEquals({value: 1, done: false}, Next(x));
238 assertEquals({value: 42, done: false}, Next(x));
239 assertEquals({value: 43, done: false}, Return(x, 666));
240 assertEquals({value: 13, done: false}, Next(x));
241 assertEquals({value: undefined, done: true}, Next(x));
242 }
243
244 {
245 let x = g();
246 assertEquals({value: 1, done: false}, Next(x));
247 assertEquals({value: 42, done: false}, Next(x));
248 assertEquals({value: 43, done: false}, Throw(x, 666));
249 assertEquals({value: 13, done: false}, Next(x));
250 assertEquals({value: undefined, done: true}, Next(x));
251 }
252}
253
254
255{ // yield*, finally clause does not perform return
256
257 let h = function*() { try {yield 42} finally {yield 43; 13} };
258 let g = function*() { yield 1; yield yield* h(); };
259
260 {
261 let x = g();
262 assertEquals({value: 1, done: false}, Next(x));
263 assertEquals({value: 42, done: false}, Next(x));
264 assertEquals({value: 43, done: false}, Next(x, 666));
265 assertEquals({value: undefined, done: false}, Next(x));
266 assertEquals({value: undefined, done: true}, Next(x));
267 }
268
269 {
270 let x = g();
271 assertEquals({value: 1, done: false}, Next(x));
272 assertEquals({value: 42, done: false}, Next(x));
273 assertEquals({value: 43, done: false}, Return(x, 44));
274 assertEquals({value: 44, done: false}, Next(x));
275 assertEquals({value: undefined, done: true}, Next(x));
276 }
277
278 {
279 let x = g();
280 assertEquals({value: 1, done: false}, Next(x));
281 assertEquals({value: 42, done: false}, Next(x));
282 assertEquals({value: 43, done: false}, Throw(x, 666));
283 assertThrowsEquals(() => Next(x), 666);
284 }
285}
286
287
288{ // yield*, .return argument is final result
289
290 function* inner() {
291 yield 2;
292 }
293
294 function* g() {
295 yield 1;
296 return yield* inner();
297 }
298
299 {
300 let x = g();
301 assertEquals({value: 1, done: false}, Next(x));
302 assertEquals({value: 2, done: false}, Next(x));
303 assertEquals({value: 42, done: true}, Return(x, 42));
304 }
305}
306
307
308// More or less random tests from here on.
309
310
311{
312 function* foo() { }
313 let g = foo();
314 assertEquals({value: undefined, done: true}, Next(g));
315 assertEquals({value: undefined, done: true}, Next(g));
316}
317
318{
319 function* foo() { return new.target }
320 let g = foo();
321 assertEquals({value: undefined, done: true}, Next(g));
322 assertEquals({value: undefined, done: true}, Next(g));
323}
324
325{
326 function* foo() { throw 666; return 42}
327 let g = foo();
328 assertThrowsEquals(() => Next(g), 666);
329 assertEquals({value: undefined, done: true}, Next(g));
330}
331
332{
333 function* foo(a) { return a; }
334 let g = foo(42);
335 assertEquals({value: 42, done: true}, Next(g));
336 assertEquals({value: undefined, done: true}, Next(g));
337}
338
339{
340 function* foo(a) { a.iwashere = true; return a; }
341 let x = {};
342 let g = foo(x);
343 assertEquals({value: {iwashere: true}, done: true}, Next(g));
344 assertEquals({value: undefined, done: true}, Next(g));
345}
346
347{
348 let a = 42;
349 function* foo() { return a; }
350 let g = foo();
351 assertEquals({value: 42, done: true}, Next(g));
352 assertEquals({value: undefined, done: true}, Next(g));
353}
354
355{
356 let a = 40;
357 function* foo(b) { return a + b; }
358 let g = foo(2);
359 assertEquals({value: 42, done: true}, Next(g));
360 assertEquals({value: undefined, done: true}, Next(g));
361}
362
363{
364 let a = 40;
365 function* foo(b) { a--; b++; return a + b; }
366 let g = foo(2);
367 assertEquals({value: 42, done: true}, Next(g));
368 assertEquals({value: undefined, done: true}, Next(g));
369}
370
371{
372 let g;
373 function* foo() { Next(g) }
374 g = foo();
375 assertThrows(() => Next(g), TypeError);
376 assertEquals({value: undefined, done: true}, Next(g));
377}
378
379{
380 function* foo() { yield 2; yield 3; yield 4 }
381 g = foo();
382 assertEquals({value: 2, done: false}, Next(g));
383 assertEquals({value: 3, done: false}, Next(g));
384 assertEquals({value: 4, done: false}, Next(g));
385 assertEquals({value: undefined, done: true}, Next(g));
386 assertEquals({value: undefined, done: true}, Next(g));
387}
388
389
390{
391 function* foo() { yield 2; if (true) { yield 3 }; yield 4 }
392 g = foo();
393 assertEquals({value: 2, done: false}, Next(g));
394 assertEquals({value: 3, done: false}, Next(g));
395 assertEquals({value: 4, done: false}, Next(g));
396 assertEquals({value: undefined, done: true}, Next(g));
397 assertEquals({value: undefined, done: true}, Next(g));
398}
399
400{
401 function* foo() { yield 2; if (true) { yield 3; yield 4 } }
402 g = foo();
403 assertEquals({value: 2, done: false}, Next(g));
404 assertEquals({value: 3, done: false}, Next(g));
405 assertEquals({value: 4, done: false}, Next(g));
406 assertEquals({value: undefined, done: true}, Next(g));
407 assertEquals({value: undefined, done: true}, Next(g));
408}
409
410{
411 function* foo() { yield 2; if (false) { yield 3 }; yield 4 }
412 g = foo();
413 assertEquals({value: 2, done: false}, Next(g));
414 assertEquals({value: 4, done: false}, Next(g));
415 assertEquals({value: undefined, done: true}, Next(g));
416 assertEquals({value: undefined, done: true}, Next(g));
417}
418
419{
420 function* foo() { yield 2; while (true) { yield 3 }; yield 4 }
421 g = foo();
422 assertEquals({value: 2, done: false}, Next(g));
423 assertEquals({value: 3, done: false}, Next(g));
424 assertEquals({value: 3, done: false}, Next(g));
425 assertEquals({value: 3, done: false}, Next(g));
426 assertEquals({value: 3, done: false}, Next(g));
427}
428
429{
430 function* foo() { yield 2; (yield 3) + 42; yield 4 }
431 g = foo();
432 assertEquals({value: 2, done: false}, Next(g));
433 assertEquals({value: 3, done: false}, Next(g));
434 assertEquals({value: 4, done: false}, Next(g));
435}
436
437{
438 function* foo() { yield 2; (do {yield 3}) + 42; yield 4 }
439 g = foo();
440 assertEquals({value: 2, done: false}, Next(g));
441 assertEquals({value: 3, done: false}, Next(g));
442 assertEquals({value: 4, done: false}, Next(g));
443}
444
445{
446 function* foo() { yield 2; return (yield 3) + 42; yield 4 }
447 g = foo();
448 assertEquals({value: 2, done: false}, Next(g));
449 assertEquals({value: 3, done: false}, Next(g));
450 assertEquals({value: 42, done: true}, Next(g, 0));
451 assertEquals({value: undefined, done: true}, Next(g));
452}
453
454{
455 let x = 42;
456 function* foo() {
457 yield x;
458 for (let x in {a: 1, b: 2}) {
459 let i = 2;
460 yield x;
461 yield i;
462 do {
463 yield i;
464 } while (i-- > 0);
465 }
466 yield x;
467 return 5;
468 }
469 g = foo();
470 assertEquals({value: 42, done: false}, Next(g));
471 assertEquals({value: 'a', 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: 'b', done: false}, Next(g));
477 assertEquals({value: 2, done: false}, Next(g));
478 assertEquals({value: 2, done: false}, Next(g));
479 assertEquals({value: 1, done: false}, Next(g));
480 assertEquals({value: 0, done: false}, Next(g));
481 assertEquals({value: 42, done: false}, Next(g));
482 assertEquals({value: 5, done: true}, Next(g));
483}
484
485{
486 let a = 3;
487 function* foo() {
488 let b = 4;
489 yield 1;
490 { let c = 5; yield 2; yield a; yield b; yield c; }
491 }
492 g = foo();
493 assertEquals({value: 1, done: false}, Next(g));
494 assertEquals({value: 2, done: false}, Next(g));
495 assertEquals({value: 3, done: false}, Next(g));
496 assertEquals({value: 4, done: false}, Next(g));
497 assertEquals({value: 5, done: false}, Next(g));
498 assertEquals({value: undefined, done: true}, Next(g));
499}
500
501{
502 function* foo() {
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 yield 42;
599 yield 42;
600 yield 42;
601 yield 42;
602 yield 42;
603 }
604 g = foo();
605 for (let i = 0; i < 100; ++i) {
606 assertEquals({value: 42, done: false}, i%25 === 0 ? Next(g) : g.next());
607 }
608 assertEquals({value: undefined, done: true}, Next(g));
609}
610
611{
612 function* foo() {
613 for (let i = 0; i < 3; ++i) {
614 let j = 0
615 yield i;
616 do {
617 yield (i + 10);
618 } while (++j < 2);
619 }
620 }
621 g = foo();
622 assertEquals({value: 0, done: false}, Next(g));
623 assertEquals({value: 10, done: false}, Next(g));
624 assertEquals({value: 10, done: false}, Next(g));
625 assertEquals({value: 1, done: false}, Next(g));
626 assertEquals({value: 11, done: false}, Next(g));
627 assertEquals({value: 11, done: false}, Next(g));
628 assertEquals({value: 2, done: false}, Next(g));
629 assertEquals({value: 12, done: false}, Next(g));
630 assertEquals({value: 12, done: false}, Next(g));
631 assertEquals({value: undefined, done: true}, Next(g));
632}
633
634{
635 let foo = function*() {
636 while (true) {
637 if (true || false) yield 42;
638 continue;
639 }
640 }
641 g = foo();
642 assertEquals({value: 42, done: false}, Next(g));
643 assertEquals({value: 42, done: false}, Next(g));
644 assertEquals({value: 42, done: false}, Next(g));
645}
646
647{
648 let foo = function*() {
649 yield* (function*() { yield 42; }());
650 assertUnreachable();
651 }
652 g = foo();
653 assertEquals({value: 42, done: false}, Next(g));
654 assertEquals({value: 23, done: true}, Return(g, 23));
655}