@dimina-kit/devtools 0.3.2-dev.20260601115343 → 0.3.2-dev.20260610114009

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 (189) hide show
  1. package/README.md +49 -59
  2. package/dist/main/api.d.ts +1 -2
  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 +249 -122
  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 +6071 -1863
  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 +1333 -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 +1 -1
  19. package/dist/main/ipc/projects.d.ts +1 -1
  20. package/dist/main/ipc/session.d.ts +1 -1
  21. package/dist/main/ipc/settings.d.ts +1 -1
  22. package/dist/main/ipc/simulator-module.d.ts +6 -0
  23. package/dist/main/ipc/simulator-module.js +9 -1
  24. package/dist/main/ipc/simulator.d.ts +2 -2
  25. package/dist/main/ipc/simulator.js +29 -5
  26. package/dist/main/ipc/toolbar.d.ts +1 -1
  27. package/dist/main/ipc/views.d.ts +1 -1
  28. package/dist/main/ipc/views.js +40 -2
  29. package/dist/main/runtime/devtools-backend.d.ts +17 -0
  30. package/dist/main/runtime/devtools-backend.js +49 -0
  31. package/dist/main/runtime/miniapp-runtime.d.ts +39 -0
  32. package/dist/main/runtime/miniapp-runtime.js +17 -0
  33. package/dist/main/services/automation/exec.d.ts +27 -2
  34. package/dist/main/services/automation/exec.js +37 -3
  35. package/dist/main/services/automation/handlers/app.js +127 -11
  36. package/dist/main/services/automation/handlers/page.js +36 -19
  37. package/dist/main/services/automation/index.js +40 -13
  38. package/dist/main/services/automation/wait-active-page.d.ts +56 -0
  39. package/dist/main/services/automation/wait-active-page.js +71 -0
  40. package/dist/main/services/console-forward/index.d.ts +36 -0
  41. package/dist/main/services/console-forward/index.js +81 -0
  42. package/dist/main/services/dimina-resource-server.d.ts +7 -0
  43. package/dist/main/services/dimina-resource-server.js +99 -0
  44. package/dist/main/services/elements-forward/index.d.ts +66 -0
  45. package/dist/main/services/elements-forward/index.js +583 -0
  46. package/dist/main/services/layout/index.d.ts +22 -0
  47. package/dist/main/services/layout/index.js +25 -0
  48. package/dist/main/services/mcp/index.d.ts +1 -0
  49. package/dist/main/services/mcp/index.js +3 -0
  50. package/dist/main/services/mcp/server.d.ts +1 -1
  51. package/dist/main/services/mcp/server.js +1 -1
  52. package/dist/main/services/mcp/target-manager.d.ts +35 -0
  53. package/dist/main/services/mcp/target-manager.js +63 -1
  54. package/dist/main/services/mcp/tools/context-tools.js +15 -1
  55. package/dist/main/services/module.d.ts +1 -1
  56. package/dist/main/services/network-forward/index.d.ts +190 -0
  57. package/dist/main/services/network-forward/index.js +765 -0
  58. package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
  59. package/dist/main/services/notifications/renderer-notifier.js +7 -1
  60. package/dist/main/services/render-inspect/index.d.ts +41 -0
  61. package/dist/main/services/render-inspect/index.js +88 -0
  62. package/dist/main/services/safe-area/index.d.ts +17 -0
  63. package/dist/main/services/safe-area/index.js +59 -0
  64. package/dist/main/services/service-host-pool/pool.d.ts +197 -0
  65. package/dist/main/services/service-host-pool/pool.js +364 -0
  66. package/dist/main/services/simulator/custom-apis.d.ts +34 -0
  67. package/dist/main/services/simulator/custom-apis.js +22 -0
  68. package/dist/main/services/simulator-appdata/index.d.ts +35 -0
  69. package/dist/main/services/simulator-appdata/index.js +71 -0
  70. package/dist/main/services/simulator-current-page/index.d.ts +24 -0
  71. package/dist/main/services/simulator-current-page/index.js +19 -0
  72. package/dist/main/services/simulator-storage/index.d.ts +37 -2
  73. package/dist/main/services/simulator-storage/index.js +209 -32
  74. package/dist/main/services/simulator-storage/service-storage-ops.d.ts +40 -0
  75. package/dist/main/services/simulator-storage/service-storage-ops.js +67 -0
  76. package/dist/main/services/simulator-temp-files/index.d.ts +1 -1
  77. package/dist/main/services/simulator-temp-files/index.js +39 -17
  78. package/dist/main/services/simulator-wxml/index.d.ts +29 -0
  79. package/dist/main/services/simulator-wxml/index.js +28 -0
  80. package/dist/main/services/toolbar/toolbar-store.d.ts +3 -3
  81. package/dist/main/services/toolbar/toolbar-store.js +1 -18
  82. package/dist/main/services/views/devtools-tabs.d.ts +47 -0
  83. package/dist/main/services/views/devtools-tabs.js +95 -0
  84. package/dist/main/services/views/miniapp-partition.d.ts +80 -0
  85. package/dist/main/services/views/miniapp-partition.js +138 -0
  86. package/dist/main/services/views/simulator-session-policy.d.ts +28 -0
  87. package/dist/main/services/views/simulator-session-policy.js +82 -0
  88. package/dist/main/services/views/view-manager.d.ts +125 -0
  89. package/dist/main/services/views/view-manager.js +852 -4
  90. package/dist/main/services/workbench-context.d.ts +67 -7
  91. package/dist/main/services/workbench-context.js +6 -1
  92. package/dist/main/services/workspace/workspace-service.js +7 -13
  93. package/dist/main/utils/ipc-registry.d.ts +1 -1
  94. package/dist/main/utils/ipc-registry.js +21 -4
  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 +6 -80
  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 +67 -0
  106. package/dist/main/windows/service-host-window/create.js +138 -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 +30 -12
  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 +1935 -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 +244 -574
  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/index-CcJKzatF.js +50 -0
  143. package/dist/renderer/assets/{input-CCYS8Ave.js → input-QGx6FFX1.js} +2 -2
  144. package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
  145. package/dist/renderer/assets/{ipc-transport-Bn4KXvhu.js → ipc-transport-DvZvwK-Z.js} +2 -2
  146. package/dist/renderer/assets/{popover-CH4rwpdt.js → popover-BOH1If1J.js} +2 -2
  147. package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
  148. package/dist/renderer/assets/{settings-CMTB-t0x.js → settings-DpAbTJyF.js} +2 -2
  149. package/dist/renderer/assets/{settings-api-Csdngf9Z.js → settings-api-RD2IZF53.js} +2 -2
  150. package/dist/renderer/assets/{workbenchSettings-CODFCzOg.js → workbenchSettings-CNJX4Qna.js} +2 -2
  151. package/dist/renderer/entries/main/index.html +5 -5
  152. package/dist/renderer/entries/popover/index.html +5 -5
  153. package/dist/renderer/entries/settings/index.html +5 -5
  154. package/dist/renderer/entries/workbench-settings/index.html +4 -4
  155. package/dist/service-host/preload.cjs +254 -0
  156. package/dist/service-host/service.html +10 -0
  157. package/dist/service-host/sourcemap-rewrite.cjs +58 -0
  158. package/dist/service-host/sync-api-patch.js +20 -0
  159. package/dist/service-host/sync-impls/menu-button-geometry.js +8 -0
  160. package/dist/service-host/sync-impls/menu-button.js +16 -0
  161. package/dist/service-host/sync-impls/storage.js +50 -0
  162. package/dist/service-host/sync-impls/system-info.js +54 -0
  163. package/dist/shared/appdata-accumulator.d.ts +95 -0
  164. package/dist/shared/appdata-accumulator.js +213 -0
  165. package/dist/shared/bridge-channels.d.ts +378 -0
  166. package/dist/shared/bridge-channels.js +81 -0
  167. package/dist/shared/ipc-channels.d.ts +84 -1
  168. package/dist/shared/ipc-channels.js +90 -10
  169. package/dist/shared/ipc-schemas.d.ts +59 -2
  170. package/dist/shared/ipc-schemas.js +64 -3
  171. package/dist/shared/open-in-editor.d.ts +71 -0
  172. package/dist/shared/open-in-editor.js +138 -0
  173. package/dist/shared/simulator-api-metadata.d.ts +21 -0
  174. package/dist/shared/simulator-api-metadata.js +23 -0
  175. package/dist/shared/types.d.ts +2 -39
  176. package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
  177. package/dist/simulator/assets/device-shell-fH2cI-3q.js +2 -0
  178. package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
  179. package/dist/simulator/assets/simulator-DHylZf9Z.js +10 -0
  180. package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
  181. package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
  182. package/dist/simulator/simulator.html +2 -112
  183. package/package.json +12 -12
  184. package/dist/main/utils/disposable.d.ts +0 -18
  185. package/dist/main/utils/disposable.js +0 -67
  186. package/dist/renderer/assets/index-BDMxXUfn.js +0 -50
  187. package/dist/renderer/assets/ipc-transport-Cu7tubyg.css +0 -1
  188. package/dist/renderer/assets/select-Ct4-sijm.js +0 -2
  189. package/dist/simulator/assets/simulator-B4e3c6_O.js +0 -9
