gistfile1.txt WebStorm 的 attach 原理,经过一些实验,猜测如下:1. 会传递环境变量 NODE_DEBUG_OPTION ,在 inspect 协议下会传递 --inspect-brk=XXXX,旧协议传递 --debug-brk=XXXX --expose_debug_as=v8debug2. 应用
WebStorm 的 attach 原理,经过一些实验,猜测如下: 1. 会传递环境变量 NODE_DEBUG_OPTION ,在 inspect 协议下会传递 --inspect-brk=XXXX,旧协议传递 --debug-brk=XXXX --expose_debug_as=v8debug 2. 应用需把该调试端口传递给 execArgv 来启动调试 3. WebStorm 会首先 attach 该端口对应的 process 4. 然后会自动 attach 该 process 的所有开启 debug 的子程序(即包括我们的 agent 和所有 worker,包括重启后的 worker) node调试协议 引言 研究node调试协议(实际上是chrome调试协议)对设计和实现自己的node远程调试工具来说至关重要,它不仅被用在chrome的开发工具中,也可以用它来实现自己的web ide产品,比如调试node中运行的javascript代码。 协议的版本 chrome调试协议是调试客户端和调试目标进行调试交互的规范,该协议通过json格式的文档protocol.json给出。 目前协议稳定版本是1.2,针对不同的运行环境protocol.json分为两个不同的协议内容,一种是提供给chrome浏览器的,一种是提供给基于V8 javascript引擎的运行环境,如node。 通过https://chromedevtools.github.io/debugger-protocol-viewer/ 可以了解协议的相关信息。 目前,提供给浏览器的协议描述在: https://chromedevtools.github.io/debugger-protocol-viewer/1-2/。 提供给基于V8运行环境的在: https://chromedevtools.github.io/debugger-protocol-viewer/v8/。 为了调试node应用程序,所以我们比较关注后者。 node6.3.0发布了一个v8-inspector重大变更,支持–inspect启动标识,因此从该版本开始,可以基于chrome调试协议去调试node了。 查看node所支持的协议版本 通过如下命令启动node应用程序,如下所示:(app.js是你要运行的应用程序的入口程序) node --inspect=9222 app.js 1 在浏览器中输入url: http://127.0.0.1:9222/json/version 将得到类似如下返回内容: 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)"} ] 1 node7.0 [ { "Browser": "node.js/v7.0.0", "Protocol-Version": "1.1" } ] 1 2 3 4 从返回内容来看协议版本为1.1。 最好升级node到最新的稳定版,因为在node6.8中发布了一个变更,可以通过url: http://127.0.0.1:9222/json/protocol获取到json格式的具体协议内容。 类似如下内容: { "version": { "major": "1", "minor": "1" }, "domains": [ ...... ] } 1 2 3 4 5 6 协议内容 调试协议分为六个domain,分别为Schema、Runtime、Debugger、Console、Profiler、HeapProfiler。我们这里主要关注Debugger。 Debugger向开发者提供了调试javascript的的能力,如java调试一样,可以设置断点、跟踪线程栈、进行step。 Debugger域 方法 enable() 针对当前页面启动调试能力,客户端在调试前必须调用该方法启动调试能力,并在得到该方法的返回后才能正式进入调试 disable() 针对当前页面禁用调试能力 setBreakpointsActive(active:boolean) 激活当前页面的所有断点 setSkipAllPauses(skip:boolean) 使当前页不会被任何暂停事件所中断,如断点、异常、dom异常等 setBreakpointByUrl 参数: lineNumber:integer url:string optional 设置断点的目标脚本url urlRegex:string optional 匹配正则表达式的url columnNumber:integer optional condition:string optional 设置断点条件 返回值: {breakpointId:BreakpointId,locations:[Location]} 在给定url的javascript文件中设置断点。一旦该命令得到执行,将返回断点id,和应用该断点的文件位置。url和urlRegex必须得设置一个。 setBreakpoint 参数: location:Location condition:string 返回: {breakpointId:BreakpointId,actualLocation:Location} 在给定的Location处设置断点 removeBreakpoint(breakpointId:BreakpointId) 删除断点 continueToLocation(location:Location) 继续执行,直到到达目标位置 stepOver() stepInto() stepOut() pause() resume() searchInContent 参数: scriptId:Runtime.ScriptId 搜索目标脚本的id query:string 搜索内容 caseSensitive:boolean optional 是否大小写敏感 isRegex:boolean optional 是否使用正则表达式 返回: {result:[SearchMatch]} 在指定目标脚本里搜索字符串,该方法属于体验性方法 setScriptSource 参数: scriptId:Runtime.ScriptId scriptSource:string 新的脚本内容 dryRun:boolean optional 如果设置为true,改变不会被真正被应用。经常用来获取结果而并不真正去改变代码 返回: { callFrames:[CallFrame], //optional 如果编辑发生了,返回新的栈帧 stackChanged:boolean, //optional 当前调用栈是否被改变 asyncStackTrace:Runtime.StackTrace //optional 异步的stack trace,如果有的话 exceptionDetails:Runtime.ExceptionDetails //optional 异常信息,如果有的话 } 编辑脚本内容 restartFrame 参数: callFrameId:CallFrameId 栈帧id 返回: { callFrames:[CallFrame] //新的stack trace asyncStackTrace:Runtime.StackTrace } 重新从某一栈帧开始执行 getScriptSource(scriptId:Runtime.ScriptId) 返回: { scriptSource:string } 获取脚本内容 setPauseOnExceptions 参数: state:string 只能设置三个值:none, uncaught, all. 定义在什么异常情况下暂定,默认是none。all为任何异常都暂停。 evaluateOnCallFrame 参数: callFrameId:CallFrameId expression:string 表达式内容 objectGroup:string optional 将结果放在哪个分组下 includeCommandLineAPI:boolean optional 指定表达式是否应该存在命令行api,默认false silent:boolean optional 在静默状态下,表达式评估异常不会报告且不会造成暂定 returnByValue:boolean optional 是否期望返回结果是json对象 generatePreview:boolean optional 是否生成结果预览,体验性参数 返回: { result:Runtime.RemoteObject exceptionDetails:Runtime.ExceptionDetails//optional } 在指定栈帧评估表达式 setVariableValue 参数: scopeNumber:integer 域序号,基于0。只运行local、closure、catch域。 variableName:string 变量名 newValue:Runtime.CallArgument 新的变量值 callFrameId:CallFrameId 指定栈帧上设置某变量的值 setAsyncCallStackDepth 参数: maxDepth:integer 异步调用栈的最大深度,,默认为0,不去收集异步调用栈 禁用或启用异步调用栈的跟踪 setBlackboxPatterns 体验性 略 setBlackboxedRanges 体验性 略 事件 scriptParsed 虚拟机解析脚本时触发 参数: scriptId:Runtime.ScriptId url:string startLine:integer startColumn:integer endLine:integer endColumn:integer executionContextId:Runtime.ExecutionContextId 脚本的执行上下文 hash:string executionContextAuxData:object optional isLiveEdit:boolean optional 脚本是否来自动态改变的内容。体验性。 sourceMapURL:string optional source map的url hasSourceURL:boolean optional 脚本是否存在source url scriptFailedToParse 虚拟机解析脚本失败时触发 参数: scriptId:Runtime.ScriptId url:string startLine:integer startColumn:integer endLine:integer endColumn:integer executionContextId:Runtime.ExecutionContextId 脚本的执行上下文 hash:string executionContextAuxData:object optional sourceMapURL:string optional source map的url hasSourceURL:boolean optional 脚本是否存在source url breakpointResolved 当一个断点在某脚本的目标位置得带应用时触发 参数: breakpointId:BreakpointId location:Location paused 当虚拟因异常或断点或其它缘由暂停时 参数: callFrames: [ CallFrame ] 虚拟机停止在哪个栈 reason:string 原因(包括XHR, DOM, EventListener, exception, assert, debugCommand, promiseRejection, other). data:object optional 辅助属性 hitBreakpoints:[string] optional hit到的断点id asyncStackTrace:Runtime.StackTrace optional resumed 虚拟机恢复运行时触发 类型 BreakpointId 断点id string CallFrameId 调用栈id string Location 代码位置 object 属性: scriptId:Runtime.ScriptId lineNumber:integer columnNumber:integer optional CallFrame 栈帧 object 属性: callFrameId:CallFrameId functionName:string 函数名 functionLocation:Location optional 体验性 location:Location scopeChain:[Scope] 该帧的调用域链 this:Runtime.RemoteObject 该帧的调用者 returnValue:Runtime.RemoteObject optional 如果该帧处于函数返回点将得到返回值 Scope 执行域 object 属性: type:string 包括:global, local, with, closure, catch, block, script object:Runtime.RemoteObject 代表该执行域的对象,对global和with域来说代表真正的对象,对于其他域只是该域的描述,包括了域里的属性和变量 name:string optional startLocation:Location endLocation:Location SearchMatch 搜索匹配结果 object 属性: lineNumber:number 所在行 lineContent:string 匹配的内容