Node.js API详解之 vm模块用法实例分析


Posted in Javascript onMay 27, 2020

本文实例讲述了Node.js API详解之 vm模块用法。分享给大家供大家参考,具体如下:

Node.js API详解之 vm

vm 模块提供了一系列 API 用于在 V8 虚拟机环境中编译和运行代码。
JavaScript 代码可以被编译并立即运行,或编译、保存然后再运行。
常见的用法是在沙盒中运行代码。沙盒代码使用不同的V8上下文。

const vm = require('vm');
const x = 1;
const sandbox = { x: 2 };
vm.createContext(sandbox); // Contextify the sandbox.
const code = 'x += 40; var y = 17;';
// x and y are global variables in the sandboxed environment.
// Initially, x has the value 2 because that is the value of sandbox.x.
vm.runInContext(code, sandbox);
console.log(sandbox.x); // 42
console.log(sandbox.y); // 17
console.log(x); // 1; y is not defined.

注意: vm模块并不是实现代码安全性的一套机制。 绝不要试图用其运行未经信任的代码.

vm.createContext([sandbox])

说明:

vm.createContext()主要是用于创建一个能运行多个脚本的sandbox。
比如说,在模拟一个网页浏览器时,此方法可以被用于创建一个单独的sandbox来代表一个窗口的全局对象,然后所有的script标签都可以在这个sandbox的上下文中运行。
给定一个sandbox对象, vm.createContext()会设置此sandbox,
从而让它具备在vm.runInContext()或者script.runInContext()中被使用的能力。
如果未提供sandbox(或者传入undefined),那么会返回一个全新的,空的,上下文隔离化后的sandbox对象。
对于此方法中所调用的脚本,他们的全局对象不仅拥有我们提供的sandbox对象的所有属性,同时还有任何global object所拥有的属性。
对于这些脚本之外的所有代码,他们的全局变量将保持不变。

demo:

const util = require('util');
const vm = require('vm');
global.globalVar = 3;
const sandbox = { globalVar: 1 };
vm.createContext(sandbox);
vm.runInContext('globalVar *= 2;', sandbox);
console.log(util.inspect(sandbox)); // { globalVar: 2 }
console.log(util.inspect(globalVar)); // 3

vm.isContext(sandbox)

说明:

当给定的sandbox对象已经被vm.createContext()上下文隔离化,则返回真。

demo:

const util = require('util');
const vm = require('vm');
global.globalVar = 3;
const sandbox = { globalVar: 1 };
vm.createContext(sandbox);
console.log(vm.isContext(sandbox));
// true

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

说明:

code:将被编译和运行的JavaScript代码
contextifiedSandbox:一个被上下文隔离化过的对象,会在代码被编译和执行之后充当global对象
options:
filename:定义供脚本生成的堆栈跟踪信息所使用的文件名
lineOffset:定义脚本生成的堆栈跟踪信息所显示的行号偏移
columnOffset:定义脚本生成的堆栈跟踪信息所显示的列号偏移
displayErrors:当值为真的时候,假如在解析代码的时候发生错误Error,引起错误的行将会被加入堆栈跟踪信息
timeout:定义在被终止执行之前此code被允许执行的最大毫秒数。假如执行被终止,将会抛出一个错误Error
vm.runInContext()在指定的contextifiedSandbox的上下文里执行vm.Script对象中被编译后的代码并返回其结果。
被执行的代码无法获取本地作用域。contextifiedSandbox必须是事先被vm.createContext()上下文隔离化过的对象。

demo:

const util = require('util');
const vm = require('vm');
global.globalVar = 3;
const sandbox = { globalVar: 1 };
vm.createContext(sandbox);
vm.runInContext('globalVar *= 2;', sandbox);
console.log(util.inspect(sandbox)); 
// { globalVar: 2 }

vm.runInDebugContext(code)(已废弃)

说明:

vm.runInDebugContext()会在V8的调试上下文中编译并执行code。此方法主要在需要获取V8Debug对象的时候使用。
注意: 调试上下文和对象从本质而言是从属于V8调试器的,故有可能会在没有事先警告的情况下被改变(甚至被移除)
Debug对象另外还可以通过特定于V8的?expose_debug_as命令行选项获得。

demo:

const vm = require('vm')
const Debug = vm.runInDebugContext('Debug');
console.log(Debug.findScript(process.emit).name); // 'events.js'
console.log(Debug.findScript(process.exit).name); // 'internal/process.js'

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

说明:

首先给指定的sandbox(若为undefined,则会新建一个sandbox)提供一个隔离的上下文,
再在此上下文中执行vm.Script中被编译的代码,最后返回结果。运行中的代码无法获取本地作用域。

