"vscode:/vscode.git/clone" did not exist on "362de561edbaa8555112664485c469372faafb88"
Commit ec9f9d23 authored by Vinicius Jarina's avatar Vinicius Jarina Committed by GitHub
Browse files

Merge pull request #234 from SinusPi/master

Added support for debug.traceback running in pcalls.
parents d87a3e5a 20bda3d4
...@@ -259,6 +259,7 @@ function luanet.each(o) ...@@ -259,6 +259,7 @@ function luanet.each(o)
end end
end end
"; ";
public bool UseTraceback { get; set; } = false;
#region Globals auto-complete #region Globals auto-complete
/// <summary> /// <summary>
...@@ -376,6 +377,33 @@ end ...@@ -376,6 +377,33 @@ end
throw new LuaScriptException (err.ToString (), string.Empty); throw new LuaScriptException (err.ToString (), string.Empty);
} }
/// <summary>
/// Push a debug.traceback reference onto the stack, for a pcall function to use as error handler. (Remember to increment any top-of-stack markers!)
/// </summary>
private int PushDebugTraceback(LuaState luaState, int argcount)
{
LuaLib.LuaGetGlobal(luaState, "debug");
LuaLib.LuaGetField(luaState, -1, "traceback");
LuaLib.LuaRemove(luaState, -2);
int errindex = -argcount -2;
LuaLib.LuaInsert(luaState, errindex);
return errindex;
}
/// <summary>
/// <para>Return a debug.traceback() call result (a multi-line string, containing a full stack trace, including C calls.</para>
/// <para>Note: it won't return anything unless the interpreter is in the middle of execution - that is, it only makes sense to call it from a method called from Lua, or during a coroutine yield.</para>
/// </summary>
public string GetDebugTraceback()
{
int oldTop = LuaLib.LuaGetTop(luaState);
LuaLib.LuaGetGlobal(luaState, "debug"); // stack: debug
LuaLib.LuaGetField(luaState, -1, "traceback"); // stack: debug,traceback
LuaLib.LuaRemove(luaState, -2); // stack: traceback
LuaLib.LuaPCall(luaState, 0, -1, 0);
return translator.PopValues(luaState, oldTop)[0] as string;
}
/// <summary> /// <summary>
/// Convert C# exceptions into Lua errors /// Convert C# exceptions into Lua errors
/// </summary> /// </summary>
...@@ -469,9 +497,15 @@ end ...@@ -469,9 +497,15 @@ end
if (LuaLib.LuaLLoadBuffer(luaState, chunk, chunkName) == 0) if (LuaLib.LuaLLoadBuffer(luaState, chunk, chunkName) == 0)
{ {
int errfunction = 0;
if (UseTraceback) {
errfunction = PushDebugTraceback(luaState, 0);
oldTop++;
}
try try
{ {
if (LuaLib.LuaPCall(luaState, 0, -1, 0) == 0) if (LuaLib.LuaPCall(luaState, 0, -1, errfunction) == 0)
return translator.PopValues(luaState, oldTop); return translator.PopValues(luaState, oldTop);
else else
ThrowExceptionFromError(oldTop); ThrowExceptionFromError(oldTop);
...@@ -500,9 +534,15 @@ end ...@@ -500,9 +534,15 @@ end
if (LuaLib.LuaLLoadBuffer(luaState, chunk, chunkName) == 0) if (LuaLib.LuaLLoadBuffer(luaState, chunk, chunkName) == 0)
{ {
int errfunction = 0;
if (UseTraceback) {
errfunction = PushDebugTraceback(luaState, 0);
oldTop++;
}
try try
{ {
if (LuaLib.LuaPCall(luaState, 0, -1, 0) == 0) if (LuaLib.LuaPCall(luaState, 0, -1, errfunction) == 0)
return translator.PopValues(luaState, oldTop); return translator.PopValues(luaState, oldTop);
else else
ThrowExceptionFromError(oldTop); ThrowExceptionFromError(oldTop);
...@@ -529,8 +569,14 @@ end ...@@ -529,8 +569,14 @@ end
if (LuaLib.LuaLLoadFile (luaState, fileName) == 0) { if (LuaLib.LuaLLoadFile (luaState, fileName) == 0) {
executing = true; executing = true;
int errfunction = 0;
if (UseTraceback) {
errfunction = PushDebugTraceback(luaState, 0);
oldTop++;
}
try { try {
if (LuaLib.LuaPCall (luaState, 0, -1, 0) == 0) if (LuaLib.LuaPCall(luaState, 0, -1, errfunction) == 0)
return translator.PopValues (luaState, oldTop); return translator.PopValues (luaState, oldTop);
else else
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
...@@ -793,7 +839,13 @@ end ...@@ -793,7 +839,13 @@ end
executing = true; executing = true;
try { try {
int error = LuaLib.LuaPCall (luaState, nArgs, -1, 0); int errfunction = 0;
if (UseTraceback) {
errfunction = PushDebugTraceback(luaState, nArgs);
oldTop++;
}
int error = LuaLib.LuaPCall (luaState, nArgs, -1, errfunction);
if (error != 0) if (error != 0)
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
} finally { } finally {
......
...@@ -191,8 +191,9 @@ namespace NLua.Method ...@@ -191,8 +191,9 @@ namespace NLua.Method
} }
failedCall = false; failedCall = false;
} catch (TargetInvocationException e) { } catch (TargetInvocationException e) {
// Failure of method invocation // Failure of method invocation
if (_Translator.interpreter.UseTraceback) e.GetBaseException().Data["Traceback"] = _Translator.interpreter.GetDebugTraceback();
return SetPendingException (e.GetBaseException ()); return SetPendingException (e.GetBaseException ());
} catch (Exception e) { } catch (Exception e) {
if (_Members.Length == 1) // Is the method overloaded? if (_Members.Length == 1) // Is the method overloaded?
...@@ -288,7 +289,8 @@ namespace NLua.Method ...@@ -288,7 +289,8 @@ namespace NLua.Method
else else
_Translator.Push (luaState, _LastCalledMethod.cachedMethod.Invoke (targetObject, _LastCalledMethod.args)); _Translator.Push (luaState, _LastCalledMethod.cachedMethod.Invoke (targetObject, _LastCalledMethod.args));
} }
} catch (TargetInvocationException e) { } catch (TargetInvocationException e) {
if (_Translator.interpreter.UseTraceback) e.GetBaseException().Data["Traceback"] = _Translator.interpreter.GetDebugTraceback();
return SetPendingException (e.GetBaseException ()); return SetPendingException (e.GetBaseException ());
} catch (Exception e) { } catch (Exception e) {
return SetPendingException (e); return SetPendingException (e);
......
...@@ -242,6 +242,7 @@ namespace NLua ...@@ -242,6 +242,7 @@ namespace NLua
*/ */
internal void ThrowError (LuaState luaState, object e) internal void ThrowError (LuaState luaState, object e)
{ {
// We use this to remove anything pushed by luaL_where // We use this to remove anything pushed by luaL_where
int oldTop = LuaLib.LuaGetTop (luaState); int oldTop = LuaLib.LuaGetTop (luaState);
...@@ -260,12 +261,14 @@ namespace NLua ...@@ -260,12 +261,14 @@ namespace NLua
if (message != null) { if (message != null) {
// Wrap Lua error (just a string) and store the error location // Wrap Lua error (just a string) and store the error location
if (interpreter.UseTraceback) message += Environment.NewLine + interpreter.GetDebugTraceback();
e = new LuaScriptException (message, errLocation); e = new LuaScriptException (message, errLocation);
} else { } else {
var ex = e as Exception; var ex = e as Exception;
if (ex != null) { if (ex != null) {
// Wrap generic .NET exception as an InnerException and store the error location // Wrap generic .NET exception as an InnerException and store the error location
if (interpreter.UseTraceback) ex.Data["Traceback"] = interpreter.GetDebugTraceback();
e = new LuaScriptException (ex, errLocation); e = new LuaScriptException (ex, errLocation);
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment