Răsfoiți Sursa

Reserve a stack slot for 'this' in recursive RunProgram calls. Fixes #477

Dmitry Panov 2 ani în urmă
părinte
comite
78b980256d
2 a modificat fișierele cu 9 adăugiri și 5 ștergeri
  1. 7 3
      runtime.go
  2. 2 2
      runtime_test.go

+ 7 - 3
runtime.go

@@ -1444,7 +1444,7 @@ func (r *Runtime) RunProgram(p *Program) (result Value, err error) {
 	recursive := len(vm.callStack) > 0
 	defer func() {
 		if recursive {
-			vm.sp--
+			vm.sp -= 2
 			vm.popCtx()
 		} else {
 			vm.callStack = vm.callStack[:len(vm.callStack)-1]
@@ -1463,8 +1463,12 @@ func (r *Runtime) RunProgram(p *Program) (result Value, err error) {
 	if recursive {
 		vm.pushCtx()
 		vm.stash = &r.global.stash
-		vm.push(_undefined) // make sure the 'callee' value (stack[sb-1]) is set
-		vm.sb = vm.sp
+		sp := vm.sp
+		vm.stack.expand(sp + 1)
+		vm.stack[sp] = _undefined // 'callee'
+		vm.stack[sp+1] = nil      // 'this'
+		vm.sb = sp + 1
+		vm.sp = sp + 2
 	} else {
 		vm.callStack = append(vm.callStack, context{})
 	}

+ 2 - 2
runtime_test.go

@@ -211,7 +211,7 @@ func TestRecursiveRun(t *testing.T) {
 	// corruptions occur.
 	vm := New()
 	vm.Set("f", func() (Value, error) {
-		return vm.RunString("let x = 1; { let z = 100, z1 = 200, z2 = 300, z3 = 400; } x;")
+		return vm.RunString("let x = 1; { let z = 100, z1 = 200, z2 = 300, z3 = 400; x = x + z3} x;")
 	})
 	res, err := vm.RunString(`
 	function f1() {
@@ -234,7 +234,7 @@ func TestRecursiveRun(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if !res.SameAs(valueInt(1)) {
+	if !res.SameAs(valueInt(401)) {
 		t.Fatal(res)
 	}
 }