bunite-core 0.6.0 → 0.8.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 (39) hide show
  1. package/package.json +4 -2
  2. package/src/bun/core/App.ts +35 -34
  3. package/src/bun/core/BrowserView.ts +3 -9
  4. package/src/bun/core/singleInstanceLock.ts +91 -0
  5. package/src/bun/index.ts +5 -6
  6. package/src/bun/preload/inline.ts +1 -2
  7. package/src/bun/proc/native.ts +54 -78
  8. package/src/native/linux/bunite_linux_appres.cpp +173 -0
  9. package/src/native/linux/bunite_linux_ffi.cpp +263 -0
  10. package/src/native/linux/bunite_linux_internal.h +148 -0
  11. package/src/native/linux/bunite_linux_preload.cpp +1 -0
  12. package/src/native/linux/bunite_linux_runtime.cpp +120 -0
  13. package/src/native/linux/bunite_linux_utils.cpp +114 -0
  14. package/src/native/linux/bunite_linux_view.cpp +244 -0
  15. package/src/native/linux/bunite_linux_window.cpp +101 -0
  16. package/src/native/mac/bunite_mac_appres.mm +163 -0
  17. package/src/native/mac/bunite_mac_ffi.mm +470 -0
  18. package/src/native/mac/bunite_mac_internal.h +151 -0
  19. package/src/native/mac/bunite_mac_runtime.mm +15 -0
  20. package/src/native/mac/bunite_mac_utils.mm +121 -0
  21. package/src/native/mac/bunite_mac_view.mm +279 -0
  22. package/src/native/mac/bunite_mac_window.mm +187 -0
  23. package/src/native/shared/ffi_exports.h +13 -13
  24. package/src/native/shared/permissions.h +14 -0
  25. package/src/native/shared/webview_storage.h +6 -3
  26. package/src/native/win/native_host_cef.cpp +4 -8
  27. package/src/native/win/native_host_ffi.cpp +76 -123
  28. package/src/native/win/native_host_internal.h +5 -3
  29. package/src/native/win/native_host_runtime.cpp +2 -6
  30. package/src/native/win/native_host_utils.cpp +23 -52
  31. package/src/native/win/process_helper_win.cpp +1 -3
  32. package/src/preload/runtime.ts +1 -3
  33. package/src/preload/tsconfig.tsbuildinfo +1 -1
  34. package/src/preload/webviewElement.ts +3 -8
  35. package/src/shared/paths.ts +35 -44
  36. package/src/shared/platform.ts +1 -2
  37. package/src/shared/rpcDemux.ts +47 -2
  38. package/src/shared/webviewPolyfill.ts +64 -6
  39. package/src/bun/core/Utils.ts +0 -301
@@ -57,62 +57,12 @@ std::string escapeJsonString(const std::string& value) {
57
57
  return escaped;
58
58
  }
59
59
 
60
- std::vector<std::string> splitButtonLabels(const std::string& buttons_csv) {
61
- std::vector<std::string> labels;
62
- if (buttons_csv.empty()) {
63
- return labels;
64
- }
65
-
66
- std::stringstream stream(buttons_csv);
67
- std::string label;
68
- while (std::getline(stream, label, '\x1f')) {
69
- const size_t first = label.find_first_not_of(" \t");
70
- if (first == std::string::npos) {
71
- continue;
72
- }
73
- const size_t last = label.find_last_not_of(" \t");
74
- std::string normalized = label.substr(first, last - first + 1);
75
- std::transform(
76
- normalized.begin(),
77
- normalized.end(),
78
- normalized.begin(),
79
- [](unsigned char ch) { return static_cast<char>(std::tolower(ch)); }
80
- );
81
- if (!normalized.empty()) {
82
- labels.push_back(normalized);
83
- }
84
- }
85
-
86
- return labels;
87
- }
88
-
89
- std::string trimAsciiWhitespace(const std::string& value) {
90
- const size_t first = value.find_first_not_of(" \t\r\n");
91
- if (first == std::string::npos) {
92
- return {};
93
- }
94
- const size_t last = value.find_last_not_of(" \t\r\n");
95
- return value.substr(first, last - first + 1);
96
- }
97
-
98
- std::string toLowerAscii(std::string value) {
99
- std::transform(
100
- value.begin(),
101
- value.end(),
102
- value.begin(),
103
- [](unsigned char ch) { return static_cast<char>(std::tolower(ch)); }
104
- );
105
- return value;
106
- }
107
-
108
60
  // ---------------------------------------------------------------------------
109
61
  // Chromium flags parsing
