@dimina-kit/devtools 0.4.0-dev.20260828161241 → 0.4.0-dev.20260907055341

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 (277) hide show
  1. package/README.md +52 -729
  2. package/dist/main/app/app.d.ts +27 -7
  3. package/dist/main/app/app.js +285 -681
  4. package/dist/main/app/editor-view.d.ts +21 -0
  5. package/dist/main/app/editor-view.js +71 -0
  6. package/dist/main/app/global-mirrors.d.ts +23 -0
  7. package/dist/main/app/global-mirrors.js +37 -0
  8. package/dist/main/app/host-sidebar-default.d.ts +19 -0
  9. package/dist/main/app/host-sidebar-default.js +44 -0
  10. package/dist/main/app/menu-setup.d.ts +13 -0
  11. package/dist/main/app/menu-setup.js +49 -0
  12. package/dist/main/app/open-project-ipc.d.ts +13 -0
  13. package/dist/main/app/open-project-ipc.js +21 -0
  14. package/dist/main/app/project-list-surface.d.ts +31 -0
  15. package/dist/main/app/project-list-surface.js +20 -0
  16. package/dist/main/app/project-window.d.ts +36 -0
  17. package/dist/main/app/project-window.js +93 -0
  18. package/dist/main/app/servers.d.ts +17 -0
  19. package/dist/main/app/servers.js +60 -0
  20. package/dist/main/app/ui-extension-targets.d.ts +42 -0
  21. package/dist/main/app/ui-extension-targets.js +101 -0
  22. package/dist/main/app/window-close-reveal.harness.d.ts +34 -0
  23. package/dist/main/app/window-close-reveal.harness.js +65 -0
  24. package/dist/main/app/window-events.d.ts +15 -0
  25. package/dist/main/app/window-events.js +45 -0
  26. package/dist/main/app/window-runtime-services.d.ts +41 -0
  27. package/dist/main/app/window-runtime-services.js +178 -0
  28. package/dist/main/app/workbench-modules.d.ts +24 -0
  29. package/dist/main/app/workbench-modules.js +51 -0
  30. package/dist/main/app/workbench-window.d.ts +85 -0
  31. package/dist/main/app/workbench-window.js +310 -0
  32. package/dist/main/index.bundle.js +10669 -9096
  33. package/dist/main/ipc/app.d.ts +4 -1
  34. package/dist/main/ipc/app.js +4 -3
  35. package/dist/main/ipc/device-picker.d.ts +16 -0
  36. package/dist/main/ipc/device-picker.js +27 -0
  37. package/dist/main/ipc/index.d.ts +1 -0
  38. package/dist/main/ipc/index.js +1 -0
  39. package/dist/main/ipc/internal-devtools.d.ts +2 -1
  40. package/dist/main/ipc/internal-devtools.js +4 -3
  41. package/dist/main/ipc/popover.d.ts +4 -1
  42. package/dist/main/ipc/popover.js +25 -9
  43. package/dist/main/ipc/project-create.d.ts +2 -1
  44. package/dist/main/ipc/project-create.js +6 -5
  45. package/dist/main/ipc/project-fs.d.ts +3 -1
  46. package/dist/main/ipc/project-fs.js +17 -17
  47. package/dist/main/ipc/projects.d.ts +3 -3
  48. package/dist/main/ipc/projects.js +13 -12
  49. package/dist/main/ipc/session.d.ts +4 -1
  50. package/dist/main/ipc/session.js +16 -11
  51. package/dist/main/ipc/settings.d.ts +4 -1
  52. package/dist/main/ipc/settings.js +12 -19
  53. package/dist/main/ipc/simulator-module.d.ts +5 -0
  54. package/dist/main/ipc/simulator-module.js +9 -5
  55. package/dist/main/ipc/simulator.d.ts +4 -1
  56. package/dist/main/ipc/simulator.js +12 -18
  57. package/dist/main/ipc/tooltip.d.ts +2 -1
  58. package/dist/main/ipc/tooltip.js +8 -7
  59. package/dist/main/ipc/views.d.ts +4 -1
  60. package/dist/main/ipc/views.js +20 -9
  61. package/dist/main/runtime/devtools-backend-before-quit.harness.d.ts +2 -20
  62. package/dist/main/runtime/devtools-backend-before-quit.harness.js +14 -283
  63. package/dist/main/runtime/devtools-backend.js +14 -3
  64. package/dist/main/runtime/devtools-runtime-mock.harness.d.ts +21 -0
  65. package/dist/main/runtime/devtools-runtime-mock.harness.js +313 -0
  66. package/dist/main/services/app-services.d.ts +62 -0
  67. package/dist/main/services/app-services.js +64 -0
  68. package/dist/main/services/automation/connection-target.d.ts +36 -0
  69. package/dist/main/services/automation/connection-target.js +29 -0
  70. package/dist/main/services/automation/console-bridge.d.ts +28 -0
  71. package/dist/main/services/automation/console-bridge.js +91 -0
  72. package/dist/main/services/automation/handlers/app.js +4 -4
  73. package/dist/main/services/automation/handlers/element.js +55 -21
  74. package/dist/main/services/automation/index.d.ts +12 -1
  75. package/dist/main/services/automation/index.js +54 -133
  76. package/dist/main/services/default-adapter.js +1 -1
  77. package/dist/main/services/fs-bridge-protocol.d.ts +61 -0
  78. package/dist/main/services/fs-bridge-protocol.js +34 -0
  79. package/dist/main/services/fs-watch-sse.d.ts +8 -1
  80. package/dist/main/services/fs-watch-sse.js +19 -5
  81. package/dist/main/services/mcp/connection-owner.d.ts +38 -0
  82. package/dist/main/services/mcp/connection-owner.js +79 -0
  83. package/dist/main/services/mcp/index.d.ts +3 -1
  84. package/dist/main/services/mcp/index.js +4 -3
  85. package/dist/main/services/mcp/opened-project.d.ts +88 -0
  86. package/dist/main/services/mcp/opened-project.js +60 -0
  87. package/dist/main/services/mcp/target-manager.d.ts +71 -23
  88. package/dist/main/services/mcp/target-manager.js +269 -142
  89. package/dist/main/services/mcp/target-selection.d.ts +47 -0
  90. package/dist/main/services/mcp/target-selection.js +71 -0
  91. package/dist/main/services/mcp/tools/context-tools.js +20 -5
  92. package/dist/main/services/mcp/tools/project-tools.d.ts +29 -6
  93. package/dist/main/services/mcp/tools/project-tools.js +37 -25
  94. package/dist/main/services/module.d.ts +13 -5
  95. package/dist/main/services/notifications/renderer-notifier.d.ts +28 -4
  96. package/dist/main/services/notifications/renderer-notifier.js +15 -3
  97. package/dist/main/services/projects/local-provider.js +2 -0
  98. package/dist/main/services/projects/project-repository.d.ts +31 -1
  99. package/dist/main/services/projects/project-repository.js +144 -20
  100. package/dist/main/services/projects/types.d.ts +31 -8
  101. package/dist/main/services/safe-area/index.d.ts +19 -5
  102. package/dist/main/services/safe-area/index.js +38 -13
  103. package/dist/main/services/simulator/ui-extensions.d.ts +8 -0
  104. package/dist/main/services/simulator/ui-extensions.js +16 -6
  105. package/dist/main/services/simulator-storage/index.d.ts +12 -1
  106. package/dist/main/services/simulator-storage/index.js +22 -7
  107. package/dist/main/services/simulator-storage/window-scope.d.ts +20 -0
  108. package/dist/main/services/simulator-storage/window-scope.js +20 -0
  109. package/dist/main/services/views/host-slot-port-channel.d.ts +20 -3
  110. package/dist/main/services/views/host-slot-port-channel.js +33 -5
  111. package/dist/main/services/views/managed-web-contents-view.js +21 -1
  112. package/dist/main/services/views/native-simulator-view.js +13 -16
  113. package/dist/main/services/views/overlay-panels-view.d.ts +13 -0
  114. package/dist/main/services/views/overlay-panels-view.js +31 -0
  115. package/dist/main/services/views/view-manager.d.ts +1 -1
  116. package/dist/main/services/views/view-manager.js +3 -0
  117. package/dist/main/services/window-contexts/context-router.d.ts +36 -0
  118. package/dist/main/services/window-contexts/context-router.js +55 -0
  119. package/dist/main/services/workbench-coi-host.d.ts +52 -0
  120. package/dist/main/services/workbench-coi-host.js +227 -0
  121. package/dist/main/services/workbench-coi-server.js +75 -133
  122. package/dist/main/services/workbench-coi-shutdown.d.ts +40 -0
  123. package/dist/main/services/workbench-coi-shutdown.js +69 -0
  124. package/dist/main/services/workbench-coi-static.d.ts +23 -0
  125. package/dist/main/services/workbench-coi-static.js +87 -0
  126. package/dist/main/services/workbench-context.d.ts +27 -3
  127. package/dist/main/services/workbench-context.js +10 -5
  128. package/dist/main/services/workspace/compile-mode-adapter.d.ts +18 -0
  129. package/dist/main/services/workspace/compile-mode-adapter.js +57 -0
  130. package/dist/main/services/workspace/compile-mode-store.d.ts +25 -0
  131. package/dist/main/services/workspace/compile-mode-store.js +71 -0
  132. package/dist/main/services/workspace/workspace-compile-modes.d.ts +59 -0
  133. package/dist/main/services/workspace/workspace-compile-modes.js +93 -0
  134. package/dist/main/services/workspace/workspace-referer.d.ts +17 -0
  135. package/dist/main/services/workspace/workspace-referer.js +26 -0
  136. package/dist/main/services/workspace/workspace-service.d.ts +4 -0
  137. package/dist/main/services/workspace/workspace-service.js +51 -84
  138. package/dist/main/services/workspace/workspace-thumbnails.d.ts +22 -0
  139. package/dist/main/services/workspace/workspace-thumbnails.js +67 -0
  140. package/dist/main/utils/ipc-context-source.d.ts +40 -0
  141. package/dist/main/utils/ipc-context-source.js +23 -0
  142. package/dist/main/utils/ipc-registry.d.ts +42 -36
  143. package/dist/main/utils/ipc-registry.js +117 -50
  144. package/dist/main/utils/sender-policy.d.ts +9 -0
  145. package/dist/main/utils/sender-policy.js +26 -3
  146. package/dist/main/utils/theme.d.ts +3 -2
  147. package/dist/main/utils/theme.js +3 -2
  148. package/dist/main/windows/main-window/create.d.ts +16 -0
  149. package/dist/main/windows/main-window/create.js +19 -11
  150. package/dist/main/windows/main-window/events.d.ts +1 -1
  151. package/dist/main/windows/main-window/events.js +26 -13
  152. package/dist/main/windows/main-window/index.d.ts +1 -1
  153. package/dist/main/windows/main-window/index.js +1 -1
  154. package/dist/native-host/common/common.js +94 -73
  155. package/dist/native-host/render/render.js +4079 -3171
  156. package/dist/native-host/service/service.js +2 -2
  157. package/dist/preload/runtime/native-host.d.ts +4 -0
  158. package/dist/preload/runtime/temp-files.js +9 -2
  159. package/dist/preload/runtime/wait-for-slot-root.d.ts +7 -4
  160. package/dist/preload/runtime/wait-for-slot-root.js +36 -8
  161. package/dist/preload/windows/host-dialog-runtime.cjs +10 -3
  162. package/dist/preload/windows/host-dialog-runtime.cjs.map +2 -2
  163. package/dist/preload/windows/host-sidebar-runtime.cjs +10 -3
  164. package/dist/preload/windows/host-sidebar-runtime.cjs.map +2 -2
  165. package/dist/preload/windows/host-toolbar-runtime.cjs +10 -3
  166. package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
  167. package/dist/preload/windows/main.cjs +181 -4
  168. package/dist/preload/windows/main.cjs.map +4 -4
  169. package/dist/preload/windows/simulator.cjs +10 -0
  170. package/dist/preload/windows/simulator.cjs.map +2 -2
  171. package/dist/preload/windows/simulator.js +10 -0
  172. package/dist/render-host/pageFrame.html +1 -1
  173. package/dist/render-host/preload.cjs +16 -4
  174. package/dist/renderer/assets/button-CB2MWjHY.js +2 -0
  175. package/dist/renderer/assets/constants-CkoGPQTS.js +2 -0
  176. package/dist/renderer/assets/constants-zQZ2-y21.js +2 -0
  177. package/dist/renderer/assets/{createLucideIcon-Bqi8hpdi.js → createLucideIcon-cZ9FlZZw.js} +2 -2
  178. package/dist/renderer/assets/devicePicker-H2eIO4e1.js +2 -0
  179. package/dist/renderer/assets/dialog-pHzEA8Vx.js +46 -0
  180. package/dist/renderer/assets/dist-B5HADirS.js +2 -0
  181. package/dist/renderer/assets/{dist-DKWdE1TK.js → dist-DIFlRMKe.js} +2 -2
  182. package/dist/renderer/assets/hostSidebarDefault-DRWh6OCt.js +2 -0
  183. package/dist/renderer/assets/index-CEL_XFge.js +2 -0
  184. package/dist/renderer/assets/{input-Ct3alvkq.js → input-CAObw95L.js} +2 -2
  185. package/dist/renderer/assets/ipc-channels-overlays-gIPUFnqc.js +2 -0
  186. package/dist/renderer/assets/jsx-runtime-DICEQH_0.css +1 -0
  187. package/dist/renderer/assets/{jsx-runtime-DGLHmmOq.js → jsx-runtime-DIw5wnYl.js} +1 -1
  188. package/dist/renderer/assets/plus-BQ9u5EbL.js +2 -0
  189. package/dist/renderer/assets/popover-Cw7G2Ctp.js +2 -0
  190. package/dist/renderer/assets/presets-DMZOb9ay.js +2 -0
  191. package/dist/renderer/assets/project-api-YTOr_Yvo.js +2 -0
  192. package/dist/renderer/assets/{projectCreateDialog-Bbjz75bP.js → projectCreateDialog-BmLqiYxn.js} +2 -2
  193. package/dist/renderer/assets/search-BMvuYF48.js +2 -0
  194. package/dist/renderer/assets/select-nFP95TxM.js +2 -0
  195. package/dist/renderer/assets/settings-CnpVfSWt.js +2 -0
  196. package/dist/renderer/assets/settings-api-Ccsf-Nsj.js +2 -0
  197. package/dist/renderer/assets/settings-tab-bar-CAzrv32m.js +2 -0
  198. package/dist/renderer/assets/smartphone-Bb2GdIKy.js +2 -0
  199. package/dist/renderer/assets/tabs-CPKN3Mmq.js +2 -0
  200. package/dist/renderer/assets/{tooltip-B_-_YVbw.js → tooltip-D6AxXRk5.js} +2 -2
  201. package/dist/renderer/assets/types-Bh0hA7El.js +2 -0
  202. package/dist/renderer/assets/updateDialog-CwndJ0Bl.js +2 -0
  203. package/dist/renderer/assets/{utils-kfQov6Pa.js → utils-sEB5OZEQ.js} +2 -2
  204. package/dist/renderer/assets/view-api-B-2zPBR5.js +2 -0
  205. package/dist/renderer/assets/view-ids-BfaDVV5P.js +2 -0
  206. package/dist/renderer/assets/workbench-BLJ0wKsg.js +5 -0
  207. package/dist/renderer/assets/{workbenchSettings-CV4LVA9b.js → workbenchSettings-YD0Ctbm_.js} +3 -3
  208. package/dist/renderer/entries/device-picker/index.html +28 -0
  209. package/dist/renderer/entries/host-sidebar-default/index.html +6 -5
  210. package/dist/renderer/entries/main/index.html +16 -17
  211. package/dist/renderer/entries/popover/index.html +16 -10
  212. package/dist/renderer/entries/project-create-dialog/index.html +12 -12
  213. package/dist/renderer/entries/settings/index.html +10 -10
  214. package/dist/renderer/entries/tooltip/index.html +5 -5
  215. package/dist/renderer/entries/update-dialog/index.html +10 -10
  216. package/dist/renderer/entries/workbench/index.html +49 -0
  217. package/dist/renderer/entries/workbench-settings/index.html +12 -11
  218. package/dist/service-host/host-env-update.cjs +23 -0
  219. package/dist/service-host/preload.cjs +24 -49
  220. package/dist/service-host/service-message-queue.cjs +71 -0
  221. package/dist/service-host/sync-impls/system-info.js +31 -9
  222. package/dist/shared/compile-mode-state.d.ts +73 -0
  223. package/dist/shared/compile-mode-state.js +100 -0
  224. package/dist/shared/compile-modes.d.ts +152 -0
  225. package/dist/shared/compile-modes.js +237 -0
  226. package/dist/shared/ipc-channels-overlays.d.ts +8 -2
  227. package/dist/shared/ipc-channels-overlays.js +19 -2
  228. package/dist/shared/ipc-channels.d.ts +5 -10
  229. package/dist/shared/ipc-channels.js +17 -14
  230. package/dist/shared/ipc-schemas.d.ts +76 -24
  231. package/dist/shared/ipc-schemas.js +55 -10
  232. package/dist/shared/project-window-types.d.ts +42 -0
  233. package/dist/shared/project-window-types.js +2 -0
  234. package/dist/shared/types.d.ts +43 -17
  235. package/dist/shared/view-ids.d.ts +1 -0
  236. package/dist/shared/view-ids.js +3 -1
  237. package/dist/simulator/assets/bridge-channels-B3JAmRfl.js +2 -0
  238. package/dist/simulator/assets/device-shell-ATEhHV2_.css +1 -0
  239. package/dist/simulator/assets/device-shell-pxnZZp10.js +431 -0
  240. package/dist/simulator/assets/simulator-Dwp7lnvu.js +10 -0
  241. package/dist/simulator/assets/simulator-mini-app-DFo7fhi5.js +2 -0
  242. package/dist/simulator/assets/simulator-ui-B2ddJB1R.js +2 -0
  243. package/dist/simulator/simulator.html +3 -3
  244. package/dist/simulator/temp-files.d.ts +6 -0
  245. package/dist/simulator/temp-files.js +46 -4
  246. package/dist/simulator/types.d.ts +7 -0
  247. package/dist/vscode-workbench/assets/__vite-browser-external-JIkWewFf.js +1 -0
  248. package/dist/vscode-workbench/assets/{dist-CMfmHflW.js → dist-CXG-u1VB.js} +3 -3
  249. package/dist/vscode-workbench/assets/{iconv-lite-umd-Bx8CgaZq.js → iconv-lite-umd-Dxx9Qyb4.js} +1 -1
  250. package/dist/vscode-workbench/assets/{index-CdG6YWhW.js → index-6VJMsaWj.js} +460 -460
  251. package/dist/vscode-workbench/assets/{jschardet-M0qgd2lN.js → jschardet-Ba3D16vt.js} +1 -1
  252. package/dist/vscode-workbench/index.html +1 -1
  253. package/package.json +11 -8
  254. package/dist/renderer/assets/button-D5Q2wkXq.js +0 -2
  255. package/dist/renderer/assets/constants-D7DfVqMp.js +0 -2
  256. package/dist/renderer/assets/constants-D8zsejFq.js +0 -2
  257. package/dist/renderer/assets/dialog-e1TecTOY.js +0 -46
  258. package/dist/renderer/assets/hostSidebarDefault-B3yLfy8j.js +0 -2
  259. package/dist/renderer/assets/index-CsPD68N_.js +0 -5
  260. package/dist/renderer/assets/ipc-channels-overlays-LsDzGAtV.js +0 -2
  261. package/dist/renderer/assets/jsx-runtime-2vXHouwr.css +0 -1
  262. package/dist/renderer/assets/popover-Dix5cm_b.js +0 -2
  263. package/dist/renderer/assets/project-api-k7Oq9iaq.js +0 -2
  264. package/dist/renderer/assets/select-acGb0AmJ.js +0 -2
  265. package/dist/renderer/assets/settings-CQrTMr43.js +0 -2
  266. package/dist/renderer/assets/settings-api-CrUQ9rYV.js +0 -2
  267. package/dist/renderer/assets/settings-tab-bar-Cw1kVIf2.js +0 -2
  268. package/dist/renderer/assets/types-CsEKtFyr.js +0 -2
  269. package/dist/renderer/assets/updateDialog-NsF8223A.js +0 -2
  270. package/dist/renderer/assets/view-api-CLn3rcQE.js +0 -2
  271. package/dist/simulator/assets/bridge-channels-zhsumfky.js +0 -2
  272. package/dist/simulator/assets/device-shell-CmtM1QxP.js +0 -2
  273. package/dist/simulator/assets/device-shell-iFZo1igL.css +0 -1
  274. package/dist/simulator/assets/simulator-CIobn3Mh.js +0 -10
  275. package/dist/simulator/assets/simulator-mini-app-CRe6n9br.js +0 -2
  276. package/dist/simulator/assets/simulator-ui-C_cP602X.js +0 -2
  277. package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +0 -1
