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