Skip to content

Commit da757bb

Browse files
authored
fix: don't keep the infinite debugger spinner (#493)
* fix: don't keep the infinite debugger spinner * chore: cleanup * chore: cleanup delayed calls
1 parent b6a8696 commit da757bb

File tree

9 files changed

+323
-36
lines changed

9 files changed

+323
-36
lines changed

patches/birpc@0.2.17.patch

Lines changed: 265 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,275 @@
1+
diff --git a/dist/index.cjs b/dist/index.cjs
2+
index d8119336758abcb11f5e247dfe579b1b5c5fefd5..00e4b1a01cfa480a874f5da6f8dcdd4db2b89e99 100644
3+
--- a/dist/index.cjs
4+
+++ b/dist/index.cjs
5+
@@ -11,18 +11,24 @@ function createBirpc(functions, options) {
6+
const {
7+
post,
8+
on,
9+
+ off = () => {
10+
+ },
11+
eventNames = [],
12+
serialize = defaultSerialize,
13+
deserialize = defaultDeserialize,
14+
resolver,
15+
+ bind = "rpc",
16+
timeout = DEFAULT_TIMEOUT
17+
} = options;
18+
const rpcPromiseMap = /* @__PURE__ */ new Map();
19+
let _promise;
20+
+ let closed = false;
21+
const rpc = new Proxy({}, {
22+
get(_, method) {
23+
if (method === "$functions")
24+
return functions;
25+
+ if (method === "$close")
26+
+ return close;
27+
if (method === "then" && !eventNames.includes("then") && !("then" in functions))
28+
return void 0;
29+
const sendEvent = (...args) => {
30+
@@ -33,7 +39,15 @@ function createBirpc(functions, options) {
31+
return sendEvent;
32+
}
33+
const sendCall = async (...args) => {
34+
- await _promise;
35+
+ if (closed)
36+
+ throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
37+
+ if (_promise) {
38+
+ try {
39+
+ await _promise;
40+
+ } finally {
41+
+ _promise = void 0;
42+
+ }
43+
+ }
44+
return new Promise((resolve, reject) => {
45+
const id = nanoid();
46+
let timeoutId;
47+
@@ -58,7 +72,15 @@ function createBirpc(functions, options) {
48+
return sendCall;
49+
}
50+
});
51+
- _promise = on(async (data, ...extra) => {
52+
+ function close() {
53+
+ closed = true;
54+
+ rpcPromiseMap.forEach(({ reject }) => {
55+
+ reject(new Error("[birpc] rpc is closed"));
56+
+ });
57+
+ rpcPromiseMap.clear();
58+
+ off(onMessage);
59+
+ }
60+
+ async function onMessage(data, ...extra) {
61+
const msg = deserialize(data);
62+
if (msg.t === "q") {
63+
const { m: method, a: args } = msg;
64+
@@ -68,7 +90,7 @@ function createBirpc(functions, options) {
65+
error = new Error(`[birpc] function "${method}" not found`);
66+
} else {
67+
try {
68+
- result = await fn.apply(rpc, args);
69+
+ result = await fn.apply(bind === "rpc" ? rpc : functions, args);
70+
} catch (e) {
71+
error = e;
72+
}
73+
@@ -90,7 +112,8 @@ function createBirpc(functions, options) {
74+
}
75+
rpcPromiseMap.delete(ack);
76+
}
77+
- });
78+
+ }
79+
+ _promise = on(onMessage);
80+
return rpc;
81+
}
82+
const cacheMap = /* @__PURE__ */ new WeakMap();
83+
diff --git a/dist/index.d.cts b/dist/index.d.cts
84+
index 010f33e6343281a894b6835d89b7fcf1157250a7..f7618f7f8118d24723693415dc321adfa5881458 100644
85+
--- a/dist/index.d.cts
86+
+++ b/dist/index.d.cts
87+
@@ -11,6 +11,10 @@ interface ChannelOptions {
88+
* Listener to receive raw message
89+
*/
90+
on: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>;
91+
+ /**
92+
+ * Clear the listener when `$close` is called
93+
+ */
94+
+ off?: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>;
95+
/**
96+
* Custom function to serialize data
97+
*
98+
@@ -23,6 +27,10 @@ interface ChannelOptions {
99+
* by default it passes the data as-is
100+
*/
101+
deserialize?: (data: any) => any;
102+
+ /**
103+
+ * Call the methods with the RPC context or the original functions object
104+
+ */
105+
+ bind?: 'rpc' | 'functions';
106+
}
107+
interface EventOptions<Remote> {
108+
/**
109+
@@ -71,6 +79,7 @@ type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
110+
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
111+
} & {
112+
$functions: LocalFunctions;
113+
+ $close: () => void;
114+
};
115+
type BirpcGroupReturn<RemoteFunctions> = {
116+
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>;
117+
diff --git a/dist/index.d.mts b/dist/index.d.mts
118+
index 010f33e6343281a894b6835d89b7fcf1157250a7..f7618f7f8118d24723693415dc321adfa5881458 100644
119+
--- a/dist/index.d.mts
120+
+++ b/dist/index.d.mts
121+
@@ -11,6 +11,10 @@ interface ChannelOptions {
122+
* Listener to receive raw message
123+
*/
124+
on: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>;
125+
+ /**
126+
+ * Clear the listener when `$close` is called
127+
+ */
128+
+ off?: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>;
129+
/**
130+
* Custom function to serialize data
131+
*
132+
@@ -23,6 +27,10 @@ interface ChannelOptions {
133+
* by default it passes the data as-is
134+
*/
135+
deserialize?: (data: any) => any;
136+
+ /**
137+
+ * Call the methods with the RPC context or the original functions object
138+
+ */
139+
+ bind?: 'rpc' | 'functions';
140+
}
141+
interface EventOptions<Remote> {
142+
/**
143+
@@ -71,6 +79,7 @@ type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
144+
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
145+
} & {
146+
$functions: LocalFunctions;
147+
+ $close: () => void;
148+
};
149+
type BirpcGroupReturn<RemoteFunctions> = {
150+
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>;
151+
diff --git a/dist/index.d.ts b/dist/index.d.ts
152+
index 010f33e6343281a894b6835d89b7fcf1157250a7..f7618f7f8118d24723693415dc321adfa5881458 100644
153+
--- a/dist/index.d.ts
154+
+++ b/dist/index.d.ts
155+
@@ -11,6 +11,10 @@ interface ChannelOptions {
156+
* Listener to receive raw message
157+
*/
158+
on: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>;
159+
+ /**
160+
+ * Clear the listener when `$close` is called
161+
+ */
162+
+ off?: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>;
163+
/**
164+
* Custom function to serialize data
165+
*
166+
@@ -23,6 +27,10 @@ interface ChannelOptions {
167+
* by default it passes the data as-is
168+
*/
169+
deserialize?: (data: any) => any;
170+
+ /**
171+
+ * Call the methods with the RPC context or the original functions object
172+
+ */
173+
+ bind?: 'rpc' | 'functions';
174+
}
175+
interface EventOptions<Remote> {
176+
/**
177+
@@ -71,6 +79,7 @@ type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
178+
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
179+
} & {
180+
$functions: LocalFunctions;
181+
+ $close: () => void;
182+
};
183+
type BirpcGroupReturn<RemoteFunctions> = {
184+
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>;
1185
diff --git a/dist/index.mjs b/dist/index.mjs
2-
index 8396fdbfbd7e1df8935c0806af9e7b31f8ccc261..7fcc87a89d7ca21cbf3a3e97ddedec0c51a7ef2a 100644
186+
index 8396fdbfbd7e1df8935c0806af9e7b31f8ccc261..4544cebb4378902b8e08686ed882689d7102f0f5 100644
3187
--- a/dist/index.mjs
4188
+++ b/dist/index.mjs
5-
@@ -66,7 +66,7 @@ function createBirpc(functions, options) {
189+
@@ -9,18 +9,24 @@ function createBirpc(functions, options) {
190+
const {
191+
post,
192+
on,
193+
+ off = () => {
194+
+ },
195+
eventNames = [],
196+
serialize = defaultSerialize,
197+
deserialize = defaultDeserialize,
198+
resolver,
199+
+ bind = "rpc",
200+
timeout = DEFAULT_TIMEOUT
201+
} = options;
202+
const rpcPromiseMap = /* @__PURE__ */ new Map();
203+
let _promise;
204+
+ let closed = false;
205+
const rpc = new Proxy({}, {
206+
get(_, method) {
207+
if (method === "$functions")
208+
return functions;
209+
+ if (method === "$close")
210+
+ return close;
211+
if (method === "then" && !eventNames.includes("then") && !("then" in functions))
212+
return void 0;
213+
const sendEvent = (...args) => {
214+
@@ -31,7 +37,15 @@ function createBirpc(functions, options) {
215+
return sendEvent;
216+
}
217+
const sendCall = async (...args) => {
218+
- await _promise;
219+
+ if (closed)
220+
+ throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
221+
+ if (_promise) {
222+
+ try {
223+
+ await _promise;
224+
+ } finally {
225+
+ _promise = void 0;
226+
+ }
227+
+ }
228+
return new Promise((resolve, reject) => {
229+
const id = nanoid();
230+
let timeoutId;
231+
@@ -48,7 +62,7 @@ function createBirpc(functions, options) {
232+
if (typeof timeoutId === "object")
233+
timeoutId = timeoutId.unref?.();
234+
}
235+
- rpcPromiseMap.set(id, { resolve, reject, timeoutId });
236+
+ rpcPromiseMap.set(id, { resolve, reject, timeoutId, method });
237+
post(serialize({ m: method, a: args, i: id, t: "q" }));
238+
});
239+
};
240+
@@ -56,7 +70,15 @@ function createBirpc(functions, options) {
241+
return sendCall;
242+
}
243+
});
244+
- _promise = on(async (data, ...extra) => {
245+
+ function close() {
246+
+ closed = true;
247+
+ rpcPromiseMap.forEach(({ reject, method }) => {
248+
+ reject(new Error(`[birpc] rpc is closed, cannot call "${method}"`));
249+
+ });
250+
+ rpcPromiseMap.clear();
251+
+ off(onMessage);
252+
+ }
253+
+ async function onMessage(data, ...extra) {
254+
const msg = deserialize(data);
255+
if (msg.t === "q") {
256+
const { m: method, a: args } = msg;
257+
@@ -66,7 +88,7 @@ function createBirpc(functions, options) {
6258
error = new Error(`[birpc] function "${method}" not found`);
7259
} else {
8260
try {
9261
- result = await fn.apply(rpc, args);
10-
+ result = await fn.apply(functions, args);
262+
+ result = await fn.apply(bind === "rpc" ? rpc : functions, args);
11263
} catch (e) {
12264
error = e;
13265
}
266+
@@ -88,7 +110,8 @@ function createBirpc(functions, options) {
267+
}
268+
rpcPromiseMap.delete(ack);
269+
}
270+
- });
271+
+ }
272+
+ _promise = on(onMessage);
273+
return rpc;
274+
}
275+
const cacheMap = /* @__PURE__ */ new WeakMap();

pnpm-lock.yaml

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

src/api.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ export class VitestFolderAPI {
7272

7373
private handlers: ResolvedMeta['handlers']
7474

75+
public createDate = Date.now()
76+
7577
constructor(
7678
private pkg: VitestPackage,
7779
private meta: ResolvedMeta,
@@ -115,19 +117,28 @@ export class VitestFolderAPI {
115117
return this.meta.rpc.getFiles()
116118
}
117119

118-
onFileCreated = createQueuedHandler((files: string[]) => {
120+
onFileCreated = createQueuedHandler(async (files: string[]) => {
121+
if (this.process.closed) {
122+
return
123+
}
119124
return this.meta.rpc.onFilesCreated(files)
120125
})
121126

122-
onFileChanged = createQueuedHandler((files: string[]) => {
127+
onFileChanged = createQueuedHandler(async (files: string[]) => {
128+
if (this.process.closed) {
129+
return
130+
}
123131
return this.meta.rpc.onFilesChanged(files)
124132
})
125133

126134
async collectTests(projectName: string, testFile: string) {
127135
return this._collectTests(`${projectName}\0${normalize(testFile)}`)
128136
}
129137

130-
private _collectTests = createQueuedHandler((testsQueue: string[]) => {
138+
private _collectTests = createQueuedHandler(async (testsQueue: string[]) => {
139+
if (this.process.closed) {
140+
return
141+
}
131142
const tests = Array.from(testsQueue).map((spec) => {
132143
const [projectName, filepath] = spec.split('\0', 2)
133144
return [projectName, filepath] as [string, string]
@@ -163,6 +174,7 @@ export class VitestFolderAPI {
163174
log.error('[API]', 'Failed to close Vitest process', err)
164175
})
165176
}
177+
this.meta.rpc.$close()
166178
}
167179

168180
async cancelRun() {

src/api/rpc.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export function createVitestRpc(options: {
9696
events,
9797
{
9898
timeout: -1,
99+
bind: 'functions',
99100
on(listener) {
100101
options.on(listener)
101102
},

0 commit comments

Comments
 (0)