扩展 lua require 的行为
擴展 lua require 的行為
?
來源 https://blog.codingnow.com/2015/10/lua_require_env.html
?
今天同事提了個需求,他希望可以給部分 lua 代碼(由策劃編寫)做一個沙盒關起來。在 lua 里做沙盒很容易,只需要控制函數的環境就可以了。不過另一個附加需求是,這些代碼還可以直接利用 require 加載。
而我們又不想去修改系統的 api 接口,那么怎么做到這點呢?
首先, 我希望使用的時候看起來像這樣:
local xxx = require "xxx" (myEnv)和傳統的 require 用法不同,可以在后面追加一個參數 myEnv 。這樣的話,每次 xxx 模塊被 require 時,它其實被重復運行一次,但會綁定不同的?_ENV?。
其次,既然模塊會被反復初始化,那么我們甚至還可以約定,每個這種沙盒封裝的模塊還可以接收 require 的傳入的額外參數。
做到這點很容易,我們只需要在 package.searchers 里追加一個自定義的 loader 然后并不返回加載的模塊 chunk ,而是做一個函數封裝。將 chunk 的運行推遲到傳入 myEnv 調用之后。
這樣,load chunk 本身還是依靠 require 的 package 機制緩存代碼的,只是每次調用后,重新綁定?_ENV?生成了一組新實例。
我在 gist 上貼了一組代碼實現這個特性:延遲綁定環境的 require?。
?
mymod.user.lua
local M = {}function M.test(...)print(...) endreturn M?
?
requirenv.lua
local package = package local debug = debuglocal function load_env(filename)local f,err = loadfile(filename)if f == nil thenreturn errendreturn function()return function(env)if env thendebug.setupvalue(f, 1, env)endreturn f(filename)endend endlocal function searcher_env(name)local filename, err = package.searchpath(name, package.upath)if filename == nil thenreturn errelsereturn load_env(filename)end endtable.insert(package.searchers, searcher_env)?
test.lua
require "requirenv"package.upath = "./?.user.lua"local myprint = printlocal env = {print = function (...)myprint("hook", ...)end }local s = require "mymod"(env)s.test "hello world" -- hook hello world?
轉載于:https://www.cnblogs.com/lsgxeva/p/7761000.html
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的扩展 lua require 的行为的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tomcat服务器安装
- 下一篇: 编程低级错误记录