@@ -28,16 +28,16 @@
28
28
  overflow: hidden;
29
29
  }
30
30
  </style>
31
- <script type="module" crossorigin src="../../assets/index-BDMxXUfn.js"></script>
31
+ <script type="module" crossorigin src="../../assets/index-CcJKzatF.js"></script>
32
32
  <link rel="modulepreload" crossorigin href="../../assets/chunk-DPI0Y_ll.js">
33
- <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-Bn4KXvhu.js">
33
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-DvZvwK-Z.js">
34
34
  <link rel="modulepreload" crossorigin href="../../assets/editor.api2-BTaYmRq7.js">
35
35
  <link rel="modulepreload" crossorigin href="../../assets/monaco.contribution-B7rUMaEv.js">
36
- <link rel="modulepreload" crossorigin href="../../assets/input-CCYS8Ave.js">
37
- <link rel="modulepreload" crossorigin href="../../assets/select-Ct4-sijm.js">
36
+ <link rel="modulepreload" crossorigin href="../../assets/input-QGx6FFX1.js">
37
+ <link rel="modulepreload" crossorigin href="../../assets/select-C7JQ8G5N.js">
38
38
  <link rel="modulepreload" crossorigin href="../../assets/workers-CRBS0W-v.js">
39
39
  <link rel="modulepreload" crossorigin href="../../assets/constants-CLAQX6VZ.js">
