I'm trying to use raw Lua files for configuration purposes, but don't want the config files polluting the global namespace.
The problem I'm running into is that dofile
always seems to execute in the real global environment, so external files just throw all their declarations into _G.
Here's an example main file, with comments indicating my wishful thinking.
function myFunc()
print("In the sandbox:")
print("Should be 1:", a) -- falls back to _G for lookup
a = 2 -- instantiating new global for sandbox
print("Should be 2:", a) -- from sandbox
print("Should still be 1:", _G.a) -- from host environment
dofile("loading.lua") -- here's where things go wrong
print "\nBack in the sandbox:"
print("Should be 3:", a) -- changed by loadfile
print("Should STILL be 1:", _G.a) -- unchanged
end
a = 1
local newgt = {} -- new environment
setmetatable(newgt, {__index = _G})
setfenv(myFunc, newgt)
myFunc()
print("\nOutside of the sandbox:")
print("Should be 1: ", a) -- in theory, has never changed
And the file it's loading (loading.lua
:
print ("\nLoading file...")
print("Should be 2: ", a) -- coming from the sandbox environment
a = 3
print("Should be 3: ", a) -- made a change to the environment
And finally the output I'm seeing:
In the sandbox:
Should be 1: 1
Should be 2: 2
Should still be 1: 1
Loading file...
Should be 2: 1
Should be 3: 3
Back in the sandbox:
Should be 3: 2
Should STILL be 1: 3
Outside of the sandbox:
Should be 1: 3
The scoping that most programmers are used to is called lexical scoping. It's found in Lua and many other languages. Lexical scoping is the dominant choice for a reason: it's easy to reason about and understand just by looking at the code.
Sets the environment to be used by the given function. f can be a Lua function or a number that specifies the function at that stack level: Level 1 is the function calling setfenv . setfenv returns the given function.
You can access the local variables of any active function by calling getlocal , from the debug library. It has two parameters: the stack level of the function you are querying and a variable index. It returns two values: the name and the current value of that variable.
If so, then you need to learn a very important programming concept known as scope. Scope impacts Lua's ability to "see" variables (as in the error above) as well your ability to manage where functions exist in relation to other functions and variables.
The problem you describe is also discussed on this page Dofile Namespace Proposal. The solution seemed to be the following replacement for dofile
:
function myapp.import(name)
local f,e = loadfile(name)
if not f then error(e, 2) end
setfenv(f, getfenv(2))
return f()
end
See also: Sand Boxes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With