From ad1d7477adeb618f5e08b482b2b1f33c1b9d41ba Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 27 Apr 2026 02:16:24 +0300 Subject: [PATCH] cleanup global environment (_ENV* variables) --- src/logic/scripting/lua/libs/libgui.cpp | 5 +-- src/logic/scripting/lua/lua_engine.cpp | 8 +++-- src/logic/scripting/lua/lua_util.cpp | 32 ++++++++++------- src/logic/scripting/lua/lua_util.hpp | 46 +++++++++++++++---------- 4 files changed, 54 insertions(+), 37 deletions(-) diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index 382113171..0e4645adc 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -1010,8 +1010,9 @@ static int l_gui_get_env(lua::State* L) { "document '" + std::string(name) + "' not found" ); } - lua::getglobal(L, lua::env_name(*doc->getEnvironment())); - return 1; + return lua::getregistry( + L, lua::ENVS_TABLE, lua::env_name(*doc->getEnvironment()) + ); } static int l_gui_str(lua::State* L) { diff --git a/src/logic/scripting/lua/lua_engine.cpp b/src/logic/scripting/lua/lua_engine.cpp index 1536cb41f..0143f6a9e 100644 --- a/src/logic/scripting/lua/lua_engine.cpp +++ b/src/logic/scripting/lua/lua_engine.cpp @@ -122,15 +122,17 @@ void lua::init_state(State* L, StateType stateType) { remove_lib_funcs(L, "os", removed_os); create_libs(L, stateType); - pushglobals(L); - setglobal(L, env_name(0)); - createtable(L, 0, 0); setregistry(L, LAMBDAS_TABLE); createtable(L, 0, 0); setregistry(L, CHUNKS_TABLE); + createtable(L, 0, 0); + pushglobals(L); + setfield(L, env_name(0)); + setregistry(L, ENVS_TABLE); + initialize_libs_extends(L); newusertype(L); diff --git a/src/logic/scripting/lua/lua_util.cpp b/src/logic/scripting/lua/lua_util.cpp index 51bfb4d65..ded9cc79b 100644 --- a/src/logic/scripting/lua/lua_util.cpp +++ b/src/logic/scripting/lua/lua_util.cpp @@ -8,7 +8,7 @@ using namespace lua; -static int nextEnvironment = 1; +static int next_environment = 1; std::unordered_map lua::usertypeNames; @@ -20,7 +20,7 @@ int lua::userdata_destructor(lua::State* L) { } std::string lua::env_name(int env) { - return "_ENV" + util::mangleid(env); + return std::to_string(env); } int lua::pushvalue(State* L, const dv::value& value) { @@ -317,8 +317,16 @@ scripting::common_func lua::create_lambda_nothrow(State* L) { }; } +static void store_env(lua::State* L, int id) { + requireregistry(L, ENVS_TABLE); + pushvalue(L, -2); + lua_remove(L, -3); + setfield(L, env_name(id)); + pop(L); +} + int lua::create_environment(State* L, int parent) { - int id = nextEnvironment++; + int id = next_environment++; // local env = {} createtable(L, 0, 1); @@ -335,24 +343,22 @@ int lua::create_environment(State* L, int parent) { setfield(L, "__index"); setmetatable(L); - // envname = env - setglobal(L, env_name(id)); + store_env(L, id); return id; } int lua::restore_pack_environment(lua::State* L, const std::string& packid) { - if(!lua::requireregistry(L, lua::PACK_ENVS_TABLE)) { + if(!requireregistry(L, PACK_ENVS_TABLE)) { return -1; } - int id = nextEnvironment++; + int id = next_environment++; - if (lua::getfield(L, packid)) { - // envname = env - setglobal(L, env_name(id)); - lua::pop(L); + if (getfield(L, packid)) { + store_env(L, id); + pop(L); return id; } - lua::pop(L); + pop(L); return -1; } @@ -361,5 +367,5 @@ void lua::remove_environment(State* L, int id) { return; } pushnil(L); - setglobal(L, env_name(id)); + store_env(L, id); } diff --git a/src/logic/scripting/lua/lua_util.hpp b/src/logic/scripting/lua/lua_util.hpp index d6a45fecd..9ae1e48f6 100644 --- a/src/logic/scripting/lua/lua_util.hpp +++ b/src/logic/scripting/lua/lua_util.hpp @@ -15,6 +15,7 @@ namespace lua { inline std::string LAMBDAS_TABLE = "$L"; // lambdas storage inline std::string CHUNKS_TABLE = "$C"; // precompiled lua chunks inline std::string PACK_ENVS_TABLE = "$P"; + inline std::string ENVS_TABLE = "$E"; extern std::unordered_map usertypeNames; int userdata_destructor(lua::State* L); @@ -58,6 +59,16 @@ namespace lua { } } + inline bool getregistry(lua::State* L, const std::string& name, const std::string& key) { + requireregistry(L, name); + if (getfield(L, key)) { + lua_remove(L, -2); + return true; + } + pop(L); + return false; + } + inline bool hasglobal(lua::State* L, const std::string& name) { lua_getglobal(L, name.c_str()); if (isnil(L, -1)) { @@ -550,7 +561,7 @@ namespace lua { if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) { throw luaerror(tostring(L, -1)); } - if (env && getglobal(L, env_name(env))) { + if (env && getregistry(L, ENVS_TABLE, env_name(env))) { lua_setfenv(L, -2); } } @@ -658,10 +669,7 @@ namespace lua { scripting::common_func create_lambda_nothrow(lua::State*); inline int pushenv(lua::State* L, int env) { - if (getglobal(L, env_name(env))) { - return 1; - } - return 0; + return getregistry(L, ENVS_TABLE, env_name(env)); } int create_environment(lua::State*, int parent); int restore_pack_environment(lua::State*, const std::string& packid); @@ -790,14 +798,14 @@ namespace lua { inline void read_bytes_from_table( lua::State* L, int tableIndex, std::vector& bytes ) { - if (!lua::istable(L, tableIndex)) { + if (!istable(L, tableIndex)) { throw std::runtime_error("table expected"); } else { - size_t size = lua::objlen(L, tableIndex); + size_t size = objlen(L, tableIndex); for (size_t i = 0; i < size; i++) { - lua::rawgeti(L, i + 1, tableIndex); - const int byte = lua::tointeger(L, -1); - lua::pop(L); + rawgeti(L, i + 1, tableIndex); + const int byte = tointeger(L, -1); + pop(L); if (byte < 0 || byte > 255) { throw std::runtime_error( "invalid byte '" + std::to_string(byte) + "'" @@ -809,11 +817,11 @@ namespace lua { } inline int create_bytearray(lua::State* L, const void* bytes, size_t size) { - lua::requireglobal(L, "Bytearray_construct"); - lua::pushlstring( + requireglobal(L, "Bytearray_construct"); + pushlstring( L, std::string_view(reinterpret_cast(bytes), size) ); - return lua::call(L, 1, 1); + return call(L, 1, 1); } inline int create_bytearray(lua::State* L, const std::vector& bytes) { @@ -821,12 +829,12 @@ namespace lua { } inline std::string_view bytearray_as_string(lua::State* L, int idx) { - lua::pushvalue(L, idx); - lua::requireglobal(L, "Bytearray_as_string"); - lua::pushvalue(L, -2); - lua::call(L, 1, 1); - auto view = lua::tolstring(L, -1); - lua::pop(L, 2); + pushvalue(L, idx); + requireglobal(L, "Bytearray_as_string"); + pushvalue(L, -2); + call(L, 1, 1); + auto view = tolstring(L, -1); + pop(L, 2); return view; } }