diff --git a/core/src/datatypes/signal.cpp b/core/src/datatypes/signal.cpp index e369ea3..1c3d4db 100644 --- a/core/src/datatypes/signal.cpp +++ b/core/src/datatypes/signal.cpp @@ -38,25 +38,6 @@ LuaSignalConnection::~LuaSignalConnection() { luaL_unref(state, LUA_REGISTRYINDEX, thread); } -#if 0 -static void stackdump(lua_State* L) { - printf("%d\n", lua_gettop(L)); - fflush(stdout); - lua_getfield(L, LUA_GLOBALSINDEX, "tostring"); - for (int i = lua_gettop(L)-1; i >= 1; i--) { - lua_pushvalue(L, -1); - lua_pushvalue(L, i); - lua_call(L, 1, 1); - const char* str = lua_tostring(L, -1); - lua_pop(L, 1); - printf("%s: %s\n", lua_typename(L, lua_type(L, i)), str); - } - lua_pop(L, 1); - printf("\n\n"); - fflush(stdout); -} -#endif - void LuaSignalConnection::Call(std::vector args) { lua_State* thread = lua_newthread(state); diff --git a/core/src/objects/script.cpp b/core/src/objects/script.cpp index 213e21c..4c72dab 100644 --- a/core/src/objects/script.cpp +++ b/core/src/objects/script.cpp @@ -31,13 +31,22 @@ void Script::Run() { this->thread = lua_newthread(L); lua_State* Lt = thread; + lua_pushthread(Lt); // Push thread for later* + // Initialize script globals - lua_getglobal(Lt, "_G"); + scriptContext->NewEnvironment(Lt); // Pushes envtable, metatable + + // Set script in metatable source + InstanceRef(shared_from_this()).PushLuaValue(Lt); + lua_setfield(Lt, -2, "source"); + + lua_pop(Lt, 1); // Pop metatable InstanceRef(shared_from_this()).PushLuaValue(Lt); lua_setfield(Lt, -2, "script"); - lua_pop(Lt, 1); // _G + lua_setfenv(Lt, -2); // *Set env of current thread + lua_pop(Lt, 1); // Pop thread // Push wrapper as thread function lua_getfield(Lt, LUA_REGISTRYINDEX, "LuaPCallWrapper"); diff --git a/core/src/objects/service/script/scriptcontext.cpp b/core/src/objects/service/script/scriptcontext.cpp index 88bdbaf..9515dff 100644 --- a/core/src/objects/service/script/scriptcontext.cpp +++ b/core/src/objects/service/script/scriptcontext.cpp @@ -17,13 +17,14 @@ int g_wait(lua_State*); int g_delay(lua_State*); static int g_print(lua_State*); static int g_require(lua_State*); -static const struct luaL_Reg luaglobals [] = { +static const luaL_Reg luaglobals [] = { {"print", g_print}, {"require", g_require}, {NULL, NULL} /* end of array */ }; std::string unsafe_globals[] = { + // Todo implement our own "safe" setfenv/getfenv "loadfile", "loadstring", "load", "dofile", "getfenv", "setfenv" }; @@ -161,6 +162,27 @@ void ScriptContext::RunSleepingThreads() { schedTime = tu_clock_micros() - startTime; } +void ScriptContext::NewEnvironment(lua_State* L) { + lua_newtable(L); // Env table + lua_newtable(L); // Metatable + + // Push __index + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setfield(L, -2, "__index"); + + // Push __metatable + lua_pushstring(L, "metatable is locked"); + lua_setfield(L, -2, "__metatable"); + + // Copy metatable and set the env table's metatable + lua_pushvalue(L, -1); + lua_setmetatable(L, -3); + + // Remainder on stack: + // 1. Env table + // 2. Metatable +} + // https://www.lua.org/source/5.1/lbaselib.c.html static int g_print(lua_State* L) { std::string buf; diff --git a/core/src/objects/service/script/scriptcontext.h b/core/src/objects/service/script/scriptcontext.h index 3872dbc..3c2df2f 100644 --- a/core/src/objects/service/script/scriptcontext.h +++ b/core/src/objects/service/script/scriptcontext.h @@ -32,5 +32,8 @@ public: void PushThreadSleep(lua_State* thread, float delay); void RunSleepingThreads(); + // Generates an environment with a metatable and pushes it both the env table and metatable in order onto the stack + void NewEnvironment(lua_State* state); + static inline std::shared_ptr Create() { return std::make_shared(); }; }; \ No newline at end of file