首先启动一个nodejs的进程,加上参数–inspect-brk=58580,58580是一个自定义的端口,然后该进程会停在开始的位置,并输出类似的log:
Debugger listening on ws://127.0.0.1:58580/96f1cb2b-6a8b-4745-a842-3d91e6ec61c9
For help, see: https://nodejs.org/en/docs/inspector
import {ChromeDebugAdapter, ChromeDebugSession} from 'vscode-chrome-debug-core'
let debugAdapter
//其中log是上述的nodejs进程输出的log,通过分析这个log可以得到port信息
//logFilePath是一个路径,log文件路径,onPaused是回调函数,在收到paused事件时会调用
//可以传给onPaused传一些参数,比如当前变量值,当前监视的表达式的值,当前脚本所在的行,当前脚本的内容等
async function init (log, logFilePath, onPaused) {
debugAdapter = new ChromeDebugAdapter(
{
enableSourceMapCaching: true,
logFilePath: logPath
},
new ChromeDebugSession(true, false, {
adapter: ChromeDebugAdapter,
extensionName: 'Debugger',
logFilePath: logFilePath
})
)
//启动debugger
await debugAdapter.attach({
port: getDebugPort(log)
})
debugAdapter.chrome.Debugger.on('paused', async (pausedEvent, data) => {
if (pausedEvent.reason === 'Break on start') {
//停止原因是在最开始的位置停止了
} else {
//其他原因停止
}
if (pausedEvent.hitBreakpoints.length > 0) {
//表示当前停止位置有断点,可以做一些处理
}
//在这里可以做一些其他操作
//获得当前文件的文本信息
//let scripts = await getScripts(pausedEvent.callFrames[0].url)
//修改变量的值,其中参数分别是callFrameId,scopeIndex,variable name, variable value
//就是把当前的callFrame里面的变量a的值设置为了dd
//await setVariableValue(pausedEvent.callFrames[0].callFrameId, 0, 'a', '"dd"')
//获取所有的变量值
//await getVariables(pausedEvent.callFrames)
//获取表达式a+b的值
//await evaluateOnCallFrame('a+b', pausedEvent.callFrames[0])
//再比如,next,stepIn,stepOut,continue等操作
onPaused()
})
debugAdapter.chrome.Debugger.on('resumed', (event) => {
// console.log(event, '====resumed')
})
debugAdapter.chrome.Debugger.on('scriptParsed', async event => {
// console.log(event, '=====scriptParsed')
})
}
//breakpoints是断点集合,let breakpoints = {'/root/index.js': [{line: 2,id: 0}]}
//key是文件路径,value是断点位置集合,id是唯一的数字
async function resetBreakpoints (breakpoints) {
if (!debugAdapter) return
for (let file in breakpoints) {
let breakpointData = getBreakpoints(file, breakpoints[file])
await debugAdapter.setBreakpoints(breakpointData.breakpoints, undefined, sessionRequestId++, breakpointData.ids)
}
}
function getBreakpoints (file, breakpoints) {
let result = {
breakpoints: {source: {path: file}, breakpoints: []},
ids: []
}
for (let index in breakpoints) {
result.breakpoints.breakpoints.push({line: breakpoints[index].line, column: 1})
result.ids.push(breakpoints[index].id)
}
return result
}
没有找到相关的文档介绍,看源码也没什么注释,我也不是太清楚自己用的是不是完全正确,不过,就获得的结果来看,以下的函数没有发现大的问题,如果哪里写的有问题,欢迎指正。
//设置变量值
async function setVariableValue (callFrameId, scopeIndex, name, value) {
await debugAdapter.setVariableValue(callFrameId, scopeIndex, name, value)
}
//获取表达式值
async function evaluateOnCallFrame (expression, callFrame) {
let res = await debugAdapter.evaluateOnCallFrame(expression, callFrame)
return res
}
//获得指定url的脚本的内容
async function getScripts (url) {
let script = debugAdapter.getScriptByUrl(url)
let source = await debugAdapter.scriptToSource(script)
let str = await debugAdapter.source(source)
let scripts = str.content.split('\n')}
return scripts
}
//获取类型为local的所有变量的值(这里我过滤了其他的种类,还有global等,如果想获得所有的话,就取消过滤)
async function getVariables () {
let scopes = []
for (let i = 0; i < currentCallFrames[0].scopeChain.length; i++) {
let scope = currentCallFrames[0].scopeChain[i]
if (scope.type === 'local') {
let objectId = scope.object.objectId
let variables = await debugAdapter.getVariablesForObjectId(objectId)
scopes.push({
type: scope.type,
scopeIndex: i,
variables: variables,
frameId: currentCallFrames[0].callFrameId
})
}
}
return scopes
}
async function next () {
await debugAdapter.next()
}
async function stepIn () {
await debugAdapter.stepIn()
}
async function stepOut () {
await debugAdapter.stepOut()
}
//起名continue有点问题,就改了个名字
async function resume () {
await debugAdapter.continue()
}
这里面有些方法在定义的ts文件里面标注为protected,private的,本意可能并不想用户调用,不过js你们了解的了啊,就没有不能调用的,虽然使用的可能有点问题,不过目前看来好用(谁让文档这么坑,读源码我的耐心又有限呢,一切以实现功能为目标,其他的都不重要,,,)。如果大家有更好的实现方法,欢迎分享。