-
Notifications
You must be signed in to change notification settings - Fork 327
/
Copy pathindex.js
151 lines (124 loc) · 4.42 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
'use strict'
const {
workerData: {
breakpointSetChannel,
breakpointHitChannel,
breakpointRemoveChannel
}
} = require('worker_threads')
const { randomUUID } = require('crypto')
// TODO: move debugger/devtools_client/session to common place
const session = require('../../../debugger/devtools_client/session')
// TODO: move debugger/devtools_client/source-maps to common place
const { getSourceMappedLine } = require('../../../debugger/devtools_client/source-maps')
// TODO: move debugger/devtools_client/snapshot to common place
const { getLocalStateForCallFrame } = require('../../../debugger/devtools_client/snapshot')
// TODO: move debugger/devtools_client/state to common place
const {
findScriptFromPartialPath,
getStackFromCallFrames
} = require('../../../debugger/devtools_client/state')
const log = require('../../../log')
let sessionStarted = false
const breakpointIdToProbe = new Map()
const probeIdToBreakpointId = new Map()
session.on('Debugger.paused', async ({ params: { hitBreakpoints: [hitBreakpoint], callFrames } }) => {
log.warn(`Debugger.paused: ${JSON.stringify(hitBreakpoint, null, 2)}`)
const probe = breakpointIdToProbe.get(hitBreakpoint)
log.warn(`probe: ${JSON.stringify(probe, null, 2)}`)
if (!probe) {
log.warn(`No probe found for breakpoint ${hitBreakpoint}`)
return session.post('Debugger.resume')
}
const stack = getStackFromCallFrames(callFrames)
const getLocalState = await getLocalStateForCallFrame(callFrames[0])
await session.post('Debugger.resume')
const snapshot = {
id: randomUUID(),
timestamp: Date.now(),
probe: {
id: probe.id,
version: '0',
location: probe.location
},
stack,
language: 'javascript'
}
log.warn(`snapshot: ${JSON.stringify(snapshot, null, 2)}`)
const state = getLocalState()
if (state) {
snapshot.captures = {
lines: { [probe.location.lines[0]]: { locals: state } }
}
}
breakpointHitChannel.postMessage({ snapshot })
})
breakpointRemoveChannel.on('message', async (probeId) => {
log.warn(`remove breakpoint ${probeId}`)
await removeBreakpoint(probeId)
log.warn(`removed breakpoint ${probeId}`)
breakpointRemoveChannel.postMessage(probeId)
})
breakpointSetChannel.on('message', async (probe) => {
log.warn(`set breakpoint ${JSON.stringify(probe, null, 2)}`)
await addBreakpoint(probe)
breakpointSetChannel.postMessage(probe.id)
log.warn(`added breakpoint ${probe.id}`)
})
async function removeBreakpoint (probeId) {
if (!sessionStarted) {
// We should not get in this state, but abort if we do, so the code doesn't fail unexpected
throw Error(`Cannot remove probe ${probeId}: Debugger not started`)
}
const breakpointId = probeIdToBreakpointId.get(probeId)
if (!breakpointId) {
throw Error(`Unknown probe id: ${probeId}`)
}
await session.post('Debugger.removeBreakpoint', { breakpointId })
probeIdToBreakpointId.delete(probeId)
breakpointIdToProbe.delete(breakpointId)
}
async function addBreakpoint (probe) {
if (!sessionStarted) await start()
const { file, line } = probe
probe.location = { file, lines: [String(line)] }
const script = findScriptFromPartialPath(file)
if (!script) {
log.error(`No loaded script found for ${file}`)
throw new Error(`No loaded script found for ${file}`)
}
const { url, scriptId, sourceMapURL } = script
log.warn(`Adding breakpoint at ${url}:${line}`)
log.warn(`scriptId: ${scriptId}`)
let lineNumber = line
// if (sourceMapURL) {
// try {
// lineNumber = await getSourceMappedLine(url, source, line, sourceMapURL)
// } catch (err) {
// log.error('Error processing script with source map', err)
// }
// if (lineNumber === null) {
// log.error('Could not find generated position for %s:%s', url, line)
// lineNumber = line
// }
// }
log.warn(`Source map: ${sourceMapURL}`)
log.warn(`Actual line number ${lineNumber}`)
try {
const { breakpointId } = await session.post('Debugger.setBreakpoint', {
location: {
scriptId,
lineNumber: lineNumber - 1
}
})
log.warn(`breakpointId: ${breakpointId}`)
breakpointIdToProbe.set(breakpointId, probe)
probeIdToBreakpointId.set(probe.id, breakpointId)
} catch (e) {
log.error('Error setting breakpoint at %s:%s', url, line, e)
}
}
function start () {
sessionStarted = true
return session.post('Debugger.enable') // return instead of await to reduce number of promises created
}