1

I've been trying to work with setfenv() in order to load a chunk into an environment outside of the global environment but I'm having a little trouble. The following is the code I'm running:

-- 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

I'm expecting the output of this to be:

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)


Instead I'm getting:

nil
table: 05143108
Init
Changed
Changed
Changed

Indicating that the "sandbox()" is loading the table into the global space even though the I set the sandbox's environment to "scriptTable" using "setfenv(sandbox, scriptTable)" prior to execution of "sandbox()".

I've gone through the Sand Boxes Example mentioned in other posts but I'm still getting the same results. Any idea what I can do to load a script in it's own environment without polluting the global environment?

asked Feb 12, 2014 at 18:16
2
  • It seems that require("Singleton") executes Singleton.lua in global environment in despite of current environment. Commented Feb 12, 2014 at 18:37
  • @egor-skriptunoff You gave me an idea. It didn't solve the entire problem but made a little headway. Doing the following in TestTable: local singletonTable = loadfile("C:\\pathto\\Singleton.lua") singletonTable() Lead to the following output: nil table: 051D3108 Init Changed Init Changed Which appears to have still loaded Singleton into the global environment but at least kept the instance in the correct environment this time. Commented Feb 12, 2014 at 19:09

1 Answer 1

1

You are not really polluting the global environment, what you see here is a nature of package system, that modules are cached and shared for every call to require, not depending on environment of calling function. That allows Singleton module to work, because if you will not require it, but do loadfile, it will load twice (and be very less singleton than expected).

So, if the real task is to load module only once per sandbox, then you may swap package.loaded, package.preload and other loader state variables before entering into a sandbox. More info in Modules section of Lua 5.1 Reference Manual.

The solution with loadfile may be just fine, but if you plan to cross-require modules in complex module system inside your sandbox, this will lead to a big problem indeed.

answered Feb 13, 2014 at 8:55
Sign up to request clarification or add additional context in comments.

1 Comment

You're absolutely right, reading the Lua documentation I was incorrect about how require works and it turns out that behind the scenes, for all intents and purposes, require is just loadfile. I've changed my code to use loadfile and everything is working perfectly.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.