@dimina-kit/devtools 0.3.2-dev.20260525152421 → 0.3.2-dev.20260610082053

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 (295) hide show
  1. package/README.md +43 -40
  2. package/dist/main/api.d.ts +0 -1
  3. package/dist/main/api.js +5 -1
  4. package/dist/main/app/app.d.ts +15 -5
  5. package/dist/main/app/app.js +247 -110
  6. package/dist/main/app/bootstrap.d.ts +16 -0
  7. package/dist/main/app/bootstrap.js +20 -0
  8. package/dist/main/app/launch.d.ts +8 -4
  9. package/dist/main/app/launch.js +9 -4
  10. package/dist/main/index.bundle.js +6607 -2102
  11. package/dist/main/index.js +9 -1
  12. package/dist/main/ipc/app.d.ts +1 -1
  13. package/dist/main/ipc/bridge-router.d.ts +61 -0
  14. package/dist/main/ipc/bridge-router.js +1300 -0
  15. package/dist/main/ipc/panels.d.ts +1 -1
  16. package/dist/main/ipc/panels.js +6 -2
  17. package/dist/main/ipc/popover.d.ts +1 -1
  18. package/dist/main/ipc/project-fs.d.ts +57 -0
  19. package/dist/main/ipc/project-fs.js +448 -0
  20. package/dist/main/ipc/projects.d.ts +1 -1
  21. package/dist/main/ipc/session.d.ts +1 -1
  22. package/dist/main/ipc/settings.d.ts +1 -1
  23. package/dist/main/ipc/simulator-module.d.ts +6 -0
  24. package/dist/main/ipc/simulator-module.js +11 -1
  25. package/dist/main/ipc/simulator.d.ts +2 -2
  26. package/dist/main/ipc/simulator.js +49 -5
  27. package/dist/main/ipc/toolbar.d.ts +1 -1
  28. package/dist/main/ipc/views.d.ts +19 -0
  29. package/dist/main/ipc/views.js +65 -0
  30. package/dist/main/runtime/devtools-backend.d.ts +17 -0
  31. package/dist/main/runtime/devtools-backend.js +49 -0
  32. package/dist/main/runtime/miniapp-runtime.d.ts +39 -0
  33. package/dist/main/runtime/miniapp-runtime.js +17 -0
  34. package/dist/main/services/automation/exec.d.ts +27 -2
  35. package/dist/main/services/automation/exec.js +37 -3
  36. package/dist/main/services/automation/handlers/app.js +127 -11
  37. package/dist/main/services/automation/handlers/page.js +36 -19
  38. package/dist/main/services/automation/index.js +40 -13
  39. package/dist/main/services/automation/wait-active-page.d.ts +56 -0
  40. package/dist/main/services/automation/wait-active-page.js +71 -0
  41. package/dist/main/services/console-forward/index.d.ts +36 -0
  42. package/dist/main/services/console-forward/index.js +81 -0
  43. package/dist/main/services/dimina-resource-server.d.ts +7 -0
  44. package/dist/main/services/dimina-resource-server.js +99 -0
  45. package/dist/main/services/elements-forward/index.d.ts +66 -0
  46. package/dist/main/services/elements-forward/index.js +583 -0
  47. package/dist/main/services/layout/index.d.ts +23 -1
  48. package/dist/main/services/layout/index.js +28 -3
  49. package/dist/main/services/mcp/index.d.ts +1 -0
  50. package/dist/main/services/mcp/index.js +3 -0
  51. package/dist/main/services/mcp/server.d.ts +1 -1
  52. package/dist/main/services/mcp/server.js +1 -1
  53. package/dist/main/services/mcp/target-manager.d.ts +35 -0
  54. package/dist/main/services/mcp/target-manager.js +63 -1
  55. package/dist/main/services/mcp/tools/context-tools.js +15 -1
  56. package/dist/main/services/module.d.ts +1 -1
  57. package/dist/main/services/network-forward/index.d.ts +190 -0
  58. package/dist/main/services/network-forward/index.js +765 -0
  59. package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
  60. package/dist/main/services/notifications/renderer-notifier.js +7 -1
  61. package/dist/main/services/render-inspect/index.d.ts +41 -0
  62. package/dist/main/services/render-inspect/index.js +88 -0
  63. package/dist/main/services/safe-area/index.d.ts +17 -0
  64. package/dist/main/services/safe-area/index.js +59 -0
  65. package/dist/main/services/service-host-pool/pool.d.ts +197 -0
  66. package/dist/main/services/service-host-pool/pool.js +364 -0
  67. package/dist/main/services/simulator/custom-apis.d.ts +34 -0
  68. package/dist/main/services/simulator/custom-apis.js +22 -0
  69. package/dist/main/services/simulator-appdata/index.d.ts +35 -0
  70. package/dist/main/services/simulator-appdata/index.js +71 -0
  71. package/dist/main/services/simulator-current-page/index.d.ts +24 -0
  72. package/dist/main/services/simulator-current-page/index.js +19 -0
  73. package/dist/main/services/simulator-storage/index.d.ts +37 -2
  74. package/dist/main/services/simulator-storage/index.js +209 -32
  75. package/dist/main/services/simulator-storage/service-storage-ops.d.ts +40 -0
  76. package/dist/main/services/simulator-storage/service-storage-ops.js +67 -0
  77. package/dist/main/services/simulator-temp-files/fs-channels.js +1 -1
  78. package/dist/main/services/simulator-temp-files/index.d.ts +1 -1
  79. package/dist/main/services/simulator-temp-files/index.js +1 -1
  80. package/dist/main/services/simulator-temp-files/request-handler.js +1 -1
  81. package/dist/main/services/simulator-wxml/index.d.ts +29 -0
  82. package/dist/main/services/simulator-wxml/index.js +28 -0
  83. package/dist/main/services/update/update-manager.d.ts +10 -0
  84. package/dist/main/services/update/update-manager.js +16 -3
  85. package/dist/main/services/views/devtools-tabs.d.ts +47 -0
  86. package/dist/main/services/views/devtools-tabs.js +95 -0
  87. package/dist/main/services/views/view-manager.d.ts +142 -4
  88. package/dist/main/services/views/view-manager.js +909 -17
  89. package/dist/main/services/workbench-context.d.ts +66 -1
  90. package/dist/main/services/workbench-context.js +6 -1
  91. package/dist/main/services/workspace/workspace-service.d.ts +8 -0
  92. package/dist/main/services/workspace/workspace-service.js +12 -0
  93. package/dist/main/utils/ipc-registry.d.ts +11 -2
  94. package/dist/main/utils/ipc-registry.js +63 -3
  95. package/dist/main/utils/paths.d.ts +15 -0
  96. package/dist/main/utils/paths.js +19 -0
  97. package/dist/main/utils/sender-policy.d.ts +9 -3
  98. package/dist/main/utils/sender-policy.js +18 -4
  99. package/dist/main/utils/theme.d.ts +1 -1
  100. package/dist/main/utils/theme.js +1 -1
  101. package/dist/main/windows/main-window/create.d.ts +0 -6
  102. package/dist/main/windows/main-window/create.js +11 -59
  103. package/dist/main/windows/main-window/events.d.ts +1 -1
  104. package/dist/main/windows/main-window/events.js +1 -1
  105. package/dist/main/windows/service-host-window/create.d.ts +52 -0
  106. package/dist/main/windows/service-host-window/create.js +112 -0
  107. package/dist/native-host/common/common.js +368 -0
  108. package/dist/native-host/container/pageFrame.css +1 -0
  109. package/dist/native-host/render/render.js +9334 -0
  110. package/dist/native-host/service/service.js +6 -0
  111. package/dist/preload/index.d.ts +2 -0
  112. package/dist/preload/index.js +6 -0
  113. package/dist/preload/instrumentation/app-data.d.ts +18 -20
  114. package/dist/preload/instrumentation/app-data.js +23 -160
  115. package/dist/preload/instrumentation/wxml-extract.d.ts +1 -1
  116. package/dist/preload/instrumentation/wxml-extract.js +1 -1
  117. package/dist/preload/runtime/bridge.d.ts +3 -8
  118. package/dist/preload/runtime/bridge.js +2 -32
  119. package/dist/preload/runtime/custom-apis.js +20 -17
  120. package/dist/preload/runtime/host-toolbar-advertiser.d.ts +27 -0
  121. package/dist/preload/runtime/host-toolbar-advertiser.js +55 -0
  122. package/dist/preload/runtime/main-api-runner.d.ts +9 -0
  123. package/dist/preload/runtime/main-api-runner.js +85 -0
  124. package/dist/preload/runtime/native-host.d.ts +43 -0
  125. package/dist/preload/runtime/native-host.js +83 -0
  126. package/dist/preload/shared/expose.d.ts +10 -5
  127. package/dist/preload/shared/expose.js +29 -11
  128. package/dist/preload/shared/sid-registry.d.ts +11 -0
  129. package/dist/preload/shared/sid-registry.js +38 -0
  130. package/dist/preload/windows/host-toolbar.cjs +161 -0
  131. package/dist/preload/windows/host-toolbar.cjs.map +7 -0
  132. package/dist/preload/windows/host-toolbar.d.ts +2 -0
  133. package/dist/preload/windows/host-toolbar.js +12 -0
  134. package/dist/preload/windows/main.cjs +1939 -0
  135. package/dist/preload/windows/main.cjs.map +4 -4
  136. package/dist/preload/windows/simulator.cjs +925 -0
  137. package/dist/preload/windows/simulator.cjs.map +7 -0
  138. package/dist/preload/windows/simulator.js +243 -573
  139. package/dist/render-host/pageFrame.html +29 -0
  140. package/dist/render-host/preload.cjs +154 -0
  141. package/dist/render-host/render-inspect.js +295 -0
  142. package/dist/renderer/assets/abap-DiwvWnMr.js +2 -0
  143. package/dist/renderer/assets/apex-CmtZjKlf.js +2 -0
  144. package/dist/renderer/assets/azcli-DL2My_i-.js +2 -0
  145. package/dist/renderer/assets/bat-B-nC98wG.js +2 -0
  146. package/dist/renderer/assets/bicep-Ju5MwOgh.js +3 -0
  147. package/dist/renderer/assets/cameligo-8Eu1TyBr.js +2 -0
  148. package/dist/renderer/assets/chunk-DPI0Y_ll.js +1 -0
  149. package/dist/renderer/assets/clojure-u-RpMkH3.js +2 -0
  150. package/dist/renderer/assets/codicon-ngg6Pgfi.ttf +0 -0
  151. package/dist/renderer/assets/coffee-CdA7bbTe.js +2 -0
  152. package/dist/renderer/assets/constants-CLAQX6VZ.js +2 -0
  153. package/dist/renderer/assets/cpp-CzNFP8ks.js +2 -0
  154. package/dist/renderer/assets/csharp-j1LThmcE.js +2 -0
  155. package/dist/renderer/assets/csp-CLRC61y6.js +2 -0
  156. package/dist/renderer/assets/css-r6rC_7P2.js +4 -0
  157. package/dist/renderer/assets/css.worker-DyDu5ynT.js +90 -0
  158. package/dist/renderer/assets/cssMode-BCBgxrnA.js +2 -0
  159. package/dist/renderer/assets/cypher-CW08XVUh.js +2 -0
  160. package/dist/renderer/assets/dart-Cs9aL5T_.js +2 -0
  161. package/dist/renderer/assets/dockerfile-BWM0M184.js +2 -0
  162. package/dist/renderer/assets/ecl-MJJuer5P.js +2 -0
  163. package/dist/renderer/assets/editor-CWI9TnMM.css +1 -0
  164. package/dist/renderer/assets/editor.api2-BTaYmRq7.js +873 -0
  165. package/dist/renderer/assets/editor.worker-Dpt_xPrs.js +27 -0
  166. package/dist/renderer/assets/elixir-D2AIuXqn.js +2 -0
  167. package/dist/renderer/assets/flow9-B2H24giC.js +2 -0
  168. package/dist/renderer/assets/freemarker2-DGDGzimW.js +4 -0
  169. package/dist/renderer/assets/fsharp-CMk2OIJN.js +2 -0
  170. package/dist/renderer/assets/go-BrMkuJg0.js +2 -0
  171. package/dist/renderer/assets/graphql-PSR1UKGv.js +2 -0
  172. package/dist/renderer/assets/handlebars-bOHhw3EG.js +2 -0
  173. package/dist/renderer/assets/hcl-DAQrbDOW.js +2 -0
  174. package/dist/renderer/assets/html-BMyuX0_c.js +2 -0
  175. package/dist/renderer/assets/html.worker-IWNXhnIC.js +503 -0
  176. package/dist/renderer/assets/htmlMode-DR4kXJ7l.js +2 -0
  177. package/dist/renderer/assets/index-CcJKzatF.js +50 -0
  178. package/dist/renderer/assets/ini-0TG5BxW0.js +2 -0
  179. package/dist/renderer/assets/input-QGx6FFX1.js +2 -0
  180. package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
  181. package/dist/renderer/assets/{ipc-transport-BzPzxPwf.js → ipc-transport-DvZvwK-Z.js} +5 -5
  182. package/dist/renderer/assets/java-rgorz17v.js +2 -0
  183. package/dist/renderer/assets/javascript-Bu-tl1P7.js +2 -0
  184. package/dist/renderer/assets/json.worker-c4h5s80L.js +59 -0
  185. package/dist/renderer/assets/jsonMode-MQV_ffLR.js +8 -0
  186. package/dist/renderer/assets/julia-C8VMdHm8.js +2 -0
  187. package/dist/renderer/assets/kotlin-AhhC4Qhm.js +2 -0
  188. package/dist/renderer/assets/less-Cgca25AP.js +3 -0
  189. package/dist/renderer/assets/lexon-D0GHdBaw.js +2 -0
  190. package/dist/renderer/assets/liquid-ClkfOvhB.js +2 -0
  191. package/dist/renderer/assets/lspLanguageFeatures-Bke_4Ie9.js +5 -0
  192. package/dist/renderer/assets/lua-DmRsNG-P.js +2 -0
  193. package/dist/renderer/assets/m3-BgL5dNKT.js +2 -0
  194. package/dist/renderer/assets/markdown-BuJfycGS.js +2 -0
  195. package/dist/renderer/assets/mdx-RZdUskPu.js +2 -0
  196. package/dist/renderer/assets/mips-C9m_93PR.js +2 -0
  197. package/dist/renderer/assets/monaco.contribution-B7rUMaEv.js +3 -0
  198. package/dist/renderer/assets/msdax-CpFHC9OI.js +2 -0
  199. package/dist/renderer/assets/mysql-qFvltsqN.js +2 -0
  200. package/dist/renderer/assets/objective-c-Bnmr858J.js +2 -0
  201. package/dist/renderer/assets/pascal-WP0_D5AO.js +2 -0
  202. package/dist/renderer/assets/pascaligo-Blom4Rij.js +2 -0
  203. package/dist/renderer/assets/perl-B-vk8g64.js +2 -0
  204. package/dist/renderer/assets/pgsql-Cgvz6v67.js +2 -0
  205. package/dist/renderer/assets/php-8a3Lrw9m.js +2 -0
  206. package/dist/renderer/assets/pla-DuFqEZ8V.js +2 -0
  207. package/dist/renderer/assets/popover-BOH1If1J.js +2 -0
  208. package/dist/renderer/assets/postiats-DkLtSgkp.js +2 -0
  209. package/dist/renderer/assets/powerquery-BJ1aNepW.js +2 -0
  210. package/dist/renderer/assets/powershell-rE98k687.js +2 -0
  211. package/dist/renderer/assets/protobuf-CUheFacr.js +3 -0
  212. package/dist/renderer/assets/pug-LDcAMD8w.js +2 -0
  213. package/dist/renderer/assets/python-Cobrm_-8.js +2 -0
  214. package/dist/renderer/assets/qsharp-DUKSQoR1.js +2 -0
  215. package/dist/renderer/assets/r-D-QApv87.js +2 -0
  216. package/dist/renderer/assets/razor-BEUIQFNJ.js +2 -0
  217. package/dist/renderer/assets/redis-SXdDyWR9.js +2 -0
  218. package/dist/renderer/assets/redshift-Y6lsCryn.js +2 -0
  219. package/dist/renderer/assets/restructuredtext-edObr9a8.js +2 -0
  220. package/dist/renderer/assets/ruby-CNnUfF-8.js +2 -0
  221. package/dist/renderer/assets/rust-IHUZWzBr.js +2 -0
  222. package/dist/renderer/assets/sb-DrUvY44N.js +2 -0
  223. package/dist/renderer/assets/scala-B4hbXGLM.js +2 -0
  224. package/dist/renderer/assets/scheme-BGrd12j3.js +2 -0
  225. package/dist/renderer/assets/scss-x5G1ES4U.js +4 -0
  226. package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
  227. package/dist/renderer/assets/settings-DpAbTJyF.js +2 -0
  228. package/dist/renderer/assets/{settings-api-BXCw9vOZ.js → settings-api-RD2IZF53.js} +2 -2
  229. package/dist/renderer/assets/shell-DOehe2Y8.js +2 -0
  230. package/dist/renderer/assets/solidity-BeRvcwWV.js +2 -0
  231. package/dist/renderer/assets/sophia-DZbkUNjy.js +2 -0
  232. package/dist/renderer/assets/sparql-B7_oi5-h.js +2 -0
  233. package/dist/renderer/assets/sql-CTlsFWVE.js +2 -0
  234. package/dist/renderer/assets/st-DJVEJdPE.js +2 -0
  235. package/dist/renderer/assets/swift-CwhT3fYa.js +2 -0
  236. package/dist/renderer/assets/systemverilog-BQN63pkN.js +2 -0
  237. package/dist/renderer/assets/tcl-DqwfpskA.js +2 -0
  238. package/dist/renderer/assets/ts.worker-BwM5Ha3L.js +67720 -0
  239. package/dist/renderer/assets/tsMode-BHa7dl9v.js +12 -0
  240. package/dist/renderer/assets/twig-BiyenUgc.js +2 -0
  241. package/dist/renderer/assets/typescript-15aT0Yj8.js +2 -0
  242. package/dist/renderer/assets/typespec-CWOJribt.js +2 -0
  243. package/dist/renderer/assets/vb-Cq5F87m3.js +2 -0
  244. package/dist/renderer/assets/wgsl-BAvW2lVr.js +299 -0
  245. package/dist/renderer/assets/workbenchSettings-CNJX4Qna.js +8 -0
  246. package/dist/renderer/assets/workers-CRBS0W-v.js +2 -0
  247. package/dist/renderer/assets/xml-bR2Zh-HV.js +2 -0
  248. package/dist/renderer/assets/yaml-Bdk54Qrb.js +2 -0
  249. package/dist/renderer/entries/main/index.html +29 -6
  250. package/dist/renderer/entries/popover/index.html +7 -6
  251. package/dist/renderer/entries/settings/index.html +6 -5
  252. package/dist/renderer/entries/workbench-settings/index.html +6 -5
  253. package/dist/service-host/preload.cjs +254 -0
  254. package/dist/service-host/service.html +10 -0
  255. package/dist/service-host/sourcemap-rewrite.cjs +58 -0
  256. package/dist/service-host/sync-api-patch.js +20 -0
  257. package/dist/service-host/sync-impls/menu-button.js +16 -0
  258. package/dist/service-host/sync-impls/storage.js +50 -0
  259. package/dist/service-host/sync-impls/system-info.js +54 -0
  260. package/dist/shared/appdata-accumulator.d.ts +95 -0
  261. package/dist/shared/appdata-accumulator.js +213 -0
  262. package/dist/shared/bridge-channels.d.ts +364 -0
  263. package/dist/shared/bridge-channels.js +54 -0
  264. package/dist/shared/constants.d.ts +0 -4
  265. package/dist/shared/constants.js +0 -4
  266. package/dist/shared/ipc-channels.d.ts +108 -1
  267. package/dist/shared/ipc-channels.js +127 -10
  268. package/dist/shared/ipc-schemas.d.ts +65 -2
  269. package/dist/shared/ipc-schemas.js +79 -3
  270. package/dist/shared/open-in-editor.d.ts +71 -0
  271. package/dist/shared/open-in-editor.js +138 -0
  272. package/dist/shared/simulator-api-metadata.d.ts +21 -0
  273. package/dist/shared/simulator-api-metadata.js +23 -0
  274. package/dist/shared/types.d.ts +2 -2
  275. package/dist/shared/vpath.d.ts +42 -0
  276. package/dist/shared/vpath.js +105 -0
  277. package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
  278. package/dist/simulator/assets/device-shell-vwYSOVrh.js +2 -0
  279. package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
  280. package/dist/simulator/assets/simulator-DddliUL5.js +10 -0
  281. package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
  282. package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
  283. package/dist/simulator/simulator.html +2 -112
  284. package/package.json +9 -9
  285. package/dist/main/utils/disposable.d.ts +0 -18
  286. package/dist/main/utils/disposable.js +0 -67
  287. package/dist/renderer/assets/constants-DI382mTP.js +0 -2
  288. package/dist/renderer/assets/index-4lkyF644.js +0 -46
  289. package/dist/renderer/assets/input-D4byFOLS.js +0 -2
  290. package/dist/renderer/assets/ipc-transport-DqbRdZNO.css +0 -1
  291. package/dist/renderer/assets/popover-cxKrg_os.js +0 -2
  292. package/dist/renderer/assets/select-BgSkkdHW.js +0 -2
  293. package/dist/renderer/assets/settings-oD2K1jdT.js +0 -2
  294. package/dist/renderer/assets/workbenchSettings-CTNBpTft.js +0 -8
  295. package/dist/simulator/assets/simulator-CVOFTpSj.js +0 -9
