-
-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: don't keep the infinite debugger spinner (#493)
* fix: don't keep the infinite debugger spinner * chore: cleanup * chore: cleanup delayed calls
- Loading branch information
1 parent
b6a8696
commit da757bb
Showing
9 changed files
with
323 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,275 @@ | ||
diff --git a/dist/index.cjs b/dist/index.cjs | ||
index d8119336758abcb11f5e247dfe579b1b5c5fefd5..00e4b1a01cfa480a874f5da6f8dcdd4db2b89e99 100644 | ||
--- a/dist/index.cjs | ||
+++ b/dist/index.cjs | ||
@@ -11,18 +11,24 @@ function createBirpc(functions, options) { | ||
const { | ||
post, | ||
on, | ||
+ off = () => { | ||
+ }, | ||
eventNames = [], | ||
serialize = defaultSerialize, | ||
deserialize = defaultDeserialize, | ||
resolver, | ||
+ bind = "rpc", | ||
timeout = DEFAULT_TIMEOUT | ||
} = options; | ||
const rpcPromiseMap = /* @__PURE__ */ new Map(); | ||
let _promise; | ||
+ let closed = false; | ||
const rpc = new Proxy({}, { | ||
get(_, method) { | ||
if (method === "$functions") | ||
return functions; | ||
+ if (method === "$close") | ||
+ return close; | ||
if (method === "then" && !eventNames.includes("then") && !("then" in functions)) | ||
return void 0; | ||
const sendEvent = (...args) => { | ||
@@ -33,7 +39,15 @@ function createBirpc(functions, options) { | ||
return sendEvent; | ||
} | ||
const sendCall = async (...args) => { | ||
- await _promise; | ||
+ if (closed) | ||
+ throw new Error(`[birpc] rpc is closed, cannot call "${method}"`); | ||
+ if (_promise) { | ||
+ try { | ||
+ await _promise; | ||
+ } finally { | ||
+ _promise = void 0; | ||
+ } | ||
+ } | ||
return new Promise((resolve, reject) => { | ||
const id = nanoid(); | ||
let timeoutId; | ||
@@ -58,7 +72,15 @@ function createBirpc(functions, options) { | ||
return sendCall; | ||
} | ||
}); | ||
- _promise = on(async (data, ...extra) => { | ||
+ function close() { | ||
+ closed = true; | ||
+ rpcPromiseMap.forEach(({ reject }) => { | ||
+ reject(new Error("[birpc] rpc is closed")); | ||
+ }); | ||
+ rpcPromiseMap.clear(); | ||
+ off(onMessage); | ||
+ } | ||
+ async function onMessage(data, ...extra) { | ||
const msg = deserialize(data); | ||
if (msg.t === "q") { | ||
const { m: method, a: args } = msg; | ||
@@ -68,7 +90,7 @@ function createBirpc(functions, options) { | ||
error = new Error(`[birpc] function "${method}" not found`); | ||
} else { | ||
try { | ||
- result = await fn.apply(rpc, args); | ||
+ result = await fn.apply(bind === "rpc" ? rpc : functions, args); | ||
} catch (e) { | ||
error = e; | ||
} | ||
@@ -90,7 +112,8 @@ function createBirpc(functions, options) { | ||
} | ||
rpcPromiseMap.delete(ack); | ||
} | ||
- }); | ||
+ } | ||
+ _promise = on(onMessage); | ||
return rpc; | ||
} | ||
const cacheMap = /* @__PURE__ */ new WeakMap(); | ||
diff --git a/dist/index.d.cts b/dist/index.d.cts | ||
index 010f33e6343281a894b6835d89b7fcf1157250a7..f7618f7f8118d24723693415dc321adfa5881458 100644 | ||
--- a/dist/index.d.cts | ||
+++ b/dist/index.d.cts | ||
@@ -11,6 +11,10 @@ interface ChannelOptions { | ||
* Listener to receive raw message | ||
*/ | ||
on: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>; | ||
+ /** | ||
+ * Clear the listener when `$close` is called | ||
+ */ | ||
+ off?: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>; | ||
/** | ||
* Custom function to serialize data | ||
* | ||
@@ -23,6 +27,10 @@ interface ChannelOptions { | ||
* by default it passes the data as-is | ||
*/ | ||
deserialize?: (data: any) => any; | ||
+ /** | ||
+ * Call the methods with the RPC context or the original functions object | ||
+ */ | ||
+ bind?: 'rpc' | 'functions'; | ||
} | ||
interface EventOptions<Remote> { | ||
/** | ||
@@ -71,6 +79,7 @@ type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = { | ||
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>; | ||
} & { | ||
$functions: LocalFunctions; | ||
+ $close: () => void; | ||
}; | ||
type BirpcGroupReturn<RemoteFunctions> = { | ||
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>; | ||
diff --git a/dist/index.d.mts b/dist/index.d.mts | ||
index 010f33e6343281a894b6835d89b7fcf1157250a7..f7618f7f8118d24723693415dc321adfa5881458 100644 | ||
--- a/dist/index.d.mts | ||
+++ b/dist/index.d.mts | ||
@@ -11,6 +11,10 @@ interface ChannelOptions { | ||
* Listener to receive raw message | ||
*/ | ||
on: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>; | ||
+ /** | ||
+ * Clear the listener when `$close` is called | ||
+ */ | ||
+ off?: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>; | ||
/** | ||
* Custom function to serialize data | ||
* | ||
@@ -23,6 +27,10 @@ interface ChannelOptions { | ||
* by default it passes the data as-is | ||
*/ | ||
deserialize?: (data: any) => any; | ||
+ /** | ||
+ * Call the methods with the RPC context or the original functions object | ||
+ */ | ||
+ bind?: 'rpc' | 'functions'; | ||
} | ||
interface EventOptions<Remote> { | ||
/** | ||
@@ -71,6 +79,7 @@ type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = { | ||
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>; | ||
} & { | ||
$functions: LocalFunctions; | ||
+ $close: () => void; | ||
}; | ||
type BirpcGroupReturn<RemoteFunctions> = { | ||
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>; | ||
diff --git a/dist/index.d.ts b/dist/index.d.ts | ||
index 010f33e6343281a894b6835d89b7fcf1157250a7..f7618f7f8118d24723693415dc321adfa5881458 100644 | ||
--- a/dist/index.d.ts | ||
+++ b/dist/index.d.ts | ||
@@ -11,6 +11,10 @@ interface ChannelOptions { | ||
* Listener to receive raw message | ||
*/ | ||
on: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>; | ||
+ /** | ||
+ * Clear the listener when `$close` is called | ||
+ */ | ||
+ off?: (fn: (data: any, ...extras: any[]) => void) => any | Promise<any>; | ||
/** | ||
* Custom function to serialize data | ||
* | ||
@@ -23,6 +27,10 @@ interface ChannelOptions { | ||
* by default it passes the data as-is | ||
*/ | ||
deserialize?: (data: any) => any; | ||
+ /** | ||
+ * Call the methods with the RPC context or the original functions object | ||
+ */ | ||
+ bind?: 'rpc' | 'functions'; | ||
} | ||
interface EventOptions<Remote> { | ||
/** | ||
@@ -71,6 +79,7 @@ type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = { | ||
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>; | ||
} & { | ||
$functions: LocalFunctions; | ||
+ $close: () => void; | ||
}; | ||
type BirpcGroupReturn<RemoteFunctions> = { | ||
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>; | ||
diff --git a/dist/index.mjs b/dist/index.mjs | ||
index 8396fdbfbd7e1df8935c0806af9e7b31f8ccc261..7fcc87a89d7ca21cbf3a3e97ddedec0c51a7ef2a 100644 | ||
index 8396fdbfbd7e1df8935c0806af9e7b31f8ccc261..4544cebb4378902b8e08686ed882689d7102f0f5 100644 | ||
--- a/dist/index.mjs | ||
+++ b/dist/index.mjs | ||
@@ -66,7 +66,7 @@ function createBirpc(functions, options) { | ||
@@ -9,18 +9,24 @@ function createBirpc(functions, options) { | ||
const { | ||
post, | ||
on, | ||
+ off = () => { | ||
+ }, | ||
eventNames = [], | ||
serialize = defaultSerialize, | ||
deserialize = defaultDeserialize, | ||
resolver, | ||
+ bind = "rpc", | ||
timeout = DEFAULT_TIMEOUT | ||
} = options; | ||
const rpcPromiseMap = /* @__PURE__ */ new Map(); | ||
let _promise; | ||
+ let closed = false; | ||
const rpc = new Proxy({}, { | ||
get(_, method) { | ||
if (method === "$functions") | ||
return functions; | ||
+ if (method === "$close") | ||
+ return close; | ||
if (method === "then" && !eventNames.includes("then") && !("then" in functions)) | ||
return void 0; | ||
const sendEvent = (...args) => { | ||
@@ -31,7 +37,15 @@ function createBirpc(functions, options) { | ||
return sendEvent; | ||
} | ||
const sendCall = async (...args) => { | ||
- await _promise; | ||
+ if (closed) | ||
+ throw new Error(`[birpc] rpc is closed, cannot call "${method}"`); | ||
+ if (_promise) { | ||
+ try { | ||
+ await _promise; | ||
+ } finally { | ||
+ _promise = void 0; | ||
+ } | ||
+ } | ||
return new Promise((resolve, reject) => { | ||
const id = nanoid(); | ||
let timeoutId; | ||
@@ -48,7 +62,7 @@ function createBirpc(functions, options) { | ||
if (typeof timeoutId === "object") | ||
timeoutId = timeoutId.unref?.(); | ||
} | ||
- rpcPromiseMap.set(id, { resolve, reject, timeoutId }); | ||
+ rpcPromiseMap.set(id, { resolve, reject, timeoutId, method }); | ||
post(serialize({ m: method, a: args, i: id, t: "q" })); | ||
}); | ||
}; | ||
@@ -56,7 +70,15 @@ function createBirpc(functions, options) { | ||
return sendCall; | ||
} | ||
}); | ||
- _promise = on(async (data, ...extra) => { | ||
+ function close() { | ||
+ closed = true; | ||
+ rpcPromiseMap.forEach(({ reject, method }) => { | ||
+ reject(new Error(`[birpc] rpc is closed, cannot call "${method}"`)); | ||
+ }); | ||
+ rpcPromiseMap.clear(); | ||
+ off(onMessage); | ||
+ } | ||
+ async function onMessage(data, ...extra) { | ||
const msg = deserialize(data); | ||
if (msg.t === "q") { | ||
const { m: method, a: args } = msg; | ||
@@ -66,7 +88,7 @@ function createBirpc(functions, options) { | ||
error = new Error(`[birpc] function "${method}" not found`); | ||
} else { | ||
try { | ||
- result = await fn.apply(rpc, args); | ||
+ result = await fn.apply(functions, args); | ||
+ result = await fn.apply(bind === "rpc" ? rpc : functions, args); | ||
} catch (e) { | ||
error = e; | ||
} | ||
@@ -88,7 +110,8 @@ function createBirpc(functions, options) { | ||
} | ||
rpcPromiseMap.delete(ack); | ||
} | ||
- }); | ||
+ } | ||
+ _promise = on(onMessage); | ||
return rpc; | ||
} | ||
const cacheMap = /* @__PURE__ */ new WeakMap(); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.