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 相关文章推荐
TFDN图片播放器 不错自动播放
Oct 03 Javascript
JavaScript 设计模式 富有表现力的Javascript(一)
May 26 Javascript
jquery 添加节点的几种方法介绍
Sep 04 Javascript
JS获取IP、MAC和主机名的五种方法
Nov 14 Javascript
再探JavaScript作用域
Sep 24 Javascript
JS动态改变表格边框宽度的方法
Mar 31 Javascript
js时间戳格式化成日期格式的多种方法介绍
Feb 16 Javascript
教你用十行node.js代码读取docx的文本
Mar 08 Javascript
源码分析Vue.js的监听实现教程
Apr 23 Javascript
layui获取选中行数据的实例讲解
Aug 19 Javascript
element ui table 增加筛选的方法示例
Nov 02 Javascript
ES6的解构赋值实例详解
May 06 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
php入门学习知识点六 PHP文件的读写操作代码
2011/07/14 PHP
PHP设计模式 注册表模式
2012/02/05 PHP
PHP 设计模式系列之 specification规格模式
2016/01/10 PHP
PHP使用第三方即时获取物流动态实例详解
2017/04/27 PHP
jquery插件jbox使用iframe关闭问题
2009/02/09 Javascript
jQuery 遍历json数组的实现代码
2020/09/22 Javascript
原生javascript实现图片轮播效果代码
2010/09/03 Javascript
深入理解JavaScript系列(8) S.O.L.I.D五大原则之里氏替换原则LSP
2012/01/15 Javascript
Javascript模块化编程(一)模块的写法最佳实践
2013/01/17 Javascript
vue.js表格分页示例
2016/10/18 Javascript
Javascript同时声明一连串(多个)变量的方法
2017/01/23 Javascript
jQuery使用方法
2017/02/04 Javascript
JS失效 提示HTML1114: (UNICODE 字节顺序标记)的代码页 utf-8 覆盖(META 标记)的冲突的代码页 utf-8
2017/06/23 Javascript
jquery.rotate.js实现可选抽奖次数和中奖内容的转盘抽奖代码
2017/08/23 jQuery
Django中使用jquery的ajax进行数据交互的实例代码
2017/10/15 jQuery
JS/HTML5游戏常用算法之碰撞检测 地图格子算法实例详解
2018/12/12 Javascript
vue.js的简单自动求和计算实例
2019/11/08 Javascript
SpringBoot+Vue开发之Login校验规则、实现登录和重置事件
2020/10/19 Javascript
[01:16]2014DOTA2 TI专访C9战队EE:中国五强中会占三席
2014/07/10 DOTA
在树莓派2或树莓派B+上安装Python和OpenCV的教程
2015/03/30 Python
python简单分割文件的方法
2015/07/30 Python
深入源码解析Python中的对象与类型
2015/12/11 Python
Python selenium根据class定位页面元素的方法
2019/02/26 Python
Python数据类型之String字符串实例详解
2019/05/08 Python
python登录WeChat 实现自动回复实例详解
2019/05/28 Python
使用Django和Postgres进行全文搜索的实例代码
2020/02/13 Python
Expedia挪威官网:酒店、机票和租车
2018/03/03 全球购物
什么是smarty? Smarty的优点是什么?
2013/08/11 面试题
应聘美工求职信
2013/11/07 职场文书
董事长职责范文
2013/11/08 职场文书
会计的岗位职责
2014/03/15 职场文书
关爱残疾人演讲稿
2014/05/24 职场文书
乡党政领导班子群众路线教育实践活动个人对照检查材料
2014/09/20 职场文书
教师三严三实学习心得体会
2014/10/11 职场文书
企业务虚会发言材料
2014/10/20 职场文书
2014年个人师德工作总结
2014/12/04 职场文书