IO.js VM

2018-11-28 22:36 更新

執(zhí)行JavaScript

穩(wěn)定度: 2 - 穩(wěn)定

要獲取這個(gè)模塊,你可以通過(guò):

var vm = require('vm');

JavaScript代碼會(huì)被編譯且立刻執(zhí)行 或 編譯,保存,并且稍后執(zhí)行。

vm.runInThisContext(code[, options])

vm.runInThisContext()編譯代碼,運(yùn)行它,然后返回結(jié)果。運(yùn)行中的代碼不能訪問(wèn)本地作用域,但是可以訪問(wèn)當(dāng)前的全局對(duì)象。

使用vm.runInThisContexteval運(yùn)行相同代碼的例子:

var vm = require('vm');
var localVar = 'initial value';

var vmResult = vm.runInThisContext('localVar = "vm";');
console.log('vmResult: ', vmResult);
console.log('localVar: ', localVar);

var evalResult = eval('localVar = "eval";');
console.log('evalResult: ', evalResult);
console.log('localVar: ', localVar);

// vmResult: 'vm', localVar: 'initial value'
// evalResult: 'eval', localVar: 'eval'

vm.runInThisContext不能訪問(wèn)本地作用域,所以localVar沒(méi)有改變。eval可以訪問(wèn)本地作用域,所以localVar改變了。

這種情況下,vm.runInThisContext更像是一個(gè)間接的eval調(diào)用,像(0,eval)('code')。但是,它還有以下這些額外的選項(xiàng):

  • filename: 允許你控制提供在堆棧追蹤信息中的文件名。
  • displayErrors: 是否在拋出異常前向stderr打印任何的錯(cuò)誤,并且造成錯(cuò)誤的行會(huì)被高亮。會(huì)捕獲編譯代碼時(shí)的語(yǔ)法錯(cuò)誤和編譯完的代碼運(yùn)行時(shí)拋出的異常。默認(rèn)為true。
  • timeout: 在關(guān)閉之前,允許代碼執(zhí)行的時(shí)間(毫秒)。如果超時(shí),一個(gè)錯(cuò)誤被會(huì)拋出。

vm.createContext([sandbox])

如果指定了一個(gè)sandbox對(duì)象,則將sandbox“上下文化”,這樣它才可以被vm.runInContextscript.runInContext使用。在腳本內(nèi)部,sandbox將會(huì)是全局對(duì)象,保留了它自己所有的屬性,并且包含內(nèi)建對(duì)象和標(biāo)準(zhǔn)全局對(duì)象的所有函數(shù)。在由vm模塊運(yùn)行的腳本之外的地方,sandbox將不會(huì)被改變。

如果沒(méi)有指定sandbox對(duì)象,將會(huì)返回一個(gè)你可以使用的新的,無(wú)內(nèi)容的sandbox對(duì)象。

這個(gè)函數(shù)在創(chuàng)建被用來(lái)運(yùn)行多個(gè)腳本的沙箱時(shí)十分有用,例如,如果你正在模擬一個(gè)web瀏覽器,則可以創(chuàng)建一個(gè)代表了window全局對(duì)象的沙箱,然后在沙箱內(nèi)運(yùn)行所有的<script>標(biāo)簽。

vm.isContext(sandbox)

返回一個(gè)沙箱是否已經(jīng)通過(guò)調(diào)用vm.createContext上下文化。

vm.runInContext(code, contextifiedSandbox[, options])

vm.runInContext編譯代碼,然后將其在contextifiedSandbox中運(yùn)行,然后返回結(jié)果。運(yùn)行的代碼不能訪問(wèn)本地作用域。contextifiedSandbox必須通過(guò)vm.createContext上下文化;它被用來(lái)當(dāng)做代碼的全局對(duì)象。

vm.runInContext的選項(xiàng)和vm.runInThisContext相同。

例子:編譯并執(zhí)行不同的腳本,在同一個(gè)已存在的上下文中。

var util = require('util');
var vm = require('vm');

var 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 }

注意,運(yùn)行不受信任的代碼是一個(gè)十分棘手的工作,需要十分小心。vm.runInContext是十分有用的,但是為了安全的運(yùn)行不受信任的代碼,還是將它們放在另一個(gè)單獨(dú)的進(jìn)程中為好。

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

vm.runInNewContext編譯代碼,接著,如果傳遞了sandbox則上下文化sandbox,如果沒(méi)有就創(chuàng)建一個(gè)新的已上下文化的沙箱,然后將沙箱作為全局對(duì)象運(yùn)行代碼并返回結(jié)果。

vm.runInNewContext的選項(xiàng)和vm.runInThisContext相同。

例子:編譯并執(zhí)行一個(gè) 自增一個(gè)全局變量然后設(shè)置一個(gè)新的全局變量 的代碼。這些全局變量包含在沙箱中。

var util = require('util');
var vm = require('vm');

var sandbox = {
  animal: 'cat',
  count: 2
};

vm.runInNewContext('count += 1; name = "kitty"', sandbox);
console.log(util.inspect(sandbox));

// { animal: 'cat', count: 3, name: 'kitty' }

注意,運(yùn)行不受信任的代碼是一個(gè)十分棘手的工作,需要十分小心。vm.runInNewContext是十分有用的,但是為了安全的運(yùn)行不受信任的代碼,還是將它們放在另一個(gè)單獨(dú)的進(jìn)程中為好。

vm.runInDebugContext(code)

vm.runInDebugContext編譯代碼,然后將它們?cè)赩8調(diào)試上下文中執(zhí)行。主要的用途是訪問(wèn)V8調(diào)試對(duì)象:

