扩展 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, , 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

扩展 lua require 的行为的更多相关文章

  1. Lua Require函数

    转自:http://www.cppblog.com/cslover/archive/2013/12/21/204934.html Lua提供高级的require函数来加载运行库.粗略的说require ...

  2. ulua 路径小记 以及 lua require 机制整理

    ulua 路径小记 在学习ulua时,require模块的根路径可以为项目的Lua文件夹或者ToLua文件夹(Editor下),但是在package.path和package.cpath中并没有看到当 ...

  3. Lua require 相对路径

    lua require 加载方式与我们现在熟知的路径系统不太一样,想要知道lua require 方法的工作原理也很简单 随便写一个错误的require 代码即可: 1 require("l ...

  4. lua require路径设置实例

    1.首先要强调的是,lua require的路径用的是斜杠"/",而不是从Windows文件属性那里复制来的反斜杠"\". 2.通过 print(pagckag ...

  5. LUA require 搜索路径指定方法

    如果是一个 *.LUA 的文件, 里面用到了自己写的库, 或者第三方写的库, 但是你不想把它放到 lua 的安装目录里, 则在代码里面可以指定require搜索的路径. package.path = ...

  6. Lua require搜索路径指定方法

    在自己的lua文件中,如果使用到了自己写的C库或者第三方库,想让lua编译到自己指定的目录下寻找*.lua或*.so文件的时候,可以再自己的Lua代码中添加如下代码,可以指定require搜索的路径. ...

  7. unity lua require dofile loadfile 区别

    oadfile,加载文件,编译文件,并且返回一个函数,不运行 dofile其实就是包装了Loadfile,根据loadfile的返回函数运行一遍 require加载文件的时候,不用带目录,有lua自己 ...

  8. lua加载函数require和dofile

    lua加载函数require和dofile Lua提供高级的require函数来加载运行库.粗略的说require和dofile完成同样的功能但有两点不同: 1. require会搜索目录加载文件; ...

  9. Lua中的loadfile,dofile,require使用,最后还有调试

    1.loadfile---只编译,不运行. loadfile编译代码成中间码并且返回编译后的chunk作为一个函数,而不执行代码:另外loadfile不会抛出错误信息而是返回错误代号. loadstr ...

随机推荐

  1. 利用Docker快速创建Nginx负载均衡节点

    本文版权归博客园和作者吴双本人共同所有 转载和爬虫请注明原文地址 www.cnblogs.com/tdws 一.Self-Host Kestrel 1. 在vs2017中新建dotnet core2. ...

  2. angular $observe() 和$watch的区别

    1.$observe()是属性attributes的方法,只能在DOM属性的值发生变化时用,并且只用于directive内. 当需要监听一个包含变量的属性值时attr1="Name:{{na ...

  3. 用vue开发一个app(1,基础环境配置)

    在今天之前,我没有很系统的看过,学习过vue.也是第一次尝试用vue写个小应用 现在开始研究配环境 这边参考的是https://cn.vuejs.org/v2/guide/installation.h ...

  4. 翻译连载 | 第 9 章:递归(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  5. js 倒计时(服务器时间同步)

    首先说一下,为什么要服务器时间同步, 因为服务器时间和本地电脑时间存在一定的时间差.有些对时效性要求非常高的应用,例如时时彩开奖,是不能容忍这种时间差存在的. 方案1:每次倒计时去服务端请求时间 // ...

  6. DOM中document对象的常用属性方法

    每个载入浏览器的 HTML 文档都会成为 Document 对象. Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问. 属性 1  document.anchors  返 ...

  7. 国外支付PayPal

    PayPal官网https://www.paypal.com/ PayPal沙箱https://www.sandbox.paypal.com/signin?country.x=US&local ...

  8. 怎样使用自定义标签简化 js、css 引入?

    国庆将至,工作兴致全无,来总结点项目里平时不起眼干货. 前端引入 js .css 一般是这样: <script type="text/javascript" src=&quo ...

  9. Codeforces 858A. k-rounding 数论

    题目: 题意:输入n和k,找到一个最小的数,满足末尾有至少k个0和是n的倍数. 最小的情况 ans = n,最大的情况 ans = n*pow(10,k). 令 k = pow(10,k); 我们发现 ...

  10. js 防止变量冲突

    解决方法 sc1 和sc2 的a都是window.a 会指向一个变量 1:使用匿名函数将脚本包起来,全局变量用来通信 如window.x; 2:命名空间 代码: <script> (fun ...