Таблица Luf 5.1 setfenv() все еще загружается в глобальном пространстве
Я пытался работать с setfenv(), чтобы загрузить чанк в среду вне глобальной среды, но у меня возникли небольшие проблемы. Вот код, который я запускаю:
-- main.lua
function SandboxScript(scriptTable, scriptName)
setmetatable(scriptTable, { __index = _G })
local sandbox = loadfile(scriptName)
setfenv(sandbox, scriptTable)
sandbox()
return scriptTable
end
local function main()
print(Singleton)
local test = {}
local single1 = SandboxScript(test, "C:\\pathto\\TestTable.lua")
print(Singleton)
test.Update()
local test2 = {}
local single2 = SandboxScript(test2, "C:\\pathto\\TestTable.lua")
test2.Update()
end
main()
-- TestTable.lua
require("Singleton")
local test = {}
function Update()
test = Singleton:new()
print(test.var)
test.var = "Changed"
print(test.var)
end
-- Singleton.lua
Singleton = {}
Instance = {}
function Singleton:new()
if(next(Instance)) then
return Instance
end
Instance.var = "Init"
return Instance
end
Я ожидаю, что результат этого будет:
nil --(First check in global table before running sandbox code)
nil --(Second check in global table after running sandbox code)
Init --(Initial value of the Singleton's var)
Changed --(Singleton's var after we change it)
Init --(Initial value of the Singleton's var in a different sandbox)
Changed --(Singleton's var after we change it in the different sandbox)
Вместо этого я получаю:
nil
table: 05143108
Init
Changed
Changed
Changed
Указывает, что "sandbox()" загружает таблицу в глобальное пространство, хотя я установил среду "песочницы" в "scriptTable", используя "setfenv (sandbox, scriptTable)" до выполнения "sandbox()".
Я прошел Пример Песочницы, упомянутый в других постах, но я все еще получаю те же результаты. Любая идея, что я могу сделать, чтобы загрузить сценарий в его собственной среде, не загрязняя глобальную среду?
1 ответ
Вы на самом деле не загрязняете глобальную среду, вы видите здесь природу системы пакетов, что модули кэшируются и совместно используются для каждого вызова require
, не зависящий от среды вызывающей функции. Это позволяет модулю Singleton работать, потому что если вы не будете require
это, но сделать loadfile
, он будет загружен дважды (и будет меньше, чем ожидалось).
Таким образом, если реальная задача состоит в том, чтобы загрузить модуль только один раз для песочницы, то вы можете поменять местами package.loaded
, package.preload
и другие переменные состояния загрузчика перед входом в песочницу. Больше информации в Modules
раздел Lua 5.1 Справочное руководство.
Решение с loadfile
Это может быть просто замечательно, но если вы планируете перекрестно требовать модули в сложной модульной системе внутри вашей песочницы, это действительно приведет к большой проблеме.