@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.
- package/README.md +49 -59
- package/dist/main/api.d.ts +1 -2
- package/dist/main/api.js +5 -1
- package/dist/main/app/app.d.ts +15 -5
- package/dist/main/app/app.js +249 -122
- package/dist/main/app/bootstrap.d.ts +16 -0
- package/dist/main/app/bootstrap.js +20 -0
- package/dist/main/app/launch.d.ts +8 -4
- package/dist/main/app/launch.js +9 -4
- package/dist/main/index.bundle.js +6071 -1863
- package/dist/main/index.js +9 -1
- package/dist/main/ipc/app.d.ts +1 -1
- package/dist/main/ipc/bridge-router.d.ts +61 -0
- package/dist/main/ipc/bridge-router.js +1333 -0
- package/dist/main/ipc/panels.d.ts +1 -1
- package/dist/main/ipc/panels.js +6 -2
- package/dist/main/ipc/popover.d.ts +1 -1
- package/dist/main/ipc/project-fs.d.ts +1 -1
- package/dist/main/ipc/projects.d.ts +1 -1
- package/dist/main/ipc/session.d.ts +1 -1
- package/dist/main/ipc/settings.d.ts +1 -1
- package/dist/main/ipc/simulator-module.d.ts +6 -0
- package/dist/main/ipc/simulator-module.js +9 -1
- package/dist/main/ipc/simulator.d.ts +2 -2
- package/dist/main/ipc/simulator.js +29 -5
- package/dist/main/ipc/toolbar.d.ts +1 -1
- package/dist/main/ipc/views.d.ts +1 -1
- package/dist/main/ipc/views.js +40 -2
- package/dist/main/runtime/devtools-backend.d.ts +17 -0
- package/dist/main/runtime/devtools-backend.js +49 -0
- package/dist/main/runtime/miniapp-runtime.d.ts +39 -0
- package/dist/main/runtime/miniapp-runtime.js +17 -0
- package/dist/main/services/automation/exec.d.ts +27 -2
- package/dist/main/services/automation/exec.js +37 -3
- package/dist/main/services/automation/handlers/app.js +127 -11
- package/dist/main/services/automation/handlers/page.js +36 -19
- package/dist/main/services/automation/index.js +40 -13
- package/dist/main/services/automation/wait-active-page.d.ts +56 -0
- package/dist/main/services/automation/wait-active-page.js +71 -0
- package/dist/main/services/console-forward/index.d.ts +36 -0
- package/dist/main/services/console-forward/index.js +81 -0
- package/dist/main/services/dimina-resource-server.d.ts +7 -0
- package/dist/main/services/dimina-resource-server.js +99 -0
- package/dist/main/services/elements-forward/index.d.ts +66 -0
- package/dist/main/services/elements-forward/index.js +583 -0
- package/dist/main/services/layout/index.d.ts +22 -0
- package/dist/main/services/layout/index.js +25 -0
- package/dist/main/services/mcp/index.d.ts +1 -0
- package/dist/main/services/mcp/index.js +3 -0
- package/dist/main/services/mcp/server.d.ts +1 -1
- package/dist/main/services/mcp/server.js +1 -1
- package/dist/main/services/mcp/target-manager.d.ts +35 -0
- package/dist/main/services/mcp/target-manager.js +63 -1
- package/dist/main/services/mcp/tools/context-tools.js +15 -1
- package/dist/main/services/module.d.ts +1 -1
- package/dist/main/services/network-forward/index.d.ts +190 -0
- package/dist/main/services/network-forward/index.js +765 -0
- package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
- package/dist/main/services/notifications/renderer-notifier.js +7 -1
- package/dist/main/services/render-inspect/index.d.ts +41 -0
- package/dist/main/services/render-inspect/index.js +88 -0
- package/dist/main/services/safe-area/index.d.ts +17 -0
- package/dist/main/services/safe-area/index.js +59 -0
- package/dist/main/services/service-host-pool/pool.d.ts +197 -0
- package/dist/main/services/service-host-pool/pool.js +364 -0
- package/dist/main/services/simulator/custom-apis.d.ts +34 -0
- package/dist/main/services/simulator/custom-apis.js +22 -0
- package/dist/main/services/simulator-appdata/index.d.ts +35 -0
- package/dist/main/services/simulator-appdata/index.js +71 -0
- package/dist/main/services/simulator-current-page/index.d.ts +24 -0
- package/dist/main/services/simulator-current-page/index.js +19 -0
- package/dist/main/services/simulator-storage/index.d.ts +37 -2
- package/dist/main/services/simulator-storage/index.js +209 -32
- package/dist/main/services/simulator-storage/service-storage-ops.d.ts +40 -0
- package/dist/main/services/simulator-storage/service-storage-ops.js +67 -0
- package/dist/main/services/simulator-temp-files/index.d.ts +1 -1
- package/dist/main/services/simulator-temp-files/index.js +39 -17
- package/dist/main/services/simulator-wxml/index.d.ts +29 -0
- package/dist/main/services/simulator-wxml/index.js +28 -0
- package/dist/main/services/toolbar/toolbar-store.d.ts +3 -3
- package/dist/main/services/toolbar/toolbar-store.js +1 -18
- package/dist/main/services/views/devtools-tabs.d.ts +47 -0
- package/dist/main/services/views/devtools-tabs.js +95 -0
- package/dist/main/services/views/miniapp-partition.d.ts +80 -0
- package/dist/main/services/views/miniapp-partition.js +138 -0
- package/dist/main/services/views/simulator-session-policy.d.ts +28 -0
- package/dist/main/services/views/simulator-session-policy.js +82 -0
- package/dist/main/services/views/view-manager.d.ts +125 -0
- package/dist/main/services/views/view-manager.js +852 -4
- package/dist/main/services/workbench-context.d.ts +67 -7
- package/dist/main/services/workbench-context.js +6 -1
- package/dist/main/services/workspace/workspace-service.js +7 -13
- package/dist/main/utils/ipc-registry.d.ts +1 -1
- package/dist/main/utils/ipc-registry.js +21 -4
- package/dist/main/utils/paths.d.ts +15 -0
- package/dist/main/utils/paths.js +19 -0
- package/dist/main/utils/sender-policy.d.ts +9 -3
- package/dist/main/utils/sender-policy.js +18 -4
- package/dist/main/utils/theme.d.ts +1 -1
- package/dist/main/utils/theme.js +1 -1
- package/dist/main/windows/main-window/create.d.ts +0 -6
- package/dist/main/windows/main-window/create.js +6 -80
- package/dist/main/windows/main-window/events.d.ts +1 -1
- package/dist/main/windows/main-window/events.js +1 -1
- package/dist/main/windows/service-host-window/create.d.ts +67 -0
- package/dist/main/windows/service-host-window/create.js +138 -0
- package/dist/native-host/common/common.js +368 -0
- package/dist/native-host/container/pageFrame.css +1 -0
- package/dist/native-host/render/render.js +9334 -0
- package/dist/native-host/service/service.js +6 -0
- package/dist/preload/index.d.ts +2 -0
- package/dist/preload/index.js +6 -0
- package/dist/preload/instrumentation/app-data.d.ts +18 -20
- package/dist/preload/instrumentation/app-data.js +23 -160
- package/dist/preload/instrumentation/wxml-extract.d.ts +1 -1
- package/dist/preload/instrumentation/wxml-extract.js +1 -1
- package/dist/preload/runtime/bridge.d.ts +3 -8
- package/dist/preload/runtime/bridge.js +2 -32
- package/dist/preload/runtime/custom-apis.js +20 -17
- package/dist/preload/runtime/host-toolbar-advertiser.d.ts +27 -0
- package/dist/preload/runtime/host-toolbar-advertiser.js +55 -0
- package/dist/preload/runtime/main-api-runner.d.ts +9 -0
- package/dist/preload/runtime/main-api-runner.js +85 -0
- package/dist/preload/runtime/native-host.d.ts +43 -0
- package/dist/preload/runtime/native-host.js +83 -0
- package/dist/preload/shared/expose.d.ts +10 -5
- package/dist/preload/shared/expose.js +30 -12
- package/dist/preload/shared/sid-registry.d.ts +11 -0
- package/dist/preload/shared/sid-registry.js +38 -0
- package/dist/preload/windows/host-toolbar.cjs +161 -0
- package/dist/preload/windows/host-toolbar.cjs.map +7 -0
- package/dist/preload/windows/host-toolbar.d.ts +2 -0
- package/dist/preload/windows/host-toolbar.js +12 -0
- package/dist/preload/windows/main.cjs +1935 -0
- package/dist/preload/windows/main.cjs.map +4 -4
- package/dist/preload/windows/simulator.cjs +925 -0
- package/dist/preload/windows/simulator.cjs.map +7 -0
- package/dist/preload/windows/simulator.js +244 -574
- package/dist/render-host/pageFrame.html +29 -0
- package/dist/render-host/preload.cjs +154 -0
- package/dist/render-host/render-inspect.js +295 -0
- package/dist/renderer/assets/index-CcJKzatF.js +50 -0
- package/dist/renderer/assets/{input-CCYS8Ave.js → input-QGx6FFX1.js} +2 -2
- package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
- package/dist/renderer/assets/{ipc-transport-Bn4KXvhu.js → ipc-transport-DvZvwK-Z.js} +2 -2
- package/dist/renderer/assets/{popover-CH4rwpdt.js → popover-BOH1If1J.js} +2 -2
- package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
- package/dist/renderer/assets/{settings-CMTB-t0x.js → settings-DpAbTJyF.js} +2 -2
- package/dist/renderer/assets/{settings-api-Csdngf9Z.js → settings-api-RD2IZF53.js} +2 -2
- package/dist/renderer/assets/{workbenchSettings-CODFCzOg.js → workbenchSettings-CNJX4Qna.js} +2 -2
- package/dist/renderer/entries/main/index.html +5 -5
- package/dist/renderer/entries/popover/index.html +5 -5
- package/dist/renderer/entries/settings/index.html +5 -5
- package/dist/renderer/entries/workbench-settings/index.html +4 -4
- package/dist/service-host/preload.cjs +254 -0
- package/dist/service-host/service.html +10 -0
- package/dist/service-host/sourcemap-rewrite.cjs +58 -0
- package/dist/service-host/sync-api-patch.js +20 -0
- package/dist/service-host/sync-impls/menu-button-geometry.js +8 -0
- package/dist/service-host/sync-impls/menu-button.js +16 -0
- package/dist/service-host/sync-impls/storage.js +50 -0
- package/dist/service-host/sync-impls/system-info.js +54 -0
- package/dist/shared/appdata-accumulator.d.ts +95 -0
- package/dist/shared/appdata-accumulator.js +213 -0
- package/dist/shared/bridge-channels.d.ts +378 -0
- package/dist/shared/bridge-channels.js +81 -0
- package/dist/shared/ipc-channels.d.ts +84 -1
- package/dist/shared/ipc-channels.js +90 -10
- package/dist/shared/ipc-schemas.d.ts +59 -2
- package/dist/shared/ipc-schemas.js +64 -3
- package/dist/shared/open-in-editor.d.ts +71 -0
- package/dist/shared/open-in-editor.js +138 -0
- package/dist/shared/simulator-api-metadata.d.ts +21 -0
- package/dist/shared/simulator-api-metadata.js +23 -0
- package/dist/shared/types.d.ts +2 -39
- package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
- package/dist/simulator/assets/device-shell-fH2cI-3q.js +2 -0
- package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
- package/dist/simulator/assets/simulator-DHylZf9Z.js +10 -0
- package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
- package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
- package/dist/simulator/simulator.html +2 -112
- package/package.json +12 -12
- package/dist/main/utils/disposable.d.ts +0 -18
- package/dist/main/utils/disposable.js +0 -67
- package/dist/renderer/assets/index-BDMxXUfn.js +0 -50
- package/dist/renderer/assets/ipc-transport-Cu7tubyg.css +0 -1
- package/dist/renderer/assets/select-Ct4-sijm.js +0 -2
- 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-
|
|
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-
|
|
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-
|
|
37
|
-
<link rel="modulepreload" crossorigin href="../../assets/select-
|
|
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-
|
|
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-
|
|
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-
|
|
14
|
-
<link rel="modulepreload" crossorigin href="../../assets/input-
|
|
15
|
-
<link rel="modulepreload" crossorigin href="../../assets/select-
|
|
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-
|
|
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-
|
|
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-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="../../assets/input-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="../../assets/settings-api-
|
|
13
|
-
<link rel="stylesheet" crossorigin href="../../assets/ipc-transport-
|
|
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-
|
|
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-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="../../assets/settings-api-
|
|
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-
|
|
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,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
|