@@ -1,8 +1,14 @@
1
- import { WebContentsView, webContents } from 'electron';
1
+ import { ipcMain, shell, WebContentsView, webContents } from 'electron';
2
2
  import path from 'path';
3
- import { mainPreloadPath } from '../../utils/paths.js';
4
- import { applyNavigationHardening } from '../../windows/navigation-hardening.js';
3
+ import { cjsSiblingPreloadPath, hostToolbarPreloadPath, mainPreloadPath } from '../../utils/paths.js';
4
+ import { applyNavigationHardening, handleWindowOpenExternal, } from '../../windows/navigation-hardening.js';
5
+ import { SimulatorCustomApiBridgeChannel } from '../../../shared/ipc-channels.js';
6
+ import { OPEN_IN_EDITOR_SCHEME, decodeOpenInEditorUrl, resourceUrlToProjectRelativePath, } from '../../../shared/open-in-editor.js';
7
+ import { createSafeAreaController } from '../safe-area/index.js';
8
+ import { buildCustomizeTabsScript } from './devtools-tabs.js';
9
+ import { installElementsForward } from '../elements-forward/index.js';
5
10
  import * as layout from '../layout/index.js';
11
+ import { handleCustomApiBridgeRequest, } from '../simulator/custom-apis.js';
6
12
  import { getDefaultTab } from '../workbench-context.js';
