1

グローバル環境外の環境にチャンクをロードするために setfenv() を使用しようとしましたが、少し問題があります。以下は私が実行しているコードです:

-- main.lua
function SandboxScript(scriptTable, scriptName)
    setmetatable(scriptTable, { __index = _G })
    local sandbox = loadfile(scriptName)
    setfenv(sandbox, scriptTable)
    sandbox()
    return scriptTable
end

local function main()
    print(Singleton)
    local test = {}
    local single1 = SandboxScript(test, "C:\\pathto\\TestTable.lua")
    print(Singleton)
    test.Update()

    local test2 = {}
    local single2 = SandboxScript(test2, "C:\\pathto\\TestTable.lua")
    test2.Update()
end
main()

-- TestTable.lua
require("Singleton")
local test = {}

function Update()
    test = Singleton:new()
    print(test.var)
    test.var = "Changed"
    print(test.var)
end

-- Singleton.lua
Singleton = {}
Instance = {}

function Singleton:new()
    if(next(Instance)) then
        return Instance
    end

    Instance.var = "Init"
    return Instance
end

私はこれの出力が次のようになることを期待しています:

nil      --(First check in global table before running sandbox code)
nil      --(Second check in global table after running sandbox code)
Init     --(Initial value of the Singleton's var)
Changed  --(Singleton's var after we change it)
Init     --(Initial value of the Singleton's var in a different sandbox)
Changed  --(Singleton's var after we change it in the different sandbox)


代わりに私は得ています:

nil
table: 05143108
Init
Changed
Changed
Changed

「sandbox()」の実行前に「setfenv(sandbox, scriptTable)」を使用してサンドボックスの環境を「scriptTable」に設定したにもかかわらず、「sandbox()」がテーブルをグローバル空間にロードしていることを示しています。

他の投稿で言及されているサンド ボックスの例を確認しましたが、それでも同じ結果が得られます。グローバル環境を汚染することなく、独自の環境にスクリプトをロードするために何ができるか考えていますか?

4

1 に答える 1

1

グローバル環境を実際に汚染しているわけではありません。ここに表示されているのは、require関数を呼び出す環境に依存するのではなく、 への呼び出しごとにモジュールがキャッシュされ、共有されるというパッケージ システムの性質です。これにより、Singleton モジュールが機能するようになります。なぜなら、そうしないrequireで実行するloadfileと、2 回ロードされるからです (そして、予想よりもシングルトンが非常に少なくなります)。

したがって、実際のタスクがサンドボックスごとに 1回だけモジュールをロードすることである場合は、サンドボックスに入る前にpackage.loaded、および他のローダー状態変数を交換できます。package.preload詳細についてはModules、Lua 5.1 リファレンス マニュアルのセクションを参照してください。

を使用したソリューションは問題loadfileないかもしれませんが、サンドボックス内の複雑なモジュール システムで複数のモジュールを相互要求することを計画している場合、これは大きな問題につながります。

于 2014-02-13T08:55:43.387 に答える