electrobun 1.18.4-beta.12 → 1.18.4-beta.17

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 (101) hide show
  1. package/README.md +14 -1
  2. package/bun.lock +13 -0
  3. package/dash.config.ts +35 -8
  4. package/dist/api/browser/index.ts +51 -22
  5. package/dist/api/browser/webviewtag.ts +2 -0
  6. package/dist/api/config/ElectrobunConfig.ts +64 -1
  7. package/dist/api/config/validate.test.ts +16 -10
  8. package/dist/api/config/validate.ts +4 -6
  9. package/dist/api/config/windowsPermissions.ts +24 -0
  10. package/dist/api/preload/.generated/compiled.ts +2 -2
  11. package/dist/api/preload/dragRegions.test.ts +153 -0
  12. package/dist/api/preload/dragRegions.ts +446 -24
  13. package/dist/api/preload/events.test.ts +33 -0
  14. package/dist/api/preload/events.ts +23 -6
  15. package/dist/api/preload/externalDropFocus.test.ts +86 -0
  16. package/dist/api/preload/externalDropFocus.ts +41 -0
  17. package/dist/api/preload/globals.d.ts +1 -0
  18. package/dist/api/preload/index.ts +2 -0
  19. package/dist/api/preload/overlaySync.test.ts +50 -0
  20. package/dist/api/preload/overlaySync.ts +2 -0
  21. package/dist/api/preload/webviewTag.ts +67 -16
  22. package/dist/api/preload/webviewTagNavigation.test.ts +23 -0
  23. package/dist/api/preload/webviewTagNavigation.ts +26 -0
  24. package/dist/api/preload/wgpuTag.ts +1 -6
  25. package/dist/api/sdks/bun/__tests__/build-config.test.ts +12 -0
  26. package/dist/api/sdks/bun/core/BrowserView.ts +158 -13
  27. package/dist/api/sdks/bun/core/BrowserWindow.ts +58 -15
  28. package/dist/api/sdks/bun/core/BuildConfig.ts +61 -10
  29. package/dist/api/sdks/bun/core/GpuWindow.ts +32 -13
  30. package/dist/api/sdks/bun/core/Updater.ts +39 -19
  31. package/dist/api/sdks/bun/core/Utils.ts +2 -2
  32. package/dist/api/sdks/bun/core/WindowsUpdateTask.test.ts +174 -0
  33. package/dist/api/sdks/bun/core/WindowsUpdateTask.ts +111 -0
  34. package/dist/api/sdks/bun/entries/app-menu.ts +2 -0
  35. package/dist/api/sdks/bun/entries/browser-view.ts +2 -0
  36. package/dist/api/sdks/bun/entries/browser-window.ts +2 -0
  37. package/dist/api/sdks/bun/entries/build-config.ts +2 -0
  38. package/dist/api/sdks/bun/entries/context-menu.ts +2 -0
  39. package/dist/api/sdks/bun/entries/events.ts +5 -0
  40. package/dist/api/sdks/bun/entries/gpu-window.ts +2 -0
  41. package/dist/api/sdks/bun/entries/native.ts +16 -0
  42. package/dist/api/sdks/bun/entries/paths.ts +1 -0
  43. package/dist/api/sdks/bun/entries/rpc.ts +14 -0
  44. package/dist/api/sdks/bun/entries/socket.ts +4 -0
  45. package/dist/api/sdks/bun/entries/tray.ts +2 -0
  46. package/dist/api/sdks/bun/entries/updater.ts +6 -0
  47. package/dist/api/sdks/bun/entries/utils.ts +1 -0
  48. package/dist/api/sdks/bun/entries/webgpu.ts +6 -0
  49. package/dist/api/sdks/bun/entries/wgpu-view.ts +2 -0
  50. package/dist/api/sdks/bun/events/windowEvents.ts +2 -0
  51. package/dist/api/sdks/bun/index.ts +14 -1
  52. package/dist/api/sdks/bun/proc/eventBridge.test.ts +40 -0
  53. package/dist/api/sdks/bun/proc/eventBridge.ts +43 -0
  54. package/dist/api/sdks/bun/proc/native.ts +146 -25
  55. package/dist/api/sdks/bun/webgpuAdapter.ts +50 -35
  56. package/dist/api/sdks/bun/webgpuRenderPass.test.ts +77 -0
  57. package/dist/api/sdks/bun/webgpuRenderPass.ts +58 -0
  58. package/dist/api/shared/bridge-payload-ownership.test.ts +50 -0
  59. package/dist/api/shared/build-dependencies.ts +2 -2
  60. package/dist/api/shared/bun-version.ts +2 -0
  61. package/dist/api/shared/cef-find-session.test.ts +117 -0
  62. package/dist/api/shared/console-forwarding.test.ts +80 -0
  63. package/dist/api/shared/dialog-paths.test.ts +30 -0
  64. package/dist/api/shared/dialog-paths.ts +12 -0
  65. package/dist/api/shared/linux-abi-release-contract.test.ts +29 -0
  66. package/dist/api/shared/linux-cef-dpi.test.ts +132 -0
  67. package/dist/api/shared/linux-cef-lifecycle.test.ts +195 -0
  68. package/dist/api/shared/linux-desktop-wm-class.test.ts +26 -0
  69. package/dist/api/shared/linux-native-file-dialog.test.ts +40 -0
  70. package/dist/api/shared/linux-tray-contract.test.ts +54 -0
  71. package/dist/api/shared/linux-webkit-automation.test.ts +70 -0
  72. package/dist/api/shared/linux-window-sizing.test.ts +27 -0
  73. package/dist/api/shared/linux-x11-geometry.test.ts +302 -0
  74. package/dist/api/shared/native-compile-flags.test.ts +82 -0
  75. package/dist/api/shared/native-compile-flags.ts +41 -0
  76. package/dist/api/shared/package-exports.test.ts +206 -0
  77. package/dist/api/shared/partition-context.test.ts +38 -0
  78. package/dist/api/shared/published-package-contract.test.ts +128 -0
  79. package/dist/api/shared/rpc.test.ts +117 -0
  80. package/dist/api/shared/rpc.ts +73 -19
  81. package/dist/api/shared/spell-check.test.js +64 -0
  82. package/dist/api/shared/window-visibility.test.ts +42 -0
  83. package/dist/api/shared/windows-cef-lifecycle.test.ts +189 -0
  84. package/dist/api/shared/windows-profile-paths.test.ts +105 -0
  85. package/dist/api/shared/windows-unicode-ui.test.ts +135 -0
  86. package/dist/api/shared/windows-webview-bounds.test.ts +46 -0
  87. package/dist/api/shared/windows-webview-socket-lifecycle.test.ts +36 -0
  88. package/dist/api/shared/windows-webview2-permissions.test.ts +70 -0
  89. package/dist/api/shared/windows-window-shell.test.ts +222 -0
  90. package/dist/go-sdk/callbacks.go +12 -0
  91. package/dist/go-sdk/electrobun.go +72 -13
  92. package/dist/odin-sdk/electrobun/electrobun.odin +115 -9
  93. package/dist/preload-full.js +473 -47
  94. package/dist/preload-sandboxed.js +10 -5
  95. package/dist/rust-sdk/electrobun.rs +70 -0
  96. package/dist/zig-sdk/electrobun.zig +135 -3
  97. package/package.json +19 -1
  98. package/src/cli/bun.lockb +0 -0
  99. package/src/cli/index.ts +0 -5632
  100. package/src/cli/package-lock.json +0 -81
  101. package/src/cli/package.json +0 -11