7
13
  /**
8
14
  * Build a ViewManager bound to the given context. The returned object is the
@@ -15,14 +21,71 @@ export function createViewManager(ctx) {
15
21
  // Resolve once: full WorkbenchContext always provides headerHeight; partial
16
22
  // test contexts may omit it, in which case fall back to the default 40.
17
23
  const headerHeight = ctx.headerHeight ?? 40;
24
+ // CSS env(safe-area-inset-*) simulation for render-host guests (per device).
25
+ // Driven from did-attach-webview below; re-pushed on device change via
26
+ // reapplySafeArea. Torn down in disposeAll.
27
+ const safeArea = createSafeAreaController({ connections: ctx.connections });
18
28
  // ── Private mutable state ───────────────────────────────────────────────
19
29
  let simulatorView = null;
20
30
  let simulatorViewAdded = false;
31
+ // NATIVE-HOST ONLY: the simulator content WebContentsView (the DeviceShell
32
+ // host). In the default path the simulator is a renderer `<webview>` and this
33
+ // stays null. Positioned in the simulator panel region (left of the splitter)
34
+ // while `simulatorView` above hosts its DevTools in the right panel region.
35
+ let nativeSimulatorView = null;
36
+ let nativeSimulatorViewAdded = false;
37
+ // Model A: the renderer's measured inner-screen rect is the SOLE authority for
38
+ // the native simulator WCV bounds (see docs/simulator-render-architecture.md).
39
+ // Cache the last rect so a report that lands before attachNativeSimulator (the
40
+ // project-open ordering) is not lost — attach replays it instead of using a
41
+ // coarse panel-size fallback (which raced and caused the clip/surround flips).
42
+ let lastRendererRect = null;
43
+ // NATIVE-HOST ONLY. The `ipcMain.on` listener that services the
44
+ // `__diminaCustomApis` bridge for the current native simulator webContents
45
+ // (see `attachNativeCustomApiBridge`). Tracked so we can remove it before
46
+ // tearing down / re-attaching the view (otherwise listeners leak across
47
+ // relaunch cycles).
48
+ let nativeCustomApiBridgeHandler = null;
49
+ // NATIVE-HOST ONLY. The current device zoom as a factor (zoomPercent/100),
50
+ // last reported by the renderer via setNativeSimulatorViewBounds. Stored so
51
+ // nested render-host `<webview>` guests attached AFTER a zoom change still
52
+ // pick up the correct scale in `did-attach-webview`. Defaults to 1 (100%).
53
+ let currentZoomFactor = 1;
21
54
  let settingsView = null;
22
55
  let settingsViewAdded = false;
23
56
  let popoverView = null;
24
57
  let lastSimWidth = 375;
25
58
  let simulatorWebContentsId = null;
59
+ // NATIVE-HOST ONLY. The webContents the right-panel Chrome DevTools front-end
60
+ // currently inspects. We point it at the SERVICE HOST (logic layer) — the
61
+ // hidden BrowserWindow where the mini-app's page code runs (`console.log`,
62
+ // `wx.request`, Sources/Network(fetch) all live there). The UI/view layer
63
+ // (Elements/Styles/WXML tree) is served separately by the native WXML panel +
64
+ // render-guest highlight chain (`simulator-storage`/`simulator-wxml`), so a
65
+ // single DevTools front-end is enough. The service window can be swapped on
66
+ // respawn (pre-warm pool recycles it), so this is re-resolved fresh via
67
+ // `ctx.bridge.getServiceWc()` and re-pointed on every render-side event.
68
+ let nativeDevtoolsSourceWc = null;
69
+ let unsubscribeNativeRenderEvents = null;
70
+ // Disposer for the Elements-forward feature (routes the front-end's Elements
71
+ // CDP traffic at the active render guest). Installed in
72
+ // `attachNativeSimulatorDevtoolsHost`, stopped on detach / host destroyed.
73
+ let stopElementsForward = null;
74
+ let nativeDevtoolsRetryTimer = null;
75
+ let nativeDevtoolsRetryToken = 0;
76
+ // Renderer-driven overlay bounds for the simulator DevTools view. When
77
+ // non-null this takes precedence over the legacy layout computed from the
78
+ // window content size. A zero-area rectangle means "hide" — the overlay is
79
+ // removed from the contentView but its WebContents stays alive.
80
+ let simulatorBoundsOverride = null;
81
+ // ── Host-controllable toolbar WebContentsView ───────────────────────────
82
+ // A strip above the devtools header that the downstream host loads its own
83
+ // content into and fully controls. Bounds come from a renderer DOM anchor
84
+ // (forward anchor, like the simulator DevTools overlay); its height is
85
+ // dynamic via a reverse size-advertiser the toolbar's own renderer drives.
86
+ let hostToolbarView = null;
87
+ let hostToolbarPreloadOverride = null;
88
+ let hostToolbarViewAdded = false;
26
89
  // ── Internal helpers ────────────────────────────────────────────────────
27
90
  function destroyViewInternal(view) {
28
91
  if (!view)
@@ -43,9 +106,160 @@ export function createViewManager(ctx) {
43
106
  function applySimulatorBounds(simWidth) {
44
107
  if (!simulatorView || ctx.windows.mainWindow.isDestroyed())
45
108
  return;
109
+ if (simulatorBoundsOverride) {
110
+ simulatorView.setBounds(simulatorBoundsOverride);
111
+ return;
112
+ }
46
113
  const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
47
114
  simulatorView.setBounds(layout.computeSimulatorBounds(w, h, simWidth, headerHeight));
48
115
  }
116
+ // Renderer publishes width/height = 0 to mean "hide overlay" — the
117
+ // surrounding React panel is unmounted/collapsed. We keep the cached
118
+ // value (so future republishes win over legacy layout) but remove the
119
+ // child view from the contentView until a non-empty rect arrives.
120
+ function isHidden(b) {
121
+ return b.width <= 0 || b.height <= 0;
122
+ }
123
+ function setSimulatorDevtoolsBounds(bounds) {
124
+ simulatorBoundsOverride = bounds;
125
+ if (!simulatorView || simulatorView.webContents.isDestroyed())
126
+ return;
127
+ if (ctx.windows.mainWindow.isDestroyed())
128
+ return;
129
+ if (isHidden(bounds)) {
130
+ if (simulatorViewAdded) {
131
+ try {
132
+ ctx.windows.mainWindow.contentView.removeChildView(simulatorView);
133
+ }
134
+ catch { /* already removed */ }
135
+ simulatorViewAdded = false;
136
+ }
137
+ return;
138
+ }
139
+ if (!simulatorViewAdded) {
140
+ ctx.windows.mainWindow.contentView.addChildView(simulatorView);
141
+ simulatorViewAdded = true;
142
+ }
143
+ simulatorView.setBounds(bounds);
144
+ }
145
+ // ── Host-controllable toolbar WebContentsView ───────────────────────────
146
+ // Lazily create the host-toolbar view. Mirrors `showSettings` for the
147
+ // webPreferences shape and the native simulator for nav hardening +
148
+ // background color (the host may load arbitrary URLs / content). Idempotent.
149
+ function ensureHostToolbarView() {
150
+ if (hostToolbarView && !hostToolbarView.webContents.isDestroyed()) {
151
+ return hostToolbarView;
152
+ }
153
+ // Rebuilding after the host destroyed the underlying webContents: detach the
154
+ // dead view from the contentView and reset the added-flag so the new view
155
+ // gets re-mounted (otherwise the `hostToolbarViewAdded` guard would skip the
156
+ // addChildView and the toolbar would silently disappear).
157
+ if (hostToolbarView && hostToolbarViewAdded) {
158
+ try {
159
+ ctx.windows.mainWindow.contentView.removeChildView(hostToolbarView);
160
+ }
161
+ catch { /* already removed */ }
162
+ hostToolbarViewAdded = false;
163
+ }
164
+ const view = new WebContentsView({
165
+ webPreferences: {
166
+ nodeIntegration: false,
167
+ contextIsolation: true,
168
+ sandbox: false,
169
+ // Default: the reverse size-advertiser preload that measures the host
170
+ // content's intrinsic height and posts it on the advertise channel so
171
+ // main reserves exactly that strip height (dynamic height via
172
+ // ViewAnchor). When the host-shell supplies its own toolbar preload
173
+ // (workbench config.toolbar.preloadPath), use that instead — the host
174
+ // owns the bridge and may install the advertiser itself.
175
+ preload: hostToolbarPreloadOverride ?? hostToolbarPreloadPath,
176
+ },
177
+ });
178
+ hostToolbarView = view;
179
+ // Paint the surface a neutral color so growing the reserved strip never
180
+ // flashes white before the host content paints (mirrors the native
181
+ // simulator's setBackgroundColor anti-flash).
182
+ try {
183
+ view.setBackgroundColor('#121212');
184
+ }
185
+ catch { /* stub may lack it */ }
186
+ // The host may load arbitrary URLs; route popups + cross-origin in-place
187
+ // navigation to the OS browser (mirror the native simulator hardening).
188
+ try {
189
+ view.webContents.setWindowOpenHandler(({ url }) => handleWindowOpenExternal(url));
190
+ }
191
+ catch { /* stub may lack it */ }
192
+ return view;
193
+ }
194
+ function setHostToolbarBounds(bounds) {
195
+ if (ctx.windows.mainWindow.isDestroyed())
196
+ return;
197
+ // Zero-area rect means "hide" — remove the child view but keep its
198
+ // WebContents (and the host's loaded content) alive. Do NOT create the
199
+ // view just to immediately hide it.
200
+ if (isHidden(bounds)) {
201
+ if (hostToolbarView && hostToolbarViewAdded && !hostToolbarView.webContents.isDestroyed()) {
202
+ try {
203
+ ctx.windows.mainWindow.contentView.removeChildView(hostToolbarView);
204
+ }
205
+ catch { /* already removed */ }
206
+ }
207
+ hostToolbarViewAdded = false;
208
+ return;
209
+ }
210
+ const view = ensureHostToolbarView();
211
+ if (!hostToolbarViewAdded) {
212
+ // addChildView appends = topmost z-order, which is correct for a strip
213
+ // that sits above the devtools header.
214
+ ctx.windows.mainWindow.contentView.addChildView(view);
215
+ hostToolbarViewAdded = true;
216
+ }
217
+ view.setBounds(bounds);
218
+ }
219
+ function setHostToolbarHeight(extent) {
220
+ // Push the reserved height back to the main-window renderer so its
221
+ // placeholder div resizes (closing the dynamic-height loop). The height is
222
+ // not retained in main — the renderer placeholder is the single source of
223
+ // truth, and the forward anchor re-reports bounds from it.
224
+ ctx.notify.hostToolbarHeightChanged(extent);
225
+ }
226
+ function hideHostToolbar() {
227
+ if (hostToolbarView && hostToolbarViewAdded && !ctx.windows.mainWindow.isDestroyed()) {
228
+ try {
229
+ ctx.windows.mainWindow.contentView.removeChildView(hostToolbarView);
230
+ }
231
+ catch { /* already removed */ }
232
+ }
233
+ hostToolbarViewAdded = false;
234
+ // Collapse the renderer placeholder to 0 too. Otherwise its anchor keeps a
235
+ // non-zero reserved height and re-publishes bounds on the next window
236
+ // resize, silently re-adding the view we just hid (unstable hide). Zeroing
237
+ // the height flips the anchor to `present:false` so it stops re-publishing.
238
+ ctx.notify.hostToolbarHeightChanged(0);
239
+ }
240
+ const hostToolbar = {
241
+ async loadURL(url) {
242
+ const view = ensureHostToolbarView();
243
+ await view.webContents.loadURL(url);
244
+ },
245
+ async loadFile(filePath) {
246
+ const view = ensureHostToolbarView();
247
+ await view.webContents.loadFile(filePath);
248
+ },
249
+ get webContents() {
250
+ if (!hostToolbarView)
251
+ return null;
252
+ if (hostToolbarView.webContents.isDestroyed())
253
+ return null;
254
+ return hostToolbarView.webContents;
255
+ },
256
+ hide() {
257
+ hideHostToolbar();
258
+ },
259
+ setPreloadPath(path) {
260
+ hostToolbarPreloadOverride = path;
261
+ },
262
+ };
49
263
  function applySettingsBounds() {
50
264
  if (!settingsView || ctx.windows.mainWindow.isDestroyed())
51
265
  return;
@@ -58,6 +272,242 @@ export function createViewManager(ctx) {
58
272
  const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
59
273
  popoverView.setBounds(layout.computePopoverBounds(w, h, headerHeight));
60
274
  }
275
+ function clearNativeDevtoolsRetry() {
276
+ nativeDevtoolsRetryToken++;
277
+ if (nativeDevtoolsRetryTimer) {
278
+ clearTimeout(nativeDevtoolsRetryTimer);
279
+ nativeDevtoolsRetryTimer = null;
280
+ }
281
+ }
282
+ function closeNativeDevtoolsSource() {
283
+ const source = nativeDevtoolsSourceWc;
284
+ nativeDevtoolsSourceWc = null;
285
+ if (!source || source.isDestroyed())
286
+ return;
287
+ try {
288
+ if (source.isDevToolsOpened()) {
289
+ source.closeDevTools();
290
+ }
291
+ }
292
+ catch { /* source may be mid-destroy */ }
293
+ }
294
+ function stopFollowingNativeServiceHost() {
295
+ clearNativeDevtoolsRetry();
296
+ if (unsubscribeNativeRenderEvents) {
297
+ try {
298
+ unsubscribeNativeRenderEvents();
299
+ }
300
+ catch { /* ignore */ }
301
+ unsubscribeNativeRenderEvents = null;
302
+ }
303
+ closeNativeDevtoolsSource();
304
+ }
305
+ // ── Open-in-editor: click a console file link → built-in Monaco ──────────
306
+ // The right-panel console is the embedded Chromium DevTools front-end. Once a
307
+ // sourcemap maps a console frame back to source (restored by the service-host
308
+ // importScripts sourcemap rewrite), we redirect a source-link click to OUR
309
+ // Monaco editor instead of the DevTools Sources panel: install an "open
310
+ // resource handler" in the front-end realm that encodes (url, line, col) into
311
+ // a sentinel URL and asks the front-end to open it; Electron surfaces that as
312
+ // `devtools-open-url` on the inspected (service-host) wc, which we decode,
313
+ // map to a project-relative path, and broadcast to the renderer's Monaco.
314
+ const openInEditorWiredWcIds = new Set();
315
+ function injectOpenResourceHandler(devtoolsWc) {
316
+ // `setOpenResourceHandler` is the official Chromium DevTools hook IDEs use
317
+ // to route source-link clicks to an external editor. We poll for the host
318
+ // (it appears once the front-end finishes bootstrapping, like `UI` above)
319
+ // and register a handler that re-emits an encoded sentinel via
320
+ // `openInNewTab` → Electron `devtools-open-url`. Best-effort: wrapped in
321
+ // try/catch and a bounded poll so a missing API never throws.
322
+ const scheme = JSON.stringify(OPEN_IN_EDITOR_SCHEME);
323
+ devtoolsWc.executeJavaScript(`
324
+ (function() {
325
+ try {
326
+ let tries = 0
327
+ const timer = setInterval(() => {
328
+ tries++
329
+ try {
330
+ const Host = globalThis.Host
331
+ const host = Host && Host.InspectorFrontendHost
332
+ if (host && typeof host.setOpenResourceHandler === 'function'
333
+ && typeof host.openInNewTab === 'function') {
334
+ host.setOpenResourceHandler((url, lineNumber, columnNumber) => {
335
+ try {
336
+ const p = new URLSearchParams()
337
+ p.set('u', String(url))
338
+ if (typeof lineNumber === 'number') p.set('l', String(lineNumber))
339
+ if (typeof columnNumber === 'number') p.set('c', String(columnNumber))
340
+ host.openInNewTab(${scheme} + ':?' + p.toString())
341
+ } catch (_) {}
342
+ })
343
+ clearInterval(timer)
344
+ return
345
+ }
346
+ } catch (_) {}
347
+ if (tries > 80) clearInterval(timer)
348
+ }, 50)
349
+ } catch (_) {}
350
+ })()
351
+ `).catch(() => { });
352
+ }
353
+ // ── DevTools tab customization: keep only Elements/Console/Network ──────────
354
+ // Inject into the same DevTools front-end host wc that the console/network
355
+ // injectors target. Reorders Elements/Console/Network to the front and closes
356
+ // every other panel tab by driving the front-end's UI.ViewManager /
357
+ // InspectorView.tabbedLocation (see ./devtools-tabs.ts). Best-effort: the
358
+ // injected script bounded-polls for the lazily-registered panels, wraps
359
+ // everything in try/catch, and silently no-ops if the API never appears —
360
+ // DevTools default tab behaviour is preserved on any failure. Re-injected on
361
+ // every (re)point so a re-`openDevTools` (service-host pool swap) re-applies.
362
+ function customizeDevtoolsTabs(devtoolsWc) {
363
+ try {
364
+ if (devtoolsWc.isDestroyed())
365
+ return;
366
+ const inject = () => {
367
+ if (devtoolsWc.isDestroyed())
368
+ return;
369
+ try {
370
+ void devtoolsWc.executeJavaScript(buildCustomizeTabsScript()).catch(() => { });
371
+ }
372
+ catch { /* wc torn down mid-call */ }
373
+ };
374
+ if (devtoolsWc.isLoading()) {
375
+ devtoolsWc.once('dom-ready', inject);
376
+ }
377
+ else {
378
+ inject();
379
+ }
380
+ }
381
+ catch { /* wc surface incomplete / torn down; degrade silently */ }
382
+ }
383
+ function wireOpenInEditor(serviceWc, devtoolsWc) {
384
+ // Inject the front-end handler on every (re)attach — the DevTools front-end
385
+ // wc is recreated per simulatorView, so a fresh host needs the handler set.
386
+ if (!devtoolsWc.isDestroyed()) {
387
+ if (devtoolsWc.isLoading()) {
388
+ devtoolsWc.once('dom-ready', () => injectOpenResourceHandler(devtoolsWc));
389
+ }
390
+ else {
391
+ injectOpenResourceHandler(devtoolsWc);
392
+ }
393
+ }
394
+ // Attach the `devtools-open-url` decoder to the inspected service wc once
395
+ // (the listener is keyed off the encoded sentinel scheme, so it only acts on
396
+ // OUR redirected links; any other devtools "open in new tab" falls through).
397
+ if (openInEditorWiredWcIds.has(serviceWc.id))
398
+ return;
399
+ openInEditorWiredWcIds.add(serviceWc.id);
400
+ const onOpenUrl = (_event, url) => {
401
+ const req = decodeOpenInEditorUrl(url);
402
+ if (!req)
403
+ return; // not our sentinel — leave it to Electron's default path
404
+ const rel = resourceUrlToProjectRelativePath(req.url);
405
+ if (!rel)
406
+ return;
407
+ // DevTools reports 0-based line/column; Monaco is 1-based.
408
+ const line = typeof req.line === 'number' ? req.line + 1 : undefined;
409
+ const column = typeof req.column === 'number' ? req.column + 1 : undefined;
410
+ ctx.notify.editorOpenFile({ path: rel, line, column });
411
+ };
412
+ serviceWc.on('devtools-open-url', onOpenUrl);
413
+ // Consolidate teardown onto the connection layer (foundation.md §4 / P2),
414
+ // but as a wc-LIFETIME resource: the open-in-editor wiring inspects this
415
+ // service-host wc and must SURVIVE pool reuse (`reset`) — the dedup set
416
+ // entry + listener stay valid across sessions reusing the same wc, and the
417
+ // early-return dedup above correctly skips re-wiring after a reset. So we
418
+ // register on `'closed'` (fires only on real wc destroy), NOT `own()`
419
+ // (which also fires on `reset` and would leave the wc un-wired after reuse
420
+ // because re-pointing the same wc.id early-returns). acquire() is
421
+ // idempotent — bridge-router owning session-scoped resources on the same
422
+ // serviceWc connection coexists cleanly.
423
+ const conn = ctx.connections.acquire(serviceWc);
424
+ conn.on('closed', () => {
425
+ openInEditorWiredWcIds.delete(serviceWc.id);
426
+ try {
427
+ serviceWc.removeListener('devtools-open-url', onOpenUrl);
428
+ }
429
+ catch { /* wc gone */ }
430
+ });
431
+ }
432
+ // Point the right-panel Chrome DevTools front-end at `next` — the SERVICE HOST
433
+ // webContents (logic layer). Idempotent: if we already inspect this wc, no-op.
434
+ function pointNativeDevtoolsAtServiceWc(next) {
435
+ if (!simulatorView || simulatorView.webContents.isDestroyed())
436
+ return true;
437
+ if (nativeDevtoolsSourceWc?.id === next.id && !nativeDevtoolsSourceWc.isDestroyed()) {
438
+ return true;
439
+ }
440
+ closeNativeDevtoolsSource();
441
+ nativeDevtoolsSourceWc = next;
442
+ try {
443
+ next.setDevToolsWebContents(simulatorView.webContents);
444
+ // DevTools renders into the right-panel host view (simulatorView); with a
445
+ // custom host the `mode` is overridden, and `activate:false` prevents it
446
+ // stealing focus — this re-points whenever the service window is swapped,
447
+ // so a focusing window would yank focus repeatedly (disrupting the user /
448
+ // e2e).
449
+ next.openDevTools({ mode: 'detach', activate: false });
450
+ // Redirect console source-link clicks to the built-in Monaco editor.
451
+ wireOpenInEditor(next, simulatorView.webContents);
452
+ // Keep only Elements/Console/Network tabs (front-most, in that order).
453
+ // Re-applied on every re-point so a service-host pool swap (fresh
454
+ // openDevTools) re-asserts the custom tab bar.
455
+ customizeDevtoolsTabs(simulatorView.webContents);
456
+ return true;
457
+ }
458
+ catch {
459
+ if (nativeDevtoolsSourceWc?.id === next.id) {
460
+ nativeDevtoolsSourceWc = null;
461
+ }
462
+ return false;
463
+ }
464
+ }
465
+ // Resolve the SERVICE HOST webContents for the active (or named) app. This is
466
+ // the hidden service BrowserWindow's wc — a top-level wc that CAN host a
467
+ // Chrome DevTools front-end (unlike a `<webview>` guest's). Re-resolved fresh
468
+ // so a pre-warm-pool swap on respawn is tolerated.
469
+ function pointNativeDevtoolsAtActiveServiceHost(appId) {
470
+ if (!ctx.bridge?.isNativeHost())
471
+ return true;
472
+ if (!simulatorView || simulatorView.webContents.isDestroyed())
473
+ return true;
474
+ const wc = ctx.bridge.getServiceWc(appId);
475
+ if (!wc || wc.isDestroyed())
476
+ return false;
477
+ return pointNativeDevtoolsAtServiceWc(wc);
478
+ }
479
+ function scheduleNativeDevtoolsFollow(appId, attempt = 0) {
480
+ if (attempt >= 20)
481
+ return;
482
+ if (!ctx.bridge?.isNativeHost())
483
+ return;
484
+ const token = nativeDevtoolsRetryToken;
485
+ if (nativeDevtoolsRetryTimer)
486
+ clearTimeout(nativeDevtoolsRetryTimer);
487
+ nativeDevtoolsRetryTimer = setTimeout(() => {
488
+ nativeDevtoolsRetryTimer = null;
489
+ if (token !== nativeDevtoolsRetryToken)
490
+ return;
491
+ if (pointNativeDevtoolsAtActiveServiceHost(appId))
492
+ return;
493
+ scheduleNativeDevtoolsFollow(appId, attempt + 1);
494
+ }, 50);
495
+ }
496
+ function followNativeDevtoolsServiceHost(appId) {
497
+ clearNativeDevtoolsRetry();
498
+ if (pointNativeDevtoolsAtActiveServiceHost(appId))
499
+ return;
500
+ scheduleNativeDevtoolsFollow(appId);
501
+ }
502
+ // Render-side activity (a page DOM mounting / the visible page changing)
503
+ // always follows a spawn or respawn, by which point the service window exists
504
+ // (and may have been swapped by the pool). Re-resolve + re-point the DevTools
505
+ // at the now-current service host on every such event.
506
+ function onNativeRenderEvent(event) {
507
+ if (event.kind !== 'activePage' && event.kind !== 'domReady')
508
+ return;
509
+ followNativeDevtoolsServiceHost(event.appId);
510
+ }
61
511
  // ── ViewManager methods ─────────────────────────────────────────────────
62
512
  function attachSimulator(simWcId, simWidth) {
63
513
  const sim = webContents.fromId(simWcId);
@@ -80,12 +530,20 @@ export function createViewManager(ctx) {
80
530
  }
81
531
  simulatorView = new WebContentsView();
82
532
  sim.setDevToolsWebContents(simulatorView.webContents);
83
- sim.openDevTools();
533
+ // Embedded in the right-panel host view; never bring it to the foreground
534
+ // (would steal focus from the user / disrupt e2e).
535
+ sim.openDevTools({ mode: 'detach', activate: false });
84
536
  // Default DevTools to Console panel (Chrome DevTools defaults to Elements).
85
- // The DevTools UI renders inside simulatorView.webContents; we click the
86
- // Console tab once its header is laid out, and persist the choice via
87
- // localStorage so subsequent reloads honor it.
537
+ // The DevTools UI lives inside closed shadow roots, so a light-DOM
538
+ // querySelector('[role="tab"]') cannot reach the tab bar to click it.
539
+ // Instead drive the front-end's own view manager: the bundled DevTools
540
+ // exposes `UI.ViewManager.instance().showView(id)` on `globalThis.UI`
541
+ // once the front-end has finished bootstrapping. We poll for it and
542
+ // request the `console` view, and also persist the choice via the
543
+ // `panel-selectedTab` localStorage key so subsequent reloads honor it.
88
544
  const devtoolsWc = simulatorView.webContents;
545
+ // Keep only Elements/Console/Network tabs (front-most, in that order).
546
+ customizeDevtoolsTabs(devtoolsWc);
89
547
  devtoolsWc.once('dom-ready', () => {
90
548
  devtoolsWc.executeJavaScript(`
91
549
  (function() {
@@ -93,27 +551,380 @@ export function createViewManager(ctx) {
93
551
  let tries = 0
94
552
  const timer = setInterval(() => {
95
553
  tries++
96
- const tabs = document.querySelectorAll('[role="tab"], .tabbed-pane-header-tab')
97
- for (const tab of tabs) {
98
- const label = (tab.getAttribute('aria-label') || tab.textContent || '').trim().toLowerCase()
99
- if (label === 'console' || label.startsWith('console')) {
100
- tab.click()
554
+ try {
555
+ const UI = globalThis.UI
556
+ const vm = UI && UI.ViewManager && typeof UI.ViewManager.instance === 'function'
557
+ ? UI.ViewManager.instance()
558
+ : null
559
+ if (vm && typeof vm.showView === 'function') {
560
+ vm.showView('console')
101
561
  clearInterval(timer)
102
562
  return
103
563
  }
564
+ } catch {}
565
+ if (tries > 80) clearInterval(timer)
566
+ }, 50)
567
+ })()
568
+ `).catch(() => { });
569
+ });
570
+ if (getDefaultTab(ctx) === 'simulator') {
571
+ if (simulatorBoundsOverride) {
572
+ if (!isHidden(simulatorBoundsOverride)) {
573
+ ctx.windows.mainWindow.contentView.addChildView(simulatorView);
574
+ simulatorViewAdded = true;
575
+ simulatorView.setBounds(simulatorBoundsOverride);
576
+ }
577
+ }
578
+ else {
579
+ ctx.windows.mainWindow.contentView.addChildView(simulatorView);
580
+ simulatorViewAdded = true;
581
+ applySimulatorBounds(simWidth);
582
+ }
583
+ }
584
+ }
585
+ function attachNativeSimulatorDevtoolsHost(simWidth) {
586
+ stopFollowingNativeServiceHost();
587
+ // Destroy old simulatorView to prevent WebContentsView leak
588
+ if (simulatorView) {
589
+ hideSimulator();
590
+ try {
591
+ if (!simulatorView.webContents.isDestroyed()) {
592
+ simulatorView.webContents.close();
593
+ }
104
594
  }
105
- if (tries > 40) clearInterval(timer)
106
- }, 100)
595
+ catch { /* ignore */ }
596
+ simulatorView = null;
597
+ }
598
+ simulatorView = new WebContentsView();
599
+ // Default DevTools to Console panel (Chrome DevTools defaults to Elements).
600
+ // The DevTools UI lives inside closed shadow roots, so a light-DOM
601
+ // querySelector('[role="tab"]') cannot reach the tab bar to click it.
602
+ // Instead drive the front-end's own view manager: the bundled DevTools
603
+ // exposes `UI.ViewManager.instance().showView(id)` on `globalThis.UI`
604
+ // once the front-end has finished bootstrapping. We poll for it and
605
+ // request the `console` view, and also persist the choice via the
606
+ // `panel-selectedTab` localStorage key so subsequent reloads honor it.
607
+ const devtoolsWc = simulatorView.webContents;
608
+ // Hand the network forwarder THIS front-end host wc — it injects the
609
+ // simulator WCV's Network.* CDP events into `window.DevToolsAPI.dispatchMessage`
610
+ // here so the native Network tab renders them (falls back to the service-host
611
+ // console line when null / the API never appears). Cleared on detach.
612
+ ctx.networkForward?.setDevtoolsHost(devtoolsWc);
613
+ // Elements forwarding (production, always on for the native simulator): route
614
+ // the front-end's Elements-panel CDP traffic (DOM/CSS/Overlay/DOMSnapshot/
615
+ // DOMDebugger) onto the ACTIVE RENDER GUEST so the panel reflects the page's
616
+ // live DOM tree instead of the service host it natively inspects. Reuses the
617
+ // safe-area-attached debugger session (never detaches one it doesn't own);
618
+ // Emulation.* and every other domain stay on the service-host path. Degrades
619
+ // to the native service-host DOM if the front-end hook is unavailable. The
620
+ // disposer is stopped on detach / host destroyed.
621
+ if (ctx.bridge) {
622
+ try {
623
+ stopElementsForward?.();
624
+ }
625
+ catch { /* prior disposer already gone */ }
626
+ stopElementsForward = installElementsForward({ devtoolsWc, bridge: ctx.bridge, connections: ctx.connections });
627
+ devtoolsWc.once('destroyed', () => {
628
+ try {
629
+ stopElementsForward?.();
630
+ }
631
+ catch { /* already stopped */ }
632
+ stopElementsForward = null;
633
+ });
634
+ }
635
+ devtoolsWc.once('dom-ready', () => {
636
+ devtoolsWc.executeJavaScript(`
637
+ (function() {
638
+ try { localStorage.setItem('panel-selectedTab', '"console"') } catch {}
639
+ let tries = 0
640
+ const timer = setInterval(() => {
641
+ tries++
642
+ try {
643
+ const UI = globalThis.UI
644
+ const vm = UI && UI.ViewManager && typeof UI.ViewManager.instance === 'function'
645
+ ? UI.ViewManager.instance()
646
+ : null
647
+ if (vm && typeof vm.showView === 'function') {
648
+ vm.showView('console')
649
+ clearInterval(timer)
650
+ return
651
+ }
652
+ } catch {}
653
+ if (tries > 80) clearInterval(timer)
654
+ }, 50)
107
655
  })()
108
656
  `).catch(() => { });
109
657
  });
