Browse Source

Fix: support exceptions wrapping LuaValue

Akeit0 1 year ago
parent
commit
55e90cbd05
3 changed files with 31 additions and 15 deletions
  1. 5 0
      src/Lua/Exceptions.cs
  2. 8 7
      src/Lua/LuaCoroutine.cs
  3. 18 8
      src/Lua/Standard/BasicLibrary.cs

+ 5 - 0
src/Lua/Exceptions.cs

@@ -102,4 +102,9 @@ public class LuaModuleNotFoundException(string moduleName) : LuaException($"modu
 public class LuaRuntimeCSharpException(Traceback traceback, Exception exception) : LuaRuntimeException(traceback, exception.Message)
 {
     public Exception Exception { get; } = exception;
+}
+
+public class LuaRuntimeLuaValueException(Traceback traceback, LuaValue value) : LuaRuntimeException(traceback, value.ToString())
+{
+    public LuaValue Value { get; } = value;
 }

+ 8 - 7
src/Lua/LuaCoroutine.cs

@@ -73,6 +73,7 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                                 : context.Arguments[1..].ToArray()
                         });
                     }
+
                     break;
                 case LuaThreadStatus.Normal:
                 case LuaThreadStatus.Running:
@@ -149,9 +150,7 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                         State = context.State,
                         Thread = this,
                         ArgumentCount = context.ArgumentCount - 1,
-                        FrameBase = frameBase,
-                        ChunkName = Function.Name,
-                        RootChunkName = context.RootChunkName,
+                        FrameBase = frameBase
                     }, this.buffer, cancellationToken).Preserve();
 
                     Volatile.Write(ref isFirstCall, false);
@@ -192,7 +191,9 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
 
                     Volatile.Write(ref status, (byte)LuaThreadStatus.Dead);
                     buffer.Span[0] = false;
-                    buffer.Span[1] = ex.Message;
+                    buffer.Span[1] = ex is LuaRuntimeLuaValueException luaValueException
+                        ? luaValueException.Value
+                        : ex.Message;
                     return 2;
                 }
                 else
@@ -219,12 +220,12 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
         {
             throw new LuaRuntimeException(context.State.GetTraceback(), "cannot call yield on a coroutine that is not currently running");
         }
-        
+
         if (context.Thread.GetCallStackFrames()[^2].Function is not Closure)
         {
             throw new LuaRuntimeException(context.State.GetTraceback(), "attempt to yield across a C#-call boundary");
         }
-        
+
         resume.SetResult(new()
         {
             Results = context.Arguments.ToArray(),
@@ -242,7 +243,7 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
             }, this);
         }
 
-    RETRY:
+        RETRY:
         try
         {
             var result = await new ValueTask<YieldContext>(this, yield.Version);

+ 18 - 8
src/Lua/Standard/BasicLibrary.cs

@@ -102,11 +102,11 @@ public sealed class BasicLibrary
 
     public ValueTask<int> Error(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
-        var obj = context.ArgumentCount == 0 || context.Arguments[0].Type is LuaValueType.Nil
+        var value = context.ArgumentCount == 0 || context.Arguments[0].Type is LuaValueType.Nil
             ? "(error object is a nil value)"
-            : context.Arguments[0].ToString();
+            : context.Arguments[0];
 
-        throw new LuaRuntimeException(context.State.GetTraceback(), obj!);
+        throw new LuaRuntimeLuaValueException(context.State.GetTraceback(), value);
     }
 
     public ValueTask<int> GetMetatable(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
@@ -285,7 +285,15 @@ public sealed class BasicLibrary
         catch (Exception ex)
         {
             buffer.Span[0] = false;
-            buffer.Span[1] = ex.Message;
+            if(ex is LuaRuntimeLuaValueException luaEx)
+            {
+                buffer.Span[1] = luaEx.Value;
+            }
+            else
+            {
+                buffer.Span[1] = ex.Message;
+            }
+
             return 2;
         }
     }
@@ -605,19 +613,21 @@ public sealed class BasicLibrary
         catch (Exception ex)
         {
             methodBuffer.AsSpan().Clear();
-
-            context.State.Push(ex.Message);
+            var error = (ex is LuaRuntimeLuaValueException luaEx) ? luaEx.Value : ex.Message;
+            
+            context.State.Push(error);
 
             // invoke error handler
             await arg1.InvokeAsync(context with
             {
                 State = context.State,
                 ArgumentCount = 1,
-                FrameBase = context.Thread.Stack.Count - context.ArgumentCount,
+                FrameBase = context.Thread.Stack.Count - 1,
             }, methodBuffer.AsMemory(), cancellationToken);
 
             buffer.Span[0] = false;
-            buffer.Span[1] = ex.Message;
+            buffer.Span[1] = methodBuffer[0];
+            
 
             return 2;
         }