当您将模块加载到
require
它与全球环境息息相关。一旦在一个环境中创建了一个函数,它就会在其整个生命周期内拥有该环境。
在Lua 5.2之前,您可以使用
set/getfenv
改变环境,但环境现在是词汇化的。只有通过更改
_ENV
增值。
那么,如何在不同的环境中运行相同的功能呢?可以将环境作为参数传入:
function env.resolve(str, _ENV)
print("mod", _ENV)
if _resolve_path ~= nil then
return _resolve_path(str)
else
error("bad env")
end
end
然后你打电话到哪里
resolve
例如:
env.resolve('test', _ENV)
或者,如果您希望不必为每个
决定
调用可以绑定
决定
每个新环境的功能:
-- env.lua
local print = print
local error = error
local env = {}
-- this is the actual resolve function that takes the environment as a parameter
local function resolve_env(str, _ENV)
print("mod", _ENV)
if _resolve_path ~= nil then
return _resolve_path(str)
else
error("bad env")
end
end
-- this is the module (ie. global) resolve
function env.resolve(str)
return resolve_env(str, _ENV)
end
-- this function binds a resolve function to a sandbox environment
function env.bind(_ENV)
_ENV.env = {
resolve = function(str)
return resolve_env(str, _ENV)
end
}
return _ENV
end
return env
沙盒现在可以设置绑定解析:
-- sandbox.lua
env = require 'env'
function _resolve_path(path)
return "/" .. path
end
print("before main()")
print("", _ENV)
print("", env.resolve("test"))
local sandbox; do
local _ENV = env.bind{
print = print,
_resolve_path = function (path)
return "/chroot/" .. path
end
}
function sandbox()
print("from sandbox()")
print("", _ENV)
print("", env.resolve("test"))
end
end
sandbox()
print("after main()")
print("", _ENV)
print("", env.resolve("test"))
这将产生以下结果:
$ lua sandbox.lua
before main()
table: 00612f40
mod table: 00612f40
/test
from sandbox()
table: 0061c7a8
mod table: 0061c7a8
/chroot/test
after main()
table: 00612f40
mod table: 00612f40
/test