sparkbun 0.1.0

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.
Files changed (131) hide show
  1. package/bin/sparkbun.cjs +18 -0
  2. package/dist-linux-arm64/bsdiff +0 -0
  3. package/dist-linux-arm64/bspatch +0 -0
  4. package/dist-linux-arm64/libElectrobunCore.so +0 -0
  5. package/dist-linux-arm64/libNativeWrapper.so +0 -0
  6. package/dist-linux-arm64/libasar.so +0 -0
  7. package/dist-linux-x64/bsdiff +0 -0
  8. package/dist-linux-x64/bspatch +0 -0
  9. package/dist-linux-x64/libElectrobunCore.so +0 -0
  10. package/dist-linux-x64/libNativeWrapper.so +0 -0
  11. package/dist-linux-x64/libasar.so +0 -0
  12. package/dist-macos-arm64/bsdiff +0 -0
  13. package/dist-macos-arm64/bspatch +0 -0
  14. package/dist-macos-arm64/libElectrobunCore.dylib +0 -0
  15. package/dist-macos-arm64/libNativeWrapper.dylib +0 -0
  16. package/dist-macos-arm64/libasar.dylib +0 -0
  17. package/dist-macos-arm64/libwebgpu_dawn.dylib +0 -0
  18. package/dist-macos-arm64/preload-full.js +885 -0
  19. package/dist-macos-arm64/preload-sandboxed.js +111 -0
  20. package/dist-macos-arm64/process_helper +0 -0
  21. package/dist-win-x64/ElectrobunCore.dll +0 -0
  22. package/dist-win-x64/WebView2Loader.dll +0 -0
  23. package/dist-win-x64/bsdiff.exe +0 -0
  24. package/dist-win-x64/bspatch.exe +0 -0
  25. package/dist-win-x64/libNativeWrapper.dll +0 -0
  26. package/dist-win-x64/zig-asar/arm64/libasar.dll +0 -0
  27. package/dist-win-x64/zig-asar/x64/libasar.dll +0 -0
  28. package/package.json +47 -0
  29. package/scripts/build-and-upload-artifacts.js +207 -0
  30. package/scripts/gen-webgpu-ffi.mjs +162 -0
  31. package/scripts/install-windows-deps.ps1 +80 -0
  32. package/scripts/package-release.js +237 -0
  33. package/scripts/push-version.js +84 -0
  34. package/scripts/update-bun-version.ts +122 -0
  35. package/scripts/update-cef-version.ts +145 -0
  36. package/src/browser/builtinrpcSchema.ts +19 -0
  37. package/src/browser/global.d.ts +36 -0
  38. package/src/browser/index.ts +234 -0
  39. package/src/browser/webviewtag.ts +88 -0
  40. package/src/browser/wgputag.ts +48 -0
  41. package/src/bun/SparkBunConfig.ts +497 -0
  42. package/src/bun/__tests__/ffi-contract.test.ts +105 -0
  43. package/src/bun/core/ApplicationMenu.ts +70 -0
  44. package/src/bun/core/BrowserView.ts +416 -0
  45. package/src/bun/core/BrowserWindow.ts +396 -0
  46. package/src/bun/core/BuildConfig.ts +71 -0
  47. package/src/bun/core/ContextMenu.ts +75 -0
  48. package/src/bun/core/GpuWindow.ts +289 -0
  49. package/src/bun/core/Paths.ts +5 -0
  50. package/src/bun/core/Socket.ts +22 -0
  51. package/src/bun/core/Tray.ts +197 -0
  52. package/src/bun/core/Updater.ts +1131 -0
  53. package/src/bun/core/Utils.ts +487 -0
  54. package/src/bun/core/WGPUView.ts +167 -0
  55. package/src/bun/core/menuRoles.ts +181 -0
  56. package/src/bun/events/ApplicationEvents.ts +22 -0
  57. package/src/bun/events/event.ts +27 -0
  58. package/src/bun/events/eventEmitter.ts +45 -0
  59. package/src/bun/events/trayEvents.ts +11 -0
  60. package/src/bun/events/webviewEvents.ts +39 -0
  61. package/src/bun/events/windowEvents.ts +23 -0
  62. package/src/bun/index.ts +120 -0
  63. package/src/bun/preload/.generated/compiled.ts +2 -0
  64. package/src/bun/preload/build.ts +65 -0
  65. package/src/bun/preload/dragRegions.ts +41 -0
  66. package/src/bun/preload/encryption.ts +86 -0
  67. package/src/bun/preload/events.ts +171 -0
  68. package/src/bun/preload/globals.d.ts +45 -0
  69. package/src/bun/preload/index-sandboxed.ts +28 -0
  70. package/src/bun/preload/index.ts +77 -0
  71. package/src/bun/preload/internalRpc.ts +80 -0
  72. package/src/bun/preload/overlaySync.ts +107 -0
  73. package/src/bun/preload/webviewTag.ts +451 -0
  74. package/src/bun/preload/wgpuTag.ts +246 -0
  75. package/src/bun/proc/linux.md +43 -0
  76. package/src/bun/proc/native.ts +3253 -0
  77. package/src/bun/webGPU.ts +346 -0
  78. package/src/bun/webgpuAdapter.ts +3011 -0
  79. package/src/cli/bun.lockb +0 -0
  80. package/src/cli/index.ts +4653 -0
  81. package/src/cli/package-lock.json +81 -0
  82. package/src/cli/package.json +11 -0
  83. package/src/cli/templates/embedded.ts +2 -0
  84. package/src/core/build.zig +16 -0
  85. package/src/core/main.zig +3378 -0
  86. package/src/extractor/build.zig +22 -0
  87. package/src/installer/installer-template.ts +216 -0
  88. package/src/launcher/main.ts +221 -0
  89. package/src/native/build/libNativeWrapper.so +0 -0
  90. package/src/native/linux/build/nativeWrapper.o +0 -0
  91. package/src/native/linux/cef_loader.cpp +110 -0
  92. package/src/native/linux/cef_loader.h +28 -0
  93. package/src/native/linux/cef_process_helper_linux.cpp +160 -0
  94. package/src/native/linux/nativeWrapper.cpp +11768 -0
  95. package/src/native/macos/cef_process_helper_mac.cc +160 -0
  96. package/src/native/macos/nativeWrapper.mm +9172 -0
  97. package/src/native/shared/accelerator_parser.h +72 -0
  98. package/src/native/shared/app_paths.h +110 -0
  99. package/src/native/shared/asar.h +35 -0
  100. package/src/native/shared/cache_migration.h +244 -0
  101. package/src/native/shared/callbacks.h +57 -0
  102. package/src/native/shared/cef_response_filter.h +189 -0
  103. package/src/native/shared/chromium_flags.h +181 -0
  104. package/src/native/shared/config.h +66 -0
  105. package/src/native/shared/download_event.h +197 -0
  106. package/src/native/shared/ffi_helpers.h +139 -0
  107. package/src/native/shared/glob_match.h +59 -0
  108. package/src/native/shared/json_menu_parser.h +223 -0
  109. package/src/native/shared/mime_types.h +101 -0
  110. package/src/native/shared/navigation_rules.h +98 -0
  111. package/src/native/shared/partition_context.h +137 -0
  112. package/src/native/shared/pending_resize_queue.h +45 -0
  113. package/src/native/shared/permissions.h +118 -0
  114. package/src/native/shared/permissions_cef.h +74 -0
  115. package/src/native/shared/preload_script.h +71 -0
  116. package/src/native/shared/shutdown_guard.h +134 -0
  117. package/src/native/shared/thread_safe_map.h +138 -0
  118. package/src/native/shared/webview_storage.h +91 -0
  119. package/src/native/win/cef_process_helper_win.cpp +143 -0
  120. package/src/native/win/dcomp_compositor.h +352 -0
  121. package/src/native/win/nativeWrapper.cpp +12434 -0
  122. package/src/npmbin/index.js +34 -0
  123. package/src/shared/bun-version.ts +3 -0
  124. package/src/shared/cef-version.ts +5 -0
  125. package/src/shared/naming.test.ts +327 -0
  126. package/src/shared/naming.ts +188 -0
  127. package/src/shared/platform.ts +48 -0
  128. package/src/shared/rpc.ts +541 -0
  129. package/src/shared/sparkbun-version.ts +2 -0
  130. package/src/types/three.d.ts +1 -0
  131. package/tsconfig.json +31 -0