var Debug = vm.runInDebugContext('Debug');
Debug.scripts().forEach(function(script) { console.log(script.name); });

注意,調(diào)試上下文和對(duì)象與V8的調(diào)試實(shí)現(xiàn)聯(lián)系緊密,它們可能在沒(méi)有事先提醒的情況就發(fā)生改變(或被移除)。

調(diào)試對(duì)象也可以通過(guò)--expose_debug_as= switch被暴露。

Class: Script

一個(gè)包含預(yù)編譯代碼,然后將它們運(yùn)行在指定沙箱中的類(lèi)。

new vm.Script(code, options)

創(chuàng)建一個(gè)編譯代碼但不執(zhí)行它的新Script類(lèi)。也就是說(shuō),一個(gè)創(chuàng)建好的vm.Script對(duì)象代表了它的編譯完畢的代碼。這個(gè)腳本已經(jīng)通過(guò)下文的方法在晚些時(shí)候被調(diào)用多次。返回的腳本沒(méi)有被綁定在任何的全局對(duì)象上。它可以在每次運(yùn)行前被綁定,所以只在那次運(yùn)行時(shí)有效。

options可以有以下屬性:

  • filename: 允許你控制提供在堆棧追蹤信息中的文件名。
  • displayErrors: 是否在拋出異常前向stderr打印任何的錯(cuò)誤,并且造成錯(cuò)誤的行會(huì)被高亮。會(huì)捕獲編譯代碼時(shí)的語(yǔ)法錯(cuò)誤和運(yùn)行時(shí)由腳本的方法的配置所控制的代碼拋出的錯(cuò)誤。

script.runInThisContext([options])

vm.runInThisContext相似,但是是一個(gè)預(yù)編譯的Script對(duì)象的方法。script.runInThisContext運(yùn)行腳本被編譯完畢的代碼,然后返回結(jié)果。運(yùn)行中的代碼不能訪問(wèn)本地作用域,但是可以訪問(wèn)當(dāng)前的全局對(duì)象。

一個(gè)使用script.runInThisContext來(lái)編譯一次代碼,然后運(yùn)行多次的例子:

var vm = require('vm');

global.globalVar = 0;

var script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' });

for (var i = 0; i < 1000; ++i) {
  script.runInThisContext();
}

console.log(globalVar);

// 1000

options可以有以下屬性:

  • displayErrors: 是否在拋出異常前向stderr打印任何的錯(cuò)誤,并且造成錯(cuò)誤的行會(huì)被高亮。只會(huì)應(yīng)用于運(yùn)行中代碼的執(zhí)行錯(cuò)誤;創(chuàng)建一個(gè)有語(yǔ)法錯(cuò)誤的Script實(shí)例是不可能的,因?yàn)闃?gòu)造函數(shù)會(huì)拋出異常。

  • timeout: 在關(guān)閉之前,允許代碼執(zhí)行的時(shí)間(毫秒)。如果超時(shí),一個(gè)錯(cuò)誤被會(huì)拋出。

script.runInContext(contextifiedSandbox[, options])

vm.runInContext相似,但是是一個(gè)預(yù)編譯的Script對(duì)象的方法。script.runInContext運(yùn)行腳本被編譯完畢的代碼,然后返回結(jié)果。運(yùn)行中的代碼不能訪問(wèn)本地作用域。

script.runInContext的選項(xiàng)和script.runInThisContext相同。

例子:編譯一段 自增一個(gè)全局對(duì)象并且創(chuàng)建一個(gè)全局對(duì)象 的代碼,然后執(zhí)行多次,這些全局對(duì)象包含在沙箱中。

var util = require('util');
var vm = require('vm');

var sandbox = {
  animal: 'cat',
  count: 2
};

var context = new vm.createContext(sandbox);
var script = new vm.Script('count += 1; name = "kitty"');

for (var i = 0; i < 10; ++i) {
  script.runInContext(context);
}

console.log(util.inspect(sandbox));

// { animal: 'cat', count: 12, name: 'kitty' }

注意,運(yùn)行不受信任的代碼是一個(gè)十分棘手的工作,需要十分小心。script.runInContext是十分有用的,但是為了安全的運(yùn)行不受信任的代碼,還是將它們放在另一個(gè)單獨(dú)的進(jìn)程中為好。

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

vm.runInNewContext相似,但是是一個(gè)預(yù)編譯的Script對(duì)象的方法。如果傳遞了sandbox,script.runInNewContext將上下文化sandbox,如果沒(méi)有就創(chuàng)建一個(gè)新的已上下文化的沙箱,然后將沙箱作為全局對(duì)象運(yùn)行代碼并返回結(jié)果。運(yùn)行中的代碼不能訪問(wèn)本地作用域。

script.runInNewContext的選項(xiàng)和script.runInThisContext相同。

例子:編譯一段 設(shè)置一個(gè)全局對(duì)象 的代碼,然后在不同的上下文中多次執(zhí)行它。這些全局對(duì)象包含在沙箱中。

var util = require('util');
var vm = require('vm');

var sandboxes = [{}, {}, {}];

var script = new vm.Script('globalVar = "set"');

sandboxes.forEach(function (sandbox) {
  script.runInNewContext(sandbox);
});

console.log(util.inspect(sandboxes));

// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]

注意,運(yùn)行不受信任的代碼是一個(gè)十分棘手的工作,需要十分小心。script.runInNewContext是十分有用的,但是為了安全的運(yùn)行不受信任的代碼,還是將它們放在另一個(gè)單獨(dú)的進(jìn)程中為好。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)