cleanup global environment (_ENV* variables)

This commit is contained in:
MihailRis 2026-04-27 02:16:24 +03:00
parent 629f672d38
commit ad1d7477ad
4 changed files with 54 additions and 37 deletions

View file

@ -1010,8 +1010,9 @@ static int l_gui_get_env(lua::State* L) {
"document '" + std::string(name) + "' not found" "document '" + std::string(name) + "' not found"
); );
} }
lua::getglobal(L, lua::env_name(*doc->getEnvironment())); return lua::getregistry(
return 1; L, lua::ENVS_TABLE, lua::env_name(*doc->getEnvironment())
);
} }
static int l_gui_str(lua::State* L) { static int l_gui_str(lua::State* L) {

View file

@ -122,15 +122,17 @@ void lua::init_state(State* L, StateType stateType) {
remove_lib_funcs(L, "os", removed_os); remove_lib_funcs(L, "os", removed_os);
create_libs(L, stateType); create_libs(L, stateType);
pushglobals(L);
setglobal(L, env_name(0));
createtable(L, 0, 0); createtable(L, 0, 0);
setregistry(L, LAMBDAS_TABLE); setregistry(L, LAMBDAS_TABLE);
createtable(L, 0, 0); createtable(L, 0, 0);
setregistry(L, CHUNKS_TABLE); setregistry(L, CHUNKS_TABLE);
createtable(L, 0, 0);
pushglobals(L);
setfield(L, env_name(0));
setregistry(L, ENVS_TABLE);
initialize_libs_extends(L); initialize_libs_extends(L);
newusertype<LuaHeightmap>(L); newusertype<LuaHeightmap>(L);

View file

@ -8,7 +8,7 @@
using namespace lua; using namespace lua;
static int nextEnvironment = 1; static int next_environment = 1;
std::unordered_map<std::type_index, std::string> lua::usertypeNames; std::unordered_map<std::type_index, std::string> lua::usertypeNames;
@ -20,7 +20,7 @@ int lua::userdata_destructor(lua::State* L) {
} }
std::string lua::env_name(int env) { 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) { 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 lua::create_environment(State* L, int parent) {
int id = nextEnvironment++; int id = next_environment++;
// local env = {} // local env = {}
createtable(L, 0, 1); createtable(L, 0, 1);
@ -335,24 +343,22 @@ int lua::create_environment(State* L, int parent) {
setfield(L, "__index"); setfield(L, "__index");
setmetatable(L); setmetatable(L);
// envname = env store_env(L, id);
setglobal(L, env_name(id));
return id; return id;
} }
int lua::restore_pack_environment(lua::State* L, const std::string& packid) { 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; return -1;
} }
int id = nextEnvironment++; int id = next_environment++;
if (lua::getfield(L, packid)) { if (getfield(L, packid)) {
// envname = env store_env(L, id);
setglobal(L, env_name(id)); pop(L);
lua::pop(L);
return id; return id;
} }
lua::pop(L); pop(L);
return -1; return -1;
} }
@ -361,5 +367,5 @@ void lua::remove_environment(State* L, int id) {
return; return;
} }
pushnil(L); pushnil(L);
setglobal(L, env_name(id)); store_env(L, id);
} }

View file

@ -15,6 +15,7 @@ namespace lua {
inline std::string LAMBDAS_TABLE = "$L"; // lambdas storage inline std::string LAMBDAS_TABLE = "$L"; // lambdas storage
inline std::string CHUNKS_TABLE = "$C"; // precompiled lua chunks inline std::string CHUNKS_TABLE = "$C"; // precompiled lua chunks
inline std::string PACK_ENVS_TABLE = "$P"; inline std::string PACK_ENVS_TABLE = "$P";
inline std::string ENVS_TABLE = "$E";
extern std::unordered_map<std::type_index, std::string> usertypeNames; extern std::unordered_map<std::type_index, std::string> usertypeNames;
int userdata_destructor(lua::State* L); 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) { inline bool hasglobal(lua::State* L, const std::string& name) {
lua_getglobal(L, name.c_str()); lua_getglobal(L, name.c_str());
if (isnil(L, -1)) { if (isnil(L, -1)) {
@ -550,7 +561,7 @@ namespace lua {
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) { if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
throw luaerror(tostring(L, -1)); 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); lua_setfenv(L, -2);
} }
} }
@ -658,10 +669,7 @@ namespace lua {
scripting::common_func create_lambda_nothrow(lua::State*); scripting::common_func create_lambda_nothrow(lua::State*);
inline int pushenv(lua::State* L, int env) { inline int pushenv(lua::State* L, int env) {
if (getglobal(L, env_name(env))) { return getregistry(L, ENVS_TABLE, env_name(env));
return 1;
}
return 0;
} }
int create_environment(lua::State*, int parent); int create_environment(lua::State*, int parent);
int restore_pack_environment(lua::State*, const std::string& packid); int restore_pack_environment(lua::State*, const std::string& packid);
@ -790,14 +798,14 @@ namespace lua {
inline void read_bytes_from_table( inline void read_bytes_from_table(
lua::State* L, int tableIndex, std::vector<ubyte>& bytes lua::State* L, int tableIndex, std::vector<ubyte>& bytes
) { ) {
if (!lua::istable(L, tableIndex)) { if (!istable(L, tableIndex)) {
throw std::runtime_error("table expected"); throw std::runtime_error("table expected");
} else { } else {
size_t size = lua::objlen(L, tableIndex); size_t size = objlen(L, tableIndex);
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
lua::rawgeti(L, i + 1, tableIndex); rawgeti(L, i + 1, tableIndex);
const int byte = lua::tointeger(L, -1); const int byte = tointeger(L, -1);
lua::pop(L); pop(L);
if (byte < 0 || byte > 255) { if (byte < 0 || byte > 255) {
throw std::runtime_error( throw std::runtime_error(
"invalid byte '" + std::to_string(byte) + "'" "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) { inline int create_bytearray(lua::State* L, const void* bytes, size_t size) {
lua::requireglobal(L, "Bytearray_construct"); requireglobal(L, "Bytearray_construct");
lua::pushlstring( pushlstring(
L, std::string_view(reinterpret_cast<const char*>(bytes), size) L, std::string_view(reinterpret_cast<const char*>(bytes), size)
); );
return lua::call(L, 1, 1); return call(L, 1, 1);
} }
inline int create_bytearray(lua::State* L, const std::vector<ubyte>& bytes) { inline int create_bytearray(lua::State* L, const std::vector<ubyte>& bytes) {
@ -821,12 +829,12 @@ namespace lua {
} }
inline std::string_view bytearray_as_string(lua::State* L, int idx) { inline std::string_view bytearray_as_string(lua::State* L, int idx) {
lua::pushvalue(L, idx); pushvalue(L, idx);
lua::requireglobal(L, "Bytearray_as_string"); requireglobal(L, "Bytearray_as_string");
lua::pushvalue(L, -2); pushvalue(L, -2);
lua::call(L, 1, 1); call(L, 1, 1);
auto view = lua::tolstring(L, -1); auto view = tolstring(L, -1);
lua::pop(L, 2); pop(L, 2);
return view; return view;
} }
} }