electrobun 0.0.18 → 0.0.19-beta.6
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/BETA_RELEASE.md +67 -0
- package/README.md +48 -21
- package/{dist → bin}/electrobun +0 -0
- package/package.json +23 -29
- package/src/cli/bun.lockb +0 -0
- package/src/cli/index.ts +1527 -0
- package/src/cli/package-lock.json +93 -0
- package/src/cli/package.json +14 -0
- package/test-npm-install.sh +34 -0
- package/dist/api/browser/builtinrpcSchema.ts +0 -10
- package/dist/api/browser/index.ts +0 -474
- package/dist/api/browser/stylesAndElements.ts +0 -3
- package/dist/api/browser/webviewtag.ts +0 -650
- package/dist/api/bun/core/ApplicationMenu.ts +0 -66
- package/dist/api/bun/core/BrowserView.ts +0 -417
- package/dist/api/bun/core/BrowserWindow.ts +0 -178
- package/dist/api/bun/core/ContextMenu.ts +0 -67
- package/dist/api/bun/core/Paths.ts +0 -5
- package/dist/api/bun/core/Socket.ts +0 -181
- package/dist/api/bun/core/Tray.ts +0 -105
- package/dist/api/bun/core/Updater.ts +0 -388
- package/dist/api/bun/core/Utils.ts +0 -48
- package/dist/api/bun/events/applicationEvents.ts +0 -14
- package/dist/api/bun/events/event.ts +0 -29
- package/dist/api/bun/events/eventEmitter.ts +0 -45
- package/dist/api/bun/events/trayEvents.ts +0 -9
- package/dist/api/bun/events/webviewEvents.ts +0 -19
- package/dist/api/bun/events/windowEvents.ts +0 -12
- package/dist/api/bun/index.ts +0 -45
- package/dist/api/bun/proc/zig.ts +0 -622
- package/dist/bsdiff +0 -0
- package/dist/bspatch +0 -0
- package/dist/bun +0 -0
- package/dist/extractor +0 -0
- package/dist/launcher +0 -0
- package/dist/webview +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "electrobun-cli",
|
|
3
|
+
"lockfileVersion": 3,
|
|
4
|
+
"requires": true,
|
|
5
|
+
"packages": {
|
|
6
|
+
"": {
|
|
7
|
+
"name": "electrobun-cli",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@oneidentity/zstd-js": "^1.0.3",
|
|
10
|
+
"bsdiff-wasm": "^0.1.4",
|
|
11
|
+
"node-tar": "^1.0.0"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/bun": "latest"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"typescript": "^5.0.0"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"node_modules/@oneidentity/zstd-js": {
|
|
21
|
+
"version": "1.0.3",
|
|
22
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@types/emscripten": "^1.39.4"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"node_modules/@types/bun": {
|
|
28
|
+
"version": "1.0.10",
|
|
29
|
+
"resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.0.10.tgz",
|
|
30
|
+
"integrity": "sha512-Jaz6YYAdm1u3NVlgSyEK+qGmrlLQ20sbWeEoXD64b9w6z/YKYNWlfaphu+xF2Kiy5Tpykm5Q9jIquLegwXx4ng==",
|
|
31
|
+
"dev": true,
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"bun-types": "1.0.33"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"node_modules/@types/emscripten": {
|
|
37
|
+
"version": "1.39.10",
|
|
38
|
+
"license": "MIT"
|
|
39
|
+
},
|
|
40
|
+
"node_modules/@types/node": {
|
|
41
|
+
"version": "20.11.30",
|
|
42
|
+
"dev": true,
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"undici-types": "~5.26.4"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"node_modules/@types/ws": {
|
|
49
|
+
"version": "8.5.10",
|
|
50
|
+
"dev": true,
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@types/node": "*"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"node_modules/bsdiff-wasm": {
|
|
57
|
+
"version": "0.1.4",
|
|
58
|
+
"license": "MIT"
|
|
59
|
+
},
|
|
60
|
+
"node_modules/bun-types": {
|
|
61
|
+
"version": "1.0.33",
|
|
62
|
+
"dev": true,
|
|
63
|
+
"license": "MIT",
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@types/node": "~20.11.3",
|
|
66
|
+
"@types/ws": "~8.5.10"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"node_modules/node-tar": {
|
|
70
|
+
"version": "1.0.0",
|
|
71
|
+
"resolved": "https://registry.npmjs.org/node-tar/-/node-tar-1.0.0.tgz",
|
|
72
|
+
"integrity": "sha512-cowng5lugLQ3Bb5wWYfWM3067/S9xHDwCw3RWbqn0swqmgApDwklyg31XRci97cT7gNbVHmxoXQSkr2zDi5n+g==",
|
|
73
|
+
"deprecated": "please use 'tar'"
|
|
74
|
+
},
|
|
75
|
+
"node_modules/typescript": {
|
|
76
|
+
"version": "5.4.3",
|
|
77
|
+
"license": "Apache-2.0",
|
|
78
|
+
"peer": true,
|
|
79
|
+
"bin": {
|
|
80
|
+
"tsc": "bin/tsc",
|
|
81
|
+
"tsserver": "bin/tsserver"
|
|
82
|
+
},
|
|
83
|
+
"engines": {
|
|
84
|
+
"node": ">=14.17"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"node_modules/undici-types": {
|
|
88
|
+
"version": "5.26.5",
|
|
89
|
+
"dev": true,
|
|
90
|
+
"license": "MIT"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Test npm installation locally
|
|
4
|
+
echo "Testing Electrobun npm installation..."
|
|
5
|
+
|
|
6
|
+
# Create a temporary test directory
|
|
7
|
+
TEST_DIR=$(mktemp -d)
|
|
8
|
+
cd $TEST_DIR
|
|
9
|
+
|
|
10
|
+
echo "Test directory: $TEST_DIR"
|
|
11
|
+
|
|
12
|
+
# Initialize a test project
|
|
13
|
+
npm init -y
|
|
14
|
+
|
|
15
|
+
# Set environment variable to use specific version
|
|
16
|
+
export ELECTROBUN_VERSION=v0.0.19-beta.1
|
|
17
|
+
|
|
18
|
+
# Install electrobun (will use local package.json)
|
|
19
|
+
npm install file:///home/yoav/code/electrobun
|
|
20
|
+
|
|
21
|
+
# Check if installation worked
|
|
22
|
+
if [ -f "node_modules/electrobun/dist/electrobun" ]; then
|
|
23
|
+
echo "✓ Electrobun CLI installed successfully"
|
|
24
|
+
./node_modules/.bin/electrobun --version
|
|
25
|
+
else
|
|
26
|
+
echo "✗ Electrobun CLI not found"
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# List installed files
|
|
30
|
+
echo -e "\nInstalled files:"
|
|
31
|
+
find node_modules/electrobun -type f -name "*.ts" | head -10
|
|
32
|
+
find node_modules/electrobun/dist -type f | head -10
|
|
33
|
+
|
|
34
|
+
echo -e "\nTest complete. Directory: $TEST_DIR"
|
|
@@ -1,474 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type RPCSchema,
|
|
3
|
-
type RPCRequestHandler,
|
|
4
|
-
type RPCOptions,
|
|
5
|
-
type RPCMessageHandlerFn,
|
|
6
|
-
type WildcardRPCMessageHandlerFn,
|
|
7
|
-
type RPCTransport,
|
|
8
|
-
createRPC,
|
|
9
|
-
} from "rpc-anywhere";
|
|
10
|
-
import { ConfigureWebviewTags } from "./webviewtag";
|
|
11
|
-
// todo: should this just be injected as a preload script?
|
|
12
|
-
import { isAppRegionDrag } from "./stylesAndElements";
|
|
13
|
-
import type { BuiltinBunToWebviewSchema } from "./builtinrpcSchema";
|
|
14
|
-
|
|
15
|
-
interface ElectrobunWebviewRPCSChema {
|
|
16
|
-
bun: RPCSchema;
|
|
17
|
-
webview: RPCSchema;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const WEBVIEW_ID = window.__electrobunWebviewId;
|
|
21
|
-
const RPC_SOCKET_PORT = window.__electrobunRpcSocketPort;
|
|
22
|
-
|
|
23
|
-
// todo (yoav): move this stuff to browser/rpc/webview.ts
|
|
24
|
-
type ZigWebviewHandlers = RPCSchema<{
|
|
25
|
-
requests: {
|
|
26
|
-
webviewTagCallAsyncJavaScript: {
|
|
27
|
-
params: {
|
|
28
|
-
messageId: string;
|
|
29
|
-
webviewId: number;
|
|
30
|
-
hostWebviewId: number;
|
|
31
|
-
script: string;
|
|
32
|
-
};
|
|
33
|
-
response: void;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
}>;
|
|
37
|
-
|
|
38
|
-
type WebviewTagHandlers = RPCSchema<{
|
|
39
|
-
requests: {};
|
|
40
|
-
messages: {
|
|
41
|
-
webviewTagResize: {
|
|
42
|
-
id: number;
|
|
43
|
-
frame: {
|
|
44
|
-
x: number;
|
|
45
|
-
y: number;
|
|
46
|
-
width: number;
|
|
47
|
-
height: number;
|
|
48
|
-
};
|
|
49
|
-
masks: string;
|
|
50
|
-
};
|
|
51
|
-
webviewTagUpdateSrc: {
|
|
52
|
-
id: number;
|
|
53
|
-
url: string;
|
|
54
|
-
};
|
|
55
|
-
webviewTagGoBack: {
|
|
56
|
-
id: number;
|
|
57
|
-
};
|
|
58
|
-
webviewTagGoForward: {
|
|
59
|
-
id: number;
|
|
60
|
-
};
|
|
61
|
-
webviewTagReload: {
|
|
62
|
-
id: number;
|
|
63
|
-
};
|
|
64
|
-
webviewTagRemove: {
|
|
65
|
-
id: number;
|
|
66
|
-
};
|
|
67
|
-
startWindowMove: {
|
|
68
|
-
id: number;
|
|
69
|
-
};
|
|
70
|
-
stopWindowMove: {
|
|
71
|
-
id: number;
|
|
72
|
-
};
|
|
73
|
-
moveWindowBy: {
|
|
74
|
-
id: number;
|
|
75
|
-
x: number;
|
|
76
|
-
y: number;
|
|
77
|
-
};
|
|
78
|
-
webviewTagSetTransparent: {
|
|
79
|
-
id: number;
|
|
80
|
-
transparent: boolean;
|
|
81
|
-
};
|
|
82
|
-
webviewTagToggleMirroring: {
|
|
83
|
-
id: number;
|
|
84
|
-
enable: boolean;
|
|
85
|
-
};
|
|
86
|
-
webviewTagSetPassthrough: {
|
|
87
|
-
id: number;
|
|
88
|
-
enablePassthrough: boolean;
|
|
89
|
-
};
|
|
90
|
-
webviewTagSetHidden: {
|
|
91
|
-
id: number;
|
|
92
|
-
hidden: boolean;
|
|
93
|
-
};
|
|
94
|
-
};
|
|
95
|
-
}>;
|
|
96
|
-
|
|
97
|
-
class Electroview<T> {
|
|
98
|
-
bunSocket?: WebSocket;
|
|
99
|
-
// user's custom rpc browser <-> bun
|
|
100
|
-
rpc?: T;
|
|
101
|
-
rpcHandler?: (msg: any) => void;
|
|
102
|
-
// electrobun rpc browser <-> zig
|
|
103
|
-
zigRpc?: any;
|
|
104
|
-
zigRpcHandler?: (msg: any) => void;
|
|
105
|
-
// give it a default function
|
|
106
|
-
syncRpc: (params: any) => any = () => {
|
|
107
|
-
console.log("syncRpc not initialized");
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
constructor(config: { rpc: T }) {
|
|
111
|
-
this.rpc = config.rpc;
|
|
112
|
-
this.init();
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
init() {
|
|
116
|
-
// todo (yoav): should init webviewTag by default when src is local
|
|
117
|
-
// and have a setting that forces it enabled or disabled
|
|
118
|
-
this.initZigRpc();
|
|
119
|
-
this.initSocketToBun();
|
|
120
|
-
// Note:
|
|
121
|
-
// syncRPC messages doesn't need to be defined since there's no need for sync 1-way message
|
|
122
|
-
// just use non-blocking async rpc for that, we just need sync requests
|
|
123
|
-
// We don't need request ids either since we're not receiving the response on a different pipe
|
|
124
|
-
if (true) {
|
|
125
|
-
// TODO: define sync requests on schema (separate from async reqeusts and messages)
|
|
126
|
-
this.syncRpc = (msg: { method: string; params: any }) => {
|
|
127
|
-
try {
|
|
128
|
-
const messageString = JSON.stringify(msg);
|
|
129
|
-
return this.bunBridgeSync(messageString);
|
|
130
|
-
} catch (error) {
|
|
131
|
-
console.error(
|
|
132
|
-
"bun: failed to serialize message to webview syncRpc",
|
|
133
|
-
error
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
ConfigureWebviewTags(true, this.zigRpc, this.syncRpc);
|
|
139
|
-
|
|
140
|
-
this.initElectrobunListeners();
|
|
141
|
-
|
|
142
|
-
window.__electrobun = {
|
|
143
|
-
receiveMessageFromBun: this.receiveMessageFromBun.bind(this),
|
|
144
|
-
receiveMessageFromZig: this.receiveMessageFromZig.bind(this),
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
if (this.rpc) {
|
|
148
|
-
this.rpc.setTransport(this.createTransport());
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
initZigRpc() {
|
|
153
|
-
this.zigRpc = createRPC<WebviewTagHandlers, ZigWebviewHandlers>({
|
|
154
|
-
transport: this.createZigTransport(),
|
|
155
|
-
// requestHandler: {
|
|
156
|
-
|
|
157
|
-
// },
|
|
158
|
-
maxRequestTime: 1000,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
initSocketToBun() {
|
|
163
|
-
// todo: upgrade to tls
|
|
164
|
-
const socket = new WebSocket(
|
|
165
|
-
`ws://localhost:${RPC_SOCKET_PORT}/socket?webviewId=${WEBVIEW_ID}`
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
this.bunSocket = socket;
|
|
169
|
-
|
|
170
|
-
socket.addEventListener("open", () => {
|
|
171
|
-
// this.bunSocket?.send("Hello from webview " + WEBVIEW_ID);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
socket.addEventListener("message", async (event) => {
|
|
175
|
-
const message = event.data;
|
|
176
|
-
if (typeof message === "string") {
|
|
177
|
-
try {
|
|
178
|
-
const encryptedPacket = JSON.parse(message);
|
|
179
|
-
|
|
180
|
-
const decrypted = await window.__electrobun_decrypt(
|
|
181
|
-
encryptedPacket.encryptedData,
|
|
182
|
-
encryptedPacket.iv,
|
|
183
|
-
encryptedPacket.tag
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
this.rpcHandler?.(JSON.parse(decrypted));
|
|
187
|
-
} catch (err) {
|
|
188
|
-
console.error("Error parsing bun message:", err);
|
|
189
|
-
}
|
|
190
|
-
} else if (message instanceof Blob) {
|
|
191
|
-
// Handle binary data (e.g., convert Blob to ArrayBuffer if needed)
|
|
192
|
-
} else {
|
|
193
|
-
console.error("UNKNOWN DATA TYPE RECEIVED:", event.data);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
socket.addEventListener("error", (event) => {
|
|
198
|
-
console.error("Socket error:", event);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
socket.addEventListener("close", (event) => {
|
|
202
|
-
// console.log("Socket closed:", event);
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// This will be attached to the global object, zig can rpc reply by executingJavascript
|
|
207
|
-
// of that global reference to the function
|
|
208
|
-
receiveMessageFromZig(msg: any) {
|
|
209
|
-
if (this.zigRpcHandler) {
|
|
210
|
-
this.zigRpcHandler(msg);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// TODO: implement proper rpc-anywhere style rpc here
|
|
215
|
-
// todo: this is duplicated in webviewtag.ts and should be DRYed up
|
|
216
|
-
sendToZig(message: {}) {
|
|
217
|
-
window.webkit.messageHandlers.webviewTagBridge.postMessage(
|
|
218
|
-
JSON.stringify(message)
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
initElectrobunListeners() {
|
|
223
|
-
document.addEventListener("mousedown", (e) => {
|
|
224
|
-
if (isAppRegionDrag(e)) {
|
|
225
|
-
this.zigRpc?.send.startWindowMove({ id: WEBVIEW_ID });
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
document.addEventListener("mouseup", (e) => {
|
|
230
|
-
if (isAppRegionDrag(e)) {
|
|
231
|
-
this.zigRpc?.send.stopWindowMove({ id: WEBVIEW_ID });
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
createTransport() {
|
|
237
|
-
const that = this;
|
|
238
|
-
return {
|
|
239
|
-
send(message) {
|
|
240
|
-
try {
|
|
241
|
-
const messageString = JSON.stringify(message);
|
|
242
|
-
that.bunBridge(messageString);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.error("bun: failed to serialize message to webview", error);
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
registerHandler(handler) {
|
|
248
|
-
that.rpcHandler = handler;
|
|
249
|
-
},
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
createZigTransport(): RPCTransport {
|
|
254
|
-
const that = this;
|
|
255
|
-
return {
|
|
256
|
-
send(message) {
|
|
257
|
-
window.webkit.messageHandlers.webviewTagBridge.postMessage(
|
|
258
|
-
JSON.stringify(message)
|
|
259
|
-
);
|
|
260
|
-
},
|
|
261
|
-
registerHandler(handler) {
|
|
262
|
-
that.zigRpcHandler = handler;
|
|
263
|
-
// webview tag doesn't handle any messages from zig just yet
|
|
264
|
-
},
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// call any of your bun syncrpc methods in a way that appears synchronous from the browser context
|
|
269
|
-
bunBridgeSync(msg: string) {
|
|
270
|
-
console.warn("DEPRECATED: use async rpc if possible");
|
|
271
|
-
var xhr = new XMLHttpRequest();
|
|
272
|
-
// Note: setting false here makes the xhr request blocking. This completely
|
|
273
|
-
// blocks the main thread which is terrible. You can use this safely from a webworker.
|
|
274
|
-
// There are also cases where exposing bun sync apis (eg: existsSync) is useful especially
|
|
275
|
-
// on a first pass when migrating from Electron to Electrobun.
|
|
276
|
-
// This mechanism is designed to make any rpc call over the bridge into a sync blocking call
|
|
277
|
-
// from the browser context while bun asynchronously replies. Use it sparingly from the main thread.
|
|
278
|
-
xhr.open("POST", "views://syncrpc", false); // Synchronous call
|
|
279
|
-
xhr.send(msg);
|
|
280
|
-
if (!xhr.responseText) {
|
|
281
|
-
return xhr.responseText;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
try {
|
|
285
|
-
return JSON.parse(xhr.responseText);
|
|
286
|
-
} catch {
|
|
287
|
-
return xhr.responseText;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
async bunBridge(msg: string) {
|
|
292
|
-
if (this.bunSocket?.readyState === WebSocket.OPEN) {
|
|
293
|
-
try {
|
|
294
|
-
const { encryptedData, iv, tag } = await window.__electrobun_encrypt(
|
|
295
|
-
msg
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
const encryptedPacket = {
|
|
299
|
-
encryptedData: encryptedData,
|
|
300
|
-
iv: iv,
|
|
301
|
-
tag: tag,
|
|
302
|
-
};
|
|
303
|
-
const encryptedPacketString = JSON.stringify(encryptedPacket);
|
|
304
|
-
this.bunSocket.send(encryptedPacketString);
|
|
305
|
-
return;
|
|
306
|
-
} catch (error) {
|
|
307
|
-
console.error("Error sending message to bun via socket:", error);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// if socket's are unavailable, fallback to postMessage
|
|
312
|
-
|
|
313
|
-
// Note: messageHandlers seem to freeze when sending large messages
|
|
314
|
-
// but xhr to views://rpc can run into CORS issues on non views://
|
|
315
|
-
// loaded content (eg: when writing extensions/preload scripts for
|
|
316
|
-
// remote content).
|
|
317
|
-
|
|
318
|
-
// Since most messages--especially those on remote content, are small
|
|
319
|
-
// we can solve most use cases by having a fallback to xhr for
|
|
320
|
-
// large messages
|
|
321
|
-
|
|
322
|
-
// TEMP: disable the fallback for now. for some reason suddenly can't
|
|
323
|
-
// repro now that other places are chunking messages and laptop restart
|
|
324
|
-
|
|
325
|
-
if (true || msg.length < 8 * 1024) {
|
|
326
|
-
window.webkit.messageHandlers.bunBridge.postMessage(msg);
|
|
327
|
-
} else {
|
|
328
|
-
var xhr = new XMLHttpRequest();
|
|
329
|
-
|
|
330
|
-
// Note: we're only using synchronouse http on this async
|
|
331
|
-
// call to get around CORS for now
|
|
332
|
-
// Note: DO NOT use postMessage handlers since it
|
|
333
|
-
// freezes the process when sending lots of large messages
|
|
334
|
-
|
|
335
|
-
xhr.open("POST", "views://rpc", false); // sychronous call
|
|
336
|
-
xhr.send(msg);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
receiveMessageFromBun(msg) {
|
|
341
|
-
// NOTE: in the webview messages are passed by executing ElectrobunView.receiveMessageFromBun(object)
|
|
342
|
-
// so they're already parsed into an object here
|
|
343
|
-
if (this.rpcHandler) {
|
|
344
|
-
this.rpcHandler(msg);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
// todo (yoav): This is mostly just the reverse of the one in BrowserView.ts on the bun side. Should DRY this up.
|
|
348
|
-
static defineRPC<
|
|
349
|
-
Schema extends ElectrobunWebviewRPCSChema,
|
|
350
|
-
BunSchema extends RPCSchema = Schema["bun"],
|
|
351
|
-
WebviewSchema extends RPCSchema = Schema["webview"]
|
|
352
|
-
>(config: {
|
|
353
|
-
maxRequestTime?: number;
|
|
354
|
-
handlers: {
|
|
355
|
-
requests?: RPCRequestHandler<WebviewSchema["requests"]>;
|
|
356
|
-
messages?: {
|
|
357
|
-
[key in keyof WebviewSchema["messages"]]: RPCMessageHandlerFn<
|
|
358
|
-
WebviewSchema["messages"],
|
|
359
|
-
key
|
|
360
|
-
>;
|
|
361
|
-
} & {
|
|
362
|
-
"*"?: WildcardRPCMessageHandlerFn<WebviewSchema["messages"]>;
|
|
363
|
-
};
|
|
364
|
-
};
|
|
365
|
-
}) {
|
|
366
|
-
// Note: RPC Anywhere requires defining the requests that a schema handles and the messages that a schema sends.
|
|
367
|
-
// eg: BunSchema {
|
|
368
|
-
// requests: // ... requests bun handles, sent by webview
|
|
369
|
-
// messages: // ... messages bun sends, handled by webview
|
|
370
|
-
// }
|
|
371
|
-
// In some generlized contexts that makes sense,
|
|
372
|
-
// In the Electrobun context it can feel a bit counter-intuitive so we swap this around a bit. In Electrobun, the
|
|
373
|
-
// webview and bun are known endpoints so we simplify schema definitions by combining them.
|
|
374
|
-
// Schema {
|
|
375
|
-
// bun: BunSchema {
|
|
376
|
-
// requests: // ... requests bun sends, handled by webview,
|
|
377
|
-
// messages: // ... messages bun sends, handled by webview
|
|
378
|
-
// },
|
|
379
|
-
// webview: WebviewSchema {
|
|
380
|
-
// requests: // ... requests webview sends, handled by bun,
|
|
381
|
-
// messages: // ... messages webview sends, handled by bun
|
|
382
|
-
// },
|
|
383
|
-
// }
|
|
384
|
-
// electrobun also treats messages as "requests that we don't wait for to complete", and normalizes specifying the
|
|
385
|
-
// handlers for them alongside request handlers.
|
|
386
|
-
|
|
387
|
-
const builtinHandlers: {
|
|
388
|
-
requests: RPCRequestHandler<BuiltinBunToWebviewSchema["requests"]>;
|
|
389
|
-
} = {
|
|
390
|
-
requests: {
|
|
391
|
-
evaluateJavascriptWithResponse: ({ script }) => {
|
|
392
|
-
return new Promise((resolve) => {
|
|
393
|
-
try {
|
|
394
|
-
const resultFunction = new Function(script);
|
|
395
|
-
const result = resultFunction();
|
|
396
|
-
|
|
397
|
-
if (result instanceof Promise) {
|
|
398
|
-
result
|
|
399
|
-
.then((resolvedResult) => {
|
|
400
|
-
resolve(resolvedResult);
|
|
401
|
-
})
|
|
402
|
-
.catch((error) => {
|
|
403
|
-
console.error("bun: async script execution failed", error);
|
|
404
|
-
resolve(String(error));
|
|
405
|
-
});
|
|
406
|
-
} else {
|
|
407
|
-
resolve(result);
|
|
408
|
-
}
|
|
409
|
-
} catch (error) {
|
|
410
|
-
console.error("bun: failed to eval script", error);
|
|
411
|
-
resolve(String(error));
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
},
|
|
415
|
-
},
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
type mixedWebviewSchema = {
|
|
419
|
-
requests: BunSchema["requests"];
|
|
420
|
-
messages: WebviewSchema["messages"];
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
type mixedBunSchema = {
|
|
424
|
-
requests: WebviewSchema["requests"] &
|
|
425
|
-
BuiltinBunToWebviewSchema["requests"];
|
|
426
|
-
messages: BunSchema["messages"];
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
const rpcOptions = {
|
|
430
|
-
maxRequestTime: config.maxRequestTime,
|
|
431
|
-
requestHandler: {
|
|
432
|
-
...config.handlers.requests,
|
|
433
|
-
...builtinHandlers.requests,
|
|
434
|
-
},
|
|
435
|
-
transport: {
|
|
436
|
-
// Note: RPC Anywhere will throw if you try add a message listener if transport.registerHandler is falsey
|
|
437
|
-
registerHandler: () => {},
|
|
438
|
-
},
|
|
439
|
-
} as RPCOptions<mixedBunSchema, mixedWebviewSchema>;
|
|
440
|
-
|
|
441
|
-
const rpc = createRPC<mixedBunSchema, mixedWebviewSchema>(rpcOptions);
|
|
442
|
-
|
|
443
|
-
const messageHandlers = config.handlers.messages;
|
|
444
|
-
if (messageHandlers) {
|
|
445
|
-
// note: this can only be done once there is a transport
|
|
446
|
-
// @ts-ignore - this is due to all the schema mixing we're doing, fine to ignore
|
|
447
|
-
// while types in here are borked, they resolve correctly/bubble up to the defineRPC call site.
|
|
448
|
-
rpc.addMessageListener(
|
|
449
|
-
"*",
|
|
450
|
-
(messageName: keyof WebviewSchema["messages"], payload) => {
|
|
451
|
-
const globalHandler = messageHandlers["*"];
|
|
452
|
-
if (globalHandler) {
|
|
453
|
-
globalHandler(messageName, payload);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
const messageHandler = messageHandlers[messageName];
|
|
457
|
-
if (messageHandler) {
|
|
458
|
-
messageHandler(payload);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
return rpc;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
export { type RPCSchema, createRPC, Electroview };
|
|
469
|
-
|
|
470
|
-
const Electrobun = {
|
|
471
|
-
Electroview,
|
|
472
|
-
};
|
|
473
|
-
|
|
474
|
-
export default Electrobun;
|