110
62
  // ---------------------------------------------------------------------------
111
63
 
112
64
 
113
- // Simple flat JSON object parser for chromiumFlags.
114
- // Input is always a JSON-serialized Record<string, string | boolean> from TS.
115
- // Does not depend on CEF, so it can run before CefInitialize.
65
+ // Flat JSON object parser for Chromium flags (Record<string, string|boolean>). No CEF dep — runs before CefInitialize.
116
66
  std::map<std::string, std::string> parseChromiumFlagsJson(const std::string& json) {
117
67
  std::map<std::string, std::string> flags;
118
68
  if (json.empty()) {
@@ -264,12 +214,33 @@ bool shouldAlwaysAllowNavigationUrl(const std::string& url) {
264
214
  return url == "about:blank" || url.rfind("appres://app.internal/internal/", 0) == 0;
265
215
  }
266
216
 
217
+ uint32_t cefPermissionsToBuniteKind(uint32_t cef_bits) {
218
+ uint32_t bunite = 0;
219
+ if (cef_bits & CEF_PERMISSION_TYPE_MIC_STREAM) bunite |= BUNITE_PERMISSION_MICROPHONE;
220
+ if (cef_bits & CEF_PERMISSION_TYPE_CAMERA_STREAM) bunite |= BUNITE_PERMISSION_CAMERA;
221
+ if (cef_bits & CEF_PERMISSION_TYPE_GEOLOCATION) bunite |= BUNITE_PERMISSION_GEOLOCATION;
222
+ if (cef_bits & CEF_PERMISSION_TYPE_NOTIFICATIONS) bunite |= BUNITE_PERMISSION_NOTIFICATIONS;
223
+ if (cef_bits & CEF_PERMISSION_TYPE_CLIPBOARD) bunite |= BUNITE_PERMISSION_CLIPBOARD;
224
+ if (cef_bits & CEF_PERMISSION_TYPE_POINTER_LOCK) bunite |= BUNITE_PERMISSION_POINTER_LOCK;
225
+ if (cef_bits & CEF_PERMISSION_TYPE_MIDI_SYSEX) bunite |= BUNITE_PERMISSION_MIDI_SYSEX;
226
+ return bunite;
227
+ }
228
+
229
+ uint32_t cefMediaAccessToBuniteKind(uint32_t cef_bits) {
230
+ uint32_t bunite = 0;
231
+ if (cef_bits & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE) bunite |= BUNITE_PERMISSION_MICROPHONE;
232
+ if (cef_bits & CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE) bunite |= BUNITE_PERMISSION_CAMERA;
233
+ if (cef_bits & (CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
234
+ CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE)) bunite |= BUNITE_PERMISSION_SCREEN_CAPTURE;
235
+ return bunite;
236
+ }
237
+
267
238
  bool shouldAllowNavigation(const ViewHost* view, const std::string& url) {
268
239
  if (!view || shouldAlwaysAllowNavigationUrl(url) || view->navigation_rules.empty()) {
269
240
  return true;
270
241
  }
271
242
 
272
- bool allowed = true; // Match electrobun's last-match-wins, default-allow semantics.
243
+ bool allowed = true; // default-allow, last-match-wins
273
244
  for (const std::string& raw_rule : view->navigation_rules) {
274
245
  const bool is_block_rule = !raw_rule.empty() && raw_rule.front() == '^';
275
246
  const std::string pattern = is_block_rule ? raw_rule.substr(1) : raw_rule;
@@ -92,9 +92,7 @@ public:
92
92
  }
93
93
  if (!is_appres && !is_allowed_origin) return;
94
94
 
95
- // Skip isolated-world contexts (DevTools overlay, extensions, etc.) that
96
- // lack full Web APIs. The page's main-world context has customElements;
97
- // DevTools-injected contexts do not.
95
+ // Skip isolated-world contexts (DevTools/extensions) only main-world has customElements.
98
96
  context->Enter();
99
97
  CefRefPtr<CefV8Value> ce = context->GetGlobal()->GetValue("customElements");
100
98
  bool is_main_world = ce && !ce->IsNull() && !ce->IsUndefined();
@@ -1,6 +1,4 @@
1
- // Preload runtime — built once at package build time, injected into every appres:// page.
2
- // The config variables (__buniteWebviewId, __buniteRpcSocketPort, __buniteSecretKeyBase64)
3
- // are injected by inline.ts as a small preamble before this script.
1
+ // Preload runtime injected into every appres:// page. Config vars (__bunite*) prepended by inline.ts.
4
2
 
5
3
  declare const __buniteWebviewId: number;
6
4
  declare const __buniteRpcSocketPort: number;
@@ -1 +1 @@
1
- {"fileNames":["../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2021.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2022.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2021.string.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2022.array.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2022.error.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2022.object.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2022.string.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/.bun/typescript@6.0.2/node_modules/typescript/lib/lib.decorators.legacy.d.ts","./webviewelement.ts","./runtime.ts"],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"8a15b4607d9a499e2dbeed9ec0d3c0d7372c850b2d5f1fb259e8f6d41d468a84","impliedFormat":1},{"version":"26e0fe14baee4e127f4365d1ae0b276f400562e45e19e35fd2d4c296684715e6","impliedFormat":1},{"version":"d6b1eba8496bdd0eed6fc8a685768fe01b2da4a0388b5fe7df558290bffcf32f","affectsGlobalScope":true,"impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"db9709688f82c9e5f65a119c64d835f906efe5f559d08b11642d56eb85b79357","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b25b8c874acd1a4cf8444c3617e037d444d19080ac9f634b405583fd10ce1f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be57d7c90cf1f8112ee2636a068d8fd181289f82b744160ec56a7dc158a9f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"a917a49ac94cd26b754ab84e113369a75d1a47a710661d7cd25e961cc797065f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d3261badeb7843d157ef3e6f5d1427d0eeb0af0cf9df84a62cfd29fd47ac86e","affectsGlobalScope":true,"impliedFormat":1},{"version":"195daca651dde22f2167ac0d0a05e215308119a3100f5e6268e8317d05a92526","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b11e4285cd2bb164a4dc09248bdec69e9842517db4ca47c1ba913011e44ff2f","affectsGlobalScope":true,"impliedFormat":1},{"version":"0508571a52475e245b02bc50fa1394065a0a3d05277fbf5120c3784b85651799","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f9af488f510c3015af3cc8c267a9e9d96c4dd38a1fdff0e11dc5a544711415b","affectsGlobalScope":true,"impliedFormat":1},{"version":"fc611fea8d30ea72c6bbfb599c9b4d393ce22e2f5bfef2172534781e7d138104","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"f7924c67469cd6b44b50480cec49f3d34b3feae7bb292d6f44b7939f9d07a2dc","signature":"5c08c27ab7fdb9d3a443d5b81d066acf9a3b44413dbfe91153a2288779910ad5","affectsGlobalScope":true},{"version":"b61a26197044cf31caa83db322ecb653d081fc67e14b25c5a41cd7cc33b3fca1","signature":"6447fe52d8ee29270b95a53b62dece95739c334d51b6271bd7e1323e81b79a2c"}],"root":[59,60],"options":{"composite":true,"exactOptionalPropertyTypes":false,"module":7,"skipLibCheck":true,"strict":true,"target":9},"affectedFilesPendingEmit":[[60,17],[59,17]],"emitSignatures":[59,60],"version":"6.0.2"}
1
+ {"fileNames":["../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2021.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2021.string.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.array.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.object.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.string.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","./webviewelement.ts","./runtime.ts"],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"8a15b4607d9a499e2dbeed9ec0d3c0d7372c850b2d5f1fb259e8f6d41d468a84","impliedFormat":1},{"version":"26e0fe14baee4e127f4365d1ae0b276f400562e45e19e35fd2d4c296684715e6","impliedFormat":1},{"version":"d6b1eba8496bdd0eed6fc8a685768fe01b2da4a0388b5fe7df558290bffcf32f","affectsGlobalScope":true,"impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"db9709688f82c9e5f65a119c64d835f906efe5f559d08b11642d56eb85b79357","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b25b8c874acd1a4cf8444c3617e037d444d19080ac9f634b405583fd10ce1f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be57d7c90cf1f8112ee2636a068d8fd181289f82b744160ec56a7dc158a9f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"a917a49ac94cd26b754ab84e113369a75d1a47a710661d7cd25e961cc797065f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d3261badeb7843d157ef3e6f5d1427d0eeb0af0cf9df84a62cfd29fd47ac86e","affectsGlobalScope":true,"impliedFormat":1},{"version":"195daca651dde22f2167ac0d0a05e215308119a3100f5e6268e8317d05a92526","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b11e4285cd2bb164a4dc09248bdec69e9842517db4ca47c1ba913011e44ff2f","affectsGlobalScope":true,"impliedFormat":1},{"version":"0508571a52475e245b02bc50fa1394065a0a3d05277fbf5120c3784b85651799","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f9af488f510c3015af3cc8c267a9e9d96c4dd38a1fdff0e11dc5a544711415b","affectsGlobalScope":true,"impliedFormat":1},{"version":"fc611fea8d30ea72c6bbfb599c9b4d393ce22e2f5bfef2172534781e7d138104","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"d1d2b74439bf388c1b2a5806029a7d6f23146a906e163721473d684aa9a8f1e5","signature":"5c08c27ab7fdb9d3a443d5b81d066acf9a3b44413dbfe91153a2288779910ad5","affectsGlobalScope":true},{"version":"3782d5b638f6529d7049c5ce5e778c01aadad180784460eb5c69430fd405de49","signature":"6447fe52d8ee29270b95a53b62dece95739c334d51b6271bd7e1323e81b79a2c"}],"root":[59,60],"options":{"composite":true,"exactOptionalPropertyTypes":false,"module":7,"skipLibCheck":true,"strict":true,"target":9},"affectedFilesPendingEmit":[[60,17],[59,17]],"emitSignatures":[59,60],"version":"6.0.3"}
@@ -6,10 +6,7 @@ declare const bunite: {
6
6
  off: (channel: string, handler: (data: any) => void) => void;
7
7
  };
8
8
 
9
- // --- OverlaySyncController ---
10
- // Tracks element bounds and notifies when they change.
11
- // Uses ResizeObserver for size changes and rAF polling for position changes.
12
- // Dirty-flag coalescing ensures at most one IPC per animation frame.
9
+ // OverlaySyncController: ResizeObserver + rAF position polling; dirty-flag coalescing ≤1 IPC/frame.
13
10
 
14
11
  type Rect = { x: number; y: number; width: number; height: number };
15
12
 
@@ -290,13 +287,11 @@ class BuniteWebviewElement extends HTMLElement {
290
287
  if (typeof customElements !== "undefined") {
291
288
  customElements.define("bunite-webview", BuniteWebviewElement);
292
289
 
293
- // When the host page gains focus (click on non-surface area), the host BrowserView
294
- // HWND comes to front and covers surface child HWNDs. Re-raise surfaces on focus.
290
+ // Host BrowserView HWND covers surface HWNDs on focus re-raise.
295
291
  const raiseAll = () => bunite.invoke("__bunite:surface.bringAllVisiblesToFront").catch(() => {});
296
292
  document.addEventListener("pointerdown", raiseAll, true);
297
293
 
298
- // During host-page drag (e.g. dockview tab drag), send surfaces behind host
299
- // via Z-order swap so OLE DragDrop reaches the host's IDropTarget.
294
+ // Send surfaces behind host during drag so OLE DragDrop reaches host's IDropTarget.
300
295
  document.addEventListener("dragstart", () => {
301
296
  bunite.invoke("__bunite:surface.setAllPassthrough", { passthrough: true }).catch(() => {});
302
297
  }, true);
@@ -1,7 +1,7 @@
1
1
  import { dirname, join } from "node:path";
2
2
  import { existsSync, readdirSync } from "node:fs";
3
3
  import { createRequire } from "node:module";
4
- import { ARCH, BIN_EXT, NATIVE_LIB_EXT, PLATFORM_TAG } from "./platform";
4
+ import { ARCH, NATIVE_LIB_EXT, PLATFORM_TAG } from "./platform";
5
5
  import { CEF_VERSION } from "./cefVersion";
6
6
 
7
7
  const require = createRequire(import.meta.url);
@@ -10,10 +10,14 @@ export type ResolvedNativeArtifacts = {
10
10
  packageRoot: string;
11
11
  source: "optional-package" | "local-build" | "missing";
12
12
  nativePackageName: string | null;
13
- cefPackageName: string | null;
13
+ enginePackageName: string | null;
14
14
  nativeLibPath: string | null;
15
- processHelperPath: string | null;
16
- cefDir: string | null;
15
+ /**
16
+ * Engine runtime directory. Engine-specific meaning:
17
+ * - CEF (Windows): CEF framework dir containing libcef.dll. Resolved via env, package, or vendors/cef.
18
+ * - WKWebView (macOS), WebKitGTK (Linux): null. Engine is the system framework.
19
+ */
20
+ engineDir: string | null;
17
21
  };
18
22
 
19
23
  export function resolvePackageRoot(packageName: string): string | null {
@@ -43,9 +47,12 @@ function parseCefVersion(name: string): number[] | null {
43
47
  return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
44
48
  }
45
49
 
46
- function resolveCefDir(searchDirs: string[]): string | null {
47
- // 0. Explicit override (testing / development)
48
- const forceDir = process.env.BUNITE_CEF_DIR;
50
+ function resolveEngineDir(searchDirs: string[]): string | null {
51
+ // CEF-only (Win). mac/linux use system frameworks.
52
+ if (PLATFORM_TAG !== "win") return null;
53
+
54
+ // 0. Explicit override (BUNITE_ENGINE_DIR; BUNITE_CEF_DIR as legacy fallback).
55
+ const forceDir = process.env.BUNITE_ENGINE_DIR ?? process.env.BUNITE_CEF_DIR;
49
56
  if (forceDir && hasCefRuntime(forceDir)) {
50
57
  return forceDir;
51
58
  }
@@ -111,51 +118,40 @@ export function resolveNativeArtifacts(): ResolvedNativeArtifacts {
111
118
 
112
119
  // 1. Executable-relative (compiled standalone binary)
113
120
  const exeNativeLib = join(exeDir, `libBuniteNative${NATIVE_LIB_EXT}`);
114
- const exeProcessHelper = join(exeDir, `process_helper${BIN_EXT}`);
115
- if (existsSync(exeNativeLib) && existsSync(exeProcessHelper)) {
121
+ if (existsSync(exeNativeLib)) {
116
122
  return {
117
123
  packageRoot: exeDir,
118
124
  source: "local-build",
119
125
  nativePackageName: null,
120
- cefPackageName: null,
126
+ enginePackageName: null,
121
127
  nativeLibPath: exeNativeLib,
122
- processHelperPath: exeProcessHelper,
123
- cefDir: resolveCefDir([exeDir])
128
+ engineDir: resolveEngineDir([exeDir])
124
129
  };
125
130
  }
126
131
 
127
132
  const packageRoot = resolveBunitePackageRoot();
128
133
 
129
- // 2. Optional npm packages (bunite-native-*, bunite-cef-*)
134
+ // 2. Optional npm packages (bunite-native-*, bunite-cef-* on Windows only)
130
135
  const nativePackageName = `bunite-native-${PLATFORM_TAG}-${ARCH}`;
131
- const cefPackageName = `bunite-cef-${PLATFORM_TAG}-${ARCH}`;
136
+ const enginePackageName = PLATFORM_TAG === "win" ? `bunite-cef-${PLATFORM_TAG}-${ARCH}` : null;
132
137
  const nativePackageRoot = resolvePackageRoot(nativePackageName);
133
- const cefPackageRoot = resolvePackageRoot(cefPackageName);
138
+ const enginePackageRoot = enginePackageName ? resolvePackageRoot(enginePackageName) : null;
134
139
 
135
140
  const packagedNativeLibPath = nativePackageRoot
136
141
  ? join(nativePackageRoot, `libBuniteNative${NATIVE_LIB_EXT}`)
137
142
  : null;
138
- const packagedProcessHelperPath = nativePackageRoot
139
- ? join(nativePackageRoot, `process_helper${BIN_EXT}`)
140
- : null;
141
- const packagedCefDir = cefPackageRoot ?? null;
142
-
143
- if (
144
- packagedNativeLibPath &&
145
- packagedProcessHelperPath &&
146
- existsSync(packagedNativeLibPath) &&
147
- existsSync(packagedProcessHelperPath)
148
- ) {
143
+ const packagedEngineDir = enginePackageRoot ?? null;
144
+
145
+ if (packagedNativeLibPath && existsSync(packagedNativeLibPath)) {
149
146
  return {
150
147
  packageRoot: packageRoot ?? exeDir,
151
148
  source: "optional-package",
152
149
  nativePackageName,
153
- cefPackageName: packagedCefDir && existsSync(packagedCefDir) ? cefPackageName : null,
150
+ enginePackageName: packagedEngineDir && existsSync(packagedEngineDir) ? enginePackageName : null,
154
151
  nativeLibPath: packagedNativeLibPath,
155
- processHelperPath: packagedProcessHelperPath,
156
- cefDir: (packagedCefDir && existsSync(packagedCefDir))
157
- ? packagedCefDir
158
- : resolveCefDir([nativePackageRoot, packageRoot].filter(Boolean) as string[])
152
+ engineDir: (packagedEngineDir && existsSync(packagedEngineDir))
153
+ ? packagedEngineDir
154
+ : resolveEngineDir([nativePackageRoot, packageRoot].filter(Boolean) as string[])
159
155
  };
160
156
  }
161
157
 
@@ -163,32 +159,28 @@ export function resolveNativeArtifacts(): ResolvedNativeArtifacts {
163
159
  if (packageRoot) {
164
160
  const localBuildRoot = join(packageRoot, "native-build", `${PLATFORM_TAG}-${ARCH}`);
165
161
  const directLib = join(localBuildRoot, `libBuniteNative${NATIVE_LIB_EXT}`);
166
- const directHelper = join(localBuildRoot, `process_helper${BIN_EXT}`);
167
162
 
168
- if (existsSync(directLib) && existsSync(directHelper)) {
163
+ if (existsSync(directLib)) {
169
164
  return {
170
165
  packageRoot,
171
166
  source: "local-build",
172
167
  nativePackageName: null,
173
- cefPackageName: null,
168
+ enginePackageName: null,
174
169
  nativeLibPath: directLib,
175
- processHelperPath: directHelper,
176
- cefDir: resolveCefDir([localBuildRoot])
170
+ engineDir: resolveEngineDir([localBuildRoot])
177
171
  };
178
172
  }
179
173
 
180
174
  const releaseLib = join(localBuildRoot, "Release", `libBuniteNative${NATIVE_LIB_EXT}`);
181
- const releaseHelper = join(localBuildRoot, "Release", `process_helper${BIN_EXT}`);
182
175
 
183
- if (existsSync(releaseLib) && existsSync(releaseHelper)) {
176
+ if (existsSync(releaseLib)) {
184
177
  return {
185
178
  packageRoot,
186
179
  source: "local-build",
187
180
  nativePackageName: null,
188
- cefPackageName: null,
181
+ enginePackageName: null,
189
182
  nativeLibPath: releaseLib,
190
- processHelperPath: releaseHelper,
191
- cefDir: resolveCefDir([localBuildRoot])
183
+ engineDir: resolveEngineDir([localBuildRoot])
192
184
  };
193
185
  }
194
186
  }
@@ -197,9 +189,8 @@ export function resolveNativeArtifacts(): ResolvedNativeArtifacts {
197
189
  packageRoot: packageRoot ?? exeDir,
198
190
  source: "missing",
199
191
  nativePackageName: nativePackageRoot ? nativePackageName : null,
200
- cefPackageName: cefPackageRoot ? cefPackageName : null,
192
+ enginePackageName: enginePackageRoot ? enginePackageName : null,
201
193
  nativeLibPath: null,
202
- processHelperPath: null,
203
- cefDir: null
194
+ engineDir: null
204
195
  };
205
196
  }
@@ -2,8 +2,7 @@ export const OS = process.platform;
2
2
  export const ARCH = process.arch;
3
3
 
4
4
  export const PLATFORM_TAG =
5
- OS === "win32" ? "win" : OS === "darwin" ? "darwin" : OS;
5
+ OS === "win32" ? "win" : OS === "darwin" ? "mac" : OS;
6
6
 
7
- export const BIN_EXT = OS === "win32" ? ".exe" : "";
8
7
  export const NATIVE_LIB_EXT =
9
8
  OS === "win32" ? ".dll" : OS === "darwin" ? ".dylib" : ".so";
@@ -32,9 +32,18 @@ export type RpcTransportDemuxer = {
32
32
  dispose(): void;
33
33
  };
34
34
 
35
+ export type RpcDemuxBufferPolicy = "drop-oldest" | "drop-newest";
36
+
35
37
  export type RpcTransportDemuxerOptions = {
36
38
  /** ms to wait for peer before `bindTo` rejects. Default 10_000. */
37
39
  readyTimeout?: number;
40
+ /**
41
+ * Per-channel cap for packets received before a handler is registered.
42
+ * Drained FIFO on registerHandler. Default 64. Set 0 to disable buffering.
43
+ */
44
+ bufferSize?: number;
45
+ /** Overflow behaviour when bufferSize is exceeded. Default "drop-oldest". */
46
+ bufferPolicy?: RpcDemuxBufferPolicy;
38
47
  };
39
48
 
40
49
  type ChannelState = {
@@ -45,9 +54,11 @@ type ChannelState = {
45
54
  rejectReady: (error: Error) => void;
46
55
  readySettled: boolean;
47
56
  readyTimer?: ReturnType<typeof setTimeout>;
57
+ pending: RpcPacket[];
48
58
  };
49
59
 
50
60
  const DEFAULT_READY_TIMEOUT = 10_000;
61
+ const DEFAULT_BUFFER_SIZE = 64;
51
62
 
52
63
  export function createRpcTransportDemuxer(
53
64
  base: RpcTransport,
@@ -58,6 +69,8 @@ export function createRpcTransportDemuxer(
58
69
  }
59
70
 
60
71
  const readyTimeout = options.readyTimeout ?? DEFAULT_READY_TIMEOUT;
72
+ const bufferSize = Math.max(0, options.bufferSize ?? DEFAULT_BUFFER_SIZE);
73
+ const bufferPolicy: RpcDemuxBufferPolicy = options.bufferPolicy ?? "drop-oldest";
61
74
  const channels = new Map<string, ChannelState>();
62
75
  let disposed = false;
63
76
 
@@ -78,12 +91,26 @@ export function createRpcTransportDemuxer(
78
91
  ready,
79
92
  resolveReady,
80
93
  rejectReady,
81
- readySettled: false
94
+ readySettled: false,
95
+ pending: []
82
96
  };
83
97
  channels.set(name, state);
84
98
  return state;
85
99
  }
86
100
 
101
+ function bufferIncoming(state: ChannelState, packet: RpcPacket) {
102
+ if (bufferSize === 0) return;
103
+ if (state.pending.length < bufferSize) {
104
+ state.pending.push(packet);
105
+ return;
106
+ }
107
+ if (bufferPolicy === "drop-oldest") {
108
+ state.pending.shift();
109
+ state.pending.push(packet);
110
+ }
111
+ // drop-newest: leave the queue alone, discard the new packet
112
+ }
113
+
87
114
  function settleReady(state: ChannelState, action: () => void) {
88
115
  if (state.readySettled) return;
89
116
  state.readySettled = true;
@@ -112,12 +139,17 @@ export function createRpcTransportDemuxer(
112
139
  }
113
140
 
114
141
  if (isPacketEnvelope(data)) {
115
- state.handler?.(data.packet);
142
+ if (state.handler) {
143
+ state.handler(data.packet);
144
+ } else {
145
+ bufferIncoming(state, data.packet);
146
+ }
116
147
  }
117
148
  });
118
149
 
119
150
  return {
120
151
  channel(name) {
152
+ if (disposed) throw new Error(`Demuxer disposed; cannot open channel "${name}"`);
121
153
  const state = getOrCreateState(name);
122
154
 
123
155
  const transport: RpcTransport = {
@@ -144,6 +176,18 @@ export function createRpcTransportDemuxer(
144
176
  );
145
177
  }, readyTimeout);
146
178
  }
179
+
180
+ // Drain after handshake bookkeeping so a thrown handler doesn't
181
+ // leave HELLO unsent or the ready promise un-armed. Handler errors
182
+ // during drain are swallowed so one bad packet doesn't drop the rest;
183
+ // synchronous throws from RPC handlers are a consumer bug.
184
+ if (state.pending.length > 0) {
185
+ const drained = state.pending;
186
+ state.pending = [];
187
+ for (const packet of drained) {
188
+ try { handler(packet); } catch { /* drain continues */ }
189
+ }
190
+ }
147
191
  },
148
192
  unregisterHandler() {
149
193
  state.handler = undefined;
@@ -166,6 +210,7 @@ export function createRpcTransportDemuxer(
166
210
  state.readySettled = true;
167
211
  state.rejectReady(new Error("Demuxer disposed"));
168
212
  }
213
+ state.pending.length = 0;
169
214
  }
170
215
  channels.clear();
171
216
  base.unregisterHandler?.();
@@ -1,5 +1,22 @@
1
- // Iframe-based fallback for web browsers. No-op when the native element is already registered by the CEF preload.
2
- // HTMLElement reference is lazy so this module is import-safe in Node/Bun.
1
+ // Iframe fallback for web (no-op if native already registered). HTMLElement deref'd lazily so module is import-safe in Node/Bun.
2
+
3
+ // Default sandbox omits allow-same-origin / allow-top-navigation / allow-modals /
4
+ // allow-popups-to-escape-sandbox — popup escape stays opt-in so a sandboxed page
5
+ // can't launch unsandboxed auxiliary contexts by default.
6
+ const DEFAULT_SANDBOX = "allow-scripts allow-forms allow-popups";
7
+ const BLOCKED_SCHEME_RE = /^(javascript|data|vbscript|file|about):/i;
8
+
9
+ // WHATWG URL parsing strips embedded ASCII tab/LF/CR and leading C0/space
10
+ // before scheme detection. Mirror that so embedded controls (e.g. `java\nscript:`)
11
+ // can't bypass the scheme guard.
12
+ function normalizeForSchemeCheck(src: string): string {
13
+ return src.replace(/[\t\n\r]/g, "").replace(/^[\x00-\x20]+/, "");
14
+ }
15
+
16
+ export function isBlockedSrc(src: string | null | undefined): boolean {
17
+ if (typeof src !== "string") return false;
18
+ return BLOCKED_SCHEME_RE.test(normalizeForSchemeCheck(src));
19
+ }
3
20
 
4
21
  let cachedClass: CustomElementConstructor | null = null;
5
22
 
@@ -7,18 +24,38 @@ function definePolyfillClass(): CustomElementConstructor {
7
24
  if (cachedClass) return cachedClass;
8
25
 
9
26
  class BuniteWebviewPolyfill extends HTMLElement {
10
- static observedAttributes = ["src"];
27
+ static observedAttributes = ["src", "sandbox", "unsandboxed"];
11
28
 
12
29
  private _iframe: HTMLIFrameElement | null = null;
13
30
 
31
+ private applySandbox(iframe: HTMLIFrameElement) {
32
+ if (this.hasAttribute("unsandboxed")) {
33
+ iframe.removeAttribute("sandbox");
34
+ return;
35
+ }
36
+ const override = this.getAttribute("sandbox");
37
+ iframe.setAttribute("sandbox", override ?? DEFAULT_SANDBOX);
38
+ }
39
+
40
+ private dispatchBlocked(url: string) {
41
+ this.dispatchEvent(new CustomEvent("did-fail-load", { detail: { url, reason: "blocked-scheme" } }));
42
+ }
43
+
14
44
  connectedCallback() {
15
45
  if (this._iframe) return;
16
46
 
17
47
  const iframe = document.createElement("iframe");
18
48
  iframe.style.cssText = "display:block;width:100%;height:100%;border:0;background:inherit;";
49
+ iframe.referrerPolicy = "no-referrer";
50
+ this.applySandbox(iframe);
51
+
19
52
  const src = this.getAttribute("src");
20
53
  if (src) {
21
- iframe.src = src;
54
+ if (isBlockedSrc(src)) {
55
+ this.dispatchBlocked(src);
56
+ } else {
57
+ iframe.src = src;
58
+ }
22
59
  }
23
60
 
24
61
  iframe.addEventListener("load", () => {
@@ -26,7 +63,9 @@ function definePolyfillClass(): CustomElementConstructor {
26
63
  try {
27
64
  url = iframe.contentWindow?.location.href ?? url;
28
65
  } catch {}
29
-
66
+ // Suppress the spurious about:blank load that fires after a blocked
67
+ // navigation (or before any explicit navigate).
68
+ if (isBlockedSrc(url)) return;
30
69
  this.dispatchEvent(new CustomEvent("did-navigate", { detail: { url } }));
31
70
  });
32
71
 
@@ -40,8 +79,16 @@ function definePolyfillClass(): CustomElementConstructor {
40
79
  }
41
80
 
42
81
  attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {
43
- if (name === "src" && this._iframe) {
82
+ if (!this._iframe) return;
83
+ if (name === "src") {
84
+ if (newValue && isBlockedSrc(newValue)) {
85
+ this.dispatchBlocked(newValue);
86
+ return;
87
+ }
44
88
  this._iframe.src = newValue ?? "";
89
+ } else if (name === "sandbox" || name === "unsandboxed") {
90
+ // Sandbox token changes take effect on the next navigation per HTML spec.
91
+ this.applySandbox(this._iframe);
45
92
  }
46
93
  }
47
94
 
@@ -81,6 +128,17 @@ function definePolyfillClass(): CustomElementConstructor {
81
128
  * environments and when the native CEF preload has already registered the element.
82
129
  * `BuniteView` calls this automatically on construction; call directly only when
83
130
  * using `<bunite-webview>` markup without instantiating `BuniteView`.
131
+ *
132
+ * Defaults (web fallback only — native paths bypass these):
133
+ * - `sandbox="allow-scripts allow-forms allow-popups"` (popup-escape stays opt-in).
134
+ * - `referrerpolicy="no-referrer"`.
135
+ * - `javascript:` / `data:` / `vbscript:` / `file:` / `about:` schemes blocked
136
+ * (with WHATWG URL-style normalization to defeat embedded-control bypass);
137
+ * navigation attempt dispatches `did-fail-load` with `detail.reason === "blocked-scheme"`.
138
+ *
139
+ * Opt-out attributes on `<bunite-webview>` (observed — mutations re-apply):
140
+ * - `sandbox="..."` — override the default sandbox token string verbatim.
141
+ * - `unsandboxed` — remove the sandbox attribute entirely (trusted-content escape hatch).
84
142
  */
85
143
  export function registerBuniteWebviewPolyfill() {
86
144
  if (typeof customElements === "undefined") return;