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 相关文章推荐
javascript div 弹出可拖动窗口
Feb 26 Javascript
javascript 写类方式之八
Jul 05 Javascript
juqery 学习之三 选择器 简单 内容
Nov 25 Javascript
ASP.NET中基于JQUERY的高性能的TreeView补充
Feb 23 Javascript
基于jquery的横向滚动条(滑动条)
Feb 24 Javascript
简短几句jquery代码的实现一个图片向上滚动切换
Sep 02 Javascript
HTML页面滚动时获取离页面顶部的距离2种实现方法
Sep 05 Javascript
键盘上一张下一张兼容IE/google/firefox等浏览器
Jan 28 Javascript
JS实现选择TextArea内文本的方法
Aug 03 Javascript
jQuery实现模拟flash头像裁切上传功能示例
Dec 11 Javascript
JavaScript Image对象实现原理实例解析
Aug 26 Javascript
ES6的循环与可迭代对象示例详解
Jan 31 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
Protoss建筑一览
2020/03/14 星际争霸
PHP下MAIL的另一解决方案
2006/10/09 PHP
如何写php程序?
2006/12/08 PHP
PHP stripos()函数及注意事项的分析
2013/06/08 PHP
如何把php5.3版本升级到php5.4或者php5.5
2015/07/31 PHP
jquery ajax学习笔记2 使用XMLHttpRequest对象的responseXML
2011/10/16 Javascript
javascript 保存文件到本地实现方法
2012/11/29 Javascript
JavaScript中九种常用排序算法
2014/09/02 Javascript
angularjs指令中的compile与link函数详解
2014/12/06 Javascript
jquery如何获取元素的滚动条高度等实现代码
2015/10/19 Javascript
JavaScript 栈的详解及实例代码
2017/01/22 Javascript
webpack独立打包和缓存处理详解
2017/04/03 Javascript
webpack 单独打包指定JS文件的方法
2018/02/22 Javascript
如何阻止小程序遮罩层下方图层滚动
2019/09/05 Javascript
vue多页面项目中路由使用history模式的方法
2019/09/23 Javascript
js实现简单贪吃蛇游戏
2020/05/15 Javascript
python使用递归解决全排列数字示例
2014/02/11 Python
Python脚本获取操作系统版本信息
2016/12/17 Python
python的多重继承的理解
2017/08/06 Python
Python调用ctypes使用C函数printf的方法
2017/08/23 Python
pandas.DataFrame 根据条件新建列并赋值的方法
2018/04/08 Python
Python使用wget实现下载网络文件功能示例
2018/05/31 Python
Python面向对象总结及类与正则表达式详解
2019/04/18 Python
Pycharm激活方法及详细教程(详细且实用)
2020/05/12 Python
python3 循环读取excel文件并写入json操作
2020/07/14 Python
python链表类中获取元素实例方法
2021/02/23 Python
使用pandas读取表格数据并进行单行数据拼接的详细教程
2021/03/03 Python
AE美国鹰日本官方网站: American Eagle Outfitters
2016/12/10 全球购物
澳大利亚宠物食品和用品商店:PETstock
2020/01/02 全球购物
物业管理专业个人的自我评价
2013/11/19 职场文书
企业党建工作汇报材料
2014/08/19 职场文书
司法局群众路线教育实践活动整改措施思想汇报
2014/10/13 职场文书
2015世界地球日活动总结
2015/02/09 职场文书
学生党支部工作总结2015
2015/05/26 职场文书
干部理论学习心得体会
2016/01/21 职场文书
如何理解python接口自动化之logging日志模块
2021/06/15 Python