40
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-Cu7tubyg.css">
40
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-BT4QYQqu.css">
41
41
  <link rel="stylesheet" crossorigin href="../../assets/editor-CWI9TnMM.css">
42
42
  </head>
43
43
  <body>
@@ -8,13 +8,13 @@
8
8
  <style>
9
9
  html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: transparent !important; }
10
10
  </style>
11
- <script type="module" crossorigin src="../../assets/popover-CH4rwpdt.js"></script>
11
+ <script type="module" crossorigin src="../../assets/popover-BOH1If1J.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="../../assets/chunk-DPI0Y_ll.js">
13
- <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-Bn4KXvhu.js">
14
- <link rel="modulepreload" crossorigin href="../../assets/input-CCYS8Ave.js">
15
- <link rel="modulepreload" crossorigin href="../../assets/select-Ct4-sijm.js">
13
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-DvZvwK-Z.js">
14
+ <link rel="modulepreload" crossorigin href="../../assets/input-QGx6FFX1.js">
15
+ <link rel="modulepreload" crossorigin href="../../assets/select-C7JQ8G5N.js">
16
16
  <link rel="modulepreload" crossorigin href="../../assets/constants-CLAQX6VZ.js">
17
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-Cu7tubyg.css">
17
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-BT4QYQqu.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="root"></div>
@@ -5,12 +5,12 @@
5
5
  <!-- See main/index.html for CSP rationale. -->
6
6
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; media-src 'self' blob: http: https:; connect-src 'self' http: https: ws: wss:;" />
7
7
  <title>Settings</title>
8
- <script type="module" crossorigin src="../../assets/settings-CMTB-t0x.js"></script>
8
+ <script type="module" crossorigin src="../../assets/settings-DpAbTJyF.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="../../assets/chunk-DPI0Y_ll.js">
10
- <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-Bn4KXvhu.js">
11
- <link rel="modulepreload" crossorigin href="../../assets/input-CCYS8Ave.js">
12
- <link rel="modulepreload" crossorigin href="../../assets/settings-api-Csdngf9Z.js">
13
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-Cu7tubyg.css">
10
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-DvZvwK-Z.js">
11
+ <link rel="modulepreload" crossorigin href="../../assets/input-QGx6FFX1.js">
12
+ <link rel="modulepreload" crossorigin href="../../assets/settings-api-RD2IZF53.js">
13
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-BT4QYQqu.css">
14
14
  </head>
15
15
  <body>
16
16
  <div id="root"></div>
@@ -6,12 +6,12 @@
6
6
  <!-- See entries/main/index.html for CSP rationale. -->
7
7
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; media-src 'self' blob: http: https:; connect-src 'self' http: https: ws: wss:;" />
8
8
  <title>开发工具设置</title>
9
- <script type="module" crossorigin src="../../assets/workbenchSettings-CODFCzOg.js"></script>
9
+ <script type="module" crossorigin src="../../assets/workbenchSettings-CNJX4Qna.js"></script>
10
10
  <link rel="modulepreload" crossorigin href="../../assets/chunk-DPI0Y_ll.js">
11
- <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-Bn4KXvhu.js">
12
- <link rel="modulepreload" crossorigin href="../../assets/settings-api-Csdngf9Z.js">
11
+ <link rel="modulepreload" crossorigin href="../../assets/ipc-transport-DvZvwK-Z.js">
12
+ <link rel="modulepreload" crossorigin href="../../assets/settings-api-RD2IZF53.js">
13
13
  <link rel="modulepreload" crossorigin href="../../assets/constants-CLAQX6VZ.js">
