bunite-core 0.0.12 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/bun/core/BrowserView.ts +5 -2
- package/src/shared/rpc.ts +11 -0
- package/src/shared/webRpcHandler.ts +86 -32
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import { ptr } from "bun:ffi";
|
|
|
2
2
|
import { buildViewPreloadScript } from "../preload/inline";
|
|
3
3
|
import { log } from "../../shared/log";
|
|
4
4
|
import { buniteEventEmitter } from "../events/eventEmitter";
|
|
5
|
-
import { defineBuniteRPC, type BuniteRPCConfig, type BuniteRPCSchema, type RPCWithTransport
|
|
5
|
+
import { defineBuniteRPC, type BuniteRPCConfig, type BuniteRPCSchema, type RPCWithTransport } from "../../shared/rpc";
|
|
6
6
|
import { createWebRPCHandler } from "../../shared/webRpcHandler";
|
|
7
7
|
import { ensureNativeRuntime, getNativeLibrary, toCString, waitForViewReady, cancelWaitForViewReady } from "../proc/native";
|
|
8
8
|
import { attachBrowserViewRegistry, getRPCPort, sendMessageToView } from "./Socket";
|
|
@@ -165,8 +165,11 @@ export class BrowserView<T extends RPCWithTransport = RPCWithTransport> {
|
|
|
165
165
|
config: BuniteRPCConfig<Schema, "bun">
|
|
166
166
|
) {
|
|
167
167
|
const rpc = defineBuniteRPC("bun", config);
|
|
168
|
+
const webRpc = createWebRPCHandler<Schema>(config);
|
|
168
169
|
return Object.assign(rpc, {
|
|
169
|
-
webHandler:
|
|
170
|
+
webHandler: webRpc,
|
|
171
|
+
webClients: webRpc.webClients,
|
|
172
|
+
broadcast: webRpc.broadcast,
|
|
170
173
|
});
|
|
171
174
|
}
|
|
172
175
|
|
package/src/shared/rpc.ts
CHANGED
|
@@ -343,6 +343,16 @@ export function createRPC<
|
|
|
343
343
|
) => void;
|
|
344
344
|
};
|
|
345
345
|
|
|
346
|
+
function dispose() {
|
|
347
|
+
for (const [id, pending] of pendingRequests) {
|
|
348
|
+
clearTimeout(pending.timeout);
|
|
349
|
+
pending.reject(new Error("RPC disposed"));
|
|
350
|
+
}
|
|
351
|
+
pendingRequests.clear();
|
|
352
|
+
transport.unregisterHandler?.();
|
|
353
|
+
transport = {};
|
|
354
|
+
}
|
|
355
|
+
|
|
346
356
|
return {
|
|
347
357
|
setTransport,
|
|
348
358
|
setRequestHandler,
|
|
@@ -352,6 +362,7 @@ export function createRPC<
|
|
|
352
362
|
sendProxy,
|
|
353
363
|
addMessageListener,
|
|
354
364
|
removeMessageListener,
|
|
365
|
+
dispose,
|
|
355
366
|
proxy: {
|
|
356
367
|
request: requestProxy,
|
|
357
368
|
send: sendProxy
|
|
@@ -1,48 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineBuniteRPC,
|
|
3
|
+
type BuniteRPCConfig,
|
|
4
|
+
type BuniteRPCSchema,
|
|
5
|
+
type RPCTransport,
|
|
6
|
+
type RPCPacket
|
|
7
|
+
} from "./rpc";
|
|
1
8
|
import { decodeRPCPacket, encodeRPCPacket, asUint8Array } from "./rpcWire";
|
|
9
|
+
import { log } from "./log";
|
|
2
10
|
|
|
3
|
-
type
|
|
11
|
+
type WebRPCSocket = { send(data: Uint8Array | ArrayBuffer): void | number };
|
|
4
12
|
|
|
5
|
-
|
|
6
|
-
|
|
13
|
+
export type WebRPCClient<Schema extends BuniteRPCSchema = BuniteRPCSchema> = {
|
|
14
|
+
ws: WebRPCSocket;
|
|
15
|
+
rpc: ReturnType<typeof defineBuniteRPC<Schema, "bun">>;
|
|
16
|
+
handlePacket: (packet: RPCPacket) => void | Promise<void>;
|
|
17
|
+
};
|
|
7
18
|
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
19
|
+
export function createWebRPCHandler<Schema extends BuniteRPCSchema>(
|
|
20
|
+
config: BuniteRPCConfig<Schema, "bun"> & {
|
|
21
|
+
extraRequestHandlers?: Record<string, (...args: any[]) => unknown>;
|
|
22
|
+
}
|
|
23
|
+
) {
|
|
24
|
+
const connections = new WeakMap<WebRPCSocket, WebRPCClient<Schema>>();
|
|
25
|
+
const webClients = new Set<WebRPCClient<Schema>>();
|
|
26
|
+
|
|
27
|
+
const handler = {
|
|
28
|
+
open(ws: WebRPCSocket) {
|
|
29
|
+
let handlePacket: ((packet: RPCPacket) => void | Promise<void>) | undefined;
|
|
30
|
+
|
|
31
|
+
const transport: RPCTransport = {
|
|
32
|
+
send(packet) {
|
|
33
|
+
ws.send(encodeRPCPacket(packet));
|
|
34
|
+
},
|
|
35
|
+
registerHandler(h) {
|
|
36
|
+
handlePacket = h;
|
|
37
|
+
},
|
|
38
|
+
unregisterHandler() {
|
|
39
|
+
handlePacket = undefined;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const rpc = defineBuniteRPC("bun", config);
|
|
44
|
+
rpc.setTransport(transport);
|
|
45
|
+
|
|
46
|
+
const client: WebRPCClient<Schema> = {
|
|
47
|
+
ws,
|
|
48
|
+
rpc: rpc as WebRPCClient<Schema>["rpc"],
|
|
49
|
+
handlePacket: (packet) => handlePacket?.(packet)
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
connections.set(ws, client);
|
|
53
|
+
webClients.add(client);
|
|
54
|
+
handler.onWebClientConnected?.(client);
|
|
55
|
+
},
|
|
11
56
|
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
message(ws: WebRPCSocket, raw: string | Buffer) {
|
|
57
|
+
message(ws: WebRPCSocket, raw: string | Buffer | ArrayBuffer | Uint8Array) {
|
|
15
58
|
if (typeof raw === "string") return;
|
|
16
59
|
|
|
17
|
-
|
|
60
|
+
const client = connections.get(ws);
|
|
61
|
+
if (!client) return;
|
|
62
|
+
|
|
18
63
|
try {
|
|
19
|
-
|
|
64
|
+
Promise.resolve(client.handlePacket(decodeRPCPacket(asUint8Array(raw)))).catch((error) => {
|
|
65
|
+
log.error("Web RPC packet handler error", error);
|
|
66
|
+
});
|
|
20
67
|
} catch {
|
|
21
|
-
|
|
68
|
+
// malformed packet — decode failure
|
|
22
69
|
}
|
|
70
|
+
},
|
|
23
71
|
|
|
24
|
-
|
|
72
|
+
close(ws: WebRPCSocket) {
|
|
73
|
+
const client = connections.get(ws);
|
|
74
|
+
if (!client) return;
|
|
25
75
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
76
|
+
client.rpc.dispose();
|
|
77
|
+
webClients.delete(client);
|
|
78
|
+
connections.delete(ws);
|
|
79
|
+
handler.onWebClientDisconnected?.(client);
|
|
80
|
+
},
|
|
33
81
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
82
|
+
webClients: webClients as ReadonlySet<WebRPCClient<Schema>>,
|
|
83
|
+
|
|
84
|
+
broadcast<M extends keyof Schema["bun"]["messages"]>(
|
|
85
|
+
messageName: M,
|
|
86
|
+
...args: void extends Schema["bun"]["messages"][M]
|
|
87
|
+
? []
|
|
88
|
+
: undefined extends Schema["bun"]["messages"][M]
|
|
89
|
+
? [payload?: Schema["bun"]["messages"][M]]
|
|
90
|
+
: [payload: Schema["bun"]["messages"][M]]
|
|
91
|
+
) {
|
|
92
|
+
for (const client of webClients) {
|
|
93
|
+
(client.rpc.send as any)(messageName, ...args);
|
|
45
94
|
}
|
|
46
|
-
}
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
onWebClientConnected: undefined as ((client: WebRPCClient<Schema>) => void) | undefined,
|
|
98
|
+
onWebClientDisconnected: undefined as ((client: WebRPCClient<Schema>) => void) | undefined,
|
|
47
99
|
};
|
|
100
|
+
|
|
101
|
+
return handler;
|
|
48
102
|
}
|