鍍金池/ 教程/ HTML/ 虛擬機(jī)
模塊
斷言測(cè)試
Buffer
Smalloc
TTY
概述
REPL
HTTP
DNS
路徑
集群
TLS/SSL
系統(tǒng)
加密
調(diào)試器
進(jìn)程
Punycode
虛擬機(jī)
HTTPS
網(wǎng)絡(luò)
Query String
C/C++ 插件
實(shí)用工具
文件系統(tǒng)
Zlib
子進(jìn)程
UDP/Datagram Sockets
定時(shí)器
逐行讀取
字符串解碼器
全局對(duì)象
事件
URL
控制臺(tái)

虛擬機(jī)

穩(wěn)定性: 3 - 穩(wěn)定

可以通過(guò)以下方法訪問(wèn)該模塊:

var vm = require('vm');

JavaScript 可以立即編譯立即執(zhí)行,也可以編譯,保存,之后再運(yùn)行。

vm.runInThisContext(code[, options])

vm.runInThisContext() 對(duì) 參數(shù)code 編譯,運(yùn)行并返回結(jié)果。 運(yùn)行的代碼沒(méi)有權(quán)限訪問(wèn)本地作用域(local scope),但是可以訪問(wèn)全局對(duì)象。

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

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 沒(méi)有訪問(wèn)本地作用域,所以沒(méi)有改變 localVar。 eval 范圍了本地作用域,所以改變了 localVar。

vm.runInThisContext 用起來(lái)很像間接調(diào)用 eval,比如 (0,eval)('code')。但是,vm.runInThisContext 也包含以下選項(xiàng):

  • filename: 允許更改顯示在站追蹤(stack traces)的文件名。
  • displayErrors: 是否在 stderr 上打印錯(cuò)誤,拋出異常的代碼行高亮顯示。會(huì)捕獲編譯時(shí)的語(yǔ)法錯(cuò)誤,和執(zhí)行時(shí)拋出的錯(cuò)誤。默認(rèn)為 true。
  • timeout: 中斷前代碼執(zhí)行的毫秒數(shù)。如果執(zhí)行終止,將會(huì)拋出錯(cuò)誤。

vm.createContext([sandbox])

如果參數(shù) sandbox 不為空,調(diào)用 vm.runInContextscript.runInContext 時(shí)可以調(diào)用沙箱的上下文。以此方式運(yùn)行的腳本,sandbox 是全局對(duì)象,它保留自己的屬性同時(shí)擁有標(biāo)準(zhǔn)全局對(duì)象(global object)擁有的內(nèi)置對(duì)象和函數(shù)。

如果參數(shù) sandbox 對(duì)象為空,返回一個(gè)可用的新且空的上下文相關(guān)的沙盒對(duì)象。

這個(gè)函數(shù)對(duì)于創(chuàng)建一個(gè)可運(yùn)行多腳本的沙盒非常有用。比如,在模擬瀏覽器的時(shí)候可以使用該函數(shù)創(chuàng)建一個(gè)用于表示 window 全局對(duì)象的沙箱,并將所有 <script> 標(biāo)簽放入沙箱執(zhí)行。

vm.isContext(sandbox)

沙箱對(duì)象是否已經(jīng)通過(guò)調(diào)用 vm.createContext 上下文化。

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

vm.runInContext 編譯代碼,運(yùn)行在 contextifiedSandbox 并返回結(jié)果。運(yùn)行代碼不能訪問(wèn)本地域。contextifiedSandbox 對(duì)象必須通過(guò) vm.createContext 上下文化;code 會(huì)通過(guò)全局變量使用它。

vm.runInContextvm.runInThisContext 參數(shù)相同。

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

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 }

注意,執(zhí)行不被信任的代碼是需要技巧且要非常的小心。vm.runInContext 非常有用,不過(guò)想要安全些,最好還是在獨(dú)立的進(jìn)程里運(yùn)行不被信任的代碼。

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

vm.runInNewContext 編譯代碼, 如果提供了 sandbox ,則將 sandbox 上下文化,否則創(chuàng)建一個(gè)新的上下文化過(guò)的沙盒,將沙盒作為全局變量運(yùn)行代碼并返回結(jié)果。

vm.runInNewContextvm.runInThisContext 參數(shù)相同。

