方法和属性
- vm.createContext([sandbox])
- vm.isContext(sandbox)
- vm.runInThisContext(code[, options])
- vm.runInContext(code, contextifiedSandbox[, options])
- vm.runInNewContext(code[, sandbox][, options])
- vm.runInDebugContext(code)
vm.createContext([sandbox])
如果给一个 sandbox 的对象,则将沙箱 (sandbox) 对象 “上下文化 (contextify)” 供 vm.runInContext 或 script.runInContext 调用。 以此方式运行的脚本将以 sandbox 作为全局对象,该对象将在保留其所有的属性的基础上拥有标准全局对象所拥有的内置对象和函数。在由 vm 模块运行的脚本之外的地方 sandbox 将不会被改变。
如果没有提供沙箱对象,则返回一个新的、空的、没被上下文化的可用沙箱。
此函数可用于创建可执行多个脚本的沙箱,如,在模拟浏览器的时候可以使用该函数创建一个用于表示 window 全局对象的沙箱, 并将所有 <script> 标签放入沙箱执行。
vm.isContext(sandbox)
返回一个沙箱对象是否通过调用 vm.createContext() 使其上下文化。
vm.runInThisContext(code[, options])
vm.runInThisContext() 编译 code,运行它并返回结果。运行的代码不能访问本地作用域,但可以访问当前的 global 对象。
使用 vm.runInThisContext() 和 eval() 运行相同代码的例子:
const vm = require('vm');
var localVar = 'initial value';
const vmResult = vm.runInThisContext('localVar = "vm";');
console.log('vmResult: ', vmResult);
console.log('localVar: ', localVar);
const evalResult = eval('localVar = "eval";');
console.log('evalResult: ', evalResult);
console.log('localVar: ', localVar);
// vmResult: 'vm', localVar: 'initial value'
// evalResult: 'eval', localVar: 'eval'
vm.runInThisContext() 无法访问本地作用域,所以 localVar 不变。eval() 可以访问本地作用域,所以 localVar 变了。
在这种方式下, vm.runInThisContext() 更像一个间接的 eval() 调用,如,(0,eval)('code')。然而,它也有以下附加选项:
filename:允许你控制产生在任何堆栈跟踪中显示的文件名。lineOffset:允许你添加一个显示在堆栈跟踪中行号的偏移量。columnOffset:允许你添加一个显示在堆栈跟踪中列数的偏移量。displayErrors:是否在抛出异常前输出带高亮错误代码行的错误信息到 stderr。将捕捉从编译code时获得的语法错误和通过执行编译代码抛出的运行时错误。默认为true。timeout:在终止执行之前,执行code的毫秒数。如果执行被终止,错误将被抛出。
vm.runInContext(code, contextifiedSandbox[, options])
vm.runInContext() 编译 code,然后在 contextifiedSandbox 中运行它并返回结果。运行的代码不能访问本地作用域。contextifiedSandbox 对象必须预先通过 vm.createContext() 上下文化。它将被用作 code 的全局对象。
vm.runInContext() 与 vm.runInThisContext() 使用相同的选项。
例子:编译并在一个现有的上下文中执行不同的脚本。
const util = require('util');
const vm = require('vm');
const sandbox = { globalVar: 1 };
vm.createContext(sandbox);
for (var i = 0; i < 10; ++i) {
vm.runInContext('globalVar *= 2;', sandbox);
}
console.log(util.inspect(sandbox));
// { globalVar: 1024 }
vm.runInNewContext(code[, sandbox][, options])
vm.runInNewContext() 编译 code,如果传入 sandbox,则将其上下文化,如果省略参数,则创建一个新的沙箱并将其上下文化,然后将沙箱作为全局对象运行代码并返回结果。
vm.runInNewContext() 与 vm.runInThisContext() 使用相同的选项。
例子:编译并执行代码,递增一个全局变量,并设置一个新的。这些全局变量包含在沙箱中。
const util = require('util');
const vm = require('vm');
const sandbox = {
animal: 'cat',
count: 2
};
vm.runInNewContext('count += 1; name = "kitty"', sandbox);
console.log(util.inspect(sandbox));
// { animal: 'cat', count: 3, name: 'kitty' }
请注意,运行不受信任的代码是一个棘手的事情,需要非常小心。vm.runInNewContext() 非常有用,但安全运行不受信任的代码需要一个单独的进程。
vm.runInDebugContext(code)
vm.runInDebugContext() 在 V8 debug 的上下文中编译和执行 code。主要用途是获得访问 V8 调试对象的权限:
const Debug = vm.runInDebugContext('Debug');
Debug.scripts().forEach((script) => { console.log(script.name); });
请注意,debug 的上下文和对象是 V8 调试器的内部实现,并且可能会改变(或者甚至可能被移除),恕不另行通知。
debug 对象同样可以通过 --expose_debug_as= 开关暴露。