github.com/kmcsr/goja@v1.0.0/vm_test.go (about)

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