diff --git a/_glua-tests/issues.lua b/_glua-tests/issues.lua index 514d0b7a..7abcd936 100644 --- a/_glua-tests/issues.lua +++ b/_glua-tests/issues.lua @@ -457,3 +457,14 @@ function test() assert(c == 1) assert(type(c) == "number") end + +-- issue #452 +function test() + local ok, msg = pcall(function() + local ok, msg = xpcall(function() error("fn") end, function(err) error("handler") end) + assert(not ok and msg) + error("expected to reach this.") + end) + assert(not ok) +end +test() \ No newline at end of file diff --git a/_state.go b/_state.go index 645589fe..df169259 100644 --- a/_state.go +++ b/_state.go @@ -1855,6 +1855,9 @@ func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) { err = rcv.(*ApiError) err.(*ApiError).StackTrace = ls.stackTrace(0) } + ls.stack.SetSp(sp) + ls.currentFrame = ls.stack.Last() + ls.reg.SetTop(base) } }() ls.Call(1, 1) diff --git a/state.go b/state.go index 50e70ed6..8e0acbb3 100644 --- a/state.go +++ b/state.go @@ -2014,6 +2014,9 @@ func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) { err = rcv.(*ApiError) err.(*ApiError).StackTrace = ls.stackTrace(0) } + ls.stack.SetSp(sp) + ls.currentFrame = ls.stack.Last() + ls.reg.SetTop(base) } }() ls.Call(1, 1) diff --git a/state_test.go b/state_test.go index bfe93b93..7b7aa53d 100644 --- a/state_test.go +++ b/state_test.go @@ -291,17 +291,39 @@ func TestPCall(t *testing.T) { })) errorIfFalse(t, strings.Contains(err.Error(), "by handler"), "") + L.Push(L.GetGlobal("f1")) err = L.PCall(0, 0, L.NewFunction(func(L *LState) int { L.RaiseError("error!") return 1 })) errorIfFalse(t, strings.Contains(err.Error(), "error!"), "") + L.Push(L.GetGlobal("f1")) err = L.PCall(0, 0, L.NewFunction(func(L *LState) int { panic("panicc!") return 1 })) errorIfFalse(t, strings.Contains(err.Error(), "panicc!"), "") + + // Issue #452, expected to be revert back to previous call stack after any error. + currentFrame, currentTop, currentSp := L.currentFrame, L.GetTop(), L.stack.Sp() + L.Push(L.GetGlobal("f1")) + err = L.PCall(0, 0, nil) + errorIfFalse(t, err != nil, "") + errorIfFalse(t, L.currentFrame == currentFrame, "") + errorIfFalse(t, L.GetTop() == currentTop, "") + errorIfFalse(t, L.stack.Sp() == currentSp, "") + + currentFrame, currentTop, currentSp = L.currentFrame, L.GetTop(), L.stack.Sp() + L.Push(L.GetGlobal("f1")) + err = L.PCall(0, 0, L.NewFunction(func(L *LState) int { + L.RaiseError("error!") + return 1 + })) + errorIfFalse(t, err != nil, "") + errorIfFalse(t, L.currentFrame == currentFrame, "") + errorIfFalse(t, L.GetTop() == currentTop, "") + errorIfFalse(t, L.stack.Sp() == currentSp, "") } func TestCoroutineApi1(t *testing.T) {