110
658
  if (getDefaultTab(ctx) === 'simulator') {
111
- ctx.windows.mainWindow.contentView.addChildView(simulatorView);
112
- simulatorViewAdded = true;
113
- applySimulatorBounds(simWidth);
659
+ if (simulatorBoundsOverride) {
660
+ if (!isHidden(simulatorBoundsOverride)) {
661
+ ctx.windows.mainWindow.contentView.addChildView(simulatorView);
662
+ simulatorViewAdded = true;
663
+ simulatorView.setBounds(simulatorBoundsOverride);
664
+ }
665
+ }
666
+ else {
667
+ ctx.windows.mainWindow.contentView.addChildView(simulatorView);
668
+ simulatorViewAdded = true;
669
+ applySimulatorBounds(simWidth);
670
+ }
671
+ }
672
+ if (ctx.bridge?.isNativeHost()) {
673
+ unsubscribeNativeRenderEvents = ctx.bridge.onRenderEvent(onNativeRenderEvent);
674
+ followNativeDevtoolsServiceHost();
675
+ }
676
+ }
677
+ /**
678
+ * Remove the custom-apis bridge `ipcMain.on` listener, if any. Idempotent.
679
+ */
680
+ function detachNativeCustomApiBridge() {
681
+ if (nativeCustomApiBridgeHandler) {
682
+ ipcMain.removeListener(SimulatorCustomApiBridgeChannel.Request, nativeCustomApiBridgeHandler);
683
+ nativeCustomApiBridgeHandler = null;
684
+ }
685
+ }
686
+ /**
687
+ * NATIVE-HOST ONLY. The native simulator is a top-level WebContentsView with
688
+ * NO embedder renderer, so the simulator-side `__diminaCustomApis` bridge
689
+ * (`src/preload/runtime/custom-apis.ts`) cannot reach the host via
690
+ * `ipcRenderer.sendToHost` — that only delivers to a `<webview>`'s embedder,
691
+ * which is how the default path's `useCustomApiProxy` answered it. A
692
+ * top-level WebContentsView has no embedder, and `sendToHost` does NOT loop
693
+ * back as `ipc-message-host` on itself, so that channel never fires here.
694
+ *
695
+ * Under native-host the bridge instead talks to `ipcMain` directly (the same
696
+ * way `installNativeHostBridge` issues SPAWN/PAGE_OPEN): the preload sends
697
+ * `SimulatorCustomApiBridgeChannel.Request` via `ipcRenderer.send`, this
698
+ * `ipcMain.on` listener answers it. We do NOT route through `IpcRegistry` /
699
+ * the sender-policy white-list (the simulator is deliberately kept off it);
700
+ * instead we accept the message ONLY when `event.sender` is THIS precise
701
+ * simWc — the same trust model bridge-router uses for the simulator's own
702
+ * SPAWN messages. The result is dispatched through the shared
703
+ * `ctx.simulatorApis` registry and the id-correlated `Response` is posted
704
+ * back via `simWc.send`, which the preload's `ipcRenderer.on(Response)`
705
+ * listener settles.
706
+ */
707
+ function attachNativeCustomApiBridge(simWc) {
708
+ // Re-attach defensively: a stale listener from a prior simWc must never
709
+ // linger. (attachNativeSimulator already tears the old view down first.)
710
+ detachNativeCustomApiBridge();
711
+ const apis = ctx.simulatorApis;
712
+ if (!apis)
713
+ return;
714
+ const simWcId = simWc.id;
715
+ const handler = (event, req) => {
716
+ // Trust gate: only the exact native simulator webContents may drive this.
717
+ if (event.sender.id !== simWcId)
718
+ return;
719
+ const r = req;
720
+ if (!r || typeof r.id !== 'number')
721
+ return;
722
+ void handleCustomApiBridgeRequest(apis, r).then((response) => {
723
+ if (simWc.isDestroyed())
724
+ return;
725
+ simWc.send(SimulatorCustomApiBridgeChannel.Response, response);
726
+ }).catch(() => { });
727
+ };
728
+ nativeCustomApiBridgeHandler = handler;
729
+ ipcMain.on(SimulatorCustomApiBridgeChannel.Request, handler);
730
+ // Consolidate this per-webContents teardown onto the connection layer
731
+ // (foundation.md §4 / P1 DoD #3): acquiring the simWc connection makes the
732
+ // registry track this trusted webContents, and `own()`-ing the detach ties
733
+ // the ipcMain listener's lifetime to the connection so it's torn down
734
+ // deterministically when the wc is destroyed (or the connection is reset),
735
+ // instead of a bespoke `once('destroyed')`. The detach stays idempotent, so
736
+ // the defensive re-attach path calling it directly remains safe.
737
+ ctx.connections.acquire(simWc).own(detachNativeCustomApiBridge);
738
+ }
739
+ function attachNativeSimulator(simulatorUrl, simWidth) {
740
+ if (!ctx.preloadPath) {
741
+ console.error('[workbench] attachNativeSimulator — preloadPath unset; cannot mount native simulator');
742
+ return;
743
+ }
744
+ lastSimWidth = simWidth;
745
+ // Tear down any previous native simulator view (relaunch / re-open).
746
+ if (nativeSimulatorView) {
747
+ detachNativeCustomApiBridge();
748
+ if (nativeSimulatorViewAdded) {
749
+ try {
750
+ ctx.windows.mainWindow.contentView.removeChildView(nativeSimulatorView);
751
+ }
752
+ catch { /* already removed */ }
753
+ nativeSimulatorViewAdded = false;
754
+ }
755
+ try {
756
+ if (!nativeSimulatorView.webContents.isDestroyed()) {
757
+ nativeSimulatorView.webContents.close();
758
+ }
759
+ }
760
+ catch { /* ignore */ }
761
+ nativeSimulatorView = null;
114
762
  }
763
+ // The simulator preload is a CJS bundle; webPreferences.preload obeys the
764
+ // `.js` + "type":"module" ESM rule (require would be undefined), so hand the
765
+ // top-level WebContentsView the `.cjs` sibling. contextIsolation:false +
766
+ // sandbox:false + webviewTag:true mirror what the default `<webview>` guest
767
+ // runs with, and `partition:'persist:simulator'` shares storage + the
768
+ // session-registered preload/CORS rules with the rest of the simulator.
769
+ const view = new WebContentsView({
770
+ webPreferences: {
771
+ nodeIntegration: false,
772
+ contextIsolation: false,
773
+ sandbox: false,
774
+ webviewTag: true,
775
+ preload: cjsSiblingPreloadPath(ctx.preloadPath),
776
+ partition: 'persist:simulator',
777
+ },
778
+ });
779
+ nativeSimulatorView = view;
780
+ // Paint the WCV surface the simulator-panel background (≈ --color-sim-bg
781
+ // hsl(0 0% 7%)) so a height-resize that grows the region never flashes white
782
+ // in the newly-exposed strip before DeviceShell's desk repaints — the WCV,
783
+ // the desk, and the renderer placeholder behind it are all the same color.
784
+ view.setBackgroundColor('#121212');
785
+ const simWc = view.webContents;
786
+ // Service the simulator-side `__diminaCustomApis` bridge: this top-level
787
+ // WebContentsView has no embedder renderer to proxy through, so dispatch its
788
+ // `sendToHost` requests straight to `ctx.simulatorApis` from main.
789
+ attachNativeCustomApiBridge(simWc);
790
+ // DeviceShell mounts per-page render-host `<webview>`s INSIDE this view.
791
+ // Mirror windows/main-window/create.ts: pin them onto persist:simulator and
792
+ // run them with contextIsolation/sandbox off so the render runtime + its
793
+ // preload share the page realm. (A top-level WebContentsView can host these
794
+ // guests; a `<webview>` guest cannot — that's the whole point of Option A.)
795
+ simWc.on('will-attach-webview', (_event, webPreferences, params) => {
796
+ ;
797
+ webPreferences.partition = 'persist:simulator';
798
+ params.partition = 'persist:simulator';
799
+ webPreferences.contextIsolation = false;
800
+ webPreferences.sandbox = false;
801
+ });
802
+ simWc.on('did-attach-webview', (_event, guestWc) => {
803
+ // Scale the nested render-host page with the device zoom. The host WCV is
804
+ // sized to the SCALED bezel rect and runs at `currentZoomFactor`, so the
805
+ // guest must run at the same factor to lay the page out at the logical
806
+ // device width and paint at the right scale. At 100% (default) this is a
807
+ // no-op identity (factor 1). Newly-attached guests pick up the latest
808
+ // zoom here; live zoom changes re-apply via setNativeSimulatorViewBounds.
809
+ try {
810
+ guestWc.setZoomFactor(currentZoomFactor);
811
+ }
812
+ catch { /* guest not ready; setNativeSimulatorViewBounds re-applies */ }
813
+ // Simulate this device's CSS env(safe-area-inset-*) on the fresh guest
814
+ // before it paints, so notch-aware page layout resolves correctly.
815
+ safeArea.applyToGuest(guestWc, ctx.bridge?.getDevice() ?? null);
816
+ guestWc.setWindowOpenHandler(({ url }) => handleWindowOpenExternal(url));
817
+ guestWc.on('will-navigate', (e, url) => {
818
+ try {
819
+ const u = new URL(url);
820
+ if (u.protocol === 'about:')
821
+ return;
822
+ if ((u.protocol === 'http:' || u.protocol === 'https:')
823
+ && (u.hostname === 'localhost' || u.hostname === '127.0.0.1')) {
824
+ return;
825
+ }
826
+ if (u.protocol === 'file:')
827
+ return;
828
+ e.preventDefault();
829
+ if (u.protocol === 'http:' || u.protocol === 'https:') {
830
+ void shell.openExternal(url);
831
+ }
832
+ }
833
+ catch {
834
+ e.preventDefault();
835
+ }
836
+ });
837
+ // A render-host guest only attaches after a spawn, so the service window
838
+ // exists by now — (re)point the right-panel DevTools at it. Belt-and-braces
839
+ // with the `onRenderEvent` path in case its emit lost the attach race.
840
+ followNativeDevtoolsServiceHost();
841
+ });
842
+ // The simulator loads http://localhost:<port>/simulator.html. Harden popups
843
+ // + in-place navigation: allow the dev server origin (and about:blank /
844
+ // file:// render hosts), route everything else to the OS browser.
845
+ simWc.setWindowOpenHandler(({ url }) => handleWindowOpenExternal(url));
846
+ simWc.on('will-navigate', (e, url) => {
847
+ try {
848
+ const u = new URL(url);
849
+ if (u.protocol === 'about:')
850
+ return;
851
+ if (u.protocol === 'file:')
852
+ return;
853
+ if ((u.protocol === 'http:' || u.protocol === 'https:')
854
+ && (u.hostname === 'localhost' || u.hostname === '127.0.0.1')) {
855
+ return;
856
+ }
857
+ e.preventDefault();
858
+ if (u.protocol === 'http:' || u.protocol === 'https:') {
859
+ void shell.openExternal(url);
860
+ }
861
+ }
862
+ catch {
863
+ e.preventDefault();
864
+ }
865
+ });
866
+ void simWc.loadURL(simulatorUrl).catch((err) => {
867
+ console.error('[workbench] attachNativeSimulator — loadURL failed', err);
868
+ });
869
+ // This WebContentsView's webContents IS the simulator: the native-host
870
+ // preload runs here and issues SPAWN, so bridge-router resolves
871
+ // ap.simulatorWc = event.sender = this wc, and SIMULATOR_EVENTS flow back.
872
+ simulatorWebContentsId = simWc.id;
873
+ // Forward this WCV's network requests (wx.request/download/upload run here,
874
+ // not in the service host) into the service-host console so they show in the
875
+ // embedded DevTools the right panel hosts. Attaches the CDP debugger; no-op
876
+ // if the forwarder is unwired (partial test ctx) or the debugger is claimed.
877
+ ctx.networkForward?.attachSimulator(simWc);
878
+ // Model A: bounds come ONLY from the renderer's measured inner-screen rect.
879
+ // If a report already landed before this attach (project-open ordering),
880
+ // replay it now — setNativeSimulatorViewBounds adds + sizes the view. Else
881
+ // the view stays unadded until the next reportBounds. No coarse fallback.
882
+ if (lastRendererRect) {
883
+ setNativeSimulatorViewBounds(lastRendererRect);
884
+ }
885
+ // Native-host page code (console.log / wx.request / Sources) runs in the
886
+ // hidden SERVICE HOST window, not this DeviceShell host nor the render-host
887
+ // guests. Keep the right-panel DevTools host view stable and point it at the
888
+ // service host so its Console/Network(fetch)/Sources reflect the logic layer.
889
+ // (The UI/view layer's Elements equivalent is the native WXML panel +
890
+ // render-guest highlight chain, which targets the active render guest.)
891
+ attachNativeSimulatorDevtoolsHost(simWidth);
115
892
  }
