go.ketch.com/lib/goja@v0.0.1/runtime_test.go (about)

     1  package goja
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math"
     7  	"reflect"
     8  	"runtime"
     9  	"strconv"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"go.ketch.com/lib/goja/parser"
    15  )
    16  
    17  func TestGlobalObjectProto(t *testing.T) {
    18  	const SCRIPT = `
    19  	this instanceof Object
    20  	`
    21  
    22  	testScript(SCRIPT, valueTrue, t)
    23  }
    24  
    25  func TestUnicodeString(t *testing.T) {
    26  	const SCRIPT = `
    27  	var s = "Тест";
    28  	s.length === 4 && s[1] === "е";
    29  
    30  	`
    31  
    32  	testScript(SCRIPT, valueTrue, t)
    33  }
    34  
    35  func Test2TierHierarchyProp(t *testing.T) {
    36  	const SCRIPT = `
    37  	var a = {};
    38  	Object.defineProperty(a, "test", {
    39  		value: 42,
    40  		writable: false,
    41  		enumerable: false,
    42  		configurable: true
    43  	});
    44  	var b = Object.create(a);
    45  	var c = Object.create(b);
    46  	c.test = 43;
    47  	c.test === 42 && !b.hasOwnProperty("test");
    48  
    49  	`
    50  
    51  	testScript(SCRIPT, valueTrue, t)
    52  }
    53  
    54  func TestConstStringIter(t *testing.T) {
    55  	const SCRIPT = `
    56  
    57  	var count = 0;
    58  
    59  	for (var i in "1234") {
    60      		for (var j in "1234567") {
    61          		count++
    62      		}
    63  	}
    64  
    65  	count;
    66  	`
    67  
    68  	testScript(SCRIPT, intToValue(28), t)
    69  }
    70  
    71  func TestUnicodeConcat(t *testing.T) {
    72  	const SCRIPT = `
    73  
    74  	var s = "тест";
    75  	var s1 = "test";
    76  	var s2 = "абвгд";
    77  
    78  	s.concat(s1) === "тестtest" && s.concat(s1, s2) === "тестtestабвгд" && s1.concat(s, s2) === "testтестабвгд"
    79  		&& s.concat(s2) === "тестабвгд";
    80  
    81  	`
    82  
    83  	testScript(SCRIPT, valueTrue, t)
    84  }
    85  
    86  func TestIndexOf(t *testing.T) {
    87  	const SCRIPT = `
    88  
    89  	"abc".indexOf("", 4)
    90  	`
    91  
    92  	testScript(SCRIPT, intToValue(3), t)
    93  }
    94  
    95  func TestUnicodeIndexOf(t *testing.T) {
    96  	const SCRIPT = `
    97  	"абвгд".indexOf("вг", 1) === 2 && '中国'.indexOf('国') === 1
    98  	`
    99  
   100  	testScript(SCRIPT, valueTrue, t)
   101  }
   102  
   103  func TestLastIndexOf(t *testing.T) {
   104  	const SCRIPT = `
   105  
   106  	"abcabab".lastIndexOf("ab", 3)
   107  	`
   108  
   109  	testScript(SCRIPT, intToValue(3), t)
   110  }
   111  
   112  func TestUnicodeLastIndexOf(t *testing.T) {
   113  	const SCRIPT = `
   114  	"абвабаб".lastIndexOf("аб", 3)
   115  	`
   116  
   117  	testScript(SCRIPT, intToValue(3), t)
   118  }
   119  
   120  func TestUnicodeLastIndexOf1(t *testing.T) {
   121  	const SCRIPT = `
   122  	"abꞐcde".lastIndexOf("cd");
   123  	`
   124  
   125  	testScript(SCRIPT, intToValue(3), t)
   126  }
   127  
   128  func TestNumber(t *testing.T) {
   129  	const SCRIPT = `
   130  	(new Number(100111122133144155)).toString()
   131  	`
   132  
   133  	testScript(SCRIPT, asciiString("100111122133144160"), t)
   134  }
   135  
   136  func TestFractionalNumberToStringRadix(t *testing.T) {
   137  	const SCRIPT = `
   138  	(new Number(123.456)).toString(36)
   139  	`
   140  
   141  	testScript(SCRIPT, asciiString("3f.gez4w97ry"), t)
   142  }
   143  
   144  func TestNumberFormatRounding(t *testing.T) {
   145  	const SCRIPT = `
   146  	assert.sameValue((123.456).toExponential(undefined), "1.23456e+2", "undefined");
   147  	assert.sameValue((0.000001).toPrecision(2), "0.0000010")
   148  	assert.sameValue((-7).toPrecision(1), "-7");
   149  	assert.sameValue((-42).toPrecision(1), "-4e+1");
   150  	assert.sameValue((0.000001).toPrecision(1), "0.000001");
   151  	assert.sameValue((123.456).toPrecision(1), "1e+2", "1");
   152  	assert.sameValue((123.456).toPrecision(2), "1.2e+2", "2");
   153  
   154  	var n = new Number("0.000000000000000000001"); // 1e-21
   155  	assert.sameValue((n).toPrecision(1), "1e-21");
   156  	assert.sameValue((25).toExponential(0), "3e+1");
   157  	assert.sameValue((-25).toExponential(0), "-3e+1");
   158  	assert.sameValue((12345).toExponential(3), "1.235e+4");
   159  	assert.sameValue((25.5).toFixed(0), "26");
   160  	assert.sameValue((-25.5).toFixed(0), "-26");
   161  	assert.sameValue((99.9).toFixed(0), "100");
   162  	assert.sameValue((99.99).toFixed(1), "100.0");
   163  	`
   164  	testScriptWithTestLib(SCRIPT, _undefined, t)
   165  }
   166  
   167  func TestBinOctalNumbers(t *testing.T) {
   168  	const SCRIPT = `
   169  	0b111;
   170  	`
   171  
   172  	testScript(SCRIPT, valueInt(7), t)
   173  }
   174  
   175  func TestSetFunc(t *testing.T) {
   176  	const SCRIPT = `
   177  	sum(40, 2);
   178  	`
   179  	r := New()
   180  	err := r.Set("sum", func(call FunctionCall) Value {
   181  		return r.ToValue(call.Argument(0).ToInteger() + call.Argument(1).ToInteger())
   182  	})
   183  	if err != nil {
   184  		t.Fatal(err)
   185  	}
   186  	v, err := r.RunString(SCRIPT)
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	if i := v.ToInteger(); i != 42 {
   191  		t.Fatalf("Expected 42, got: %d", i)
   192  	}
   193  }
   194  
   195  func ExampleRuntime_Set_lexical() {
   196  	r := New()
   197  	_, err := r.RunString("let x")
   198  	if err != nil {
   199  		panic(err)
   200  	}
   201  	err = r.Set("x", 1)
   202  	if err != nil {
   203  		panic(err)
   204  	}
   205  	fmt.Print(r.Get("x"), r.GlobalObject().Get("x"))
   206  	// Output: 1 <nil>
   207  }
   208  
   209  func TestRecursiveRun(t *testing.T) {
   210  	// Make sure that a recursive call to Run*() correctly sets the environment and no stash or stack
   211  	// corruptions occur.
   212  	vm := New()
   213  	vm.Set("f", func() (Value, error) {
   214  		return vm.RunString("let x = 1; { let z = 100, z1 = 200, z2 = 300, z3 = 400; } x;")
   215  	})
   216  	res, err := vm.RunString(`
   217  	function f1() {
   218  		let x = 2;
   219  		eval('');
   220  		{
   221  			let y = 3;
   222  			let res = f();
   223  			if (x !== 2) { // check for stash corruption
   224  				throw new Error("x="+x);
   225  			}
   226  			if (y !== 3) { // check for stack corruption
   227  				throw new Error("y="+y);
   228  			}
   229  			return res;
   230  		}
   231  	};
   232  	f1();
   233  	`)
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  	if !res.SameAs(valueInt(1)) {
   238  		t.Fatal(res)
   239  	}
   240  }
   241  
   242  func TestObjectGetSet(t *testing.T) {
   243  	const SCRIPT = `
   244  		input.test++;
   245  		input;
   246  	`
   247  	r := New()
   248  	o := r.NewObject()
   249  	o.Set("test", 42)
   250  	r.Set("input", o)
   251  
   252  	v, err := r.RunString(SCRIPT)
   253  	if err != nil {
   254  		t.Fatal(err)
   255  	}
   256  	if o1, ok := v.(*Object); ok {
   257  		if v1 := o1.Get("test"); v1.Export() != int64(43) {
   258  			t.Fatalf("Unexpected test value: %v (%T)", v1, v1.Export())
   259  		}
   260  	}
   261  }
   262  
   263  func TestThrowFromNativeFunc(t *testing.T) {
   264  	const SCRIPT = `
   265  	var thrown;
   266  	try {
   267  		f();
   268  	} catch (e) {
   269  		thrown = e;
   270  	}
   271  	thrown;
   272  	`
   273  	r := New()
   274  	r.Set("f", func(call FunctionCall) Value {
   275  		panic(r.ToValue("testError"))
   276  	})
   277  
   278  	v, err := r.RunString(SCRIPT)
   279  	if err != nil {
   280  		t.Fatal(err)
   281  	}
   282  
   283  	if !v.Equals(asciiString("testError")) {
   284  		t.Fatalf("Unexpected result: %v", v)
   285  	}
   286  }
   287  
   288  func TestSetGoFunc(t *testing.T) {
   289  	const SCRIPT = `
   290  	f(40, 2)
   291  	`
   292  	r := New()
   293  	r.Set("f", func(a, b int) int {
   294  		return a + b
   295  	})
   296  
   297  	v, err := r.RunString(SCRIPT)
   298  	if err != nil {
   299  		t.Fatal(err)
   300  	}
   301  
   302  	if v.ToInteger() != 42 {
   303  		t.Fatalf("Unexpected result: %v", v)
   304  	}
   305  }
   306  
   307  func TestSetFuncVariadic(t *testing.T) {
   308  	vm := New()
   309  	vm.Set("f", func(s string, g ...Value) {
   310  		something := g[0].ToObject(vm).Get(s).ToInteger()
   311  		if something != 5 {
   312  			t.Fatal()
   313  		}
   314  	})
   315  	_, err := vm.RunString(`
   316             f("something", {something: 5})
   317  	`)
   318  	if err != nil {
   319  		t.Fatal(err)
   320  	}
   321  }
   322  
   323  func TestSetFuncVariadicFuncArg(t *testing.T) {
   324  	vm := New()
   325  	vm.Set("f", func(s string, g ...Value) {
   326  		if f, ok := AssertFunction(g[0]); ok {
   327  			v, err := f(nil)
   328  			if err != nil {
   329  				t.Fatal(err)
   330  			}
   331  			if v != valueTrue {
   332  				t.Fatal(v)
   333  			}
   334  		}
   335  	})
   336  	_, err := vm.RunString(`
   337             f("something", () => true)
   338  	`)
   339  	if err != nil {
   340  		t.Fatal(err)
   341  	}
   342  }
   343  
   344  func TestArgsKeys(t *testing.T) {
   345  	const SCRIPT = `
   346  	function testArgs2(x, y, z) {
   347      		// Properties of the arguments object are enumerable.
   348      		return Object.keys(arguments);
   349  	}
   350  
   351  	testArgs2(1,2).length
   352  	`
   353  
   354  	testScript(SCRIPT, intToValue(2), t)
   355  }
   356  
   357  func TestIPowOverflow(t *testing.T) {
   358  	const SCRIPT = `
   359  	Math.pow(65536, 6)
   360  	`
   361  
   362  	testScript(SCRIPT, floatToValue(7.922816251426434e+28), t)
   363  }
   364  
   365  func TestIPowZero(t *testing.T) {
   366  	const SCRIPT = `
   367  	Math.pow(0, 0)
   368  	`
   369  
   370  	testScript(SCRIPT, intToValue(1), t)
   371  }
   372  
   373  func TestInterrupt(t *testing.T) {
   374  	const SCRIPT = `
   375  	var i = 0;
   376  	for (;;) {
   377  		i++;
   378  	}
   379  	`
   380  
   381  	vm := New()
   382  	time.AfterFunc(200*time.Millisecond, func() {
   383  		vm.Interrupt("halt")
   384  	})
   385  
   386  	_, err := vm.RunString(SCRIPT)
   387  	if err == nil {
   388  		t.Fatal("Err is nil")
   389  	}
   390  }
   391  
   392  func TestRuntime_ExportToNumbers(t *testing.T) {
   393  	vm := New()
   394  	t.Run("int8/no overflow", func(t *testing.T) {
   395  		var i8 int8
   396  		err := vm.ExportTo(vm.ToValue(-123), &i8)
   397  		if err != nil {
   398  			t.Fatal(err)
   399  		}
   400  		if i8 != -123 {
   401  			t.Fatalf("i8: %d", i8)
   402  		}
   403  	})
   404  
   405  	t.Run("int8/overflow", func(t *testing.T) {
   406  		var i8 int8
   407  		err := vm.ExportTo(vm.ToValue(333), &i8)
   408  		if err != nil {
   409  			t.Fatal(err)
   410  		}
   411  		if i8 != 77 {
   412  			t.Fatalf("i8: %d", i8)
   413  		}
   414  	})
   415  
   416  	t.Run("int64/uint64", func(t *testing.T) {
   417  		var ui64 uint64
   418  		err := vm.ExportTo(vm.ToValue(-1), &ui64)
   419  		if err != nil {
   420  			t.Fatal(err)
   421  		}
   422  		if ui64 != math.MaxUint64 {
   423  			t.Fatalf("ui64: %d", ui64)
   424  		}
   425  	})
   426  
   427  	t.Run("int8/float", func(t *testing.T) {
   428  		var i8 int8
   429  		err := vm.ExportTo(vm.ToValue(333.9234), &i8)
   430  		if err != nil {
   431  			t.Fatal(err)
   432  		}
   433  		if i8 != 77 {
   434  			t.Fatalf("i8: %d", i8)
   435  		}
   436  	})
   437  
   438  	t.Run("int8/object", func(t *testing.T) {
   439  		var i8 int8
   440  		err := vm.ExportTo(vm.NewObject(), &i8)
   441  		if err != nil {
   442  			t.Fatal(err)
   443  		}
   444  		if i8 != 0 {
   445  			t.Fatalf("i8: %d", i8)
   446  		}
   447  	})
   448  
   449  	t.Run("int/object_cust_valueOf", func(t *testing.T) {
   450  		var i int
   451  		obj, err := vm.RunString(`
   452  		({
   453  			valueOf: function() { return 42; }
   454  		})
   455  		`)
   456  		if err != nil {
   457  			t.Fatal(err)
   458  		}
   459  		err = vm.ExportTo(obj, &i)
   460  		if err != nil {
   461  			t.Fatal(err)
   462  		}
   463  		if i != 42 {
   464  			t.Fatalf("i: %d", i)
   465  		}
   466  	})
   467  
   468  	t.Run("float32/no_trunc", func(t *testing.T) {
   469  		var f float32
   470  		err := vm.ExportTo(vm.ToValue(1.234567), &f)
   471  		if err != nil {
   472  			t.Fatal(err)
   473  		}
   474  		if f != 1.234567 {
   475  			t.Fatalf("f: %f", f)
   476  		}
   477  	})
   478  
   479  	t.Run("float32/trunc", func(t *testing.T) {
   480  		var f float32
   481  		err := vm.ExportTo(vm.ToValue(1.234567890), &f)
   482  		if err != nil {
   483  			t.Fatal(err)
   484  		}
   485  		if f != float32(1.234567890) {
   486  			t.Fatalf("f: %f", f)
   487  		}
   488  	})
   489  
   490  	t.Run("float64", func(t *testing.T) {
   491  		var f float64
   492  		err := vm.ExportTo(vm.ToValue(1.234567), &f)
   493  		if err != nil {
   494  			t.Fatal(err)
   495  		}
   496  		if f != 1.234567 {
   497  			t.Fatalf("f: %f", f)
   498  		}
   499  	})
   500  
   501  	t.Run("float32/object", func(t *testing.T) {
   502  		var f float32
   503  		err := vm.ExportTo(vm.NewObject(), &f)
   504  		if err != nil {
   505  			t.Fatal(err)
   506  		}
   507  		if f == f { // expecting NaN
   508  			t.Fatalf("f: %f", f)
   509  		}
   510  	})
   511  
   512  	t.Run("float64/object", func(t *testing.T) {
   513  		var f float64
   514  		err := vm.ExportTo(vm.NewObject(), &f)
   515  		if err != nil {
   516  			t.Fatal(err)
   517  		}
   518  		if f == f { // expecting NaN
   519  			t.Fatalf("f: %f", f)
   520  		}
   521  	})
   522  
   523  }
   524  
   525  func TestRuntime_ExportToSlice(t *testing.T) {
   526  	const SCRIPT = `
   527  	var a = [1, 2, 3];
   528  	a;
   529  	`
   530  
   531  	vm := New()
   532  	v, err := vm.RunString(SCRIPT)
   533  	if err != nil {
   534  		t.Fatal(err)
   535  	}
   536  	var a []string
   537  	err = vm.ExportTo(v, &a)
   538  	if err != nil {
   539  		t.Fatal(err)
   540  	}
   541  	if l := len(a); l != 3 {
   542  		t.Fatalf("Unexpected len: %d", l)
   543  	}
   544  	if a[0] != "1" || a[1] != "2" || a[2] != "3" {
   545  		t.Fatalf("Unexpected value: %+v", a)
   546  	}
   547  }
   548  
   549  func TestRuntime_ExportToMap(t *testing.T) {
   550  	const SCRIPT = `
   551  	var m = {
   552  		"0": 1,
   553  		"1": 2,
   554  		"2": 3,
   555  	}
   556  	m;
   557  	`
   558  
   559  	vm := New()
   560  	v, err := vm.RunString(SCRIPT)
   561  	if err != nil {
   562  		t.Fatal(err)
   563  	}
   564  	var m map[int]string
   565  	err = vm.ExportTo(v, &m)
   566  	if err != nil {
   567  		t.Fatal(err)
   568  	}
   569  	if l := len(m); l != 3 {
   570  		t.Fatalf("Unexpected len: %d", l)
   571  	}
   572  	if m[0] != "1" || m[1] != "2" || m[2] != "3" {
   573  		t.Fatalf("Unexpected value: %+v", m)
   574  	}
   575  }
   576  
   577  func TestRuntime_ExportToMap1(t *testing.T) {
   578  	const SCRIPT = `
   579  	var m = {
   580  		"0": 1,
   581  		"1": 2,
   582  		"2": 3,
   583  	}
   584  	m;
   585  	`
   586  
   587  	vm := New()
   588  	v, err := vm.RunString(SCRIPT)
   589  	if err != nil {
   590  		t.Fatal(err)
   591  	}
   592  	var m map[string]string
   593  	err = vm.ExportTo(v, &m)
   594  	if err != nil {
   595  		t.Fatal(err)
   596  	}
   597  	if l := len(m); l != 3 {
   598  		t.Fatalf("Unexpected len: %d", l)
   599  	}
   600  	if m["0"] != "1" || m["1"] != "2" || m["2"] != "3" {
   601  		t.Fatalf("Unexpected value: %+v", m)
   602  	}
   603  }
   604  
   605  func TestRuntime_ExportToStruct(t *testing.T) {
   606  	const SCRIPT = `
   607  	var m = {
   608  		Test: 1,
   609  	}
   610  	m;
   611  	`
   612  	vm := New()
   613  	v, err := vm.RunString(SCRIPT)
   614  	if err != nil {
   615  		t.Fatal(err)
   616  	}
   617  
   618  	var o testGoReflectMethod_O
   619  	err = vm.ExportTo(v, &o)
   620  	if err != nil {
   621  		t.Fatal(err)
   622  	}
   623  
   624  	if o.Test != "1" {
   625  		t.Fatalf("Unexpected value: '%s'", o.Test)
   626  	}
   627  
   628  }
   629  
   630  func TestRuntime_ExportToStructPtr(t *testing.T) {
   631  	const SCRIPT = `
   632  	var m = {
   633  		Test: 1,
   634  	}
   635  	m;
   636  	`
   637  	vm := New()
   638  	v, err := vm.RunString(SCRIPT)
   639  	if err != nil {
   640  		t.Fatal(err)
   641  	}
   642  
   643  	var o *testGoReflectMethod_O
   644  	err = vm.ExportTo(v, &o)
   645  	if err != nil {
   646  		t.Fatal(err)
   647  	}
   648  
   649  	if o.Test != "1" {
   650  		t.Fatalf("Unexpected value: '%s'", o.Test)
   651  	}
   652  
   653  }
   654  
   655  func TestRuntime_ExportToStructAnonymous(t *testing.T) {
   656  	type BaseTestStruct struct {
   657  		A int64
   658  		B int64
   659  	}
   660  
   661  	type TestStruct struct {
   662  		BaseTestStruct
   663  		C string
   664  	}
   665  
   666  	const SCRIPT = `
   667  	var m = {
   668  		A: 1,
   669  		B: 2,
   670  		C: "testC"
   671  	}
   672  	m;
   673  	`
   674  	vm := New()
   675  	v, err := vm.RunString(SCRIPT)
   676  	if err != nil {
   677  		t.Fatal(err)
   678  	}
   679  
   680  	test := &TestStruct{}
   681  	err = vm.ExportTo(v, test)
   682  	if err != nil {
   683  		t.Fatal(err)
   684  	}
   685  
   686  	if test.A != 1 {
   687  		t.Fatalf("Unexpected value: '%d'", test.A)
   688  	}
   689  	if test.B != 2 {
   690  		t.Fatalf("Unexpected value: '%d'", test.B)
   691  	}
   692  	if test.C != "testC" {
   693  		t.Fatalf("Unexpected value: '%s'", test.C)
   694  	}
   695  
   696  }
   697  
   698  func TestRuntime_ExportToStructFromPtr(t *testing.T) {
   699  	vm := New()
   700  	v := vm.ToValue(&testGoReflectMethod_O{
   701  		field: "5",
   702  		Test:  "12",
   703  	})
   704  
   705  	var o testGoReflectMethod_O
   706  	err := vm.ExportTo(v, &o)
   707  	if err != nil {
   708  		t.Fatal(err)
   709  	}
   710  
   711  	if o.Test != "12" {
   712  		t.Fatalf("Unexpected value: '%s'", o.Test)
   713  	}
   714  	if o.field != "5" {
   715  		t.Fatalf("Unexpected value for field: '%s'", o.field)
   716  	}
   717  }
   718  
   719  func TestRuntime_ExportToStructWithPtrValues(t *testing.T) {
   720  	type BaseTestStruct struct {
   721  		A int64
   722  		B *int64
   723  	}
   724  
   725  	type TestStruct2 struct {
   726  		E string
   727  	}
   728  
   729  	type TestStruct struct {
   730  		BaseTestStruct
   731  		C *string
   732  		D *TestStruct2
   733  	}
   734  
   735  	const SCRIPT = `
   736  	var m = {
   737  		A: 1,
   738  		B: 2,
   739  		C: "testC",
   740  		D: {
   741  			E: "testE",
   742  		}
   743  	}
   744  	m;
   745  	`
   746  	vm := New()
   747  	v, err := vm.RunString(SCRIPT)
   748  	if err != nil {
   749  		t.Fatal(err)
   750  	}
   751  
   752  	test := &TestStruct{}
   753  	err = vm.ExportTo(v, test)
   754  	if err != nil {
   755  		t.Fatal(err)
   756  	}
   757  
   758  	if test.A != 1 {
   759  		t.Fatalf("Unexpected value: '%d'", test.A)
   760  	}
   761  	if test.B == nil || *test.B != 2 {
   762  		t.Fatalf("Unexpected value: '%v'", test.B)
   763  	}
   764  	if test.C == nil || *test.C != "testC" {
   765  		t.Fatalf("Unexpected value: '%v'", test.C)
   766  	}
   767  	if test.D == nil || test.D.E != "testE" {
   768  		t.Fatalf("Unexpected value: '%s'", test.D.E)
   769  	}
   770  
   771  }
   772  
   773  func TestRuntime_ExportToTime(t *testing.T) {
   774  	const SCRIPT = `
   775  	var dateStr = "2018-08-13T15:02:13+02:00";
   776  	var str = "test123";
   777  	`
   778  
   779  	vm := New()
   780  	_, err := vm.RunString(SCRIPT)
   781  	if err != nil {
   782  		t.Fatal(err)
   783  	}
   784  
   785  	var ti time.Time
   786  	err = vm.ExportTo(vm.Get("dateStr"), &ti)
   787  	if err != nil {
   788  		t.Fatal(err)
   789  	}
   790  	if ti.Format(time.RFC3339) != "2018-08-13T15:02:13+02:00" {
   791  		t.Fatalf("Unexpected value: '%s'", ti.Format(time.RFC3339))
   792  	}
   793  
   794  	err = vm.ExportTo(vm.Get("str"), &ti)
   795  	if err == nil {
   796  		t.Fatal("Expected err to not be nil")
   797  	}
   798  
   799  	var str string
   800  	err = vm.ExportTo(vm.Get("dateStr"), &str)
   801  	if err != nil {
   802  		t.Fatal(err)
   803  	}
   804  	if str != "2018-08-13T15:02:13+02:00" {
   805  		t.Fatalf("Unexpected value: '%s'", str)
   806  	}
   807  
   808  	d, err := vm.RunString(`new Date(1000)`)
   809  	if err != nil {
   810  		t.Fatal(err)
   811  	}
   812  
   813  	ti = time.Time{}
   814  	err = vm.ExportTo(d, &ti)
   815  	if err != nil {
   816  		t.Fatal(err)
   817  	}
   818  
   819  	if ti.UnixNano() != 1000*1e6 {
   820  		t.Fatal(ti)
   821  	}
   822  	if ti.Location() != time.Local {
   823  		t.Fatalf("Wrong location: %v", ti)
   824  	}
   825  }
   826  
   827  func ExampleRuntime_ExportTo_func() {
   828  	const SCRIPT = `
   829  	function f(param) {
   830  		return +param + 2;
   831  	}
   832  	`
   833  
   834  	vm := New()
   835  	_, err := vm.RunString(SCRIPT)
   836  	if err != nil {
   837  		panic(err)
   838  	}
   839  
   840  	var fn func(string) string
   841  	err = vm.ExportTo(vm.Get("f"), &fn)
   842  	if err != nil {
   843  		panic(err)
   844  	}
   845  
   846  	fmt.Println(fn("40")) // note, _this_ value in the function will be undefined.
   847  	// Output: 42
   848  }
   849  
   850  func ExampleRuntime_ExportTo_funcThrow() {
   851  	const SCRIPT = `
   852  	function f(param) {
   853  		throw new Error("testing");
   854  	}
   855  	`
   856  
   857  	vm := New()
   858  	_, err := vm.RunString(SCRIPT)
   859  	if err != nil {
   860  		panic(err)
   861  	}
   862  
   863  	var fn func(string) (string, error)
   864  	err = vm.ExportTo(vm.Get("f"), &fn)
   865  	if err != nil {
   866  		panic(err)
   867  	}
   868  	_, err = fn("")
   869  
   870  	fmt.Println(err)
   871  	// Output: Error: testing at f (<eval>:3:9(3))
   872  }
   873  
   874  func ExampleRuntime_ExportTo_funcVariadic() {
   875  	const SCRIPT = `
   876  	function f() {
   877  		return Array.prototype.join.call(arguments, ",");
   878  	}
   879  	`
   880  	vm := New()
   881  	_, err := vm.RunString(SCRIPT)
   882  	if err != nil {
   883  		panic(err)
   884  	}
   885  
   886  	var fn func(args ...interface{}) string
   887  	err = vm.ExportTo(vm.Get("f"), &fn)
   888  	if err != nil {
   889  		panic(err)
   890  	}
   891  	fmt.Println(fn("a", "b", 42))
   892  	// Output: a,b,42
   893  }
   894  
   895  func TestRuntime_ExportToFuncFail(t *testing.T) {
   896  	const SCRIPT = `
   897  	function f(param) {
   898  		return +param + 2;
   899  	}
   900  	`
   901  
   902  	type T struct {
   903  		Field1 int
   904  	}
   905  
   906  	var fn func(string) (T, error)
   907  
   908  	vm := New()
   909  	_, err := vm.RunString(SCRIPT)
   910  	if err != nil {
   911  		t.Fatal(err)
   912  	}
   913  
   914  	err = vm.ExportTo(vm.Get("f"), &fn)
   915  	if err != nil {
   916  		t.Fatal(err)
   917  	}
   918  
   919  	if _, err := fn("40"); err == nil {
   920  		t.Fatal("Expected error")
   921  	}
   922  }
   923  
   924  func TestRuntime_ExportToCallable(t *testing.T) {
   925  	const SCRIPT = `
   926  	function f(param) {
   927  		return +param + 2;
   928  	}
   929  	`
   930  	vm := New()
   931  	_, err := vm.RunString(SCRIPT)
   932  	if err != nil {
   933  		t.Fatal(err)
   934  	}
   935  
   936  	var c Callable
   937  	err = vm.ExportTo(vm.Get("f"), &c)
   938  	if err != nil {
   939  		t.Fatal(err)
   940  	}
   941  
   942  	res, err := c(Undefined(), vm.ToValue("40"))
   943  	if err != nil {
   944  		t.Fatal(err)
   945  	} else if !res.StrictEquals(vm.ToValue(42)) {
   946  		t.Fatalf("Unexpected value: %v", res)
   947  	}
   948  }
   949  
   950  func TestRuntime_ExportToObject(t *testing.T) {
   951  	const SCRIPT = `
   952  	var o = {"test": 42};
   953  	o;
   954  	`
   955  	vm := New()
   956  	_, err := vm.RunString(SCRIPT)
   957  	if err != nil {
   958  		t.Fatal(err)
   959  	}
   960  
   961  	var o *Object
   962  	err = vm.ExportTo(vm.Get("o"), &o)
   963  	if err != nil {
   964  		t.Fatal(err)
   965  	}
   966  
   967  	if v := o.Get("test"); !v.StrictEquals(vm.ToValue(42)) {
   968  		t.Fatalf("Unexpected value: %v", v)
   969  	}
   970  }
   971  
   972  func ExampleAssertFunction() {
   973  	vm := New()
   974  	_, err := vm.RunString(`
   975  	function sum(a, b) {
   976  		return a+b;
   977  	}
   978  	`)
   979  	if err != nil {
   980  		panic(err)
   981  	}
   982  	sum, ok := AssertFunction(vm.Get("sum"))
   983  	if !ok {
   984  		panic("Not a function")
   985  	}
   986  
   987  	res, err := sum(Undefined(), vm.ToValue(40), vm.ToValue(2))
   988  	if err != nil {
   989  		panic(err)
   990  	}
   991  	fmt.Println(res)
   992  	// Output: 42
   993  }
   994  
   995  func TestGoFuncError(t *testing.T) {
   996  	const SCRIPT = `
   997  	try {
   998  		f();
   999  	} catch (e) {
  1000  		if (!(e instanceof GoError)) {
  1001  			throw(e);
  1002  		}
  1003  		if (e.value.Error() !== "Test") {
  1004  			throw("Unexpected value: " + e.value.Error());
  1005  		}
  1006  	}
  1007  	`
  1008  
  1009  	f := func() error {
  1010  		return errors.New("Test")
  1011  	}
  1012  
  1013  	vm := New()
  1014  	vm.Set("f", f)
  1015  	_, err := vm.RunString(SCRIPT)
  1016  	if err != nil {
  1017  		t.Fatal(err)
  1018  	}
  1019  }
  1020  
  1021  func TestToValueNil(t *testing.T) {
  1022  	type T struct{}
  1023  	var a *T
  1024  	vm := New()
  1025  
  1026  	if v := vm.ToValue(nil); !IsNull(v) {
  1027  		t.Fatalf("nil: %v", v)
  1028  	}
  1029  
  1030  	if v := vm.ToValue(a); !IsNull(v) {
  1031  		t.Fatalf("struct ptr: %v", v)
  1032  	}
  1033  
  1034  	var m map[string]interface{}
  1035  	if v := vm.ToValue(m); !IsNull(v) {
  1036  		t.Fatalf("map[string]interface{}: %v", v)
  1037  	}
  1038  
  1039  	var ar []interface{}
  1040  	if v := vm.ToValue(ar); !IsNull(v) {
  1041  		t.Fatalf("[]interface{}: %v", v)
  1042  	}
  1043  
  1044  	var arptr *[]interface{}
  1045  	if v := vm.ToValue(arptr); !IsNull(v) {
  1046  		t.Fatalf("*[]interface{}: %v", v)
  1047  	}
  1048  }
  1049  
  1050  func TestToValueFloat(t *testing.T) {
  1051  	vm := New()
  1052  	vm.Set("f64", float64(123))
  1053  	vm.Set("f32", float32(321))
  1054  
  1055  	v, err := vm.RunString("f64 === 123 && f32 === 321")
  1056  	if err != nil {
  1057  		t.Fatal(err)
  1058  	}
  1059  	if v.Export().(bool) != true {
  1060  		t.Fatalf("StrictEquals for golang float failed")
  1061  	}
  1062  }
  1063  
  1064  func TestToValueInterface(t *testing.T) {
  1065  
  1066  	f := func(i interface{}) bool {
  1067  		return i == t
  1068  	}
  1069  	vm := New()
  1070  	vm.Set("f", f)
  1071  	vm.Set("t", t)
  1072  	v, err := vm.RunString(`f(t)`)
  1073  	if err != nil {
  1074  		t.Fatal(err)
  1075  	}
  1076  	if v != valueTrue {
  1077  		t.Fatalf("v: %v", v)
  1078  	}
  1079  }
  1080  
  1081  func TestJSONEscape(t *testing.T) {
  1082  	const SCRIPT = `
  1083  	var a = "\\+1";
  1084  	JSON.stringify(a);
  1085  	`
  1086  
  1087  	testScript(SCRIPT, asciiString(`"\\+1"`), t)
  1088  }
  1089  
  1090  func TestJSONObjectInArray(t *testing.T) {
  1091  	const SCRIPT = `
  1092  	var a = "[{\"a\":1},{\"a\":2}]";
  1093  	JSON.stringify(JSON.parse(a)) == a;
  1094  	`
  1095  
  1096  	testScript(SCRIPT, valueTrue, t)
  1097  }
  1098  
  1099  func TestJSONQuirkyNumbers(t *testing.T) {
  1100  	const SCRIPT = `
  1101  	var s;
  1102  	s = JSON.stringify(NaN);
  1103  	if (s != "null") {
  1104  		throw new Error("NaN: " + s);
  1105  	}
  1106  
  1107  	s = JSON.stringify(Infinity);
  1108  	if (s != "null") {
  1109  		throw new Error("Infinity: " + s);
  1110  	}
  1111  
  1112  	s = JSON.stringify(-Infinity);
  1113  	if (s != "null") {
  1114  		throw new Error("-Infinity: " + s);
  1115  	}
  1116  
  1117  	`
  1118  
  1119  	testScript(SCRIPT, _undefined, t)
  1120  }
  1121  
  1122  func TestJSONNil(t *testing.T) {
  1123  	const SCRIPT = `
  1124  	JSON.stringify(i);
  1125  	`
  1126  
  1127  	vm := New()
  1128  	var i interface{}
  1129  	vm.Set("i", i)
  1130  	ret, err := vm.RunString(SCRIPT)
  1131  	if err != nil {
  1132  		t.Fatal(err)
  1133  	}
  1134  
  1135  	if ret.String() != "null" {
  1136  		t.Fatalf("Expected 'null', got: %v", ret)
  1137  	}
  1138  }
  1139  
  1140  type customJsonEncodable struct{}
  1141  
  1142  func (*customJsonEncodable) JsonEncodable() interface{} {
  1143  	return "Test"
  1144  }
  1145  
  1146  func TestJsonEncodable(t *testing.T) {
  1147  	var s customJsonEncodable
  1148  
  1149  	vm := New()
  1150  	vm.Set("s", &s)
  1151  
  1152  	ret, err := vm.RunString("JSON.stringify(s)")
  1153  	if err != nil {
  1154  		t.Fatal(err)
  1155  	}
  1156  	if !ret.StrictEquals(vm.ToValue("\"Test\"")) {
  1157  		t.Fatalf("Expected \"Test\", got: %v", ret)
  1158  	}
  1159  }
  1160  
  1161  func TestSortComparatorReturnValues(t *testing.T) {
  1162  	const SCRIPT = `
  1163  	var a = [];
  1164  	for (var i = 0; i < 12; i++) {
  1165  	    a[i] = i;
  1166  	}
  1167  
  1168  	a.sort(function(x, y) { return y - x });
  1169  
  1170  	for (var i = 0; i < 12; i++) {
  1171  	    if (a[i] !== 11-i) {
  1172  		throw new Error("Value at index " + i + " is incorrect: " + a[i]);
  1173  	    }
  1174  	}
  1175  	`
  1176  
  1177  	testScript(SCRIPT, _undefined, t)
  1178  }
  1179  
  1180  func TestSortComparatorReturnValueFloats(t *testing.T) {
  1181  	const SCRIPT = `
  1182  	var a = [
  1183  		5.97,
  1184  		9.91,
  1185  		4.13,
  1186  		9.28,
  1187  		3.29,
  1188  	];
  1189  	a.sort( function(a, b) { return a - b; } );
  1190  	for (var i = 1; i < a.length; i++) {
  1191  		if (a[i] < a[i-1]) {
  1192  			throw new Error("Array is not sorted: " + a);
  1193  		}
  1194  	}
  1195  	`
  1196  	testScript(SCRIPT, _undefined, t)
  1197  }
  1198  
  1199  func TestSortComparatorReturnValueNegZero(t *testing.T) {
  1200  	const SCRIPT = `
  1201  	var a = [2, 1];
  1202  	a.sort( function(a, b) { return a > b ? 0 : -0; } );
  1203  	for (var i = 1; i < a.length; i++) {
  1204  		if (a[i] < a[i-1]) {
  1205  			throw new Error("Array is not sorted: " + a);
  1206  		}
  1207  	}
  1208  	`
  1209  	testScript(SCRIPT, _undefined, t)
  1210  }
  1211  
  1212  func TestNilApplyArg(t *testing.T) {
  1213  	const SCRIPT = `
  1214  	(function x(a, b) {
  1215  		return a === undefined && b === 1;
  1216          }).apply(this, [,1])
  1217  	`
  1218  
  1219  	testScript(SCRIPT, valueTrue, t)
  1220  }
  1221  
  1222  func TestNilCallArg(t *testing.T) {
  1223  	const SCRIPT = `
  1224  	"use strict";
  1225  	function f(a) {
  1226  		return this === undefined && a === undefined;
  1227  	}
  1228  	`
  1229  	vm := New()
  1230  	prg := MustCompile("test.js", SCRIPT, false)
  1231  	vm.RunProgram(prg)
  1232  	if f, ok := AssertFunction(vm.Get("f")); ok {
  1233  		v, err := f(nil, nil)
  1234  		if err != nil {
  1235  			t.Fatal(err)
  1236  		}
  1237  		if !v.StrictEquals(valueTrue) {
  1238  			t.Fatalf("Unexpected result: %v", v)
  1239  		}
  1240  	}
  1241  }
  1242  
  1243  func TestNullCallArg(t *testing.T) {
  1244  	const SCRIPT = `
  1245  	f(null);
  1246  	`
  1247  	vm := New()
  1248  	prg := MustCompile("test.js", SCRIPT, false)
  1249  	vm.Set("f", func(x *int) bool {
  1250  		return x == nil
  1251  	})
  1252  
  1253  	v, err := vm.RunProgram(prg)
  1254  	if err != nil {
  1255  		t.Fatal(err)
  1256  	}
  1257  
  1258  	if !v.StrictEquals(valueTrue) {
  1259  		t.Fatalf("Unexpected result: %v", v)
  1260  	}
  1261  }
  1262  
  1263  func TestObjectKeys(t *testing.T) {
  1264  	const SCRIPT = `
  1265  	var o = { a: 1, b: 2, c: 3, d: 4 };
  1266  	o;
  1267  	`
  1268  
  1269  	vm := New()
  1270  	prg := MustCompile("test.js", SCRIPT, false)
  1271  
  1272  	res, err := vm.RunProgram(prg)
  1273  	if err != nil {
  1274  		t.Fatal(err)
  1275  	}
  1276  
  1277  	if o, ok := res.(*Object); ok {
  1278  		keys := o.Keys()
  1279  		if !reflect.DeepEqual(keys, []string{"a", "b", "c", "d"}) {
  1280  			t.Fatalf("Unexpected keys: %v", keys)
  1281  		}
  1282  	}
  1283  }
  1284  
  1285  func TestReflectCallExtraArgs(t *testing.T) {
  1286  	const SCRIPT = `
  1287  	f(41, "extra")
  1288  	`
  1289  	f := func(x int) int {
  1290  		return x + 1
  1291  	}
  1292  
  1293  	vm := New()
  1294  	vm.Set("f", f)
  1295  
  1296  	prg := MustCompile("test.js", SCRIPT, false)
  1297  
  1298  	res, err := vm.RunProgram(prg)
  1299  	if err != nil {
  1300  		t.Fatal(err)
  1301  	}
  1302  	if !res.StrictEquals(intToValue(42)) {
  1303  		t.Fatalf("Unexpected result: %v", res)
  1304  	}
  1305  }
  1306  
  1307  func TestReflectCallNotEnoughArgs(t *testing.T) {
  1308  	const SCRIPT = `
  1309  	f(42)
  1310  	`
  1311  	vm := New()
  1312  
  1313  	f := func(x, y int, z *int, s string) (int, error) {
  1314  		if z != nil {
  1315  			return 0, fmt.Errorf("z is not nil")
  1316  		}
  1317  		if s != "" {
  1318  			return 0, fmt.Errorf("s is not \"\"")
  1319  		}
  1320  		return x + y, nil
  1321  	}
  1322  
  1323  	vm.Set("f", f)
  1324  
  1325  	prg := MustCompile("test.js", SCRIPT, false)
  1326  
  1327  	res, err := vm.RunProgram(prg)
  1328  	if err != nil {
  1329  		t.Fatal(err)
  1330  	}
  1331  	if !res.StrictEquals(intToValue(42)) {
  1332  		t.Fatalf("Unexpected result: %v", res)
  1333  	}
  1334  }
  1335  
  1336  func TestReflectCallVariadic(t *testing.T) {
  1337  	const SCRIPT = `
  1338  	var r = f("Hello %s, %d", "test", 42);
  1339  	if (r !== "Hello test, 42") {
  1340  		throw new Error("test 1 has failed: " + r);
  1341  	}
  1342  
  1343  	r = f("Hello %s, %s", "test");
  1344  	if (r !== "Hello test, %!s(MISSING)") {
  1345  		throw new Error("test 2 has failed: " + r);
  1346  	}
  1347  
  1348  	r = f();
  1349  	if (r !== "") {
  1350  		throw new Error("test 3 has failed: " + r);
  1351  	}
  1352  
  1353  	`
  1354  
  1355  	vm := New()
  1356  	vm.Set("f", fmt.Sprintf)
  1357  
  1358  	prg := MustCompile("test.js", SCRIPT, false)
  1359  
  1360  	_, err := vm.RunProgram(prg)
  1361  	if err != nil {
  1362  		t.Fatal(err)
  1363  	}
  1364  }
  1365  
  1366  func TestReflectNullValueArgument(t *testing.T) {
  1367  	rt := New()
  1368  	rt.Set("fn", func(v Value) {
  1369  		if v == nil {
  1370  			t.Error("null becomes nil")
  1371  		}
  1372  		if !IsNull(v) {
  1373  			t.Error("null is not null")
  1374  		}
  1375  	})
  1376  	rt.RunString(`fn(null);`)
  1377  }
  1378  
  1379  type testNativeConstructHelper struct {
  1380  	rt   *Runtime
  1381  	base int64
  1382  	// any other state
  1383  }
  1384  
  1385  func (t *testNativeConstructHelper) calc(call FunctionCall) Value {
  1386  	return t.rt.ToValue(t.base + call.Argument(0).ToInteger())
  1387  }
  1388  
  1389  func TestNativeConstruct(t *testing.T) {
  1390  	const SCRIPT = `
  1391  	var f = new F(40);
  1392  	f instanceof F && f.method() === 42 && f.calc(2) === 42;
  1393  	`
  1394  
  1395  	rt := New()
  1396  
  1397  	method := func(call FunctionCall) Value {
  1398  		return rt.ToValue(42)
  1399  	}
  1400  
  1401  	rt.Set("F", func(call ConstructorCall) *Object { // constructor signature (as opposed to 'func(FunctionCall) Value')
  1402  		h := &testNativeConstructHelper{
  1403  			rt:   rt,
  1404  			base: call.Argument(0).ToInteger(),
  1405  		}
  1406  		call.This.Set("method", method)
  1407  		call.This.Set("calc", h.calc)
  1408  		return nil // or any other *Object which will be used instead of call.This
  1409  	})
  1410  
  1411  	prg := MustCompile("test.js", SCRIPT, false)
  1412  
  1413  	res, err := rt.RunProgram(prg)
  1414  	if err != nil {
  1415  		t.Fatal(err)
  1416  	}
  1417  
  1418  	if !res.StrictEquals(valueTrue) {
  1419  		t.Fatalf("Unexpected result: %v", res)
  1420  	}
  1421  
  1422  	if fn, ok := AssertFunction(rt.Get("F")); ok {
  1423  		v, err := fn(nil, rt.ToValue(42))
  1424  		if err != nil {
  1425  			t.Fatal(err)
  1426  		}
  1427  		if o, ok := v.(*Object); ok {
  1428  			if o.Get("method") == nil {
  1429  				t.Fatal("No method")
  1430  			}
  1431  		} else {
  1432  			t.Fatal("Not an object")
  1433  		}
  1434  	} else {
  1435  		t.Fatal("Not a function")
  1436  	}
  1437  
  1438  	resp := &testNativeConstructHelper{}
  1439  	value := rt.ToValue(resp)
  1440  	if value.Export() != resp {
  1441  		t.Fatal("no")
  1442  	}
  1443  }
  1444  
  1445  func TestCreateObject(t *testing.T) {
  1446  	const SCRIPT = `
  1447  	inst instanceof C;
  1448  	`
  1449  
  1450  	r := New()
  1451  	c := r.ToValue(func(call ConstructorCall) *Object {
  1452  		return nil
  1453  	})
  1454  
  1455  	proto := c.(*Object).Get("prototype").(*Object)
  1456  
  1457  	inst := r.CreateObject(proto)
  1458  
  1459  	r.Set("C", c)
  1460  	r.Set("inst", inst)
  1461  
  1462  	prg := MustCompile("test.js", SCRIPT, false)
  1463  
  1464  	res, err := r.RunProgram(prg)
  1465  	if err != nil {
  1466  		t.Fatal(err)
  1467  	}
  1468  
  1469  	if !res.StrictEquals(valueTrue) {
  1470  		t.Fatalf("Unexpected result: %v", res)
  1471  	}
  1472  }
  1473  
  1474  func TestInterruptInWrappedFunction(t *testing.T) {
  1475  	rt := New()
  1476  	v, err := rt.RunString(`
  1477  		var fn = function() {
  1478  			while (true) {}
  1479  		};
  1480  		fn;
  1481  	`)
  1482  	if err != nil {
  1483  		t.Fatal(err)
  1484  	}
  1485  	fn, ok := AssertFunction(v)
  1486  	if !ok {
  1487  		t.Fatal("Not a function")
  1488  	}
  1489  	go func() {
  1490  		<-time.After(10 * time.Millisecond)
  1491  		rt.Interrupt(errors.New("hi"))
  1492  	}()
  1493  
  1494  	_, err = fn(nil)
  1495  	if err == nil {
  1496  		t.Fatal("expected error")
  1497  	}
  1498  	if _, ok := err.(*InterruptedError); !ok {
  1499  		t.Fatalf("Wrong error type: %T", err)
  1500  	}
  1501  }
  1502  
  1503  func TestInterruptInWrappedFunction2(t *testing.T) {
  1504  	rt := New()
  1505  	// this test panics as otherwise goja will recover and possibly loop
  1506  	var called bool
  1507  	rt.Set("v", rt.ToValue(func() {
  1508  		if called {
  1509  			go func() {
  1510  				panic("this should never get called twice")
  1511  			}()
  1512  		}
  1513  		called = true
  1514  		rt.Interrupt("here is the error")
  1515  	}))
  1516  
  1517  	rt.Set("s", rt.ToValue(func(a Callable) (Value, error) {
  1518  		return a(nil)
  1519  	}))
  1520  
  1521  	rt.Set("k", rt.ToValue(func(e Value) {
  1522  		go func() {
  1523  			panic("this should never get called actually")
  1524  		}()
  1525  	}))
  1526  	_, err := rt.RunString(`
  1527          Promise.resolve().then(()=>k()); // this should never resolve
  1528          while(true) {
  1529              try{
  1530                  s(() =>{
  1531                      v();
  1532                  })
  1533                  break;
  1534              } catch (e) {
  1535                  k(e);
  1536              }
  1537          }
  1538  	`)
  1539  	if err == nil {
  1540  		t.Fatal("expected error but got no error")
  1541  	}
  1542  	intErr := new(InterruptedError)
  1543  	if !errors.As(err, &intErr) {
  1544  		t.Fatalf("Wrong error type: %T", err)
  1545  	}
  1546  	if !strings.Contains(intErr.Error(), "here is the error") {
  1547  		t.Fatalf("Wrong error message: %q", intErr.Error())
  1548  	}
  1549  	_, err = rt.RunString(`Promise.resolve().then(()=>globalThis.S=5)`)
  1550  	if err != nil {
  1551  		t.Fatal(err)
  1552  	}
  1553  	s := rt.Get("S")
  1554  	if s == nil || s.ToInteger() != 5 {
  1555  		t.Fatalf("Wrong value for S %v", s)
  1556  	}
  1557  }
  1558  
  1559  func TestInterruptInWrappedFunction2Recover(t *testing.T) {
  1560  	rt := New()
  1561  	// this test panics as otherwise goja will recover and possibly loop
  1562  	var vCalled int
  1563  	rt.Set("v", rt.ToValue(func() {
  1564  		if vCalled == 0 {
  1565  			rt.Interrupt("here is the error")
  1566  		}
  1567  		vCalled++
  1568  	}))
  1569  
  1570  	rt.Set("s", rt.ToValue(func(a Callable) (Value, error) {
  1571  		v, err := a(nil)
  1572  		if err != nil {
  1573  			intErr := new(InterruptedError)
  1574  			if errors.As(err, &intErr) {
  1575  				rt.ClearInterrupt()
  1576  				return nil, errors.New("oops we got interrupted let's not that")
  1577  			}
  1578  		}
  1579  		return v, err
  1580  	}))
  1581  	var kCalled int
  1582  
  1583  	rt.Set("k", rt.ToValue(func(e Value) {
  1584  		kCalled++
  1585  	}))
  1586  	_, err := rt.RunString(`
  1587          Promise.resolve().then(()=>k());
  1588          while(true) {
  1589              try{
  1590                  s(() => {
  1591                      v();
  1592                  })
  1593                  break;
  1594              } catch (e) {
  1595                  k(e);
  1596              }
  1597          }
  1598  	`)
  1599  	if err != nil {
  1600  		t.Fatal(err)
  1601  	}
  1602  	if vCalled != 2 {
  1603  		t.Fatalf("v was not called exactly twice but %d times", vCalled)
  1604  	}
  1605  	if kCalled != 2 {
  1606  		t.Fatalf("k was not called exactly twice but %d times", kCalled)
  1607  	}
  1608  	_, err = rt.RunString(`Promise.resolve().then(()=>globalThis.S=5)`)
  1609  	if err != nil {
  1610  		t.Fatal(err)
  1611  	}
  1612  	s := rt.Get("S")
  1613  	if s == nil || s.ToInteger() != 5 {
  1614  		t.Fatalf("Wrong value for S %v", s)
  1615  	}
  1616  }
  1617  
  1618  func TestRunLoopPreempt(t *testing.T) {
  1619  	vm := New()
  1620  	v, err := vm.RunString("(function() {for (;;) {}})")
  1621  	if err != nil {
  1622  		t.Fatal(err)
  1623  	}
  1624  
  1625  	fn, ok := AssertFunction(v)
  1626  	if !ok {
  1627  		t.Fatal("Not a function")
  1628  	}
  1629  
  1630  	go func() {
  1631  		<-time.After(100 * time.Millisecond)
  1632  		runtime.GC() // this hangs if the vm loop does not have any preemption points
  1633  		vm.Interrupt(errors.New("hi"))
  1634  	}()
  1635  
  1636  	_, err = fn(nil)
  1637  	if err == nil {
  1638  		t.Fatal("expected error")
  1639  	}
  1640  	if _, ok := err.(*InterruptedError); !ok {
  1641  		t.Fatalf("Wrong error type: %T", err)
  1642  	}
  1643  }
  1644  
  1645  func TestNaN(t *testing.T) {
  1646  	if !IsNaN(_NaN) {
  1647  		t.Fatal("IsNaN() doesn't detect NaN")
  1648  	}
  1649  	if IsNaN(Undefined()) {
  1650  		t.Fatal("IsNaN() says undefined is a NaN")
  1651  	}
  1652  	if !IsNaN(NaN()) {
  1653  		t.Fatal("NaN() doesn't return NaN")
  1654  	}
  1655  }
  1656  
  1657  func TestInf(t *testing.T) {
  1658  	if !IsInfinity(_positiveInf) {
  1659  		t.Fatal("IsInfinity() doesn't detect +Inf")
  1660  	}
  1661  	if !IsInfinity(_negativeInf) {
  1662  		t.Fatal("IsInfinity() doesn't detect -Inf")
  1663  	}
  1664  	if IsInfinity(Undefined()) {
  1665  		t.Fatal("IsInfinity() says undefined is a Infinity")
  1666  	}
  1667  	if !IsInfinity(PositiveInf()) {
  1668  		t.Fatal("PositiveInfinity() doesn't return Inf")
  1669  	}
  1670  	if !IsInfinity(NegativeInf()) {
  1671  		t.Fatal("NegativeInfinity() doesn't return Inf")
  1672  	}
  1673  }
  1674  
  1675  func TestRuntimeNew(t *testing.T) {
  1676  	vm := New()
  1677  	v, err := vm.New(vm.Get("Number"), vm.ToValue("12345"))
  1678  	if err != nil {
  1679  		t.Fatal(err)
  1680  	}
  1681  	if n, ok := v.Export().(int64); ok {
  1682  		if n != 12345 {
  1683  			t.Fatalf("n: %v", n)
  1684  		}
  1685  	} else {
  1686  		t.Fatalf("v: %T", v)
  1687  	}
  1688  }
  1689  
  1690  func TestAutoBoxing(t *testing.T) {
  1691  	const SCRIPT = `
  1692  	function f() {
  1693  		'use strict';
  1694  		var a = 1;
  1695  		var thrown1 = false;
  1696  		var thrown2 = false;
  1697  		try {
  1698  			a.test = 42;
  1699  		} catch (e) {
  1700  			thrown1 = e instanceof TypeError;
  1701  		}
  1702  		try {
  1703  			a["test1"] = 42;
  1704  		} catch (e) {
  1705  			thrown2 = e instanceof TypeError;
  1706  		}
  1707  		return thrown1 && thrown2;
  1708  	}
  1709  	var a = 1;
  1710  	a.test = 42; // should not throw
  1711  	a["test1"] = 42; // should not throw
  1712  	a.test === undefined && a.test1 === undefined && f();
  1713  	`
  1714  
  1715  	testScript(SCRIPT, valueTrue, t)
  1716  }
  1717  
  1718  func TestProtoGetter(t *testing.T) {
  1719  	const SCRIPT = `
  1720  	({}).__proto__ === Object.prototype && [].__proto__ === Array.prototype;
  1721  	`
  1722  	testScript(SCRIPT, valueTrue, t)
  1723  }
  1724  
  1725  func TestSymbol1(t *testing.T) {
  1726  	const SCRIPT = `
  1727  		Symbol.toPrimitive[Symbol.toPrimitive]() === Symbol.toPrimitive;
  1728  	`
  1729  
  1730  	testScript(SCRIPT, valueTrue, t)
  1731  }
  1732  
  1733  func TestFreezeSymbol(t *testing.T) {
  1734  	const SCRIPT = `
  1735  		var s = Symbol(1);
  1736  		var o = {};
  1737  		o[s] = 42;
  1738  		Object.freeze(o);
  1739  		o[s] = 43;
  1740  		o[s] === 42 && Object.isFrozen(o);
  1741  	`
  1742  
  1743  	testScript(SCRIPT, valueTrue, t)
  1744  }
  1745  
  1746  func TestToPropertyKey(t *testing.T) {
  1747  	const SCRIPT = `
  1748  	var sym = Symbol(42);
  1749  	var callCount = 0;
  1750  
  1751  	var wrapper = {
  1752  	  toString: function() {
  1753  		callCount += 1;
  1754  		return sym;
  1755  	  },
  1756  	  valueOf: function() {
  1757  		$ERROR("valueOf() called");
  1758  	  }
  1759  	};
  1760  
  1761  	var o = {};
  1762  	o[wrapper] = function() { return "test" };
  1763  	assert.sameValue(o[wrapper], o[sym], "o[wrapper] === o[sym]");
  1764  	assert.sameValue(o[wrapper](), "test", "o[wrapper]()");
  1765  	assert.sameValue(o[sym](), "test", "o[sym]()");
  1766  
  1767  	var wrapper1 = {};
  1768  	wrapper1[Symbol.toPrimitive] = function(hint) {
  1769  		if (hint === "string" || hint === "default") {
  1770  			return "1";
  1771  		}
  1772  		if (hint === "number") {
  1773  			return 2;
  1774  		}
  1775  		$ERROR("Unknown hint value "+hint);
  1776  	};
  1777  	var a = [];
  1778  	a[wrapper1] = 42;
  1779  	assert.sameValue(a[1], 42, "a[1]");
  1780  	assert.sameValue(a[1], a[wrapper1], "a[1] === a[wrapper1]");
  1781  	`
  1782  
  1783  	testScriptWithTestLib(SCRIPT, _undefined, t)
  1784  }
  1785  
  1786  func TestPrimThisValue(t *testing.T) {
  1787  	const SCRIPT = `
  1788  	function t() {
  1789  		'use strict';
  1790  
  1791  		Boolean.prototype.toString = function() {
  1792  		  return typeof this;
  1793  		};
  1794  
  1795  		assert.sameValue(true.toLocaleString(), "boolean");
  1796  
  1797  		Boolean.prototype[Symbol.iterator] = function() {
  1798  			return [typeof this][Symbol.iterator]();
  1799  		}
  1800  		var s = new Set(true);
  1801  		assert.sameValue(s.size, 1, "size");
  1802  		assert.sameValue(s.has("boolean"), true, "s.has('boolean')");
  1803  	}
  1804  	t();
  1805  	`
  1806  
  1807  	testScriptWithTestLib(SCRIPT, _undefined, t)
  1808  }
  1809  
  1810  func TestPrimThisValueGetter(t *testing.T) {
  1811  	const SCRIPT = `
  1812  	function t() {
  1813  		'use strict';
  1814  		Object.defineProperty(Boolean.prototype, "toString", {
  1815  		  get: function() {
  1816  			var v = typeof this;
  1817  			return function() {
  1818  			  return v;
  1819  			};
  1820  		  }
  1821  		});
  1822  
  1823  		assert.sameValue(true.toLocaleString(), "boolean");
  1824  	}
  1825  	t();
  1826  	`
  1827  
  1828  	testScriptWithTestLib(SCRIPT, _undefined, t)
  1829  }
  1830  
  1831  func TestObjSetSym(t *testing.T) {
  1832  	const SCRIPT = `
  1833  	'use strict';
  1834  	var sym = Symbol(true);
  1835  	var p1 = Object.create(null);
  1836  	var p2 = Object.create(p1);
  1837  	
  1838  	Object.defineProperty(p1, sym, {
  1839  	value: 42
  1840  	});
  1841  	
  1842  	Object.defineProperty(p2, sym, {
  1843  	value: 43,
  1844  	writable: true,
  1845  	});
  1846  	var o = Object.create(p2);
  1847  	o[sym] = 44;
  1848  	o[sym];
  1849  	`
  1850  	testScript(SCRIPT, intToValue(44), t)
  1851  }
  1852  
  1853  func TestObjSet(t *testing.T) {
  1854  	const SCRIPT = `
  1855  	'use strict';
  1856  	var p1 = Object.create(null);
  1857  	var p2 = Object.create(p1);
  1858  	
  1859  	Object.defineProperty(p1, "test", {
  1860  	value: 42
  1861  	});
  1862  	
  1863  	Object.defineProperty(p2, "test", {
  1864  	value: 43,
  1865  	writable: true,
  1866  	});
  1867  	var o = Object.create(p2);
  1868  	o.test = 44;
  1869  	o.test;
  1870  	`
  1871  	testScript(SCRIPT, intToValue(44), t)
  1872  }
  1873  
  1874  func TestToValueNilValue(t *testing.T) {
  1875  	r := New()
  1876  	var a Value
  1877  	r.Set("a", a)
  1878  	ret, err := r.RunString(`
  1879  	""+a;
  1880  	`)
  1881  	if err != nil {
  1882  		t.Fatal(err)
  1883  	}
  1884  	if !asciiString("null").SameAs(ret) {
  1885  		t.Fatalf("ret: %v", ret)
  1886  	}
  1887  }
  1888  
  1889  func TestDateConversion(t *testing.T) {
  1890  	now := time.Now()
  1891  	vm := New()
  1892  	val, err := vm.New(vm.Get("Date").ToObject(vm), vm.ToValue(now.UnixNano()/1e6))
  1893  	if err != nil {
  1894  		t.Fatal(err)
  1895  	}
  1896  	vm.Set("d", val)
  1897  	res, err := vm.RunString(`+d`)
  1898  	if err != nil {
  1899  		t.Fatal(err)
  1900  	}
  1901  	if exp := res.Export(); exp != now.UnixNano()/1e6 {
  1902  		t.Fatalf("Value does not match: %v", exp)
  1903  	}
  1904  	vm.Set("goval", now)
  1905  	res, err = vm.RunString(`+(new Date(goval.UnixNano()/1e6))`)
  1906  	if err != nil {
  1907  		t.Fatal(err)
  1908  	}
  1909  	if exp := res.Export(); exp != now.UnixNano()/1e6 {
  1910  		t.Fatalf("Value does not match: %v", exp)
  1911  	}
  1912  }
  1913  
  1914  func TestNativeCtorNewTarget(t *testing.T) {
  1915  	const SCRIPT = `
  1916  	function NewTarget() {
  1917  	}
  1918  
  1919  	var o = Reflect.construct(Number, [1], NewTarget);
  1920  	o.__proto__ === NewTarget.prototype && o.toString() === "[object Number]";
  1921  	`
  1922  	testScript(SCRIPT, valueTrue, t)
  1923  }
  1924  
  1925  func TestNativeCtorNonNewCall(t *testing.T) {
  1926  	vm := New()
  1927  	vm.Set(`Animal`, func(call ConstructorCall) *Object {
  1928  		obj := call.This
  1929  		obj.Set(`name`, call.Argument(0).String())
  1930  		obj.Set(`eat`, func(call FunctionCall) Value {
  1931  			self := call.This.(*Object)
  1932  			return vm.ToValue(fmt.Sprintf("%s eat", self.Get(`name`)))
  1933  		})
  1934  		return nil
  1935  	})
  1936  	v, err := vm.RunString(`
  1937  
  1938  	function __extends(d, b){
  1939  		function __() {
  1940  			this.constructor = d;
  1941  		}
  1942  		d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  1943  	}
  1944  
  1945  	var Cat = (function (_super) {
  1946  		__extends(Cat, _super);
  1947  		function Cat() {
  1948  			return _super.call(this, "cat") || this;
  1949  		}
  1950  		return Cat;
  1951  	}(Animal));
  1952  
  1953  	var cat = new Cat();
  1954  	cat instanceof Cat && cat.eat() === "cat eat";
  1955  	`)
  1956  	if err != nil {
  1957  		t.Fatal(err)
  1958  	}
  1959  	if v != valueTrue {
  1960  		t.Fatal(v)
  1961  	}
  1962  }
  1963  
  1964  func ExampleNewSymbol() {
  1965  	sym1 := NewSymbol("66")
  1966  	sym2 := NewSymbol("66")
  1967  	fmt.Printf("%s %s %v", sym1, sym2, sym1.Equals(sym2))
  1968  	// Output: 66 66 false
  1969  }
  1970  
  1971  func ExampleObject_SetSymbol() {
  1972  	type IterResult struct {
  1973  		Done  bool
  1974  		Value Value
  1975  	}
  1976  
  1977  	vm := New()
  1978  	vm.SetFieldNameMapper(UncapFieldNameMapper()) // to use IterResult
  1979  
  1980  	o := vm.NewObject()
  1981  	o.SetSymbol(SymIterator, func() *Object {
  1982  		count := 0
  1983  		iter := vm.NewObject()
  1984  		iter.Set("next", func() IterResult {
  1985  			if count < 10 {
  1986  				count++
  1987  				return IterResult{
  1988  					Value: vm.ToValue(count),
  1989  				}
  1990  			}
  1991  			return IterResult{
  1992  				Done: true,
  1993  			}
  1994  		})
  1995  		return iter
  1996  	})
  1997  	vm.Set("o", o)
  1998  
  1999  	res, err := vm.RunString(`
  2000  	var acc = "";
  2001  	for (var v of o) {
  2002  		acc += v + " ";
  2003  	}
  2004  	acc;
  2005  	`)
  2006  	if err != nil {
  2007  		panic(err)
  2008  	}
  2009  	fmt.Println(res)
  2010  	// Output: 1 2 3 4 5 6 7 8 9 10
  2011  }
  2012  
  2013  func ExampleRuntime_NewArray() {
  2014  	vm := New()
  2015  	array := vm.NewArray(1, 2, true)
  2016  	vm.Set("array", array)
  2017  	res, err := vm.RunString(`
  2018  	var acc = "";
  2019  	for (var v of array) {
  2020  		acc += v + " ";
  2021  	}
  2022  	acc;
  2023  	`)
  2024  	if err != nil {
  2025  		panic(err)
  2026  	}
  2027  	fmt.Println(res)
  2028  	// Output: 1 2 true
  2029  }
  2030  
  2031  func ExampleRuntime_SetParserOptions() {
  2032  	vm := New()
  2033  	vm.SetParserOptions(parser.WithDisableSourceMaps)
  2034  
  2035  	res, err := vm.RunString(`
  2036  	"I did not hang!";
  2037  //# sourceMappingURL=/dev/zero`)
  2038  
  2039  	if err != nil {
  2040  		panic(err)
  2041  	}
  2042  	fmt.Println(res.String())
  2043  	// Output: I did not hang!
  2044  }
  2045  
  2046  func TestRuntime_SetParserOptions_Eval(t *testing.T) {
  2047  	vm := New()
  2048  	vm.SetParserOptions(parser.WithDisableSourceMaps)
  2049  
  2050  	_, err := vm.RunString(`
  2051  	eval("//# sourceMappingURL=/dev/zero");
  2052  	`)
  2053  	if err != nil {
  2054  		t.Fatal(err)
  2055  	}
  2056  }
  2057  
  2058  func TestNativeCallWithRuntimeParameter(t *testing.T) {
  2059  	vm := New()
  2060  	vm.Set("f", func(_ FunctionCall, r *Runtime) Value {
  2061  		if r == vm {
  2062  			return valueTrue
  2063  		}
  2064  		return valueFalse
  2065  	})
  2066  	ret, err := vm.RunString(`f()`)
  2067  	if err != nil {
  2068  		t.Fatal(err)
  2069  	}
  2070  	if ret != valueTrue {
  2071  		t.Fatal(ret)
  2072  	}
  2073  }
  2074  
  2075  func TestNestedEnumerate(t *testing.T) {
  2076  	const SCRIPT = `
  2077  	var o = {baz: true, foo: true, bar: true};
  2078  	var res = "";
  2079  	for (var i in o) {
  2080  		delete o.baz;
  2081  		Object.defineProperty(o, "hidden", {value: true, configurable: true});
  2082  		for (var j in o) {
  2083  			Object.defineProperty(o, "0", {value: true, configurable: true});
  2084  			Object.defineProperty(o, "1", {value: true, configurable: true});
  2085  			for (var k in o) {}
  2086  			res += i + "-" + j + " ";
  2087  		}
  2088  	}
  2089  	assert(compareArray(Reflect.ownKeys(o), ["0","1","foo","bar","hidden"]), "keys");
  2090  	res;
  2091  	`
  2092  	testScriptWithTestLib(SCRIPT, asciiString("baz-foo baz-bar foo-foo foo-bar bar-foo bar-bar "), t)
  2093  }
  2094  
  2095  func TestAbandonedEnumerate(t *testing.T) {
  2096  	const SCRIPT = `
  2097  	var o = {baz: true, foo: true, bar: true};
  2098  	var res = "";
  2099  	for (var i in o) {
  2100  		delete o.baz;
  2101  		for (var j in o) {
  2102  			res += i + "-" + j + " ";
  2103  			break;
  2104  		}
  2105  	}
  2106  	res;
  2107  	`
  2108  	testScript(SCRIPT, asciiString("baz-foo foo-foo bar-foo "), t)
  2109  }
  2110  
  2111  func TestIterCloseThrows(t *testing.T) {
  2112  	const SCRIPT = `
  2113  	var returnCount = 0;
  2114  	var iterable = {};
  2115  	var iterator = {
  2116  	  next: function() {
  2117  		return { value: true };
  2118  	  },
  2119  	  return: function() {
  2120  		returnCount += 1;
  2121  		throw new Error();
  2122  	  }
  2123  	};
  2124  	iterable[Symbol.iterator] = function() {
  2125  	  return iterator;
  2126  	};
  2127  
  2128  	try {
  2129  		for (var i of iterable) {
  2130  				break;
  2131  		}
  2132  	} catch (e) {};
  2133  	returnCount;
  2134  	`
  2135  	testScript(SCRIPT, valueInt(1), t)
  2136  }
  2137  
  2138  func TestDeclareGlobalFunc(t *testing.T) {
  2139  	const SCRIPT = `
  2140  	var initial;
  2141  
  2142  	Object.defineProperty(this, 'f', {
  2143  	  enumerable: true,
  2144  	  writable: true,
  2145  	  configurable: false
  2146  	});
  2147  
  2148  	(0,eval)('initial = f; function f() { return 2222; }');
  2149  	var desc = Object.getOwnPropertyDescriptor(this, "f");
  2150  	assert(desc.enumerable, "enumerable");
  2151  	assert(desc.writable, "writable");
  2152  	assert(!desc.configurable, "configurable");
  2153  	assert.sameValue(initial(), 2222);
  2154  	`
  2155  	testScriptWithTestLib(SCRIPT, _undefined, t)
  2156  }
  2157  
  2158  func TestStackOverflowError(t *testing.T) {
  2159  	vm := New()
  2160  	vm.SetMaxCallStackSize(3)
  2161  	_, err := vm.RunString(`
  2162  	function f() {
  2163  		f();
  2164  	}
  2165  	f();
  2166  	`)
  2167  	if _, ok := err.(*StackOverflowError); !ok {
  2168  		t.Fatal(err)
  2169  	}
  2170  }
  2171  
  2172  func TestStacktraceLocationThrowFromCatch(t *testing.T) {
  2173  	vm := New()
  2174  	_, err := vm.RunString(`
  2175  	function main(arg) {
  2176  		try {
  2177  			if (arg === 1) {
  2178  				return f1();
  2179  			}
  2180  			if (arg === 2) {
  2181  				return f2();
  2182  			}
  2183  			if (arg === 3) {
  2184  				return f3();
  2185  			}
  2186  		} catch (e) {
  2187  			throw e;
  2188  		}
  2189  	}
  2190  	function f1() {}
  2191  	function f2() {
  2192  		throw new Error();
  2193  	}
  2194  	function f3() {}
  2195  	main(2);
  2196  	`)
  2197  	if err == nil {
  2198  		t.Fatal("Expected error")
  2199  	}
  2200  	stack := err.(*Exception).stack
  2201  	if len(stack) != 2 {
  2202  		t.Fatalf("Unexpected stack len: %v", stack)
  2203  	}
  2204  	if frame := stack[0]; frame.funcName != "main" || frame.pc != 30 {
  2205  		t.Fatalf("Unexpected stack frame 0: %#v", frame)
  2206  	}
  2207  	if frame := stack[1]; frame.funcName != "" || frame.pc != 7 {
  2208  		t.Fatalf("Unexpected stack frame 1: %#v", frame)
  2209  	}
  2210  }
  2211  
  2212  func TestStacktraceLocationThrowFromGo(t *testing.T) {
  2213  	vm := New()
  2214  	f := func() {
  2215  		panic(vm.ToValue("Test"))
  2216  	}
  2217  	vm.Set("f", f)
  2218  	_, err := vm.RunString(`
  2219  	function main() {
  2220  		(function noop() {})();
  2221  		return callee();
  2222  	}
  2223  	function callee() {
  2224  		return f();
  2225  	}
  2226  	main();
  2227  	`)
  2228  	if err == nil {
  2229  		t.Fatal("Expected error")
  2230  	}
  2231  	stack := err.(*Exception).stack
  2232  	if len(stack) != 4 {
  2233  		t.Fatalf("Unexpected stack len: %v", stack)
  2234  	}
  2235  	if frame := stack[0]; !strings.HasSuffix(frame.funcName.String(), "TestStacktraceLocationThrowFromGo.func1") {
  2236  		t.Fatalf("Unexpected stack frame 0: %#v", frame)
  2237  	}
  2238  	if frame := stack[1]; frame.funcName != "callee" || frame.pc != 1 {
  2239  		t.Fatalf("Unexpected stack frame 1: %#v", frame)
  2240  	}
  2241  	if frame := stack[2]; frame.funcName != "main" || frame.pc != 6 {
  2242  		t.Fatalf("Unexpected stack frame 2: %#v", frame)
  2243  	}
  2244  	if frame := stack[3]; frame.funcName != "" || frame.pc != 4 {
  2245  		t.Fatalf("Unexpected stack frame 3: %#v", frame)
  2246  	}
  2247  }
  2248  
  2249  func TestStrToInt64(t *testing.T) {
  2250  	if _, ok := strToInt64(""); ok {
  2251  		t.Fatal("<empty>")
  2252  	}
  2253  	if n, ok := strToInt64("0"); !ok || n != 0 {
  2254  		t.Fatal("0", n, ok)
  2255  	}
  2256  	if n, ok := strToInt64("-0"); ok {
  2257  		t.Fatal("-0", n, ok)
  2258  	}
  2259  	if n, ok := strToInt64("-1"); !ok || n != -1 {
  2260  		t.Fatal("-1", n, ok)
  2261  	}
  2262  	if n, ok := strToInt64("9223372036854775808"); ok {
  2263  		t.Fatal("max+1", n, ok)
  2264  	}
  2265  	if n, ok := strToInt64("9223372036854775817"); ok {
  2266  		t.Fatal("9223372036854775817", n, ok)
  2267  	}
  2268  	if n, ok := strToInt64("-9223372036854775818"); ok {
  2269  		t.Fatal("-9223372036854775818", n, ok)
  2270  	}
  2271  	if n, ok := strToInt64("9223372036854775807"); !ok || n != 9223372036854775807 {
  2272  		t.Fatal("max", n, ok)
  2273  	}
  2274  	if n, ok := strToInt64("-9223372036854775809"); ok {
  2275  		t.Fatal("min-1", n, ok)
  2276  	}
  2277  	if n, ok := strToInt64("-9223372036854775808"); !ok || n != -9223372036854775808 {
  2278  		t.Fatal("min", n, ok)
  2279  	}
  2280  	if n, ok := strToInt64("-00"); ok {
  2281  		t.Fatal("-00", n, ok)
  2282  	}
  2283  	if n, ok := strToInt64("-01"); ok {
  2284  		t.Fatal("-01", n, ok)
  2285  	}
  2286  }
  2287  
  2288  func TestStrToInt32(t *testing.T) {
  2289  	if _, ok := strToInt32(""); ok {
  2290  		t.Fatal("<empty>")
  2291  	}
  2292  	if n, ok := strToInt32("0"); !ok || n != 0 {
  2293  		t.Fatal("0", n, ok)
  2294  	}
  2295  	if n, ok := strToInt32("-0"); ok {
  2296  		t.Fatal("-0", n, ok)
  2297  	}
  2298  	if n, ok := strToInt32("-1"); !ok || n != -1 {
  2299  		t.Fatal("-1", n, ok)
  2300  	}
  2301  	if n, ok := strToInt32("2147483648"); ok {
  2302  		t.Fatal("max+1", n, ok)
  2303  	}
  2304  	if n, ok := strToInt32("2147483657"); ok {
  2305  		t.Fatal("2147483657", n, ok)
  2306  	}
  2307  	if n, ok := strToInt32("-2147483658"); ok {
  2308  		t.Fatal("-2147483658", n, ok)
  2309  	}
  2310  	if n, ok := strToInt32("2147483647"); !ok || n != 2147483647 {
  2311  		t.Fatal("max", n, ok)
  2312  	}
  2313  	if n, ok := strToInt32("-2147483649"); ok {
  2314  		t.Fatal("min-1", n, ok)
  2315  	}
  2316  	if n, ok := strToInt32("-2147483648"); !ok || n != -2147483648 {
  2317  		t.Fatal("min", n, ok)
  2318  	}
  2319  	if n, ok := strToInt32("-00"); ok {
  2320  		t.Fatal("-00", n, ok)
  2321  	}
  2322  	if n, ok := strToInt32("-01"); ok {
  2323  		t.Fatal("-01", n, ok)
  2324  	}
  2325  }
  2326  
  2327  func TestDestructSymbol(t *testing.T) {
  2328  	const SCRIPT = `
  2329  	var S = Symbol("S");
  2330  	var s, rest;
  2331  
  2332  	({[S]: s, ...rest} = {[S]: true, test: 1});
  2333  	assert.sameValue(s, true, "S");
  2334  	assert(deepEqual(rest, {test: 1}), "rest");
  2335  	`
  2336  	testScriptWithTestLibX(SCRIPT, _undefined, t)
  2337  }
  2338  
  2339  func TestAccessorFuncName(t *testing.T) {
  2340  	const SCRIPT = `
  2341  	const namedSym = Symbol('test262');
  2342  	const emptyStrSym = Symbol("");
  2343  	const anonSym = Symbol();
  2344  
  2345  	const o = {
  2346  	  get id() {},
  2347  	  get [anonSym]() {},
  2348  	  get [namedSym]() {},
  2349        get [emptyStrSym]() {},
  2350  	  set id(v) {},
  2351  	  set [anonSym](v) {},
  2352  	  set [namedSym](v) {},
  2353        set [emptyStrSym](v) {}
  2354  	};
  2355  
  2356  	let prop;
  2357  	prop = Object.getOwnPropertyDescriptor(o, 'id');
  2358  	assert.sameValue(prop.get.name, 'get id');
  2359  	assert.sameValue(prop.set.name, 'set id');
  2360  
  2361  	prop = Object.getOwnPropertyDescriptor(o, anonSym);
  2362  	assert.sameValue(prop.get.name, 'get ');
  2363  	assert.sameValue(prop.set.name, 'set ');
  2364  
  2365  	prop = Object.getOwnPropertyDescriptor(o, emptyStrSym);
  2366  	assert.sameValue(prop.get.name, 'get []');
  2367  	assert.sameValue(prop.set.name, 'set []');
  2368  
  2369  	prop = Object.getOwnPropertyDescriptor(o, namedSym);
  2370  	assert.sameValue(prop.get.name, 'get [test262]');
  2371  	assert.sameValue(prop.set.name, 'set [test262]');
  2372  	`
  2373  	testScriptWithTestLib(SCRIPT, _undefined, t)
  2374  }
  2375  
  2376  func TestCoverFuncName(t *testing.T) {
  2377  	const SCRIPT = `
  2378  	var namedSym = Symbol('');
  2379  	var anonSym = Symbol();
  2380  	var o;
  2381  
  2382  	o = {
  2383  	  xId: (0, function() {}),
  2384  	  id: (function() {}),
  2385        id1: function x() {},
  2386  	  [anonSym]: (function() {}),
  2387  	  [namedSym]: (function() {})
  2388  	};
  2389  
  2390  	assert(o.xId.name !== 'xId');
  2391  	assert.sameValue(o.id1.name, 'x'); 
  2392  	assert.sameValue(o.id.name, 'id', 'via IdentifierName');
  2393  	assert.sameValue(o[anonSym].name, '', 'via anonymous Symbol');
  2394  	assert.sameValue(o[namedSym].name, '[]', 'via Symbol');
  2395  	`
  2396  	testScriptWithTestLib(SCRIPT, _undefined, t)
  2397  }
  2398  
  2399  func TestAnonFuncName(t *testing.T) {
  2400  	const SCRIPT = `
  2401  	const d = Object.getOwnPropertyDescriptor((function() {}), 'name');
  2402  	d !== undefined && d.value === '';
  2403  	`
  2404  	testScript(SCRIPT, valueTrue, t)
  2405  }
  2406  
  2407  func TestStringToBytesConversion(t *testing.T) {
  2408  	vm := New()
  2409  	v := vm.ToValue("Test")
  2410  	var b []byte
  2411  	err := vm.ExportTo(v, &b)
  2412  	if err != nil {
  2413  		t.Fatal(err)
  2414  	}
  2415  	if string(b) != "Test" {
  2416  		t.Fatal(b)
  2417  	}
  2418  }
  2419  
  2420  func TestPromiseAll(t *testing.T) {
  2421  	const SCRIPT = `
  2422  var p1 = new Promise(function() {});
  2423  var p2 = new Promise(function() {});
  2424  var p3 = new Promise(function() {});
  2425  var callCount = 0;
  2426  var currentThis = p1;
  2427  var nextThis = p2;
  2428  var afterNextThis = p3;
  2429  
  2430  p1.then = p2.then = p3.then = function(a, b) {
  2431    assert.sameValue(typeof a, 'function', 'type of first argument');
  2432    assert.sameValue(
  2433      a.length,
  2434      1,
  2435      'ES6 25.4.1.3.2: The length property of a promise resolve function is 1.'
  2436    );
  2437    assert.sameValue(typeof b, 'function', 'type of second argument');
  2438    assert.sameValue(
  2439      b.length,
  2440      1,
  2441      'ES6 25.4.1.3.1: The length property of a promise reject function is 1.'
  2442    );
  2443    assert.sameValue(arguments.length, 2, '"then"" invoked with two arguments');
  2444    assert.sameValue(this, currentThis, '"this" value');
  2445  
  2446    currentThis = nextThis;
  2447    nextThis = afterNextThis;
  2448    afterNextThis = null;
  2449  
  2450    callCount += 1;
  2451  };
  2452  
  2453  Promise.all([p1, p2, p3]);
  2454  
  2455  assert.sameValue(callCount, 3, '"then"" invoked once for every iterated value');
  2456  	`
  2457  	testScriptWithTestLib(SCRIPT, _undefined, t)
  2458  }
  2459  
  2460  func TestPromiseExport(t *testing.T) {
  2461  	vm := New()
  2462  	p, _, _ := vm.NewPromise()
  2463  	pv := vm.ToValue(p)
  2464  	if actual := pv.ExportType(); actual != reflect.TypeOf((*Promise)(nil)) {
  2465  		t.Fatalf("Export type: %v", actual)
  2466  	}
  2467  
  2468  	if ev := pv.Export(); ev != p {
  2469  		t.Fatalf("Export value: %v", ev)
  2470  	}
  2471  }
  2472  
  2473  func TestErrorStack(t *testing.T) {
  2474  	const SCRIPT = `
  2475  	const err = new Error("test");
  2476  	if (!("stack" in err)) {
  2477  		throw new Error("in");
  2478  	}
  2479  	if (Reflect.ownKeys(err)[0] !== "stack") {
  2480  		throw new Error("property order");
  2481  	}
  2482  	if (err.stack !== "Error\n\tat test.js:2:14(3)\n") {
  2483  		throw new Error(stack);
  2484  	}
  2485  	delete err.stack;
  2486  	if ("stack" in err) {
  2487  		throw new Error("stack still in err after delete");
  2488  	}
  2489  	`
  2490  	testScript(SCRIPT, _undefined, t)
  2491  }
  2492  
  2493  func TestErrorFormatSymbols(t *testing.T) {
  2494  	vm := New()
  2495  	vm.Set("a", func() (Value, error) { return nil, errors.New("something %s %f") })
  2496  	_, err := vm.RunString("a()")
  2497  	if !strings.Contains(err.Error(), "something %s %f") {
  2498  		t.Fatalf("Wrong value %q", err.Error())
  2499  	}
  2500  }
  2501  
  2502  /*
  2503  func TestArrayConcatSparse(t *testing.T) {
  2504  function foo(a,b,c)
  2505    {
  2506      arguments[0] = 1; arguments[1] = 'str'; arguments[2] = 2.1;
  2507      if(1 === a && 'str' === b && 2.1 === c)
  2508        return true;
  2509    }
  2510  
  2511  
  2512  	const SCRIPT = `
  2513  	var a1 = [];
  2514  	var a2 = [];
  2515  	a1[500000] = 1;
  2516  	a2[1000000] = 2;
  2517  	var a3 = a1.concat(a2);
  2518  	a3.length === 1500002 && a3[500000] === 1 && a3[1500001] == 2;
  2519  	`
  2520  
  2521  	testScript(SCRIPT, valueTrue, t)
  2522  }
  2523  */
  2524  
  2525  func BenchmarkCallReflect(b *testing.B) {
  2526  	vm := New()
  2527  	vm.Set("f", func(v Value) {
  2528  
  2529  	})
  2530  
  2531  	prg := MustCompile("test.js", "f(null)", true)
  2532  
  2533  	b.ResetTimer()
  2534  	for i := 0; i < b.N; i++ {
  2535  		vm.RunProgram(prg)
  2536  	}
  2537  }
  2538  
  2539  func BenchmarkCallNative(b *testing.B) {
  2540  	vm := New()
  2541  	vm.Set("f", func(call FunctionCall) (ret Value) {
  2542  		return
  2543  	})
  2544  
  2545  	prg := MustCompile("test.js", "f(null)", true)
  2546  
  2547  	b.ResetTimer()
  2548  	for i := 0; i < b.N; i++ {
  2549  		vm.RunProgram(prg)
  2550  	}
  2551  }
  2552  
  2553  func BenchmarkMainLoop(b *testing.B) {
  2554  	vm := New()
  2555  
  2556  	const SCRIPT = `
  2557  		for (var i=0; i<100000; i++) {
  2558  		}
  2559  	`
  2560  
  2561  	prg := MustCompile("test.js", SCRIPT, true)
  2562  
  2563  	b.ResetTimer()
  2564  	for i := 0; i < b.N; i++ {
  2565  		vm.RunProgram(prg)
  2566  	}
  2567  }
  2568  
  2569  func BenchmarkStringMapGet(b *testing.B) {
  2570  	m := make(map[string]Value)
  2571  	for i := 0; i < 100; i++ {
  2572  		m[strconv.Itoa(i)] = intToValue(int64(i))
  2573  	}
  2574  	b.ResetTimer()
  2575  	for i := 0; i < b.N; i++ {
  2576  		if m["50"] == nil {
  2577  			b.Fatal()
  2578  		}
  2579  	}
  2580  }
  2581  
  2582  func BenchmarkValueStringMapGet(b *testing.B) {
  2583  	m := make(map[valueString]Value)
  2584  	for i := 0; i < 100; i++ {
  2585  		m[asciiString(strconv.Itoa(i))] = intToValue(int64(i))
  2586  	}
  2587  	b.ResetTimer()
  2588  	var key valueString = asciiString("50")
  2589  	for i := 0; i < b.N; i++ {
  2590  		if m[key] == nil {
  2591  			b.Fatal()
  2592  		}
  2593  	}
  2594  }
  2595  
  2596  func BenchmarkAsciiStringMapGet(b *testing.B) {
  2597  	m := make(map[asciiString]Value)
  2598  	for i := 0; i < 100; i++ {
  2599  		m[asciiString(strconv.Itoa(i))] = intToValue(int64(i))
  2600  	}
  2601  	b.ResetTimer()
  2602  	var key = asciiString("50")
  2603  	for i := 0; i < b.N; i++ {
  2604  		if m[key] == nil {
  2605  			b.Fatal()
  2606  		}
  2607  	}
  2608  }