问题:我使用nodejs vm运行一个提供的脚本(可信的来源,但不在我的控制)。所提供的脚本必须回调到我在它接收到的上下文中提供的函数。
脚本内部的函数按预期工作。但是,当调用上下文中提供的函数时,它不再具有提供给被调用脚本的上下文中的任何变量。下面这个简短的程序演示了这个问题:
var vm = require('vm');
var sandbox={console:console, myfn:function() {
console.log("MYFN");
console.log("MYFN: a="+a);
}, a:42};
var ctx = new vm.createContext(sandbox);
vm.runInContext("function okfn() { console.log('OKFN'); console.log('OKFN: a='+a); } console.log('TEST'); console.log('TEST: a='+a);okfn(); myfn();", ctx, {filename:"TEST"});
运行时,我希望看到以下输出:
TEST
TEST: a=42
OKFN
OKFN: a=42
MYFN
MYFN: a=42
但是,myfn()中的最后一个console.log会产生一个ReferenceError: a is not defined
是否有一种方法来保留通过runInContext()传递给脚本的上下文,当该脚本调用上下文本身提供的函数?
函数被绑定到定义它们的全局作用域。由于myfn
是在主脚本文件中定义的,因此它将使用该文件的全局变量。为了将该函数绑定到另一个全局上下文中,必须在该上下文中重新定义/重新执行该函数:
var vm = require('vm');
function myfn() {
console.log("MYFN");
console.log("MYFN: a="+ a);
}
var sandbox={console:console, a:42};
var ctx = new vm.createContext(sandbox);
// Evaluates the source code of myfn in the new context
// This will ensure that myfn uses the global context of 'ctx'
vm.runInContext(myfn.toString(), ctx, {filename: "TEST"});
// Retained in the context
console.log(ctx.myfn);
// Use it
vm.runInContext("function okfn() { console.log('OKFN'); console.log('OKFN: a='+a); } console.log('TEST'); console.log('TEST: a='+a);okfn(); myfn();", ctx, {filename:"TEST"});