node調(diào)試協(xié)議
引言
研究node調(diào)試協(xié)議(實(shí)際上是chrome調(diào)試協(xié)議)對(duì)設(shè)計(jì)和實(shí)現(xiàn)自己的node遠(yuǎn)程調(diào)試工具來(lái)說(shuō)至關(guān)重要,它不僅被用在chrome的開(kāi)發(fā)工具中,也可以用它來(lái)實(shí)現(xiàn)自己的web ide產(chǎn)品,比如調(diào)試node中運(yùn)行的javascript代碼。
協(xié)議的版本
chrome調(diào)試協(xié)議是調(diào)試客戶端和調(diào)試目標(biāo)進(jìn)行調(diào)試交互的規(guī)范,該協(xié)議通過(guò)json格式的文檔protocol.json給出。
目前協(xié)議穩(wěn)定版本是1.2,針對(duì)不同的運(yùn)行環(huán)境protocol.json分為兩個(gè)不同的協(xié)議內(nèi)容,一種是提供給chrome瀏覽器的,一種是提供給基于V8 javascript引擎的運(yùn)行環(huán)境,如node。
通過(guò)https://chromedevtools.github.io/debugger-protocol-viewer/ 可以了解協(xié)議的相關(guān)信息。
目前,提供給瀏覽器的協(xié)議描述在:
https://chromedevtools.github.io/debugger-protocol-viewer/1-2/。
提供給基于V8運(yùn)行環(huán)境的在:
https://chromedevtools.github.io/debugger-protocol-viewer/v8/。
為了調(diào)試node應(yīng)用程序,所以我們比較關(guān)注后者。
node6.3.0發(fā)布了一個(gè)v8-inspector重大變更,支持--inspect啟動(dòng)標(biāo)識(shí),因此從該版本開(kāi)始,可以基于chrome調(diào)試協(xié)議去調(diào)試node了。
查看node所支持的協(xié)議版本
通過(guò)如下命令啟動(dòng)node應(yīng)用程序,如下所示:(app.js是你要運(yùn)行的應(yīng)用程序的入口程序)
node --inspect=9222 app.js
在瀏覽器中輸入url:
http://127.0.0.1:9222/json/version
將得到類(lèi)似如下返回內(nèi)容:
node6.3
[ { "Browser": "node.js/v6.3.0", "Protocol-Version": "1.1", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/45.0.2446.0 Safari/537.36", "WebKit-Version": "537.36 (@198122)"} ]
node7.0
[ {
"Browser": "node.js/v7.0.0",
"Protocol-Version": "1.1"
} ]
從返回內(nèi)容來(lái)看協(xié)議版本為1.1。
最好升級(jí)node到最新的穩(wěn)定版,因?yàn)樵趎ode6.8中發(fā)布了一個(gè)變更,可以通過(guò)url:
http://127.0.0.1:9222/json/protocol獲取到j(luò)son格式的具體協(xié)議內(nèi)容。
類(lèi)似如下內(nèi)容:
{
"version": { "major": "1", "minor": "1" },
"domains": [
......
]
}
協(xié)議內(nèi)容
調(diào)試協(xié)議分為六個(gè)domain,分別為Schema、Runtime、Debugger、Console、Profiler、HeapProfiler。我們這里主要關(guān)注Debugger。
Debugger向開(kāi)發(fā)者提供了調(diào)試javascript的的能力,如java調(diào)試一樣,可以設(shè)置斷點(diǎn)、跟蹤線程棧、進(jìn)行step。
Debugger域
方法
-
enable()
針對(duì)當(dāng)前頁(yè)面啟動(dòng)調(diào)試能力,客戶端在調(diào)試前必須調(diào)用該方法啟動(dòng)調(diào)試能力,并在得到該方法的返回后才能正式進(jìn)入調(diào)試
-
disable()
針對(duì)當(dāng)前頁(yè)面禁用調(diào)試能力
-
setBreakpointsActive(active:boolean)
激活當(dāng)前頁(yè)面的所有斷點(diǎn)
-
setSkipAllPauses(skip:boolean)
使當(dāng)前頁(yè)不會(huì)被任何暫停事件所中斷,如斷點(diǎn)、異常、dom異常等
-
setBreakpointByUrl
參數(shù):
lineNumber:integer
url:string optional 設(shè)置斷點(diǎn)的目標(biāo)腳本url
urlRegex:string optional 匹配正則表達(dá)式的url
columnNumber:integer optional
condition:string optional 設(shè)置斷點(diǎn)條件返回值:
{breakpointId:BreakpointId,locations:[Location]}在給定url的javascript文件中設(shè)置斷點(diǎn)。一旦該命令得到執(zhí)行,將返回?cái)帱c(diǎn)id,和應(yīng)用該斷點(diǎn)的文件位置。url和urlRegex必須得設(shè)置一個(gè)。
-
setBreakpoint
參數(shù):
location:Location
condition:string返回:
{breakpointId:BreakpointId,actualLocation:Location}在給定的Location處設(shè)置斷點(diǎn)
-
removeBreakpoint(breakpointId:BreakpointId)
刪除斷點(diǎn)
-
continueToLocation(location:Location)
繼續(xù)執(zhí)行,直到到達(dá)目標(biāo)位置
stepOver()
stepInto()
stepOut()
pause()
resume()
-
searchInContent
參數(shù):
scriptId:Runtime.ScriptId 搜索目標(biāo)腳本的id
query:string 搜索內(nèi)容
caseSensitive:boolean optional 是否大小寫(xiě)敏感
isRegex:boolean optional 是否使用正則表達(dá)式返回:
{result:[SearchMatch]}在指定目標(biāo)腳本里搜索字符串,該方法屬于體驗(yàn)性方法
-
setScriptSource
參數(shù):
scriptId:Runtime.ScriptId
scriptSource:string 新的腳本內(nèi)容
dryRun:boolean optional 如果設(shè)置為true,改變不會(huì)被真正被應(yīng)用。經(jīng)常用來(lái)獲取結(jié)果而并不真正去改變代碼返回:
{
callFrames:[CallFrame], //optional 如果編輯發(fā)生了,返回新的棧幀
stackChanged:boolean, //optional 當(dāng)前調(diào)用棧是否被改變
asyncStackTrace:Runtime.StackTrace //optional 異步的stack trace,如果有的話
exceptionDetails:Runtime.ExceptionDetails //optional 異常信息,如果有的話
}編輯腳本內(nèi)容
-
restartFrame
參數(shù):
callFrameId:CallFrameId 棧幀id返回:
{
callFrames:[CallFrame] //新的stack trace
asyncStackTrace:Runtime.StackTrace
}重新從某一棧幀開(kāi)始執(zhí)行
-
getScriptSource(scriptId:Runtime.ScriptId)
返回:
{
scriptSource:string
}獲取腳本內(nèi)容
-
setPauseOnExceptions
參數(shù):
state:string 只能設(shè)置三個(gè)值:none, uncaught, all.定義在什么異常情況下暫定,默認(rèn)是none。all為任何異常都暫停。
-
evaluateOnCallFrame
參數(shù):
callFrameId:CallFrameId
expression:string 表達(dá)式內(nèi)容
objectGroup:string optional 將結(jié)果放在哪個(gè)分組下
includeCommandLineAPI:boolean optional 指定表達(dá)式是否應(yīng)該存在命令行api,默認(rèn)false
silent:boolean optional 在靜默狀態(tài)下,表達(dá)式評(píng)估異常不會(huì)報(bào)告且不會(huì)造成暫定
returnByValue:boolean optional 是否期望返回結(jié)果是json對(duì)象
generatePreview:boolean optional 是否生成結(jié)果預(yù)覽,體驗(yàn)性參數(shù)返回:
{
result:Runtime.RemoteObject
exceptionDetails:Runtime.ExceptionDetails//optional
}在指定棧幀評(píng)估表達(dá)式
-
setVariableValue
參數(shù):
scopeNumber:integer 域序號(hào),基于0。只運(yùn)行l(wèi)ocal、closure、catch域。
variableName:string 變量名
newValue:Runtime.CallArgument 新的變量值
callFrameId:CallFrameId指定棧幀上設(shè)置某變量的值
-
setAsyncCallStackDepth
參數(shù):
maxDepth:integer 異步調(diào)用棧的最大深度,,默認(rèn)為0,不去收集異步調(diào)用棧禁用或啟用異步調(diào)用棧的跟蹤
-
setBlackboxPatterns
體驗(yàn)性 略
-
setBlackboxedRanges
體驗(yàn)性 略
事件
-
scriptParsed
虛擬機(jī)解析腳本時(shí)觸發(fā)
參數(shù):
scriptId:Runtime.ScriptId
url:string
startLine:integer
startColumn:integer
endLine:integer
endColumn:integer
executionContextId:Runtime.ExecutionContextId 腳本的執(zhí)行上下文
hash:string
executionContextAuxData:object optional
isLiveEdit:boolean optional 腳本是否來(lái)自動(dòng)態(tài)改變的內(nèi)容。體驗(yàn)性。
sourceMapURL:string optional source map的url
hasSourceURL:boolean optional 腳本是否存在source url -
scriptFailedToParse
虛擬機(jī)解析腳本失敗時(shí)觸發(fā)
參數(shù):
scriptId:Runtime.ScriptId
url:string
startLine:integer
startColumn:integer
endLine:integer
endColumn:integer
executionContextId:Runtime.ExecutionContextId 腳本的執(zhí)行上下文
hash:string
executionContextAuxData:object optional
sourceMapURL:string optional source map的url
hasSourceURL:boolean optional 腳本是否存在source url -
breakpointResolved
當(dāng)一個(gè)斷點(diǎn)在某腳本的目標(biāo)位置得帶應(yīng)用時(shí)觸發(fā)
參數(shù):
breakpointId:BreakpointId
location:Location -
paused
當(dāng)虛擬因異?;驍帱c(diǎn)或其它緣由暫停時(shí)
參數(shù):
callFrames: [ CallFrame ] 虛擬機(jī)停止在哪個(gè)棧
reason:string 原因(包括XHR, DOM, EventListener, exception, assert, debugCommand, promiseRejection, other).
data:object optional 輔助屬性
hitBreakpoints:[string] optional hit到的斷點(diǎn)id
asyncStackTrace:Runtime.StackTrace optional -
resumed
虛擬機(jī)恢復(fù)運(yùn)行時(shí)觸發(fā)
類(lèi)型
-
BreakpointId
斷點(diǎn)id
string -
CallFrameId
調(diào)用棧id
string -
Location
代碼位置
object
屬性:
scriptId:Runtime.ScriptId
lineNumber:integer
columnNumber:integer optional -
CallFrame
棧幀
object
屬性:
callFrameId:CallFrameId
functionName:string 函數(shù)名
functionLocation:Location optional 體驗(yàn)性
location:Location
scopeChain:[Scope] 該幀的調(diào)用域鏈
this:Runtime.RemoteObject 該幀的調(diào)用者
returnValue:Runtime.RemoteObject optional 如果該幀處于函數(shù)返回點(diǎn)將得到返回值 -
Scope
執(zhí)行域
object
屬性:
type:string 包括:global, local, with, closure, catch, block, script
object:Runtime.RemoteObject 代表該執(zhí)行域的對(duì)象,對(duì)global和with域來(lái)說(shuō)代表真正的對(duì)象,對(duì)于其他域只是該域的描述,包括了域里的屬性和變量
name:string optional
startLocation:Location
endLocation:Location -
SearchMatch
搜索匹配結(jié)果
object
屬性:
lineNumber:number 所在行
lineContent:string 匹配的內(nèi)容