116
893
  function detachSimulator() {
894
+ stopFollowingNativeServiceHost();
895
+ detachNativeCustomApiBridge();
896
+ // Stop Elements forwarding (detaches only the debugger sessions IT attached;
897
+ // safe-area's sessions are untouched). Idempotent — the host 'destroyed'
898
+ // handler may have already run.
899
+ try {
900
+ stopElementsForward?.();
901
+ }
902
+ catch { /* already stopped */ }
903
+ stopElementsForward = null;
904
+ // Stop forwarding the simulator WCV's network (its debugger is detached as
905
+ // the view is closed below, but drop our session deterministically first).
906
+ // Also drop the DevTools front-end host — its wc is destroyed below; a stale
907
+ // ref would make the forwarder dispatch into a dead wc instead of falling
908
+ // back to the console.
909
+ ctx.networkForward?.detachSimulator();
910
+ ctx.networkForward?.setDevtoolsHost(null);
911
+ // Native-host simulator content view (no-op in the default path).
912
+ if (nativeSimulatorView) {
913
+ if (nativeSimulatorViewAdded && !ctx.windows.mainWindow.isDestroyed()) {
914
+ try {
915
+ ctx.windows.mainWindow.contentView.removeChildView(nativeSimulatorView);
916
+ }
917
+ catch { /* already removed */ }
918
+ }
919
+ try {
920
+ if (!nativeSimulatorView.webContents.isDestroyed()) {
921
+ nativeSimulatorView.webContents.close();
922
+ }
923
+ }
924
+ catch { /* ignore */ }
925
+ nativeSimulatorView = null;
926
+ nativeSimulatorViewAdded = false;
927
+ }
117
928
  hidePopover();
118
929
  // Drop the settings view too — the previous detachAllViews() did.
119
930
  destroyViewInternal(settingsView);
@@ -123,6 +934,13 @@ export function createViewManager(ctx) {
123
934
  simulatorView = null;
124
935
  simulatorViewAdded = false;
125
936
  simulatorWebContentsId = null;
937
+ // Drop the renderer-published rect so a stale "hidden" override doesn't
938
+ // suppress the next view before its renderer republishes.
939
+ simulatorBoundsOverride = null;
940
+ // Also drop the cached native-simulator rect: attachNativeSimulator replays
941
+ // lastRendererRect on attach, so a leftover rect/offset from a torn-down
942
+ // session must not be replayed onto a fresh re-attach (stale slice/offset).
943
+ lastRendererRect = null;
126
944
  }
127
945
  function showSimulator(simWidth) {
128
946
  lastSimWidth = simWidth;
@@ -204,6 +1022,8 @@ export function createViewManager(ctx) {
204
1022
  }
205
1023
  }
206
1024
  function repositionAll() {
1025
+ // Native simulator: bounds owned by the renderer's reportBounds (Model A);
1026
+ // its window-resize listener re-measures, so no coarse re-apply here.
207
1027
  if (simulatorView && simulatorViewAdded)
208
1028
  applySimulatorBounds(lastSimWidth);
209
1029
  if (settingsView && settingsViewAdded)
@@ -213,9 +1033,67 @@ export function createViewManager(ctx) {
213
1033
  }
214
1034
  function disposeAll() {
215
1035
  detachSimulator();
1036
+ // Host-controllable toolbar view: removed from the contentView + its
1037
+ // WebContents closed (the host's loaded content is torn down on app exit).
1038
+ destroyViewInternal(hostToolbarView);
1039
+ hostToolbarView = null;
1040
+ hostToolbarViewAdded = false;
1041
+ safeArea.dispose();
1042
+ }
1043
+ function setNativeSimulatorViewBounds(params) {
1044
+ // Cache unconditionally so attachNativeSimulator can replay a report that
1045
+ // landed before the view existed (project-open ordering). This rect is the
1046
+ // ONLY authority for the native WCV bounds.
1047
+ lastRendererRect = params;
1048
+ if (ctx.windows.mainWindow.isDestroyed() || !nativeSimulatorView)
1049
+ return;
1050
+ const p = layout.computeNativeSimulatorViewParams(params, params.zoom);
1051
+ currentZoomFactor = p.zoomFactor;
1052
+ // A zero-area rect means "hide" — the renderer reports this when the
1053
+ // simulator panel/cell is toggled off or unmounts (toolbar toggle only
1054
+ // mutates renderer layout state, so without this the WCV would stay
1055
+ // painted over its old region). Mirror `setSimulatorDevtoolsBounds`:
1056
+ // remove the child view from the contentView but keep its WebContents
1057
+ // alive, so re-showing doesn't re-pay the simulator bootstrap.
1058
+ if (isHidden(p.bounds)) {
1059
+ if (nativeSimulatorViewAdded) {
1060
+ try {
1061
+ ctx.windows.mainWindow.contentView.removeChildView(nativeSimulatorView);
1062
+ }
1063
+ catch { /* already removed */ }
1064
+ nativeSimulatorViewAdded = false;
1065
+ }
1066
+ return;
1067
+ }
1068
+ if (!nativeSimulatorViewAdded) {
1069
+ ctx.windows.mainWindow.contentView.addChildView(nativeSimulatorView);
1070
+ nativeSimulatorViewAdded = true;
1071
+ }
1072
+ nativeSimulatorView.setBounds(p.bounds);
1073
+ const simWc = nativeSimulatorView.webContents;
1074
+ if (!simWc.isDestroyed()) {
1075
+ simWc.setZoomFactor(p.zoomFactor);
1076
+ }
1077
+ // Propagate zoom to any already-attached nested render-host guests so the
1078
+ // page rescales live on zoom change (newly-attached guests get it in
1079
+ // did-attach-webview). `webContents.getAllWebContents()` includes guests;
1080
+ // filter to those hosted by this simulator wc.
1081
+ try {
1082
+ for (const wc of webContents.getAllWebContents()) {
1083
+ if (wc.isDestroyed())
1084
+ continue;
1085
+ if (wc.hostWebContents === simWc) {
1086
+ wc.setZoomFactor(p.zoomFactor);
1087
+ }
1088
+ }
1089
+ }
1090
+ catch { /* hostWebContents unavailable; guests get zoom on attach */ }
216
1091
  }
217
1092
  function resize(simWidth) {
218
1093
  lastSimWidth = simWidth;
1094
+ // Native simulator bounds are owned solely by the renderer's reportBounds
1095
+ // (Model A) — its ResizeObserver/window-resize listeners re-measure on this
1096
+ // same resize. No coarse panel-size re-apply here (it raced the precise rect).
219
1097
  if (simulatorViewAdded)
220
1098
  applySimulatorBounds(simWidth);
221
1099
  if (settingsViewAdded)
@@ -234,7 +1112,9 @@ export function createViewManager(ctx) {
234
1112
  }
235
1113
  return {
236
1114
  attachSimulator,
1115
+ attachNativeSimulator,
237
1116
  detachSimulator,
1117
+ reapplySafeArea: (device) => safeArea.reapplyAll(device),
238
1118
  showSimulator,
239
1119
  hideSimulator,
240
1120
  showSettings,
@@ -274,8 +1154,20 @@ export function createViewManager(ctx) {
274
1154
  return null;
275
1155
  return popoverView.webContents.id;
276
1156
  },
1157
+ getHostToolbarWebContentsId: () => {
1158
+ if (!hostToolbarView)
1159
+ return null;
1160
+ if (hostToolbarView.webContents.isDestroyed())
1161
+ return null;
1162
+ return hostToolbarView.webContents.id;
1163
+ },
1164
+ setNativeSimulatorViewBounds,
277
1165
  resize,
278
1166
  setVisible,
1167
+ setSimulatorDevtoolsBounds,
1168
+ setHostToolbarBounds,
1169
+ setHostToolbarHeight,
1170
+ hostToolbar,
279
1171
  };
280
1172
  }
281
1173
  //# sourceMappingURL=view-manager.js.map