go.ketch.com/lib/goja@v0.0.1/compiler_test.go (about) 1 package goja 2 3 import ( 4 "os" 5 "sync" 6 "testing" 7 ) 8 9 const TESTLIB = ` 10 function $ERROR(message) { 11 throw new Error(message); 12 } 13 14 function Test262Error() { 15 } 16 17 function assert(mustBeTrue, message) { 18 if (mustBeTrue === true) { 19 return; 20 } 21 22 if (message === undefined) { 23 message = 'Expected true but got ' + String(mustBeTrue); 24 } 25 $ERROR(message); 26 } 27 28 assert._isSameValue = function (a, b) { 29 if (a === b) { 30 // Handle +/-0 vs. -/+0 31 return a !== 0 || 1 / a === 1 / b; 32 } 33 34 // Handle NaN vs. NaN 35 return a !== a && b !== b; 36 }; 37 38 assert.sameValue = function (actual, expected, message) { 39 if (assert._isSameValue(actual, expected)) { 40 return; 41 } 42 43 if (message === undefined) { 44 message = ''; 45 } else { 46 message += ' '; 47 } 48 49 message += 'Expected SameValue(«' + String(actual) + '», «' + String(expected) + '») to be true'; 50 51 $ERROR(message); 52 }; 53 54 assert.throws = function (expectedErrorConstructor, func, message) { 55 if (typeof func !== "function") { 56 $ERROR('assert.throws requires two arguments: the error constructor ' + 57 'and a function to run'); 58 return; 59 } 60 if (message === undefined) { 61 message = ''; 62 } else { 63 message += ' '; 64 } 65 66 try { 67 func(); 68 } catch (thrown) { 69 if (typeof thrown !== 'object' || thrown === null) { 70 message += 'Thrown value was not an object!'; 71 $ERROR(message); 72 } else if (thrown.constructor !== expectedErrorConstructor) { 73 message += 'Expected a ' + expectedErrorConstructor.name + ' but got a ' + thrown.constructor.name; 74 $ERROR(message); 75 } 76 return; 77 } 78 79 message += 'Expected a ' + expectedErrorConstructor.name + ' to be thrown but no exception was thrown at all'; 80 $ERROR(message); 81 }; 82 83 function compareArray(a, b) { 84 if (b.length !== a.length) { 85 return false; 86 } 87 88 for (var i = 0; i < a.length; i++) { 89 if (b[i] !== a[i]) { 90 return false; 91 } 92 } 93 return true; 94 } 95 ` 96 97 const TESTLIBX = ` 98 function looksNative(fn) { 99 return /native code/.test(Function.prototype.toString.call(fn)); 100 } 101 102 function deepEqual(a, b) { 103 if (typeof a === "object") { 104 if (typeof b === "object") { 105 if (a === b) { 106 return true; 107 } 108 if (Reflect.getPrototypeOf(a) !== Reflect.getPrototypeOf(b)) { 109 return false; 110 } 111 var keysA = Object.keys(a); 112 var keysB = Object.keys(b); 113 if (keysA.length !== keysB.length) { 114 return false; 115 } 116 if (!compareArray(keysA.sort(), keysB.sort())) { 117 return false; 118 } 119 for (var i = 0; i < keysA.length; i++) { 120 var key = keysA[i]; 121 if (!deepEqual(a[key], b[key])) { 122 return false; 123 } 124 } 125 return true; 126 } else { 127 return false; 128 } 129 } 130 return assert._isSameValue(a, b); 131 } 132 ` 133 134 var ( 135 // The reason it's implemented this way rather than just as _testLib = MustCompile(...) 136 // is because when you try to debug the compiler and set a breakpoint it gets triggered during the 137 // initialisation which is annoying. 138 _testLib, _testLibX *Program 139 testLibOnce, testLibXOnce sync.Once 140 ) 141 142 func testLib() *Program { 143 testLibOnce.Do(func() { 144 _testLib = MustCompile("testlib.js", TESTLIB, false) 145 }) 146 return _testLib 147 } 148 149 func testLibX() *Program { 150 testLibXOnce.Do(func() { 151 _testLibX = MustCompile("testlibx.js", TESTLIBX, false) 152 }) 153 return _testLibX 154 } 155 156 func (r *Runtime) testPrg(p *Program, expectedResult Value, t *testing.T) { 157 vm := r.vm 158 vm.prg = p 159 vm.pc = 0 160 vm.prg.dumpCode(t.Logf) 161 vm.result = _undefined 162 vm.run() 163 v := vm.result 164 t.Logf("stack size: %d", len(vm.stack)) 165 t.Logf("stashAllocs: %d", vm.stashAllocs) 166 167 if v == nil && expectedResult != nil || !v.SameAs(expectedResult) { 168 t.Fatalf("Result: %+v, expected: %+v", v, expectedResult) 169 } 170 171 if vm.sp != 0 { 172 t.Fatalf("sp: %d", vm.sp) 173 } 174 175 if l := len(vm.iterStack); l > 0 { 176 t.Fatalf("iter stack is not empty: %d", l) 177 } 178 } 179 180 func (r *Runtime) testScriptWithTestLib(script string, expectedResult Value, t *testing.T) { 181 _, err := r.RunProgram(testLib()) 182 if err != nil { 183 t.Fatal(err) 184 } 185 186 r.testScript(script, expectedResult, t) 187 } 188 189 func (r *Runtime) testScriptWithTestLibX(script string, expectedResult Value, t *testing.T) { 190 _, err := r.RunProgram(testLib()) 191 if err != nil { 192 t.Fatal(err) 193 } 194 195 _, err = r.RunProgram(testLibX()) 196 if err != nil { 197 t.Fatal(err) 198 } 199 200 r.testScript(script, expectedResult, t) 201 } 202 203 func (r *Runtime) testScript(script string, expectedResult Value, t *testing.T) { 204 r.testPrg(MustCompile("test.js", script, false), expectedResult, t) 205 } 206 207 func testScript(script string, expectedResult Value, t *testing.T) { 208 New().testScript(script, expectedResult, t) 209 } 210 211 func testScriptWithTestLib(script string, expectedResult Value, t *testing.T) { 212 New().testScriptWithTestLib(script, expectedResult, t) 213 } 214 215 func testScriptWithTestLibX(script string, expectedResult Value, t *testing.T) { 216 New().testScriptWithTestLibX(script, expectedResult, t) 217 } 218 219 func TestEmptyProgram(t *testing.T) { 220 const SCRIPT = ` 221 ` 222 223 testScript(SCRIPT, _undefined, t) 224 } 225 226 func TestResultEmptyBlock(t *testing.T) { 227 const SCRIPT = ` 228 undefined; 229 {} 230 ` 231 testScript(SCRIPT, _undefined, t) 232 } 233 234 func TestResultVarDecl(t *testing.T) { 235 const SCRIPT = ` 236 7; var x = 1; 237 ` 238 testScript(SCRIPT, valueInt(7), t) 239 } 240 241 func TestResultLexDecl(t *testing.T) { 242 const SCRIPT = ` 243 7; {let x = 1}; 244 ` 245 testScript(SCRIPT, valueInt(7), t) 246 } 247 248 func TestResultLexDeclBreak(t *testing.T) { 249 const SCRIPT = ` 250 L:{ 7; {let x = 1; break L;}}; 251 ` 252 testScript(SCRIPT, valueInt(7), t) 253 } 254 255 func TestResultLexDeclNested(t *testing.T) { 256 const SCRIPT = ` 257 7; {let x = (function() { return eval("8; {let y = 9}")})()}; 258 ` 259 testScript(SCRIPT, valueInt(7), t) 260 } 261 262 func TestErrorProto(t *testing.T) { 263 const SCRIPT = ` 264 var e = new TypeError(); 265 e.name; 266 ` 267 268 testScript(SCRIPT, asciiString("TypeError"), t) 269 } 270 271 func TestThis1(t *testing.T) { 272 const SCRIPT = ` 273 function independent() { 274 return this.prop; 275 } 276 var o = {}; 277 o.b = {g: independent, prop: 42}; 278 279 o.b.g(); 280 ` 281 testScript(SCRIPT, intToValue(42), t) 282 } 283 284 func TestThis2(t *testing.T) { 285 const SCRIPT = ` 286 var o = { 287 prop: 37, 288 f: function() { 289 return this.prop; 290 } 291 }; 292 293 o.f(); 294 ` 295 296 testScript(SCRIPT, intToValue(37), t) 297 } 298 299 func TestThisStrict(t *testing.T) { 300 const SCRIPT = ` 301 "use strict"; 302 303 Object.defineProperty(Object.prototype, "x", { get: function () { return this; } }); 304 305 (5).x === 5; 306 ` 307 308 testScript(SCRIPT, valueTrue, t) 309 } 310 311 func TestThisNoStrict(t *testing.T) { 312 const SCRIPT = ` 313 Object.defineProperty(Object.prototype, "x", { get: function () { return this; } }); 314 315 (5).x == 5; 316 ` 317 318 testScript(SCRIPT, valueTrue, t) 319 } 320 321 func TestNestedFuncVarResolution(t *testing.T) { 322 const SCRIPT = ` 323 (function outer() { 324 var v = 42; 325 function inner() { 326 return v; 327 } 328 return inner(); 329 })(); 330 ` 331 testScript(SCRIPT, valueInt(42), t) 332 } 333 334 func TestNestedFuncVarResolution1(t *testing.T) { 335 const SCRIPT = ` 336 function outer(argOuter) { 337 var called = 0; 338 var inner = function(argInner) { 339 if (arguments.length !== 1) { 340 throw new Error(); 341 } 342 called++; 343 if (argOuter !== 1) { 344 throw new Error("argOuter"); 345 } 346 if (argInner !== 2) { 347 throw new Error("argInner"); 348 } 349 }; 350 inner(2); 351 } 352 outer(1); 353 ` 354 testScript(SCRIPT, _undefined, t) 355 } 356 357 func TestCallFewerArgs(t *testing.T) { 358 const SCRIPT = ` 359 function A(a, b, c) { 360 return String(a) + " " + String(b) + " " + String(c); 361 } 362 363 A(1, 2); 364 ` 365 testScript(SCRIPT, asciiString("1 2 undefined"), t) 366 } 367 368 func TestCallFewerArgsClosureNoArgs(t *testing.T) { 369 const SCRIPT = ` 370 var x; 371 function A(a, b, c) { 372 var y = a; 373 x = function() { return " " + y }; 374 return String(a) + " " + String(b) + " " + String(c); 375 } 376 377 A(1, 2) + x(); 378 ` 379 testScript(SCRIPT, asciiString("1 2 undefined 1"), t) 380 } 381 382 func TestCallFewerArgsClosureArgs(t *testing.T) { 383 const SCRIPT = ` 384 var x; 385 function A(a, b, c) { 386 var y = b; 387 x = function() { return " " + a + " " + y }; 388 return String(a) + " " + String(b) + " " + String(c); 389 } 390 391 A(1, 2) + x(); 392 ` 393 testScript(SCRIPT, asciiString("1 2 undefined 1 2"), t) 394 } 395 396 func TestCallMoreArgs(t *testing.T) { 397 const SCRIPT = ` 398 function A(a, b) { 399 var c = 4; 400 return a - b + c; 401 } 402 403 A(1, 2, 3); 404 ` 405 testScript(SCRIPT, intToValue(3), t) 406 } 407 408 func TestCallMoreArgsDynamic(t *testing.T) { 409 const SCRIPT = ` 410 function A(a, b) { 411 var c = 4; 412 if (false) { 413 eval(""); 414 } 415 return a - b + c; 416 } 417 418 A(1, 2, 3); 419 ` 420 testScript(SCRIPT, intToValue(3), t) 421 } 422 423 func TestCallLessArgsDynamic(t *testing.T) { 424 const SCRIPT = ` 425 function A(a, b, c) { 426 // Make it stashful 427 function B() { 428 return a; 429 } 430 return String(a) + " " + String(b) + " " + String(c); 431 } 432 433 A(1, 2); 434 ` 435 testScript(SCRIPT, asciiString("1 2 undefined"), t) 436 } 437 438 func TestCallLessArgsDynamicLocalVar(t *testing.T) { 439 const SCRIPT = ` 440 function f(param) { 441 var a = 42; 442 if (false) { 443 eval(""); 444 } 445 return a; 446 } 447 f(); 448 ` 449 450 testScript(SCRIPT, intToValue(42), t) 451 } 452 453 /* 454 func TestFib(t *testing.T) { 455 testScript(TEST_FIB, valueInt(9227465), t) 456 } 457 */ 458 459 func TestNativeCall(t *testing.T) { 460 const SCRIPT = ` 461 var o = Object(1); 462 Object.defineProperty(o, "test", {value: 42}); 463 o.test; 464 ` 465 testScript(SCRIPT, intToValue(42), t) 466 } 467 468 func TestJSCall(t *testing.T) { 469 const SCRIPT = ` 470 function getter() { 471 return this.x; 472 } 473 var o = Object(1); 474 o.x = 42; 475 Object.defineProperty(o, "test", {get: getter}); 476 o.test; 477 ` 478 testScript(SCRIPT, intToValue(42), t) 479 480 } 481 482 func TestLoop1(t *testing.T) { 483 const SCRIPT = ` 484 function A() { 485 var x = 1; 486 for (var i = 0; i < 1; i++) { 487 var x = 2; 488 } 489 return x; 490 } 491 492 A(); 493 ` 494 testScript(SCRIPT, intToValue(2), t) 495 } 496 497 func TestLoopBreak(t *testing.T) { 498 const SCRIPT = ` 499 function A() { 500 var x = 1; 501 for (var i = 0; i < 1; i++) { 502 break; 503 var x = 2; 504 } 505 return x; 506 } 507 508 A(); 509 ` 510 testScript(SCRIPT, intToValue(1), t) 511 } 512 513 func TestForLoopOptionalExpr(t *testing.T) { 514 const SCRIPT = ` 515 function A() { 516 var x = 1; 517 for (;;) { 518 break; 519 var x = 2; 520 } 521 return x; 522 } 523 524 A(); 525 ` 526 testScript(SCRIPT, intToValue(1), t) 527 } 528 529 func TestBlockBreak(t *testing.T) { 530 const SCRIPT = ` 531 var rv = 0; 532 B1: { 533 rv = 1; 534 B2: { 535 rv = 2; 536 break B1; 537 } 538 rv = 3; 539 } 540 rv; 541 ` 542 testScript(SCRIPT, intToValue(2), t) 543 544 } 545 546 func TestTry(t *testing.T) { 547 const SCRIPT = ` 548 function A() { 549 var x = 1; 550 try { 551 x = 2; 552 } catch(e) { 553 x = 3; 554 } finally { 555 x = 4; 556 } 557 return x; 558 } 559 560 A(); 561 ` 562 testScript(SCRIPT, intToValue(4), t) 563 } 564 565 func TestTryOptionalCatchBinding(t *testing.T) { 566 const SCRIPT = ` 567 try { 568 throw null; 569 } catch { 570 } 571 ` 572 testScript(SCRIPT, _undefined, t) 573 } 574 575 func TestTryCatch(t *testing.T) { 576 const SCRIPT = ` 577 function A() { 578 var x; 579 try { 580 throw 4; 581 } catch(e) { 582 x = e; 583 } 584 return x; 585 } 586 587 A(); 588 ` 589 testScript(SCRIPT, intToValue(4), t) 590 } 591 592 func TestTryCatchDirectEval(t *testing.T) { 593 const SCRIPT = ` 594 function A() { 595 var x; 596 try { 597 throw 4; 598 } catch(e) { 599 eval("x = e"); 600 } 601 return x; 602 } 603 604 A(); 605 ` 606 testScript(SCRIPT, intToValue(4), t) 607 } 608 609 func TestTryExceptionInCatch(t *testing.T) { 610 const SCRIPT = ` 611 function A() { 612 var x; 613 try { 614 throw 4; 615 } catch(e) { 616 throw 5; 617 } 618 return x; 619 } 620 621 var rv; 622 try { 623 A(); 624 } catch (e) { 625 rv = e; 626 } 627 rv; 628 ` 629 testScript(SCRIPT, intToValue(5), t) 630 } 631 632 func TestTryContinueInCatch(t *testing.T) { 633 const SCRIPT = ` 634 var c3 = 0, fin3 = 0; 635 while (c3 < 2) { 636 try { 637 throw "ex1"; 638 } catch(er1) { 639 c3 += 1; 640 continue; 641 } finally { 642 fin3 = 1; 643 } 644 fin3 = 0; 645 } 646 647 fin3; 648 ` 649 testScript(SCRIPT, intToValue(1), t) 650 } 651 652 func TestContinueInWith(t *testing.T) { 653 const SCRIPT = ` 654 var x; 655 var o = {x: 0}; 656 for (var i = 0; i < 2; i++) { 657 with(o) { 658 x = i; 659 if (i === 0) { 660 continue; 661 } 662 } 663 break; 664 } 665 x; 666 ` 667 testScript(SCRIPT, _undefined, t) 668 } 669 670 func TestTryContinueInFinally(t *testing.T) { 671 const SCRIPT = ` 672 var c3 = 0, fin3 = 0; 673 while (c3 < 2) { 674 try { 675 throw "ex1"; 676 } catch(er1) { 677 c3 += 1; 678 } finally { 679 fin3 = 1; 680 continue; 681 } 682 fin3 = 0; 683 } 684 685 fin3; 686 ` 687 testScript(SCRIPT, intToValue(1), t) 688 } 689 690 func TestTryBreakFinallyContinue(t *testing.T) { 691 const SCRIPT = ` 692 for (var i = 0; i < 3; i++) { 693 try { 694 break; 695 } finally { 696 continue; 697 } 698 } 699 ` 700 testScript(SCRIPT, _undefined, t) 701 } 702 703 func TestTryBreakFinallyContinueWithResult(t *testing.T) { 704 const SCRIPT = ` 705 for (var i = 0; i < 3; i++) { 706 try { 707 true; 708 break; 709 } finally { 710 continue; 711 } 712 } 713 ` 714 testScript(SCRIPT, _undefined, t) 715 } 716 717 func TestTryBreakFinallyContinueWithResult1(t *testing.T) { 718 const SCRIPT = ` 719 for (var i = 0; i < 3; i++) { 720 try { 721 true; 722 break; 723 } finally { 724 var x = 1; 725 continue; 726 } 727 } 728 ` 729 testScript(SCRIPT, _undefined, t) 730 } 731 732 func TestTryBreakFinallyContinueWithResultNested(t *testing.T) { 733 const SCRIPT = ` 734 LOOP: 735 for (var i = 0; i < 3; i++) { 736 try { 737 if (true) { 738 false; break; 739 } 740 } finally { 741 if (true) { 742 true; continue; 743 } 744 } 745 } 746 ` 747 testScript(SCRIPT, valueTrue, t) 748 } 749 750 func TestTryBreakOuterFinallyContinue(t *testing.T) { 751 const SCRIPT = ` 752 let iCount = 0, jCount = 0; 753 OUTER: for (let i = 0; i < 1; i++) { 754 iCount++; 755 for (let j = 0; j < 2; j++) { 756 jCount++; 757 try { 758 break OUTER; 759 } finally { 760 continue; 761 } 762 } 763 } 764 ""+iCount+jCount; 765 ` 766 testScript(SCRIPT, asciiString("12"), t) 767 } 768 769 func TestTryIllegalContinueWithFinallyOverride(t *testing.T) { 770 const SCRIPT = ` 771 L: { 772 while (Math.random() > 0.5) { 773 try { 774 continue L; 775 } finally { 776 break; 777 } 778 } 779 } 780 ` 781 _, err := Compile("", SCRIPT, false) 782 if err == nil { 783 t.Fatal("expected error") 784 } 785 } 786 787 func TestTryIllegalContinueWithFinallyOverrideNoLabel(t *testing.T) { 788 const SCRIPT = ` 789 L: { 790 try { 791 continue; 792 } finally { 793 break L; 794 } 795 } 796 ` 797 _, err := Compile("", SCRIPT, false) 798 if err == nil { 799 t.Fatal("expected error") 800 } 801 } 802 803 func TestTryIllegalContinueWithFinallyOverrideDummy(t *testing.T) { 804 const SCRIPT = ` 805 L: { 806 while (false) { 807 try { 808 continue L; 809 } finally { 810 break; 811 } 812 } 813 } 814 ` 815 _, err := Compile("", SCRIPT, false) 816 if err == nil { 817 t.Fatal("expected error") 818 } 819 } 820 821 func TestTryNoResult(t *testing.T) { 822 const SCRIPT = ` 823 true; 824 L: 825 try { 826 break L; 827 } finally { 828 } 829 ` 830 testScript(SCRIPT, _undefined, t) 831 } 832 833 func TestCatchLexicalEnv(t *testing.T) { 834 const SCRIPT = ` 835 function F() { 836 try { 837 throw 1; 838 } catch (e) { 839 var x = e; 840 } 841 return x; 842 } 843 844 F(); 845 ` 846 testScript(SCRIPT, intToValue(1), t) 847 } 848 849 func TestThrowType(t *testing.T) { 850 const SCRIPT = ` 851 function Exception(message) { 852 this.message = message; 853 } 854 855 856 function A() { 857 try { 858 throw new Exception("boo!"); 859 } catch(e) { 860 return e; 861 } 862 } 863 var thrown = A(); 864 thrown !== null && typeof thrown === "object" && thrown.constructor === Exception; 865 ` 866 testScript(SCRIPT, valueTrue, t) 867 } 868 869 func TestThrowConstructorName(t *testing.T) { 870 const SCRIPT = ` 871 function Exception(message) { 872 this.message = message; 873 } 874 875 876 function A() { 877 try { 878 throw new Exception("boo!"); 879 } catch(e) { 880 return e; 881 } 882 } 883 A().constructor.name; 884 ` 885 886 testScript(SCRIPT, asciiString("Exception"), t) 887 } 888 889 func TestThrowNativeConstructorName(t *testing.T) { 890 const SCRIPT = ` 891 892 893 function A() { 894 try { 895 throw new TypeError(); 896 } catch(e) { 897 return e; 898 } 899 } 900 A().constructor.name; 901 ` 902 903 testScript(SCRIPT, asciiString("TypeError"), t) 904 } 905 906 func TestEmptyTryNoCatch(t *testing.T) { 907 const SCRIPT = ` 908 var called = false; 909 try { 910 } finally { 911 called = true; 912 } 913 called; 914 ` 915 916 testScript(SCRIPT, valueTrue, t) 917 } 918 919 func TestTryReturnFromCatch(t *testing.T) { 920 const SCRIPT = ` 921 function f(o) { 922 var x = 42; 923 924 function innerf(o) { 925 try { 926 throw o; 927 } catch (e) { 928 return x; 929 } 930 } 931 932 return innerf(o); 933 } 934 f({}); 935 ` 936 937 testScript(SCRIPT, valueInt(42), t) 938 } 939 940 func TestTryCompletionResult(t *testing.T) { 941 const SCRIPT = ` 942 99; do { -99; try { 39 } catch (e) { -1 } finally { break; -2 }; } while (false); 943 ` 944 945 testScript(SCRIPT, _undefined, t) 946 } 947 948 func TestIfElse(t *testing.T) { 949 const SCRIPT = ` 950 var rv; 951 if (rv === undefined) { 952 rv = "passed"; 953 } else { 954 rv = "failed"; 955 } 956 rv; 957 ` 958 959 testScript(SCRIPT, asciiString("passed"), t) 960 } 961 962 func TestIfElseRetVal(t *testing.T) { 963 const SCRIPT = ` 964 var x; 965 if (x === undefined) { 966 "passed"; 967 } else { 968 "failed"; 969 } 970 ` 971 972 testScript(SCRIPT, asciiString("passed"), t) 973 } 974 975 func TestWhileReturnValue(t *testing.T) { 976 const SCRIPT = ` 977 var x = 0; 978 while(true) { 979 x = 1; 980 break; 981 } 982 ` 983 testScript(SCRIPT, intToValue(1), t) 984 } 985 986 func TestIfElseLabel(t *testing.T) { 987 const SCRIPT = ` 988 var x = 0; 989 abc: if (true) { 990 x = 1; 991 break abc; 992 } 993 ` 994 testScript(SCRIPT, intToValue(1), t) 995 } 996 997 func TestIfMultipleLabels(t *testing.T) { 998 const SCRIPT = ` 999 var x = 0; 1000 xyz:abc: if (true) { 1001 break xyz; 1002 } 1003 ` 1004 testScript(SCRIPT, _undefined, t) 1005 } 1006 1007 func TestBreakOutOfTry(t *testing.T) { 1008 const SCRIPT = ` 1009 function A() { 1010 var x = 1; 1011 B: { 1012 try { 1013 x = 2; 1014 } catch(e) { 1015 x = 3; 1016 } finally { 1017 break B; 1018 x = 4; 1019 } 1020 } 1021 return x; 1022 } 1023 1024 A(); 1025 ` 1026 testScript(SCRIPT, intToValue(2), t) 1027 } 1028 1029 func TestReturnOutOfTryNested(t *testing.T) { 1030 const SCRIPT = ` 1031 function A() { 1032 function nested() { 1033 try { 1034 return 1; 1035 } catch(e) { 1036 return 2; 1037 } 1038 } 1039 return nested(); 1040 } 1041 1042 A(); 1043 ` 1044 testScript(SCRIPT, intToValue(1), t) 1045 } 1046 1047 func TestContinueLoop(t *testing.T) { 1048 const SCRIPT = ` 1049 function A() { 1050 var r = 0; 1051 for (var i = 0; i < 5; i++) { 1052 if (i > 1) { 1053 continue; 1054 } 1055 r++; 1056 } 1057 return r; 1058 } 1059 1060 A(); 1061 ` 1062 testScript(SCRIPT, intToValue(2), t) 1063 } 1064 1065 func TestContinueOutOfTry(t *testing.T) { 1066 const SCRIPT = ` 1067 function A() { 1068 var r = 0; 1069 for (var i = 0; i < 5; i++) { 1070 try { 1071 if (i > 1) { 1072 continue; 1073 } 1074 } catch(e) { 1075 return 99; 1076 } 1077 r++; 1078 } 1079 return r; 1080 } 1081 1082 A(); 1083 ` 1084 testScript(SCRIPT, intToValue(2), t) 1085 } 1086 1087 func TestThisInCatch(t *testing.T) { 1088 const SCRIPT = ` 1089 function O() { 1090 try { 1091 f(); 1092 } catch (e) { 1093 this.value = e.toString(); 1094 } 1095 } 1096 1097 function f() { 1098 throw "ex"; 1099 } 1100 1101 var o = new O(); 1102 o.value; 1103 ` 1104 testScript(SCRIPT, asciiString("ex"), t) 1105 } 1106 1107 func TestNestedTry(t *testing.T) { 1108 const SCRIPT = ` 1109 var ex; 1110 try { 1111 throw "ex1"; 1112 } catch (er1) { 1113 try { 1114 throw "ex2"; 1115 } catch (er1) { 1116 ex = er1; 1117 } 1118 } 1119 ex; 1120 ` 1121 testScript(SCRIPT, asciiString("ex2"), t) 1122 } 1123 1124 func TestNestedTryInStashlessFunc(t *testing.T) { 1125 const SCRIPT = ` 1126 function f() { 1127 var ex1, ex2; 1128 try { 1129 throw "ex1"; 1130 } catch (er1) { 1131 try { 1132 throw "ex2"; 1133 } catch (er1) { 1134 ex2 = er1; 1135 } 1136 ex1 = er1; 1137 } 1138 return ex1 == "ex1" && ex2 == "ex2"; 1139 } 1140 f(); 1141 ` 1142 testScript(SCRIPT, valueTrue, t) 1143 } 1144 1145 func TestEvalLexicalDecl(t *testing.T) { 1146 const SCRIPT = ` 1147 eval("let x = true; x;"); 1148 ` 1149 testScript(SCRIPT, valueTrue, t) 1150 } 1151 1152 func TestEvalInCatchInStashlessFunc(t *testing.T) { 1153 const SCRIPT = ` 1154 function f() { 1155 var ex; 1156 try { 1157 throw "ex1"; 1158 } catch (er1) { 1159 eval("ex = er1"); 1160 } 1161 return ex; 1162 } 1163 f(); 1164 ` 1165 testScript(SCRIPT, asciiString("ex1"), t) 1166 } 1167 1168 func TestCatchClosureInStashlessFunc(t *testing.T) { 1169 const SCRIPT = ` 1170 function f() { 1171 var ex; 1172 try { 1173 throw "ex1"; 1174 } catch (er1) { 1175 return function() { 1176 return er1; 1177 } 1178 } 1179 } 1180 f()(); 1181 ` 1182 testScript(SCRIPT, asciiString("ex1"), t) 1183 } 1184 1185 func TestCatchVarNotUsedInStashlessFunc(t *testing.T) { 1186 const SCRIPT = ` 1187 function f() { 1188 var ex; 1189 try { 1190 throw "ex1"; 1191 } catch (er1) { 1192 ex = "ok"; 1193 } 1194 return ex; 1195 } 1196 f(); 1197 ` 1198 testScript(SCRIPT, asciiString("ok"), t) 1199 } 1200 1201 func TestNew(t *testing.T) { 1202 const SCRIPT = ` 1203 function O() { 1204 this.x = 42; 1205 } 1206 1207 new O().x; 1208 ` 1209 1210 testScript(SCRIPT, intToValue(42), t) 1211 } 1212 1213 func TestStringConstructor(t *testing.T) { 1214 const SCRIPT = ` 1215 function F() { 1216 return String(33) + " " + String("cows"); 1217 } 1218 1219 F(); 1220 ` 1221 testScript(SCRIPT, asciiString("33 cows"), t) 1222 } 1223 1224 func TestError(t *testing.T) { 1225 const SCRIPT = ` 1226 function F() { 1227 return new Error("test"); 1228 } 1229 1230 var e = F(); 1231 e.message == "test" && e.name == "Error"; 1232 ` 1233 testScript(SCRIPT, valueTrue, t) 1234 } 1235 1236 func TestTypeError(t *testing.T) { 1237 const SCRIPT = ` 1238 function F() { 1239 return new TypeError("test"); 1240 } 1241 1242 var e = F(); 1243 e.message == "test" && e.name == "TypeError"; 1244 ` 1245 1246 testScript(SCRIPT, valueTrue, t) 1247 } 1248 1249 func TestToString(t *testing.T) { 1250 const SCRIPT = ` 1251 var o = {x: 42}; 1252 o.toString = function() { 1253 return String(this.x); 1254 } 1255 1256 var o1 = {}; 1257 o.toString() + " ### " + o1.toString(); 1258 ` 1259 testScript(SCRIPT, asciiString("42 ### [object Object]"), t) 1260 } 1261 1262 func TestEvalOrder(t *testing.T) { 1263 const SCRIPT = ` 1264 var o = {f: function() {return 42}, x: 0}; 1265 var trace = ""; 1266 1267 function F1() { 1268 trace += "First!"; 1269 return o; 1270 } 1271 1272 function F2() { 1273 trace += "Second!"; 1274 return "f"; 1275 } 1276 1277 function F3() { 1278 trace += "Third!"; 1279 } 1280 1281 var rv = F1()[F2()](F3()); 1282 rv += trace; 1283 rv; 1284 ` 1285 1286 testScript(SCRIPT, asciiString("42First!Second!Third!"), t) 1287 } 1288 1289 func TestPostfixIncBracket(t *testing.T) { 1290 const SCRIPT = ` 1291 var o = {x: 42}; 1292 var trace = ""; 1293 1294 function F1() { 1295 trace += "First!"; 1296 return o; 1297 } 1298 1299 function F2() { 1300 trace += "Second!"; 1301 return "x"; 1302 } 1303 1304 1305 var rv = F1()[F2()]++; 1306 rv + trace + o.x; 1307 ` 1308 testScript(SCRIPT, asciiString("42First!Second!43"), t) 1309 } 1310 1311 func TestPostfixIncDot(t *testing.T) { 1312 const SCRIPT = ` 1313 var o = {x: 42}; 1314 var trace = ""; 1315 1316 function F1() { 1317 trace += "First!"; 1318 return o; 1319 } 1320 1321 var rv = F1().x++; 1322 rv + trace + o.x; 1323 ` 1324 testScript(SCRIPT, asciiString("42First!43"), t) 1325 } 1326 1327 func TestPrefixIncBracket(t *testing.T) { 1328 const SCRIPT = ` 1329 var o = {x: 42}; 1330 var trace = ""; 1331 1332 function F1() { 1333 trace += "First!"; 1334 return o; 1335 } 1336 1337 function F2() { 1338 trace += "Second!"; 1339 return "x"; 1340 } 1341 1342 1343 var rv = ++F1()[F2()]; 1344 rv + trace + o.x; 1345 ` 1346 testScript(SCRIPT, asciiString("43First!Second!43"), t) 1347 } 1348 1349 func TestPrefixIncDot(t *testing.T) { 1350 const SCRIPT = ` 1351 var o = {x: 42}; 1352 var trace = ""; 1353 1354 function F1() { 1355 trace += "First!"; 1356 return o; 1357 } 1358 1359 var rv = ++F1().x; 1360 rv + trace + o.x; 1361 ` 1362 testScript(SCRIPT, asciiString("43First!43"), t) 1363 } 1364 1365 func TestPostDecObj(t *testing.T) { 1366 const SCRIPT = ` 1367 var object = {valueOf: function() {return 1}}; 1368 var y = object--; 1369 var ok = false; 1370 if (y === 1) { 1371 ok = true; 1372 } 1373 ok; 1374 ` 1375 1376 testScript(SCRIPT, valueTrue, t) 1377 } 1378 1379 func TestPropAcc1(t *testing.T) { 1380 const SCRIPT = ` 1381 1..toString() 1382 ` 1383 1384 testScript(SCRIPT, asciiString("1"), t) 1385 } 1386 1387 func TestEvalDirect(t *testing.T) { 1388 const SCRIPT = ` 1389 var rv = false; 1390 function foo(){ rv = true; } 1391 1392 var o = { }; 1393 function f() { 1394 try { 1395 eval("o.bar( foo() );"); 1396 } catch (e) { 1397 } 1398 } 1399 f(); 1400 rv; 1401 ` 1402 testScript(SCRIPT, valueTrue, t) 1403 } 1404 1405 func TestEvalRet(t *testing.T) { 1406 const SCRIPT = ` 1407 eval("for (var i = 0; i < 3; i++) {i}") 1408 ` 1409 1410 testScript(SCRIPT, valueInt(2), t) 1411 } 1412 1413 func TestEvalFunctionDecl(t *testing.T) { 1414 const SCRIPT = ` 1415 eval("function F() {}") 1416 ` 1417 1418 testScript(SCRIPT, _undefined, t) 1419 } 1420 1421 func TestEvalFunctionExpr(t *testing.T) { 1422 const SCRIPT = ` 1423 eval("(function F() {return 42;})")() 1424 ` 1425 1426 testScript(SCRIPT, intToValue(42), t) 1427 } 1428 1429 func TestEvalDirectScope(t *testing.T) { 1430 const SCRIPT = ` 1431 var __10_4_2_1_3 = "str"; 1432 function testcase() { 1433 var __10_4_2_1_3 = "str1"; 1434 try { 1435 throw "error"; 1436 } catch (e) { 1437 var __10_4_2_1_3 = "str2"; 1438 return eval("__10_4_2_1_3"); 1439 } 1440 } 1441 testcase(); 1442 ` 1443 1444 testScript(SCRIPT, asciiString("str2"), t) 1445 } 1446 1447 func TestEvalDirectScope1(t *testing.T) { 1448 const SCRIPT = ` 1449 'use strict'; 1450 var __10_4_2_1_5 = "str"; 1451 function testcase() { 1452 var __10_4_2_1_5 = "str1"; 1453 var r = eval("\ 1454 var __10_4_2_1_5 = \'str2\'; \ 1455 eval(\"\'str2\' === __10_4_2_1_5\")\ 1456 "); 1457 return r; 1458 } 1459 testcase(); 1460 ` 1461 1462 testScript(SCRIPT, valueTrue, t) 1463 } 1464 1465 func TestEvalDirectCreateBinding(t *testing.T) { 1466 const SCRIPT = ` 1467 function f() { 1468 eval("var x = true"); 1469 return x; 1470 } 1471 var res = f(); 1472 var thrown = false; 1473 try { 1474 x; 1475 } catch(e) { 1476 if (e instanceof ReferenceError) { 1477 thrown = true; 1478 } else { 1479 throw e; 1480 } 1481 } 1482 res && thrown; 1483 ` 1484 1485 testScript(SCRIPT, valueTrue, t) 1486 } 1487 1488 func TestEvalDirectCreateBinding1(t *testing.T) { 1489 const SCRIPT = ` 1490 function f() { 1491 eval("let x = 1; var y = 2; function f1() {return x};"); 1492 assert.throws(ReferenceError, function() { x }); 1493 return ""+y+f1(); 1494 } 1495 f(); 1496 ` 1497 1498 testScriptWithTestLib(SCRIPT, asciiString("21"), t) 1499 } 1500 1501 func TestEvalDirectCreateBinding3(t *testing.T) { 1502 const SCRIPT = ` 1503 function f() { 1504 let x; 1505 try { 1506 eval("var y=1, x=2"); 1507 } catch(e) {} 1508 return y; 1509 } 1510 assert.throws(ReferenceError, f); 1511 ` 1512 1513 testScriptWithTestLib(SCRIPT, _undefined, t) 1514 } 1515 1516 func TestEvalGlobalStrict(t *testing.T) { 1517 const SCRIPT = ` 1518 'use strict'; 1519 var evalStr = 1520 'for (var x in this) {\n'+ 1521 ' if ( x === \'Math\' ) {\n'+ 1522 ' }\n'+ 1523 '}\n'; 1524 1525 eval(evalStr); 1526 ` 1527 1528 testScript(SCRIPT, _undefined, t) 1529 } 1530 1531 func TestEvalEmptyStrict(t *testing.T) { 1532 const SCRIPT = ` 1533 'use strict'; 1534 eval(""); 1535 ` 1536 1537 testScript(SCRIPT, _undefined, t) 1538 } 1539 1540 func TestEvalFuncDecl(t *testing.T) { 1541 const SCRIPT = ` 1542 'use strict'; 1543 var funcA = eval("function __funcA(__arg){return __arg;}; __funcA"); 1544 typeof funcA; 1545 ` 1546 1547 testScript(SCRIPT, asciiString("function"), t) 1548 } 1549 1550 func TestGetAfterSet(t *testing.T) { 1551 const SCRIPT = ` 1552 function f() { 1553 var x = 1; 1554 return x; 1555 } 1556 ` 1557 1558 testScript(SCRIPT, _undefined, t) 1559 } 1560 1561 func TestForLoopRet(t *testing.T) { 1562 const SCRIPT = ` 1563 for (var i = 0; i < 20; i++) { if (i > 2) {break;} else { i }} 1564 ` 1565 1566 testScript(SCRIPT, _undefined, t) 1567 } 1568 1569 func TestForLoopRet1(t *testing.T) { 1570 const SCRIPT = ` 1571 for (var i = 0; i < 20; i++) { if (i > 2) {42;; {L:{break;}}} else { i }} 1572 ` 1573 1574 testScript(SCRIPT, intToValue(42), t) 1575 } 1576 1577 func TestForInLoopRet(t *testing.T) { 1578 const SCRIPT = ` 1579 var o = [1, 2, 3, 4]; 1580 for (var i in o) { if (i > 2) {break;} else { i }} 1581 ` 1582 1583 testScript(SCRIPT, _undefined, t) 1584 } 1585 1586 func TestForInLoopRet1(t *testing.T) { 1587 const SCRIPT = ` 1588 var o = {}; 1589 o.x = 1; 1590 o.y = 2; 1591 for (var i in o) { 1592 true; 1593 } 1594 1595 ` 1596 1597 testScript(SCRIPT, valueTrue, t) 1598 } 1599 1600 func TestDoWhileLoopRet(t *testing.T) { 1601 const SCRIPT = ` 1602 var i = 0; 1603 do { 1604 if (i > 2) { 1605 break; 1606 } else { 1607 i; 1608 } 1609 } while (i++ < 20); 1610 ` 1611 1612 testScript(SCRIPT, _undefined, t) 1613 } 1614 1615 func TestDoWhileContinueRet(t *testing.T) { 1616 const SCRIPT = ` 1617 var i = 0; 1618 do { 1619 if (i > 2) { 1620 true; 1621 continue; 1622 } else { 1623 i; 1624 } 1625 } while (i++ < 20); 1626 ` 1627 1628 testScript(SCRIPT, valueTrue, t) 1629 } 1630 1631 func TestWhileLoopRet(t *testing.T) { 1632 const SCRIPT = ` 1633 var i; while (i < 20) { if (i > 2) {break;} else { i++ }} 1634 ` 1635 1636 testScript(SCRIPT, _undefined, t) 1637 } 1638 1639 func TestLoopRet1(t *testing.T) { 1640 const SCRIPT = ` 1641 for (var i = 0; i < 20; i++) { } 1642 ` 1643 1644 testScript(SCRIPT, _undefined, t) 1645 } 1646 1647 func TestInstanceof(t *testing.T) { 1648 const SCRIPT = ` 1649 var rv; 1650 try { 1651 true(); 1652 } catch (e) { 1653 rv = e instanceof TypeError; 1654 } 1655 rv; 1656 ` 1657 1658 testScript(SCRIPT, valueTrue, t) 1659 } 1660 1661 func TestStrictAssign(t *testing.T) { 1662 const SCRIPT = ` 1663 'use strict'; 1664 var rv; 1665 var called = false; 1666 function F() { 1667 called = true; 1668 return 1; 1669 } 1670 try { 1671 x = F(); 1672 } catch (e) { 1673 rv = e instanceof ReferenceError; 1674 } 1675 rv + " " + called; 1676 ` 1677 1678 testScript(SCRIPT, asciiString("true true"), t) 1679 } 1680 1681 func TestStrictScope(t *testing.T) { 1682 const SCRIPT = ` 1683 var rv; 1684 var called = false; 1685 function F() { 1686 'use strict'; 1687 x = 1; 1688 } 1689 try { 1690 F(); 1691 } catch (e) { 1692 rv = e instanceof ReferenceError; 1693 } 1694 x = 1; 1695 rv + " " + x; 1696 ` 1697 1698 testScript(SCRIPT, asciiString("true 1"), t) 1699 } 1700 1701 func TestStringObj(t *testing.T) { 1702 const SCRIPT = ` 1703 var s = new String("test"); 1704 s[0] + s[2] + s[1]; 1705 ` 1706 1707 testScript(SCRIPT, asciiString("tse"), t) 1708 } 1709 1710 func TestStringPrimitive(t *testing.T) { 1711 const SCRIPT = ` 1712 var s = "test"; 1713 s[0] + s[2] + s[1]; 1714 ` 1715 1716 testScript(SCRIPT, asciiString("tse"), t) 1717 } 1718 1719 func TestCallGlobalObject(t *testing.T) { 1720 const SCRIPT = ` 1721 var rv; 1722 try { 1723 this(); 1724 } catch (e) { 1725 rv = e instanceof TypeError 1726 } 1727 rv; 1728 ` 1729 1730 testScript(SCRIPT, valueTrue, t) 1731 } 1732 1733 func TestFuncLength(t *testing.T) { 1734 const SCRIPT = ` 1735 function F(x, y) { 1736 1737 } 1738 F.length 1739 ` 1740 1741 testScript(SCRIPT, intToValue(2), t) 1742 } 1743 1744 func TestNativeFuncLength(t *testing.T) { 1745 const SCRIPT = ` 1746 eval.length + Object.defineProperty.length + String.length 1747 ` 1748 1749 testScript(SCRIPT, intToValue(5), t) 1750 } 1751 1752 func TestArguments(t *testing.T) { 1753 const SCRIPT = ` 1754 function F() { 1755 return arguments.length + " " + arguments[1]; 1756 } 1757 1758 F(1,2,3) 1759 ` 1760 1761 testScript(SCRIPT, asciiString("3 2"), t) 1762 } 1763 1764 func TestArgumentsPut(t *testing.T) { 1765 const SCRIPT = ` 1766 function F(x, y) { 1767 arguments[0] -= arguments[1]; 1768 return x; 1769 } 1770 1771 F(5, 2) 1772 ` 1773 1774 testScript(SCRIPT, intToValue(3), t) 1775 } 1776 1777 func TestArgumentsPutStrict(t *testing.T) { 1778 const SCRIPT = ` 1779 function F(x, y) { 1780 'use strict'; 1781 arguments[0] -= arguments[1]; 1782 return x; 1783 } 1784 1785 F(5, 2) 1786 ` 1787 1788 testScript(SCRIPT, intToValue(5), t) 1789 } 1790 1791 func TestArgumentsExtra(t *testing.T) { 1792 const SCRIPT = ` 1793 function F(x, y) { 1794 return arguments[2]; 1795 } 1796 1797 F(1, 2, 42) 1798 ` 1799 1800 testScript(SCRIPT, intToValue(42), t) 1801 } 1802 1803 func TestArgumentsExist(t *testing.T) { 1804 const SCRIPT = ` 1805 function F(x, arguments) { 1806 return arguments; 1807 } 1808 1809 F(1, 42) 1810 ` 1811 1812 testScript(SCRIPT, intToValue(42), t) 1813 } 1814 1815 func TestArgumentsDelete(t *testing.T) { 1816 const SCRIPT = ` 1817 function f(x) { 1818 delete arguments[0]; 1819 arguments[0] = 42; 1820 return x; 1821 } 1822 f(1) 1823 ` 1824 1825 testScript(SCRIPT, intToValue(1), t) 1826 } 1827 1828 func TestArgumentsInEval(t *testing.T) { 1829 const SCRIPT = ` 1830 function f() { 1831 return eval("arguments"); 1832 } 1833 f(1)[0]; 1834 ` 1835 1836 testScript(SCRIPT, intToValue(1), t) 1837 } 1838 1839 func TestArgumentsRedeclareInEval(t *testing.T) { 1840 const SCRIPT = ` 1841 assert.sameValue("arguments" in this, false, "No global 'arguments' binding"); 1842 1843 function f(p = eval("var arguments = 'param'"), arguments) {} 1844 assert.throws(SyntaxError, f); 1845 1846 assert.sameValue("arguments" in this, false, "No global 'arguments' binding"); 1847 ` 1848 1849 testScriptWithTestLib(SCRIPT, _undefined, t) 1850 } 1851 1852 func TestArgumentsRedeclareArrow(t *testing.T) { 1853 const SCRIPT = ` 1854 const oldArguments = globalThis.arguments; 1855 let count = 0; 1856 const f = (p = eval("var arguments = 'param'"), q = () => arguments) => { 1857 var arguments = "local"; 1858 assert.sameValue(arguments, "local", "arguments"); 1859 assert.sameValue(q(), "param", "q"); 1860 count++; 1861 } 1862 f(); 1863 assert.sameValue(count, 1); 1864 assert.sameValue(globalThis.arguments, oldArguments, "globalThis.arguments unchanged"); 1865 ` 1866 testScriptWithTestLib(SCRIPT, _undefined, t) 1867 } 1868 1869 func TestEvalParamWithDef(t *testing.T) { 1870 const SCRIPT = ` 1871 function f(param = 0) { 1872 eval("var param = 1"); 1873 return param; 1874 } 1875 f(); 1876 ` 1877 1878 testScript(SCRIPT, valueInt(1), t) 1879 } 1880 1881 func TestArgumentsRedefinedAsLetDyn(t *testing.T) { 1882 const SCRIPT = ` 1883 function f() { 1884 let arguments; 1885 eval(""); // force dynamic scope 1886 return arguments; 1887 } 1888 1889 f(1,2); 1890 ` 1891 1892 testScript(SCRIPT, _undefined, t) 1893 } 1894 1895 func TestWith(t *testing.T) { 1896 const SCRIPT = ` 1897 var b = 1; 1898 var o = {a: 41}; 1899 with(o) { 1900 a += b; 1901 } 1902 o.a; 1903 1904 ` 1905 1906 testScript(SCRIPT, intToValue(42), t) 1907 } 1908 1909 func TestWithInFunc(t *testing.T) { 1910 const SCRIPT = ` 1911 function F() { 1912 var b = 1; 1913 var c = 0; 1914 var o = {a: 40, c: 1}; 1915 with(o) { 1916 a += b + c; 1917 } 1918 return o.a; 1919 } 1920 1921 F(); 1922 ` 1923 1924 testScript(SCRIPT, intToValue(42), t) 1925 } 1926 1927 func TestAssignNonExtendable(t *testing.T) { 1928 const SCRIPT = ` 1929 'use strict'; 1930 1931 function F() { 1932 this.x = 1; 1933 } 1934 1935 var o = new F(); 1936 Object.preventExtensions(o); 1937 o.x = 42; 1938 o.x; 1939 ` 1940 1941 testScript(SCRIPT, intToValue(42), t) 1942 } 1943 1944 func TestAssignNonExtendable1(t *testing.T) { 1945 const SCRIPT = ` 1946 'use strict'; 1947 1948 function F() { 1949 } 1950 1951 var o = new F(); 1952 var rv; 1953 1954 Object.preventExtensions(o); 1955 try { 1956 o.x = 42; 1957 } catch (e) { 1958 rv = e.constructor === TypeError; 1959 } 1960 1961 rv += " " + o.x; 1962 rv; 1963 ` 1964 1965 testScript(SCRIPT, asciiString("true undefined"), t) 1966 } 1967 1968 func TestAssignStrict(t *testing.T) { 1969 const SCRIPT = ` 1970 'use strict'; 1971 1972 try { 1973 eval("eval = 42"); 1974 } catch(e) { 1975 var rv = e instanceof SyntaxError 1976 } 1977 rv; 1978 ` 1979 1980 testScript(SCRIPT, valueTrue, t) 1981 } 1982 1983 func TestIllegalArgmentName(t *testing.T) { 1984 const SCRIPT = ` 1985 'use strict'; 1986 1987 try { 1988 eval("function F(eval) {}"); 1989 } catch (e) { 1990 var rv = e instanceof SyntaxError 1991 } 1992 rv; 1993 ` 1994 1995 testScript(SCRIPT, valueTrue, t) 1996 } 1997 1998 func TestFunction(t *testing.T) { 1999 const SCRIPT = ` 2000 2001 var f0 = Function(""); 2002 var f1 = Function("return ' one'"); 2003 var f2 = Function("arg", "return ' ' + arg"); 2004 f0() + f1() + f2("two"); 2005 ` 2006 2007 testScript(SCRIPT, asciiString("undefined one two"), t) 2008 } 2009 2010 func TestFunction1(t *testing.T) { 2011 const SCRIPT = ` 2012 2013 var f = function f1(count) { 2014 if (count == 0) { 2015 return true; 2016 } 2017 return f1(count-1); 2018 } 2019 2020 f(1); 2021 ` 2022 2023 testScript(SCRIPT, valueTrue, t) 2024 } 2025 2026 func TestFunction2(t *testing.T) { 2027 const SCRIPT = ` 2028 var trace = ""; 2029 function f(count) { 2030 trace += "f("+count+")"; 2031 if (count == 0) { 2032 return; 2033 } 2034 return f(count-1); 2035 } 2036 2037 function f1() { 2038 trace += "f1"; 2039 } 2040 2041 var f2 = f; 2042 f = f1; 2043 f2(1); 2044 trace; 2045 2046 ` 2047 2048 testScript(SCRIPT, asciiString("f(1)f1"), t) 2049 } 2050 2051 func TestFunctionToString(t *testing.T) { 2052 const SCRIPT = ` 2053 2054 Function("arg1", "arg2", "return 42").toString(); 2055 ` 2056 2057 testScript(SCRIPT, asciiString("function anonymous(arg1,arg2\n) {\nreturn 42\n}"), t) 2058 } 2059 2060 func TestObjectLiteral(t *testing.T) { 2061 const SCRIPT = ` 2062 var getterCalled = false; 2063 var setterCalled = false; 2064 2065 var o = {get x() {getterCalled = true}, set x(_) {setterCalled = true}}; 2066 2067 o.x; 2068 o.x = 42; 2069 2070 getterCalled && setterCalled; 2071 ` 2072 2073 testScript(SCRIPT, valueTrue, t) 2074 } 2075 2076 func TestConst(t *testing.T) { 2077 const SCRIPT = ` 2078 2079 var v1 = true && true; 2080 var v2 = 1/(-1 * 0); 2081 var v3 = 1 == 2 || v1; 2082 var v4 = true && false 2083 v1 === true && v2 === -Infinity && v3 === v1 && v4 === false; 2084 ` 2085 2086 testScript(SCRIPT, valueTrue, t) 2087 } 2088 2089 func TestConstWhile(t *testing.T) { 2090 const SCRIPT = ` 2091 var c = 0; 2092 while (2 + 2 === 4) { 2093 if (++c > 9) { 2094 break; 2095 } 2096 } 2097 c === 10; 2098 ` 2099 2100 testScript(SCRIPT, valueTrue, t) 2101 } 2102 2103 func TestConstWhileThrow(t *testing.T) { 2104 const SCRIPT = ` 2105 var thrown = false; 2106 try { 2107 while ('s' in true) { 2108 break; 2109 } 2110 } catch (e) { 2111 thrown = e instanceof TypeError 2112 } 2113 thrown; 2114 ` 2115 2116 testScript(SCRIPT, valueTrue, t) 2117 } 2118 2119 func TestDupParams(t *testing.T) { 2120 const SCRIPT = ` 2121 function F(x, y, x) { 2122 return x; 2123 } 2124 2125 F(1, 2); 2126 ` 2127 2128 testScript(SCRIPT, _undefined, t) 2129 } 2130 2131 func TestUseUnsuppliedParam(t *testing.T) { 2132 const SCRIPT = ` 2133 function getMessage(message) { 2134 if (message === undefined) { 2135 message = ''; 2136 } 2137 message += " 123 456"; 2138 return message; 2139 } 2140 2141 getMessage(); 2142 ` 2143 2144 testScript(SCRIPT, asciiString(" 123 456"), t) 2145 } 2146 2147 func TestForInLetWithInitializer(t *testing.T) { 2148 const SCRIPT = `for (let x = 3 in {}) { }` 2149 _, err := Compile("", SCRIPT, false) 2150 if err == nil { 2151 t.Fatal("Expected error") 2152 } 2153 } 2154 2155 func TestForInLoop(t *testing.T) { 2156 const SCRIPT = ` 2157 function Proto() {} 2158 Proto.prototype.x = 42; 2159 var o = new Proto(); 2160 o.y = 44; 2161 o.x = 45; 2162 var hasX = false; 2163 var hasY = false; 2164 2165 for (var i in o) { 2166 switch(i) { 2167 case "x": 2168 if (hasX) { 2169 throw new Error("Already has X"); 2170 } 2171 hasX = true; 2172 break; 2173 case "y": 2174 if (hasY) { 2175 throw new Error("Already has Y"); 2176 } 2177 hasY = true; 2178 break; 2179 } 2180 } 2181 2182 hasX && hasY; 2183 ` 2184 2185 testScript(SCRIPT, valueTrue, t) 2186 } 2187 2188 func TestWhileLoopResult(t *testing.T) { 2189 const SCRIPT = ` 2190 while(false); 2191 2192 ` 2193 2194 testScript(SCRIPT, _undefined, t) 2195 } 2196 2197 func TestEmptySwitch(t *testing.T) { 2198 const SCRIPT = ` 2199 switch(1){} 2200 ` 2201 2202 testScript(SCRIPT, _undefined, t) 2203 } 2204 2205 func TestEmptyDoWhile(t *testing.T) { 2206 const SCRIPT = ` 2207 do {} while(false) 2208 ` 2209 2210 testScript(SCRIPT, _undefined, t) 2211 } 2212 2213 func TestSwitch(t *testing.T) { 2214 const SCRIPT = ` 2215 function F(x) { 2216 var i = 0; 2217 switch (x) { 2218 case 0: 2219 i++; 2220 case 1: 2221 i++; 2222 default: 2223 i++; 2224 case 2: 2225 i++; 2226 break; 2227 case 3: 2228 i++; 2229 } 2230 return i; 2231 } 2232 2233 F(0) + F(1) + F(2) + F(4); 2234 2235 ` 2236 2237 testScript(SCRIPT, intToValue(10), t) 2238 } 2239 2240 func TestSwitchDefFirst(t *testing.T) { 2241 const SCRIPT = ` 2242 function F(x) { 2243 var i = 0; 2244 switch (x) { 2245 default: 2246 i++; 2247 case 0: 2248 i++; 2249 case 1: 2250 i++; 2251 case 2: 2252 i++; 2253 break; 2254 case 3: 2255 i++; 2256 } 2257 return i; 2258 } 2259 2260 F(0) + F(1) + F(2) + F(4); 2261 2262 ` 2263 2264 testScript(SCRIPT, intToValue(10), t) 2265 } 2266 2267 func TestSwitchResult(t *testing.T) { 2268 const SCRIPT = ` 2269 var x = 2; 2270 2271 switch (x) { 2272 case 0: 2273 "zero"; 2274 case 1: 2275 "one"; 2276 case 2: 2277 "two"; 2278 break; 2279 case 3: 2280 "three"; 2281 default: 2282 "default"; 2283 } 2284 ` 2285 2286 testScript(SCRIPT, asciiString("two"), t) 2287 } 2288 2289 func TestSwitchResult1(t *testing.T) { 2290 const SCRIPT = ` 2291 var x = 0; 2292 switch (x) { case 0: "two"; case 1: break} 2293 ` 2294 2295 testScript(SCRIPT, asciiString("two"), t) 2296 } 2297 2298 func TestSwitchResult2(t *testing.T) { 2299 const SCRIPT = ` 2300 6; switch ("a") { case "a": 7; case "b": } 2301 ` 2302 2303 testScript(SCRIPT, valueInt(7), t) 2304 } 2305 2306 func TestSwitchResultJumpIntoEmptyEval(t *testing.T) { 2307 const SCRIPT = ` 2308 function t(x) { 2309 return eval("switch(x) { case 1: 2; break; case 2: let x = 1; case 3: x+2; break; case 4: default: 9}"); 2310 } 2311 ""+t(2)+t(); 2312 ` 2313 2314 testScript(SCRIPT, asciiString("39"), t) 2315 } 2316 2317 func TestSwitchResultJumpIntoEmpty(t *testing.T) { 2318 const SCRIPT = ` 2319 switch(2) { case 1: 2; break; case 2: let x = 1; case 3: x+2; case 4: {let y = 2}; break; default: 9}; 2320 ` 2321 2322 testScript(SCRIPT, valueInt(3), t) 2323 } 2324 2325 func TestSwitchLexical(t *testing.T) { 2326 const SCRIPT = ` 2327 switch (true) { case true: let x = 1; } 2328 ` 2329 2330 testScript(SCRIPT, _undefined, t) 2331 } 2332 2333 func TestSwitchBreakOuter(t *testing.T) { 2334 const SCRIPT = ` 2335 LOOP: 2336 for (let i = 0; i < 10; i++) { 2337 switch (i) { 2338 case 0: 2339 continue; 2340 case 1: 2341 let x = 1; 2342 continue; 2343 case 2: 2344 try { 2345 x++; 2346 } catch (e) { 2347 if (e instanceof ReferenceError) { 2348 break LOOP; 2349 } 2350 } 2351 throw new Error("Exception was not thrown"); 2352 } 2353 } 2354 ` 2355 2356 testScript(SCRIPT, _undefined, t) 2357 } 2358 2359 func TestIfBreakResult(t *testing.T) { 2360 const SCRIPT = ` 2361 L: {if (true) {42;} break L;} 2362 ` 2363 2364 testScript(SCRIPT, intToValue(42), t) 2365 } 2366 2367 func TestSwitchNoMatch(t *testing.T) { 2368 const SCRIPT = ` 2369 var result; 2370 var x; 2371 switch (x) { 2372 case 0: 2373 result = "2"; 2374 break; 2375 } 2376 2377 result; 2378 2379 ` 2380 2381 testScript(SCRIPT, _undefined, t) 2382 } 2383 2384 func TestSwitchNoMatchNoDefault(t *testing.T) { 2385 const SCRIPT = ` 2386 switch (1) { 2387 case 0: 2388 } 2389 ` 2390 2391 testScript(SCRIPT, _undefined, t) 2392 } 2393 2394 func TestSwitchNoMatchNoDefaultNoResult(t *testing.T) { 2395 const SCRIPT = ` 2396 switch (1) { 2397 case 0: 2398 } 2399 42; 2400 ` 2401 2402 testScript(SCRIPT, intToValue(42), t) 2403 } 2404 2405 func TestSwitchNoMatchNoDefaultNoResultMatch(t *testing.T) { 2406 const SCRIPT = ` 2407 switch (1) { 2408 case 1: 2409 } 2410 42; 2411 ` 2412 2413 testScript(SCRIPT, intToValue(42), t) 2414 } 2415 2416 func TestEmptySwitchNoResult(t *testing.T) { 2417 const SCRIPT = ` 2418 switch (1) {} 2419 42; 2420 ` 2421 2422 testScript(SCRIPT, intToValue(42), t) 2423 } 2424 2425 func TestGetOwnPropertyNames(t *testing.T) { 2426 const SCRIPT = ` 2427 var o = { 2428 prop1: 42, 2429 prop2: "test" 2430 } 2431 2432 var hasProp1 = false; 2433 var hasProp2 = false; 2434 2435 var names = Object.getOwnPropertyNames(o); 2436 for (var i in names) { 2437 var p = names[i]; 2438 switch(p) { 2439 case "prop1": 2440 hasProp1 = true; 2441 break; 2442 case "prop2": 2443 hasProp2 = true; 2444 break; 2445 } 2446 } 2447 2448 hasProp1 && hasProp2; 2449 ` 2450 2451 testScript(SCRIPT, valueTrue, t) 2452 } 2453 2454 func TestArrayLiteral(t *testing.T) { 2455 const SCRIPT = ` 2456 2457 var f1Called = false; 2458 var f2Called = false; 2459 var f3Called = false; 2460 var errorThrown = false; 2461 2462 function F1() { 2463 f1Called = true; 2464 } 2465 2466 function F2() { 2467 f2Called = true; 2468 } 2469 2470 function F3() { 2471 f3Called = true; 2472 } 2473 2474 2475 try { 2476 var a = [F1(), x(F3()), F2()]; 2477 } catch(e) { 2478 if (e instanceof ReferenceError) { 2479 errorThrown = true; 2480 } else { 2481 throw e; 2482 } 2483 } 2484 2485 f1Called && !f2Called && f3Called && errorThrown && a === undefined; 2486 ` 2487 2488 testScript(SCRIPT, valueTrue, t) 2489 } 2490 2491 func TestJumpOutOfReturn(t *testing.T) { 2492 const SCRIPT = ` 2493 function f() { 2494 var a; 2495 if (a == 0) { 2496 return true; 2497 } 2498 } 2499 2500 f(); 2501 ` 2502 2503 testScript(SCRIPT, _undefined, t) 2504 } 2505 2506 func TestSwitchJumpOutOfReturn(t *testing.T) { 2507 const SCRIPT = ` 2508 function f(x) { 2509 switch(x) { 2510 case 0: 2511 break; 2512 default: 2513 return x; 2514 } 2515 } 2516 2517 f(0); 2518 ` 2519 2520 testScript(SCRIPT, _undefined, t) 2521 } 2522 2523 func TestSetToReadOnlyPropertyStrictBracket(t *testing.T) { 2524 const SCRIPT = ` 2525 'use strict'; 2526 2527 var o = {}; 2528 var thrown = false; 2529 Object.defineProperty(o, "test", {value: 42, configurable: true}); 2530 try { 2531 o["test"] = 43; 2532 } catch (e) { 2533 thrown = e instanceof TypeError; 2534 } 2535 2536 thrown; 2537 ` 2538 2539 testScript(SCRIPT, valueTrue, t) 2540 } 2541 2542 func TestSetToReadOnlyPropertyStrictDot(t *testing.T) { 2543 const SCRIPT = ` 2544 'use strict'; 2545 2546 var o = {}; 2547 var thrown = false; 2548 Object.defineProperty(o, "test", {value: 42, configurable: true}); 2549 try { 2550 o.test = 43; 2551 } catch (e) { 2552 thrown = e instanceof TypeError; 2553 } 2554 2555 thrown; 2556 ` 2557 2558 testScript(SCRIPT, valueTrue, t) 2559 } 2560 2561 func TestDeleteNonConfigurablePropertyStrictBracket(t *testing.T) { 2562 const SCRIPT = ` 2563 'use strict'; 2564 2565 var o = {}; 2566 var thrown = false; 2567 Object.defineProperty(o, "test", {value: 42}); 2568 try { 2569 delete o["test"]; 2570 } catch (e) { 2571 thrown = e instanceof TypeError; 2572 } 2573 2574 thrown; 2575 ` 2576 2577 testScript(SCRIPT, valueTrue, t) 2578 } 2579 2580 func TestDeleteNonConfigurablePropertyStrictDot(t *testing.T) { 2581 const SCRIPT = ` 2582 'use strict'; 2583 2584 var o = {}; 2585 var thrown = false; 2586 Object.defineProperty(o, "test", {value: 42}); 2587 try { 2588 delete o.test; 2589 } catch (e) { 2590 thrown = e instanceof TypeError; 2591 } 2592 2593 thrown; 2594 ` 2595 2596 testScript(SCRIPT, valueTrue, t) 2597 } 2598 2599 func TestCompound1(t *testing.T) { 2600 const SCRIPT = ` 2601 var x = 0; 2602 var scope = {x: 1}; 2603 var f; 2604 with (scope) { 2605 f = function() { 2606 x *= (delete scope.x, 2); 2607 } 2608 } 2609 f(); 2610 2611 scope.x === 2 && x === 0; 2612 2613 ` 2614 2615 testScript(SCRIPT, valueTrue, t) 2616 } 2617 2618 func TestCompound2(t *testing.T) { 2619 const SCRIPT = ` 2620 2621 var x; 2622 x = "x"; 2623 x ^= "1"; 2624 2625 ` 2626 testScript(SCRIPT, intToValue(1), t) 2627 } 2628 2629 func TestDeleteArguments(t *testing.T) { 2630 defer func() { 2631 if _, ok := recover().(*CompilerSyntaxError); !ok { 2632 t.Fatal("Expected syntax error") 2633 } 2634 }() 2635 const SCRIPT = ` 2636 'use strict'; 2637 2638 function f() { 2639 delete arguments; 2640 } 2641 2642 ` 2643 testScript(SCRIPT, _undefined, t) 2644 } 2645 2646 func TestReturnUndefined(t *testing.T) { 2647 const SCRIPT = ` 2648 function f() { 2649 return x; 2650 } 2651 2652 var thrown = false; 2653 try { 2654 f(); 2655 } catch (e) { 2656 thrown = e instanceof ReferenceError; 2657 } 2658 2659 thrown; 2660 ` 2661 testScript(SCRIPT, valueTrue, t) 2662 } 2663 2664 func TestForBreak(t *testing.T) { 2665 const SCRIPT = ` 2666 var supreme, count; 2667 supreme = 5; 2668 var __evaluated = eval("for(count=0;;) {if (count===supreme)break;else count++; }"); 2669 if (__evaluated !== void 0) { 2670 throw new Error('#1: __evaluated === 4. Actual: __evaluated ==='+ __evaluated ); 2671 } 2672 2673 ` 2674 testScript(SCRIPT, _undefined, t) 2675 } 2676 2677 func TestLargeNumberLiteral(t *testing.T) { 2678 const SCRIPT = ` 2679 var x = 0x800000000000000000000; 2680 x.toString(); 2681 ` 2682 testScript(SCRIPT, asciiString("9.671406556917033e+24"), t) 2683 } 2684 2685 func TestIncDelete(t *testing.T) { 2686 const SCRIPT = ` 2687 var o = {x: 1}; 2688 o.x += (delete o.x, 1); 2689 o.x; 2690 ` 2691 testScript(SCRIPT, intToValue(2), t) 2692 } 2693 2694 func TestCompoundAssignRefError(t *testing.T) { 2695 const SCRIPT = ` 2696 var thrown = false; 2697 try { 2698 a *= 1; 2699 } catch (e) { 2700 if (e instanceof ReferenceError) { 2701 thrown = true; 2702 } else { 2703 throw e; 2704 } 2705 } 2706 thrown; 2707 ` 2708 testScript(SCRIPT, valueTrue, t) 2709 } 2710 2711 func TestObjectLiteral__Proto__(t *testing.T) { 2712 const SCRIPT = ` 2713 var o = { 2714 __proto__: null, 2715 test: 42 2716 } 2717 2718 Object.getPrototypeOf(o); 2719 ` 2720 2721 testScript(SCRIPT, _null, t) 2722 } 2723 2724 func TestEmptyCodeError(t *testing.T) { 2725 if _, err := New().RunString(`i`); err == nil { 2726 t.Fatal("Expected an error") 2727 } else { 2728 if e := err.Error(); e != "ReferenceError: i is not defined at <eval>:1:1(0)" { 2729 t.Fatalf("Unexpected error: '%s'", e) 2730 } 2731 } 2732 } 2733 2734 func TestForOfArray(t *testing.T) { 2735 const SCRIPT = ` 2736 var array = [0, 'a', true, false, null, /* hole */, undefined, NaN]; 2737 var i = 0; 2738 2739 for (var value of array) { 2740 assert.sameValue(value, array[i], 'element at index ' + i); 2741 i++; 2742 } 2743 2744 assert.sameValue(i, 8, 'Visits all elements'); 2745 ` 2746 testScriptWithTestLib(SCRIPT, _undefined, t) 2747 } 2748 2749 func TestForOfReturn(t *testing.T) { 2750 const SCRIPT = ` 2751 var callCount = 0; 2752 var iterationCount = 0; 2753 var iterable = {}; 2754 var x = { 2755 set attr(_) { 2756 throw new Test262Error(); 2757 } 2758 }; 2759 2760 iterable[Symbol.iterator] = function() { 2761 return { 2762 next: function() { 2763 return { done: false, value: 0 }; 2764 }, 2765 return: function() { 2766 callCount += 1; 2767 } 2768 } 2769 }; 2770 2771 assert.throws(Test262Error, function() { 2772 for (x.attr of iterable) { 2773 iterationCount += 1; 2774 } 2775 }); 2776 2777 assert.sameValue(iterationCount, 0, 'The loop body is not evaluated'); 2778 assert.sameValue(callCount, 1, 'Iterator is closed'); 2779 ` 2780 testScriptWithTestLib(SCRIPT, _undefined, t) 2781 } 2782 2783 func TestForOfReturn1(t *testing.T) { 2784 const SCRIPT = ` 2785 var iterable = {}; 2786 var iterationCount = 0; 2787 2788 iterable[Symbol.iterator] = function() { 2789 return { 2790 next: function() { 2791 return { done: false, value: null }; 2792 }, 2793 get return() { 2794 throw new Test262Error(); 2795 } 2796 }; 2797 }; 2798 2799 assert.throws(Test262Error, function() { 2800 for (var x of iterable) { 2801 iterationCount += 1; 2802 break; 2803 } 2804 }); 2805 2806 assert.sameValue(iterationCount, 1, 'The loop body is evaluated'); 2807 ` 2808 testScriptWithTestLib(SCRIPT, _undefined, t) 2809 } 2810 2811 func TestForOfLet(t *testing.T) { 2812 const SCRIPT = ` 2813 var iterCount = 0; 2814 function f() {} 2815 for (var let of [23]) { 2816 f(let); 2817 if (let != 23) { 2818 throw new Error(""); 2819 } 2820 iterCount += 1; 2821 } 2822 2823 iterCount; 2824 ` 2825 testScript(SCRIPT, valueInt(1), t) 2826 } 2827 2828 func TestForOfLetLet(t *testing.T) { 2829 const SCRIPT = ` 2830 for (let let of [23]) { 2831 } 2832 ` 2833 _, err := Compile("", SCRIPT, false) 2834 if err == nil { 2835 t.Fatal("Expected error") 2836 } 2837 } 2838 2839 func TestForHeadLet(t *testing.T) { 2840 const SCRIPT = ` 2841 for (let = 0; let < 2; let++); 2842 ` 2843 testScript(SCRIPT, _undefined, t) 2844 } 2845 2846 func TestLhsLet(t *testing.T) { 2847 const SCRIPT = ` 2848 let = 1; 2849 let; 2850 ` 2851 testScript(SCRIPT, valueInt(1), t) 2852 } 2853 2854 func TestLetPostfixASI(t *testing.T) { 2855 const SCRIPT = ` 2856 let 2857 ++ 2858 ` 2859 _, err := Compile("", SCRIPT, false) 2860 if err == nil { 2861 t.Fatal("Expected error") 2862 } 2863 } 2864 2865 func TestIteratorReturnNormal(t *testing.T) { 2866 const SCRIPT = ` 2867 var iterable = {}; 2868 var iterationCount = 0; 2869 2870 iterable[Symbol.iterator] = function() { 2871 return { 2872 next: function() { 2873 return { done: ++iterationCount > 2, value: null }; 2874 }, 2875 get return() { 2876 throw new Test262Error(); 2877 } 2878 }; 2879 }; 2880 2881 for (var x of iterable) { 2882 } 2883 ` 2884 testScriptWithTestLib(SCRIPT, _undefined, t) 2885 } 2886 2887 func TestIteratorReturnErrorNested(t *testing.T) { 2888 const SCRIPT = ` 2889 var returnCalled = {}; 2890 function iter(id) { 2891 return function() { 2892 var count = 0; 2893 return { 2894 next: function () { 2895 return { 2896 value: null, 2897 done: ++count > 2 2898 }; 2899 }, 2900 return: function () { 2901 returnCalled[id] = true; 2902 throw new Error(id); 2903 } 2904 }; 2905 } 2906 } 2907 var iterable1 = {}; 2908 iterable1[Symbol.iterator] = iter("1"); 2909 var iterable2 = {}; 2910 iterable2[Symbol.iterator] = iter("2"); 2911 2912 try { 2913 for (var i of iterable1) { 2914 for (var j of iterable2) { 2915 break; 2916 } 2917 } 2918 throw new Error("no exception was thrown"); 2919 } catch (e) { 2920 if (e.message !== "2") { 2921 throw e; 2922 } 2923 } 2924 if (!returnCalled["1"]) { 2925 throw new Error("no return 1"); 2926 } 2927 if (!returnCalled["2"]) { 2928 throw new Error("no return 2"); 2929 } 2930 ` 2931 testScript(SCRIPT, _undefined, t) 2932 } 2933 2934 func TestReturnFromForInLoop(t *testing.T) { 2935 const SCRIPT = ` 2936 (function f() { 2937 for (var i in {a: 1}) { 2938 return true; 2939 } 2940 })(); 2941 ` 2942 testScript(SCRIPT, valueTrue, t) 2943 } 2944 2945 func TestReturnFromForOfLoop(t *testing.T) { 2946 const SCRIPT = ` 2947 (function f() { 2948 for (var i of [1]) { 2949 return true; 2950 } 2951 })(); 2952 ` 2953 testScript(SCRIPT, valueTrue, t) 2954 } 2955 2956 func TestIfStackLeaks(t *testing.T) { 2957 const SCRIPT = ` 2958 var t = 0; 2959 if (t === 0) { 2960 t; 2961 } 2962 ` 2963 testScript(SCRIPT, _positiveZero, t) 2964 } 2965 2966 func TestWithCallee(t *testing.T) { 2967 const SCRIPT = ` 2968 function O() { 2969 var that = this; 2970 this.m = function() { 2971 return this === that; 2972 } 2973 } 2974 with(new O()) { 2975 m(); 2976 } 2977 ` 2978 testScript(SCRIPT, valueTrue, t) 2979 } 2980 2981 func TestWithScope(t *testing.T) { 2982 const SCRIPT = ` 2983 function f(o) { 2984 var x = 42; 2985 2986 function innerf(o) { 2987 with (o) { 2988 return x; 2989 } 2990 } 2991 2992 return innerf(o); 2993 } 2994 f({}); 2995 ` 2996 testScript(SCRIPT, valueInt(42), t) 2997 } 2998 2999 func TestEvalCallee(t *testing.T) { 3000 const SCRIPT = ` 3001 (function () { 3002 'use strict'; 3003 var v = function() { 3004 return this === undefined; 3005 }; 3006 return eval('v()'); 3007 })(); 3008 ` 3009 testScript(SCRIPT, valueTrue, t) 3010 } 3011 3012 func TestEvalBindingDeleteVar(t *testing.T) { 3013 const SCRIPT = ` 3014 (function () { 3015 eval("var x = 1"); 3016 return x === 1 && delete x; 3017 })(); 3018 ` 3019 testScript(SCRIPT, valueTrue, t) 3020 } 3021 3022 func TestEvalBindingDeleteFunc(t *testing.T) { 3023 const SCRIPT = ` 3024 (function () { 3025 eval("function x(){}"); 3026 return typeof x === "function" && delete x; 3027 })(); 3028 ` 3029 testScript(SCRIPT, valueTrue, t) 3030 } 3031 3032 func TestDeleteGlobalLexical(t *testing.T) { 3033 const SCRIPT = ` 3034 let x; 3035 delete x; 3036 ` 3037 testScript(SCRIPT, valueFalse, t) 3038 } 3039 3040 func TestDeleteGlobalEval(t *testing.T) { 3041 const SCRIPT = ` 3042 eval("var x"); 3043 delete x; 3044 ` 3045 testScript(SCRIPT, valueTrue, t) 3046 } 3047 3048 func TestGlobalVarNames(t *testing.T) { 3049 vm := New() 3050 _, err := vm.RunString("(0,eval)('var x')") 3051 if err != nil { 3052 t.Fatal(err) 3053 } 3054 _, err = vm.RunString("let x") 3055 if err == nil { 3056 t.Fatal("Expected error") 3057 } 3058 } 3059 3060 func TestTryResultEmpty(t *testing.T) { 3061 const SCRIPT = ` 3062 1; try { } finally { } 3063 ` 3064 testScript(SCRIPT, _undefined, t) 3065 } 3066 3067 func TestTryResultEmptyCatch(t *testing.T) { 3068 const SCRIPT = ` 3069 1; try { throw null } catch(e) { } 3070 ` 3071 testScript(SCRIPT, _undefined, t) 3072 } 3073 3074 func TestTryResultEmptyContinueLoop(t *testing.T) { 3075 const SCRIPT = ` 3076 for (var i = 0; i < 2; i++) { try {throw null;} catch(e) {continue;} 'bad'} 3077 ` 3078 testScript(SCRIPT, _undefined, t) 3079 } 3080 3081 func TestTryEmptyCatchStackLeak(t *testing.T) { 3082 const SCRIPT = ` 3083 (function() { 3084 var f; 3085 // Make sure the outer function is not stashless. 3086 (function() { 3087 f++; 3088 })(); 3089 try { 3090 throw new Error(); 3091 } catch(e) {} 3092 })(); 3093 ` 3094 testScript(SCRIPT, _undefined, t) 3095 } 3096 3097 func TestTryThrowEmptyCatch(t *testing.T) { 3098 const SCRIPT = ` 3099 try { 3100 throw new Error(); 3101 } 3102 catch (e) {} 3103 ` 3104 testScript(SCRIPT, _undefined, t) 3105 } 3106 3107 func TestFalsyLoopBreak(t *testing.T) { 3108 const SCRIPT = ` 3109 while(false) { 3110 break; 3111 } 3112 for(;false;) { 3113 break; 3114 } 3115 undefined; 3116 ` 3117 MustCompile("", SCRIPT, false) 3118 } 3119 3120 func TestFalsyLoopBreakWithResult(t *testing.T) { 3121 const SCRIPT = ` 3122 while(false) { 3123 break; 3124 } 3125 ` 3126 testScript(SCRIPT, _undefined, t) 3127 } 3128 3129 func TestDummyCompile(t *testing.T) { 3130 const SCRIPT = ` 3131 'use strict'; 3132 3133 for (;false;) { 3134 eval = 1; 3135 } 3136 ` 3137 3138 _, err := Compile("", SCRIPT, false) 3139 if err == nil { 3140 t.Fatal("expected error") 3141 } 3142 } 3143 3144 func TestDummyCompileForUpdate(t *testing.T) { 3145 const SCRIPT = ` 3146 'use strict'; 3147 3148 for (;false;eval=1) { 3149 } 3150 ` 3151 3152 _, err := Compile("", SCRIPT, false) 3153 if err == nil { 3154 t.Fatal("expected error") 3155 } 3156 } 3157 3158 func TestObjectLiteralWithNumericKeys(t *testing.T) { 3159 const SCRIPT = ` 3160 var o = {1e3: true}; 3161 var keys = Object.keys(o); 3162 var o1 = {get 1e3() {return true;}}; 3163 var keys1 = Object.keys(o1); 3164 var o2 = {1e21: true}; 3165 var keys2 = Object.keys(o2); 3166 keys.length === 1 && keys[0] === "1000" && 3167 keys1.length === 1 && keys1[0] === "1000" && o1[1e3] === true && 3168 keys2.length === 1 && keys2[0] === "1e+21"; 3169 ` 3170 testScript(SCRIPT, valueTrue, t) 3171 } 3172 3173 func TestEscapedObjectPropertyKeys(t *testing.T) { 3174 const SCRIPT = ` 3175 var obj = { 3176 w\u0069th: 42 3177 }; 3178 var obj = { 3179 with() {42} 3180 }; 3181 ` 3182 3183 _, err := Compile("", SCRIPT, false) 3184 if err != nil { 3185 t.Fatal(err) 3186 } 3187 } 3188 3189 func TestEscapedKeywords(t *testing.T) { 3190 const SCRIPT = `r\u0065turn;` 3191 _, err := Compile("", SCRIPT, false) 3192 if err == nil { 3193 t.Fatal("Expected error") 3194 } 3195 } 3196 3197 func TestEscapedLet(t *testing.T) { 3198 const SCRIPT = ` 3199 this.let = 0; 3200 3201 l\u0065t // ASI 3202 a; 3203 3204 // If the parser treated the previous escaped "let" as a lexical declaration, 3205 // this variable declaration will result an early syntax error. 3206 var a; 3207 ` 3208 _, err := Compile("", SCRIPT, false) 3209 if err != nil { 3210 t.Fatal(err) 3211 } 3212 } 3213 3214 func TestObjectLiteralFuncProps(t *testing.T) { 3215 const SCRIPT = ` 3216 (function() { 3217 'use strict'; 3218 var o = { 3219 eval: function() {return 1;}, 3220 arguments() {return 2;}, 3221 test: function test1() {} 3222 } 3223 assert.sameValue(o.eval.name, "eval"); 3224 assert.sameValue(o.arguments.name, "arguments"); 3225 assert.sameValue(o.eval(), 1); 3226 assert.sameValue(o.arguments(), 2); 3227 assert.sameValue(o.test.name, "test1"); 3228 })(); 3229 ` 3230 3231 testScriptWithTestLib(SCRIPT, _undefined, t) 3232 } 3233 3234 func TestFuncName(t *testing.T) { 3235 const SCRIPT = ` 3236 var method = 1; 3237 var o = { 3238 method: function() { 3239 return method; 3240 }, 3241 method1: function method() { 3242 return method; 3243 } 3244 } 3245 o.method() === 1 && o.method1() === o.method1; 3246 ` 3247 3248 testScript(SCRIPT, valueTrue, t) 3249 } 3250 3251 func TestFuncNameAssign(t *testing.T) { 3252 const SCRIPT = ` 3253 var f = function() {}; 3254 var f1; 3255 f1 = function() {}; 3256 let f2 = function() {}; 3257 3258 f.name === "f" && f1.name === "f1" && f2.name === "f2"; 3259 ` 3260 3261 testScript(SCRIPT, valueTrue, t) 3262 } 3263 3264 func TestLexicalDeclGlobal(t *testing.T) { 3265 const SCRIPT = ` 3266 if (true) { 3267 let it = "be"; 3268 if (it !== "be") { 3269 throw new Error(it); 3270 } 3271 } 3272 let thrown = false; 3273 try { 3274 it; 3275 } catch(e) { 3276 if (e instanceof ReferenceError) { 3277 thrown = true; 3278 } 3279 } 3280 thrown; 3281 ` 3282 testScript(SCRIPT, valueTrue, t) 3283 } 3284 3285 func TestLexicalDeclFunction(t *testing.T) { 3286 const SCRIPT = ` 3287 function f() { 3288 if (true) { 3289 let it = "be"; 3290 if (it !== "be") { 3291 throw new Error(it); 3292 } 3293 } 3294 let thrown = false; 3295 try { 3296 it; 3297 } catch(e) { 3298 if (e instanceof ReferenceError) { 3299 thrown = true; 3300 } 3301 } 3302 return thrown; 3303 } 3304 f(); 3305 ` 3306 testScript(SCRIPT, valueTrue, t) 3307 } 3308 3309 func TestLexicalDynamicScope(t *testing.T) { 3310 const SCRIPT = ` 3311 const global = 1; 3312 function f() { 3313 const func = global + 1; 3314 function inner() { 3315 function assertThrows(fn) { 3316 let thrown = false; 3317 try { 3318 fn(); 3319 } catch (e) { 3320 if (e instanceof TypeError) { 3321 thrown = true; 3322 } else { 3323 throw e; 3324 } 3325 } 3326 if (!thrown) { 3327 throw new Error("Did not throw"); 3328 } 3329 } 3330 3331 assertThrows(function() { 3332 func++; 3333 }); 3334 assertThrows(function() { 3335 global++; 3336 }); 3337 3338 assertThrows(function() { 3339 eval("func++"); 3340 }); 3341 assertThrows(function() { 3342 eval("global++"); 3343 }); 3344 3345 return eval("func + 1"); 3346 } 3347 return inner(); 3348 } 3349 f(); 3350 ` 3351 testScript(SCRIPT, valueInt(3), t) 3352 } 3353 3354 func TestLexicalDynamicScope1(t *testing.T) { 3355 const SCRIPT = ` 3356 (function() { 3357 const x = 1 * 4; 3358 return (function() { 3359 eval(""); 3360 return x; 3361 })(); 3362 })(); 3363 ` 3364 testScript(SCRIPT, intToValue(4), t) 3365 } 3366 3367 func TestLexicalDynamicScope2(t *testing.T) { 3368 const SCRIPT = ` 3369 (function() { 3370 const x = 1 + 3; 3371 var y = 2 * 2; 3372 eval(""); 3373 return x; 3374 })(); 3375 ` 3376 testScript(SCRIPT, intToValue(4), t) 3377 } 3378 3379 func TestNonStrictLet(t *testing.T) { 3380 const SCRIPT = ` 3381 var let = 1; 3382 ` 3383 3384 testScript(SCRIPT, _undefined, t) 3385 } 3386 3387 func TestStrictLet(t *testing.T) { 3388 const SCRIPT = ` 3389 var let = 1; 3390 ` 3391 3392 _, err := Compile("", SCRIPT, true) 3393 if err == nil { 3394 t.Fatal("Expected an error") 3395 } 3396 } 3397 3398 func TestLetLet(t *testing.T) { 3399 const SCRIPT = ` 3400 let let = 1; 3401 ` 3402 3403 _, err := Compile("", SCRIPT, false) 3404 if err == nil { 3405 t.Fatal("Expected an error") 3406 } 3407 } 3408 3409 func TestLetASI(t *testing.T) { 3410 const SCRIPT = ` 3411 while (false) let // ASI 3412 x = 1; 3413 ` 3414 3415 _, err := Compile("", SCRIPT, false) 3416 if err != nil { 3417 t.Fatal(err) 3418 } 3419 } 3420 3421 func TestLetASI1(t *testing.T) { 3422 const SCRIPT = ` 3423 let 3424 x = 1; 3425 ` 3426 3427 _, err := Compile("", SCRIPT, true) 3428 if err != nil { 3429 t.Fatal(err) 3430 } 3431 } 3432 3433 func TestLetNoASI(t *testing.T) { 3434 const SCRIPT = ` 3435 function f() {}let 3436 x = 1; 3437 ` 3438 3439 _, err := Compile("", SCRIPT, true) 3440 if err != nil { 3441 t.Fatal(err) 3442 } 3443 } 3444 3445 func TestLetNoASI1(t *testing.T) { 3446 const SCRIPT = ` 3447 let 3448 let = 1; 3449 ` 3450 3451 _, err := Compile("", SCRIPT, false) 3452 if err == nil { 3453 t.Fatal("Expected error") 3454 } 3455 } 3456 3457 func TestLetArrayWithNewline(t *testing.T) { 3458 const SCRIPT = ` 3459 with ({}) let 3460 [a] = 0; 3461 ` 3462 3463 _, err := Compile("", SCRIPT, false) 3464 if err == nil { 3465 t.Fatal("Expected error") 3466 } 3467 } 3468 3469 func TestDynamicUninitedVarAccess(t *testing.T) { 3470 const SCRIPT = ` 3471 function f() { 3472 var x; 3473 return eval("x"); 3474 } 3475 f(); 3476 ` 3477 testScript(SCRIPT, _undefined, t) 3478 } 3479 3480 func TestLexicalForLoopNoClosure(t *testing.T) { 3481 const SCRIPT = ` 3482 let sum = 0; 3483 for (let i = 0; i < 3; i++) { 3484 sum += i; 3485 } 3486 sum; 3487 ` 3488 testScript(SCRIPT, valueInt(3), t) 3489 } 3490 3491 func TestLexicalForLoopClosure(t *testing.T) { 3492 const SCRIPT = ` 3493 var f = []; 3494 for (let i = 0; i < 3; i++) { 3495 f.push(function() { 3496 return i; 3497 }); 3498 } 3499 f.length === 3 && f[0]() === 0 && f[1]() === 1 && f[2]() === 2; 3500 ` 3501 testScript(SCRIPT, valueTrue, t) 3502 } 3503 3504 func TestLexicalForLoopClosureInNext(t *testing.T) { 3505 const SCRIPT = ` 3506 const a = []; 3507 for (let i = 0; i < 5; a.push(function () { return i; }), ++i) { } 3508 let res = ""; 3509 for (let k = 0; k < 5; ++k) { 3510 res += ""+a[k](); 3511 } 3512 res; 3513 ` 3514 testScript(SCRIPT, asciiString("12345"), t) 3515 } 3516 3517 func TestVarForLoop(t *testing.T) { 3518 const SCRIPT = ` 3519 var f = []; 3520 for (var i = 0, j = 0; i < 3; i++) { 3521 f.push(function() { 3522 return i; 3523 }); 3524 } 3525 f.length === 3 && f[0]() === 3 && f[1]() === 3 && f[2]() === 3; 3526 ` 3527 testScript(SCRIPT, valueTrue, t) 3528 } 3529 3530 func TestLexicalForOfLoop(t *testing.T) { 3531 const SCRIPT = ` 3532 var f = []; 3533 for (let i of [0, 1, 2]) { 3534 f.push(function() { 3535 return i; 3536 }); 3537 } 3538 f.length === 3 && f[0]() === 0 && f[1]() === 1 && f[2]() === 2; 3539 ` 3540 testScript(SCRIPT, valueTrue, t) 3541 } 3542 3543 func TestLexicalForOfLoopContBreak(t *testing.T) { 3544 const SCRIPT = ` 3545 const f = []; 3546 for (let i of [0, 1, 2, 3, 4, 5]) { 3547 if (i % 2) continue; 3548 f.push(function() { 3549 return i; 3550 }); 3551 if (i > 2) break; 3552 } 3553 let res = ""; 3554 f.forEach(function(item) {res += item()}); 3555 f.length === 3 && res === "024"; 3556 ` 3557 testScript(SCRIPT, valueTrue, t) 3558 } 3559 3560 func TestVarBlockConflict(t *testing.T) { 3561 const SCRIPT = ` 3562 let x; 3563 { 3564 if (false) { 3565 var x; 3566 } 3567 } 3568 ` 3569 _, err := Compile("", SCRIPT, false) 3570 if err == nil { 3571 t.Fatal("Expected an error") 3572 } 3573 } 3574 3575 func TestVarBlockConflictEval(t *testing.T) { 3576 const SCRIPT = ` 3577 assert.throws(SyntaxError, function() { 3578 let x; 3579 { 3580 if (true) { 3581 eval("var x"); 3582 } 3583 } 3584 }); 3585 ` 3586 testScriptWithTestLib(SCRIPT, _undefined, t) 3587 } 3588 3589 func TestVarBlockNoConflict(t *testing.T) { 3590 const SCRIPT = ` 3591 function f() { 3592 let x; 3593 function ff() { 3594 { 3595 var x = 3; 3596 } 3597 } 3598 ff(); 3599 } 3600 f(); 3601 ` 3602 testScript(SCRIPT, _undefined, t) 3603 } 3604 3605 func TestVarBlockNoConflictEval(t *testing.T) { 3606 const SCRIPT = ` 3607 function f() { 3608 let x; 3609 function ff() { 3610 { 3611 eval("var x = 3"); 3612 } 3613 } 3614 ff(); 3615 } 3616 f(); 3617 ` 3618 testScript(SCRIPT, _undefined, t) 3619 } 3620 3621 func TestVarDeclCorrectScope(t *testing.T) { 3622 const SCRIPT = ` 3623 function f() { 3624 { 3625 let z; 3626 eval("var x = 3"); 3627 } 3628 return x; 3629 } 3630 f(); 3631 ` 3632 testScript(SCRIPT, valueInt(3), t) 3633 } 3634 3635 func TestLexicalCatch(t *testing.T) { 3636 const SCRIPT = ` 3637 try { 3638 throw null; 3639 } catch (e) { 3640 let x = 1; 3641 function f() {} 3642 e; 3643 } 3644 ` 3645 testScript(SCRIPT, _null, t) 3646 } 3647 3648 func TestArgumentsLexicalDecl(t *testing.T) { 3649 const SCRIPT = ` 3650 function f1() { 3651 let arguments; 3652 return arguments; 3653 } 3654 f1(42); 3655 ` 3656 testScript(SCRIPT, _undefined, t) 3657 } 3658 3659 func TestArgumentsLexicalDeclAssign(t *testing.T) { 3660 const SCRIPT = ` 3661 function f1() { 3662 let arguments = arguments; 3663 return a; 3664 } 3665 assert.throws(ReferenceError, function() { 3666 f1(42); 3667 }); 3668 ` 3669 testScriptWithTestLib(SCRIPT, _undefined, t) 3670 } 3671 3672 func TestLexicalConstModifyFromEval(t *testing.T) { 3673 const SCRIPT = ` 3674 const x = 1; 3675 function f() { 3676 eval("x = 2"); 3677 } 3678 assert.throws(TypeError, function() { 3679 f(); 3680 }); 3681 ` 3682 testScriptWithTestLib(SCRIPT, _undefined, t) 3683 } 3684 3685 func TestLexicalStrictNames(t *testing.T) { 3686 const SCRIPT = `let eval = 1;` 3687 3688 _, err := Compile("", SCRIPT, true) 3689 if err == nil { 3690 t.Fatal("Expected an error") 3691 } 3692 } 3693 3694 func TestAssignAfterStackExpand(t *testing.T) { 3695 // make sure the reference to the variable x does not remain stale after the stack is copied 3696 const SCRIPT = ` 3697 function f() { 3698 let sum = 0; 3699 for (let i = 0; i < arguments.length; i++) { 3700 sum += arguments[i]; 3701 } 3702 return sum; 3703 } 3704 function testAssignment() { 3705 var x = 0; 3706 var scope = {}; 3707 3708 with (scope) { 3709 x = (scope.x = f(0, 0, 0, 0, 0, 0, 1, 1), 1); 3710 } 3711 3712 if (scope.x !== 2) { 3713 throw new Error('#1: scope.x === 2. Actual: ' + (scope.x)); 3714 } 3715 if (x !== 1) { 3716 throw new Error('#2: x === 1. Actual: ' + (x)); 3717 } 3718 } 3719 testAssignment(); 3720 ` 3721 testScript(SCRIPT, _undefined, t) 3722 } 3723 3724 func TestArgAccessFromDynamicStash(t *testing.T) { 3725 const SCRIPT = ` 3726 function f(arg) { 3727 function test() { 3728 eval(""); 3729 return a; 3730 } 3731 return arg; 3732 } 3733 f(true); 3734 ` 3735 testScript(SCRIPT, valueTrue, t) 3736 } 3737 3738 func TestLoadMixedLex(t *testing.T) { 3739 const SCRIPT = ` 3740 function f() { 3741 let a = 1; 3742 { 3743 function inner() { 3744 eval("var a = true"); 3745 return a; 3746 } 3747 return inner(); 3748 } 3749 } 3750 f(); 3751 ` 3752 testScript(SCRIPT, valueTrue, t) 3753 } 3754 3755 func TestObjectLiteralSpread(t *testing.T) { 3756 const SCRIPT = ` 3757 let src = {prop1: 1}; 3758 Object.defineProperty(src, "prop2", {value: 2, configurable: true}); 3759 Object.defineProperty(src, "prop3", {value: 3, enumerable: true, configurable: true}); 3760 let target = {prop4: 4, ...src}; 3761 assert(deepEqual(target, {prop1: 1, prop3: 3, prop4: 4})); 3762 ` 3763 testScriptWithTestLibX(SCRIPT, _undefined, t) 3764 } 3765 3766 func TestArrayLiteralSpread(t *testing.T) { 3767 const SCRIPT = ` 3768 let a1 = [1, 2]; 3769 let a2 = [3, 4]; 3770 let a = [...a1, 0, ...a2, 1]; 3771 assert(compareArray(a, [1, 2, 0, 3, 4, 1])); 3772 ` 3773 testScriptWithTestLib(SCRIPT, _undefined, t) 3774 } 3775 3776 func TestObjectAssignmentPattern(t *testing.T) { 3777 const SCRIPT = ` 3778 let a, b, c; 3779 ({a, b, c=3} = {a: 1, b: 2}); 3780 assert.sameValue(a, 1, "a"); 3781 assert.sameValue(b, 2, "b"); 3782 assert.sameValue(c, 3, "c"); 3783 ` 3784 testScriptWithTestLib(SCRIPT, _undefined, t) 3785 } 3786 3787 func TestObjectAssignmentPatternNoDyn(t *testing.T) { 3788 const SCRIPT = ` 3789 (function() { 3790 let a, b, c; 3791 ({a, b, c=3} = {a: 1, b: 2}); 3792 assert.sameValue(a, 1, "a"); 3793 assert.sameValue(b, 2, "b"); 3794 assert.sameValue(c, 3, "c"); 3795 })(); 3796 ` 3797 testScriptWithTestLib(SCRIPT, _undefined, t) 3798 } 3799 3800 func TestObjectAssignmentPatternNested(t *testing.T) { 3801 const SCRIPT = ` 3802 let a, b, c, d; 3803 ({a, b, c: {d} = 3} = {a: 1, b: 2, c: {d: 4}}); 3804 assert.sameValue(a, 1, "a"); 3805 assert.sameValue(b, 2, "b"); 3806 assert.sameValue(c, undefined, "c"); 3807 assert.sameValue(d, 4, "d"); 3808 ` 3809 testScriptWithTestLib(SCRIPT, _undefined, t) 3810 } 3811 3812 func TestObjectAssignmentPatternEvalOrder(t *testing.T) { 3813 const SCRIPT = ` 3814 let trace = ""; 3815 let target_obj = {}; 3816 3817 function src() { 3818 trace += "src(),"; 3819 return { 3820 get a() { 3821 trace += "get a,"; 3822 return "a"; 3823 } 3824 } 3825 } 3826 3827 function prop1() { 3828 trace += "prop1()," 3829 return { 3830 toString: function() { 3831 trace += "prop1-to-string(),"; 3832 return "a"; 3833 } 3834 } 3835 } 3836 3837 function prop2() { 3838 trace += "prop2(),"; 3839 return { 3840 toString: function() { 3841 trace += "prop2-to-string(),"; 3842 return "b"; 3843 } 3844 } 3845 } 3846 3847 function target() { 3848 trace += "target()," 3849 return target_obj; 3850 } 3851 3852 let a, b; 3853 3854 ({[prop1()]: target().a, [prop2()]: b} = src()); 3855 if (target_obj.a !== "a") { 3856 throw new Error("target_obj.a="+target_obj.a); 3857 } 3858 trace; 3859 ` 3860 testScript(SCRIPT, asciiString("src(),prop1(),prop1-to-string(),target(),get a,prop2(),prop2-to-string(),"), t) 3861 } 3862 3863 func TestArrayAssignmentPatternEvalOrder(t *testing.T) { 3864 const SCRIPT = ` 3865 let trace = ""; 3866 3867 let src_arr = { 3868 [Symbol.iterator]: function() { 3869 let done = false; 3870 return { 3871 next: function() { 3872 trace += "next,"; 3873 if (!done) { 3874 done = true; 3875 return {value: 0}; 3876 } 3877 return {done: true}; 3878 }, 3879 return: function() { 3880 trace += "return,"; 3881 } 3882 } 3883 } 3884 } 3885 3886 function src() { 3887 trace += "src(),"; 3888 return src_arr; 3889 } 3890 3891 let tgt = { 3892 get a() { 3893 trace += "get a,"; 3894 return "a"; 3895 }, 3896 get b() { 3897 trace += "get b,"; 3898 return "b"; 3899 } 3900 } 3901 3902 function target() { 3903 trace += "target(),"; 3904 return tgt; 3905 } 3906 3907 function default_a() { 3908 trace += "default a,"; 3909 return "def_a"; 3910 } 3911 3912 function default_b() { 3913 trace += "default b,"; 3914 return "def_b"; 3915 } 3916 3917 ([target().a = default_a(), target().b = default_b()] = src()); 3918 trace; 3919 ` 3920 testScript(SCRIPT, asciiString("src(),target(),next,target(),next,default b,"), t) 3921 } 3922 3923 func TestObjectAssignPatternRest(t *testing.T) { 3924 const SCRIPT = ` 3925 let a, b, c, d; 3926 ({a, b, c, ...d} = {a: 1, b: 2, d: 4}); 3927 assert.sameValue(a, 1, "a"); 3928 assert.sameValue(b, 2, "b"); 3929 assert.sameValue(c, undefined, "c"); 3930 assert(deepEqual(d, {d: 4}), "d"); 3931 ` 3932 testScriptWithTestLibX(SCRIPT, _undefined, t) 3933 } 3934 3935 func TestObjectBindPattern(t *testing.T) { 3936 const SCRIPT = ` 3937 let {a, b, c, ...d} = {a: 1, b: 2, d: 4}; 3938 assert.sameValue(a, 1, "a"); 3939 assert.sameValue(b, 2, "b"); 3940 assert.sameValue(c, undefined, "c"); 3941 assert(deepEqual(d, {d: 4}), "d"); 3942 3943 var { x: y, } = { x: 23 }; 3944 3945 assert.sameValue(y, 23); 3946 3947 assert.throws(ReferenceError, function() { 3948 x; 3949 }); 3950 ` 3951 testScriptWithTestLibX(SCRIPT, _undefined, t) 3952 } 3953 3954 func TestObjLiteralShorthandWithInitializer(t *testing.T) { 3955 const SCRIPT = ` 3956 o = {a=1}; 3957 ` 3958 _, err := Compile("", SCRIPT, false) 3959 if err == nil { 3960 t.Fatal("Expected an error") 3961 } 3962 } 3963 3964 func TestObjLiteralShorthandLetStringLit(t *testing.T) { 3965 const SCRIPT = ` 3966 o = {"let"}; 3967 ` 3968 _, err := Compile("", SCRIPT, false) 3969 if err == nil { 3970 t.Fatal("Expected an error") 3971 } 3972 } 3973 3974 func TestObjLiteralComputedKeys(t *testing.T) { 3975 const SCRIPT = ` 3976 let o = { 3977 get [Symbol.toString]() { 3978 } 3979 } 3980 ` 3981 testScript(SCRIPT, _undefined, t) 3982 } 3983 3984 func TestObjLiteralComputedKeysEvalOrder(t *testing.T) { 3985 const SCRIPT = ` 3986 let trace = []; 3987 function key() { 3988 trace.push("key"); 3989 return { 3990 toString: function() { 3991 trace.push("key-toString"); 3992 return "key"; 3993 } 3994 } 3995 } 3996 function val() { 3997 trace.push("val"); 3998 return "val"; 3999 } 4000 4001 const _ = { 4002 [key()]: val(), 4003 } 4004 4005 trace.join(","); 4006 ` 4007 testScript(SCRIPT, asciiString("key,key-toString,val"), t) 4008 } 4009 4010 func TestArrayAssignPattern(t *testing.T) { 4011 const SCRIPT = ` 4012 let a, b; 4013 ([a, b] = [1, 2]); 4014 a === 1 && b === 2; 4015 ` 4016 testScript(SCRIPT, valueTrue, t) 4017 } 4018 4019 func TestArrayAssignPattern1(t *testing.T) { 4020 const SCRIPT = ` 4021 let a, b; 4022 ([a = 3, b = 2] = [1]); 4023 a === 1 && b === 2; 4024 ` 4025 testScript(SCRIPT, valueTrue, t) 4026 } 4027 4028 func TestArrayAssignPatternLHS(t *testing.T) { 4029 const SCRIPT = ` 4030 let a = {}; 4031 [ a.b, a['c'] = 2 ] = [1]; 4032 a.b === 1 && a.c === 2; 4033 ` 4034 testScript(SCRIPT, valueTrue, t) 4035 } 4036 4037 func TestArrayAssignPatternElision(t *testing.T) { 4038 const SCRIPT = ` 4039 let a, b; 4040 ([a,, b] = [1, 4, 2]); 4041 a === 1 && b === 2; 4042 ` 4043 testScript(SCRIPT, valueTrue, t) 4044 } 4045 4046 func TestArrayAssignPatternRestPattern(t *testing.T) { 4047 const SCRIPT = ` 4048 let a, b, z; 4049 [ z, ...[a, b] ] = [0, 1, 2]; 4050 z === 0 && a === 1 && b === 2; 4051 ` 4052 testScript(SCRIPT, valueTrue, t) 4053 } 4054 4055 func TestArrayBindingPattern(t *testing.T) { 4056 const SCRIPT = ` 4057 let [a, b] = [1, 2]; 4058 a === 1 && b === 2; 4059 ` 4060 testScript(SCRIPT, valueTrue, t) 4061 } 4062 4063 func TestObjectPatternShorthandInit(t *testing.T) { 4064 const SCRIPT = ` 4065 [...{ x = 1 }] = []; 4066 x; 4067 ` 4068 testScript(SCRIPT, valueInt(1), t) 4069 } 4070 4071 func TestArrayBindingPatternRestPattern(t *testing.T) { 4072 const SCRIPT = ` 4073 const [a, b, ...[c, d]] = [1, 2, 3, 4]; 4074 a === 1 && b === 2 && c === 3 && d === 4; 4075 ` 4076 testScript(SCRIPT, valueTrue, t) 4077 } 4078 4079 func TestForVarPattern(t *testing.T) { 4080 const SCRIPT = ` 4081 var o = {a: 1}; 4082 var trace = ""; 4083 for (var [key, value] of Object.entries(o)) { 4084 trace += key+":"+value; 4085 } 4086 trace; 4087 ` 4088 testScript(SCRIPT, asciiString("a:1"), t) 4089 } 4090 4091 func TestForLexPattern(t *testing.T) { 4092 const SCRIPT = ` 4093 var o = {a: 1}; 4094 var trace = ""; 4095 for (const [key, value] of Object.entries(o)) { 4096 trace += key+":"+value; 4097 } 4098 trace; 4099 ` 4100 testScript(SCRIPT, asciiString("a:1"), t) 4101 } 4102 4103 func TestBindingPatternRestTrailingComma(t *testing.T) { 4104 const SCRIPT = ` 4105 const [a, b, ...rest,] = []; 4106 ` 4107 _, err := Compile("", SCRIPT, false) 4108 if err == nil { 4109 t.Fatal("Expected an error") 4110 } 4111 } 4112 4113 func TestAssignPatternRestTrailingComma(t *testing.T) { 4114 const SCRIPT = ` 4115 ([a, b, ...rest,] = []); 4116 ` 4117 _, err := Compile("", SCRIPT, false) 4118 if err == nil { 4119 t.Fatal("Expected an error") 4120 } 4121 } 4122 4123 func TestFuncParamInitializerSimple(t *testing.T) { 4124 const SCRIPT = ` 4125 function f(a = 1) { 4126 return a; 4127 } 4128 ""+f()+f(2); 4129 ` 4130 testScript(SCRIPT, asciiString("12"), t) 4131 } 4132 4133 func TestFuncParamObjectPatternSimple(t *testing.T) { 4134 const SCRIPT = ` 4135 function f({a, b} = {a: 1, b: 2}) { 4136 return "" + a + b; 4137 } 4138 ""+f()+" "+f({a: 3, b: 4}); 4139 ` 4140 testScript(SCRIPT, asciiString("12 34"), t) 4141 } 4142 4143 func TestFuncParamRestStackSimple(t *testing.T) { 4144 const SCRIPT = ` 4145 function f(arg1, ...rest) { 4146 return rest; 4147 } 4148 let ar = f(1, 2, 3); 4149 ar.join(","); 4150 ` 4151 testScript(SCRIPT, asciiString("2,3"), t) 4152 } 4153 4154 func TestFuncParamRestStashSimple(t *testing.T) { 4155 const SCRIPT = ` 4156 function f(arg1, ...rest) { 4157 eval("true"); 4158 return rest; 4159 } 4160 let ar = f(1, 2, 3); 4161 ar.join(","); 4162 ` 4163 testScript(SCRIPT, asciiString("2,3"), t) 4164 } 4165 4166 func TestRestArgsNotInStash(t *testing.T) { 4167 const SCRIPT = ` 4168 function f(...rest) { 4169 () => rest; 4170 return rest.length; 4171 } 4172 f(1,2); 4173 ` 4174 testScript(SCRIPT, valueInt(2), t) 4175 } 4176 4177 func TestRestArgsInStash(t *testing.T) { 4178 const SCRIPT = ` 4179 function f(first, ...rest) { 4180 () => first; 4181 () => rest; 4182 return rest.length; 4183 } 4184 f(1,2); 4185 ` 4186 testScript(SCRIPT, valueInt(1), t) 4187 } 4188 4189 func TestRestArgsInStashFwdRef(t *testing.T) { 4190 const SCRIPT = ` 4191 function f(first = eval(), ...rest) { 4192 () => first; 4193 () => rest; 4194 return rest.length === 1 && rest[0] === 2; 4195 } 4196 f(1,2); 4197 ` 4198 testScript(SCRIPT, valueTrue, t) 4199 } 4200 4201 func TestFuncParamRestPattern(t *testing.T) { 4202 const SCRIPT = ` 4203 function f(arg1, ...{0: rest1, 1: rest2}) { 4204 return ""+arg1+" "+rest1+" "+rest2; 4205 } 4206 f(1, 2, 3); 4207 ` 4208 testScript(SCRIPT, asciiString("1 2 3"), t) 4209 } 4210 4211 func TestFuncParamForwardRef(t *testing.T) { 4212 const SCRIPT = ` 4213 function f(a = b + 1, b) { 4214 return ""+a+" "+b; 4215 } 4216 f(1, 2); 4217 ` 4218 testScript(SCRIPT, asciiString("1 2"), t) 4219 } 4220 4221 func TestFuncParamForwardRefMissing(t *testing.T) { 4222 const SCRIPT = ` 4223 function f(a = b + 1, b) { 4224 return ""+a+" "+b; 4225 } 4226 assert.throws(ReferenceError, function() { 4227 f(); 4228 }); 4229 ` 4230 testScriptWithTestLib(SCRIPT, _undefined, t) 4231 } 4232 4233 func TestFuncParamInnerRef(t *testing.T) { 4234 const SCRIPT = ` 4235 function f(a = inner) { 4236 var inner = 42; 4237 return a; 4238 } 4239 assert.throws(ReferenceError, function() { 4240 f(); 4241 }); 4242 ` 4243 testScriptWithTestLib(SCRIPT, _undefined, t) 4244 } 4245 4246 func TestFuncParamInnerRefEval(t *testing.T) { 4247 const SCRIPT = ` 4248 function f(a = eval("inner")) { 4249 var inner = 42; 4250 return a; 4251 } 4252 assert.throws(ReferenceError, function() { 4253 f(); 4254 }); 4255 ` 4256 testScriptWithTestLib(SCRIPT, _undefined, t) 4257 } 4258 4259 func TestFuncParamCalleeName(t *testing.T) { 4260 const SCRIPT = ` 4261 function f(a = f) { 4262 var f; 4263 return f; 4264 } 4265 typeof f(); 4266 ` 4267 testScript(SCRIPT, asciiString("undefined"), t) 4268 } 4269 4270 func TestFuncParamVarCopy(t *testing.T) { 4271 const SCRIPT = ` 4272 function f(a = f) { 4273 var a; 4274 return a; 4275 } 4276 typeof f(); 4277 ` 4278 testScript(SCRIPT, asciiString("function"), t) 4279 } 4280 4281 func TestFuncParamScope(t *testing.T) { 4282 const SCRIPT = ` 4283 var x = 'outside'; 4284 var probe1, probe2; 4285 4286 function f( 4287 _ = probe1 = function() { return x; }, 4288 __ = (eval('var x = "inside";'), probe2 = function() { return x; }) 4289 ) { 4290 } 4291 f(); 4292 probe1()+" "+probe2(); 4293 ` 4294 testScript(SCRIPT, asciiString("inside inside"), t) 4295 } 4296 4297 func TestDefParamsStackPtr(t *testing.T) { 4298 const SCRIPT = ` 4299 function A() {}; 4300 A.B = function () {}; 4301 function D(message = '') { 4302 var C = A.B; 4303 C([1,2,3]); 4304 }; 4305 4306 D(); 4307 ` 4308 testScript(SCRIPT, _undefined, t) 4309 } 4310 4311 func TestNestedVariadicCalls(t *testing.T) { 4312 const SCRIPT = ` 4313 function f() { 4314 return Array.prototype.join.call(arguments, ","); 4315 } 4316 f(...[1], "a", f(...[2])); 4317 ` 4318 testScript(SCRIPT, asciiString("1,a,2"), t) 4319 } 4320 4321 func TestVariadicNew(t *testing.T) { 4322 const SCRIPT = ` 4323 function C() { 4324 this.res = Array.prototype.join.call(arguments, ","); 4325 } 4326 var c = new C(...[1], "a", new C(...[2]).res); 4327 c.res; 4328 ` 4329 testScript(SCRIPT, asciiString("1,a,2"), t) 4330 } 4331 4332 func TestVariadicUseStackVars(t *testing.T) { 4333 const SCRIPT = ` 4334 function A(message) { return message; } 4335 function B(...args){ 4336 return A(...args); 4337 } 4338 B("C"); 4339 ` 4340 testScript(SCRIPT, asciiString("C"), t) 4341 } 4342 4343 func TestCatchParamPattern(t *testing.T) { 4344 const SCRIPT = ` 4345 function f() { 4346 let x = 3; 4347 try { 4348 throw {a: 1, b: 2}; 4349 } catch ({a, b, c = x}) { 4350 let x = 99; 4351 return ""+a+" "+b+" "+c; 4352 } 4353 } 4354 f(); 4355 ` 4356 testScript(SCRIPT, asciiString("1 2 3"), t) 4357 } 4358 4359 func TestArrowUseStrict(t *testing.T) { 4360 // simple parameter list -- ok 4361 _, err := Compile("", "(a) => {'use strict';}", false) 4362 if err != nil { 4363 t.Fatal(err) 4364 } 4365 // non-simple parameter list -- syntax error 4366 _, err = Compile("", "(a=0) => {'use strict';}", false) 4367 if err == nil { 4368 t.Fatal("expected error") 4369 } 4370 } 4371 4372 func TestArrowBoxedThis(t *testing.T) { 4373 const SCRIPT = ` 4374 var context; 4375 fn = function() { 4376 return (arg) => { var local; context = this; }; 4377 }; 4378 4379 fn()(); 4380 context === this; 4381 ` 4382 4383 testScript(SCRIPT, valueTrue, t) 4384 } 4385 4386 func TestParameterOverride(t *testing.T) { 4387 const SCRIPT = ` 4388 function f(arg) { 4389 var arg = arg || "default" 4390 return arg 4391 } 4392 f() 4393 ` 4394 testScript(SCRIPT, asciiString("default"), t) 4395 } 4396 4397 func TestEvalInIterScope(t *testing.T) { 4398 const SCRIPT = ` 4399 for (let a = 0; a < 1; a++) { 4400 eval("a"); 4401 } 4402 ` 4403 4404 testScript(SCRIPT, valueInt(0), t) 4405 } 4406 4407 func TestTemplateLiterals(t *testing.T) { 4408 vm := New() 4409 _, err := vm.RunString("const a = 1, b = 'b';") 4410 if err != nil { 4411 t.Fatal(err) 4412 } 4413 f := func(t *testing.T, template, expected string) { 4414 res, err := vm.RunString(template) 4415 if err != nil { 4416 t.Fatal(err) 4417 } 4418 if actual := res.Export(); actual != expected { 4419 t.Fatalf("Expected: %q, actual: %q", expected, actual) 4420 } 4421 } 4422 t.Run("empty", func(t *testing.T) { 4423 f(t, "``", "") 4424 }) 4425 t.Run("noSub", func(t *testing.T) { 4426 f(t, "`test`", "test") 4427 }) 4428 t.Run("emptyTail", func(t *testing.T) { 4429 f(t, "`a=${a},b=${b}`", "a=1,b=b") 4430 }) 4431 t.Run("emptyHead", func(t *testing.T) { 4432 f(t, "`${a},b=${b}$`", "1,b=b$") 4433 }) 4434 t.Run("headAndTail", func(t *testing.T) { 4435 f(t, "`a=${a},b=${b}$`", "a=1,b=b$") 4436 }) 4437 } 4438 4439 func TestTaggedTemplate(t *testing.T) { 4440 const SCRIPT = ` 4441 let res; 4442 const o = { 4443 tmpl() { 4444 res = this; 4445 return () => {}; 4446 } 4447 } 4448 ` + 4449 "o.tmpl()`test`;" + ` 4450 res === o; 4451 ` 4452 4453 testScript(SCRIPT, valueTrue, t) 4454 } 4455 4456 func TestDuplicateGlobalFunc(t *testing.T) { 4457 const SCRIPT = ` 4458 function a(){} 4459 function b(){ return "b" } 4460 function c(){ return "c" } 4461 function a(){} 4462 b(); 4463 ` 4464 4465 testScript(SCRIPT, asciiString("b"), t) 4466 } 4467 4468 func TestDuplicateFunc(t *testing.T) { 4469 const SCRIPT = ` 4470 function f() { 4471 function a(){} 4472 function b(){ return "b" } 4473 function c(){ return "c" } 4474 function a(){} 4475 return b(); 4476 } 4477 f(); 4478 ` 4479 4480 testScript(SCRIPT, asciiString("b"), t) 4481 } 4482 4483 func TestSrcLocations(t *testing.T) { 4484 // Do not reformat, assertions depend on line and column numbers 4485 const SCRIPT = ` 4486 let i = { 4487 valueOf() { 4488 throw new Error(); 4489 } 4490 }; 4491 try { 4492 i++; 4493 } catch(e) { 4494 assertStack(e, [["test.js", "valueOf", 4, 10], 4495 ["test.js", "", 8, 3] 4496 ]); 4497 } 4498 4499 Object.defineProperty(globalThis, "x", { 4500 get() { 4501 throw new Error(); 4502 }, 4503 set() { 4504 throw new Error(); 4505 } 4506 }); 4507 4508 try { 4509 x; 4510 } catch(e) { 4511 assertStack(e, [["test.js", "get", 17, 10], 4512 ["test.js", "", 25, 3] 4513 ]); 4514 } 4515 4516 try { 4517 x++; 4518 } catch(e) { 4519 assertStack(e, [["test.js", "get", 17, 10], 4520 ["test.js", "", 33, 3] 4521 ]); 4522 } 4523 4524 try { 4525 x = 2; 4526 } catch(e) { 4527 assertStack(e, [["test.js", "set", 20, 10], 4528 ["test.js", "", 41, 3] 4529 ]); 4530 } 4531 4532 try { 4533 +i; 4534 } catch(e) { 4535 assertStack(e, [["test.js", "valueOf", 4, 10], 4536 ["test.js", "", 49, 4] 4537 ]); 4538 } 4539 4540 4541 function assertStack(e, expected) { 4542 const lines = e.stack.split('\n'); 4543 let lnum = 1; 4544 for (const [file, func, line, col] of expected) { 4545 const expLine = func === "" ? 4546 "\tat " + file + ":" + line + ":" + col + "(" : 4547 "\tat " + func + " (" + file + ":" + line + ":" + col + "("; 4548 assert.sameValue(lines[lnum].substring(0, expLine.length), expLine, "line " + lnum); 4549 lnum++; 4550 } 4551 } 4552 ` 4553 testScriptWithTestLib(SCRIPT, _undefined, t) 4554 } 4555 4556 func TestSrcLocationThrowLiteral(t *testing.T) { 4557 vm := New() 4558 _, err := vm.RunString(` 4559 const z = 1; 4560 throw ""; 4561 `) 4562 if ex, ok := err.(*Exception); ok { 4563 pos := ex.stack[0].Position() 4564 if pos.Line != 3 { 4565 t.Fatal(pos) 4566 } 4567 } else { 4568 t.Fatal(err) 4569 } 4570 } 4571 4572 func TestSrcLocation(t *testing.T) { 4573 prg := MustCompile("test.js", ` 4574 f(); 4575 var x = 1; 4576 let y = 1; 4577 let [z1, z2] = [0, 0]; 4578 4579 var [z3, z4] = [0, 0]; 4580 `, false) 4581 const ( 4582 varLine = 3 4583 letLine = 4 4584 dstrLetLine = 5 4585 dstrVarLine = 7 4586 ) 4587 linesOfInterest := map[int]string{ 4588 varLine: "var", 4589 letLine: "let", 4590 dstrLetLine: "destruct let", 4591 dstrVarLine: "destruct var", 4592 } 4593 for i := range prg.code { 4594 loc := prg.src.Position(prg.sourceOffset(i)) 4595 delete(linesOfInterest, loc.Line) 4596 if len(linesOfInterest) == 0 { 4597 break 4598 } 4599 } 4600 for _, v := range linesOfInterest { 4601 t.Fatalf("no %s line", v) 4602 } 4603 } 4604 4605 func TestBadObjectKey(t *testing.T) { 4606 _, err := Compile("", "({!:0})", false) 4607 if err == nil { 4608 t.Fatal("expected error") 4609 } 4610 } 4611 4612 func TestConstantFolding(t *testing.T) { 4613 testValues := func(prg *Program, result Value, t *testing.T) { 4614 if len(prg.values) != 1 || !prg.values[0].SameAs(result) { 4615 prg.dumpCode(t.Logf) 4616 t.Fatalf("values: %v", prg.values) 4617 } 4618 } 4619 f := func(src string, result Value, t *testing.T) { 4620 prg := MustCompile("test.js", src, false) 4621 testValues(prg, result, t) 4622 New().testPrg(prg, result, t) 4623 } 4624 ff := func(src string, result Value, t *testing.T) { 4625 prg := MustCompile("test.js", src, false) 4626 fl := prg.code[0].(*newFunc) 4627 testValues(fl.prg, result, t) 4628 New().testPrg(prg, result, t) 4629 } 4630 4631 t.Run("lexical binding", func(t *testing.T) { 4632 f("const x = 1 + 2; x", valueInt(3), t) 4633 }) 4634 t.Run("var binding", func(t *testing.T) { 4635 f("var x = 1 + 2; x", valueInt(3), t) 4636 }) 4637 t.Run("assignment", func(t *testing.T) { 4638 f("x = 1 + 2; x", valueInt(3), t) 4639 }) 4640 t.Run("object pattern", func(t *testing.T) { 4641 f("const {x = 1 + 2} = {}; x", valueInt(3), t) 4642 }) 4643 t.Run("array pattern", func(t *testing.T) { 4644 f("const [x = 1 + 2] = []; x", valueInt(3), t) 4645 }) 4646 t.Run("object literal", func(t *testing.T) { 4647 f("var o = {x: 1 + 2}; o.x", valueInt(3), t) 4648 }) 4649 t.Run("array literal", func(t *testing.T) { 4650 f("var a = [3, 3, 3, 1 + 2]; a[3]", valueInt(3), t) 4651 }) 4652 t.Run("default function parameter", func(t *testing.T) { 4653 ff("function f(arg = 1 + 2) {return arg}; f()", valueInt(3), t) 4654 }) 4655 t.Run("return", func(t *testing.T) { 4656 ff("function f() {return 1 + 2}; f()", valueInt(3), t) 4657 }) 4658 } 4659 4660 func TestAssignBeforeInit(t *testing.T) { 4661 const SCRIPT = ` 4662 assert.throws(ReferenceError, () => { 4663 a = 1; 4664 let a; 4665 }); 4666 4667 assert.throws(ReferenceError, () => { 4668 ({a, b} = {a: 1, b: 2}); 4669 let a, b; 4670 }); 4671 4672 assert.throws(ReferenceError, () => { 4673 (function() { 4674 eval(""); 4675 ({a} = {a: 1}); 4676 })(); 4677 let a; 4678 }); 4679 4680 assert.throws(ReferenceError, () => { 4681 const ctx = {x: 1}; 4682 function t() { 4683 delete ctx.x; 4684 return 42; 4685 } 4686 with(ctx) { 4687 (function() { 4688 'use strict'; 4689 ({x} = {x: t()}); 4690 })(); 4691 } 4692 return ctx.x; 4693 }); 4694 4695 assert.throws(ReferenceError, () => { 4696 const ctx = {x: 1}; 4697 function t() { 4698 delete ctx.x; 4699 return 42; 4700 } 4701 with(ctx) { 4702 (function() { 4703 'use strict'; 4704 const src = {}; 4705 Object.defineProperty(src, "x", { 4706 get() { 4707 return t(); 4708 } 4709 }); 4710 ({x} = src); 4711 })(); 4712 } 4713 return ctx.x; 4714 }); 4715 ` 4716 testScriptWithTestLib(SCRIPT, _undefined, t) 4717 } 4718 4719 func TestOptChainCallee(t *testing.T) { 4720 const SCRIPT = ` 4721 var a; 4722 assert.sameValue(a?.(true), undefined); 4723 a = null; 4724 assert.sameValue(a?.(), undefined); 4725 var o = {n: null}; 4726 assert.sameValue(o.m?.(true), undefined); 4727 assert.sameValue(o.n?.(true), undefined); 4728 ` 4729 testScriptWithTestLib(SCRIPT, _undefined, t) 4730 } 4731 4732 func TestObjectLiteralSuper(t *testing.T) { 4733 const SCRIPT = ` 4734 const proto = { 4735 m() { 4736 return 40; 4737 } 4738 } 4739 const o = { 4740 m() { 4741 return super.m() + 2; 4742 } 4743 } 4744 o.__proto__ = proto; 4745 o.m(); 4746 ` 4747 testScript(SCRIPT, intToValue(42), t) 4748 } 4749 4750 func TestClassCaptureThisInFieldInit(t *testing.T) { 4751 const SCRIPT = ` 4752 let capture; 4753 4754 class C { 4755 a = () => this 4756 } 4757 4758 let c = new C(); 4759 c.a() === c; 4760 ` 4761 testScript(SCRIPT, valueTrue, t) 4762 } 4763 4764 func TestClassUseThisInFieldInit(t *testing.T) { 4765 const SCRIPT = ` 4766 let capture; 4767 4768 class C { 4769 a = this 4770 } 4771 4772 let c = new C(); 4773 c.a === c; 4774 ` 4775 testScript(SCRIPT, valueTrue, t) 4776 } 4777 4778 func TestClassCaptureThisInStaticFieldInit(t *testing.T) { 4779 const SCRIPT = ` 4780 let capture; 4781 4782 class C { 4783 static a = (capture = () => this, 0) 4784 } 4785 4786 let c = new C(); 4787 capture() === C; 4788 ` 4789 testScript(SCRIPT, valueTrue, t) 4790 } 4791 4792 func TestClassDynCaptureThisInStaticFieldInit(t *testing.T) { 4793 const SCRIPT = ` 4794 class C { 4795 static a = eval("this") 4796 } 4797 4798 C.a === C; 4799 ` 4800 testScript(SCRIPT, valueTrue, t) 4801 } 4802 4803 func TestCompileClass(t *testing.T) { 4804 const SCRIPT = ` 4805 class C extends Error { 4806 a = true; 4807 b = 1; 4808 ["b".toUpperCase()] = 2 4809 static A = Math.random() < 1 4810 constructor(message = "My Error") { 4811 super(message); 4812 } 4813 static M() { 4814 } 4815 static M1() { 4816 } 4817 m() { 4818 //return C.a; 4819 } 4820 m1() { 4821 return true; 4822 } 4823 static { 4824 this.supername = super.name; 4825 } 4826 } 4827 let c = new C(); 4828 c.a === true && c.b === 1 && c.B === 2 && c.m1() && C.A && C.supername === "Error"; 4829 ` 4830 testScript(SCRIPT, valueTrue, t) 4831 } 4832 4833 func TestSuperInEval(t *testing.T) { 4834 const SCRIPT = ` 4835 class C extends Error { 4836 constructor() { 4837 eval("super()"); 4838 } 4839 m() { 4840 return eval("super.name"); 4841 } 4842 } 4843 let c = new C(); 4844 c.m() === "Error"; 4845 ` 4846 testScript(SCRIPT, valueTrue, t) 4847 } 4848 4849 func TestSuperRefDot(t *testing.T) { 4850 const SCRIPT = ` 4851 let thisGet, thisSet; 4852 class P { 4853 _p = 0 4854 get p() { 4855 thisGet = this; 4856 return this._p; 4857 } 4858 set p(v) { 4859 thisSet = this; 4860 this._p = v; 4861 } 4862 } 4863 4864 class C extends P { 4865 g() { 4866 return super.p; 4867 } 4868 s(v) { 4869 super.p = v; 4870 } 4871 4872 inc() { 4873 super.p++; 4874 } 4875 incR() { 4876 return super.p++; 4877 } 4878 4879 inc1() { 4880 ++super.p; 4881 } 4882 4883 inc1R() { 4884 return ++super.p; 4885 } 4886 unary() { 4887 return +super.p; 4888 } 4889 pattern() { 4890 [super.p] = [9]; 4891 } 4892 } 4893 4894 let o = new C(); 4895 assert.sameValue(o.g(), 0, "get value"); 4896 assert.sameValue(thisGet, o, "get this"); 4897 o.s(1); 4898 assert.sameValue(o._p, 1, "set value"); 4899 assert.sameValue(thisSet, o, "set this"); 4900 4901 thisGet = undefined; 4902 thisSet = undefined; 4903 o.inc(); 4904 assert.sameValue(o._p, 2, "inc value"); 4905 assert.sameValue(thisGet, o, "inc thisGet"); 4906 assert.sameValue(thisSet, o, "inc thisSet"); 4907 4908 thisGet = undefined; 4909 thisSet = undefined; 4910 assert.sameValue(o.incR(), 2, "incR result"); 4911 assert.sameValue(o._p, 3, "incR value"); 4912 assert.sameValue(thisGet, o, "incR thisGet"); 4913 assert.sameValue(thisSet, o, "incR thisSet"); 4914 4915 thisGet = undefined; 4916 thisSet = undefined; 4917 o.inc1(); 4918 assert.sameValue(o._p, 4, "inc1 value"); 4919 assert.sameValue(thisGet, o, "inc1 thisGet"); 4920 assert.sameValue(thisSet, o, "inc1 thisSet"); 4921 4922 thisGet = undefined; 4923 thisSet = undefined; 4924 assert.sameValue(o.inc1R(), 5, "inc1R result"); 4925 assert.sameValue(o._p, 5, "inc1R value"); 4926 assert.sameValue(thisGet, o, "inc1R thisGet"); 4927 assert.sameValue(thisSet, o, "inc1R thisSet"); 4928 4929 assert.sameValue(o.unary(), 5, "unary"); 4930 4931 o.pattern(); 4932 assert.sameValue(o._p, 9, "pattern"); 4933 ` 4934 testScriptWithTestLib(SCRIPT, _undefined, t) 4935 } 4936 4937 func TestPrivateRefDot(t *testing.T) { 4938 const SCRIPT = ` 4939 class C { 4940 #p = 0; 4941 g() { 4942 return this.#p; 4943 } 4944 s(v) { 4945 this.#p = v; 4946 } 4947 4948 inc() { 4949 this.#p++; 4950 } 4951 incR() { 4952 return this.#p++; 4953 } 4954 4955 inc1() { 4956 ++this.#p; 4957 } 4958 4959 inc1R() { 4960 return ++this.#p; 4961 } 4962 pattern() { 4963 [this.#p] = [9]; 4964 } 4965 } 4966 4967 let o = new C(); 4968 assert.sameValue(o.g(), 0, "get value"); 4969 o.s(1); 4970 assert.sameValue(o.g(), 1, "set value"); 4971 4972 o.inc(); 4973 assert.sameValue(o.g(), 2, "inc value"); 4974 4975 assert.sameValue(o.incR(), 2, "incR result"); 4976 assert.sameValue(o.g(), 3, "incR value"); 4977 4978 o.inc1(); 4979 assert.sameValue(o.g(), 4, "inc1 value"); 4980 4981 assert.sameValue(o.inc1R(), 5, "inc1R result"); 4982 assert.sameValue(o.g(), 5, "inc1R value"); 4983 4984 o.pattern(); 4985 assert.sameValue(o.g(), 9, "pattern"); 4986 ` 4987 testScriptWithTestLib(SCRIPT, _undefined, t) 4988 } 4989 4990 func TestPrivateRefDotEval(t *testing.T) { 4991 const SCRIPT = ` 4992 class C { 4993 #p = 0; 4994 g() { 4995 return eval("this.#p"); 4996 } 4997 s(v) { 4998 eval("this.#p = v"); 4999 } 5000 5001 incR() { 5002 return eval("this.#p++"); 5003 } 5004 5005 inc1R() { 5006 return eval("++this.#p"); 5007 } 5008 5009 pattern() { 5010 eval("[this.#p] = [9]"); 5011 } 5012 } 5013 5014 let o = new C(); 5015 assert.sameValue(o.g(), 0, "get value"); 5016 o.s(1); 5017 assert.sameValue(o.g(), 1, "set value"); 5018 5019 assert.sameValue(o.incR(), 1, "incR result"); 5020 assert.sameValue(o.g(), 2, "incR value"); 5021 5022 assert.sameValue(o.inc1R(), 3, "inc1R result"); 5023 assert.sameValue(o.g(), 3, "inc1R value"); 5024 5025 o.pattern(); 5026 assert.sameValue(o.g(), 9, "pattern"); 5027 ` 5028 testScriptWithTestLib(SCRIPT, _undefined, t) 5029 } 5030 5031 func TestSuperRefDotCallee(t *testing.T) { 5032 const SCRIPT = ` 5033 class P { 5034 get p() { 5035 return function() { 5036 return this; 5037 }; 5038 } 5039 } 5040 5041 class C extends P { 5042 m() { 5043 return super.p(); 5044 } 5045 } 5046 5047 let o = new C(); 5048 o.m() === o; 5049 ` 5050 testScript(SCRIPT, valueTrue, t) 5051 } 5052 5053 func TestSuperRefBracket(t *testing.T) { 5054 const SCRIPT = ` 5055 let PROP = "p"; 5056 let thisGet, thisSet; 5057 class P { 5058 _p = 0 5059 get p() { 5060 thisGet = this; 5061 return this._p; 5062 } 5063 set p(v) { 5064 thisSet = this; 5065 this._p = v; 5066 } 5067 } 5068 5069 class C extends P { 5070 g() { 5071 return super[PROP]; 5072 } 5073 s(v) { 5074 super[PROP] = v; 5075 } 5076 5077 inc() { 5078 super[PROP]++; 5079 } 5080 incR() { 5081 return super[PROP]++; 5082 } 5083 5084 inc1() { 5085 ++super[PROP]; 5086 } 5087 5088 inc1R() { 5089 return ++super[PROP]; 5090 } 5091 pattern() { 5092 [super[PROP]] = [9]; 5093 } 5094 } 5095 5096 let o = new C(); 5097 assert.sameValue(o.g(), 0, "get value"); 5098 assert.sameValue(thisGet, o, "get this"); 5099 o.s(1); 5100 assert.sameValue(o._p, 1, "set value"); 5101 assert.sameValue(thisSet, o, "set this"); 5102 5103 thisGet = undefined; 5104 thisSet = undefined; 5105 o.inc(); 5106 assert.sameValue(o._p, 2, "inc value"); 5107 assert.sameValue(thisGet, o, "inc thisGet"); 5108 assert.sameValue(thisSet, o, "inc thisSet"); 5109 5110 thisGet = undefined; 5111 thisSet = undefined; 5112 assert.sameValue(o.incR(), 2, "incR result"); 5113 assert.sameValue(o._p, 3, "incR value"); 5114 assert.sameValue(thisGet, o, "incR thisGet"); 5115 assert.sameValue(thisSet, o, "incR thisSet"); 5116 5117 thisGet = undefined; 5118 thisSet = undefined; 5119 o.inc1(); 5120 assert.sameValue(o._p, 4, "inc1 value"); 5121 assert.sameValue(thisGet, o, "inc1 thisGet"); 5122 assert.sameValue(thisSet, o, "inc1 thisSet"); 5123 5124 thisGet = undefined; 5125 thisSet = undefined; 5126 assert.sameValue(o.inc1R(), 5, "inc1R result"); 5127 assert.sameValue(o._p, 5, "inc1R value"); 5128 assert.sameValue(thisGet, o, "inc1R thisGet"); 5129 assert.sameValue(thisSet, o, "inc1R thisSet"); 5130 5131 o.pattern(); 5132 assert.sameValue(o._p, 9, "pattern"); 5133 ` 5134 testScriptWithTestLib(SCRIPT, _undefined, t) 5135 } 5136 5137 func TestSuperRefBracketEvalOrder(t *testing.T) { 5138 const SCRIPT = ` 5139 let keyCallCount = 0; 5140 5141 function key() { 5142 keyCallCount++; 5143 C.prototype.__proto__ = null; 5144 return "k"; 5145 } 5146 5147 class C { 5148 constructor() { 5149 super[key()]++; 5150 } 5151 } 5152 5153 assert.throws(TypeError, () => new C()); 5154 assert.sameValue(keyCallCount, 1); 5155 ` 5156 testScriptWithTestLib(SCRIPT, _undefined, t) 5157 } 5158 5159 func TestSuperRefBracketCallee(t *testing.T) { 5160 const SCRIPT = ` 5161 let PROP = "p"; 5162 class P { 5163 get p() { 5164 return function() { 5165 return this; 5166 }; 5167 } 5168 } 5169 5170 class C extends P { 5171 m() { 5172 return super[PROP](); 5173 } 5174 } 5175 5176 let o = new C(); 5177 o.m() === o; 5178 ` 5179 testScript(SCRIPT, valueTrue, t) 5180 } 5181 5182 func TestSuperBaseInCtor(t *testing.T) { 5183 const SCRIPT = ` 5184 let result; 5185 class Derived extends Object { 5186 constructor() { 5187 super(); 5188 result = super.constructor === Object; 5189 } 5190 } 5191 new Derived(); 5192 result; 5193 ` 5194 testScript(SCRIPT, valueTrue, t) 5195 } 5196 5197 func TestClassNamedEval(t *testing.T) { 5198 const SCRIPT = ` 5199 const C = class { 5200 } 5201 5202 C.name === "C"; 5203 ` 5204 testScript(SCRIPT, valueTrue, t) 5205 } 5206 5207 func TestClassNonDerived(t *testing.T) { 5208 const SCRIPT = ` 5209 function initF() { 5210 } 5211 class C { 5212 f = initF() 5213 } 5214 let c = new C(); 5215 ` 5216 5217 testScript(SCRIPT, _undefined, t) 5218 } 5219 5220 func TestClassExpr(t *testing.T) { 5221 const SCRIPT = ` 5222 typeof Object.getOwnPropertyDescriptor(class {get f() {}}.prototype, "f").get === "function"; 5223 ` 5224 5225 testScript(SCRIPT, valueTrue, t) 5226 } 5227 5228 func TestClassSuperInHeritage(t *testing.T) { 5229 const SCRIPT = ` 5230 class P { 5231 a() { 5232 return Error; 5233 } 5234 } 5235 5236 class C extends P { 5237 m() { 5238 class Inner extends super.a() { 5239 } 5240 return new Inner(); 5241 } 5242 } 5243 5244 new C().m() instanceof Error; 5245 ` 5246 5247 testScript(SCRIPT, valueTrue, t) 5248 } 5249 5250 func TestClassSuperInHeritageExpr(t *testing.T) { 5251 const SCRIPT = ` 5252 class P { 5253 a() { 5254 return Error; 5255 } 5256 } 5257 5258 class C extends P { 5259 m() { 5260 function f(cls) { 5261 return new cls(); 5262 } 5263 return f(class Inner extends super.a() { 5264 }) 5265 } 5266 } 5267 5268 new C().m() instanceof Error; 5269 ` 5270 5271 testScript(SCRIPT, valueTrue, t) 5272 } 5273 5274 func TestClassReferToBinding(t *testing.T) { 5275 const SCRIPT = ` 5276 const CC = class C { 5277 static T = 40 5278 f = C.T + 2 5279 } 5280 let c = new CC(); 5281 c.f; 5282 ` 5283 5284 testScript(SCRIPT, intToValue(42), t) 5285 } 5286 5287 func TestClassReferToBindingInStaticDecl(t *testing.T) { 5288 const SCRIPT = ` 5289 class C { 5290 static T = C.name 5291 } 5292 C.T; 5293 ` 5294 5295 testScript(SCRIPT, asciiString("C"), t) 5296 } 5297 5298 func TestClassReferToBindingInStaticEval(t *testing.T) { 5299 const SCRIPT = ` 5300 const CC = class C { 5301 static T = eval("C.name") 5302 } 5303 CC.T; 5304 ` 5305 5306 testScript(SCRIPT, asciiString("C"), t) 5307 } 5308 5309 func TestClassReferToBindingFromHeritage(t *testing.T) { 5310 const SCRIPT = ` 5311 assert.throws(ReferenceError, () => { 5312 class C extends C { 5313 } 5314 }); 5315 ` 5316 5317 testScriptWithTestLib(SCRIPT, _undefined, t) 5318 } 5319 5320 func TestClassCaptureSuperCallInArrowFunc(t *testing.T) { 5321 const SCRIPT = ` 5322 let f; 5323 class C extends class {} { 5324 constructor() { 5325 f = () => super(); 5326 f(); 5327 } 5328 } 5329 let c = new C(); 5330 ` 5331 5332 testScript(SCRIPT, _undefined, t) 5333 } 5334 5335 func TestClassCaptureSuperCallInNestedArrowFunc(t *testing.T) { 5336 const SCRIPT = ` 5337 let f; 5338 class P { 5339 } 5340 class C extends P { 5341 constructor() { 5342 f = () => () => super(); 5343 f()(); 5344 } 5345 } 5346 new C() instanceof P; 5347 ` 5348 5349 testScript(SCRIPT, valueTrue, t) 5350 } 5351 5352 func TestThisInEval(t *testing.T) { 5353 const SCRIPT = ` 5354 assert.sameValue(eval("this"), this, "global"); 5355 5356 let o = { 5357 f() { 5358 return eval("this"); 5359 } 5360 } 5361 assert.sameValue(o.f(), o, "obj literal"); 5362 ` 5363 5364 testScriptWithTestLib(SCRIPT, _undefined, t) 5365 } 5366 5367 func TestStaticAsBindingTarget(t *testing.T) { 5368 const SCRIPT = ` 5369 let [static] = []; 5370 ` 5371 testScript(SCRIPT, _undefined, t) 5372 } 5373 5374 func TestEvalInStaticFieldInit(t *testing.T) { 5375 const SCRIPT = ` 5376 var C = class { 5377 static f = 'test'; 5378 static g = this.f + '262'; 5379 static h = eval('this.g') + 'test'; 5380 } 5381 C.f === "test" && C.g === "test262" && C.h === "test262test"; 5382 ` 5383 testScript(SCRIPT, valueTrue, t) 5384 } 5385 5386 func TestClassPrivateElemInEval(t *testing.T) { 5387 const SCRIPT = ` 5388 let f1, f2; 5389 5390 class C extends (f1 = o => eval("o.#a"), Object) { 5391 static #a = 42; 5392 static { 5393 f2 = o => eval("o.#a"); 5394 assert.sameValue(C.#a, 42); 5395 assert.sameValue((() => C.#a)(), 42); 5396 } 5397 } 5398 5399 assert.throws(SyntaxError, () => f1(C)); 5400 assert.sameValue(f2(C), 42); 5401 ` 5402 testScriptWithTestLib(SCRIPT, _undefined, t) 5403 } 5404 5405 func TestClassPrivateElemInIndirectEval(t *testing.T) { 5406 const SCRIPT = ` 5407 let f1, f2; 5408 5409 class C extends (f1 = o => (0, eval)("o.#a"), Object) { 5410 static #a = 42; 5411 static { 5412 f2 = o => (0, eval)("o.#a"); 5413 assert.throws(SyntaxError, () => (0, eval)("C.#a")); 5414 } 5415 } 5416 5417 assert.throws(SyntaxError, () => f1(C)); 5418 assert.throws(SyntaxError, () => f2(C)); 5419 ` 5420 testScriptWithTestLib(SCRIPT, _undefined, t) 5421 } 5422 5423 func TestClassPrivateElemInFunction(t *testing.T) { 5424 const SCRIPT = ` 5425 assert.throws(SyntaxError, () => { 5426 class C { 5427 static #a = 42; 5428 static { 5429 Function("o", "return o.#a"); 5430 } 5431 } 5432 }); 5433 ` 5434 testScriptWithTestLib(SCRIPT, _undefined, t) 5435 } 5436 5437 func TestClassPrivateElementsDecl(t *testing.T) { 5438 const SCRIPT = ` 5439 class C { 5440 #a = 42; 5441 get #b() {} 5442 set #b(_) {} 5443 get c() { 5444 return this.#a; 5445 } 5446 #m() { 5447 return this.#a; 5448 } 5449 static getter(inst) { 5450 return inst.#m(); 5451 } 5452 } 5453 let c = new C(); 5454 c.c + C.getter(c); 5455 ` 5456 testScript(SCRIPT, intToValue(84), t) 5457 } 5458 5459 func TestPrivateIn(t *testing.T) { 5460 const SCRIPT = ` 5461 class C { 5462 #a = 42; 5463 static check(inst) { 5464 return #a in inst; 5465 } 5466 } 5467 let c = new C(); 5468 C.check(c); 5469 ` 5470 testScript(SCRIPT, valueTrue, t) 5471 } 5472 5473 func TestDeletePropOfNonObject(t *testing.T) { 5474 const SCRIPT = ` 5475 delete 'Test262'[100] && delete 'Test262'.a && delete 'Test262'['@']; 5476 ` 5477 testScript(SCRIPT, valueTrue, t) 5478 } 5479 5480 func TestKeywordsAsLabels(t *testing.T) { 5481 const SCRIPT = ` 5482 let: for (let i = 0; i < 2; i++) { 5483 if (i === 0) continue let; 5484 break let; 5485 } 5486 5487 \u006Cet: for (let i = 0; i < 2; i++) { 5488 if (i === 0) continue \u006Cet; 5489 break \u006Cet; 5490 } 5491 5492 yield: for (let i = 0; i < 2; i++) { 5493 if (i === 0) continue yield; 5494 break yield; 5495 } 5496 5497 yi\u0065ld: for (let i = 0; i < 2; i++) { 5498 if (i === 0) continue yi\u0065ld; 5499 break yi\u0065ld; 5500 } 5501 ` 5502 testScript(SCRIPT, _undefined, t) 5503 } 5504 5505 func TestThisResolutionWithArg(t *testing.T) { 5506 const SCRIPT = ` 5507 let capture; 5508 function f(arg) { 5509 capture = () => this; // move 'this' to stash 5510 return [this, arg]; 5511 } 5512 const _this = {}; 5513 const arg = {}; 5514 const [_this1, arg1] = f.call(_this, arg); 5515 _this1 === _this && arg1 === arg; 5516 ` 5517 testScript(SCRIPT, valueTrue, t) 5518 } 5519 5520 func TestThisResolutionArgInStash(t *testing.T) { 5521 const SCRIPT = ` 5522 let capture; 5523 function f(arg) { 5524 capture = () => this + arg; // move 'this' and arguments to stash 5525 return [this, arg]; 5526 } 5527 const _this = {}; 5528 const arg = {}; 5529 const [_this1, arg1] = f.call(_this, arg); 5530 _this1 === _this && arg1 === arg; 5531 ` 5532 testScript(SCRIPT, valueTrue, t) 5533 } 5534 5535 func TestThisResolutionWithStackVar(t *testing.T) { 5536 const SCRIPT = ` 5537 let capture; 5538 function f(arg) { 5539 const _ = 1; // a stack variable 5540 capture = () => this + arg; // move 'this' and arguments to stash 5541 return [this, arg]; 5542 } 5543 const _this = {}; 5544 const arg = {}; 5545 const [_this1, arg1] = f.call(_this, arg); 5546 _this1 === _this && arg1 === arg; 5547 ` 5548 testScript(SCRIPT, valueTrue, t) 5549 } 5550 5551 /* 5552 func TestBabel(t *testing.T) { 5553 src, err := os.ReadFile("babel7.js") 5554 if err != nil { 5555 t.Fatal(err) 5556 } 5557 vm := New() 5558 _, err = vm.RunString(string(src)) 5559 if err != nil { 5560 t.Fatal(err) 5561 } 5562 _, err = vm.RunString(`var result = Babel.transform("", {presets: ["es2015"]});`) 5563 if err != nil { 5564 t.Fatal(err) 5565 } 5566 }*/ 5567 5568 func BenchmarkCompile(b *testing.B) { 5569 data, err := os.ReadFile("testdata/S15.10.2.12_A1_T1.js") 5570 if err != nil { 5571 b.Fatal(err) 5572 } 5573 5574 src := string(data) 5575 5576 for i := 0; i < b.N; i++ { 5577 _, err := Compile("test.js", src, false) 5578 if err != nil { 5579 b.Fatal(err) 5580 } 5581 } 5582 }