Script类


一个保存预编译脚本的类,并在特定的沙箱中运行它们。

new vm.Script(code, options)

创建一个新的 Script 编译 code,但不运行它。相反,被创建的 vm.Script 对象用于表示此编译代码。此脚本可以在之后使用以下方法运行多次。返回的脚本不绑定到任何全局对象。它在每次运行前定向绑定。

创建脚本时的选项有:

  • filename:允许你控制从该脚本中产生的任何堆栈跟踪中显示的文件名

  • lineOffset:允许你添加一个显示在堆栈跟踪中行号的偏移量。

  • columnOffset:允许你添加一个显示在堆栈跟踪中列数的偏移量。

  • displayErrors:是否在抛出异常前输出带高亮错误代码行的错误信息到 stderr。仅适用于编译代码时的语法错误;而运行代码时的错误,通过脚本的方法选项来控制。

  • timeout:在终止执行之前,执行 code 的毫秒数。如果执行被终止,错误将被抛出。

  • cachedData:一个可选的 Buffer 和提供的源代码的 V8 代码缓存数据。当提供 cachedDataRejected 值时会根据由 V8 接受的数据设置 truefalse

  • produceCachedData:如果为 true 并且不存在 cachedData - V8 试图生成代码缓存数据的 code。一旦成功,将产生和存储一个 Buffer 和 V8 的代码缓存数据到返回的 vm.Script 实例的缓存数据属性中。cachedDataProduced 值会被设置为 truefalse 取决于代码缓存数据是否被成功产生。

script.runInThisContext([options])

类似于 vm.runInThisContext() 但是一个预编译 Script 对象的方法。script.runInThisContext() 运行 script 的编译代码并返回结果。运行的代码无权限访问本地作用域,但是有权限访问当前的 global 对象。

使用 script.runInThisContext() 编译代码一次,运行多次:

  1. const vm = require('vm');
  2. global.globalVar = 0;
  3. const script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' });
  4. for (var i = 0; i < 1000; ++i) {
  5. script.runInThisContext();
  6. }
  7. console.log(globalVar);
  8. // 1000

运行脚本的选项有:

  • filename:允许你控制产生在任何堆栈跟踪中显示的文件名。

  • lineOffset:允许你添加一个显示在堆栈跟踪中行号的偏移量。

  • columnOffset:允许你添加一个显示在堆栈跟踪中列数的偏移量。

  • displayErrors:是否在抛出异常前输出带高亮错误代码行的错误信息到 stderr。将捕捉从编译 code 时获得的语法错误和通过执行编译代码抛出的运行时错误。仅适用于执行代码的运行时错误;它不可能创建一个语法错误的 Script 实例作为构造函数抛出。

  • timeout:在终止执行之前,执行 code 的毫秒数。如果执行被终止,错误将被抛出。

script.runInContext(contextifiedSandbox[, options])

类似于 vm.runInContext() 但是一个预编译 Script 对象的方法。script.runInThisContext()contextifiedSandbox 中运行 script 的编译代码并返回结果。运行的代码无权限访问本地作用域。

script.runInContext()script.runInThisContext() 使用相同的选项。

例子:编译递增一个全局变量,并设置一个变量,然后执行该代码多次。这些全局变量包含在沙箱中。

  1. const util = require('util');
  2. const vm = require('vm');
  3. var sandbox = {
  4. animal: 'cat',
  5. count: 2
  6. };
  7. var context = new vm.createContext(sandbox);
  8. var script = new vm.Script('count += 1; name = "kitty"');
  9. for (var i = 0; i < 10; ++i) {
  10. script.runInContext(context);
  11. }
  12. console.log(util.inspect(sandbox));
  13. // { animal: 'cat', count: 12, name: 'kitty' }

请注意,运行不受信任的代码是一个棘手的事情,需要非常小心。script.runInContext() 非常有用,但安全运行不受信任的代码需要一个单独的进程。

script.runInNewContext([sandbox][, options])

类似于 vm.runInNewContext() 但是一个预编译 Script 对象的方法。如果传入 sandbox,则使用 script.runInNewContext() 将其上下文化,然后运行 script 的编译代码将沙箱作为全局对象并返回结果。运行的代码无权限访问本地作用域。

script.runInNewContext()script.runInThisContext() 使用相同的选项。

例子:编译代码,设置一个全局变量,然后在不同的上下文中多次执行代码。这些全局变量在沙箱内部被设置。

  1. const util = require('util');
  2. const vm = require('vm');
  3. const sandboxes = [{}, {}, {}];
  4. const script = new vm.Script('globalVar = "set"');
  5. sandboxes.forEach((sandbox) => {
  6. script.runInNewContext(sandbox);
  7. });
  8. console.log(util.inspect(sandboxes));
  9. // [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]

请注意,运行不受信任的代码是一个棘手的事情,需要非常小心。script.runInNewContext() 非常有用,但安全运行不受信任的代码需要一个单独的进程。