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  }