14
- <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-Cu7tubyg.css">
14
+ <link rel="stylesheet" crossorigin href="../../assets/ipc-transport-BT4QYQqu.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
@@ -0,0 +1,254 @@
1
+ const { ipcRenderer } = require('electron')
2
+
3
+ const CHANNELS = {
4
+ SERVICE_INVOKE: 'dmb:service:invoke',
5
+ SERVICE_PUBLISH: 'dmb:service:publish',
6
+ TO_SERVICE: 'dmb:to-service',
7
+ // main → this window: live-update the host-env snapshot on a device change so
8
+ // wx.getSystemInfoSync() reflects the newly-selected device without a
9
+ // relaunch. Mirrors ServiceHostChannel.HostEnvUpdate in shared/ipc-channels.ts.
10
+ HOST_ENV_UPDATE: 'service-host:host-env:update',
11
+ }
12
+
13
+ const params = new URLSearchParams(globalThis.location && globalThis.location.search || '')
14
+ const bridgeId = params.get('bridgeId')
15
+ const pendingMessages = []
16
+ let onMessageFn = null
17
+ let drainScheduled = false
18
+
19
+ if (!bridgeId) {
20
+ // Warming idle: a pre-warm pool loads this preload against about:blank (no
21
+ // bridgeId) just to fork the renderer + warm the V8 isolate. Defer all bridge
22
+ // setup to the real spawn navigation (service.html?bridgeId=…), which re-runs
23
+ // this preload with a bridgeId. Real spawns always carry one, so the spawn
24
+ // path is unaffected.
25
+ return
26
+ }
27
+
28
+ function parseHostEnv() {
29
+ const raw = params.get('hostEnv')
30
+ if (!raw) return null
31
+ try {
32
+ return JSON.parse(decodeURIComponent(raw))
33
+ } catch (error) {
34
+ console.warn('[service-host] invalid hostEnv param', error)
35
+ return null
36
+ }
37
+ }
38
+
39
+ Object.defineProperty(globalThis, '__diminaSpawnContext', {
40
+ value: {
41
+ bridgeId,
42
+ appId: params.get('appId') || '',
43
+ pagePath: params.get('pagePath') || '',
44
+ pkgRoot: params.get('pkgRoot') || '',
45
+ resourceBaseUrl: params.get('resourceBaseUrl') || '',
46
+ hostEnvSnapshot: parseHostEnv(),
47
+ },
48
+ enumerable: false,
49
+ configurable: false,
50
+ })
51
+
52
+ // Live host-env updates (native-host device dropdown). The binding above is
53
+ // non-configurable, but the inner object's properties are writable — merge the
54
+ // pushed metrics into `hostEnvSnapshot` in place. `sync-impls/system-info.ts`
55
+ // reads `this.hostEnvSnapshot` fresh on every `getSystemInfoSync()`, so the
56
+ // next call (and the mini-app code that invokes it) sees the new device.
57
+ ipcRenderer.on(CHANNELS.HOST_ENV_UPDATE, (_event, snapshot) => {
58
+ if (!snapshot || typeof snapshot !== 'object') return
59
+ const ctx = globalThis.__diminaSpawnContext
60
+ if (!ctx) return
61
+ ctx.hostEnvSnapshot = { ...(ctx.hostEnvSnapshot || {}), ...snapshot }
62
+ })
63
+
64
+ function reportError(stage, error) {
65
+ const message = error && error.stack ? error.stack : String(error)
66
+ console.error(`[service-host] ${stage}`, error)
67
+ ipcRenderer.send(CHANNELS.SERVICE_INVOKE, {
68
+ bridgeId,
69
+ msg: {
70
+ type: 'serviceHostError',
71
+ target: 'container',
72
+ body: { stage, message },
73
+ },
74
+ })
75
+ }
76
+
77
+ function deliver(msg) {
78
+ if (!onMessageFn) {
79
+ pendingMessages.push(msg)
80
+ return
81
+ }
82
+ try {
83
+ onMessageFn(msg)
84
+ } catch (error) {
85
+ reportError('onMessage', error)
86
+ }
87
+ }
88
+
89
+ function scheduleDrain() {
90
+ if (drainScheduled) return
91
+ drainScheduled = true
92
+ queueMicrotask(() => {
93
+ drainScheduled = false
94
+ while (onMessageFn && pendingMessages.length > 0) {
95
+ deliver(pendingMessages.shift())
96
+ }
97
+ })
98
+ }
99
+
100
+ Object.defineProperty(globalThis, 'DiminaServiceBridge', {
101
+ value: {
102
+ get onMessage() {
103
+ return onMessageFn
104
+ },
105
+ set onMessage(handler) {
106
+ onMessageFn = typeof handler === 'function' ? handler : null
107
+ scheduleDrain()
108
+ },
109
+ invoke(msg) {
110
+ ipcRenderer.send(CHANNELS.SERVICE_INVOKE, { bridgeId, msg })
111
+ return undefined
112
+ },
113
+ publish(targetBridgeId, msg) {
114
+ ipcRenderer.send(CHANNELS.SERVICE_PUBLISH, { bridgeId, targetBridgeId, msg })
115
+ },
116
+ },
117
+ writable: false,
118
+ configurable: false,
119
+ })
120
+
121
+ // Block DOM/web globals the service logic must not touch — BUT make the
122
+ // definitions `configurable: true`. dimina's service.js (Worker-style runtime
123
+ // running here in a window) installs its OWN `globalThis.document` stub during
124
+ // boot; a `configurable: false` block makes that redefine throw
125
+ // (`Cannot redefine property: document`), aborting service boot so it never
126
+ // emits `serviceResourceLoaded` and pages never mount. Keeping these
127
+ // configurable lets dimina override them while still surfacing accidental
128
+ // access before dimina has set anything up.
129
+ const block = (key) => {
130
+ // Don't clobber a global the runtime may already rely on; only guard absent ones.
131
+ if (Object.prototype.hasOwnProperty.call(globalThis, key)) return
132
+ Object.defineProperty(globalThis, key, {
133
+ get() {
134
+ throw new Error(`[service] ${key} not available in service context`)
135
+ },
136
+ configurable: true,
137
+ })
138
+ }
139
+ ;['history', 'sessionStorage'].forEach(block)
140
+
141
+ // Worker-API shim. dimina's service loader (service/core/loader.js) loads the
142
+ // compiled `logic.js` via `globalThis.importScripts(...)` — a Web Worker global
143
+ // that doesn't exist in this BrowserWindow service host. The default
144
+ // dimina-fe path runs the service in a real Worker; here we run it in a window,
145
+ // so without this shim `loadResource` throws and the service never emits
146
+ // `serviceResourceLoaded` (the page then never mounts). We fetch each script
147
+ // synchronously (mirroring Worker `importScripts`) over the same dev-server
148
+ // origin and eval it in the global scope, so its `modDefine(...)` registers
149
+ // into the same AMD registry the service loader's `modRequire` reads. Bundles
150
+ // are small + same-origin; sync XHR keeps the loader's synchronous contract.
151
+ //
152
+ // ── Sourcemap fidelity (console file links) ─────────────────────────────────
153
+ // The compiled `logic.js` ships a RELATIVE `//# sourceMappingURL=logic.js.map`
154
+ // (see compiler/core/logic-compiler.js). A real Worker `importScripts(url)`
155
+ // loads the script with the dev-server URL as its base, so DevTools resolves
156
+ // that relative map against `…/{appId}/{root}/logic.js` and fetches the right
157
+ // `.map` — console frames + Sources links then point at the developer's
158
+ // ORIGINAL files. Under `(0, eval)(...)` the script has NO base URL of its own:
159
+ // DevTools resolves a relative `sourceMappingURL` against the service-host
160
+ // DOCUMENT (`file://…/service-host/service.html`), fetches a nonexistent
161
+ // `file://…/service-host/logic.js.map` (404), and falls back to the compiled
162
+ // bundle — so every console file:line points at `logic.js` (compiled), not
163
+ // source. Rewrite the relative map URL to an ABSOLUTE one resolved against the
164
+ // script's fetch `url`, and put `sourceURL` last, restoring sourcemapped links.
165
+ // The pure transform lives in a sibling `.cjs` (unit-tested in
166
+ // sourcemap-rewrite.test.ts) — required relative to this preload so it resolves
167
+ // from dist/service-host at runtime (build copies both files verbatim).
168
+ const { rewriteSourceMappingUrl } = require('./sourcemap-rewrite.cjs')
169
+
170
+ if (typeof globalThis.importScripts !== 'function') {
171
+ globalThis.importScripts = function importScriptsShim(...urls) {
172
+ for (const url of urls) {
173
+ const xhr = new XMLHttpRequest()
174
+ xhr.open('GET', String(url), false)
175
+ xhr.send(null)
176
+ if (xhr.status && (xhr.status < 200 || xhr.status >= 300)) {
177
+ throw new Error(`[service] importScripts failed ${xhr.status} for ${url}`)
178
+ }
179
+ // Resolve the bundle's relative sourceMappingURL to an absolute dev-server
180
+ // URL (eval'd code has no base URL → relative maps 404 against file://).
181
+ const body = rewriteSourceMappingUrl(xhr.responseText, String(url))
182
+ // Indirect eval → runs in global scope (so modDefine/modRequire bind to
183
+ // the service IIFE globals), matching real Worker importScripts semantics.
184
+ // `sourceURL` goes LAST so the script gets a stable name in the Sources
185
+ // tree while the (now absolute) sourceMappingURL above stays fetchable.
186
+ ;(0, eval)(`${body}\n//# sourceURL=${url}`)
187
+ }
188
+ }
189
+ }
190
+
191
+ ipcRenderer.on(CHANNELS.TO_SERVICE, (_event, payload) => {
192
+ deliver(payload && payload.msg)
193
+ })
194
+
195
+ // ── Console capture (native-host) ───────────────────────────────────────────
196
+ // Placed AFTER the no-bridgeId early-return (pool warming) and AFTER
197
+ // DiminaServiceBridge is defined, so it only runs for a real spawn and can use
198
+ // the bridge. This preload runs with contextIsolation effectively off, so
199
+ // patching `console` here captures the service guest's own console (wx.* +
200
+ // logic.js). Each entry is forwarded to main as a `consoleLog` container message
201
+ // (source:'service') — bridge-router routes it to ctx.guestConsole → automation
202
+ // rebroadcasts it as App.logAdded. Mirrors src/preload/instrumentation/console.ts.
203
+
204
+ function safeSerializeArg(val) {
205
+ if (val === null || val === undefined) return val
206
+ if (typeof val === 'function') return `[Function: ${val.name || 'anonymous'}]`
207
+ if (typeof val !== 'object') return val
208
+ if (val instanceof Error) return { __isError: true, message: val.message, stack: val.stack }
209
+ try {
210
+ return structuredClone(val)
211
+ } catch (_) { /* DOM nodes / proxies can't be structuredCloned */ }
212
+ try {
213
+ return JSON.parse(JSON.stringify(val))
214
+ } catch (_) { /* circular / non-serializable */ }
215
+ return String(val)
216
+ }
217
+
218
+ function emitConsoleLog(level, args) {
219
+ try {
220
+ globalThis.DiminaServiceBridge.invoke({
221
+ type: 'consoleLog',
222
+ target: 'container',
223
+ body: {
224
+ source: 'service',
225
+ level,
226
+ args: args.map(safeSerializeArg),
227
+ ts: Date.now(),
228
+ },
229
+ })
230
+ } catch (_) { /* never let console capture break the guest */ }
231
+ }
232
+
233
+ ;['log', 'warn', 'error', 'info', 'debug'].forEach((level) => {
234
+ const original = typeof console[level] === 'function' ? console[level].bind(console) : null
235
+ if (!original) return
236
+ console[level] = (...args) => {
237
+ original(...args)
238
+ emitConsoleLog(level, args)
239
+ }
240
+ })
241
+
242
+ globalThis.addEventListener('error', (event) => {
243
+ emitConsoleLog('error', [{
244
+ message: event.message,
245
+ source: event.filename,
246
+ lineno: event.lineno,
247
+ colno: event.colno,
248
+ stack: event.error && event.error.stack,
249
+ }])
250
+ })
251
+
252
+ globalThis.addEventListener('unhandledrejection', (event) => {
253
+ emitConsoleLog('error', [{ message: 'Unhandled Promise Rejection', reason: String(event.reason) }])
254
+ })
@@ -0,0 +1,10 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Dimina Service Host</title>
6
+ <script src="../native-host/service/service.js"></script>
7
+ <script type="module" src="./sync-api-patch.js"></script>
8
+ </head>
9
+ <body></body>
10
+ </html>
@@ -0,0 +1,58 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Rewrite a fetched script's RELATIVE `//# sourceMappingURL=` directive to an
5
+ * ABSOLUTE URL resolved against the script's own fetch URL.
6
+ *
7
+ * Why this exists (native-host console file links):
8
+ * The service host loads each compiled `logic.js` via the `importScripts`
9
+ * shim in preload.cjs — a synchronous XHR + `(0, eval)(...)`. The compiled
10
+ * bundle ships a RELATIVE `//# sourceMappingURL=logic.js.map`
11
+ * (compiler/core/logic-compiler.js). A real Web Worker `importScripts(url)`
12
+ * gives the script the dev-server URL as its base, so DevTools resolves the
13
+ * relative map against `…/{appId}/{root}/logic.js` and fetches the right
14
+ * `.map`. Under `(0, eval)(...)` the script has NO base URL of its own, so
15
+ * DevTools resolves a relative `sourceMappingURL` against the service-host
16
+ * DOCUMENT (`file://…/service-host/service.html`) and 404s — console
17
+ * file:line links then point at the compiled bundle, not the developer's
18
+ * original source. Rewriting the directive to an absolute dev-server URL
19
+ * restores sourcemapped console frames + Sources links.
20
+ *
21
+ * Contract:
22
+ * - Operates on the LAST `//# sourceMappingURL=` (or legacy `//@`) directive
23
+ * (the compiler appends exactly one as the final line).
24
+ * - Leaves an already-absolute (`http(s)://`, `//host`, `data:`, `file:`) map
25
+ * URL untouched — only relative specifiers are resolved.
26
+ * - Leaves source with no directive untouched.
27
+ * - On any parse/resolve failure, returns the input unchanged (console
28
+ * sourcemap fidelity is best-effort; it must never break script loading).
29
+ *
30
+ * @param {string} source The fetched script body.
31
+ * @param {string} scriptUrl The absolute URL the script was fetched from.
32
+ * @returns {string} The body with an absolute sourceMappingURL (or unchanged).
33
+ */
34
+ function rewriteSourceMappingUrl(source, scriptUrl) {
35
+ if (typeof source !== 'string' || !source) return source
36
+ const re = /(^|\n)[ \t]*\/\/[#@][ \t]*sourceMappingURL=([^\n]*)/g
37
+ let lastIndex = -1
38
+ let lastValue = ''
39
+ let m
40
+ while ((m = re.exec(source)) !== null) {
41
+ lastIndex = m.index + m[1].length
42
+ lastValue = (m[2] || '').trim()
43
+ }
44
+ if (lastIndex < 0 || !lastValue) return source
45
+ // Already absolute (scheme://, protocol-relative //host, or data:)? Leave it.
46
+ if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(lastValue) || /^data:/i.test(lastValue)) return source
47
+ let absolute
48
+ try {
49
+ absolute = new URL(lastValue, scriptUrl).toString()
50
+ } catch (_) {
51
+ return source
52
+ }
53
+ // Drop the original (relative) directive line, re-emit an absolute one.
54
+ const head = source.slice(0, lastIndex)
55
+ return `${head}\n//# sourceMappingURL=${absolute}`
56
+ }
57
+
58
+ module.exports = { rewriteSourceMappingUrl }
@@ -0,0 +1,20 @@
1
+ import { getAccountInfoSync, getSystemInfoSync } from './sync-impls/system-info.js';
2
+ import { clearStorageSync, getStorageInfoSync, getStorageSync, removeStorageSync, setStorageSync, } from './sync-impls/storage.js';
3
+ import { getMenuButtonBoundingClientRect } from './sync-impls/menu-button.js';
4
+ const spawnContext = (globalThis.__diminaSpawnContext ?? {});
5
+ function patchNamespace(ns) {
6
+ if (!ns)
7
+ return;
8
+ ns.getStorageSync = (key) => getStorageSync.call(spawnContext, { key }).data ?? '';
9
+ ns.setStorageSync = (key, data) => setStorageSync.call(spawnContext, { key, data });
10
+ ns.removeStorageSync = (key) => removeStorageSync.call(spawnContext, { key });
11
+ ns.clearStorageSync = () => clearStorageSync.call(spawnContext);
12
+ ns.getStorageInfoSync = () => getStorageInfoSync.call(spawnContext);
13
+ ns.getSystemInfoSync = () => getSystemInfoSync.call(spawnContext);
14
+ ns.getAccountInfoSync = () => getAccountInfoSync.call(spawnContext);
15
+ ns.getMenuButtonBoundingClientRect = () => getMenuButtonBoundingClientRect.call(spawnContext);
16
+ }
17
+ const globalScope = globalThis;
18
+ patchNamespace(globalScope.wx);
19
+ patchNamespace(globalScope.dd);
20
+ patchNamespace(globalScope.qd);
@@ -0,0 +1,8 @@
1
+ export function getMenuCapsuleRect(platform, statusBarHeight, windowWidth) {
2
+ const width = platform === 'ios' ? 87 : 95;
3
+ const height = 32;
4
+ const top = statusBarHeight + (platform === 'ios' ? 4 : 6);
5
+ const right = platform === 'ios' ? 7 : 10;
6
+ const left = windowWidth - right - width;
7
+ return { width, height, top, right, bottom: top + height, left };
8
+ }
@@ -0,0 +1,16 @@
1
+ import { getMenuCapsuleRect } from './menu-button-geometry.js';
2
+ /**
3
+ * wx.getMenuButtonBoundingClientRect() — synchronous, returns the WeChat
4
+ * capsule geometry. iOS: width 87, Android: width 95, height 32, top =
5
+ * statusBarHeight + (4|6), right = (7|10). See navigation-bar spec.
6
+ *
7
+ * Pulls platform + dimensions from spawn-time host env snapshot (delivered
8
+ * via `?hostEnv=` URL query, see service-host/preload.cjs).
9
+ */
10
+ export function getMenuButtonBoundingClientRect() {
11
+ const snapshot = this.hostEnvSnapshot ?? {};
12
+ const platform = snapshot.platform === 'android' ? 'android' : 'ios';
13
+ const windowWidth = typeof snapshot.windowWidth === 'number' ? snapshot.windowWidth : 390;
14
+ const statusBarHeight = typeof snapshot.statusBarHeight === 'number' ? snapshot.statusBarHeight : 44;
15
+ return getMenuCapsuleRect(platform, statusBarHeight, windowWidth);
16
+ }
@@ -0,0 +1,50 @@
1
+ function requireKey(key) {
2
+ if (!key)
3
+ throw new Error('[service-host] storage key is required');
4
+ return key;
5
+ }
6
+ function storageKey(ctx, key) {
7
+ return `${ctx.appId ?? ''}_${requireKey(key)}`;
8
+ }
9
+ export function setStorageSync({ key, data }) {
10
+ const dataString = typeof data === 'object' ? JSON.stringify(data) : String(data);
11
+ localStorage.setItem(storageKey(this, key), dataString);
12
+ }
13
+ export function getStorageSync({ key }) {
14
+ const raw = localStorage.getItem(storageKey(this, key));
15
+ if (raw === null)
16
+ return { data: '' };
17
+ try {
18
+ return { data: JSON.parse(raw) };
19
+ }
20
+ catch {
21
+ return { data: raw };
22
+ }
23
+ }
24
+ export function removeStorageSync({ key }) {
25
+ localStorage.removeItem(storageKey(this, key));
26
+ }
27
+ export function clearStorageSync() {
28
+ const prefix = `${this.appId ?? ''}_`;
29
+ const keysToRemove = [];
30
+ for (let i = 0; i < localStorage.length; i++) {
31
+ const key = localStorage.key(i);
32
+ if (key && key.startsWith(prefix))
33
+ keysToRemove.push(key);
34
+ }
35
+ keysToRemove.forEach(key => localStorage.removeItem(key));
36
+ }
37
+ export function getStorageInfoSync() {
38
+ const prefix = `${this.appId ?? ''}_`;
39
+ const keys = [];
40
+ let currentSize = 0;
41
+ for (let i = 0; i < localStorage.length; i++) {
42
+ const fullKey = localStorage.key(i);
43
+ if (fullKey && fullKey.startsWith(prefix)) {
44
+ keys.push(fullKey.substring(prefix.length));
45
+ const item = localStorage.getItem(fullKey);
46
+ currentSize += item ? item.length * 2 : 0;
47
+ }
48
+ }
49
+ return { keys, currentSize, limitSize: 10 * 1024 * 1024 };
50
+ }
@@ -0,0 +1,54 @@
1
+ export function getSystemInfoSync() {
2
+ const snapshot = this.hostEnvSnapshot ?? {};
3
+ const screenWidth = numberOr(snapshot.screenWidth, globalThis.screen?.width, 390);
4
+ const screenHeight = numberOr(snapshot.screenHeight, globalThis.screen?.height, 844);
5
+ const windowWidth = numberOr(snapshot.windowWidth, globalThis.innerWidth, screenWidth);
6
+ const windowHeight = numberOr(snapshot.windowHeight, globalThis.innerHeight, screenHeight);
7
+ const statusBarHeight = numberOr(snapshot.statusBarHeight, 0);
8
+ const safeAreaBottom = windowHeight;
9
+ return {
10
+ brand: stringOr(snapshot.brand, 'devtools'),
11
+ model: stringOr(snapshot.model, 'devtools'),
12
+ pixelRatio: numberOr(snapshot.pixelRatio, globalThis.devicePixelRatio, 2),
13
+ screenWidth,
14
+ screenHeight,
15
+ windowWidth,
16
+ windowHeight,
17
+ statusBarHeight,
18
+ language: stringOr(snapshot.language, navigator.language || 'zh_CN'),
19
+ version: stringOr(snapshot.version, '8.0.5'),
20
+ system: stringOr(snapshot.system, navigator.userAgent || 'iOS 16.0'),
21
+ platform: stringOr(snapshot.platform, navigator.platform || 'ios'),
22
+ fontSizeSetting: 16,
23
+ SDKVersion: stringOr(snapshot.SDKVersion, '3.0.0'),
24
+ deviceOrientation: 'portrait',
25
+ theme: stringOr(snapshot.theme, globalThis.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'),
26
+ safeArea: {
27
+ width: windowWidth,
28
+ height: windowHeight - statusBarHeight,
29
+ top: statusBarHeight,
30
+ bottom: safeAreaBottom,
31
+ left: 0,
32
+ right: windowWidth,
33
+ },
34
+ };
35
+ }
36
+ export function getAccountInfoSync() {
37
+ return {
38
+ miniProgram: {
39
+ appId: this.appId ?? '',
40
+ envVersion: 'develop',
41
+ version: '',
42
+ },
43
+ };
44
+ }
45
+ function stringOr(value, fallback) {
46
+ return typeof value === 'string' && value.length > 0 ? value : fallback;
47
+ }
48
+ function numberOr(...values) {
49
+ for (const value of values) {
50
+ if (typeof value === 'number' && Number.isFinite(value))
51
+ return value;
52
+ }
53
+ return 0;
54
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Framework-agnostic AppData accumulator.
3
+ *
4
+ * The dimina runtime emits two service→render messages relevant to the AppData
5
+ * panel, identical in shape on BOTH container paths:
6
+ * • update batches `{type:'ub', body:{bridgeId, updates:[{moduleId,data}]}}`
7
+ * — each `data` is a partial setData patch.
8
+ * • instance init: `type === 'page_*'`, body `{bridgeId, path, data}` with the
9
+ * COMPLETE initial state.
10
+ *
11
+ * Default (dimina-fe) path: the simulator preload sniffs these as Worker
12
+ * `message` events (app-data.ts). Native-host path: they flow service→render
13
+ * through bridge-router (SERVICE_PUBLISH). Both feed this one accumulator so the
14
+ * decode/merge/page-only/R6 policy can't drift between modes.
15
+ */
16
+ /**
17
+ * The AppData snapshot — the full, cumulative panel state.
18
+ *
19
+ * - `bridges` lists every page bridge in chronological (insertion) order, each
20
+ * carrying its page route (`pagePath`), so renderer tabs render in a stable
21
+ * sequence.
22
+ * - `entries` maps `bridgeId → (componentPath | moduleId) → setData state`.
23
+ */
24
+ export interface AppDataSnapshot {
25
+ bridges: Array<{
26
+ id: string;
27
+ pagePath: string | null;
28
+ }>;
29
+ entries: Record<string, Record<string, unknown>>;
30
+ }
31
+ export type DecodedEntry = {
32
+ mode: 'patch';
33
+ bridgeId: string;
34
+ moduleId: string;
35
+ data: unknown;
36
+ } | {
37
+ mode: 'init';
38
+ bridgeId: string;
39
+ moduleId: string;
40
+ componentPath: string;
41
+ data: Record<string, unknown>;
42
+ };
43
+ /** Normalized input to the accumulator (built from a DecodedEntry or the hook). */
44
+ export interface AppDataInput {
45
+ bridgeId?: string;
46
+ moduleId?: string;
47
+ componentPath?: string;
48
+ data?: unknown;
49
+ mode?: 'init' | 'patch';
50
+ }
51
+ /**
52
+ * Decode a service→render message into AppData entries, or null when it is not
53
+ * AppData-relevant. Policy: surface PAGE entries only — component entries are
54
+ * dropped (they sometimes flow on a bridge id distinct from their owning page's
55
+ * and never receive pageUnload, which would manifest as ghost tabs).
56
+ */
57
+ export declare function decodeWorkerMessage(message: unknown): DecodedEntry[] | null;
58
+ /** main→worker direction: container signals page teardown so cache can evict. */
59
+ export declare function decodeOutgoingMessage(message: unknown): {
60
+ type: string;
61
+ bridgeId?: string;
62
+ } | null;
63
+ /** Convert a decoded entry to the normalized accumulator input. */
64
+ export declare function decodedToInput(entry: DecodedEntry): AppDataInput;
65
+ /**
66
+ * Cumulative per-(bridgeId, moduleId) setData state. Pure data structure — no
67
+ * Worker / IPC / DOM. Callers own transport (publish/emit) and the automation
68
+ * mirror.
69
+ */
70
+ export declare class AppDataAccumulator {
71
+ private readonly cache;
72
+ private readonly bridgeOrder;
73
+ private readonly bridgePagePath;
74
+ private recordBridge;
75
+ /**
76
+ * Apply one entry. Returns true if it was accepted (a mutation worth
77
+ * republishing), false if dropped (missing ids, or the R6 gate).
78
+ */
79
+ apply(input: AppDataInput): boolean;
80
+ /** Evict every entry for a bridge (page teardown). */
81
+ clearBridge(bridgeId: string): void;
82
+ /** The full cumulative snapshot for the panel. */
83
+ snapshot(): AppDataSnapshot;
84
+ /**
85
+ * The current reactive page state for a bridge: shallow-merge of `entry.data`
86
+ * across every cache entry whose key starts with `${bridgeId}/`, in insertion
87
+ * order (later entries win on key conflicts). `{}` when no entries match
88
+ * (unknown bridge / after clearBridge). Pure, no side effects.
89
+ */
90
+ pageData(bridgeId: string): Record<string, unknown>;
91
+ /** Flat `key → data` map for the `__simulatorData.getAppdata()` mirror. */
92
+ flat(): Record<string, unknown>;
93
+ clear(): void;
94
+ }
95
+ //# sourceMappingURL=appdata-accumulator.d.ts.map