Browse Source

Do not modify sb for variadic calls as it breaks local variables resolution. Instead place a marker on stack and use it to count the number of args. Fixes #311.

Dmitry Panov 4 years ago
parent
commit
26be9bf29f
2 changed files with 29 additions and 7 deletions
  1. 11 0
      compiler_test.go
  2. 18 7
      vm.go

+ 11 - 0
compiler_test.go

@@ -4020,6 +4020,17 @@ func TestVariadicNew(t *testing.T) {
 	testScript1(SCRIPT, asciiString("1,a,2"), t)
 	testScript1(SCRIPT, asciiString("1,a,2"), t)
 }
 }
 
 
+func TestVariadicUseStackVars(t *testing.T) {
+	const SCRIPT = `
+	function A(message) { return message; }
+	function B(...args){
+			return A(...args);
+	}
+	B("C");
+	`
+	testScript1(SCRIPT, asciiString("C"), t)
+}
+
 /*
 /*
 func TestBabel(t *testing.T) {
 func TestBabel(t *testing.T) {
 	src, err := ioutil.ReadFile("babel7.js")
 	src, err := ioutil.ReadFile("babel7.js")

+ 18 - 7
vm.go

@@ -2494,7 +2494,7 @@ type _callEvalVariadic struct{}
 var callEvalVariadic _callEvalVariadic
 var callEvalVariadic _callEvalVariadic
 
 
 func (_callEvalVariadic) exec(vm *vm) {
 func (_callEvalVariadic) exec(vm *vm) {
-	vm.callEval(vm.sp-vm.sb-2, false)
+	vm.callEval(vm.countVariadicArgs()-2, false)
 }
 }
 
 
 type _callEvalVariadicStrict struct{}
 type _callEvalVariadicStrict struct{}
@@ -2502,7 +2502,7 @@ type _callEvalVariadicStrict struct{}
 var callEvalVariadicStrict _callEvalVariadicStrict
 var callEvalVariadicStrict _callEvalVariadicStrict
 
 
 func (_callEvalVariadicStrict) exec(vm *vm) {
 func (_callEvalVariadicStrict) exec(vm *vm) {
-	vm.callEval(vm.sp-vm.sb-2, true)
+	vm.callEval(vm.countVariadicArgs()-2, true)
 }
 }
 
 
 type _boxThis struct{}
 type _boxThis struct{}
@@ -2519,13 +2519,14 @@ func (_boxThis) exec(vm *vm) {
 	vm.pc++
 	vm.pc++
 }
 }
 
 
+var variadicMarker Value = newSymbol(asciiString("[variadic marker]"))
+
 type _startVariadic struct{}
 type _startVariadic struct{}
 
 
 var startVariadic _startVariadic
 var startVariadic _startVariadic
 
 
 func (_startVariadic) exec(vm *vm) {
 func (_startVariadic) exec(vm *vm) {
-	vm.push(valueInt(vm.sb))
-	vm.sb = vm.sp
+	vm.push(variadicMarker)
 	vm.pc++
 	vm.pc++
 }
 }
 
 
@@ -2533,8 +2534,19 @@ type _callVariadic struct{}
 
 
 var callVariadic _callVariadic
 var callVariadic _callVariadic
 
 
+func (vm *vm) countVariadicArgs() int {
+	count := 0
+	for i := vm.sp - 1; i >= 0; i-- {
+		if vm.stack[i] == variadicMarker {
+			return count
+		}
+		count++
+	}
+	panic("Variadic marker was not found. Compiler bug.")
+}
+
 func (_callVariadic) exec(vm *vm) {
 func (_callVariadic) exec(vm *vm) {
-	call(vm.sp - vm.sb - 2).exec(vm)
+	call(vm.countVariadicArgs() - 2).exec(vm)
 }
 }
 
 
 type _endVariadic struct{}
 type _endVariadic struct{}
@@ -2543,7 +2555,6 @@ var endVariadic _endVariadic
 
 
 func (_endVariadic) exec(vm *vm) {
 func (_endVariadic) exec(vm *vm) {
 	vm.sp--
 	vm.sp--
-	vm.sb = int(vm.stack[vm.sp-1].(valueInt))
 	vm.stack[vm.sp-1] = vm.stack[vm.sp]
 	vm.stack[vm.sp-1] = vm.stack[vm.sp]
 	vm.pc++
 	vm.pc++
 }
 }
@@ -3480,7 +3491,7 @@ type _newVariadic struct{}
 var newVariadic _newVariadic
 var newVariadic _newVariadic
 
 
 func (_newVariadic) exec(vm *vm) {
 func (_newVariadic) exec(vm *vm) {
-	_new(vm.sp - vm.sb - 1).exec(vm)
+	_new(vm.countVariadicArgs() - 1).exec(vm)
 }
 }
 
 
 type _new uint32
 type _new uint32