Skip to content

Commit 1ec6f70

Browse files
committed
fix: do not crash when restarting the debug session
1 parent 3dd2927 commit 1ec6f70

File tree

10 files changed

+250
-183
lines changed

10 files changed

+250
-183
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@
278278
"@vue/reactivity": "^3.2.33",
279279
"acorn": "^8.12.0",
280280
"acorn-walk": "^8.3.3",
281-
"birpc": "^0.2.19",
281+
"birpc": "^2.4.0",
282282
"bumpp": "^10.1.1",
283283
"chai": "^5.1.0",
284284
"changelogithub": "^13.15.0",

pnpm-lock.yaml

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/api/terminal.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ export class ExtensionTerminalProcess implements ExtensionWorkerProcess {
9595
}
9696

9797
close() {
98+
if (this.closed) {
99+
return Promise.resolve()
100+
}
98101
// send ctrl+c to sigint any running processs (vscode/#108289)
99102
this.terminal.sendText('\x03')
100103
// and then destroy it on the next event loop tick

src/api/ws.ts

Lines changed: 97 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -20,88 +20,17 @@ export function waitForWsConnection(
2020
) {
2121
return new Promise<WsConnectionMetadata>((resolve, reject) => {
2222
wss.once('connection', (ws) => {
23-
function onMessage(_message: any) {
24-
const message = JSON.parse(_message.toString()) as WorkerEvent
25-
26-
if (message.type === 'debug')
27-
log.worker('info', ...message.args)
28-
29-
if (message.type === 'ready') {
30-
const { api, handlers } = createVitestRpc({
31-
on: listener => ws.on('message', listener),
32-
send: message => ws.send(message),
33-
})
34-
ws.once('close', () => {
35-
log.verbose?.('[API]', 'Vitest WebSocket connection closed, cannot call RPC anymore.')
36-
api.$close()
37-
})
38-
resolve({
39-
rpc: api,
40-
workspaceSource: message.workspaceSource,
41-
handlers: {
42-
...handlers,
43-
onStdout() {
44-
// do nothing by default
45-
},
46-
},
47-
configs: message.configs,
48-
ws,
49-
pkg,
50-
})
51-
}
52-
53-
if (message.type === 'error') {
54-
const error = new Error(`Vitest failed to start: \n${message.error}`)
55-
reject(error)
56-
}
57-
ws.off('error', onError)
58-
ws.off('message', onMessage)
59-
ws.off('close', onExit)
60-
}
61-
62-
function onError(err: Error) {
63-
log.error('[API]', err)
64-
reject(err)
65-
ws.off('error', onError)
66-
ws.off('message', onMessage)
67-
ws.off('close', onExit)
68-
}
69-
70-
function onExit(code: number) {
71-
reject(new Error(`Vitest process exited with code ${code}`))
72-
}
23+
onWsConnection(
24+
ws,
25+
pkg,
26+
debug,
27+
shellType,
28+
meta => resolve(meta),
29+
err => reject(err),
30+
)
7331

7432
wss.off('error', onUnexpectedError)
7533
wss.off('exit', onUnexpectedExit)
76-
77-
ws.on('error', onError)
78-
ws.on('message', onMessage)
79-
ws.on('close', onExit)
80-
81-
const pnpLoader = pkg.loader
82-
const pnp = pkg.pnp
83-
84-
const runnerOptions: WorkerRunnerOptions = {
85-
type: 'init',
86-
meta: {
87-
shellType,
88-
vitestNodePath: pkg.vitestNodePath,
89-
env: getConfig(pkg.folder).env || undefined,
90-
configFile: pkg.configFile,
91-
cwd: pkg.cwd,
92-
arguments: pkg.arguments,
93-
workspaceFile: pkg.workspaceFile,
94-
id: pkg.id,
95-
pnpApi: pnp,
96-
pnpLoader: pnpLoader && gte(process.version, '18.19.0')
97-
? pathToFileURL(pnpLoader).toString()
98-
: undefined,
99-
},
100-
debug,
101-
astCollect: getConfig(pkg.folder).experimentalStaticAstCollect,
102-
}
103-
104-
ws.send(JSON.stringify(runnerOptions))
10534
})
10635

10736
function onUnexpectedExit() {
@@ -116,3 +45,92 @@ export function waitForWsConnection(
11645
wss.once('close', onUnexpectedExit)
11746
})
11847
}
48+
49+
export function onWsConnection(
50+
ws: WebSocket,
51+
pkg: VitestPackage,
52+
debug: boolean,
53+
shellType: 'terminal' | 'child_process',
54+
onStart: (meta: WsConnectionMetadata) => unknown,
55+
onFail: (err: Error) => unknown,
56+
) {
57+
function onMessage(_message: any) {
58+
const message = JSON.parse(_message.toString()) as WorkerEvent
59+
60+
if (message.type === 'debug')
61+
log.worker('info', ...message.args)
62+
63+
if (message.type === 'ready') {
64+
const { api, handlers } = createVitestRpc({
65+
on: listener => ws.on('message', listener),
66+
send: message => ws.send(message),
67+
})
68+
ws.once('close', () => {
69+
log.verbose?.('[API]', 'Vitest WebSocket connection closed, cannot call RPC anymore.')
70+
api.$close()
71+
})
72+
onStart({
73+
rpc: api,
74+
workspaceSource: message.workspaceSource,
75+
handlers: {
76+
...handlers,
77+
onStdout() {
78+
// do nothing by default
79+
},
80+
},
81+
configs: message.configs,
82+
ws,
83+
pkg,
84+
})
85+
}
86+
87+
if (message.type === 'error') {
88+
const error = new Error(`Vitest failed to start: \n${message.error}`)
89+
onFail(error)
90+
}
91+
ws.off('error', onError)
92+
ws.off('message', onMessage)
93+
ws.off('close', onExit)
94+
}
95+
96+
function onError(err: Error) {
97+
log.error('[API]', err)
98+
onFail(err)
99+
ws.off('error', onError)
100+
ws.off('message', onMessage)
101+
ws.off('close', onExit)
102+
}
103+
104+
function onExit(code: number) {
105+
onFail(new Error(`Vitest process exited with code ${code}`))
106+
}
107+
108+
ws.on('error', onError)
109+
ws.on('message', onMessage)
110+
ws.on('close', onExit)
111+
112+
const pnpLoader = pkg.loader
113+
const pnp = pkg.pnp
114+
115+
const runnerOptions: WorkerRunnerOptions = {
116+
type: 'init',
117+
meta: {
118+
shellType,
119+
vitestNodePath: pkg.vitestNodePath,
120+
env: getConfig(pkg.folder).env || undefined,
121+
configFile: pkg.configFile,
122+
cwd: pkg.cwd,
123+
arguments: pkg.arguments,
124+
workspaceFile: pkg.workspaceFile,
125+
id: pkg.id,
126+
pnpApi: pnp,
127+
pnpLoader: pnpLoader && gte(process.version, '18.19.0')
128+
? pathToFileURL(pnpLoader).toString()
129+
: undefined,
130+
},
131+
debug,
132+
astCollect: getConfig(pkg.folder).experimentalStaticAstCollect,
133+
}
134+
135+
ws.send(JSON.stringify(runnerOptions))
136+
}

0 commit comments

Comments
 (0)