diff --git a/src/cpp/function.cpp b/src/cpp/function.cpp index ee045d5..9a0af46 100644 --- a/src/cpp/function.cpp +++ b/src/cpp/function.cpp @@ -2,28 +2,6 @@ namespace effil { -namespace { - -bool allowTableUpvalues(const sol::optional& newValue = sol::nullopt) { - static std::atomic_bool value(true); - - if (newValue) - return value.exchange(newValue.value()); - return value; -} - -} // anonymous - -sol::object luaAllowTableUpvalues(sol::this_state state, const sol::stack_object& value) { - if (value.valid()) { - REQUIRE(value.get_type() == sol::type::boolean) << "bad argument #1 to 'effil.allow_table_upvalues' (boolean expected, got " << luaTypename(value) << ")"; - return sol::make_object(state, allowTableUpvalues(value.template as())); - } - else { - return sol::make_object(state, allowTableUpvalues()); - } -} - Function::Function(const sol::function& luaObject) { assert(luaObject.valid()); assert(luaObject.get_type() == sol::type::function); @@ -38,30 +16,29 @@ Function::Function(const sol::function& luaObject) { ctx_->function = dumpFunction(luaObject); ctx_->upvalues.resize(dbgInfo.nups); #if LUA_VERSION_NUM > 501 - ctx_->envUpvaluePos = 0; // means no _ENV upvalue + ctx_->envUpvaluePos = 0; // means no _G upvalue + + lua_pushglobaltable(state); + const auto gTable = sol::stack::pop(state); #endif // LUA_VERSION_NUM > 501 + for (unsigned char i = 1; i <= dbgInfo.nups; ++i) { const char* valueName = lua_getupvalue(state, -1, i); // push value on stack (void)valueName; // get rid of 'unused' warning for Lua5.1 assert(valueName != nullptr); #if LUA_VERSION_NUM > 501 - if (strcmp(valueName, "_ENV") == 0) { // do not serialize _ENV + if (gTable == sol::stack::get(state)) { // do not serialize _G sol::stack::pop(state); ctx_->envUpvaluePos = i; continue; } #endif // LUA_VERSION_NUM > 501 - const auto& upvalue = sol::stack::pop(state); // pop from stack - if (!allowTableUpvalues() && upvalue.get_type() == sol::type::table) { - sol::stack::pop(state); - throw effil::Exception() << "bad function upvalue #" << (int)i << " (table is disabled by effil.allow_table_upvalues)"; - } - StoredObject storedObject; try { + const auto& upvalue = sol::stack::pop(state); storedObject = createStoredObject(upvalue); assert(storedObject.get() != nullptr); } @@ -87,8 +64,8 @@ sol::object Function::loadFunction(lua_State* state) { for(size_t i = 0; i < ctx_->upvalues.size(); ++i) { #if LUA_VERSION_NUM > 501 if (ctx_->envUpvaluePos == i + 1) { - lua_rawgeti(state, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); // push _ENV to stack - lua_setupvalue(state, -2, i + 1); // pop _ENV and set as upvalue + lua_pushglobaltable(state); // push _G to stack + lua_setupvalue(state, -2, i + 1); // pop _G and set as upvalue continue; } #endif // LUA_VERSION_NUM > 501 diff --git a/src/cpp/function.h b/src/cpp/function.h index c3774fd..e06d8e9 100644 --- a/src/cpp/function.h +++ b/src/cpp/function.h @@ -7,8 +7,6 @@ namespace effil { -sol::object luaAllowTableUpvalues(sol::this_state state, const sol::stack_object&); - class FunctionData : public GCData { public: std::string function; diff --git a/src/cpp/lua-module.cpp b/src/cpp/lua-module.cpp index 89c5d6a..3881044 100644 --- a/src/cpp/lua-module.cpp +++ b/src/cpp/lua-module.cpp @@ -107,7 +107,6 @@ int luaopen_effil(lua_State* L) { "pairs", SharedTable::globalLuaPairs, "ipairs", SharedTable::globalLuaIPairs, "size", luaSize, - "allow_table_upvalues", luaAllowTableUpvalues, "hardware_threads", std::thread::hardware_concurrency, sol::meta_function::index, luaIndex ); diff --git a/tests/lua/type_mismatch.lua b/tests/lua/type_mismatch.lua index 3d5d4c1..00eecfd 100644 --- a/tests/lua/type_mismatch.lua +++ b/tests/lua/type_mismatch.lua @@ -122,11 +122,6 @@ local function generate_tests() -- effil.gc.step test.type_mismatch.input_types_mismatch_p(1, "number", "gc.step", type_instance) end - - if typename ~= "boolean" then - -- effil.allow_table_upvalue - test.type_mismatch.input_types_mismatch_p(1, "boolean", "allow_table_upvalues", type_instance) - end end -- Below presented tests which support everything except coroutines @@ -155,6 +150,5 @@ end generate_tests() test.type_mismatch.gc_checks_after_tests = function() - effil.allow_table_upvalues(true) default_tear_down() end \ No newline at end of file diff --git a/tests/lua/upvalues.lua b/tests/lua/upvalues.lua index 704c119..94f0376 100644 --- a/tests/lua/upvalues.lua +++ b/tests/lua/upvalues.lua @@ -60,7 +60,7 @@ test.upvalues.check_table = function() test.equal(ret, "effil.table: value") end -test.upvalues.check_env = function() +test.upvalues.check_global_env = function() local obj1 = 13 -- local obj2 = { key = "origin" } -- global local obj3 = 79 -- local @@ -81,39 +81,19 @@ test.upvalues.check_env = function() test.equal(ret, "13, local, 79") end -local function check_works(should_work) - local obj = { key = "value"} - local function worker() - return obj.key +if LUA_VERSION > 51 then + +test.upvalues.check_custom_env = function() + local function create_foo() + local _ENV = { key = 'value' } + return function() + return key + end end - local ret, err = pcall(effil.thread(worker)) - if ret then - err:wait() - end - test.equal(ret, should_work) - if not should_work then - test.equal(err, "effil.thread: bad function upvalue #1 (table is disabled by effil.allow_table_upvalues)") - end + local foo = create_foo() + local ret = effil.thread(foo)():get() + test.equal(ret, 'value') end -test.upvalues_table.tear_down = function() - effil.allow_table_upvalues(true) - default_tear_down() -end - -test.upvalues_table.disabling_table_upvalues = function() - test.equal(effil.allow_table_upvalues(), true) - -- works by default - check_works(true) - - -- disable - test.equal(effil.allow_table_upvalues(false), true) - check_works(false) - test.equal(effil.allow_table_upvalues(), false) - - -- enable back - test.equal(effil.allow_table_upvalues(true), false) - check_works(true) - test.equal(effil.allow_table_upvalues(), true) -end +end -- LUA_VERSION > 51