編譯并執(zhí)行代碼,增加全局變量值,并設(shè)置一個(gè)新的。這些全局變量包含在一個(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' }

注意,執(zhí)行不被信任的代碼是需要技巧且要非常的小心。vm.runInNewContext 非常有用,不過(guò)想要安全些,最好還是在獨(dú)立的進(jìn)程里運(yùn)行不被信任的代碼。

vm.runInDebugContext(code)

vm.runInDebugContext 在 V8 的調(diào)試上下文中編譯并執(zhí)行。最主要的應(yīng)用場(chǎng)景是獲得 V8 調(diào)試對(duì)象訪問(wèn)權(quán)限。

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

注意,調(diào)試上下文和對(duì)象內(nèi)部綁定到 V8 的調(diào)試實(shí)現(xiàn)里,并可能在沒(méi)有警告時(shí)改變(或移除)。

可以通過(guò) --expose_debug_as= 開(kāi)關(guān)暴露調(diào)試對(duì)象。

Class: Script

包含預(yù)編譯腳本的類(lèi),并在指定的沙盒里執(zhí)行。

new vm.Script(code, options)

創(chuàng)建一個(gè)新的腳本編譯代碼,但是不運(yùn)行。使用被創(chuàng)建的 vm.Script 來(lái)表示編譯完的代碼。這個(gè)代碼可以使用以下的方法調(diào)用多次。返回的腳本沒(méi)有綁定到任何全局變量。在運(yùn)行前綁定,執(zhí)行后釋放。

創(chuàng)建腳本的選項(xiàng)有:

  • filename: 允許更改顯示在站追蹤(stack traces)的文件名。
  • displayErrors: 是否在 stderr 上打印錯(cuò)誤,拋出異常的代碼行高亮顯示。只會(huì)捕獲編譯時(shí)的語(yǔ)法錯(cuò)誤,執(zhí)行時(shí)拋出的錯(cuò)誤由腳本的方法的選項(xiàng)來(lái)控制。默認(rèn)為 true

script.runInThisContext([options])

vm.runInThisContext 類(lèi)似,只是作為 Script 腳本對(duì)象的預(yù)編譯方法。script.runInThisContext 執(zhí)行編譯過(guò)的腳本并返回結(jié)果。被運(yùn)行的代碼沒(méi)有本地作用域訪問(wèn)權(quán)限,但是擁有權(quán)限訪問(wèn)全局對(duì)象。

以下例子,使用 script.runInThisContext 編譯代碼一次,并運(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

所運(yùn)行的代碼選項(xiàng):

  • displayErrors: 是否在 stderr 上打印錯(cuò)誤,拋出異常的代碼行高亮顯示。僅適用于執(zhí)行時(shí)拋出的錯(cuò)誤。不能創(chuàng)建一個(gè)語(yǔ)法錯(cuò)誤的 Script 實(shí)例,因?yàn)闃?gòu)造函數(shù)會(huì)拋出。
  • timeout: 中斷前代碼執(zhí)行的毫秒數(shù)。如果執(zhí)行終止,將會(huì)拋出錯(cuò)誤。

script.runInContext(contextifiedSandbox[, options])

vm.runInContext 類(lèi)似,只是作為預(yù)編譯的 Script 對(duì)象方法。script.runInContext 運(yùn)行腳本(在 contextifiedSandbox 中編譯)并返回結(jié)果。運(yùn)行的代碼沒(méi)有權(quán)限訪問(wèn)本地域。

script.runInContext 的選項(xiàng)和 script.runInThisContext 類(lèi)似。

例子: 編譯一段代碼,并執(zhí)行多次,這段代碼實(shí)現(xiàn)了一個(gè)全局變量的自增,并創(chuàng)建一個(gè)新的全局變量。這些全局變量保存在沙盒里。

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

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

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

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

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

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

注意,執(zhí)行不被信任的代碼是需要技巧且要非常的小心。script.runInContext 非常有用,不過(guò)想要安全些,最好還是在獨(dú)立的進(jìn)程里運(yùn)行不被信任的代碼。

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

vm.runInNewContext 類(lèi)似,只是作為預(yù)編譯的 Script 對(duì)象方法。 若提供 sandbox 則 script.runInNewContext 將 sandbox 上下文化,若未提供,則創(chuàng)建一個(gè)新的上下文化的沙箱。

script.runInNewContextscript.runInThisContext 的參數(shù)類(lèi)似。

例子: 編譯代碼(設(shè)置了一個(gè)全局變量)并在不同的上下文里執(zhí)行多次。這些全局變量會(huì)被保存在沙箱中。

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' }]

注意,執(zhí)行不被信任的代碼是需要技巧且要非常的小心。script.runInNewContext 非常有用,不過(guò)想要安全些,最好還是在獨(dú)立的進(jìn)程里運(yùn)行不被信任的代碼。

上一篇:Buffer下一篇:概述