0

Is there a way to run a script in a sandbox environment to not pollute global state, but still be able to require"someluafile" in which global vars get set for said environment and NOT the global state

-- main script
local moduleXY = require"moduleXY"
v = 0
moduleXY.setV()

-- moduleXY
local function setV ()
  v = 42
end

local moduleXY = {
   setV = setV
}

return moduleXY

so that after the call the states v is nil and envs v is set to 42 (instead of state v being 42 and envs 0)

luajit (so 5.1), cpp binding sol3

alf_gralf
  • 31
  • 5

1 Answers1

1

Lua 5.1 uses setfenv to change the environment of a function. Here's an example.

local moduleXY = require"moduleXY"
v = 0

env = setmetatable({}, {__index = _G}) -- create an environment
setfenv(moduleXY.setV, env) -- change the environment
moduleXY.setV()
print(v)     -- 0
print(env.v) -- 42

setfenv(moduleXY.setV, _G)  -- revert the environment
moduleXY.setV()
print(v)     -- 42

To change the environment of the current thread use setfenv(0).

setfenv(0, env) -- this doesn't affect loaded functions
local moduleXY = require"moduleXY" -- module is loaded in 'env' environment
moduleXY.setV()
print(env.v) -- 42

setfenv(0, getfenv()) -- revert the thread environment
require"othermodule" -- load other module in default environment
shingo
  • 18,436
  • 5
  • 23
  • 42
  • that's the perfect approach. thank you. but the main script is already run in an environment & I would need to run the function from moduleXY in the same environment, not a new one. currently my problem with require is that it breaks out of that sandbox – alf_gralf Oct 24 '22 at 13:26
  • I've updated my answer, added an approach to change the environment of the required file. – shingo Oct 24 '22 at 14:11