package/README.md CHANGED
@@ -59,6 +59,8 @@ Don't miss our:
59
59
  - [dotlock](https://github.com/tsconfigdotjson/dotlock) - macOS desktop app for managing `.env` files across your projects
60
60
  - [electrobun-pdf](https://github.com/GijungKim/electrobun-pdf) - local-first PDF & DOCX editor for opening, annotating, and exporting documents without leaving your machine
61
61
  - [electrobun-rms](https://github.com/khanhthanhdev/electrobun-rms) - fast Electrobun desktop app template with React, Tailwind CSS, and Vite
62
+ - [FLACK](https://github.com/BLCK-B/FLACK) - local audio player for Windows
63
+ - [gloomberb](https://gloom.sh) - financial terminal for the rest of us
62
64
  - [golb](https://github.com/chrisdadev13/golb) - desktop AI coding workspace built with React, Vite, and Tailwind
63
65
  - [GOG Achievements GUI](https://github.com/timendum/gog-achievements-gui) - desktop app for managing GOG achievements
64
66
  - [groov](https://github.com/laurenzcodes/groov) - desktop audio deck monitor
@@ -142,6 +144,12 @@ On Windows PowerShell:
142
144
 
143
145
  On Ubuntu/Debian based distros: `sudo apt install build-essential cmake pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev`
144
146
 
147
+ Linux applications also require the corresponding GTK 3, WebKitGTK 4.1,
148
+ Ayatana AppIndicator, and librsvg runtime packages on end-user systems. See the
149
+ [cross-platform development guide](./docs/src/content/docs/electrobun/guides/cross-platform-development.mdx#linux)
150
+ for distro-specific install commands. The launcher reports the exact missing
151
+ shared library when these dependencies are unavailable.
152
+
145
153
  ### First-time Setup
146
154
 
147
155
  ```bash
@@ -164,6 +172,11 @@ hutch dev
164
172
  hutch dev:clean
165
173
  ```
166
174
 
175
+ The native build generates `package/src/native/compile_flags.txt` from the
176
+ compiler flags resolved for the current machine. clangd-compatible editors
177
+ discover it automatically; rerun the build after changing native dependencies
178
+ or system toolchains.
179
+
167
180
  With sibling `jsc`, `cottontail`, `dash-cloud`, and `electrobun` checkouts, use
168
181
  one command to build only changed native layers and run Kitchen with the local
169
182
  stack:
@@ -194,6 +207,6 @@ All commands are run from the `/package` directory:
194
207
  |---|---|
195
208
  | macOS 14+ | Official |
196
209
  | Windows 11+ | Official |
197
- | Ubuntu 22.04+ | Official |
210
+ | Ubuntu 24.04+ | Official |
198
211
  | Other Linux distros (gtk3, webkit2gtk-4.1) | Community |
199
212
  | Raspberry Pi | Unofficial fork: [kortexa-ai/electrobun (linux-wpe)](https://github.com/kortexa-ai/electrobun/tree/kortexa/linux-wpe) — follow the author [@francip](https://x.com/francip/status/2050149256053539059?s=20) |
package/bun.lock CHANGED
@@ -7,6 +7,7 @@
7
7
  "dependencies": {
8
8
  "@babylonjs/core": "^7.45.0",
9
9
  "@types/bun": "^1.3.8",
10
+ "@types/three": "^0.165.0",
10
11
  "png-to-ico": "^2.1.8",
11
12
  "proxy-agent": "^6.5.0",
12
13
  "rcedit": "^4.0.1",
@@ -24,10 +25,18 @@
24
25
 
25
26
  "@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="],
26
27
 
28
+ "@tweenjs/tween.js": ["@tweenjs/tween.js@23.1.3", "", {}, "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA=="],
29
+
27
30
  "@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
28
31
 
29
32
  "@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="],
30
33
 
34
+ "@types/stats.js": ["@types/stats.js@0.17.4", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="],
35
+
36
+ "@types/three": ["@types/three@0.165.0", "", { "dependencies": { "@tweenjs/tween.js": "~23.1.1", "@types/stats.js": "*", "@types/webxr": "*", "fflate": "~0.8.2", "meshoptimizer": "~0.18.1" } }, "sha512-AJK8JZAFNBF0kBXiAIl5pggYlzAGGA8geVYQXAcPCEDRbyA+oEjkpUBcJJrtNz6IiALwzGexFJGZG2yV3WsYBw=="],
37
+
38
+ "@types/webxr": ["@types/webxr@0.5.24", "", {}, "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg=="],
39
+
31
40
  "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
32
41
 
33
42
  "ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="],
@@ -54,6 +63,8 @@
54
63
 
55
64
  "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
56
65
 
66
+ "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="],
67
+
57
68
  "get-uri": ["get-uri@6.0.5", "", { "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4" } }, "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg=="],
58
69
 
59
70
  "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
@@ -70,6 +81,8 @@
70
81
 
71
82
  "lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
72
83
 
84
+ "meshoptimizer": ["meshoptimizer@0.18.1", "", {}, "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw=="],
85
+
73
86
  "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
74
87
 
75
88
  "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
package/dash.config.ts CHANGED
@@ -1,4 +1,4 @@
1
- // @dash cli=0.3.1 cottontail=0.2.3
1
+ // @dash cli=0.5.0-canary.5 cottontail=0.2.3
2
2
  export default {
3
3
  scripts: {
4
4
  start: "hutch src/sdks/bun/index.ts",
@@ -8,6 +8,7 @@ export default {
8
8
  "build:local": "scripts/build-local.js",
9
9
  "build:release": "hutch build.ts --release",
10
10
  dev: "scripts/dev.ts",
11
+ "dev:matrix": "scripts/dev-matrix.ts",
11
12
  "dev:test": "scripts/dev.test.ts",
12
13
  "dev:clean": "cd ../kitchen && rm -rf node_modules vendors/cef && cd ../package && hutch dev",
13
14
  "dev:canary": "hutch install && hutch build:release && cd ../kitchen && hutch install && hutch electrobun build --env=canary",
@@ -15,14 +16,40 @@ export default {
15
16
  "build:docs:release": "cd ../docs && hutch run build",
16
17
  "npm:publish": "hutch build:release && npm publish",
17
18
  "npm:publish:beta": "hutch build:release && npm publish --tag beta",
18
- typecheck: "./node_modules/.bin/tsc --noEmit && cd ../kitchen && ./node_modules/.bin/tsc --noEmit",
19
- "push:beta": "hutch typecheck && node scripts/push-version.js beta",
20
- "push:patch": "hutch typecheck && node scripts/push-version.js patch",
21
- "push:minor": "hutch typecheck && node scripts/push-version.js minor",
22
- "push:major": "hutch typecheck && node scripts/push-version.js major",
23
- "push:stable": "hutch typecheck && node scripts/push-version.js stable",
19
+ typecheck:
20
+ "node node_modules/typescript/bin/tsc --noEmit && cd ../kitchen && node node_modules/typescript/bin/tsc --noEmit",
21
+ "check:release": "hutch typecheck && hutch test:templates && hutch test:template-publisher && hutch test:signing && hutch test:deployment-target && hutch test:linux-abi && hutch test:linux-extractor && hutch test:npm-bootstrap && hutch test:release-notes",
22
+ "push:beta": "hutch check:release && node scripts/push-version.js beta",
23
+ "push:patch": "hutch check:release && node scripts/push-version.js patch",
24
+ "push:minor": "hutch check:release && node scripts/push-version.js minor",
25
+ "push:major": "hutch check:release && node scripts/push-version.js major",
26
+ "push:stable": "hutch check:release && node scripts/push-version.js stable",
24
27
  "build:push:artifacts": "node scripts/build-and-upload-artifacts.js",
25
- "test:unit": "hutch test src/shared src/sdks/bun src/config",
28
+ "test:dialog-paths-native": "hutch scripts/test-dialog-paths-native.js",
29
+ "test:linux-cef-idle": "node scripts/test-linux-cef-idle.js",
30
+ "test:linux-dpi-native": "hutch scripts/test-linux-dpi-native.js",
31
+ "test:linux-x11-geometry-native":
32
+ "hutch scripts/test-linux-x11-geometry-native.js",
33
+ "test:views-url-native": "hutch scripts/test-views-url-native.js",
34
+ "test:windows-ui-native": "hutch scripts/test-windows-ui-native.js",
35
+ "test:windows-ui-native-integration":
36
+ "hutch scripts/test-windows-ui-native.js --require-native-wrapper",
37
+ "test:unit": "node scripts/run-cottontail-test.js src/shared src/sdks/bun src/config src/preload && hutch test:dialog-paths-native && hutch test:linux-dpi-native && hutch test:linux-x11-geometry-native && hutch test:views-url-native && hutch test:webview2-permissions && hutch test:windows-ui-native",
38
+ "test:linux-native-dialog":
39
+ "node scripts/run-cottontail-test.js src/shared/linux-native-file-dialog.test.ts && scripts/test-linux-native-file-dialog.sh",
40
+ "test:cef-debug": "scripts/test-cef-remote-debugging.ts",
41
+ "test:webview2-permissions": "scripts/test-webview2-permissions.ts",
42
+ "test:macos-inspector-layout": "scripts/test-macos-inspector-layout.sh",
43
+ "test:templates": "node scripts/run-cottontail-test.js ../templates/template-manifests.test.ts",
44
+ "test:template-publisher": "node --test ../scripts/publish-templates.test.mjs",
45
+ "test:signing": "node scripts/run-cottontail-test.js scripts/verify-macho-code-signing.test.ts",
46
+ "test:deployment-target": "node scripts/run-cottontail-test.js scripts/verify-macho-deployment-target.test.ts",
47
+ "test:linux-abi": "node scripts/run-cottontail-test.js scripts/verify-linux-elf-abi.test.ts",
48
+ "test:linux-extractor": "node scripts/test-linux-adjacent-extractor.mjs",
49
+ "test:npm-bootstrap": "node scripts/run-cottontail-test.js bin/npm-bootstrap-retirement.test.ts",
50
+ "test:release-notes": "node scripts/release-notes-contract.test.mjs",
51
+ "test:spell-check": "node --test src/shared/spell-check.test.js",
52
+ "test:macos-spell-check": "scripts/test-macos-spell-check.sh",
26
53
  "bump-cef": "hutch scripts/update-cef-version.ts",
27
54
  },
28
55
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  type RPCSchema,
3
3
  type RPCTransport,
4
+ type RPCRequestOptions,
4
5
  type ElectrobunRPCSchema,
5
6
  type ElectrobunRPCConfig,
6
7
  type RPCWithTransport,
@@ -18,12 +19,17 @@ const WEBVIEW_ID = window.__electrobunWebviewId;
18
19
  const HOST_SOCKET_PORT =
19
20
  window.__electrobunHostSocketPort ?? window.__electrobunRpcSocketPort;
20
21
 
22
+ type QueuedHostMessage = {
23
+ message: string;
24
+ markSent: () => void;
25
+ };
26
+
21
27
  class Electroview<T extends RPCWithTransport> {
22
28
  hostSocket?: WebSocket;
23
29
  hostSocketCanSend = false;
24
- pendingHostSocketMessages: string[] = [];
30
+ pendingHostSocketMessages: QueuedHostMessage[] = [];
25
31
  flushingHostSocketMessages = false;
26
- hostSocketSendQueue: string[] = [];
32
+ hostSocketSendQueue: QueuedHostMessage[] = [];
27
33
  flushingHostSocketSendQueue = false;
28
34
  // user's custom rpc browser <-> bun
29
35
  rpc?: T;
@@ -119,7 +125,8 @@ class Electroview<T extends RPCWithTransport> {
119
125
 
120
126
  socket.addEventListener("close", (_event) => {
121
127
  this.hostSocketCanSend = false;
122
- this.pendingHostSocketMessages = [];
128
+ this.flushHostMessagesViaFallback(this.pendingHostSocketMessages);
129
+ this.flushHostMessagesViaFallback(this.hostSocketSendQueue);
123
130
  // console.log("Socket closed:", event);
124
131
  });
125
132
  }
@@ -130,7 +137,7 @@ class Electroview<T extends RPCWithTransport> {
130
137
  send(message: unknown) {
131
138
  try {
132
139
  const messageString = JSON.stringify(message);
133
- that.sendMessageToHost(messageString);
140
+ return that.sendMessageToHost(messageString);
134
141
  } catch (error) {
135
142
  console.error("host: failed to serialize message to webview", error);
136
143
  }
@@ -141,20 +148,24 @@ class Electroview<T extends RPCWithTransport> {
141
148
  };
142
149
  }
143
150
 
144
- async sendMessageToHost(msg: string) {
145
- if (this.canSendToHostSocket()) {
146
- this.hostSocketSendQueue.push(msg);
147
- void this.flushHostSocketSendQueue();
148
- return;
149
- }
151
+ sendMessageToHost(msg: string): Promise<void> {
152
+ return new Promise((markSent) => {
153
+ const queuedMessage = { message: msg, markSent };
150
154
 
151
- if (this.hostSocket?.readyState === WebSocket.CONNECTING) {
152
- this.pendingHostSocketMessages.push(msg);
153
- return;
154
- }
155
+ if (this.canSendToHostSocket()) {
156
+ this.hostSocketSendQueue.push(queuedMessage);
157
+ void this.flushHostSocketSendQueue();
158
+ return;
159
+ }
155
160
 
156
- // if socket's are unavailable, fallback to postMessage
157
- window.__electrobunHostBridge?.postMessage(msg);
161
+ if (this.hostSocket?.readyState === WebSocket.CONNECTING) {
162
+ this.pendingHostSocketMessages.push(queuedMessage);
163
+ return;
164
+ }
165
+
166
+ // If sockets are unavailable, hand the packet to the native bridge.
167
+ this.sendMessageToHostViaFallback(queuedMessage);
168
+ });
158
169
  }
159
170
 
160
171
  canSendToHostSocket() {
@@ -174,7 +185,6 @@ class Electroview<T extends RPCWithTransport> {
174
185
  this.hostSocket!.send(msg);
175
186
  return true;
176
187
  }
177
- await new Promise((resolve) => setTimeout(resolve, 0));
178
188
  const { encryptedData, iv, tag } =
179
189
  await window.__electrobun_encrypt(msg);
180
190
 
@@ -192,6 +202,22 @@ class Electroview<T extends RPCWithTransport> {
192
202
  }
193
203
  }
194
204
 
205
+ sendMessageToHostViaFallback(queuedMessage: QueuedHostMessage) {
206
+ try {
207
+ window.__electrobunHostBridge?.postMessage(queuedMessage.message);
208
+ } catch (error) {
209
+ console.error("Error sending message to host via native bridge:", error);
210
+ } finally {
211
+ queuedMessage.markSent();
212
+ }
213
+ }
214
+
215
+ flushHostMessagesViaFallback(queue: QueuedHostMessage[]) {
216
+ while (queue.length > 0) {
217
+ this.sendMessageToHostViaFallback(queue.shift()!);
218
+ }
219
+ }
220
+
195
221
  async flushHostSocketSendQueue() {
196
222
  if (this.flushingHostSocketSendQueue) {
197
223
  return;
@@ -203,10 +229,12 @@ class Electroview<T extends RPCWithTransport> {
203
229
  this.hostSocketSendQueue.length > 0 &&
204
230
  this.canSendToHostSocket()
205
231
  ) {
206
- const message = this.hostSocketSendQueue[0]!;
232
+ const queuedMessage = this.hostSocketSendQueue[0]!;
207
233
  this.hostSocketSendQueue.shift();
208
- if (!(await this.sendMessageToHostSocket(message))) {
209
- window.__electrobunHostBridge?.postMessage(message);
234
+ if (!(await this.sendMessageToHostSocket(queuedMessage.message))) {
235
+ this.sendMessageToHostViaFallback(queuedMessage);
236
+ } else {
237
+ queuedMessage.markSent();
210
238
  }
211
239
  }
212
240
  } finally {
@@ -222,8 +250,8 @@ class Electroview<T extends RPCWithTransport> {
222
250
  this.flushingHostSocketMessages = true;
223
251
  try {
224
252
  while (this.pendingHostSocketMessages.length > 0) {
225
- const message = this.pendingHostSocketMessages.shift()!;
226
- this.hostSocketSendQueue.push(message);
253
+ const queuedMessage = this.pendingHostSocketMessages.shift()!;
254
+ this.hostSocketSendQueue.push(queuedMessage);
227
255
  }
228
256
  await this.flushHostSocketSendQueue();
229
257
  } finally {
@@ -293,6 +321,7 @@ class Electroview<T extends RPCWithTransport> {
293
321
 
294
322
  export {
295
323
  type RPCSchema,
324
+ type RPCRequestOptions,
296
325
  type ElectrobunRPCSchema,
297
326
  type ElectrobunRPCConfig,
298
327
  createRPC,
@@ -23,6 +23,7 @@ interface WebviewTagElement extends HTMLElement {
23
23
  maskSelectors: Set<string>;
24
24
  transparent: boolean;
25
25
  passthroughEnabled: boolean;
26
+ spellCheckEnabled: boolean;
26
27
  hidden: boolean;
27
28
  hiddenMirrorMode: boolean;
28
29
  partition: string | null;
@@ -45,6 +46,7 @@ interface WebviewTagElement extends HTMLElement {
45
46
  reload(): void;
46
47
  loadURL(url: string): void;
47
48
  loadHTML(html: string): void;
49
+ setSpellCheck(enabled: boolean): Promise<boolean>;
48
50
 
49
51
  // Visibility and interaction
50
52
  toggleTransparent(transparent?: boolean, bypassState?: boolean): void;
@@ -3,6 +3,8 @@
3
3
  * Used in electrobun.config.ts files
4
4
  */
5
5
 
6
+ import type { WindowsWebView2Permission } from "./windowsPermissions";
7
+
6
8
  type BundlerOptions = {
7
9
  external?: string[];
8
10
  define?: Record<string, string>;
@@ -137,6 +139,7 @@ export interface ElectrobunConfig {
137
139
  build?: {
138
140
  /**
139
141
  * Main process implementation to build and package.
142
+ * - "bun": bundle and run the Bun main process entrypoint
140
143
  * - "cottontail": bundle and run the Cottontail main process entrypoint
141
144
  * - "zig": compile and run the Zig main process entrypoint
142
145
  * - "rust": compile and run the Rust main process entrypoint
@@ -144,7 +147,19 @@ export interface ElectrobunConfig {
144
147
  * - "odin": compile and run the Odin main process entrypoint
145
148
  * @default "cottontail"
146
149
  */
147
- mainProcess?: "cottontail" | "zig" | "rust" | "go" | "odin";
150
+ mainProcess?: "bun" | "cottontail" | "zig" | "rust" | "go" | "odin";
151
+
152
+ /**
153
+ * Bun main process build configuration.
154
+ * Used when `build.mainProcess` is set to `"bun"`.
155
+ */
156
+ bun?: {
157
+ /**
158
+ * Entry point for the main Bun process
159
+ * @default "src/bun/index.ts"
160
+ */
161
+ entrypoint?: string;
162
+ } & BundlerOptions;
148
163
 
149
164
  /**
150
165
  * Cottontail main process build configuration.
@@ -364,6 +379,10 @@ export interface ElectrobunConfig {
364
379
  * - `"value"` — add a flag with a value
365
380
  * - `false` — remove a default flag set by Electrobun
366
381
  *
382
+ * CEF remote debugging is automatic for dev builds and disabled by
383
+ * default for packaged builds. Set `"remote-debugging-port"` to a
384
+ * string port to opt in, or `false` to disable it explicitly.
385
+ *
367
386
  * @example
368
387
  * ```typescript
369
388
  * chromiumFlags: {
@@ -423,6 +442,10 @@ export interface ElectrobunConfig {
423
442
  * - `"value"` — add a flag with a value
424
443
  * - `false` — remove a default flag set by Electrobun
425
444
  *
445
+ * CEF remote debugging is automatic for dev builds and disabled by
446
+ * default for packaged builds. Set `"remote-debugging-port"` to a
447
+ * string port to opt in, or `false` to disable it explicitly.
448
+ *
426
449
  * @example
427
450
  * ```typescript
428
451
  * chromiumFlags: {
@@ -433,6 +456,17 @@ export interface ElectrobunConfig {
433
456
  */
434
457
  chromiumFlags?: Record<string, string | boolean>;
435
458
 
459
+ /**
460
+ * WebView2 permissions to grant automatically without showing a prompt.
461
+ * This applies to every origin loaded in a native Windows webview, so only
462
+ * enable permissions that the application intentionally delegates to its
463
+ * web content. This option does not affect CEF webviews.
464
+ *
465
+ * @example ["camera", "microphone"]
466
+ * @default []
467
+ */
468
+ autoGrantPermissions?: WindowsWebView2Permission[];
469
+
436
470
  /**
437
471
  * Path to application icon (.ico format)
438
472
  * Used for the installer/extractor wrapper, desktop shortcuts, and taskbar
@@ -465,6 +499,31 @@ export interface ElectrobunConfig {
465
499
  */
466
500
  defaultRenderer?: "native" | "cef";
467
501
 
502
+ /**
503
+ * Emit an expanded Flatpak-builder recipe alongside the normal Linux
504
+ * artifacts. This is an opt-in packaging MVP: Hutch writes a manifest
505
+ * and `/app` payload but does not invoke `flatpak-builder`.
506
+ */
507
+ flatpak?: {
508
+ /** Enable Flatpak recipe generation. @default false */
509
+ enabled: boolean;
510
+
511
+ /** Output directory relative to `build.artifactFolder`. @default "flatpak" */
512
+ outputPath?: string;
513
+
514
+ /** Flatpak runtime identifier. @default "org.freedesktop.Platform" */
515
+ runtime?: string;
516
+
517
+ /** Flatpak runtime branch. @default "25.08" */
518
+ runtimeVersion?: string;
519
+
520
+ /** Flatpak SDK identifier. @default "org.freedesktop.Sdk" */
521
+ sdk?: string;
522
+
523
+ /** Override the manifest's default sandbox finish arguments. */
524
+ finishArgs?: string[];
525
+ };
526
+
468
527
  /**
469
528
  * Custom Chromium command-line flags to pass to CEF during initialization.
470
529
  * Keys are flag names without the "--" prefix.
@@ -472,6 +531,10 @@ export interface ElectrobunConfig {
472
531
  * - `"value"` — add a flag with a value
473
532
  * - `false` — remove a default flag set by Electrobun
474
533
  *
534
+ * CEF remote debugging is automatic for dev builds and disabled by
535
+ * default for packaged builds. Set `"remote-debugging-port"` to a
536
+ * string port to opt in, or `false` to disable it explicitly.
537
+ *
475
538
  * @example
476
539
  * ```typescript
477
540
  * chromiumFlags: {
@@ -1,10 +1,10 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { assertNoLegacyBunMainProcessConfig } from "./validate";
2
+ import { assertNoLegacyBunVersionConfig } from "./validate";
3
3
 
4
- describe("assertNoLegacyBunMainProcessConfig", () => {
5
- it("accepts Cottontail and native main-process configurations", () => {
4
+ describe("assertNoLegacyBunVersionConfig", () => {
5
+ it("accepts Bun, Cottontail, and native main-process configurations", () => {
6
6
  expect(() =>
7
- assertNoLegacyBunMainProcessConfig({
7
+ assertNoLegacyBunVersionConfig({
8
8
  build: {
9
9
  mainProcess: "cottontail",
10
10
  cottontail: { entrypoint: "src/bun/index.ts" },
@@ -12,20 +12,26 @@ describe("assertNoLegacyBunMainProcessConfig", () => {
12
12
  }),
13
13
  ).not.toThrow();
14
14
  expect(() =>
15
- assertNoLegacyBunMainProcessConfig({
15
+ assertNoLegacyBunVersionConfig({
16
16
  build: { mainProcess: "zig" },
17
17
  }),
18
18
  ).not.toThrow();
19
+ expect(() =>
20
+ assertNoLegacyBunVersionConfig({
21
+ build: {
22
+ mainProcess: "bun",
23
+ bun: { entrypoint: "src/bun/index.ts" },
24
+ },
25
+ }),
26
+ ).not.toThrow();
19
27
  });
20
28
 
21
29
  it.each([
22
- { mainProcess: "bun" },
23
- { bun: { entrypoint: "src/bun/index.ts" } },
24
30
  { bunVersion: "1.3.8" },
25
31
  { bunnyBun: "bunny-bun-test" },
26
- ])("rejects removed Bun configuration: %p", (build) => {
27
- expect(() => assertNoLegacyBunMainProcessConfig({ build })).toThrow(
28
- 'Use build.mainProcess = "cottontail"',
32
+ ])("rejects unsupported per-project Bun version configuration: %p", (build) => {
33
+ expect(() => assertNoLegacyBunVersionConfig({ build })).toThrow(
34
+ "one pinned Bun runtime version",
29
35
  );
30
36
  });
31
37
  });
@@ -1,7 +1,7 @@
1
- const LEGACY_BUN_CONFIG_ERROR =
2
- 'Bun main-process configuration has been removed. Use build.mainProcess = "cottontail" and move build.bun options to build.cottontail.';
1
+ const LEGACY_BUN_VERSION_CONFIG_ERROR =
2
+ "Per-project Bun runtime version selection is not supported. Electrobun ships one pinned Bun runtime version.";
3
3
 
4
- export function assertNoLegacyBunMainProcessConfig(config: unknown): void {
4
+ export function assertNoLegacyBunVersionConfig(config: unknown): void {
5
5
  if (!config || typeof config !== "object") return;
6
6
 
7
7
  const build = (config as Record<string, unknown>)["build"];
@@ -9,11 +9,9 @@ export function assertNoLegacyBunMainProcessConfig(config: unknown): void {
9
9
 
10
10
  const buildConfig = build as Record<string, unknown>;
11
11
  if (
12
- buildConfig["mainProcess"] === "bun" ||
13
- Object.hasOwn(buildConfig, "bun") ||
14
12
  Object.hasOwn(buildConfig, "bunVersion") ||
15
13
  Object.hasOwn(buildConfig, "bunnyBun")
16
14
  ) {
17
- throw new Error(LEGACY_BUN_CONFIG_ERROR);
15
+ throw new Error(LEGACY_BUN_VERSION_CONFIG_ERROR);
18
16
  }
19
17
  }
@@ -0,0 +1,24 @@
1
+ export const WINDOWS_WEBVIEW2_AUTO_GRANT_PERMISSIONS = [
2
+ "camera",
3
+ "microphone",
4
+ "geolocation",
5
+ "notifications",
6
+ ] as const;
7
+
8
+ export type WindowsWebView2Permission =
9
+ (typeof WINDOWS_WEBVIEW2_AUTO_GRANT_PERMISSIONS)[number];
10
+
11
+ /**
12
+ * Return the Windows-only permission fragment written to Resources/build.json.
13
+ * Empty lists are omitted so existing applications keep the native prompt path.
14
+ */
15
+ export function getWindowsPermissionBuildConfig(
16
+ targetOS: "macos" | "win" | "linux",
17
+ permissions: readonly WindowsWebView2Permission[] | undefined,
18
+ ): { autoGrantPermissions?: WindowsWebView2Permission[] } {
19
+ if (targetOS !== "win" || !permissions?.length) return {};
20
+
21
+ return {
22
+ autoGrantPermissions: [...new Set(permissions)],
23
+ };
24
+ }