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 相关文章推荐
AngularJS入门教程(二):AngularJS模板
Dec 06 Javascript
js实现横向伸展开的二级导航菜单代码
Aug 28 Javascript
JavaScript简单下拉菜单实例代码
Sep 07 Javascript
Bootstrap布局方式详解
May 27 Javascript
Jquery Easyui选项卡组件Tab使用详解(10)
Dec 18 Javascript
Vuex利用state保存新闻数据实例
Jun 28 Javascript
详解微信小程序设置底部导航栏目方法
Jun 29 Javascript
vue-router 组件复用问题详解
Jan 22 Javascript
js实现指定时间倒计时效果
Aug 26 Javascript
Vue路由守卫及页面登录权限控制的设置方法(两种)
Mar 31 Javascript
JS+canvas五子棋人机对战实现步骤详解
Jun 04 Javascript
基于JS实现操作成功之后自动跳转页面
Sep 25 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
【COS正片】蕾姆睡衣cos,纯洁可爱被治愈了 cn名濑弥七
2020/03/02 日漫
用户的详细注册和判断
2006/10/09 PHP
又一个php 分页类实现代码
2009/12/03 PHP
Zend的AutoLoad机制介绍
2012/09/27 PHP
php天翼开放平台短信发送接口实现方法
2014/12/22 PHP
PHP 实现从数据库导出到.csv文件方法
2017/07/06 PHP
jquery 必填项判断表单是否为空的方法
2008/09/14 Javascript
jQuery 写的简单打字游戏可以提示正确和错误的次数
2014/07/01 Javascript
浅谈JavaScript的Polymer框架中的事件绑定
2015/07/29 Javascript
Jsonp 关键字详解及json和jsonp的区别,ajax和jsonp的区别
2015/12/30 Javascript
果断收藏9个Javascript代码高亮脚本
2016/01/06 Javascript
javascript 常用验证函数总结
2016/06/28 Javascript
bootstrap制作jsp页面(根据值让table显示选中)
2017/01/05 Javascript
vue axios 在页面切换时中断请求方法 ajax
2018/03/05 Javascript
Vue 实现树形视图数据功能
2018/05/07 Javascript
vue打包的时候自动将px转成rem的操作方法
2018/06/20 Javascript
bootstrap table表格插件之服务器端分页实例代码
2018/09/12 Javascript
jQuery表单选择器用法详解
2019/08/22 jQuery
jQuery实现提交表单时不提交隐藏div中input的方法
2019/10/08 jQuery
基于node+vue实现简单的WebSocket聊天功能
2020/02/01 Javascript
在vue中使用image-webpack-loader实例
2020/11/12 Javascript
Python计时相关操作详解【time,datetime】
2017/05/26 Python
利用Python库Scapy解析pcap文件的方法
2019/07/23 Python
全球知名鞋履品牌授权零售商:Journeys
2016/09/17 全球购物
幼儿园秋游感想
2014/03/12 职场文书
学习全国两会精神心得体会范文
2014/03/17 职场文书
幼儿园招生广告
2014/03/19 职场文书
优秀党务工作者事迹材料
2014/05/07 职场文书
奥巴马获胜演讲稿
2014/05/15 职场文书
2014年教师节讲话稿5篇
2014/09/10 职场文书
2014教师教育实践活动对照检查材料思想汇报
2014/09/21 职场文书
群众路线剖析材料(四风问题)
2014/10/08 职场文书
沈阳故宫导游词
2015/01/31 职场文书
民间借贷被告代理词
2015/05/23 职场文书
新农村建设指导员工作总结
2015/08/13 职场文书
一文带你探究MySQL中的NULL
2021/11/11 MySQL