• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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}
656