demo:

const util = require('util');
const vm = require('vm');
const sandbox = {
 animal: 'cat',
 count: 2
};
vm.runInNewContext('count += 1; name = "kitty"', sandbox);
console.log(util.inspect(sandbox));
// { animal: 'cat', count: 3, name: 'kitty' }

vm.runInThisContext(code[, options])

说明:

vm.runInThisContext()在当前的global对象的上下文中编译并执行code,最后返回结果。
运行中的代码无法获取本地作用域,但可以获取当前的global对象。

demo:

const vm = require('vm');
let localVar = 'initial value';
const vmResult = vm.runInThisContext('localVar = "vm";');
console.log('vmResult:', vmResult);
console.log('localVar:', localVar);
const evalResult = eval('localVar = "eval";');
console.log('evalResult:', evalResult);
console.log('localVar:', localVar);
// vmResult: 'vm', localVar: 'initial value'
// evalResult: 'eval', localVar: 'eval'

vm.Script 类

说明:

vm.Script类型的实例包含若干预编译的脚本,这些脚本能够在特定的沙箱(或者上下文)中被运行。

new vm.Script(code, options)

说明:

创建一个新的vm.Script对象只编译代码但不会执行它。编译过的vm.Script此后可以被多次执行。
值得注意的是,code是不绑定于任何全局对象的,相反,它仅仅绑定于每次执行它的对象。
code:要被解析的JavaScript代码
options:
filename:定义供脚本生成的堆栈跟踪信息所使用的文件名
lineOffset:定义脚本生成的堆栈跟踪信息所显示的行号偏移
columnOffset:定义脚本生成的堆栈跟踪信息所显示的列号偏移
displayErrors:当值为真的时候,假如在解析代码的时候发生错误Error,引起错误的行将会被加入堆栈跟踪信息
timeout:定义在被终止执行之前此code被允许执行的最大毫秒数。假如执行被终止,将会抛出一个错误[Error][]。
cachedData:为源码提供一个可选的存有v8代码缓存数据的Buffer。一旦提供了此Buffer,取决于v8引擎对Buffer中数据的接受状况,cachedDataRejected值将会被设为要么 真要么为假。
produceCachedData:当值为真且cachedData不存在的时候,v8将会试图为code生成代码缓存数据。一旦成功,一个有V8代码缓存数据的Buffer将会被生成和储存在vm.Script返回的实例的cachedData属性里。 取决于代码缓存数据是否被成功生成,cachedDataProduced的值会被设置为true或者false。

demo:

const util = require('util');
const vm = require('vm');
const sandbox = {
 animal: 'cat',
 count: 2
};
const script = new vm.Script('count += 1; name = "kitty";');
const context = vm.createContext(sandbox);
script.runInContext(context);
console.log(util.inspect(sandbox));
// { animal: 'cat', count: 3, name: 'kitty' }

script.runInContext(contextifiedSandbox[, options])

说明:

在指定的contextifiedSandbox中执行vm.Script对象中被编译后的代码并返回其结果。
被执行的代码无法获取本地作用域。
contextifiedSandbox:由vm.createContext()返回的[contextified][]对象

demo:

const util = require('util');
const vm = require('vm');
const sandbox = {
 animal: 'cat',
 count: 2
};
const script = new vm.Script('count += 1; name = "kitty";');
const context = vm.createContext(sandbox);
for (let i = 0; i < 10; ++i) {
 script.runInContext(context);
}
console.log(util.inspect(sandbox));
// { animal: 'cat', count: 12, name: 'kitty' }

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

说明:

首先给指定的sandbox提供一个隔离的上下文, 再在此上下文中执行vm.Script中被编译的代码,最后返回结果。
运行中的代码无法获取本地作用域。

demo:

const util = require('util');
const vm = require('vm');
const script = new vm.Script('globalVar = "set"');
const sandboxes = [{}, {}, {}];
sandboxes.forEach((sandbox) => {
 script.runInNewContext(sandbox);
});
console.log(util.inspect(sandboxes));
// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]

script.runInThisContext([options])

说明:

在指定的global对象的上下文中执行vm.Script对象里被编译的代码并返回其结果。
被执行的代码虽然无法获取本地作用域,但是能获取global对象。

demo:

const vm = require('vm');
global.globalVar = 0;
const script = new vm.Script('globalVar += 1');
for (let i = 0; i < 1000; ++i) {
 script.runInThisContext();
}
console.log(globalVar);
// 1000

例子:在vm中运行一个http server

