NodeJs-VM

 后端   小卒子   2024-09-11 09:27   172
  nodejs

Node.js 的 vm 模块为执行 JavaScript 代码提供了独立的沙箱环境,它允许将 JavaScript 代码放入隔离的虚拟机 (VM) 上下文中运行,并提供与主上下文的有限交互。这对于需要安全地运行不信任的代码或需要创建隔离环境的场景非常有用。

以下是 vm 模块的属性和方法的详细说明,涵盖该模块的所有主要功能和用法。


1. 引入 vm 模块

const vm = require('vm');

2. vm.Script

vm.Script 类表示一个预编译的 JavaScript 脚本,可以在多个上下文中反复执行。

构造函数:new vm.Script(code[, options])

  • code:要编译的 JavaScript 代码。
  • options:可选项。可以配置的属性包括:
    • filename:脚本的文件名(用于错误堆栈跟踪)。
    • lineOffset:错误报告的行偏移量。
    • columnOffset:错误报告的列偏移量。
    • displayErrors:如果为 true,则会在错误时显示更具描述性的错误消息。

示例:

const vm = require('vm');

const script = new vm.Script('const x = 42; x + 1;');
const result = script.runInThisContext();
console.log(result);  // 输出: 43

3. vm.createContext(sandbox)

vm.createContext() 创建一个隔离的沙箱上下文。沙箱是一个 JavaScript 对象,所有脚本在这个上下文中执行时都可以访问该对象中的属性。

示例:

const vm = require('vm');

const sandbox = { x: 2 };
vm.createContext(sandbox);

const code = 'x += 40; var y = 17;';
vm.runInContext(code, sandbox);

console.log(sandbox);  // 输出: { x: 42, y: 17 }

vm.createContext()sandbox 转换为一个可以运行代码的安全环境。在这个例子中,代码 x += 40;var y = 17; 在沙箱中执行,并修改了沙箱中的 x 值,同时添加了新的 y 值。


4. vm.runInContext(code, context[, options])

vm.runInContext() 在指定的上下文中执行代码。这种方式允许在隔离的沙箱中运行 JavaScript 代码,并且代码对主进程的上下文没有直接影响。

  • code:要执行的 JavaScript 代码。
  • context:通过 vm.createContext() 创建的上下文。
  • options:可选配置,类似于 vm.Script 的选项。

示例:

const vm = require('vm');

const sandbox = { a: 1, b: 2 };
vm.createContext(sandbox);

vm.runInContext('a += 5; b *= 3;', sandbox);

console.log(sandbox);  // 输出: { a: 6, b: 6 }

5. vm.runInNewContext(code[, sandbox][, options])

vm.runInNewContext() 在一个全新的上下文中执行代码,该上下文与当前的环境完全隔离。可以传递一个沙箱对象来作为上下文的全局对象。

示例:

const vm = require('vm');

const result = vm.runInNewContext('x + y', { x: 10, y: 5 });
console.log(result);  // 输出: 15

6. vm.runInThisContext(code[, options])

vm.runInThisContext() 在当前的全局上下文中运行代码,类似于直接在当前上下文中执行代码,但代码在一个隔离的环境中运行。它允许执行代码,但不会对当前上下文做出任何全局更改。

示例:

const vm = require('vm');

const result = vm.runInThisContext('var z = 5; z * 2;');
console.log(result);  // 输出: 10

// `z` 不会被定义在当前上下文中
console.log(typeof z);  // 输出: 'undefined'

7. vm.isContext(sandbox)

vm.isContext() 检查某个对象是否是通过 vm.createContext() 创建的上下文对象。

示例:

const vm = require('vm');

const sandbox = { x: 1 };
console.log(vm.isContext(sandbox));  // 输出: false

vm.createContext(sandbox);
console.log(vm.isContext(sandbox));  // 输出: true

8. vm.measureMemory([context])

vm.measureMemory() 返回与 V8 引擎内存使用情况相关的指标。这个函数返回一个 Promise,可以报告当前上下文或特定上下文的内存使用情况。此 API 是实验性的。

  • context:可选参数,指定要测量的上下文。如果未提供,则测量当前的上下文。

示例:

const vm = require('vm');

vm.measureMemory().then((memoryUsage) => {
  console.log(memoryUsage);
});

输出的结果包含几个字段,如 total, used, external, arrayBuffers,这些字段提供了内存的总大小、已使用大小等信息。


9. vm.Script.prototype.runInNewContext([sandbox][, options])

这是 vm.Script 实例的一个方法,用于在新创建的上下文中运行预编译的脚本。

示例:

const vm = require('vm');

const script = new vm.Script('x = 10');
const sandbox = {};
script.runInNewContext(sandbox);

console.log(sandbox.x);  // 输出: 10

10. vm.Script.prototype.runInContext(context[, options])

在指定的上下文中运行预编译的脚本。

示例:

const vm = require('vm');

const script = new vm.Script('x = 5');
const sandbox = { x: 1 };
vm.createContext(sandbox);

script.runInContext(sandbox);
console.log(sandbox.x);  // 输出: 5

11. vm.Script.prototype.runInThisContext([options])

在当前上下文中执行预编译的脚本。这个方法在概念上类似于 vm.runInThisContext(),但它运行的是预编译的脚本。

示例:

const vm = require('vm');

const script = new vm.Script('var y = 20;');
script.runInThisContext();

console.log(typeof y);  // 输出: 'undefined'

12. vm.compileFunction(functionBody, params, options)

vm.compileFunction() 用于编译一个函数,在独立的上下文中执行函数体。它允许指定函数的参数以及执行的环境(沙箱)。

  • functionBody:要编译的函数体(字符串)。
  • params:函数参数列表(数组)。
  • options:可选项,支持指定上下文、文件名、行/列偏移等。

示例:

const vm = require('vm');

const fn = vm.compileFunction('return a + b;', ['a', 'b']);
console.log(fn(10, 20));  // 输出: 30

总结

Node.js 的 vm 模块提供了一个强大的工具,用于在隔离环境中执行 JavaScript 代码。通过 vm.Script, vm.createContext(), vm.runInContext() 等方法,开发者可以在虚拟机沙箱中运行代码,有效提高代码的安全性和灵活性。