擴充套件 lua require 的行為

2021-09-07 15:32:46 字數 1836 閱讀 1240

**

今天同事提了個需求,他希望可以給部分 lua **(由策劃編寫)做乙個沙盒關起來。在 lua 裡做沙盒很容易,只需要控制函式的環境就可以了。不過另乙個附加需求是,這些**還可以直接利用 require 載入。

而我們又不想去修改系統的 api 介面,那麼怎麼做到這點呢?

首先, 我希望使用的時候看起來像這樣:

local *** = require "***" (myenv)
和傳統的 require 用法不同,可以在後面追加乙個引數 myenv 。這樣的話,每次 *** 模組被 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 =debug

local

function

load_env(filename)

local f,err = loadfile

(filename)

if f == nil

then

return

err

endreturn

function

()

return

function

(env)

if env then

debug.setupvalue(f, 1

, env)

endreturn

f(filename)

endend

endlocal

function

searcher_env(name)

local filename, err =package.searchpath(name, package.upath)

if filename == nil

then

return

err

else

return

load_env(filename)

endend

table.insert(package.searchers, searcher_env)

test.lua

require

"requirenv

"package.upath = "

./?.user.lua

"local myprint = print

local env =

local s = require

"mymod

"(env)

s.test

"hello world"--

hook hello world

設計模式 行為擴充套件

訪問者模式 表示乙個作用於某物件結構中各元素的操作。它讓我們可以在不改變各元素的前提下定義作用於這些元素的新操作 使用場景 1.乙個複雜的物件結構包含很多其它物件,它們有不同的介面,但是相對這些物件實施一些依賴於其具體型別的操作 2.需要對乙個組合結構中的物件進行許多不相關的操作,但是不想讓這些操作...

vim中lua require路徑的gf跳轉

vimrc中配置如下 path指定查詢的路徑,詳情help path includeexpr是嘗試替換路徑名中的.為 詳情help includeexpr suffixesadd為嘗試路徑字尾,詳情help suffixesadd set path usr include,lualib,work,s...

物件的行為

建構函式 是乙個特殊函式,該函式將在建立物件時執行,該函式返回類i型固定為該類的型別。若沒有手動書寫建構函式,編譯器會使用預設的建構函式,預設建構函式無參無函式體 建構函式宣告語法 訪問修飾符 類名 形參列表 函式體 建構函式的呼叫語法 new 類名 實參列表 呼叫建構函式即建立新的物件 函式過載 ...