'use strict';
const vm = require('vm');
const code = `
(function(require) {
 const http = require('http');
 http.createServer((request, response) => {
  response.writeHead(200, { 'Content-Type': 'text/plain' });
  response.end('Hello World\\n');
 }).listen(8124);
 console.log('Server running at http://127.0.0.1:8124/');
})`;
vm.runInThisContext(code)(require);

希望本文所述对大家node.js程序设计有所帮助。

Javascript 相关文章推荐
从jQuery.camelCase()学习string.replace() 函数学习
Sep 13 Javascript
jQuery+CSS 半开折叠效果原理及代码(自写)
Mar 04 Javascript
javascript中如何处理引号编码&amp;#034;
Aug 15 Javascript
实例说明为什么不要行内使用javascript
Apr 18 Javascript
jquery实现搜索框常见效果的方法
Jan 22 Javascript
分享9点个人认为比较重要的javascript 编程技巧
Apr 27 Javascript
JS实现可展开折叠层的鼠标拖曳效果
Oct 09 Javascript
JavaScript判断对象是否为数组
Dec 22 Javascript
js日期插件dateHelp获取本月、三个月、今年的日期
Mar 07 Javascript
seajs学习教程之基础篇
Oct 20 Javascript
Bootstrap中datetimepicker使用小结
Dec 28 Javascript
Vue 3.0中jsx语法的使用
Nov 13 Javascript
jQuery实现鼠标滑动切换图片
May 27 #jQuery
js验证账户名是否重复
May 26 #Javascript
小程序富文本提取图片可放大缩小
May 26 #Javascript
微信小程序自定义联系人弹窗
May 26 #Javascript
微信小程序单选框自定义赋值
May 26 #Javascript
vue输入框使用模糊搜索功能的实现代码
May 26 #Javascript
jQuery弹框插件使用方法详解
May 26 #jQuery
You might like
苏联队长,苏联超人蝙蝠侠,这些登场的“山寨”英雄真的很严肃
2020/04/09 欧美动漫
完美解决dedecms中的[html][/html]和[code][/code]问题
2007/03/20 PHP
php生成zip压缩文件的方法详解
2013/06/09 PHP
简述php环境搭建与配置
2016/12/05 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
google地图的路线实现代码
2009/08/20 Javascript
js function使用心得
2010/05/10 Javascript
分享8款优秀的 jQuery 加载动画和进度条插件
2012/10/24 Javascript
JavaScript代码复用模式实例分析
2012/12/02 Javascript
NodeJS与Mysql的交互示例代码
2013/08/18 NodeJs
jquery如何实现在加载完iframe的内容后再进行操作
2013/09/10 Javascript
js中arguments的用法(实例讲解)
2013/11/30 Javascript
JavaScript弹出新窗口并控制窗口移动到指定位置的方法
2015/04/06 Javascript
如何实现移动端浏览器不显示 pc 端的广告
2015/10/15 Javascript
使用jQuery获取data-的自定义属性
2015/11/10 Javascript
jQuery ajax中使用confirm,确认是否删除的简单实例
2016/06/17 Javascript
AngularJS 模块详解及简单实例
2016/07/28 Javascript
flag和jq on 的绑定多个对象和方法(必看)
2017/02/27 Javascript
微信小程序 下拉菜单简单实例
2017/04/13 Javascript
使用Bootstrap和Vue实现用户信息的编辑删除功能
2017/10/25 Javascript
Vue2.0 实现歌手列表滚动及右侧快速入口功能
2018/08/08 Javascript
Vue项目中使用jsonp抓取跨域数据的方法
2019/11/10 Javascript
Python中捕捉详细异常信息的代码示例
2014/09/18 Python
代码分析Python地图坐标转换
2018/02/08 Python
Python函数和模块的使用总结
2019/05/20 Python
Pandas直接读取sql脚本的方法
2021/01/21 Python
使用css3实现的tab选项卡代码分享
2014/12/09 HTML / CSS
HTML5 UTF-8 中文乱码的解决方法
2013/11/18 HTML / CSS
MediaMarkt比利时:欧洲最大电器连锁店
2020/12/21 全球购物
Java面试中常遇到的问题,也是需要注意的几点
2013/08/30 面试题
大学军训自我鉴定
2013/12/15 职场文书
安全例会汇报材料
2014/08/23 职场文书
法务专员岗位职责
2015/02/14 职场文书
Java org.w3c.dom.Document 类方法引用报错
2021/08/07 Java/Android
Go 语言中 20 个占位符的整理
2021/10/16 Golang
TypeScript实用技巧 Nominal Typing名义类型详解
2022/09/23 Javascript