Node VM#
node.js VM 模組#
VM 是 node.js 的核心模組,提供安全的環境 (沙箱) 來測試不信任的程式碼。
基本概念#
在 VM 模組裡面,有兩個基本的物件,script 和 context。script 是經過「編譯」程式,context 是給在沙箱裡面的程式碼的全域物件 (global) 。沙箱中的程式只能存取透過 context 指定的物件。
建立 script#
VM 模組提供 Script
建構子,可以透過他來建立 Script
物件。
const vm = require('vm');
const script = new vm.Script('i++');
js也可以用 vm.createScript
const vm = require('vm');
const script = vm.createScript('i++');
jsvm.Script ↗
vm.createScript 在 nodejs docs 上我沒有找到,但是我在自己的電腦上 (node v14.15.0) 測試是可以用的
建立 context#
vm 模組沒有提供建立 context 的建構子,我們只能透過 vm.createContext
來建立 context。
注意 vm.createContext
不是 pure function,除了會回傳 context 以外,還會把傳入的物件變成 context,兩者傳入 vm.isContext
都會回傳 true
。
const vm = require('vm');
const context1 = { i: 0 };
const context2 = vm.createContext(context1);
vm.isContext(context1); // true
vm.isContext(context2); // true
// 注意,其實 context1 和 context2 指向同一個物件。
context1 === context2; // true
js執行 script (預先編譯 Script)#
最基本的函式是 script.runInContext
,它會把傳入的 context 當作 vm 的全域執行裡面的程式,script 的最後一個表達式的回傳值會被當作這次執行的回傳值。
下面的範例,會把 context 中的 i
複製一遍後回傳他的值和長度。
const vm = require('vm');
const script = vm.createScript('i += i; [i, i.length]');
const context = vm.createContext({ i: 'node' });
script.runInContext(context); // [ 'nodenode', 8 ]
js如果沒有事先準備 context,可以用 script.runInNewContext
,直接把還沒 contextify ↗ 物件傳進來,這個函式會
自動建立 context。這個參數是可略的,如果沒傳物件進進來的話,context 就會是空物件。
如果想要讓 script 直接存取全域物件的話,可以用 script.runInThisContext
。這個函式不接受 context,因為 context 就是全域 (this) 了。
method | context |
---|---|
runInContext | contextified object |
runInNewContext | any Object |
runInThisContext | 不用傳,this |
執行 script (沒有預先編譯 Script)#
如果你很懶,或是你只是想要一次行的執行這段 code,可以用 vm.runInContext
、vm.runInNewContext
和 vm.runInThisContext
。用法跟先編譯過再執行一樣,只是其中第一個參數變成還沒編譯過的 code (String)。