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