github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/compiler_test.go (about)

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