From bf2b2eb01ca8680914d17dda713d9365e2ecc3eb Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 3 Sep 2024 16:26:03 -0400
Subject: Add Lua traceback to errors from calling lluau::expr().

That includes scripts run by LLLUAmanager::runScriptFile(), runScriptLine()
et al.
---
 indra/llcommon/lua_function.cpp | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/llcommon/lua_function.cpp b/indra/llcommon/lua_function.cpp
index 67ca29c689..c3d336bfcb 100644
--- a/indra/llcommon/lua_function.cpp
+++ b/indra/llcommon/lua_function.cpp
@@ -65,10 +65,26 @@ int dostring(lua_State* L, const std::string& desc, const std::string& text)
     if (r != LUA_OK)
         return r;
 
+    // Push debug.traceback() onto the stack as lua_pcall()'s error
+    // handler function. On error, lua_pcall() calls the specified error
+    // handler function with the original error message; the message
+    // returned by the error handler is then returned by lua_pcall().
+    // Luau's debug.traceback() is called with a message to prepend to the
+    // returned traceback string. Almost as if they'd been designed to
+    // work together...
+    lua_getglobal(L, "debug");
+    lua_getfield(L, -1, "traceback");
+    // ditch "debug"
+    lua_remove(L, -2);
+    // stack: compiled chunk, debug.traceback()
+    lua_insert(L, -2);
+    // stack: debug.traceback(), compiled chunk
+    LuaRemover cleanup(L, -2);
+
     // It's important to pass LUA_MULTRET as the expected number of return
     // values: if we pass any fixed number, we discard any returned values
     // beyond that number.
-    return lua_pcall(L, 0, LUA_MULTRET, 0);
+    return lua_pcall(L, 0, LUA_MULTRET, -2);
 }
 
 int loadstring(lua_State *L, const std::string &desc, const std::string &text)
-- 
cgit v1.2.3