@@ -0,0 +1,234 @@
1
+ import {
2
+ type RPCSchema,
3
+ type RPCTransport,
4
+ type SparkBunRPCSchema,
5
+ type SparkBunRPCConfig,
6
+ type RPCWithTransport,
7
+ createRPC,
8
+ defineSparkBunRPC,
9
+ } from "../shared/rpc.js";
10
+ import {
11
+ type WebviewTagElement,
12
+ type WebviewEventTypes,
13
+ } from "./webviewtag";
14
+ import { type WgpuTagElement, type WgpuEventTypes } from "./wgputag";
15
+ import "./global.d.ts";
16
+
17
+ const WEBVIEW_ID = window.__sparkbunWebviewId;
18
+ const HOST_SOCKET_PORT =
19
+ window.__sparkbunHostSocketPort ?? window.__sparkbunRpcSocketPort;
20
+
21
+ class Electroview<T extends RPCWithTransport> {
22
+ hostSocket?: WebSocket;
23
+ hostSocketCanSend = false;
24
+ // user's custom rpc browser <-> bun
25
+ rpc?: T;
26
+ rpcHandler?: (msg: unknown) => void;
27
+ carrots = {
28
+ invoke: <R = unknown>(
29
+ carrotId: string,
30
+ method: string,
31
+ params?: unknown,
32
+ options?: { windowId?: string },
33
+ ) => this.invokeCarrot<R>(carrotId, method, params, options),
34
+ };
35
+
36
+ constructor(config: { rpc: T }) {
37
+ this.rpc = config.rpc;
38
+ this.init();
39
+ }
40
+
41
+ init() {
42
+ this.initSocketToHost();
43
+
44
+ // Set up handler for user RPC messages from the host runtime.
45
+ const hostMessageHandler = this.receiveMessageFromHost.bind(this);
46
+ window.__sparkbun!.receiveMessageFromHost = hostMessageHandler;
47
+ window.__sparkbun!.receiveMessageFromBun = hostMessageHandler;
48
+
49
+ if (this.rpc) {
50
+ this.rpc.setTransport(this.createTransport());
51
+ }
52
+
53
+ const pendingMessages = window.__sparkbunPendingHostMessages;
54
+ if (pendingMessages?.length) {
55
+ window.__sparkbunPendingHostMessages = [];
56
+ for (const message of pendingMessages) {
57
+ hostMessageHandler(message);
58
+ }
59
+ }
60
+ }
61
+
62
+ initSocketToHost() {
63
+ // Skip native socket when running in a remote browser (no port/webview ID)
64
+ if (!HOST_SOCKET_PORT || !WEBVIEW_ID) {
65
+ return;
66
+ }
67
+
68
+ // Note: Using ws:// for localhost is intentional - all RPC messages are
69
+ // encrypted with per-webview AES-GCM keys, making TLS redundant
70
+ const socket = new WebSocket(
71
+ `ws://localhost:${HOST_SOCKET_PORT}/socket?webviewId=${WEBVIEW_ID}`,
72
+ );
73
+
74
+ this.hostSocket = socket;
75
+
76
+ socket.addEventListener("open", () => {
77
+ // this.hostSocket?.send("Hello from webview " + WEBVIEW_ID);
78
+ });
79
+
80
+ socket.addEventListener("message", async (event) => {
81
+ const message = event.data;
82
+ if (typeof message === "string") {
83
+ try {
84
+ const encryptedPacket = JSON.parse(message);
85
+
86
+ const decrypted = await window.__sparkbun_decrypt(
87
+ encryptedPacket.encryptedData,
88
+ encryptedPacket.iv,
89
+ encryptedPacket.tag,
90
+ );
91
+
92
+ this.hostSocketCanSend = true;
93
+ this.rpcHandler?.(JSON.parse(decrypted));
94
+ } catch (err) {
95
+ console.error("Error parsing bun message:", err);
96
+ }
97
+ } else if (message instanceof Blob) {
98
+ // Handle binary data (e.g., convert Blob to ArrayBuffer if needed)
99
+ } else {
100
+ console.error("UNKNOWN DATA TYPE RECEIVED:", event.data);
101
+ }
102
+ });
103
+
104
+ socket.addEventListener("error", (event) => {
105
+ this.hostSocketCanSend = false;
106
+ console.error("Socket error:", event);
107
+ });
108
+
109
+ socket.addEventListener("close", (_event) => {
110
+ this.hostSocketCanSend = false;
111
+ // console.log("Socket closed:", event);
112
+ });
113
+ }
114
+
115
+ createTransport(): RPCTransport {
116
+ const that = this;
117
+ return {
118
+ send(message: unknown) {
119
+ try {
120
+ const messageString = JSON.stringify(message);
121
+ that.sendMessageToHost(messageString);
122
+ } catch (error) {
123
+ console.error("host: failed to serialize message to webview", error);
124
+ }
125
+ },
126
+ registerHandler(handler: (msg: unknown) => void) {
127
+ that.rpcHandler = handler;
128
+ },
129
+ };
130
+ }
131
+
132
+ async sendMessageToHost(msg: string) {
133
+ if (
134
+ this.hostSocketCanSend &&
135
+ this.hostSocket?.readyState === WebSocket.OPEN
136
+ ) {
137
+ try {
138
+ const { encryptedData, iv, tag } =
139
+ await window.__sparkbun_encrypt(msg);
140
+
141
+ const encryptedPacket = {
142
+ encryptedData: encryptedData,
143
+ iv: iv,
144
+ tag: tag,
145
+ };
146
+ const encryptedPacketString = JSON.stringify(encryptedPacket);
147
+ this.hostSocket.send(encryptedPacketString);
148
+ return;
149
+ } catch (error) {
150
+ console.error("Error sending message to host via socket:", error);
151
+ }
152
+ }
153
+
154
+ // if socket's are unavailable, fallback to postMessage
155
+ window.__sparkbunHostBridge?.postMessage(msg);
156
+ }
157
+
158
+ receiveMessageFromHost(msg: unknown) {
159
+ // NOTE: in the webview messages are passed by executing window.__sparkbun.receiveMessageFromHost(object)
160
+ // so they're already parsed into an object here
161
+ if (this.rpcHandler) {
162
+ this.rpcHandler(msg);
163
+ }
164
+ }
165
+
166
+ async invokeCarrot<R = unknown>(
167
+ carrotId: string,
168
+ method: string,
169
+ params?: unknown,
170
+ options?: { windowId?: string },
171
+ ): Promise<R> {
172
+ const requestProxy = (this.rpc as any)?.request;
173
+ if (!requestProxy || typeof requestProxy.invokeCarrot !== "function") {
174
+ throw new Error("Renderer carrot invocation is not available in this SparkBun host.");
175
+ }
176
+ return requestProxy.invokeCarrot({
177
+ carrotId,
178
+ method,
179
+ params,
180
+ windowId: options?.windowId,
181
+ }) as Promise<R>;
182
+ }
183
+ static defineRPC<Schema extends SparkBunRPCSchema>(
184
+ config: SparkBunRPCConfig<Schema, "webview">,
185
+ ) {
186
+ return defineSparkBunRPC("webview", {
187
+ ...config,
188
+ extraRequestHandlers: {
189
+ evaluateJavascriptWithResponse: ({ script }: { script: string }) => {
190
+ return new Promise((resolve) => {
191
+ try {
192
+ const resultFunction = new Function(script);
193
+ const result = resultFunction();
194
+
195
+ if (result instanceof Promise) {
196
+ result
197
+ .then((resolvedResult) => {
198
+ resolve(resolvedResult);
199
+ })
200
+ .catch((error) => {
201
+ console.error("bun: async script execution failed", error);
202
+ resolve(String(error));
203
+ });
204
+ } else {
205
+ resolve(result);
206
+ }
207
+ } catch (error) {
208
+ console.error("bun: failed to eval script", error);
209
+ resolve(String(error));
210
+ }
211
+ });
212
+ },
213
+ },
214
+ });
215
+ }
216
+ }
217
+
218
+ export {
219
+ type RPCSchema,
220
+ type SparkBunRPCSchema,
221
+ type SparkBunRPCConfig,
222
+ createRPC,
223
+ Electroview,
224
+ type WebviewTagElement,
225
+ type WebviewEventTypes,
226
+ type WgpuTagElement,
227
+ type WgpuEventTypes,
228
+ };
229
+
230
+ const SparkBun = {
231
+ Electroview,
232
+ };
233
+
234
+ export default SparkBun;
@@ -0,0 +1,88 @@
1
+ import "./global.d.ts";
2
+
3
+ type WebviewEventTypes =
4
+ | "did-navigate"
5
+ | "did-navigate-in-page"
6
+ | "did-commit-navigation"
7
+ | "dom-ready"
8
+ | "host-message"
9
+ | "new-window-open";
10
+
11
+ /**
12
+ * Interface representing an <sparkbun-webview> custom element.
13
+ * Use this to properly type webview elements obtained via querySelector.
14
+ *
15
+ * @example
16
+ * const webview = document.querySelector('sparkbun-webview') as WebviewTagElement;
17
+ * webview.loadURL('https://example.com');
18
+ * webview.toggleHidden(false);
19
+ */
20
+ interface WebviewTagElement extends HTMLElement {
21
+ // Properties
22
+ webviewId?: number;
23
+ maskSelectors: Set<string>;
24
+ transparent: boolean;
25
+ passthroughEnabled: boolean;
26
+ hidden: boolean;
27
+ hiddenMirrorMode: boolean;
28
+ partition: string | null;
29
+
30
+ // Attribute-backed properties (getters/setters)
31
+ src: string | null;
32
+ html: string | null;
33
+ preload: string | null;
34
+ renderer: "cef" | "native";
35
+
36
+ // Mask management
37
+ addMaskSelector(selector: string): void;
38
+ removeMaskSelector(selector: string): void;
39
+
40
+ // Navigation
41
+ canGoBack(): Promise<boolean>;
42
+ canGoForward(): Promise<boolean>;
43
+ goBack(): void;
44
+ goForward(): void;
45
+ reload(): void;
46
+ loadURL(url: string): void;
47
+ loadHTML(html: string): void;
48
+
49
+ // Visibility and interaction
50
+ toggleTransparent(transparent?: boolean, bypassState?: boolean): void;
51
+ togglePassthrough(enablePassthrough?: boolean, bypassState?: boolean): void;
52
+ toggleHidden(hidden?: boolean, bypassState?: boolean): void;
53
+
54
+ // Events - listener receives a CustomEvent with detail property
55
+ on(event: WebviewEventTypes, listener: (event: CustomEvent) => void): void;
56
+ off(event: WebviewEventTypes, listener: (event: CustomEvent) => void): void;
57
+ emit(event: WebviewEventTypes, detail: unknown): void;
58
+
59
+ // Dimension sync
60
+ syncDimensions(force?: boolean): void;
61
+
62
+ // Navigation rules
63
+ setNavigationRules(rules: string[]): void;
64
+
65
+ // Find in page
66
+ findInPage(
67
+ searchText: string,
68
+ options?: { forward?: boolean; matchCase?: boolean },
69
+ ): void;
70
+ stopFindInPage(): void;
71
+
72
+ // Developer tools
73
+ openDevTools(): void;
74
+ closeDevTools(): void;
75
+ toggleDevTools(): void;
76
+
77
+ // JavaScript execution
78
+ executeJavascript(js: string): void;
79
+ }
80
+
81
+ // Augment global types so querySelector('sparkbun-webview') returns WebviewTagElement
82
+ declare global {
83
+ interface HTMLElementTagNameMap {
84
+ "sparkbun-webview": WebviewTagElement;
85
+ }
86
+ }
87
+
88
+ export { type WebviewTagElement, type WebviewEventTypes };
@@ -0,0 +1,48 @@
1
+ import "./global.d.ts";
2
+
3
+ type WgpuEventTypes = "ready";
4
+
5
+ /**
6
+ * Interface representing an <sparkbun-wgpu> custom element.
7
+ * Use this to properly type wgpu elements obtained via querySelector.
8
+ *
9
+ * @example
10
+ * const wgpu = document.querySelector('sparkbun-wgpu') as WgpuTagElement;
11
+ * wgpu.toggleTransparent(true);
12
+ */
13
+ interface WgpuTagElement extends HTMLElement {
14
+ // Properties
15
+ wgpuViewId?: number;
16
+ transparent: boolean;
17
+ passthroughEnabled: boolean;
18
+ hidden: boolean;
19
+
20
+ // Visibility and interaction
21
+ toggleTransparent(transparent?: boolean): void;
22
+ togglePassthrough(enablePassthrough?: boolean): void;
23
+ toggleHidden(hidden?: boolean): void;
24
+
25
+ // Dimension sync
26
+ syncDimensions(force?: boolean): void;
27
+
28
+ // Debug helper
29
+ runTest(): void;
30
+
31
+ // Mask management
32
+ addMaskSelector(selector: string): void;
33
+ removeMaskSelector(selector: string): void;
34
+
35
+ // Events - listener receives a CustomEvent with detail property
36
+ on(event: WgpuEventTypes, listener: (event: CustomEvent) => void): void;
37
+ off(event: WgpuEventTypes, listener: (event: CustomEvent) => void): void;
38
+ emit(event: WgpuEventTypes, detail: unknown): void;
39
+ }
40
+
41
+ // Augment global types so querySelector('sparkbun-wgpu') returns WgpuTagElement
42
+ declare global {
43
+ interface HTMLElementTagNameMap {
44
+ "sparkbun-wgpu": WgpuTagElement;
45
+ }
46
+ }
47
+
48
+ export { type WgpuTagElement, type WgpuEventTypes };