Skip to content

Commit 6a4930a

Browse files
feat(network-debugger): integrate with Node native inspector DevTools
- Detect active native inspector connections and route intercepted network logs directly to it. - Suppress native network debugging logs to prevent double-logging. - Add `onSend` callback to `DevtoolServer` for broadcasting CDP events. - Broadcast DevTools WS messages to connected clients in `RequestCenter`. - Fix typing issues in tests to support new properties on mock classes. Co-authored-by: GrinZero <70185413+GrinZero@users.noreply.github.com>
1 parent 5cc46a6 commit 6a4930a

8 files changed

Lines changed: 165 additions & 94 deletions

File tree

packages/network-debugger/src/core/fork.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ vi.mock('ws', () => {
5151

5252
function MockWebSocket(this: EventEmitter) {
5353
EventEmitter.call(this)
54-
this.send = mockWsSend
55-
this.terminate = mockWsTerminate
54+
(this as any).send = mockWsSend
55+
(this as any).terminate = mockWsTerminate
5656
const originalRemoveAllListeners = this.removeAllListeners.bind(this)
5757
this.removeAllListeners = function () {
5858
mockWsRemoveAllListeners()

packages/network-debugger/src/core/fork.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import WebSocket from 'ws'
44
import { ChildProcess, fork } from 'child_process'
55
import { __dirname } from '../common'
66
import { resolve as resolvePath } from 'path'
7+
import { IS_DEV_MODE } from '../common'
78
import { RegisterOptions } from '../common'
89
import fs from 'fs'
910
import { sleep, checkMainProcessAlive } from '../utils/process'
@@ -26,9 +27,38 @@ export class MainProcess {
2627
private ws: Promise<WebSocket>
2728
private options: RegisterOptions
2829
private cp?: ChildProcess
30+
private nativeNetwork?: any
2931

3032
constructor(props: RegisterOptions & { key: string }) {
31-
this.options = props
33+
this.options = { ...props }
34+
35+
try {
36+
const inspector = require('inspector')
37+
// Check if native inspector is active and supports Network
38+
if (inspector.url() && inspector.Network) {
39+
this.nativeNetwork = { ...inspector.Network }
40+
// Disable native network tracking to prevent duplicate logs
41+
const methods = [
42+
'requestWillBeSent',
43+
'responseReceived',
44+
'loadingFinished',
45+
'loadingFailed',
46+
'dataSent',
47+
'dataReceived'
48+
]
49+
methods.forEach((method) => {
50+
if (typeof (inspector.Network as any)[method] === 'function') {
51+
;(inspector.Network as any)[method] = () => {}
52+
}
53+
})
54+
55+
// Since the user is already connected to native devtools, don't open a new browser
56+
this.options.autoOpenDevtool = false
57+
}
58+
} catch (e) {
59+
// ignore
60+
}
61+
3262
this.ws = new Promise<WebSocket>(async (resolve, reject) => {
3363
const lockFilePath = resolvePath(__dirname, `./${props.key}`)
3464
if (fs.existsSync(lockFilePath)) {
@@ -50,15 +80,36 @@ export class MainProcess {
5080
}
5181
fs.writeFileSync(lockFilePath, `${process.pid}`)
5282
const socket = new WebSocket(`ws://localhost:${props.port}`)
83+
const setupSocket = (s: WebSocket) => {
84+
s.on('message', (msg) => {
85+
try {
86+
const data = JSON.parse(msg.toString())
87+
if (data.type === 'cdp' && this.nativeNetwork) {
88+
const { method, params } = data.data
89+
if (method && method.startsWith('Network.')) {
90+
const methodName = method.split('.')[1]
91+
if (typeof this.nativeNetwork[methodName] === 'function') {
92+
this.nativeNetwork[methodName](params)
93+
}
94+
}
95+
}
96+
} catch (e) {
97+
// ignore
98+
}
99+
})
100+
}
101+
53102
socket.on('open', () => {
54103
unlinkSafe(lockFilePath)
104+
setupSocket(socket)
55105
resolve(socket)
56106
})
57107
socket.on('error', () => {
58108
this.openProcess(() => {
59109
unlinkSafe(lockFilePath)
60110
const socket = new WebSocket(`ws://localhost:${props.port}`)
61111
socket.on('open', () => {
112+
setupSocket(socket)
62113
resolve(socket)
63114
})
64115
socket.on('error', reject)

packages/network-debugger/src/fork/__tests__/cdp-protocol.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe('CDP Protocol Correctness Tests', () => {
1717
const messages: Array<{ method: string; timestamp?: number }> = []
1818

1919
// 模拟 devtool.send 收集消息
20-
const mockSend = vi.fn((msg: { method?: string; params?: { timestamp?: number } }) => {
20+
const mockSend = vi.fn((msg: any) => {
2121
if (msg.method) {
2222
messages.push({
2323
method: msg.method,

packages/network-debugger/src/fork/devtool/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export interface DevtoolServerInitOptions {
1111
autoOpenDevtool?: boolean
1212
onConnect?: () => void
1313
onClose?: () => void
14+
onSend?: (message: DevtoolMessage) => void
1415
}
1516

1617
export interface IDevtoolServer {
@@ -26,10 +27,13 @@ export class DevtoolServer extends BaseDevtoolServer implements IDevtoolServer {
2627
private browser: ChildProcess | null = null
2728
private socket: Promise<[WebSocket]>
2829

30+
private onSend?: (message: DevtoolMessage) => void
31+
2932
constructor(props: DevtoolServerInitOptions) {
3033
super()
31-
const { port, autoOpenDevtool = true, onConnect, onClose } = props
34+
const { port, autoOpenDevtool = true, onConnect, onClose, onSend } = props
3235
this.port = port
36+
this.onSend = onSend
3337
this.server = new Server({ port })
3438
const { server } = this
3539

@@ -135,6 +139,9 @@ export class DevtoolServer extends BaseDevtoolServer implements IDevtoolServer {
135139
}
136140

137141
async send(message: DevtoolMessage) {
142+
if (this.onSend) {
143+
this.onSend(message)
144+
}
138145
const [socket] = await this.socket
139146
return socket.send(JSON.stringify(message))
140147
}

packages/network-debugger/src/fork/module/common.test.ts

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ describe('fork/module/common.ts', () => {
9999
const plugins = [plugin]
100100

101101
const result = plugin({
102-
devtool: mockDevtool,
103-
core: mockCore,
102+
devtool: mockDevtool as any,
103+
core: mockCore as any,
104104
plugins
105105
})
106106

107107
expect(pluginFn).toHaveBeenCalledWith({
108-
devtool: mockDevtool,
109-
core: mockCore,
108+
devtool: mockDevtool as any,
109+
core: mockCore as any,
110110
plugins
111111
})
112112
expect(result).toEqual({ result: 'test' })
@@ -123,8 +123,8 @@ describe('fork/module/common.ts', () => {
123123
const mockCore = createMockCore()
124124

125125
const result = plugin({
126-
devtool: mockDevtool,
127-
core: mockCore,
126+
devtool: mockDevtool as any,
127+
core: mockCore as any,
128128
plugins: [plugin]
129129
})
130130

@@ -142,8 +142,8 @@ describe('fork/module/common.ts', () => {
142142
const mockCore = createMockCore()
143143

144144
const result = plugin({
145-
devtool: mockDevtool,
146-
core: mockCore,
145+
devtool: mockDevtool as any,
146+
core: mockCore as any,
147147
plugins: [plugin]
148148
})
149149

@@ -165,8 +165,8 @@ describe('fork/module/common.ts', () => {
165165
const mockCore = createMockCore()
166166

167167
plugin({
168-
devtool: mockDevtool,
169-
core: mockCore,
168+
devtool: mockDevtool as any,
169+
core: mockCore as any,
170170
plugins: [plugin]
171171
})
172172

@@ -198,8 +198,8 @@ describe('fork/module/common.ts', () => {
198198
const mockCore = createMockCore()
199199

200200
plugin({
201-
devtool: mockDevtool,
202-
core: mockCore,
201+
devtool: mockDevtool as any,
202+
core: mockCore as any,
203203
plugins: [plugin]
204204
})
205205

@@ -222,8 +222,8 @@ describe('fork/module/common.ts', () => {
222222
const mockCore = createMockCore()
223223

224224
plugin({
225-
devtool: mockDevtool,
226-
core: mockCore,
225+
devtool: mockDevtool as any,
226+
core: mockCore as any,
227227
plugins: [plugin]
228228
})
229229

@@ -246,8 +246,8 @@ describe('fork/module/common.ts', () => {
246246
const mockCore = createMockCore()
247247

248248
plugin({
249-
devtool: mockDevtool,
250-
core: mockCore,
249+
devtool: mockDevtool as any,
250+
core: mockCore as any,
251251
plugins: [plugin]
252252
})
253253

@@ -279,8 +279,8 @@ describe('fork/module/common.ts', () => {
279279
const mockCore = createMockCore()
280280

281281
plugin({
282-
devtool: mockDevtool,
283-
core: mockCore,
282+
devtool: mockDevtool as any,
283+
core: mockCore as any,
284284
plugins: [plugin]
285285
})
286286

@@ -313,8 +313,8 @@ describe('fork/module/common.ts', () => {
313313
const mockCore = createMockCore()
314314

315315
plugin({
316-
devtool: mockDevtool,
317-
core: mockCore,
316+
devtool: mockDevtool as any,
317+
core: mockCore as any,
318318
plugins: [plugin]
319319
})
320320

@@ -346,14 +346,14 @@ describe('fork/module/common.ts', () => {
346346
const plugins = [plugin1, plugin2]
347347

348348
plugin1({
349-
devtool: mockDevtool,
350-
core: mockCore,
349+
devtool: mockDevtool as any,
350+
core: mockCore as any,
351351
plugins
352352
})
353353

354354
plugin2({
355-
devtool: mockDevtool,
356-
core: mockCore,
355+
devtool: mockDevtool as any,
356+
core: mockCore as any,
357357
plugins
358358
})
359359

@@ -378,8 +378,8 @@ describe('fork/module/common.ts', () => {
378378
const mockCore = createMockCore()
379379

380380
plugin({
381-
devtool: mockDevtool,
382-
core: mockCore,
381+
devtool: mockDevtool as any,
382+
core: mockCore as any,
383383
plugins: [plugin]
384384
})
385385

@@ -403,8 +403,8 @@ describe('fork/module/common.ts', () => {
403403
const plugins = [plugin]
404404

405405
plugin({
406-
devtool: mockDevtool,
407-
core: mockCore,
406+
devtool: mockDevtool as any,
407+
core: mockCore as any,
408408
plugins
409409
})
410410

packages/network-debugger/src/fork/module/health/index.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ describe('fork/module/health/index.ts', () => {
101101
const mockCore = createMockCore()
102102

103103
healthPlugin({
104-
devtool: mockDevtool,
105-
core: mockCore,
104+
devtool: mockDevtool as any,
105+
core: mockCore as any,
106106
plugins: [healthPlugin]
107107
})
108108

@@ -116,8 +116,8 @@ describe('fork/module/health/index.ts', () => {
116116
const mockCore = createMockCore()
117117

118118
healthPlugin({
119-
devtool: mockDevtool,
120-
core: mockCore,
119+
devtool: mockDevtool as any,
120+
core: mockCore as any,
121121
plugins: [healthPlugin]
122122
})
123123

@@ -134,8 +134,8 @@ describe('fork/module/health/index.ts', () => {
134134
const mockCore = createMockCore()
135135

136136
healthPlugin({
137-
devtool: mockDevtool,
138-
core: mockCore,
137+
devtool: mockDevtool as any,
138+
core: mockCore as any,
139139
plugins: [healthPlugin]
140140
})
141141

@@ -166,8 +166,8 @@ describe('fork/module/health/index.ts', () => {
166166
const mockCore = createMockCore()
167167

168168
healthPlugin({
169-
devtool: mockDevtool,
170-
core: mockCore,
169+
devtool: mockDevtool as any,
170+
core: mockCore as any,
171171
plugins: [healthPlugin]
172172
})
173173

@@ -196,8 +196,8 @@ describe('fork/module/health/index.ts', () => {
196196
const mockCore = createMockCore()
197197

198198
healthPlugin({
199-
devtool: mockDevtool,
200-
core: mockCore,
199+
devtool: mockDevtool as any,
200+
core: mockCore as any,
201201
plugins: [healthPlugin]
202202
})
203203

0 commit comments

Comments
 (0)