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