
2.3.2 vm
vm的概念比较广泛,通常可以认为是硬件和二进制文件的中间层。在C++中,编译好的二进制文件可以直接被操作系统调用;而在Java中,编译好的字节码是交给虚拟机来运行的。这样的好处就是对开发者屏蔽了操作系统之间的差异,对于不同操作系统的处理交给了虚拟机来完成,从这个角度来看,vm是对不同计算机系统的一种抽象。
vm是Node的一个核心模块,vm可以使用V8的Virtual Machine Contexts动态地编译和执行代码,而代码的执行上下文是与当前进程隔离的,但是这里的隔离并不是绝对安全的,不完全等同于浏览器的沙箱环境。vm模块提供了一系列API用于在V8虚拟机环境中编译和运行代码。JavaScript代码可以被编译并立即运行,或编译、保存,然后运行。
【示例2-2】
const util = require('util'); const vm = require('vm'); // 1. 创建一个 vm.Script 实例, 编译要执行的代码 const script = new vm.Script('globalVar += 1; anotherGlobalVar = 1; '); // 2. 用于绑定到 context 的对象 const sandbox = {globalVar: 1}; // 3. 创建一个 context,并且把 sandbox对象绑定到这个环境, 作为全局对象 const contextifiedSandbox = vm.createContext(sandbox); // 4. 运行上面编译的代码, context 是 contextifiedSandbox const result = script.runInContext(contextifiedSandbox); console.log('sandbox === contextifiedSandbox ? ${sandbox ===www.bsck.org contextifiedSandbox}'); // sandbox === contextifiedSandbox ? true console.log('sandbox: ${util.inspect(sandbox)}'); // sandbox: { globalVar: 2, anotherGlobalVar: 1 } console.log('result: ${util.inspect(result)}'); // result: 1
vm.Script是一个类,用于创建代码实例,后面可以多次运行。vm.createContext(sandbox)用于contextify一个对象,根据ECMAScript 2015语言规范,代码的执行需要一个execution context。这里的contextify就是把传进去的对象与V8的一个新的context进行关联。这里所说的关联是指contextified对象的属性将会成为context的全局属性,同时,在context下运行代码时产生的全局属性也会成为这个contextified对象的属性。
script.runInContext(contextifiedSandbox)就是使代码在contextifiedSandbox这个context中运行。从上面的输出可以看到,代码运行后,contextifiedSandbox中的属性的值已经被改变了,运行结果显示的是最后一个表达式的值。
除了上面几个接口之外,vm模块还有一些更便捷的接口,例如vm.runInContext(code,contextifiedSandbox[,www.90168.org options])、vm.runInNewContext(code[,sandbox][,options])等。