@@ -9,6 +9,10 @@ export interface RenderHostUrlOptions {
9
9
  /** Whether this page is a tabBar page. Surfaced on the URL so main can pick
10
10
  * the bottom safe-area policy at `did-attach-webview` (services/safe-area). */
11
11
  isTab?: boolean;
12
+ /** The page's resolved `navigationStyle` (page ∪ app-level). Surfaced on the
13
+ * URL as `navStyle` so main can pick the TOP safe-area policy at
14
+ * `did-attach-webview` (services/safe-area). */
15
+ navigationStyle?: 'default' | 'custom';
12
16
  /** The page's resolved `window.backgroundColor` (page ∪ app-level, already
13
17
  * defaulted — see `pageBackgroundColor` in page-stack-controller.ts).
14
18
  * Surfaced on the URL as `bgColor`: render-host/preload.cjs reads it and
@@ -19,8 +19,15 @@ export function installTempFileBridge() {
19
19
  });
20
20
  })
21
21
  .catch(() => {
22
- // best effort: blob read failures cannot be surfaced through the
23
- // sink contract (`write` is sync void), so we swallow them.
22
+ // 旧的同步创建入口只能 best effort;要求立即可读的调用走 writeAndWait。
23
+ });
24
+ },
25
+ async writeAndWait(path, blob) {
26
+ const bytes = await blob.arrayBuffer();
27
+ await ipcRenderer.invoke('simulator:temp-file:write-confirmed', {
28
+ path,
29
+ mime: blob.type,
30
+ bytes,
24
31
  });
25
32
  },
26
33
  revoke(path) {
@@ -11,10 +11,13 @@
11
11
  * The "root is missing" warning exists for downstream authors who forgot the
12
12
  * element entirely, so it must not fire on the healthy async-mount path — a
13
13
  * warning printed on every normal load is noise that trains its readers to
14
- * ignore it. It is therefore withheld until the document has finished loading
15
- * (`window.load`, a real event rather than a guessed delay) with the root
16
- * still absent; the observer stays armed either way, so a root that mounts
17
- * even later is still picked up.
14
+ * ignore it. Two conditions gate it, both signals rather than guessed delays:
15
+ * the document must be one the host actually loaded content into (not the
16
+ * view's own blank document), and it must have finished loading AND run out of
17
+ * pending work (`window.load`, then an idle callback — a framework's first
18
+ * commit is normal-priority work, so it always lands before idle). The
19
+ * observer stays armed either way, so a root that mounts even later is still
20
+ * picked up.
18
21
  */
19
22
  export declare function whenSlotRootReady(selector: string, missingWarning: string, install: (root: HTMLElement) => void): void;
20
23
  //# sourceMappingURL=wait-for-slot-root.d.ts.map
@@ -11,13 +11,22 @@
11
11
  * The "root is missing" warning exists for downstream authors who forgot the
12
12
  * element entirely, so it must not fire on the healthy async-mount path — a
13
13
  * warning printed on every normal load is noise that trains its readers to
14
- * ignore it. It is therefore withheld until the document has finished loading
15
- * (`window.load`, a real event rather than a guessed delay) with the root
16
- * still absent; the observer stays armed either way, so a root that mounts
17
- * even later is still picked up.
14
+ * ignore it. Two conditions gate it, both signals rather than guessed delays:
15
+ * the document must be one the host actually loaded content into (not the
16
+ * view's own blank document), and it must have finished loading AND run out of
17
+ * pending work (`window.load`, then an idle callback — a framework's first
18
+ * commit is normal-priority work, so it always lands before idle). The
19
+ * observer stays armed either way, so a root that mounts even later is still
20
+ * picked up.
18
21
  */
19
22
  export function whenSlotRootReady(selector, missingWarning, install) {
20
23
  function attempt() {
24
+ // The slot's WebContentsView holds its own empty document until the host
25
+ // loads content into it, and this preload runs there too. That document
26
+ // has no author: a missing root in it is not a mistake anyone made, and
27
+ // warning about it fires on every app start. The observer below still gets
28
+ // armed, so content that does arrive is picked up.
29
+ const authored = location.href !== 'about:blank' && location.href !== '';
21
30
  const root = document.querySelector(selector);
22
31
  if (root) {
23
32
  install(root);
@@ -33,14 +42,33 @@ export function whenSlotRootReady(selector, missingWarning, install) {
33
42
  install(lateRoot);
34
43
  });
35
44
  observer.observe(document.documentElement, { childList: true, subtree: true });
45
+ // Re-queries rather than trusting `installed`: the observer delivers on a
46
+ // microtask, so a root that is already in the DOM may not have been
47
+ // installed yet — it is present either way, which is what the warning is
48
+ // about.
36
49
  const warnIfStillMissing = () => {
37
- if (!installed)
38
- console.warn(missingWarning);
50
+ if (installed || !authored || document.querySelector(selector))
51
+ return;
52
+ console.warn(missingWarning);
53
+ };
54
+ // `load` alone is too early a verdict: a concurrent React root commits its
55
+ // first render on a scheduler task that can land after it, and the warning
56
+ // would then race the healthy mount it is supposed to ignore. Idle
57
+ // callbacks run only once the main thread has no pending work of that
58
+ // kind, so a root still absent then is genuinely absent. The timeout is
59
+ // the cap for a page that never goes idle, not the mechanism.
60
+ const decide = () => {
61
+ const idle = globalThis
62
+ .requestIdleCallback;
63
+ if (typeof idle === 'function')
64
+ idle(warnIfStillMissing, { timeout: 5_000 });
65
+ else
66
+ warnIfStillMissing();
39
67
  };
40
68
  if (document.readyState === 'complete')
41
- warnIfStillMissing();
69
+ decide();
42
70
  else
43
- window.addEventListener('load', warnIfStillMissing, { once: true });
71
+ window.addEventListener('load', decide, { once: true });
44
72
  }
45
73
  if (document.readyState === 'loading') {
46
74
  document.addEventListener('DOMContentLoaded', attempt, { once: true });
@@ -211,6 +211,7 @@ var ViewChannel = {
211
211
  // src/preload/runtime/wait-for-slot-root.ts
212
212
  function whenSlotRootReady(selector, missingWarning, install) {
213
213
  function attempt() {
214
+ const authored = location.href !== "about:blank" && location.href !== "";
214
215
  const root = document.querySelector(selector);
215
216
  if (root) {
216
217
  install(root);
@@ -226,10 +227,16 @@ function whenSlotRootReady(selector, missingWarning, install) {
226
227
  });
227
228
  observer.observe(document.documentElement, { childList: true, subtree: true });
228
229
  const warnIfStillMissing = () => {
229
- if (!installed) console.warn(missingWarning);
230
+ if (installed || !authored || document.querySelector(selector)) return;
231
+ console.warn(missingWarning);
230
232
  };
231
- if (document.readyState === "complete") warnIfStillMissing();
232
- else window.addEventListener("load", warnIfStillMissing, { once: true });
233
+ const decide = () => {
234
+ const idle = globalThis.requestIdleCallback;
235
+ if (typeof idle === "function") idle(warnIfStillMissing, { timeout: 5e3 });
236
+ else warnIfStillMissing();
237
+ };
238
+ if (document.readyState === "complete") decide();
239
+ else window.addEventListener("load", decide, { once: true });
233
240
  }
234
241
  if (document.readyState === "loading") {
235
242
  document.addEventListener("DOMContentLoaded", attempt, { once: true });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/shared/constants.ts", "../../../src/preload/runtime/host-dialog-advertiser.ts", "../../../../view-anchor/src/measure-loop.ts", "../../../../view-anchor/src/size-advertiser.ts", "../../../src/shared/ipc-channels-overlays.ts", "../../../src/preload/runtime/wait-for-slot-root.ts", "../../../src/preload/runtime/host-slot-port-bridge.ts", "../../../src/preload/runtime/host-dialog-port.ts", "../../../src/preload/runtime/host-dialog-runtime.ts", "../../../src/preload/windows/host-dialog-runtime.ts"],
4
- "sourcesContent": ["/** Shared cross-process constants for dimina-devtools. */\n\n/** Default Chrome DevTools Protocol (CDP) remote debugging port. */\nexport const DEFAULT_CDP_PORT = 9222\n\n/** Default scene value for mini-app launch. */\nexport const DEFAULT_SCENE = 1001\n\n/**\n * Fixed devtools toolbar header height (px). Single source of truth shared by\n * the main process (overlay view layout) and the renderer (toolbar/popover\n * layout). Not host-configurable \u2014 the deprecated\n * `WorkbenchAppConfig.headerHeight` is ignored; hosts that need their own\n * toolbar use the host toolbar WCV instead.\n */\nexport const HEADER_H = 40\n\n/**\n * Process-level argv marker injected (via `webPreferences.additionalArguments`)\n * into the host-toolbar WebContentsView. The session-registered toolbar-runtime\n * preload (`src/preload/runtime/host-toolbar-runtime.ts`) executes in EVERY\n * defaultSession renderer; its guard activates the height advertiser only when\n * `process.argv` carries this marker AND `process.isMainFrame` is true (the\n * marker is process-level, so subframes of the toolbar window see it too \u2014\n * both guard wings are required).\n */\nexport const HOST_TOOLBAR_RUNTIME_MARKER = '--dimina-host-toolbar'\n\n/**\n * Same guard-marker contract as {@link HOST_TOOLBAR_RUNTIME_MARKER}, for the\n * host-sidebar WebContentsView (`src/preload/runtime/host-sidebar-runtime.ts`).\n */\nexport const HOST_SIDEBAR_RUNTIME_MARKER = '--dimina-host-sidebar'\n\n/**\n * Same guard-marker contract as {@link HOST_TOOLBAR_RUNTIME_MARKER}, for the\n * host-dialog WebContentsView (`src/preload/runtime/host-dialog-runtime.ts`).\n */\nexport const HOST_DIALOG_RUNTIME_MARKER = '--dimina-host-dialog'\n\n/**\n * Intrinsic width (px) of devtools' own default host-sidebar content (the\n * project-category icon rail). Single source of truth shared by the renderer\n * (`host-sidebar-default.tsx`, which gives its `[data-host-sidebar-root]` this\n * exact width so the width advertiser reports it) and anything in main that\n * needs to reason about the default rail's size. The slot is NOT left pinned\n * at this width: main pushes it once as a seed and immediately returns the\n * slot to 'auto' (see `createDevtoolsRuntime`), so the rail \u2014 and any\n * downstream `loadURL`/`loadFile` content that replaces it \u2014 advertises its\n * own width from then on, exactly like any other host-sidebar content.\n */\nexport const HOST_SIDEBAR_DEFAULT_WIDTH = 56\n", "/**\n * Reverse size-advertiser preload for the host-controllable dialog\n * WebContentsView. Runs in that WCV's OWN renderer (the dialog content's\n * preload). Unlike the toolbar/sidebar (single-axis persistent strips), the\n * dialog self-sizes on BOTH axes \u2014 it has no renderer placeholder to anchor\n * against, so main centers it in the main window purely from what this\n * advertiser reports. Two independent `createSizeAdvertiser` instances (one\n * per axis) share the same root and the same outbound channel\n * (`HostDialogAdvertiseSize` carries `{ axis, extent }` for either axis); main\n * re-centers using whichever axes it has measured so far (see\n * `host-dialog-view.ts`'s `reportMeasuredExtent` / default-size fallback).\n */\n\nimport { ipcRenderer } from 'electron'\nimport { createSizeAdvertiser } from '@dimina-kit/view-anchor'\nimport { ViewChannel } from '../../shared/ipc-channels-overlays.js'\nimport { whenSlotRootReady } from './wait-for-slot-root.js'\n\n/**\n * Attach both axis advertisers to the dialog content's shrink-to-fit root\n * (`[data-host-dialog-root]`), waiting for it if necessary \u2014 the root may be\n * mounted asynchronously by a framework rather than present in the initial\n * HTML. That element MUST be shrink-to-fit on BOTH axes \u2014 same footgun as\n * the toolbar/sidebar (`createSizeAdvertiser`'s single-axis-ownership\n * requirement), just doubled.\n */\nexport function installHostDialogAdvertiserWhenReady(): void {\n whenSlotRootReady(\n '[data-host-dialog-root]',\n '[host-dialog-advertiser] no `[data-host-dialog-root]` element found \u2014 ' +\n 'not advertising a size yet. The dialog content must wrap itself in a ' +\n 'shrink-to-fit `[data-host-dialog-root]` element so its size is the ' +\n 'content size, not the host-given view size.',\n (root) => {\n const publish = (size: { axis: 'block' | 'inline'; extent: number }): void => {\n ipcRenderer.send(ViewChannel.HostDialogAdvertiseSize, size)\n }\n\n createSizeAdvertiser(root, { axis: 'block', publish })\n createSizeAdvertiser(root, { axis: 'inline', publish })\n },\n )\n}\n", "/**\n * Internal \u2014 the RAF-coalesced measure/dedupe/dispose engine behind the REVERSE\n * primitive `createSizeAdvertiser`.\n *\n * The forward `createViewAnchor` deliberately does NOT use this: it publishes\n * SYNCHRONOUSLY (a native overlay's `setBounds` already lands a cross-process\n * frame late, and a RAF stacked a second frame of visible trailing). The\n * reverse direction is different \u2014 it is a cross-process FEEDBACK loop\n * (advertise \u2192 host resizes the view \u2192 content re-measures \u2192 re-advertise), so\n * the RAF's one-publish-per-frame coalescing is a useful damper. The two\n * directions thus have different optimal emit timing; this engine serves only\n * the reverse.\n *\n * NOT exported from the package: it is pure mechanism with no knowledge of\n * direction, the DOM, `ResizeObserver`, or the structure of the value `T` it\n * carries. The wrapping primitive injects `produce` / `same` / `sink` and\n * drives the lifecycle.\n *\n * - `schedule()` \u2014 coalesce a burst of triggers into ONE RAF; the frame\n * body re-`produce()`s, dedupes against the last emit (`same`), and `sink`s.\n * Bails if inactive or disposed (stale-RAF safe).\n * - `emitNow(v)` \u2014 explicit synchronous emit (create / update path). Always\n * fires, bypassing the dedupe check, and refreshes the dedupe baseline.\n * - `setActive` \u2014 gate the observer stream; a queued frame bails on `!active`.\n * - `cancel` \u2014 drop any in-flight RAF.\n * - `dispose` \u2014 cancel + go inert; after dispose nothing emits again.\n */\nexport interface MeasureLoop<T> {\n schedule(): void\n emitNow(value: T): void\n setActive(on: boolean): void\n cancel(): void\n dispose(): void\n}\n\nexport function createMeasureLoop<T>(cfg: {\n /** Produce the value to emit in the RAF body. Return `null` to decline the\n * frame entirely (no dedupe, no sink, baseline untouched) \u2014 e.g. a\n * non-finite or unavailable measurement. */\n produce: () => T | null\n same: (a: T, b: T) => boolean\n sink: (value: T) => void\n}): MeasureLoop<T> {\n const { produce, same, sink } = cfg\n let rafId: number | null = null\n let active = false\n let disposed = false\n let last: T | null = null\n\n const cancel = (): void => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n rafId = null\n }\n }\n\n return {\n schedule(): void {\n if (disposed || !active || rafId !== null) return\n rafId = requestAnimationFrame(() => {\n rafId = null\n if (disposed || !active) return\n const value = produce()\n if (value === null) return // producer declined this frame\n // last-value dedupe: a frame whose produced value equals the last one\n // we emitted costs nothing (no IPC / setBounds).\n if (last !== null && same(value, last)) return\n last = value\n sink(value)\n })\n },\n emitNow(value: T): void {\n if (disposed) return\n last = value\n sink(value)\n },\n setActive(on: boolean): void {\n active = on\n },\n cancel,\n dispose(): void {\n if (disposed) return\n disposed = true\n cancel()\n },\n }\n}\n", "import type {\n AdvertisedSize,\n SizeAdvertiserOptions,\n SizeAdvertiserHandle,\n} from './types.js'\nimport { createMeasureLoop } from './measure-loop.js'\n\n/**\n * Reverse of `createViewAnchor`: runs in a downstream WebContentsView's own\n * renderer, measures the content's own size on ONE owned axis (from the\n * `ResizeObserver` border-box \u2014 no `getBoundingClientRect`, no forced reflow),\n * and advertises it via the injected `publish`. Shares the forward primitive's\n * measure/coalesce/dedupe/dispose engine (`createMeasureLoop`).\n *\n * The extent is `Math.round`ed and clamped to `>= 0`; non-finite measurements\n * drop the frame.\n *\n * FOOTGUN \u2014 `target` must be shrink-to-fit on the owned axis: its owned-axis\n * size must NOT be driven by the host-applied view size, or the cross-process\n * loop (advertise \u2192 host resizes view \u2192 remeasure) never converges (it\n * oscillates or stays \"stable but wrong\"). Measuring `<body>`/`<html>` is the\n * classic mistake \u2014 their size *is* the view size. See\n * `docs/bidirectional-design.md`'s single-axis-ownership and trust-boundary\n * sections.\n */\nexport function createSizeAdvertiser(\n target: HTMLElement,\n opts: SizeAdvertiserOptions,\n): SizeAdvertiserHandle {\n const axis = opts.axis // immutable for the advertiser's life\n let publish = opts.publish\n let observer: ResizeObserver | null = null\n let disposed = false\n // Latest border-box, stashed by the RO callback and read by `produce` in the\n // RAF body (keep the entry out of the shared, DOM-agnostic loop).\n let latest: ResizeObserverSize | null = null\n\n const produce = (): AdvertisedSize | null => {\n if (!latest) return null\n const raw = axis === 'block' ? latest.blockSize : latest.inlineSize\n if (!Number.isFinite(raw)) return null\n return { axis, extent: Math.max(0, Math.round(raw)) }\n }\n\n const loop = createMeasureLoop<AdvertisedSize>({\n produce,\n same: (a, b) => a.extent === b.extent, // axis is constant\n sink: (size) => publish(size),\n })\n\n const onResize: ResizeObserverCallback = (entries) => {\n const entry = entries[entries.length - 1]\n if (entry) {\n latest = entry.borderBoxSize?.[0] ?? entry.contentBoxSize?.[0] ?? latest\n }\n loop.schedule()\n }\n\n // One cheap, once-per-advertiser guard for the textbook feedback-loop footgun.\n const doc = target.ownerDocument\n if (target === doc.body || target === doc.documentElement) {\n console.warn(\n `[view-anchor] size-advertiser: <${target === doc.body ? 'body' : 'html'}>'s ` +\n `${axis} size is the host-given view size, not the content size \u2014 the ` +\n `advertiser will never shrink to content. Measure a shrink-to-fit wrapper. ` +\n `See bidirectional-design.md's single-axis-ownership section.`,\n )\n }\n\n loop.setActive(true)\n observer = new ResizeObserver(onResize)\n observer.observe(target)\n\n return {\n update(nextPublish: (size: AdvertisedSize) => void): void {\n if (disposed) return\n publish = nextPublish\n // Re-advertise the current size to the new sink immediately (mirrors the\n // forward anchor's re-publish on update) so the new channel is not left\n // sizeless until the next ResizeObserver tick.\n const cur = produce()\n if (cur) loop.emitNow(cur)\n },\n dispose(): void {\n if (disposed) return\n disposed = true\n loop.cancel()\n if (observer) {\n observer.disconnect()\n observer = null\n }\n loop.dispose()\n },\n }\n}\n", "/**\n * IPC channel name constants for dimina-devtools' overlay/panel\n * WebContentsViews \u2014 layout slots (host-toolbar/host-sidebar/host-dialog),\n * the popover, tooltip, project-create dialog and settings overlays, plus\n * the update flow. Split out of `ipc-channels.ts` (see that file's header)\n * once this group alone pushed it past the repo's file-length threshold \u2014\n * these constants share no runtime dependency on the rest of that file, so\n * the split is a pure line-count relief valve, not a behavior change.\n */\n\n// \u2500\u2500 Embedded views (renderer \u2192 main) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The main window's React layout owns the *positions* of the editor +\n// simulator-DevTools WebContentsView overlays \u2014 each visible placeholder\n// `<div>` measures its client rect via ResizeObserver and pushes the\n// rectangle to the main process. The view manager caches the latest\n// payload per kind and applies it to the overlay; no payload means the\n// overlay is hidden.\n//\n// Payload (after schema validation): `{ x, y, width, height }` in CSS\n// pixels relative to the window's content area (origin = top-left,\n// not including the OS chrome).\nexport const ViewChannel = {\n /**\n * Reverse size-advertiser: the host-toolbar WCV's OWN renderer advertises its\n * intrinsic content height so main reserves exactly that much. Payload\n * `{ axis: 'block', extent }`. fire-and-forget (send), NOT invoke.\n */\n HostToolbarAdvertiseHeight: 'view:host-toolbar:advertise-height',\n /**\n * main \u2192 host-toolbar WCV renderer: per-load MessagePort handshake for the\n * gated narrow channel. On every toolbar `did-finish-load` main creates a\n * `MessageChannelMain` and transfers port2 here\n * (`wc.postMessage(HostToolbarPort, null, [port2])`); the session-resident\n * toolbar runtime preload receives it via `event.ports[0]` and bridges it to\n * the page as `window.diminaHostToolbar`. Envelope both directions:\n * `{ channel: string, payload: unknown }`.\n */\n HostToolbarPort: 'view:host-toolbar:port',\n /**\n * main \u2192 main-window renderer: push the reserved host-toolbar height so the\n * renderer placeholder div resizes (closing the dynamic-height loop).\n */\n HostToolbarHeightChanged: 'view:host-toolbar:height-changed',\n /**\n * main \u2190 main-window renderer (invoke): pull the last NOTIFIED toolbar\n * height retained in main. Mount-time replay companion to\n * `HostToolbarHeightChanged`: the push listener mounts with the project\n * view and the toolbar's size-advertiser deduplicates (never re-reports),\n * so a height pushed while no project view was mounted would otherwise be\n * lost forever (cold start on the project list races it; close-project \u2192\n * reopen hits it deterministically). No payload; resolves a number.\n */\n HostToolbarGetHeight: 'view:host-toolbar:get-height',\n /**\n * Reverse size-advertiser for the host-sidebar WCV, mirroring\n * `HostToolbarAdvertiseHeight` on the inline (width) axis instead of block.\n * Payload `{ axis: 'inline', extent }`. fire-and-forget (send), NOT invoke.\n */\n HostSidebarAdvertiseWidth: 'view:host-sidebar:advertise-width',\n /**\n * main \u2192 host-sidebar WCV renderer: per-load MessagePort handshake, same\n * contract as `HostToolbarPort` (see that entry).\n */\n HostSidebarPort: 'view:host-sidebar:port',\n /**\n * main \u2192 main-window renderer: push the reserved host-sidebar width so the\n * renderer placeholder div resizes, mirroring `HostToolbarHeightChanged`.\n */\n HostSidebarWidthChanged: 'view:host-sidebar:width-changed',\n /**\n * main \u2190 main-window renderer (invoke): pull the last NOTIFIED sidebar\n * width, mirroring `HostToolbarGetHeight`'s mount-time replay role.\n */\n HostSidebarGetWidth: 'view:host-sidebar:get-width',\n /**\n * main \u2192 main-window renderer: push the project category (`Project.type`)\n * selected in the host-sidebar's content \u2014 devtools' own default icon rail,\n * or any downstream replacement that sends on the same channel. No\n * pull/replay companion like `HostSidebarGetWidth`: the default category is\n * a stable initial value regardless of load-order, and nothing is ever sent\n * before the main-window renderer (and thus `ProjectListScreen`) is already\n * mounted.\n */\n HostSidebarCategorySelected: 'view:host-sidebar:category-selected',\n /**\n * Reverse size-advertiser for the host-dialog WCV. Unlike the toolbar/sidebar\n * (single-axis, `setBaseDesired`-placed strips), the dialog is a BOTH-AXES\n * overlay positioned by `setOverlayDesired` \u2014 main centers it in the main\n * window once it knows both dimensions. One channel carries either axis'\n * report (`{ axis: 'block' | 'inline', extent }`); the dialog's own content\n * advertises both from the same root (see `host-dialog-advertiser.ts`).\n * fire-and-forget (send), NOT invoke.\n *\n * No `HostDialogSizeChanged` / `HostDialogGetSize` counterparts: those exist\n * for toolbar/sidebar so a renderer-owned PLACEHOLDER can replay a size it\n * missed. The dialog has no such placeholder \u2014 it is a main-driven overlay\n * shown/hidden on demand (`hostDialog.show()`/`hide()`), so there is nothing\n * in the renderer to replay a size into.\n */\n HostDialogAdvertiseSize: 'view:host-dialog:advertise-size',\n /**\n * main \u2192 host-dialog WCV renderer: per-load MessagePort handshake, same\n * contract as `HostToolbarPort` (see that entry).\n */\n HostDialogPort: 'view:host-dialog:port',\n /**\n * Renderer \u2192 main: the window-level placement snapshot (one monotonic epoch\n * per commit tick, one generation per renderer lifetime) that drives the view\n * reconciler. The single source of truth for every managed native view's\n * bounds/visibility/z-order \u2014 supersedes the per-view bounds channels above.\n * invoke.\n */\n PlacementSnapshot: 'view:placement-snapshot',\n /**\n * main \u2190 main-window renderer (invoke): allocate a fresh placement\n * generation seed for this renderer bootstrap. See\n * renderer-placement-generation.ts for why the seed comes from main\n * (a wall-clock `Date.now()` seed is not guaranteed to exceed main's\n * still-standing high-water mark across two reloads that happen faster\n * than the clock's resolution). No payload; resolves a number.\n */\n AllocatePlacementGeneration: 'view:allocate-placement-generation',\n} as const\n\nexport interface ViewBounds {\n x: number\n y: number\n width: number\n height: number\n}\n\n// \u2500\u2500 Popover \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const PopoverChannel = {\n Show: 'popover:show',\n Hide: 'popover:hide',\n Relaunch: 'popover:relaunch',\n Closed: 'popover:closed',\n Init: 'popover:init',\n} as const\n\n// \u2500\u2500 Tooltip \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// A top-tier overlay WebContentsView (VIEW_LAYER.tooltip \u2014 see view-ids.ts),\n// NOT a DOM tooltip in the main renderer: any DOM-portaled floating UI (Radix\n// Tooltip) or the browser-native `title` attribute lives in the main\n// renderer's own paint surface, which every other WCV (simulator, editor,\n// settings, popover) renders on top of \u2014 CSS cannot reach across that\n// boundary. A trigger reports its anchor rect + label; main computes the\n// tooltip's screen bounds and shows/repositions/hides this overlay.\n\nexport const OverlayChannel = {\n Ready: 'overlay:ready',\n} as const\n\nexport const TooltipChannel = {\n Prepare: 'tooltip:prepare',\n Show: 'tooltip:show',\n Hide: 'tooltip:hide',\n Init: 'tooltip:init',\n Measured: 'tooltip:measured',\n} as const\n\n// \u2500\u2500 Project-create dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// A top-tier overlay WebContentsView (VIEW_LAYER.dialog), NOT the Radix\n// `fixed inset-0` DOM portal it replaced \u2014 a DOM overlay paints inside the\n// main window's own renderer, so any native WebContentsView mounted on top\n// (simulator, host-toolbar, host-sidebar) occludes it. main.tsx fetches the\n// template catalog + base-dir defaults, then asks main to show this panel;\n// the panel relays submit/cancel back to main.tsx to run the existing\n// scaffold flow.\n\nexport const ProjectCreateChannel = {\n Show: 'projectCreate:show',\n Init: 'projectCreate:init',\n Submit: 'projectCreate:submit',\n Cancel: 'projectCreate:cancel',\n Submitted: 'projectCreate:submitted',\n} as const\n\n// \u2500\u2500 Embedded settings overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const SettingsChannel = {\n SetVisible: 'settings:setVisible',\n ConfigChanged: 'settings:configChanged',\n ProjectSettingsChanged: 'settings:projectSettingsChanged',\n Init: 'settings:init',\n} as const\n\n// \u2500\u2500 Updates (UpdateManager) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// String values are FROZEN: shipped builds key off them. Add new entries\n// here, never rename existing ones.\nexport const UpdateChannel = {\n Check: 'updates:check',\n Download: 'updates:download',\n Install: 'updates:install',\n DownloadProgress: 'updates:downloadProgress',\n Available: 'updates:available',\n Close: 'updates:close',\n} as const\n", "/**\n * Shared readiness wait for a host-slot content's shrink-to-fit measurement\n * root (`[data-host-*-root]`). A one-shot `document.querySelector` at\n * `DOMContentLoaded` time only works when the root is present in the initial\n * HTML. Framework-rendered content (e.g. a React app) can mount its root\n * asynchronously, after `DOMContentLoaded` has already fired \u2014 a one-shot\n * check misses it permanently and the slot's width/height is never\n * advertised. This keeps watching via `MutationObserver` instead of assuming\n * a synchronous mount, without polling on a fixed delay.\n *\n * The \"root is missing\" warning exists for downstream authors who forgot the\n * element entirely, so it must not fire on the healthy async-mount path \u2014 a\n * warning printed on every normal load is noise that trains its readers to\n * ignore it. It is therefore withheld until the document has finished loading\n * (`window.load`, a real event rather than a guessed delay) with the root\n * still absent; the observer stays armed either way, so a root that mounts\n * even later is still picked up.\n */\nexport function whenSlotRootReady(\n selector: string,\n missingWarning: string,\n install: (root: HTMLElement) => void,\n): void {\n function attempt(): void {\n const root = document.querySelector<HTMLElement>(selector)\n if (root) {\n install(root)\n return\n }\n\n let installed = false\n const observer = new MutationObserver(() => {\n const lateRoot = document.querySelector<HTMLElement>(selector)\n if (!lateRoot) return\n observer.disconnect()\n installed = true\n install(lateRoot)\n })\n observer.observe(document.documentElement, { childList: true, subtree: true })\n\n const warnIfStillMissing = (): void => {\n if (!installed) console.warn(missingWarning)\n }\n if (document.readyState === 'complete') warnIfStillMissing()\n else window.addEventListener('load', warnIfStillMissing, { once: true })\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', attempt, { once: true })\n } else {\n attempt()\n }\n}\n", "/**\n * Shared implementation behind every host-slot page bridge (toolbar/sidebar/\n * dialog): the MessagePort handshake, pending-queue-with-bounded-overflow,\n * handler registry and `{ send, onMessage }` contextBridge exposure are\n * IDENTICAL across slots \u2014 only the bridge key, handshake channel, queue cap\n * and overflow-warning label differ. Each slot's own `host-*-port.ts` stays\n * the frozen public surface (see its own \"PUBLIC SURFACE EVOLUTION RULE\"\n * doc-comment) and calls this factory with its own constants; this module has\n * no public-surface contract of its own.\n */\nimport { contextBridge, ipcRenderer } from 'electron'\n\nexport interface HostSlotPortBridgeOptions {\n /** contextBridge key the page-facing API is exposed under, e.g. 'diminaHostToolbar'. */\n bridgeKey: string\n /** main \u2192 renderer per-load handshake channel, e.g. ViewChannel.HostToolbarPort. */\n channel: string\n /** Cap on pre-handshake queued sends; overflow drops the NEWEST envelope. */\n pendingLimit: number\n /** Slot label used in the overflow console.warn, e.g. 'host-toolbar'. */\n label: string\n}\n\n/**\n * Subscribe the handshake channel and expose the page bridge. Call ONLY from\n * a passing per-slot runtime guard \u2014 a failing guard must leave zero\n * footprint (no bridge key, no IPC listener), so this factory itself does no\n * guard checking; the caller decides whether to call it at all.\n */\nexport function createHostSlotPortBridge(opts: HostSlotPortBridgeOptions): void {\n const { bridgeKey, channel, pendingLimit, label } = opts\n let activePort: MessagePort | null = null\n const pending: Array<{ channel: string; payload: unknown }> = []\n // One overflow warning per load (this installer runs once per document) \u2014\n // a runaway page send-loop must not get per-drop console spam.\n let warnedPendingOverflow = false\n const handlers: Array<{ channel: string; handler: (payload: unknown) => void }> = []\n\n // Entry-waist channel validation, parity with the main side's `onMessage`\n // guard (same TypeError, message names `channel`). Runs BEFORE any state is\n // touched (no queue slot, no registry entry), in both port states \u2014 a page\n // author's typo throws at the call site instead of vanishing into main's\n // silent inbound drop.\n function assertValidChannel(method: string, ch: unknown): asserts ch is string {\n if (typeof ch !== 'string' || ch === '') {\n throw new TypeError(`${bridgeKey}.${method}: channel must be a non-empty string`)\n }\n }\n\n const dispatch = (data: unknown): void => {\n // Defensive symmetry with main: drop anything that is not an object\n // envelope with a string channel \u2014 never throw in the dispatcher.\n if (typeof data !== 'object' || data === null) return\n const { channel: ch, payload } = data as { channel?: unknown; payload?: unknown }\n if (typeof ch !== 'string') return\n for (const entry of [...handlers]) {\n if (entry.channel === ch) entry.handler(payload)\n }\n }\n\n const onPortMessage = (event: MessageEvent): void => {\n dispatch(event.data)\n }\n\n ipcRenderer.on(channel, (event) => {\n const port = event.ports[0]\n if (!port) return\n // Same-load duplicate handshake: the LATER port wins. Main closed (or is\n // about to close) its end of the old pair \u2014 detach and stop writing to it.\n if (activePort) {\n try {\n activePort.removeEventListener('message', onPortMessage)\n activePort.close()\n } catch {\n /* already dead */\n }\n }\n activePort = port\n // addEventListener (not onmessage) keeps the handler removable on\n // re-handshake; it REQUIRES start() or inbound never delivers.\n port.addEventListener('message', onPortMessage)\n port.start()\n // Flush sends issued before the port arrived, in order.\n while (pending.length > 0) {\n const envelope = pending.shift()!\n port.postMessage(envelope)\n }\n })\n\n // EXACTLY { send, onMessage } \u2014 functions only; the port stays in the\n // isolated world.\n contextBridge.exposeInMainWorld(bridgeKey, {\n send(ch: string, payload: unknown): void {\n assertValidChannel('send', ch)\n const envelope = { channel: ch, payload }\n if (activePort) {\n activePort.postMessage(envelope)\n return\n }\n // Bounded queue: drop the NEWEST send on overflow (FIFO first-comers\n // survive), warn once per load, never throw into page code.\n if (pending.length >= pendingLimit) {\n if (!warnedPendingOverflow) {\n warnedPendingOverflow = true\n console.warn(\n `[dimina-devtools] ${label} pending queue full (${pendingLimit}); ` +\n 'dropping further pre-handshake send() calls until the port arrives',\n )\n }\n return\n }\n pending.push(envelope)\n },\n onMessage(ch: string, handler: (payload: unknown) => void): () => void {\n assertValidChannel('onMessage', ch)\n const entry = { channel: ch, handler }\n handlers.push(entry)\n return () => {\n const i = handlers.indexOf(entry)\n if (i >= 0) handlers.splice(i, 1)\n }\n },\n })\n}\n", "/**\n * Preload side of the host-dialog gated narrow channel.\n *\n * \u2500\u2500 PUBLIC SURFACE EVOLUTION RULE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * `window.diminaHostDialog` is a published page-facing API, typed by the\n * exported `DiminaHostDialogPageBridge` (src/main/runtime/miniapp-runtime.ts)\n * \u2014 arbitrary host dialog pages compile against it. Members may only be\n * ADDED, never changed: any semantic change to an existing member (signature,\n * return shape, queueing/throw behavior) ships under a NEW name instead.\n * Exception: security fixes / compliance corrections may change existing\n * member semantics, and MUST be called out in the release's version notes.\n * Keep the exported bridge type in lockstep with what is exposed here.\n *\n * Receives the per-load MessagePort main transfers on `did-finish-load`\n * (`ViewChannel.HostDialogPort`, `event.ports[0]`) and bridges it to the page\n * as `window.diminaHostDialog` \u2014 EXACTLY `{ send, onMessage }`, functions\n * only. The raw MessagePort never crosses into the main world: the page only\n * ever talks through these two functions, so the `{ channel, payload }`\n * envelope stays the single waist (same posture as the main side's\n * host-dialog-port-channel.ts).\n *\n * Ordering reality this module absorbs \u2014 identical to the toolbar's port\n * bridge (see host-toolbar-port.ts for the full rationale): pre-handshake\n * sends queue and bounded-drop, handlers register before the port exists and\n * re-attach across same-load re-handshakes, inbound dispatch drops malformed\n * envelopes without throwing.\n *\n * Shared implementation: see `host-slot-port-bridge.ts` (the toolbar/sidebar/\n * dialog port bridges are otherwise identical; only the constants below\n * differ).\n */\n\nimport { ViewChannel } from '../../shared/ipc-channels-overlays.js'\nimport { createHostSlotPortBridge } from './host-slot-port-bridge.js'\n\n/**\n * Cap on pre-handshake queued sends. Same rationale and value as\n * `HOST_TOOLBAR_PENDING_LIMIT` \u2014 overflow drops the NEWEST envelope, one\n * console.warn per load.\n */\nexport const HOST_DIALOG_PENDING_LIMIT = 128\n\n/**\n * Subscribe the handshake channel and expose the page bridge. Call ONLY from\n * a passing dialog-runtime guard (`activateHostDialogRuntime`) \u2014 a failing\n * guard must leave zero footprint (no bridge key, no IPC listener).\n */\nexport function installHostDialogPortBridge(): void {\n createHostSlotPortBridge({\n bridgeKey: 'diminaHostDialog',\n channel: ViewChannel.HostDialogPort,\n pendingLimit: HOST_DIALOG_PENDING_LIMIT,\n label: 'host-dialog',\n })\n}\n", "/**\n * Session-resident host-dialog framework runtime: GUARD + ACTIVATION.\n *\n * Same registration and guard shape as host-toolbar-runtime.ts (see that\n * module for the full rationale): registered once per process on\n * `session.defaultSession`, so it runs in EVERY defaultSession renderer;\n * this guard keeps it inert everywhere except the host-dialog WCV's main\n * frame, identified by `HOST_DIALOG_RUNTIME_MARKER` in that process' argv.\n */\n\nimport { HOST_DIALOG_RUNTIME_MARKER } from '../../shared/constants.js'\nimport { installHostDialogAdvertiserWhenReady } from './host-dialog-advertiser.js'\nimport { installHostDialogPortBridge } from './host-dialog-port.js'\n\n/**\n * Pure guard predicate: should the dialog runtime activate in a renderer with\n * this `argv` / `isMainFrame`? True only for the MAIN frame of a process whose\n * argv carries the `'--dimina-host-dialog'` marker.\n */\nexport function shouldActivateHostDialogRuntime(\n argv: readonly string[],\n isMainFrame: boolean,\n): boolean {\n return isMainFrame && argv.includes(HOST_DIALOG_RUNTIME_MARKER)\n}\n\n/**\n * Run the guard; only when it passes, install the dual-axis size advertiser\n * (`installHostDialogAdvertiserWhenReady`) and the narrow-channel page\n * bridge (`installHostDialogPortBridge` \u2014 `window.diminaHostDialog` +\n * the MessagePort handshake listener). Returns whether the runtime\n * activated. A failed guard installs NOTHING (zero footprint in non-dialog\n * windows and subframes: no advertiser, no bridge key, no IPC listener).\n */\nexport function activateHostDialogRuntime(env: {\n argv: readonly string[]\n isMainFrame: boolean\n}): boolean {\n if (!shouldActivateHostDialogRuntime(env.argv, env.isMainFrame)) return false\n installHostDialogAdvertiserWhenReady()\n installHostDialogPortBridge()\n return true\n}\n", "// Session-registered dialog-runtime preload entry.\n//\n// Bundled into a single CJS file (dist/preload/windows/host-dialog-runtime.cjs)\n// via build:preload and registered ONCE per process on `session.defaultSession`\n// (`registerPreloadScript({ type: 'frame', \u2026 })` \u2014 see\n// `src/main/services/views/host-dialog-session-runtime.ts`). It therefore runs\n// in EVERY defaultSession renderer; `activateHostDialogRuntime`'s guard\n// (`process.isMainFrame && process.argv.includes('--dimina-host-dialog')`)\n// makes it a zero-footprint no-op everywhere except the host-dialog WCV's\n// main frame, where it installs the reverse dual-axis size-advertiser.\nimport { activateHostDialogRuntime } from '../runtime/host-dialog-runtime.js'\n\nactivateHostDialogRuntime({ argv: process.argv, isMainFrame: process.isMainFrame })\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/** Shared cross-process constants for dimina-devtools. */\n\n/** Default Chrome DevTools Protocol (CDP) remote debugging port. */\nexport const DEFAULT_CDP_PORT = 9222\n\n/** Default scene value for mini-app launch. */\nexport const DEFAULT_SCENE = 1001\n\n/**\n * Fixed devtools toolbar header height (px). Single source of truth shared by\n * the main process (overlay view layout) and the renderer (toolbar/popover\n * layout). Not host-configurable \u2014 the deprecated\n * `WorkbenchAppConfig.headerHeight` is ignored; hosts that need their own\n * toolbar use the host toolbar WCV instead.\n */\nexport const HEADER_H = 40\n\n/**\n * Process-level argv marker injected (via `webPreferences.additionalArguments`)\n * into the host-toolbar WebContentsView. The session-registered toolbar-runtime\n * preload (`src/preload/runtime/host-toolbar-runtime.ts`) executes in EVERY\n * defaultSession renderer; its guard activates the height advertiser only when\n * `process.argv` carries this marker AND `process.isMainFrame` is true (the\n * marker is process-level, so subframes of the toolbar window see it too \u2014\n * both guard wings are required).\n */\nexport const HOST_TOOLBAR_RUNTIME_MARKER = '--dimina-host-toolbar'\n\n/**\n * Same guard-marker contract as {@link HOST_TOOLBAR_RUNTIME_MARKER}, for the\n * host-sidebar WebContentsView (`src/preload/runtime/host-sidebar-runtime.ts`).\n */\nexport const HOST_SIDEBAR_RUNTIME_MARKER = '--dimina-host-sidebar'\n\n/**\n * Same guard-marker contract as {@link HOST_TOOLBAR_RUNTIME_MARKER}, for the\n * host-dialog WebContentsView (`src/preload/runtime/host-dialog-runtime.ts`).\n */\nexport const HOST_DIALOG_RUNTIME_MARKER = '--dimina-host-dialog'\n\n/**\n * Intrinsic width (px) of devtools' own default host-sidebar content (the\n * project-category icon rail). Single source of truth shared by the renderer\n * (`host-sidebar-default.tsx`, which gives its `[data-host-sidebar-root]` this\n * exact width so the width advertiser reports it) and anything in main that\n * needs to reason about the default rail's size. The slot is NOT left pinned\n * at this width: main pushes it once as a seed and immediately returns the\n * slot to 'auto' (see `createDevtoolsRuntime`), so the rail \u2014 and any\n * downstream `loadURL`/`loadFile` content that replaces it \u2014 advertises its\n * own width from then on, exactly like any other host-sidebar content.\n */\nexport const HOST_SIDEBAR_DEFAULT_WIDTH = 56\n", "/**\n * Reverse size-advertiser preload for the host-controllable dialog\n * WebContentsView. Runs in that WCV's OWN renderer (the dialog content's\n * preload). Unlike the toolbar/sidebar (single-axis persistent strips), the\n * dialog self-sizes on BOTH axes \u2014 it has no renderer placeholder to anchor\n * against, so main centers it in the main window purely from what this\n * advertiser reports. Two independent `createSizeAdvertiser` instances (one\n * per axis) share the same root and the same outbound channel\n * (`HostDialogAdvertiseSize` carries `{ axis, extent }` for either axis); main\n * re-centers using whichever axes it has measured so far (see\n * `host-dialog-view.ts`'s `reportMeasuredExtent` / default-size fallback).\n */\n\nimport { ipcRenderer } from 'electron'\nimport { createSizeAdvertiser } from '@dimina-kit/view-anchor'\nimport { ViewChannel } from '../../shared/ipc-channels-overlays.js'\nimport { whenSlotRootReady } from './wait-for-slot-root.js'\n\n/**\n * Attach both axis advertisers to the dialog content's shrink-to-fit root\n * (`[data-host-dialog-root]`), waiting for it if necessary \u2014 the root may be\n * mounted asynchronously by a framework rather than present in the initial\n * HTML. That element MUST be shrink-to-fit on BOTH axes \u2014 same footgun as\n * the toolbar/sidebar (`createSizeAdvertiser`'s single-axis-ownership\n * requirement), just doubled.\n */\nexport function installHostDialogAdvertiserWhenReady(): void {\n whenSlotRootReady(\n '[data-host-dialog-root]',\n '[host-dialog-advertiser] no `[data-host-dialog-root]` element found \u2014 ' +\n 'not advertising a size yet. The dialog content must wrap itself in a ' +\n 'shrink-to-fit `[data-host-dialog-root]` element so its size is the ' +\n 'content size, not the host-given view size.',\n (root) => {\n const publish = (size: { axis: 'block' | 'inline'; extent: number }): void => {\n ipcRenderer.send(ViewChannel.HostDialogAdvertiseSize, size)\n }\n\n createSizeAdvertiser(root, { axis: 'block', publish })\n createSizeAdvertiser(root, { axis: 'inline', publish })\n },\n )\n}\n", "/**\n * Internal \u2014 the RAF-coalesced measure/dedupe/dispose engine behind the REVERSE\n * primitive `createSizeAdvertiser`.\n *\n * The forward `createViewAnchor` deliberately does NOT use this: it publishes\n * SYNCHRONOUSLY (a native overlay's `setBounds` already lands a cross-process\n * frame late, and a RAF stacked a second frame of visible trailing). The\n * reverse direction is different \u2014 it is a cross-process FEEDBACK loop\n * (advertise \u2192 host resizes the view \u2192 content re-measures \u2192 re-advertise), so\n * the RAF's one-publish-per-frame coalescing is a useful damper. The two\n * directions thus have different optimal emit timing; this engine serves only\n * the reverse.\n *\n * NOT exported from the package: it is pure mechanism with no knowledge of\n * direction, the DOM, `ResizeObserver`, or the structure of the value `T` it\n * carries. The wrapping primitive injects `produce` / `same` / `sink` and\n * drives the lifecycle.\n *\n * - `schedule()` \u2014 coalesce a burst of triggers into ONE RAF; the frame\n * body re-`produce()`s, dedupes against the last emit (`same`), and `sink`s.\n * Bails if inactive or disposed (stale-RAF safe).\n * - `emitNow(v)` \u2014 explicit synchronous emit (create / update path). Always\n * fires, bypassing the dedupe check, and refreshes the dedupe baseline.\n * - `setActive` \u2014 gate the observer stream; a queued frame bails on `!active`.\n * - `cancel` \u2014 drop any in-flight RAF.\n * - `dispose` \u2014 cancel + go inert; after dispose nothing emits again.\n */\nexport interface MeasureLoop<T> {\n schedule(): void\n emitNow(value: T): void\n setActive(on: boolean): void\n cancel(): void\n dispose(): void\n}\n\nexport function createMeasureLoop<T>(cfg: {\n /** Produce the value to emit in the RAF body. Return `null` to decline the\n * frame entirely (no dedupe, no sink, baseline untouched) \u2014 e.g. a\n * non-finite or unavailable measurement. */\n produce: () => T | null\n same: (a: T, b: T) => boolean\n sink: (value: T) => void\n}): MeasureLoop<T> {\n const { produce, same, sink } = cfg\n let rafId: number | null = null\n let active = false\n let disposed = false\n let last: T | null = null\n\n const cancel = (): void => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n rafId = null\n }\n }\n\n return {\n schedule(): void {\n if (disposed || !active || rafId !== null) return\n rafId = requestAnimationFrame(() => {\n rafId = null\n if (disposed || !active) return\n const value = produce()\n if (value === null) return // producer declined this frame\n // last-value dedupe: a frame whose produced value equals the last one\n // we emitted costs nothing (no IPC / setBounds).\n if (last !== null && same(value, last)) return\n last = value\n sink(value)\n })\n },\n emitNow(value: T): void {\n if (disposed) return\n last = value\n sink(value)\n },\n setActive(on: boolean): void {\n active = on\n },\n cancel,\n dispose(): void {\n if (disposed) return\n disposed = true\n cancel()\n },\n }\n}\n", "import type {\n AdvertisedSize,\n SizeAdvertiserOptions,\n SizeAdvertiserHandle,\n} from './types.js'\nimport { createMeasureLoop } from './measure-loop.js'\n\n/**\n * Reverse of `createViewAnchor`: runs in a downstream WebContentsView's own\n * renderer, measures the content's own size on ONE owned axis (from the\n * `ResizeObserver` border-box \u2014 no `getBoundingClientRect`, no forced reflow),\n * and advertises it via the injected `publish`. Shares the forward primitive's\n * measure/coalesce/dedupe/dispose engine (`createMeasureLoop`).\n *\n * The extent is `Math.round`ed and clamped to `>= 0`; non-finite measurements\n * drop the frame.\n *\n * FOOTGUN \u2014 `target` must be shrink-to-fit on the owned axis: its owned-axis\n * size must NOT be driven by the host-applied view size, or the cross-process\n * loop (advertise \u2192 host resizes view \u2192 remeasure) never converges (it\n * oscillates or stays \"stable but wrong\"). Measuring `<body>`/`<html>` is the\n * classic mistake \u2014 their size *is* the view size. See\n * `docs/bidirectional-design.md`'s single-axis-ownership and trust-boundary\n * sections.\n */\nexport function createSizeAdvertiser(\n target: HTMLElement,\n opts: SizeAdvertiserOptions,\n): SizeAdvertiserHandle {\n const axis = opts.axis // immutable for the advertiser's life\n let publish = opts.publish\n let observer: ResizeObserver | null = null\n let disposed = false\n // Latest border-box, stashed by the RO callback and read by `produce` in the\n // RAF body (keep the entry out of the shared, DOM-agnostic loop).\n let latest: ResizeObserverSize | null = null\n\n const produce = (): AdvertisedSize | null => {\n if (!latest) return null\n const raw = axis === 'block' ? latest.blockSize : latest.inlineSize\n if (!Number.isFinite(raw)) return null\n return { axis, extent: Math.max(0, Math.round(raw)) }\n }\n\n const loop = createMeasureLoop<AdvertisedSize>({\n produce,\n same: (a, b) => a.extent === b.extent, // axis is constant\n sink: (size) => publish(size),\n })\n\n const onResize: ResizeObserverCallback = (entries) => {\n const entry = entries[entries.length - 1]\n if (entry) {\n latest = entry.borderBoxSize?.[0] ?? entry.contentBoxSize?.[0] ?? latest\n }\n loop.schedule()\n }\n\n // One cheap, once-per-advertiser guard for the textbook feedback-loop footgun.\n const doc = target.ownerDocument\n if (target === doc.body || target === doc.documentElement) {\n console.warn(\n `[view-anchor] size-advertiser: <${target === doc.body ? 'body' : 'html'}>'s ` +\n `${axis} size is the host-given view size, not the content size \u2014 the ` +\n `advertiser will never shrink to content. Measure a shrink-to-fit wrapper. ` +\n `See bidirectional-design.md's single-axis-ownership section.`,\n )\n }\n\n loop.setActive(true)\n observer = new ResizeObserver(onResize)\n observer.observe(target)\n\n return {\n update(nextPublish: (size: AdvertisedSize) => void): void {\n if (disposed) return\n publish = nextPublish\n // Re-advertise the current size to the new sink immediately (mirrors the\n // forward anchor's re-publish on update) so the new channel is not left\n // sizeless until the next ResizeObserver tick.\n const cur = produce()\n if (cur) loop.emitNow(cur)\n },\n dispose(): void {\n if (disposed) return\n disposed = true\n loop.cancel()\n if (observer) {\n observer.disconnect()\n observer = null\n }\n loop.dispose()\n },\n }\n}\n", "/**\n * IPC channel name constants for dimina-devtools' overlay/panel\n * WebContentsViews \u2014 layout slots (host-toolbar/host-sidebar/host-dialog),\n * the popover, tooltip, project-create dialog and settings overlays, plus\n * the update flow. Split out of `ipc-channels.ts` (see that file's header)\n * once this group alone pushed it past the repo's file-length threshold \u2014\n * these constants share no runtime dependency on the rest of that file, so\n * the split is a pure line-count relief valve, not a behavior change.\n */\n\n// \u2500\u2500 Embedded views (renderer \u2192 main) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The main window's React layout owns the *positions* of the editor +\n// simulator-DevTools WebContentsView overlays \u2014 each visible placeholder\n// `<div>` measures its client rect via ResizeObserver and pushes the\n// rectangle to the main process. The view manager caches the latest\n// payload per kind and applies it to the overlay; no payload means the\n// overlay is hidden.\n//\n// Payload (after schema validation): `{ x, y, width, height }` in CSS\n// pixels relative to the window's content area (origin = top-left,\n// not including the OS chrome).\nexport const ViewChannel = {\n /**\n * Reverse size-advertiser: the host-toolbar WCV's OWN renderer advertises its\n * intrinsic content height so main reserves exactly that much. Payload\n * `{ axis: 'block', extent }`. fire-and-forget (send), NOT invoke.\n */\n HostToolbarAdvertiseHeight: 'view:host-toolbar:advertise-height',\n /**\n * main \u2192 host-toolbar WCV renderer: per-load MessagePort handshake for the\n * gated narrow channel. On every toolbar `did-finish-load` main creates a\n * `MessageChannelMain` and transfers port2 here\n * (`wc.postMessage(HostToolbarPort, null, [port2])`); the session-resident\n * toolbar runtime preload receives it via `event.ports[0]` and bridges it to\n * the page as `window.diminaHostToolbar`. Envelope both directions:\n * `{ channel: string, payload: unknown }`.\n */\n HostToolbarPort: 'view:host-toolbar:port',\n /**\n * main \u2192 main-window renderer: push the reserved host-toolbar height so the\n * renderer placeholder div resizes (closing the dynamic-height loop).\n */\n HostToolbarHeightChanged: 'view:host-toolbar:height-changed',\n /**\n * main \u2190 main-window renderer (invoke): pull the last NOTIFIED toolbar\n * height retained in main. Mount-time replay companion to\n * `HostToolbarHeightChanged`: the push listener mounts with the project\n * view and the toolbar's size-advertiser deduplicates (never re-reports),\n * so a height pushed while no project view was mounted would otherwise be\n * lost forever (cold start on the project list races it; close-project \u2192\n * reopen hits it deterministically). No payload; resolves a number.\n */\n HostToolbarGetHeight: 'view:host-toolbar:get-height',\n /**\n * Reverse size-advertiser for the host-sidebar WCV, mirroring\n * `HostToolbarAdvertiseHeight` on the inline (width) axis instead of block.\n * Payload `{ axis: 'inline', extent }`. fire-and-forget (send), NOT invoke.\n */\n HostSidebarAdvertiseWidth: 'view:host-sidebar:advertise-width',\n /**\n * main \u2192 host-sidebar WCV renderer: per-load MessagePort handshake, same\n * contract as `HostToolbarPort` (see that entry).\n */\n HostSidebarPort: 'view:host-sidebar:port',\n /**\n * main \u2192 main-window renderer: push the reserved host-sidebar width so the\n * renderer placeholder div resizes, mirroring `HostToolbarHeightChanged`.\n */\n HostSidebarWidthChanged: 'view:host-sidebar:width-changed',\n /**\n * main \u2190 main-window renderer (invoke): pull the last NOTIFIED sidebar\n * width, mirroring `HostToolbarGetHeight`'s mount-time replay role.\n */\n HostSidebarGetWidth: 'view:host-sidebar:get-width',\n /**\n * main \u2192 main-window renderer: push the project category (`Project.type`)\n * selected in the host-sidebar's content \u2014 devtools' own default icon rail,\n * or any downstream replacement that sends on the same channel. No\n * pull/replay companion like `HostSidebarGetWidth`: the default category is\n * a stable initial value regardless of load-order, and nothing is ever sent\n * before the main-window renderer (and thus `ProjectListScreen`) is already\n * mounted.\n */\n HostSidebarCategorySelected: 'view:host-sidebar:category-selected',\n /**\n * Reverse size-advertiser for the host-dialog WCV. Unlike the toolbar/sidebar\n * (single-axis, `setBaseDesired`-placed strips), the dialog is a BOTH-AXES\n * overlay positioned by `setOverlayDesired` \u2014 main centers it in the main\n * window once it knows both dimensions. One channel carries either axis'\n * report (`{ axis: 'block' | 'inline', extent }`); the dialog's own content\n * advertises both from the same root (see `host-dialog-advertiser.ts`).\n * fire-and-forget (send), NOT invoke.\n *\n * No `HostDialogSizeChanged` / `HostDialogGetSize` counterparts: those exist\n * for toolbar/sidebar so a renderer-owned PLACEHOLDER can replay a size it\n * missed. The dialog has no such placeholder \u2014 it is a main-driven overlay\n * shown/hidden on demand (`hostDialog.show()`/`hide()`), so there is nothing\n * in the renderer to replay a size into.\n */\n HostDialogAdvertiseSize: 'view:host-dialog:advertise-size',\n /**\n * main \u2192 host-dialog WCV renderer: per-load MessagePort handshake, same\n * contract as `HostToolbarPort` (see that entry).\n */\n HostDialogPort: 'view:host-dialog:port',\n /**\n * Renderer \u2192 main: the window-level placement snapshot (one monotonic epoch\n * per commit tick, one generation per renderer lifetime) that drives the view\n * reconciler. The single source of truth for every managed native view's\n * bounds/visibility/z-order \u2014 supersedes the per-view bounds channels above.\n * invoke.\n */\n PlacementSnapshot: 'view:placement-snapshot',\n /**\n * main \u2190 main-window renderer (invoke): allocate a fresh placement\n * generation seed for this renderer bootstrap. See\n * renderer-placement-generation.ts for why the seed comes from main\n * (a wall-clock `Date.now()` seed is not guaranteed to exceed main's\n * still-standing high-water mark across two reloads that happen faster\n * than the clock's resolution). No payload; resolves a number.\n */\n AllocatePlacementGeneration: 'view:allocate-placement-generation',\n} as const\n\nexport interface ViewBounds {\n x: number\n y: number\n width: number\n height: number\n}\n\n// \u2500\u2500 Popover \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const PopoverChannel = {\n Show: 'popover:show',\n Hide: 'popover:hide',\n // Popover \u2192 main \u2192 main-renderer: the edited compile modes, plus whether\n // the change affects what is currently running (selecting a mode, or\n // editing the selected one) and so needs a relaunch.\n Apply: 'popover:apply',\n Closed: 'popover:closed',\n Init: 'popover:init',\n} as const\n\n// \u2500\u2500 Tooltip \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// A top-tier overlay WebContentsView (VIEW_LAYER.tooltip \u2014 see view-ids.ts),\n// NOT a DOM tooltip in the main renderer: any DOM-portaled floating UI (Radix\n// Tooltip) or the browser-native `title` attribute lives in the main\n// renderer's own paint surface, which every other WCV (simulator, editor,\n// settings, popover) renders on top of \u2014 CSS cannot reach across that\n// boundary. A trigger reports its anchor rect + label; main computes the\n// tooltip's screen bounds and shows/repositions/hides this overlay.\n\nexport const OverlayChannel = {\n Ready: 'overlay:ready',\n} as const\n\nexport const TooltipChannel = {\n Prepare: 'tooltip:prepare',\n Show: 'tooltip:show',\n Hide: 'tooltip:hide',\n Init: 'tooltip:init',\n Measured: 'tooltip:measured',\n} as const\n\n// \u2500\u2500 Project-create dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// A top-tier overlay WebContentsView (VIEW_LAYER.dialog), NOT the Radix\n// `fixed inset-0` DOM portal it replaced \u2014 a DOM overlay paints inside the\n// main window's own renderer, so any native WebContentsView mounted on top\n// (simulator, host-toolbar, host-sidebar) occludes it. main.tsx fetches the\n// template catalog + base-dir defaults, then asks main to show this panel;\n// the panel relays submit/cancel back to main.tsx to run the existing\n// scaffold flow.\n\nexport const ProjectCreateChannel = {\n Show: 'projectCreate:show',\n Init: 'projectCreate:init',\n Submit: 'projectCreate:submit',\n Cancel: 'projectCreate:cancel',\n Submitted: 'projectCreate:submitted',\n} as const\n\n// \u2500\u2500 Device picker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// A top-tier overlay WebContentsView (VIEW_LAYER.dialog), for the same reason\n// as the project-create dialog above: the simulator's own WebContentsView is\n// mounted on top of the main renderer and overlaps the centred search panel,\n// so a DOM-portaled dialog is cut in half by it. The toolbar keeps only the\n// trigger button; it asks main to show this panel with the currently selected\n// device, and main relays the picked device name back to the toolbar.\n\nexport const DevicePickerChannel = {\n Show: 'devicePicker:show',\n Init: 'devicePicker:init',\n Select: 'devicePicker:select',\n Cancel: 'devicePicker:cancel',\n Selected: 'devicePicker:selected',\n} as const\n\n// \u2500\u2500 Embedded settings overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const SettingsChannel = {\n SetVisible: 'settings:setVisible',\n ProjectSettingsChanged: 'settings:projectSettingsChanged',\n Init: 'settings:init',\n} as const\n\n// \u2500\u2500 Updates (UpdateManager) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// String values are FROZEN: shipped builds key off them. Add new entries\n// here, never rename existing ones.\nexport const UpdateChannel = {\n Check: 'updates:check',\n Download: 'updates:download',\n Install: 'updates:install',\n DownloadProgress: 'updates:downloadProgress',\n Available: 'updates:available',\n Close: 'updates:close',\n} as const\n", "/**\n * Shared readiness wait for a host-slot content's shrink-to-fit measurement\n * root (`[data-host-*-root]`). A one-shot `document.querySelector` at\n * `DOMContentLoaded` time only works when the root is present in the initial\n * HTML. Framework-rendered content (e.g. a React app) can mount its root\n * asynchronously, after `DOMContentLoaded` has already fired \u2014 a one-shot\n * check misses it permanently and the slot's width/height is never\n * advertised. This keeps watching via `MutationObserver` instead of assuming\n * a synchronous mount, without polling on a fixed delay.\n *\n * The \"root is missing\" warning exists for downstream authors who forgot the\n * element entirely, so it must not fire on the healthy async-mount path \u2014 a\n * warning printed on every normal load is noise that trains its readers to\n * ignore it. Two conditions gate it, both signals rather than guessed delays:\n * the document must be one the host actually loaded content into (not the\n * view's own blank document), and it must have finished loading AND run out of\n * pending work (`window.load`, then an idle callback \u2014 a framework's first\n * commit is normal-priority work, so it always lands before idle). The\n * observer stays armed either way, so a root that mounts even later is still\n * picked up.\n */\nexport function whenSlotRootReady(\n selector: string,\n missingWarning: string,\n install: (root: HTMLElement) => void,\n): void {\n function attempt(): void {\n // The slot's WebContentsView holds its own empty document until the host\n // loads content into it, and this preload runs there too. That document\n // has no author: a missing root in it is not a mistake anyone made, and\n // warning about it fires on every app start. The observer below still gets\n // armed, so content that does arrive is picked up.\n const authored = location.href !== 'about:blank' && location.href !== ''\n\n const root = document.querySelector<HTMLElement>(selector)\n if (root) {\n install(root)\n return\n }\n\n let installed = false\n const observer = new MutationObserver(() => {\n const lateRoot = document.querySelector<HTMLElement>(selector)\n if (!lateRoot) return\n observer.disconnect()\n installed = true\n install(lateRoot)\n })\n observer.observe(document.documentElement, { childList: true, subtree: true })\n\n // Re-queries rather than trusting `installed`: the observer delivers on a\n // microtask, so a root that is already in the DOM may not have been\n // installed yet \u2014 it is present either way, which is what the warning is\n // about.\n const warnIfStillMissing = (): void => {\n if (installed || !authored || document.querySelector(selector)) return\n console.warn(missingWarning)\n }\n\n // `load` alone is too early a verdict: a concurrent React root commits its\n // first render on a scheduler task that can land after it, and the warning\n // would then race the healthy mount it is supposed to ignore. Idle\n // callbacks run only once the main thread has no pending work of that\n // kind, so a root still absent then is genuinely absent. The timeout is\n // the cap for a page that never goes idle, not the mechanism.\n const decide = (): void => {\n const idle = (globalThis as { requestIdleCallback?: (cb: () => void, opts?: { timeout: number }) => number })\n .requestIdleCallback\n if (typeof idle === 'function') idle(warnIfStillMissing, { timeout: 5_000 })\n else warnIfStillMissing()\n }\n if (document.readyState === 'complete') decide()\n else window.addEventListener('load', decide, { once: true })\n }\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', attempt, { once: true })\n } else {\n attempt()\n }\n}\n", "/**\n * Shared implementation behind every host-slot page bridge (toolbar/sidebar/\n * dialog): the MessagePort handshake, pending-queue-with-bounded-overflow,\n * handler registry and `{ send, onMessage }` contextBridge exposure are\n * IDENTICAL across slots \u2014 only the bridge key, handshake channel, queue cap\n * and overflow-warning label differ. Each slot's own `host-*-port.ts` stays\n * the frozen public surface (see its own \"PUBLIC SURFACE EVOLUTION RULE\"\n * doc-comment) and calls this factory with its own constants; this module has\n * no public-surface contract of its own.\n */\nimport { contextBridge, ipcRenderer } from 'electron'\n\nexport interface HostSlotPortBridgeOptions {\n /** contextBridge key the page-facing API is exposed under, e.g. 'diminaHostToolbar'. */\n bridgeKey: string\n /** main \u2192 renderer per-load handshake channel, e.g. ViewChannel.HostToolbarPort. */\n channel: string\n /** Cap on pre-handshake queued sends; overflow drops the NEWEST envelope. */\n pendingLimit: number\n /** Slot label used in the overflow console.warn, e.g. 'host-toolbar'. */\n label: string\n}\n\n/**\n * Subscribe the handshake channel and expose the page bridge. Call ONLY from\n * a passing per-slot runtime guard \u2014 a failing guard must leave zero\n * footprint (no bridge key, no IPC listener), so this factory itself does no\n * guard checking; the caller decides whether to call it at all.\n */\nexport function createHostSlotPortBridge(opts: HostSlotPortBridgeOptions): void {\n const { bridgeKey, channel, pendingLimit, label } = opts\n let activePort: MessagePort | null = null\n const pending: Array<{ channel: string; payload: unknown }> = []\n // One overflow warning per load (this installer runs once per document) \u2014\n // a runaway page send-loop must not get per-drop console spam.\n let warnedPendingOverflow = false\n const handlers: Array<{ channel: string; handler: (payload: unknown) => void }> = []\n\n // Entry-waist channel validation, parity with the main side's `onMessage`\n // guard (same TypeError, message names `channel`). Runs BEFORE any state is\n // touched (no queue slot, no registry entry), in both port states \u2014 a page\n // author's typo throws at the call site instead of vanishing into main's\n // silent inbound drop.\n function assertValidChannel(method: string, ch: unknown): asserts ch is string {\n if (typeof ch !== 'string' || ch === '') {\n throw new TypeError(`${bridgeKey}.${method}: channel must be a non-empty string`)\n }\n }\n\n const dispatch = (data: unknown): void => {\n // Defensive symmetry with main: drop anything that is not an object\n // envelope with a string channel \u2014 never throw in the dispatcher.\n if (typeof data !== 'object' || data === null) return\n const { channel: ch, payload } = data as { channel?: unknown; payload?: unknown }\n if (typeof ch !== 'string') return\n for (const entry of [...handlers]) {\n if (entry.channel === ch) entry.handler(payload)\n }\n }\n\n const onPortMessage = (event: MessageEvent): void => {\n dispatch(event.data)\n }\n\n ipcRenderer.on(channel, (event) => {\n const port = event.ports[0]\n if (!port) return\n // Same-load duplicate handshake: the LATER port wins. Main closed (or is\n // about to close) its end of the old pair \u2014 detach and stop writing to it.\n if (activePort) {\n try {\n activePort.removeEventListener('message', onPortMessage)\n activePort.close()\n } catch {\n /* already dead */\n }\n }\n activePort = port\n // addEventListener (not onmessage) keeps the handler removable on\n // re-handshake; it REQUIRES start() or inbound never delivers.\n port.addEventListener('message', onPortMessage)\n port.start()\n // Flush sends issued before the port arrived, in order.\n while (pending.length > 0) {\n const envelope = pending.shift()!\n port.postMessage(envelope)\n }\n })\n\n // EXACTLY { send, onMessage } \u2014 functions only; the port stays in the\n // isolated world.\n contextBridge.exposeInMainWorld(bridgeKey, {\n send(ch: string, payload: unknown): void {\n assertValidChannel('send', ch)\n const envelope = { channel: ch, payload }\n if (activePort) {\n activePort.postMessage(envelope)\n return\n }\n // Bounded queue: drop the NEWEST send on overflow (FIFO first-comers\n // survive), warn once per load, never throw into page code.\n if (pending.length >= pendingLimit) {\n if (!warnedPendingOverflow) {\n warnedPendingOverflow = true\n console.warn(\n `[dimina-devtools] ${label} pending queue full (${pendingLimit}); ` +\n 'dropping further pre-handshake send() calls until the port arrives',\n )\n }\n return\n }\n pending.push(envelope)\n },\n onMessage(ch: string, handler: (payload: unknown) => void): () => void {\n assertValidChannel('onMessage', ch)\n const entry = { channel: ch, handler }\n handlers.push(entry)\n return () => {\n const i = handlers.indexOf(entry)\n if (i >= 0) handlers.splice(i, 1)\n }\n },\n })\n}\n", "/**\n * Preload side of the host-dialog gated narrow channel.\n *\n * \u2500\u2500 PUBLIC SURFACE EVOLUTION RULE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * `window.diminaHostDialog` is a published page-facing API, typed by the\n * exported `DiminaHostDialogPageBridge` (src/main/runtime/miniapp-runtime.ts)\n * \u2014 arbitrary host dialog pages compile against it. Members may only be\n * ADDED, never changed: any semantic change to an existing member (signature,\n * return shape, queueing/throw behavior) ships under a NEW name instead.\n * Exception: security fixes / compliance corrections may change existing\n * member semantics, and MUST be called out in the release's version notes.\n * Keep the exported bridge type in lockstep with what is exposed here.\n *\n * Receives the per-load MessagePort main transfers on `did-finish-load`\n * (`ViewChannel.HostDialogPort`, `event.ports[0]`) and bridges it to the page\n * as `window.diminaHostDialog` \u2014 EXACTLY `{ send, onMessage }`, functions\n * only. The raw MessagePort never crosses into the main world: the page only\n * ever talks through these two functions, so the `{ channel, payload }`\n * envelope stays the single waist (same posture as the main side's\n * host-dialog-port-channel.ts).\n *\n * Ordering reality this module absorbs \u2014 identical to the toolbar's port\n * bridge (see host-toolbar-port.ts for the full rationale): pre-handshake\n * sends queue and bounded-drop, handlers register before the port exists and\n * re-attach across same-load re-handshakes, inbound dispatch drops malformed\n * envelopes without throwing.\n *\n * Shared implementation: see `host-slot-port-bridge.ts` (the toolbar/sidebar/\n * dialog port bridges are otherwise identical; only the constants below\n * differ).\n */\n\nimport { ViewChannel } from '../../shared/ipc-channels-overlays.js'\nimport { createHostSlotPortBridge } from './host-slot-port-bridge.js'\n\n/**\n * Cap on pre-handshake queued sends. Same rationale and value as\n * `HOST_TOOLBAR_PENDING_LIMIT` \u2014 overflow drops the NEWEST envelope, one\n * console.warn per load.\n */\nexport const HOST_DIALOG_PENDING_LIMIT = 128\n\n/**\n * Subscribe the handshake channel and expose the page bridge. Call ONLY from\n * a passing dialog-runtime guard (`activateHostDialogRuntime`) \u2014 a failing\n * guard must leave zero footprint (no bridge key, no IPC listener).\n */\nexport function installHostDialogPortBridge(): void {\n createHostSlotPortBridge({\n bridgeKey: 'diminaHostDialog',\n channel: ViewChannel.HostDialogPort,\n pendingLimit: HOST_DIALOG_PENDING_LIMIT,\n label: 'host-dialog',\n })\n}\n", "/**\n * Session-resident host-dialog framework runtime: GUARD + ACTIVATION.\n *\n * Same registration and guard shape as host-toolbar-runtime.ts (see that\n * module for the full rationale): registered once per process on\n * `session.defaultSession`, so it runs in EVERY defaultSession renderer;\n * this guard keeps it inert everywhere except the host-dialog WCV's main\n * frame, identified by `HOST_DIALOG_RUNTIME_MARKER` in that process' argv.\n */\n\nimport { HOST_DIALOG_RUNTIME_MARKER } from '../../shared/constants.js'\nimport { installHostDialogAdvertiserWhenReady } from './host-dialog-advertiser.js'\nimport { installHostDialogPortBridge } from './host-dialog-port.js'\n\n/**\n * Pure guard predicate: should the dialog runtime activate in a renderer with\n * this `argv` / `isMainFrame`? True only for the MAIN frame of a process whose\n * argv carries the `'--dimina-host-dialog'` marker.\n */\nexport function shouldActivateHostDialogRuntime(\n argv: readonly string[],\n isMainFrame: boolean,\n): boolean {\n return isMainFrame && argv.includes(HOST_DIALOG_RUNTIME_MARKER)\n}\n\n/**\n * Run the guard; only when it passes, install the dual-axis size advertiser\n * (`installHostDialogAdvertiserWhenReady`) and the narrow-channel page\n * bridge (`installHostDialogPortBridge` \u2014 `window.diminaHostDialog` +\n * the MessagePort handshake listener). Returns whether the runtime\n * activated. A failed guard installs NOTHING (zero footprint in non-dialog\n * windows and subframes: no advertiser, no bridge key, no IPC listener).\n */\nexport function activateHostDialogRuntime(env: {\n argv: readonly string[]\n isMainFrame: boolean\n}): boolean {\n if (!shouldActivateHostDialogRuntime(env.argv, env.isMainFrame)) return false\n installHostDialogAdvertiserWhenReady()\n installHostDialogPortBridge()\n return true\n}\n", "// Session-registered dialog-runtime preload entry.\n//\n// Bundled into a single CJS file (dist/preload/windows/host-dialog-runtime.cjs)\n// via build:preload and registered ONCE per process on `session.defaultSession`\n// (`registerPreloadScript({ type: 'frame', \u2026 })` \u2014 see\n// `src/main/services/views/host-dialog-session-runtime.ts`). It therefore runs\n// in EVERY defaultSession renderer; `activateHostDialogRuntime`'s guard\n// (`process.isMainFrame && process.argv.includes('--dimina-host-dialog')`)\n// makes it a zero-footprint no-op everywhere except the host-dialog WCV's\n// main frame, where it installs the reverse dual-axis size-advertiser.\nimport { activateHostDialogRuntime } from '../runtime/host-dialog-runtime.js'\n\nactivateHostDialogRuntime({ argv: process.argv, isMainFrame: process.isMainFrame })\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_electron"]
7
7
  }
@@ -211,6 +211,7 @@ var ViewChannel = {
211
211
  // src/preload/runtime/wait-for-slot-root.ts
212
212
  function whenSlotRootReady(selector, missingWarning, install) {
213
213
  function attempt() {
214
+ const authored = location.href !== "about:blank" && location.href !== "";
214
215
  const root = document.querySelector(selector);
215
216
  if (root) {
216
217
  install(root);
@@ -226,10 +227,16 @@ function whenSlotRootReady(selector, missingWarning, install) {
226
227
  });
227
228
  observer.observe(document.documentElement, { childList: true, subtree: true });
228
229
  const warnIfStillMissing = () => {
229
- if (!installed) console.warn(missingWarning);
230
+ if (installed || !authored || document.querySelector(selector)) return;
231
+ console.warn(missingWarning);
230
232
  };
231
- if (document.readyState === "complete") warnIfStillMissing();
232
- else window.addEventListener("load", warnIfStillMissing, { once: true });
233
+ const decide = () => {
234
+ const idle = globalThis.requestIdleCallback;
235
+ if (typeof idle === "function") idle(warnIfStillMissing, { timeout: 5e3 });
236
+ else warnIfStillMissing();
237
+ };
238
+ if (document.readyState === "complete") decide();
239
+ else window.addEventListener("load", decide, { once: true });
233
240
  }
234
241
  if (document.readyState === "loading") {
235
242
  document.addEventListener("DOMContentLoaded", attempt, { once: true });