Node.js API详解之 vm模块用法实例分析
本文实例讲述了Node.jsAPI详解之vm模块用法。分享给大家供大家参考,具体如下:
Node.jsAPI详解之vm
vm模块提供了一系列API用于在V8虚拟机环境中编译和运行代码。
JavaScript代码可以被编译并立即运行,或编译、保存然后再运行。
常见的用法是在沙盒中运行代码。沙盒代码使用不同的V8上下文。
constvm=require('vm'); constx=1; constsandbox={x:2}; vm.createContext(sandbox);//Contextifythesandbox. constcode='x+=40;vary=17;'; //xandyareglobalvariablesinthesandboxedenvironment. //Initially,xhasthevalue2becausethatisthevalueofsandbox.x. vm.runInContext(code,sandbox); console.log(sandbox.x);//42 console.log(sandbox.y);//17 console.log(x);//1;yisnotdefined.
注意:vm模块并不是实现代码安全性的一套机制。绝不要试图用其运行未经信任的代码.
vm.createContext([sandbox])
说明:
vm.createContext()主要是用于创建一个能运行多个脚本的sandbox。
比如说,在模拟一个网页浏览器时,此方法可以被用于创建一个单独的sandbox来代表一个窗口的全局对象,然后所有的script标签都可以在这个sandbox的上下文中运行。
给定一个sandbox对象,vm.createContext()会设置此sandbox,
从而让它具备在vm.runInContext()或者script.runInContext()中被使用的能力。
如果未提供sandbox(或者传入undefined),那么会返回一个全新的,空的,上下文隔离化后的sandbox对象。
对于此方法中所调用的脚本,他们的全局对象不仅拥有我们提供的sandbox对象的所有属性,同时还有任何globalobject所拥有的属性。
对于这些脚本之外的所有代码,他们的全局变量将保持不变。
demo:
constutil=require('util'); constvm=require('vm'); global.globalVar=3; constsandbox={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:
constutil=require('util'); constvm=require('vm'); global.globalVar=3; constsandbox={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:
constutil=require('util'); constvm=require('vm'); global.globalVar=3; constsandbox={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:
constvm=require('vm') constDebug=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:
constutil=require('util'); constvm=require('vm'); constsandbox={ 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:
constvm=require('vm'); letlocalVar='initialvalue'; constvmResult=vm.runInThisContext('localVar="vm";'); console.log('vmResult:',vmResult); console.log('localVar:',localVar); constevalResult=eval('localVar="eval";'); console.log('evalResult:',evalResult); console.log('localVar:',localVar); //vmResult:'vm',localVar:'initialvalue' //evalResult:'eval',localVar:'eval'
vm.Script类
说明:
vm.Script类型的实例包含若干预编译的脚本,这些脚本能够在特定的沙箱(或者上下文)中被运行。
newvm.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:
constutil=require('util'); constvm=require('vm'); constsandbox={ animal:'cat', count:2 }; constscript=newvm.Script('count+=1;name="kitty";'); constcontext=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:
constutil=require('util'); constvm=require('vm'); constsandbox={ animal:'cat', count:2 }; constscript=newvm.Script('count+=1;name="kitty";'); constcontext=vm.createContext(sandbox); for(leti=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:
constutil=require('util'); constvm=require('vm'); constscript=newvm.Script('globalVar="set"'); constsandboxes=[{},{},{}]; 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:
constvm=require('vm'); global.globalVar=0; constscript=newvm.Script('globalVar+=1'); for(leti=0;i<1000;++i){ script.runInThisContext(); } console.log(globalVar); //1000
例子:在vm中运行一个httpserver
'usestrict'; constvm=require('vm'); constcode=` (function(require){ consthttp=require('http'); http.createServer((request,response)=>{ response.writeHead(200,{'Content-Type':'text/plain'}); response.end('HelloWorld\\n'); }).listen(8124); console.log('Serverrunningathttp://127.0.0.1:8124/'); })`; vm.runInThisContext(code)(require);
希望本文所述对大家node.js程序设计有所帮助。