summaryrefslogtreecommitdiff
path: root/indra/llcommon/lua_function.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/lua_function.h')
-rw-r--r--indra/llcommon/lua_function.h56
1 files changed, 48 insertions, 8 deletions
diff --git a/indra/llcommon/lua_function.h b/indra/llcommon/lua_function.h
index 7b59af30f5..6965e206ab 100644
--- a/indra/llcommon/lua_function.h
+++ b/indra/llcommon/lua_function.h
@@ -60,11 +60,11 @@ namespace lluau
int loadstring(lua_State* L, const std::string& desc, const std::string& text);
fsyspath source_path(lua_State* L);
-
- void set_interrupts_counter(lua_State *L, S32 counter);
- void check_interrupts_counter(lua_State* L);
} // namespace lluau
+// must be a macro because LL_PRETTY_FUNCTION is context-sensitive
+#define lluau_checkstack(L, n) luaL_checkstack((L), (n), LL_PRETTY_FUNCTION)
+
std::string lua_tostdstring(lua_State* L, int index);
void lua_pushstdstring(lua_State* L, const std::string& str);
LLSD lua_tollsd(lua_State* L, int index);
@@ -107,10 +107,18 @@ public:
// Find or create LuaListener for passed lua_State.
static LuaListener& obtainListener(lua_State* L);
+ // Given lua_State* L, return the LuaState object managing (the main Lua
+ // thread for) L.
+ static LuaState& getParent(lua_State* L);
+
+ void set_interrupts_counter(S32 counter);
+ void check_interrupts_counter();
+
private:
script_finished_fn mCallback;
lua_State* mState;
std::string mError;
+ S32 mInterrupts{ 0 };
};
/*****************************************************************************
@@ -170,6 +178,32 @@ private:
};
/*****************************************************************************
+* LuaStackDelta
+*****************************************************************************/
+/**
+ * Instantiate LuaStackDelta in a block to compare the Lua data stack depth on
+ * entry (LuaStackDelta construction) and exit. Optionally, pass the expected
+ * depth increment. (But be aware that LuaStackDelta cannot observe the effect
+ * of a LuaPopper or LuaRemover declared previously in the same block.)
+ */
+class LuaStackDelta
+{
+public:
+ LuaStackDelta(lua_State* L, const std::string& where, int delta=0);
+ LuaStackDelta(const LuaStackDelta&) = delete;
+ LuaStackDelta& operator=(const LuaStackDelta&) = delete;
+
+ ~LuaStackDelta();
+
+private:
+ lua_State* L;
+ std::string mWhere;
+ int mDepth, mDelta;
+};
+
+#define lua_checkdelta(L, ...) LuaStackDelta delta(L, LL_PRETTY_FUNCTION, ##__VA_ARGS__)
+
+/*****************************************************************************
* lua_push() wrappers for generic code
*****************************************************************************/
inline
@@ -294,7 +328,8 @@ auto lua_to<void*>(lua_State* L, int index)
template <typename T>
auto lua_getfieldv(lua_State* L, int index, const char* k)
{
- luaL_checkstack(L, 1, nullptr);
+ lua_checkdelta(L);
+ lluau_checkstack(L, 1);
lua_getfield(L, index, k);
LuaPopper pop(L, 1);
return lua_to<T>(L, -1);
@@ -304,7 +339,8 @@ auto lua_getfieldv(lua_State* L, int index, const char* k)
template <typename T>
auto lua_setfieldv(lua_State* L, int index, const char* k, const T& value)
{
- luaL_checkstack(L, 1, nullptr);
+ lua_checkdelta(L);
+ lluau_checkstack(L, 1);
lua_push(L, value);
lua_setfield(L, index, k);
}
@@ -313,7 +349,8 @@ auto lua_setfieldv(lua_State* L, int index, const char* k, const T& value)
template <typename T>
auto lua_rawgetfield(lua_State* L, int index, const std::string_view& k)
{
- luaL_checkstack(L, 1, nullptr);
+ lua_checkdelta(L);
+ lluau_checkstack(L, 1);
lua_pushlstring(L, k.data(), k.length());
lua_rawget(L, index);
LuaPopper pop(L, 1);
@@ -324,7 +361,8 @@ auto lua_rawgetfield(lua_State* L, int index, const std::string_view& k)
template <typename T>
void lua_rawsetfield(lua_State* L, int index, const std::string_view& k, const T& value)
{
- luaL_checkstack(L, 2, nullptr);
+ lua_checkdelta(L);
+ lluau_checkstack(L, 2);
lua_pushlstring(L, k.data(), k.length());
lua_push(L, value);
lua_rawset(L, index);
@@ -430,7 +468,8 @@ DistinctInt TypeTag<T>::value;
template <class T, typename... ARGS>
void lua_emplace(lua_State* L, ARGS&&... args)
{
- luaL_checkstack(L, 1, nullptr);
+ lua_checkdelta(L, 1);
+ lluau_checkstack(L, 1);
int tag{ TypeTag<T>::value };
if (! lua_getuserdatadtor(L, tag))
{
@@ -464,6 +503,7 @@ void lua_emplace(lua_State* L, ARGS&&... args)
template <class T>
T* lua_toclass(lua_State* L, int index)
{
+ lua_checkdelta(L);
// get void* pointer to userdata (if that's what it is)
void* ptr{ lua_touserdatatagged(L, index, TypeTag<T>::value) };
// Derive the T* from ptr. If in future lua_emplace() must manually