Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions extension/script/backend/worker/eval/readonly.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ do
i = i + 1
end
end
if not env and getfenv then
env = getfenv(f)
end
do
local i = 1
while true do
Expand Down Expand Up @@ -76,6 +79,9 @@ end
local compiled = env
and assert(_load(full_source, '=(EVAL)', "t", env))
or assert(_load(full_source, '=(EVAL)'))
if env and setfenv then
setfenv(compiled, env)
end
local func = compiled()
do
local i = 1
Expand Down
6 changes: 6 additions & 0 deletions extension/script/backend/worker/eval/readwrite.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ do
i = i + 1
end
end
if not env and getfenv then
env = getfenv(f)
end
do
local i = 1
while true do
Expand Down Expand Up @@ -90,6 +93,9 @@ end
local compiled = env
and assert(_load(full_source, '=(EVAL)', "t", env))
or assert(_load(full_source, '=(EVAL)'))
if env and setfenv then
setfenv(compiled, env)
end
local func, update = compiled()
local found = {}
do
Expand Down
15 changes: 13 additions & 2 deletions extension/script/backend/worker/variables.lua
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,19 @@ function special_has.Global(frameId)
rdebug.getinfo(frameId, "f", info)
local eval, value = rdebug.getupvaluev(info.func, 1)
if eval ~= "_ENV" then
eval = "_G"
value = rdebug._G
if LUAVERSION == 51 then
local fenv = rdebug.getfenv(info.func)
if fenv and not rdebug.equal(fenv, rdebug._G) then
eval = nil
value = fenv
else
eval = "_G"
value = rdebug._G
end
else
eval = "_G"
value = rdebug._G
end
Comment on lines +149 to +161
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for setting the default global environment (_G) is duplicated in both the else branch of the Lua 5.1 check and the else branch of the custom environment check. This can be simplified by setting the defaults first and then overriding them only if the specific Lua 5.1 condition is met, which improves maintainability.

        eval = "_G"
        value = rdebug._G
        if LUAVERSION == 51 then
            local fenv = rdebug.getfenv(info.func)
            if fenv and not rdebug.equal(fenv, rdebug._G) then
                eval = nil
                value = fenv
            end
        end

end
if eval == "_G" and globalCache._G then
local t = globalCache._G
Expand Down
14 changes: 14 additions & 0 deletions src/luadebug/rdebug_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,19 @@ namespace luadebug::visitor {
return 2;
}

static int visitor_getfenv(luadbg_State* L, lua_State* hL, protected_area& area) {
#if LUA_VERSION_NUM == 501
if (!copy_from_dbg(L, hL, area, 1, LUADBG_TFUNCTION)) {
return 0;
}
lua_pop(hL, 1);
refvalue::create(L, 1, refvalue::FENV {});
return 1;
#else
return 0;
#endif
}

template <bool getref = true>
static int visitor_getmetatable(luadbg_State* L, lua_State* hL, protected_area& area) {
area.check_client_stack(2);
Expand Down Expand Up @@ -1120,6 +1133,7 @@ namespace luadebug::visitor {
{ "getlocalv", protected_call<visitor_getlocal<false>> },
{ "getupvalue", protected_call<visitor_getupvalue> },
{ "getupvaluev", protected_call<visitor_getupvalue<false>> },
{ "getfenv", protected_call<visitor_getfenv> },
{ "getmetatable", protected_call<visitor_getmetatable> },
{ "getmetatablev", protected_call<visitor_getmetatable<false>> },
{ "getuservalue", protected_call<visitor_getuservalue> },
Expand Down
19 changes: 19 additions & 0 deletions src/luadebug/util/refvalue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,25 @@ namespace luadebug::refvalue {
}
}

template <>
int eval<FENV>(FENV& v, lua_State* hL, value* parent) {
int t = eval(parent, hL);
if (t == LUA_TNONE)
return LUA_TNONE;
if (t != LUA_TFUNCTION) {
lua_pop(hL, 1);
return LUA_TNONE;
}
#if LUA_VERSION_NUM == 501
lua_getfenv(hL, -1);
lua_replace(hL, -2);
return lua_type(hL, -1);
#else
lua_pop(hL, 1);
return LUA_TNONE;
#endif
}

int eval(value* v, lua_State* hL) {
return visit([hL, v](auto&& arg) { return eval(arg, hL, v + 1); }, *v);
}
Expand Down
6 changes: 5 additions & 1 deletion src/luadebug/util/refvalue.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace luadebug::refvalue {
struct USERDATA_VAL {
unsigned int index;
};
struct FENV {};
using value = variant<
FRAME_LOCAL,
FRAME_FUNC,
Expand All @@ -66,7 +67,8 @@ namespace luadebug::refvalue {
TABLE_HASH_KEY,
TABLE_HASH_VAL,
USERDATA_KEY,
USERDATA_VAL>;
USERDATA_VAL,
FENV>;
static_assert(std::is_trivially_copyable_v<value>);

template <typename T>
Expand Down Expand Up @@ -102,6 +104,8 @@ namespace luadebug::refvalue {
struct allow_as_child<USERDATA_KEY> : public std::true_type {};
template <>
struct allow_as_child<USERDATA_VAL> : public std::true_type {};
template <>
struct allow_as_child<FENV> : public std::true_type {};

int eval(value* v, lua_State* hL);
bool assign(value* v, lua_State* hL);
Expand Down