• 扩展 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(...)
    end
    
    return 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
        end
        return function()
            return function(env)
                if env then
                    debug.setupvalue(f, 1, env)
                end
                return f(filename)
            end
        end
    end
    
    local function searcher_env(name)
        local filename, err = package.searchpath(name, package.upath)
        if filename == nil then
            return err
        else
            return load_env(filename)
        end
    end
    
    table.insert(package.searchers, searcher_env)

    test.lua

    require "requirenv"
    
    package.upath = "./?.user.lua"
    
    local myprint = print
    
    local env = {
        print = function (...)
            myprint("hook", ...)
        end
    }
    
    local s = require "mymod"(env)
    
    s.test "hello world"  -- hook hello world
  • 相关阅读:
    NSURLSession实现文件上传
    JS中如何判断null、undefined与NaN
    jquery
    url操作等
    设计模式
    javaScript类型转换
    jQuery.noop
    JavaScript严谨模式(Strict Mode)提升开发效率和质量
    Data URI
    e.target e.currenttarget
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/7761000.html
Copyright © 2020-2023  润新知