diff --git a/src/core/org/luaj/vm2/LuaError.java b/src/core/org/luaj/vm2/LuaError.java index 03c3d5b9..e57035c6 100644 --- a/src/core/org/luaj/vm2/LuaError.java +++ b/src/core/org/luaj/vm2/LuaError.java @@ -40,10 +40,14 @@ public class LuaError extends RuntimeException { private static String errorHook(String msg) { LuaThread thread = LuaThread.getRunning(); if ( thread.err != null ) { + LuaValue errfunc = thread.err; + thread.err = null; try { - return thread.err.call( LuaValue.valueOf(msg) ).tojstring(); + return errfunc.call( LuaValue.valueOf(msg) ).tojstring(); } catch ( Throwable t ) { return "error in error handling"; + } finally { + thread.err = errfunc; } } return msg; diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index cc158eed..f5b639f5 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -238,43 +238,21 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { return varargsOf(NIL, valueOf(e.getMessage())); } case 5: // "pcall", // (f, arg1, ...) -> status, result1, ... + { + LuaThread.onCall(this); try { - LuaThread.onCall(this); - try { - return varargsOf(LuaValue.TRUE, args.arg1().invoke(args.subargs(2))); - } finally { - LuaThread.onReturn(); - } - } catch ( LuaError le ) { - String m = le.getMessage(); - return varargsOf(FALSE, m!=null? valueOf(m): NIL); - } catch ( Exception e ) { - String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + return pcall(args.arg1(),args.subargs(2),null); + } finally { + LuaThread.onReturn(); } + } case 6: // "xpcall", // (f, err) -> result1, ... { - LuaValue errfunc = args.checkvalue(2); + LuaThread.onCall(this); try { - LuaThread.onCall(this); - try { - LuaThread thread = LuaThread.getRunning(); - LuaValue olderr = thread.err; - try { - thread.err = errfunc; - return varargsOf(LuaValue.TRUE, args.arg1().invoke(args.subargs(2))); - } finally { - thread.err = olderr; - } - } finally { - LuaThread.onReturn(); - } - } catch ( LuaError le ) { - String m = le.getMessage(); - return varargsOf(FALSE, m!=null? valueOf(m): NIL); - } catch ( Exception e ) { - String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + return pcall(args.arg1(),NONE,args.checkvalue(2)); + } finally { + LuaThread.onReturn(); } } case 7: // "print", // (...) -> void @@ -358,6 +336,25 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { } } + public static Varargs pcall(LuaValue func, Varargs args, LuaValue errfunc) { + try { + LuaThread thread = LuaThread.getRunning(); + LuaValue olderr = thread.err; + try { + thread.err = errfunc; + return varargsOf(LuaValue.TRUE, func.invoke(args)); + } finally { + thread.err = olderr; + } + } catch ( LuaError le ) { + String m = le.getMessage(); + return varargsOf(FALSE, m!=null? valueOf(m): NIL); + } catch ( Exception e ) { + String m = e.getMessage(); + return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + } + } + public static Varargs loadFile(String filename) throws IOException { InputStream is = FINDER.findResource(filename); if ( is == null ) diff --git a/test/lua/baselib.lua b/test/lua/baselib.lua index 2b99756a..a4e893fb 100644 --- a/test/lua/baselib.lua +++ b/test/lua/baselib.lua @@ -286,3 +286,20 @@ print( 'pcall(unpack,t,function() end)', pcall(unpack,t,function() end) ); -- _VERSION print( '_VERSION', type(_VERSION) ) +-- xpcall +local errfunc = function( detail ) + print( ' in errfunc', type(detail) ) + return 'response-from-xpcall' +end +local badfunc = function() error( 'error-from-badfunc' ) end +local wrappedbad = function() pcall( badfunc ) end +print( 'pcall(badfunc)', pcall(badfunc) ) +print( 'pcall(badfunc,errfunc)', pcall(badfunc,errfunc) ) +print( 'pcall(badfunc,badfunc)', pcall(badfunc,badfunc) ) +print( 'pcall(wrappedbad)', pcall(wrappedbad) ) +print( 'pcall(wrappedbad,errfunc)', pcall(wrappedbad,errfunc) ) +print( 'pcall(xpcall(badfunc))', pcall(xpcall,badfunc) ) +print( 'pcall(xpcall(badfunc,errfunc))', pcall(xpcall,badfunc,errfunc) ) +print( 'pcall(xpcall(badfunc,badfunc))', pcall(xpcall,badfunc,badfunc) ) +print( 'pcall(xpcall(wrappedbad))', pcall(xpcall,wrappedbad) ) +print( 'xpcall(wrappedbad,errfunc)', xpcall(wrappedbad,errfunc) )