lua 环境和模块
lua environments and modules
假设我有一个模块:
-- env.lua
local env = {}
function env.resolve(str)
print("mod", _ENV)
if _resolve_path ~= nil then
return _resolve_path(str)
else
error("bad env")
end
end
return env
和一些使用它的代码:
-- sandbox demo
-- run as: lua env-test.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 = {
print = print,
env = env,
_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"))
我想要实现的是 sandbox() 中的 env.resolve()
将使用环境中的自定义 _resolve_path 函数。它看到环境不适用于从沙盒函数调用的代码。目标是根据调用它们的位置来增强某些模块的行为方式。例如。具有具有不同本地 _resolve_path() 函数的沙箱{1,2,3}()。
当您使用 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)
或者,如果您希望不必为每个 resolve
调用指定环境,您可以将 resolve
函数绑定到每个新环境:
-- 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
假设我有一个模块:
-- env.lua
local env = {}
function env.resolve(str)
print("mod", _ENV)
if _resolve_path ~= nil then
return _resolve_path(str)
else
error("bad env")
end
end
return env
和一些使用它的代码:
-- sandbox demo
-- run as: lua env-test.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 = {
print = print,
env = env,
_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"))
我想要实现的是 sandbox() 中的 env.resolve()
将使用环境中的自定义 _resolve_path 函数。它看到环境不适用于从沙盒函数调用的代码。目标是根据调用它们的位置来增强某些模块的行为方式。例如。具有具有不同本地 _resolve_path() 函数的沙箱{1,2,3}()。
当您使用 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)
或者,如果您希望不必为每个 resolve
调用指定环境,您可以将 resolve
函数绑定到每个新环境:
-- 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