github.com/AnxiangLemon/goja@v0.0.0-20230422122739-2e5df2244546/vm_test.go (about)

     1  package goja
     2  
     3  import (
     4  	"github.com/AnxiangLemon/goja/file"
     5  	"github.com/AnxiangLemon/goja/parser"
     6  	"github.com/AnxiangLemon/goja/unistring"
     7  	"testing"
     8  )
     9  
    10  func TestTaggedTemplateArgExport(t *testing.T) {
    11  	vm := New()
    12  	vm.Set("f", func(v Value) {
    13  		v.Export()
    14  	})
    15  	vm.RunString("f`test`")
    16  }
    17  
    18  func TestVM1(t *testing.T) {
    19  	r := &Runtime{}
    20  	r.init()
    21  
    22  	vm := r.vm
    23  
    24  	vm.prg = &Program{
    25  		src:    file.NewFile("dummy", "", 1),
    26  		values: []Value{valueInt(2), valueInt(3), asciiString("test")},
    27  		code: []instruction{
    28  			&bindGlobal{vars: []unistring.String{"v"}},
    29  			newObject,
    30  			setGlobal("v"),
    31  			loadVal(2),
    32  			loadVal(1),
    33  			loadVal(0),
    34  			add,
    35  			setElem,
    36  			pop,
    37  			loadDynamic("v"),
    38  		},
    39  	}
    40  
    41  	vm.run()
    42  
    43  	rv := vm.pop()
    44  
    45  	if obj, ok := rv.(*Object); ok {
    46  		if v := obj.self.getStr("test", nil).ToInteger(); v != 5 {
    47  			t.Fatalf("Unexpected property value: %v", v)
    48  		}
    49  	} else {
    50  		t.Fatalf("Unexpected result: %v", rv)
    51  	}
    52  
    53  }
    54  
    55  func TestEvalVar(t *testing.T) {
    56  	const SCRIPT = `
    57  	function test() {
    58  		var a;
    59  		return eval("var a = 'yes'; var z = 'no'; a;") === "yes" && a === "yes";
    60  	}
    61  	test();
    62  	`
    63  
    64  	testScript(SCRIPT, valueTrue, t)
    65  }
    66  
    67  func TestResolveMixedStack1(t *testing.T) {
    68  	const SCRIPT = `
    69  	function test(arg) {
    70  		var a = 1;
    71  		var scope = {};
    72  		(function() {return arg})(); // move arguments to stash
    73  		with (scope) {
    74  			a++; // resolveMixedStack1 here
    75  			return a + arg;
    76  		}
    77  	}
    78  	test(40);
    79  	`
    80  
    81  	testScript(SCRIPT, valueInt(42), t)
    82  }
    83  
    84  func TestNewArrayFromIterClosed(t *testing.T) {
    85  	const SCRIPT = `
    86  	const [a, ...other] = [];
    87  	assert.sameValue(a, undefined);
    88  	assert(Array.isArray(other));
    89  	assert.sameValue(other.length, 0);
    90  	`
    91  	testScriptWithTestLib(SCRIPT, _undefined, t)
    92  }
    93  
    94  func BenchmarkVmNOP2(b *testing.B) {
    95  	prg := []func(*vm){
    96  		//loadVal(0).exec,
    97  		//loadVal(1).exec,
    98  		//add.exec,
    99  		jump(1).exec,
   100  	}
   101  
   102  	r := &Runtime{}
   103  	r.init()
   104  
   105  	vm := r.vm
   106  	vm.prg = &Program{
   107  		values: []Value{intToValue(2), intToValue(3)},
   108  	}
   109  
   110  	for i := 0; i < b.N; i++ {
   111  		vm.pc = 0
   112  		for !vm.halted() {
   113  			prg[vm.pc](vm)
   114  		}
   115  		//vm.sp--
   116  		/*r := vm.pop()
   117  		if r.ToInteger() != 5 {
   118  			b.Fatalf("Unexpected result: %+v", r)
   119  		}
   120  		if vm.sp != 0 {
   121  			b.Fatalf("Unexpected sp: %d", vm.sp)
   122  		}*/
   123  	}
   124  }
   125  
   126  func BenchmarkVmNOP(b *testing.B) {
   127  	r := &Runtime{}
   128  	r.init()
   129  
   130  	vm := r.vm
   131  	vm.prg = &Program{
   132  		code: []instruction{
   133  			jump(1),
   134  			//jump(1),
   135  		},
   136  	}
   137  
   138  	for i := 0; i < b.N; i++ {
   139  		vm.pc = 0
   140  		vm.run()
   141  	}
   142  
   143  }
   144  
   145  func BenchmarkVm1(b *testing.B) {
   146  	r := &Runtime{}
   147  	r.init()
   148  
   149  	vm := r.vm
   150  
   151  	//ins1 := loadVal1(0)
   152  	//ins2 := loadVal1(1)
   153  
   154  	vm.prg = &Program{
   155  		values: []Value{valueInt(2), valueInt(3)},
   156  		code: []instruction{
   157  			loadVal(0),
   158  			loadVal(1),
   159  			add,
   160  		},
   161  	}
   162  
   163  	for i := 0; i < b.N; i++ {
   164  		vm.pc = 0
   165  		vm.run()
   166  		r := vm.pop()
   167  		if r.ToInteger() != 5 {
   168  			b.Fatalf("Unexpected result: %+v", r)
   169  		}
   170  		if vm.sp != 0 {
   171  			b.Fatalf("Unexpected sp: %d", vm.sp)
   172  		}
   173  	}
   174  }
   175  
   176  func BenchmarkFib(b *testing.B) {
   177  	const TEST_FIB = `
   178  function fib(n) {
   179  if (n < 2) return n;
   180  return fib(n - 2) + fib(n - 1);
   181  }
   182  
   183  fib(35);
   184  `
   185  	b.StopTimer()
   186  	prg, err := parser.ParseFile(nil, "test.js", TEST_FIB, 0)
   187  	if err != nil {
   188  		b.Fatal(err)
   189  	}
   190  
   191  	c := newCompiler()
   192  	c.compile(prg, false, true, nil)
   193  	c.p.dumpCode(b.Logf)
   194  
   195  	r := &Runtime{}
   196  	r.init()
   197  
   198  	vm := r.vm
   199  
   200  	var expectedResult Value = valueInt(9227465)
   201  
   202  	b.StartTimer()
   203  
   204  	vm.prg = c.p
   205  	vm.run()
   206  	v := vm.result
   207  
   208  	b.Logf("stack size: %d", len(vm.stack))
   209  	b.Logf("stashAllocs: %d", vm.stashAllocs)
   210  
   211  	if !v.SameAs(expectedResult) {
   212  		b.Fatalf("Result: %+v, expected: %+v", v, expectedResult)
   213  	}
   214  
   215  }
   216  
   217  func BenchmarkEmptyLoop(b *testing.B) {
   218  	const SCRIPT = `
   219  	function f() {
   220  		for (var i = 0; i < 100; i++) {
   221  		}
   222  	}
   223  	f()
   224  	`
   225  	b.StopTimer()
   226  	vm := New()
   227  	prg := MustCompile("test.js", SCRIPT, false)
   228  	// prg.dumpCode(log.Printf)
   229  	b.StartTimer()
   230  	for i := 0; i < b.N; i++ {
   231  		vm.RunProgram(prg)
   232  	}
   233  }
   234  
   235  func BenchmarkVMAdd(b *testing.B) {
   236  	vm := &vm{}
   237  	vm.stack = append(vm.stack, nil, nil)
   238  	vm.sp = len(vm.stack)
   239  
   240  	var v1 Value = valueInt(3)
   241  	var v2 Value = valueInt(5)
   242  
   243  	for i := 0; i < b.N; i++ {
   244  		vm.stack[0] = v1
   245  		vm.stack[1] = v2
   246  		add.exec(vm)
   247  		vm.sp++
   248  	}
   249  }
   250  
   251  func BenchmarkFuncCall(b *testing.B) {
   252  	const SCRIPT = `
   253  	function f(a, b, c, d) {
   254  	}
   255  	`
   256  
   257  	b.StopTimer()
   258  
   259  	vm := New()
   260  	prg := MustCompile("test.js", SCRIPT, false)
   261  
   262  	vm.RunProgram(prg)
   263  	if f, ok := AssertFunction(vm.Get("f")); ok {
   264  		b.StartTimer()
   265  		for i := 0; i < b.N; i++ {
   266  			f(nil, nil, intToValue(1), intToValue(2), intToValue(3), intToValue(4), intToValue(5), intToValue(6))
   267  		}
   268  	} else {
   269  		b.Fatal("f is not a function")
   270  	}
   271  }
   272  
   273  func BenchmarkAssertInt(b *testing.B) {
   274  	v := intToValue(42)
   275  	for i := 0; i < b.N; i++ {
   276  		if i, ok := v.(valueInt); !ok || int64(i) != 42 {
   277  			b.Fatal()
   278  		}
   279  	}
   280  }