@dimina-kit/devtools 0.4.0-dev.20260828161241 → 0.4.0-dev.20260907055341
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -729
- package/dist/main/app/app.d.ts +27 -7
- package/dist/main/app/app.js +285 -681
- package/dist/main/app/editor-view.d.ts +21 -0
- package/dist/main/app/editor-view.js +71 -0
- package/dist/main/app/global-mirrors.d.ts +23 -0
- package/dist/main/app/global-mirrors.js +37 -0
- package/dist/main/app/host-sidebar-default.d.ts +19 -0
- package/dist/main/app/host-sidebar-default.js +44 -0
- package/dist/main/app/menu-setup.d.ts +13 -0
- package/dist/main/app/menu-setup.js +49 -0
- package/dist/main/app/open-project-ipc.d.ts +13 -0
- package/dist/main/app/open-project-ipc.js +21 -0
- package/dist/main/app/project-list-surface.d.ts +31 -0
- package/dist/main/app/project-list-surface.js +20 -0
- package/dist/main/app/project-window.d.ts +36 -0
- package/dist/main/app/project-window.js +93 -0
- package/dist/main/app/servers.d.ts +17 -0
- package/dist/main/app/servers.js +60 -0
- package/dist/main/app/ui-extension-targets.d.ts +42 -0
- package/dist/main/app/ui-extension-targets.js +101 -0
- package/dist/main/app/window-close-reveal.harness.d.ts +34 -0
- package/dist/main/app/window-close-reveal.harness.js +65 -0
- package/dist/main/app/window-events.d.ts +15 -0
- package/dist/main/app/window-events.js +45 -0
- package/dist/main/app/window-runtime-services.d.ts +41 -0
- package/dist/main/app/window-runtime-services.js +178 -0
- package/dist/main/app/workbench-modules.d.ts +24 -0
- package/dist/main/app/workbench-modules.js +51 -0
- package/dist/main/app/workbench-window.d.ts +85 -0
- package/dist/main/app/workbench-window.js +310 -0
- package/dist/main/index.bundle.js +10669 -9096
- package/dist/main/ipc/app.d.ts +4 -1
- package/dist/main/ipc/app.js +4 -3
- package/dist/main/ipc/device-picker.d.ts +16 -0
- package/dist/main/ipc/device-picker.js +27 -0
- package/dist/main/ipc/index.d.ts +1 -0
- package/dist/main/ipc/index.js +1 -0
- package/dist/main/ipc/internal-devtools.d.ts +2 -1
- package/dist/main/ipc/internal-devtools.js +4 -3
- package/dist/main/ipc/popover.d.ts +4 -1
- package/dist/main/ipc/popover.js +25 -9
- package/dist/main/ipc/project-create.d.ts +2 -1
- package/dist/main/ipc/project-create.js +6 -5
- package/dist/main/ipc/project-fs.d.ts +3 -1
- package/dist/main/ipc/project-fs.js +17 -17
- package/dist/main/ipc/projects.d.ts +3 -3
- package/dist/main/ipc/projects.js +13 -12
- package/dist/main/ipc/session.d.ts +4 -1
- package/dist/main/ipc/session.js +16 -11
- package/dist/main/ipc/settings.d.ts +4 -1
- package/dist/main/ipc/settings.js +12 -19
- package/dist/main/ipc/simulator-module.d.ts +5 -0
- package/dist/main/ipc/simulator-module.js +9 -5
- package/dist/main/ipc/simulator.d.ts +4 -1
- package/dist/main/ipc/simulator.js +12 -18
- package/dist/main/ipc/tooltip.d.ts +2 -1
- package/dist/main/ipc/tooltip.js +8 -7
- package/dist/main/ipc/views.d.ts +4 -1
- package/dist/main/ipc/views.js +20 -9
- package/dist/main/runtime/devtools-backend-before-quit.harness.d.ts +2 -20
- package/dist/main/runtime/devtools-backend-before-quit.harness.js +14 -283
- package/dist/main/runtime/devtools-backend.js +14 -3
- package/dist/main/runtime/devtools-runtime-mock.harness.d.ts +21 -0
- package/dist/main/runtime/devtools-runtime-mock.harness.js +313 -0
- package/dist/main/services/app-services.d.ts +62 -0
- package/dist/main/services/app-services.js +64 -0
- package/dist/main/services/automation/connection-target.d.ts +36 -0
- package/dist/main/services/automation/connection-target.js +29 -0
- package/dist/main/services/automation/console-bridge.d.ts +28 -0
- package/dist/main/services/automation/console-bridge.js +91 -0
- package/dist/main/services/automation/handlers/app.js +4 -4
- package/dist/main/services/automation/handlers/element.js +55 -21
- package/dist/main/services/automation/index.d.ts +12 -1
- package/dist/main/services/automation/index.js +54 -133
- package/dist/main/services/default-adapter.js +1 -1
- package/dist/main/services/fs-bridge-protocol.d.ts +61 -0
- package/dist/main/services/fs-bridge-protocol.js +34 -0
- package/dist/main/services/fs-watch-sse.d.ts +8 -1
- package/dist/main/services/fs-watch-sse.js +19 -5
- package/dist/main/services/mcp/connection-owner.d.ts +38 -0
- package/dist/main/services/mcp/connection-owner.js +79 -0
- package/dist/main/services/mcp/index.d.ts +3 -1
- package/dist/main/services/mcp/index.js +4 -3
- package/dist/main/services/mcp/opened-project.d.ts +88 -0
- package/dist/main/services/mcp/opened-project.js +60 -0
- package/dist/main/services/mcp/target-manager.d.ts +71 -23
- package/dist/main/services/mcp/target-manager.js +269 -142
- package/dist/main/services/mcp/target-selection.d.ts +47 -0
- package/dist/main/services/mcp/target-selection.js +71 -0
- package/dist/main/services/mcp/tools/context-tools.js +20 -5
- package/dist/main/services/mcp/tools/project-tools.d.ts +29 -6
- package/dist/main/services/mcp/tools/project-tools.js +37 -25
- package/dist/main/services/module.d.ts +13 -5
- package/dist/main/services/notifications/renderer-notifier.d.ts +28 -4
- package/dist/main/services/notifications/renderer-notifier.js +15 -3
- package/dist/main/services/projects/local-provider.js +2 -0
- package/dist/main/services/projects/project-repository.d.ts +31 -1
- package/dist/main/services/projects/project-repository.js +144 -20
- package/dist/main/services/projects/types.d.ts +31 -8
- package/dist/main/services/safe-area/index.d.ts +19 -5
- package/dist/main/services/safe-area/index.js +38 -13
- package/dist/main/services/simulator/ui-extensions.d.ts +8 -0
- package/dist/main/services/simulator/ui-extensions.js +16 -6
- package/dist/main/services/simulator-storage/index.d.ts +12 -1
- package/dist/main/services/simulator-storage/index.js +22 -7
- package/dist/main/services/simulator-storage/window-scope.d.ts +20 -0
- package/dist/main/services/simulator-storage/window-scope.js +20 -0
- package/dist/main/services/views/host-slot-port-channel.d.ts +20 -3
- package/dist/main/services/views/host-slot-port-channel.js +33 -5
- package/dist/main/services/views/managed-web-contents-view.js +21 -1
- package/dist/main/services/views/native-simulator-view.js +13 -16
- package/dist/main/services/views/overlay-panels-view.d.ts +13 -0
- package/dist/main/services/views/overlay-panels-view.js +31 -0
- package/dist/main/services/views/view-manager.d.ts +1 -1
- package/dist/main/services/views/view-manager.js +3 -0
- package/dist/main/services/window-contexts/context-router.d.ts +36 -0
- package/dist/main/services/window-contexts/context-router.js +55 -0
- package/dist/main/services/workbench-coi-host.d.ts +52 -0
- package/dist/main/services/workbench-coi-host.js +227 -0
- package/dist/main/services/workbench-coi-server.js +75 -133
- package/dist/main/services/workbench-coi-shutdown.d.ts +40 -0
- package/dist/main/services/workbench-coi-shutdown.js +69 -0
- package/dist/main/services/workbench-coi-static.d.ts +23 -0
- package/dist/main/services/workbench-coi-static.js +87 -0
- package/dist/main/services/workbench-context.d.ts +27 -3
- package/dist/main/services/workbench-context.js +10 -5
- package/dist/main/services/workspace/compile-mode-adapter.d.ts +18 -0
- package/dist/main/services/workspace/compile-mode-adapter.js +57 -0
- package/dist/main/services/workspace/compile-mode-store.d.ts +25 -0
- package/dist/main/services/workspace/compile-mode-store.js +71 -0
- package/dist/main/services/workspace/workspace-compile-modes.d.ts +59 -0
- package/dist/main/services/workspace/workspace-compile-modes.js +93 -0
- package/dist/main/services/workspace/workspace-referer.d.ts +17 -0
- package/dist/main/services/workspace/workspace-referer.js +26 -0
- package/dist/main/services/workspace/workspace-service.d.ts +4 -0
- package/dist/main/services/workspace/workspace-service.js +51 -84
- package/dist/main/services/workspace/workspace-thumbnails.d.ts +22 -0
- package/dist/main/services/workspace/workspace-thumbnails.js +67 -0
- package/dist/main/utils/ipc-context-source.d.ts +40 -0
- package/dist/main/utils/ipc-context-source.js +23 -0
- package/dist/main/utils/ipc-registry.d.ts +42 -36
- package/dist/main/utils/ipc-registry.js +117 -50
- package/dist/main/utils/sender-policy.d.ts +9 -0
- package/dist/main/utils/sender-policy.js +26 -3
- package/dist/main/utils/theme.d.ts +3 -2
- package/dist/main/utils/theme.js +3 -2
- package/dist/main/windows/main-window/create.d.ts +16 -0
- package/dist/main/windows/main-window/create.js +19 -11
- package/dist/main/windows/main-window/events.d.ts +1 -1
- package/dist/main/windows/main-window/events.js +26 -13
- package/dist/main/windows/main-window/index.d.ts +1 -1
- package/dist/main/windows/main-window/index.js +1 -1
- package/dist/native-host/common/common.js +94 -73
- package/dist/native-host/render/render.js +4079 -3171
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/runtime/native-host.d.ts +4 -0
- package/dist/preload/runtime/temp-files.js +9 -2
- package/dist/preload/runtime/wait-for-slot-root.d.ts +7 -4
- package/dist/preload/runtime/wait-for-slot-root.js +36 -8
- package/dist/preload/windows/host-dialog-runtime.cjs +10 -3
- package/dist/preload/windows/host-dialog-runtime.cjs.map +2 -2
- package/dist/preload/windows/host-sidebar-runtime.cjs +10 -3
- package/dist/preload/windows/host-sidebar-runtime.cjs.map +2 -2
- package/dist/preload/windows/host-toolbar-runtime.cjs +10 -3
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs +181 -4
- package/dist/preload/windows/main.cjs.map +4 -4
- package/dist/preload/windows/simulator.cjs +10 -0
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +10 -0
- package/dist/render-host/pageFrame.html +1 -1
- package/dist/render-host/preload.cjs +16 -4
- package/dist/renderer/assets/button-CB2MWjHY.js +2 -0
- package/dist/renderer/assets/constants-CkoGPQTS.js +2 -0
- package/dist/renderer/assets/constants-zQZ2-y21.js +2 -0
- package/dist/renderer/assets/{createLucideIcon-Bqi8hpdi.js → createLucideIcon-cZ9FlZZw.js} +2 -2
- package/dist/renderer/assets/devicePicker-H2eIO4e1.js +2 -0
- package/dist/renderer/assets/dialog-pHzEA8Vx.js +46 -0
- package/dist/renderer/assets/dist-B5HADirS.js +2 -0
- package/dist/renderer/assets/{dist-DKWdE1TK.js → dist-DIFlRMKe.js} +2 -2
- package/dist/renderer/assets/hostSidebarDefault-DRWh6OCt.js +2 -0
- package/dist/renderer/assets/index-CEL_XFge.js +2 -0
- package/dist/renderer/assets/{input-Ct3alvkq.js → input-CAObw95L.js} +2 -2
- package/dist/renderer/assets/ipc-channels-overlays-gIPUFnqc.js +2 -0
- package/dist/renderer/assets/jsx-runtime-DICEQH_0.css +1 -0
- package/dist/renderer/assets/{jsx-runtime-DGLHmmOq.js → jsx-runtime-DIw5wnYl.js} +1 -1
- package/dist/renderer/assets/plus-BQ9u5EbL.js +2 -0
- package/dist/renderer/assets/popover-Cw7G2Ctp.js +2 -0
- package/dist/renderer/assets/presets-DMZOb9ay.js +2 -0
- package/dist/renderer/assets/project-api-YTOr_Yvo.js +2 -0
- package/dist/renderer/assets/{projectCreateDialog-Bbjz75bP.js → projectCreateDialog-BmLqiYxn.js} +2 -2
- package/dist/renderer/assets/search-BMvuYF48.js +2 -0
- package/dist/renderer/assets/select-nFP95TxM.js +2 -0
- package/dist/renderer/assets/settings-CnpVfSWt.js +2 -0
- package/dist/renderer/assets/settings-api-Ccsf-Nsj.js +2 -0
- package/dist/renderer/assets/settings-tab-bar-CAzrv32m.js +2 -0
- package/dist/renderer/assets/smartphone-Bb2GdIKy.js +2 -0
- package/dist/renderer/assets/tabs-CPKN3Mmq.js +2 -0
- package/dist/renderer/assets/{tooltip-B_-_YVbw.js → tooltip-D6AxXRk5.js} +2 -2
- package/dist/renderer/assets/types-Bh0hA7El.js +2 -0
- package/dist/renderer/assets/updateDialog-CwndJ0Bl.js +2 -0
- package/dist/renderer/assets/{utils-kfQov6Pa.js → utils-sEB5OZEQ.js} +2 -2
- package/dist/renderer/assets/view-api-B-2zPBR5.js +2 -0
- package/dist/renderer/assets/view-ids-BfaDVV5P.js +2 -0
- package/dist/renderer/assets/workbench-BLJ0wKsg.js +5 -0
- package/dist/renderer/assets/{workbenchSettings-CV4LVA9b.js → workbenchSettings-YD0Ctbm_.js} +3 -3
- package/dist/renderer/entries/device-picker/index.html +28 -0
- package/dist/renderer/entries/host-sidebar-default/index.html +6 -5
- package/dist/renderer/entries/main/index.html +16 -17
- package/dist/renderer/entries/popover/index.html +16 -10
- package/dist/renderer/entries/project-create-dialog/index.html +12 -12
- package/dist/renderer/entries/settings/index.html +10 -10
- package/dist/renderer/entries/tooltip/index.html +5 -5
- package/dist/renderer/entries/update-dialog/index.html +10 -10
- package/dist/renderer/entries/workbench/index.html +49 -0
- package/dist/renderer/entries/workbench-settings/index.html +12 -11
- package/dist/service-host/host-env-update.cjs +23 -0
- package/dist/service-host/preload.cjs +24 -49
- package/dist/service-host/service-message-queue.cjs +71 -0
- package/dist/service-host/sync-impls/system-info.js +31 -9
- package/dist/shared/compile-mode-state.d.ts +73 -0
- package/dist/shared/compile-mode-state.js +100 -0
- package/dist/shared/compile-modes.d.ts +152 -0
- package/dist/shared/compile-modes.js +237 -0
- package/dist/shared/ipc-channels-overlays.d.ts +8 -2
- package/dist/shared/ipc-channels-overlays.js +19 -2
- package/dist/shared/ipc-channels.d.ts +5 -10
- package/dist/shared/ipc-channels.js +17 -14
- package/dist/shared/ipc-schemas.d.ts +76 -24
- package/dist/shared/ipc-schemas.js +55 -10
- package/dist/shared/project-window-types.d.ts +42 -0
- package/dist/shared/project-window-types.js +2 -0
- package/dist/shared/types.d.ts +43 -17
- package/dist/shared/view-ids.d.ts +1 -0
- package/dist/shared/view-ids.js +3 -1
- package/dist/simulator/assets/bridge-channels-B3JAmRfl.js +2 -0
- package/dist/simulator/assets/device-shell-ATEhHV2_.css +1 -0
- package/dist/simulator/assets/device-shell-pxnZZp10.js +431 -0
- package/dist/simulator/assets/simulator-Dwp7lnvu.js +10 -0
- package/dist/simulator/assets/simulator-mini-app-DFo7fhi5.js +2 -0
- package/dist/simulator/assets/simulator-ui-B2ddJB1R.js +2 -0
- package/dist/simulator/simulator.html +3 -3
- package/dist/simulator/temp-files.d.ts +6 -0
- package/dist/simulator/temp-files.js +46 -4
- package/dist/simulator/types.d.ts +7 -0
- package/dist/vscode-workbench/assets/__vite-browser-external-JIkWewFf.js +1 -0
- package/dist/vscode-workbench/assets/{dist-CMfmHflW.js → dist-CXG-u1VB.js} +3 -3
- package/dist/vscode-workbench/assets/{iconv-lite-umd-Bx8CgaZq.js → iconv-lite-umd-Dxx9Qyb4.js} +1 -1
- package/dist/vscode-workbench/assets/{index-CdG6YWhW.js → index-6VJMsaWj.js} +460 -460
- package/dist/vscode-workbench/assets/{jschardet-M0qgd2lN.js → jschardet-Ba3D16vt.js} +1 -1
- package/dist/vscode-workbench/index.html +1 -1
- package/package.json +11 -8
- package/dist/renderer/assets/button-D5Q2wkXq.js +0 -2
- package/dist/renderer/assets/constants-D7DfVqMp.js +0 -2
- package/dist/renderer/assets/constants-D8zsejFq.js +0 -2
- package/dist/renderer/assets/dialog-e1TecTOY.js +0 -46
- package/dist/renderer/assets/hostSidebarDefault-B3yLfy8j.js +0 -2
- package/dist/renderer/assets/index-CsPD68N_.js +0 -5
- package/dist/renderer/assets/ipc-channels-overlays-LsDzGAtV.js +0 -2
- package/dist/renderer/assets/jsx-runtime-2vXHouwr.css +0 -1
- package/dist/renderer/assets/popover-Dix5cm_b.js +0 -2
- package/dist/renderer/assets/project-api-k7Oq9iaq.js +0 -2
- package/dist/renderer/assets/select-acGb0AmJ.js +0 -2
- package/dist/renderer/assets/settings-CQrTMr43.js +0 -2
- package/dist/renderer/assets/settings-api-CrUQ9rYV.js +0 -2
- package/dist/renderer/assets/settings-tab-bar-Cw1kVIf2.js +0 -2
- package/dist/renderer/assets/types-CsEKtFyr.js +0 -2
- package/dist/renderer/assets/updateDialog-NsF8223A.js +0 -2
- package/dist/renderer/assets/view-api-CLn3rcQE.js +0 -2
- package/dist/simulator/assets/bridge-channels-zhsumfky.js +0 -2
- package/dist/simulator/assets/device-shell-CmtM1QxP.js +0 -2
- package/dist/simulator/assets/device-shell-iFZo1igL.css +0 -1
- package/dist/simulator/assets/simulator-CIobn3Mh.js +0 -10
- package/dist/simulator/assets/simulator-mini-app-CRe6n9br.js +0 -2
- package/dist/simulator/assets/simulator-ui-C_cP602X.js +0 -2
- package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +0 -1
|
@@ -1,41 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SimulatorChannel, SimulatorCustomApiChannel } from '../../shared/ipc-channels.js';
|
|
2
2
|
import { SimulatorAttachNativeSchema, SimulatorCustomApiInvokeSchema, SimulatorSetDeviceInfoSchema, SimulatorSoftReloadSchema, } from '../../shared/ipc-schemas.js';
|
|
3
|
-
import { deviceInfoToHostEnv } from '../../shared/bridge-channels.js';
|
|
4
3
|
import { validate } from '../utils/ipc-schema.js';
|
|
5
4
|
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import { toIpcContextSource } from '../utils/ipc-context-source.js';
|
|
6
|
+
export function registerSimulatorIpc(input) {
|
|
7
|
+
return new IpcRegistry(toIpcContextSource(input))
|
|
8
|
+
.handleRouted(SimulatorChannel.AttachNative, (ctx, _e, ...args) => {
|
|
9
9
|
const [simulatorUrl, simWidth] = validate(SimulatorChannel.AttachNative, SimulatorAttachNativeSchema, args);
|
|
10
10
|
return ctx.views.attachNativeSimulator(simulatorUrl, simWidth);
|
|
11
11
|
})
|
|
12
|
-
.
|
|
12
|
+
.handleRouted(SimulatorChannel.SoftReload, (ctx, _e, ...args) => {
|
|
13
13
|
const [simulatorUrl] = validate(SimulatorChannel.SoftReload, SimulatorSoftReloadSchema, args);
|
|
14
14
|
return ctx.views.softReloadNativeSimulator(simulatorUrl);
|
|
15
15
|
})
|
|
16
|
-
.
|
|
16
|
+
.handleRouted(SimulatorChannel.Detach, (ctx) => {
|
|
17
17
|
ctx.views.detachSimulator();
|
|
18
18
|
})
|
|
19
|
-
.
|
|
19
|
+
.handleRouted(SimulatorChannel.SetDeviceInfo, (ctx, _e, ...args) => {
|
|
20
20
|
const [device] = validate(SimulatorChannel.SetDeviceInfo, SimulatorSetDeviceInfoSchema, args);
|
|
21
21
|
// Cache the selection (rides the next NATIVE_HOST_ENABLED reply for a
|
|
22
22
|
// race-free DeviceShell init) and push DEVICE_CHANGE to the live simulator
|
|
23
23
|
// WCV so the DeviceShell resizes the bezel + re-renders status bar / notch.
|
|
24
|
+
// `setDevice` also pushes `hostEnvUpdate` + `pageResize` to every running
|
|
25
|
+
// service host, so `wx.getSystemInfoSync()` and `Page.onResize` follow
|
|
26
|
+
// the selection without a relaunch.
|
|
24
27
|
ctx.bridge?.setDevice(device);
|
|
25
28
|
// Re-push the CSS env(safe-area-inset-*) override to attached render-host
|
|
26
29
|
// guests so notch-aware page layout updates without a reload.
|
|
27
30
|
ctx.views.reapplySafeArea(device);
|
|
28
|
-
// Live-update the running service-host window's host-env snapshot so
|
|
29
|
-
// `wx.getSystemInfoSync()` reflects the selected device without a relaunch.
|
|
30
|
-
// The service-host preload mutates `__diminaSpawnContext` in place;
|
|
31
|
-
// `getSystemInfoSync` reads it fresh on each call. No service window yet
|
|
32
|
-
// (pre-spawn) → no-op.
|
|
33
|
-
const serviceWc = ctx.bridge?.getServiceWc();
|
|
34
|
-
if (serviceWc && !serviceWc.isDestroyed()) {
|
|
35
|
-
serviceWc.send(ServiceHostChannel.HostEnvUpdate, deviceInfoToHostEnv(device));
|
|
36
|
-
}
|
|
37
31
|
})
|
|
38
|
-
.
|
|
32
|
+
.handleRouted(SimulatorCustomApiChannel.Invoke, (ctx, _e, ...args) => {
|
|
39
33
|
const [name, params] = validate(SimulatorCustomApiChannel.Invoke, SimulatorCustomApiInvokeSchema, args);
|
|
40
34
|
return ctx.simulatorApis.invoke(name, params);
|
|
41
35
|
});
|
|
@@ -2,12 +2,13 @@ import type { WorkbenchModule } from '../services/module.js';
|
|
|
2
2
|
import type { ViewManager } from '../services/views/view-manager.js';
|
|
3
3
|
import type { Disposable } from '@dimina-kit/electron-deck/main';
|
|
4
4
|
import { type SenderPolicy } from '../utils/ipc-registry.js';
|
|
5
|
+
import { type IpcInput } from '../utils/ipc-context-source.js';
|
|
5
6
|
/** Module-local narrow deps — deliberately NOT `Pick<WorkbenchContext, ...>`
|
|
6
7
|
* (the gate in eslint.config.* is shrink-only; see its message). */
|
|
7
8
|
export interface TooltipIpcDeps {
|
|
8
9
|
views: Pick<ViewManager, 'prepareTooltip' | 'showTooltip' | 'hideTooltip' | 'markOverlayReady' | 'applyTooltipMeasurement'>;
|
|
9
10
|
senderPolicy?: SenderPolicy;
|
|
10
11
|
}
|
|
11
|
-
export declare function registerTooltipIpc(
|
|
12
|
+
export declare function registerTooltipIpc(input: IpcInput<TooltipIpcDeps>): Disposable;
|
|
12
13
|
export declare const tooltipModule: WorkbenchModule;
|
|
13
14
|
//# sourceMappingURL=tooltip.d.ts.map
|
package/dist/main/ipc/tooltip.js
CHANGED
|
@@ -2,22 +2,23 @@ import { OverlayChannel, TooltipChannel } from '../../shared/ipc-channels-overla
|
|
|
2
2
|
import { TooltipMeasuredSchema, TooltipShowSchema } from '../../shared/ipc-schemas.js';
|
|
3
3
|
import { validate } from '../utils/ipc-schema.js';
|
|
4
4
|
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { toIpcContextSource } from '../utils/ipc-context-source.js';
|
|
6
|
+
export function registerTooltipIpc(input) {
|
|
7
|
+
return new IpcRegistry(toIpcContextSource(input))
|
|
8
|
+
.onRouted(TooltipChannel.Prepare, (ctx) => {
|
|
8
9
|
ctx.views.prepareTooltip();
|
|
9
10
|
})
|
|
10
|
-
.
|
|
11
|
+
.onRouted(TooltipChannel.Show, (ctx, _event, ...args) => {
|
|
11
12
|
const [data] = validate(TooltipChannel.Show, TooltipShowSchema, args);
|
|
12
13
|
ctx.views.showTooltip(data);
|
|
13
14
|
})
|
|
14
|
-
.
|
|
15
|
+
.onRouted(TooltipChannel.Hide, (ctx) => {
|
|
15
16
|
ctx.views.hideTooltip();
|
|
16
17
|
})
|
|
17
|
-
.
|
|
18
|
+
.onRouted(OverlayChannel.Ready, (ctx, event) => {
|
|
18
19
|
ctx.views.markOverlayReady(event.sender.id);
|
|
19
20
|
})
|
|
20
|
-
.
|
|
21
|
+
.onRouted(TooltipChannel.Measured, (ctx, event, ...args) => {
|
|
21
22
|
const [measurement] = validate(TooltipChannel.Measured, TooltipMeasuredSchema, args);
|
|
22
23
|
ctx.views.applyTooltipMeasurement(event.sender.id, measurement);
|
|
23
24
|
});
|
package/dist/main/ipc/views.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { WorkbenchContext } from '../services/workbench-context.js';
|
|
2
2
|
import type { Disposable } from '@dimina-kit/electron-deck/main';
|
|
3
|
+
import { type IpcInput } from '../utils/ipc-context-source.js';
|
|
4
|
+
type ViewsIpcCtx = Pick<WorkbenchContext, 'views' | 'senderPolicy'>;
|
|
3
5
|
/**
|
|
4
6
|
* Renderer-driven overlay bounds, plus the renderer bootstrap's
|
|
5
7
|
* placement-generation seed pull.
|
|
@@ -29,5 +31,6 @@ import type { Disposable } from '@dimina-kit/electron-deck/main';
|
|
|
29
31
|
* disables it on the fatal boot-failure page, or leave placement silently
|
|
30
32
|
* non-functional. See disabled-module.test.ts for the end-to-end guard.
|
|
31
33
|
*/
|
|
32
|
-
export declare function registerViewsIpc(
|
|
34
|
+
export declare function registerViewsIpc(input: IpcInput<ViewsIpcCtx>): Disposable;
|
|
35
|
+
export {};
|
|
33
36
|
//# sourceMappingURL=views.d.ts.map
|
package/dist/main/ipc/views.js
CHANGED
|
@@ -3,6 +3,7 @@ import { ViewChannel } from '../../shared/ipc-channels-overlays.js';
|
|
|
3
3
|
import { PlacementSnapshotSchema, HostToolbarAdvertiseHeightSchema, HostSidebarAdvertiseWidthSchema, HostDialogAdvertiseSizeSchema, } from '../../shared/ipc-schemas.js';
|
|
4
4
|
import { validate } from '../utils/ipc-schema.js';
|
|
5
5
|
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
6
|
+
import { toIpcContextSource } from '../utils/ipc-context-source.js';
|
|
6
7
|
/**
|
|
7
8
|
* Renderer-driven overlay bounds, plus the renderer bootstrap's
|
|
8
9
|
* placement-generation seed pull.
|
|
@@ -32,16 +33,23 @@ import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
|
32
33
|
* disables it on the fatal boot-failure page, or leave placement silently
|
|
33
34
|
* non-functional. See disabled-module.test.ts for the end-to-end guard.
|
|
34
35
|
*/
|
|
35
|
-
export function registerViewsIpc(
|
|
36
|
-
const
|
|
36
|
+
export function registerViewsIpc(input) {
|
|
37
|
+
const source = toIpcContextSource(input);
|
|
38
|
+
// The raw listeners below trust an exact wc id, and each window mounts its
|
|
39
|
+
// own host slots — so the id itself names the owning window. Scanning the
|
|
40
|
+
// live contexts for the one whose slot holds this sender is both the trust
|
|
41
|
+
// gate and the routing decision; no match means the message came from
|
|
42
|
+
// somewhere that is not a host slot at all, and is dropped.
|
|
43
|
+
const ownerOfSlot = (event, slotWebContentsId) => source.list().find((ctx) => slotWebContentsId(ctx) === event.sender.id) ?? null;
|
|
44
|
+
const registry = new IpcRegistry(source)
|
|
37
45
|
// Renderer bootstrap: allocate this session's placement-generation seed
|
|
38
46
|
// (see renderer-placement-generation.ts / PlacementReconciler.allocateGeneration).
|
|
39
|
-
.
|
|
47
|
+
.handleRouted(ViewChannel.AllocatePlacementGeneration, (ctx) => ctx.views.allocatePlacementGeneration())
|
|
40
48
|
// Window-level placement snapshot: the single source of truth for every
|
|
41
49
|
// managed native view's bounds/visibility/z-order. The renderer's central
|
|
42
50
|
// publisher coalesces one snapshot per frame; the reconciler diffs it
|
|
43
51
|
// against the actual view tree. Supersedes the per-view bounds channels.
|
|
44
|
-
.
|
|
52
|
+
.handleRouted(ViewChannel.PlacementSnapshot, (ctx, _event, ...args) => {
|
|
45
53
|
const [snapshot] = validate(ViewChannel.PlacementSnapshot, PlacementSnapshotSchema, args);
|
|
46
54
|
ctx.views.setPlacementSnapshot(snapshot);
|
|
47
55
|
})
|
|
@@ -53,10 +61,10 @@ export function registerViewsIpc(ctx) {
|
|
|
53
61
|
// senderPolicy-gated registry as HostToolbarBounds: the toolbar WCV's
|
|
54
62
|
// arbitrary host content must not reach this — only the trusted main
|
|
55
63
|
// renderer pulls. Live delegation, not a registration-time snapshot.
|
|
56
|
-
.
|
|
64
|
+
.handleRouted(ViewChannel.HostToolbarGetHeight, (ctx) => ctx.views.getHostToolbarHeight())
|
|
57
65
|
// Same mount-time replay role as HostToolbarGetHeight, on the sidebar's
|
|
58
66
|
// inline (width) axis.
|
|
59
|
-
.
|
|
67
|
+
.handleRouted(ViewChannel.HostSidebarGetWidth, (ctx) => ctx.views.getHostSidebarWidth());
|
|
60
68
|
// Reverse size-advertiser: the toolbar WCV's OWN renderer sends this, and the
|
|
61
69
|
// host loads ARBITRARY content into that WCV. We DELIBERATELY do NOT add the
|
|
62
70
|
// toolbar wc to the global sender policy — that would trust it for ALL ~72
|
|
@@ -68,7 +76,8 @@ export function registerViewsIpc(ctx) {
|
|
|
68
76
|
// The host content can reach ONLY this one channel, carrying only a
|
|
69
77
|
// non-negative integer height.
|
|
70
78
|
const onAdvertiseHeight = (event, ...args) => {
|
|
71
|
-
|
|
79
|
+
const ctx = ownerOfSlot(event, (c) => c.views.getHostToolbarWebContentsId());
|
|
80
|
+
if (!ctx)
|
|
72
81
|
return;
|
|
73
82
|
let extent;
|
|
74
83
|
try {
|
|
@@ -84,7 +93,8 @@ export function registerViewsIpc(ctx) {
|
|
|
84
93
|
// Same precise-sender-id trust model as onAdvertiseHeight, on the
|
|
85
94
|
// sidebar's inline (width) axis.
|
|
86
95
|
const onAdvertiseWidth = (event, ...args) => {
|
|
87
|
-
|
|
96
|
+
const ctx = ownerOfSlot(event, (c) => c.views.getHostSidebarWebContentsId());
|
|
97
|
+
if (!ctx)
|
|
88
98
|
return;
|
|
89
99
|
let extent;
|
|
90
100
|
try {
|
|
@@ -102,7 +112,8 @@ export function registerViewsIpc(ctx) {
|
|
|
102
112
|
// slot: either axis may arrive, and the view manager re-centers using
|
|
103
113
|
// whichever axes it has measured so far.
|
|
104
114
|
const onAdvertiseDialogSize = (event, ...args) => {
|
|
105
|
-
|
|
115
|
+
const ctx = ownerOfSlot(event, (c) => c.views.getHostDialogWebContentsId());
|
|
116
|
+
if (!ctx)
|
|
106
117
|
return;
|
|
107
118
|
let axis;
|
|
108
119
|
let extent;
|
|
@@ -1,30 +1,12 @@
|
|
|
1
1
|
import type { WorkbenchAppConfig } from '../../shared/types.js';
|
|
2
2
|
import type { RuntimeBackend } from '@dimina-kit/electron-deck';
|
|
3
|
-
declare const stubs: {
|
|
4
|
-
handlers: Map<string, (...args: unknown[]) => unknown>;
|
|
5
|
-
projectsJsonPath: string;
|
|
6
|
-
getProjectsJson(): string | null;
|
|
7
|
-
setProjectsJson(v: string | null): void;
|
|
8
|
-
projectsWithAppJson: Set<string>;
|
|
9
|
-
makeEmitter: () => {
|
|
10
|
-
listeners: Record<string, Set<(...args: unknown[]) => unknown>>;
|
|
11
|
-
on(event: string, fn: (...args: unknown[]) => unknown): /*elided*/ any;
|
|
12
|
-
once(event: string, fn: (...args: unknown[]) => unknown): /*elided*/ any;
|
|
13
|
-
off(event: string, fn: (...args: unknown[]) => unknown): /*elided*/ any;
|
|
14
|
-
removeListener(event: string, fn: (...args: unknown[]) => unknown): /*elided*/ any;
|
|
15
|
-
emit(event: string, ...args: unknown[]): void;
|
|
16
|
-
};
|
|
17
|
-
reset: () => void;
|
|
18
|
-
};
|
|
19
|
-
declare const devkitStubs: {
|
|
20
|
-
sessionClose: import("vitest").Mock<() => Promise<void>>;
|
|
21
|
-
};
|
|
22
3
|
declare const viewManagerStubs: {
|
|
23
4
|
createdManagers: Array<{
|
|
24
5
|
disposeAll: () => void;
|
|
25
6
|
}>;
|
|
26
7
|
};
|
|
27
|
-
export { stubs, devkitStubs
|
|
8
|
+
export { stubs, devkitStubs } from './devtools-runtime-mock.harness.js';
|
|
9
|
+
export { viewManagerStubs };
|
|
28
10
|
/**
|
|
29
11
|
* Shared per-test setup both `devtools-backend-before-quit.test.ts` and
|
|
30
12
|
* `devtools-backend-shutdown-race.test.ts` need identically: reset modules
|
|
@@ -1,291 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared vitest mock harness for `devtools-backend-before-quit.test.ts` and
|
|
3
3
|
* `devtools-backend-shutdown-race.test.ts` — both drive the REAL
|
|
4
|
-
* `createDevtoolsBackend`/`createDevtoolsRuntime` against
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* mock setup between them.
|
|
4
|
+
* `createDevtoolsBackend`/`createDevtoolsRuntime` against the electron/fs/
|
|
5
|
+
* `@dimina-kit/devkit` mock set defined in `./devtools-runtime-mock.harness.ts`,
|
|
6
|
+
* plus the view-manager spy shim and backend-lifecycle helpers below that
|
|
7
|
+
* only these two tests need.
|
|
9
8
|
*
|
|
10
|
-
* `vi.mock(...)` calls
|
|
11
|
-
* module graph (vitest scopes mocking per test
|
|
12
|
-
* module has the same effect as if
|
|
13
|
-
* importing file — both test files' `beforeEach`
|
|
14
|
-
* `await import('./devtools-backend.js')` AFTER
|
|
15
|
-
* after
|
|
9
|
+
* `vi.mock(...)` calls in the imported core module run once per importing
|
|
10
|
+
* test file's own isolated module graph (vitest scopes mocking per test
|
|
11
|
+
* file); chaining through this module has the same effect as if they were
|
|
12
|
+
* written directly in the importing file — both test files' `beforeEach`
|
|
13
|
+
* still dynamically `await import('./devtools-backend.js')` AFTER
|
|
14
|
+
* `vi.resetModules()`, well after the core module's mock registrations have
|
|
15
|
+
* already run.
|
|
16
16
|
*/
|
|
17
17
|
import { beforeEach, expect, vi } from 'vitest';
|
|
18
|
-
|
|
19
|
-
// `export const x = vi.hoisted(...)` is rejected by vitest's hoisting
|
|
20
|
-
// transform ("Cannot export hoisted variable") — declare then export below.
|
|
21
|
-
const stubs = vi.hoisted(() => {
|
|
22
|
-
const handlers = new Map();
|
|
23
|
-
const projectsJsonPath = '/tmp/dimina-test-userdata/dimina-projects.json';
|
|
24
|
-
let projectsJsonContent = null;
|
|
25
|
-
const projectsWithAppJson = new Set();
|
|
26
|
-
function makeEmitter() {
|
|
27
|
-
const listeners = {};
|
|
28
|
-
return {
|
|
29
|
-
listeners,
|
|
30
|
-
on(event, fn) {
|
|
31
|
-
;
|
|
32
|
-
(listeners[event] ??= new Set()).add(fn);
|
|
33
|
-
return this;
|
|
34
|
-
},
|
|
35
|
-
once(event, fn) {
|
|
36
|
-
const wrap = (...args) => {
|
|
37
|
-
listeners[event]?.delete(wrap);
|
|
38
|
-
return fn(...args);
|
|
39
|
-
};
|
|
40
|
-
(listeners[event] ??= new Set()).add(wrap);
|
|
41
|
-
return this;
|
|
42
|
-
},
|
|
43
|
-
off(event, fn) {
|
|
44
|
-
listeners[event]?.delete(fn);
|
|
45
|
-
return this;
|
|
46
|
-
},
|
|
47
|
-
removeListener(event, fn) {
|
|
48
|
-
listeners[event]?.delete(fn);
|
|
49
|
-
return this;
|
|
50
|
-
},
|
|
51
|
-
emit(event, ...args) {
|
|
52
|
-
for (const fn of [...(listeners[event] ?? [])])
|
|
53
|
-
fn(...args);
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
function reset() {
|
|
58
|
-
handlers.clear();
|
|
59
|
-
projectsJsonContent = null;
|
|
60
|
-
projectsWithAppJson.clear();
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
handlers,
|
|
64
|
-
projectsJsonPath,
|
|
65
|
-
getProjectsJson() {
|
|
66
|
-
return projectsJsonContent;
|
|
67
|
-
},
|
|
68
|
-
setProjectsJson(v) {
|
|
69
|
-
projectsJsonContent = v;
|
|
70
|
-
},
|
|
71
|
-
projectsWithAppJson,
|
|
72
|
-
makeEmitter,
|
|
73
|
-
reset,
|
|
74
|
-
};
|
|
75
|
-
});
|
|
76
|
-
// ── electron stub ────────────────────────────────────────────────────────
|
|
77
|
-
// `app` is a live emitter so `registerAppLifecycle` can attach a
|
|
78
|
-
// `before-quit` listener that the test fires directly.
|
|
79
|
-
vi.mock('electron', () => {
|
|
80
|
-
const ipcEmitter = stubs.makeEmitter();
|
|
81
|
-
const ipcMain = {
|
|
82
|
-
...ipcEmitter,
|
|
83
|
-
handle: vi.fn((channel, fn) => {
|
|
84
|
-
stubs.handlers.set(channel, fn);
|
|
85
|
-
}),
|
|
86
|
-
removeHandler: vi.fn((channel) => {
|
|
87
|
-
stubs.handlers.delete(channel);
|
|
88
|
-
}),
|
|
89
|
-
on: vi.fn((event, fn) => ipcEmitter.on(event, fn)),
|
|
90
|
-
removeListener: vi.fn((event, fn) => ipcEmitter.removeListener(event, fn)),
|
|
91
|
-
};
|
|
92
|
-
const appEmitter = stubs.makeEmitter();
|
|
93
|
-
const app = {
|
|
94
|
-
...appEmitter,
|
|
95
|
-
isPackaged: true,
|
|
96
|
-
whenReady: vi.fn(() => Promise.resolve()),
|
|
97
|
-
getPath: vi.fn(() => '/tmp/dimina-test-userdata'),
|
|
98
|
-
quit: vi.fn(),
|
|
99
|
-
setName: vi.fn(),
|
|
100
|
-
commandLine: {
|
|
101
|
-
getSwitchValue: vi.fn(() => ''),
|
|
102
|
-
appendSwitch: vi.fn(),
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
// `WebContents` and `BrowserWindow` below both wrap a `stubs.makeEmitter()`
|
|
106
|
-
// and need the SAME on/once/off/removeListener/emit delegation (the
|
|
107
|
-
// emitter's own methods use `this` internally, so a plain property copy
|
|
108
|
-
// would call them with the wrong receiver — each needs `.bind(em)`). Shared
|
|
109
|
-
// base class instead of re-declaring the same 5 bound fields in both.
|
|
110
|
-
class EmittingStub {
|
|
111
|
-
em = stubs.makeEmitter();
|
|
112
|
-
on = this.em.on.bind(this.em);
|
|
113
|
-
once = this.em.once.bind(this.em);
|
|
114
|
-
off = this.em.off.bind(this.em);
|
|
115
|
-
removeListener = this.em.removeListener.bind(this.em);
|
|
116
|
-
emit = this.em.emit.bind(this.em);
|
|
117
|
-
}
|
|
118
|
-
class WebContents extends EmittingStub {
|
|
119
|
-
destroyed = false;
|
|
120
|
-
id = Math.floor(Math.random() * 1e6);
|
|
121
|
-
send = vi.fn();
|
|
122
|
-
isDestroyed = () => this.destroyed;
|
|
123
|
-
openDevTools = vi.fn();
|
|
124
|
-
closeDevTools = vi.fn();
|
|
125
|
-
setDevToolsWebContents = vi.fn();
|
|
126
|
-
setWindowOpenHandler = vi.fn();
|
|
127
|
-
loadFile = vi.fn(() => Promise.resolve());
|
|
128
|
-
loadURL = vi.fn(() => Promise.resolve());
|
|
129
|
-
executeJavaScript = vi.fn(() => Promise.resolve(undefined));
|
|
130
|
-
reload = vi.fn();
|
|
131
|
-
getType = () => 'window';
|
|
132
|
-
getURL = () => '';
|
|
133
|
-
debugger = {
|
|
134
|
-
attach: vi.fn(),
|
|
135
|
-
detach: vi.fn(),
|
|
136
|
-
isAttached: () => false,
|
|
137
|
-
on: vi.fn(),
|
|
138
|
-
removeListener: vi.fn(),
|
|
139
|
-
sendCommand: vi.fn(() => Promise.resolve({ entries: [] })),
|
|
140
|
-
};
|
|
141
|
-
close = vi.fn(() => {
|
|
142
|
-
this.destroyed = true;
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
class WebContentsView {
|
|
146
|
-
webContents = new WebContents();
|
|
147
|
-
setBounds = vi.fn();
|
|
148
|
-
setBackgroundColor = vi.fn();
|
|
149
|
-
}
|
|
150
|
-
class View {
|
|
151
|
-
children = [];
|
|
152
|
-
addChildView(child) {
|
|
153
|
-
this.children.push(child);
|
|
154
|
-
}
|
|
155
|
-
removeChildView(child) {
|
|
156
|
-
const i = this.children.indexOf(child);
|
|
157
|
-
if (i >= 0)
|
|
158
|
-
this.children.splice(i, 1);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
class BrowserWindow extends EmittingStub {
|
|
162
|
-
destroyed = false;
|
|
163
|
-
webContents = new WebContents();
|
|
164
|
-
contentView = new WebContentsView();
|
|
165
|
-
isDestroyed = () => this.destroyed;
|
|
166
|
-
getContentSize = () => [1280, 980];
|
|
167
|
-
setIcon = vi.fn();
|
|
168
|
-
setTitle = vi.fn();
|
|
169
|
-
show = vi.fn();
|
|
170
|
-
showInactive = vi.fn();
|
|
171
|
-
focus = vi.fn();
|
|
172
|
-
close = vi.fn();
|
|
173
|
-
destroy = vi.fn(() => {
|
|
174
|
-
this.destroyed = true;
|
|
175
|
-
});
|
|
176
|
-
loadFile = vi.fn(() => Promise.resolve());
|
|
177
|
-
loadURL = vi.fn(() => Promise.resolve());
|
|
178
|
-
static getAllWindows = vi.fn(() => []);
|
|
179
|
-
}
|
|
180
|
-
const sessionStub = {
|
|
181
|
-
fromPartition: vi.fn(() => ({
|
|
182
|
-
webRequest: {
|
|
183
|
-
onBeforeSendHeaders: vi.fn(),
|
|
184
|
-
onHeadersReceived: vi.fn(),
|
|
185
|
-
},
|
|
186
|
-
registerPreloadScript: vi.fn(),
|
|
187
|
-
protocol: { handle: vi.fn(), unhandle: vi.fn() },
|
|
188
|
-
})),
|
|
189
|
-
defaultSession: {
|
|
190
|
-
protocol: { handle: vi.fn(), unhandle: vi.fn() },
|
|
191
|
-
},
|
|
192
|
-
};
|
|
193
|
-
const dialog = {
|
|
194
|
-
showOpenDialog: vi.fn(() => Promise.resolve({ canceled: true, filePaths: [] })),
|
|
195
|
-
showMessageBox: vi.fn(() => Promise.resolve({ response: 0 })),
|
|
196
|
-
};
|
|
197
|
-
const Menu = {
|
|
198
|
-
buildFromTemplate: vi.fn((tpl) => ({ template: tpl })),
|
|
199
|
-
setApplicationMenu: vi.fn(),
|
|
200
|
-
};
|
|
201
|
-
const shell = {
|
|
202
|
-
openExternal: vi.fn(() => Promise.resolve()),
|
|
203
|
-
openPath: vi.fn(() => Promise.resolve('')),
|
|
204
|
-
};
|
|
205
|
-
const nativeImage = {
|
|
206
|
-
createFromPath: vi.fn(() => ({ isEmpty: () => true })),
|
|
207
|
-
};
|
|
208
|
-
const nativeTheme = { ...stubs.makeEmitter(), themeSource: 'system' };
|
|
209
|
-
const globalShortcut = {
|
|
210
|
-
register: vi.fn(() => false),
|
|
211
|
-
unregister: vi.fn(),
|
|
212
|
-
unregisterAll: vi.fn(),
|
|
213
|
-
};
|
|
214
|
-
const webContentsStatic = {
|
|
215
|
-
fromId: vi.fn(() => null),
|
|
216
|
-
getAllWebContents: vi.fn(() => []),
|
|
217
|
-
};
|
|
218
|
-
const Tray = vi.fn();
|
|
219
|
-
return {
|
|
220
|
-
app,
|
|
221
|
-
ipcMain,
|
|
222
|
-
BrowserWindow,
|
|
223
|
-
WebContentsView,
|
|
224
|
-
BrowserView: WebContentsView,
|
|
225
|
-
View,
|
|
226
|
-
webContents: webContentsStatic,
|
|
227
|
-
session: sessionStub,
|
|
228
|
-
protocol: { registerSchemesAsPrivileged: vi.fn(), handle: vi.fn(), unhandle: vi.fn() },
|
|
229
|
-
dialog,
|
|
230
|
-
Menu,
|
|
231
|
-
shell,
|
|
232
|
-
nativeImage,
|
|
233
|
-
nativeTheme,
|
|
234
|
-
globalShortcut,
|
|
235
|
-
Tray,
|
|
236
|
-
default: {},
|
|
237
|
-
};
|
|
238
|
-
});
|
|
239
|
-
vi.mock('fs', async () => {
|
|
240
|
-
const real = await vi.importActual('fs');
|
|
241
|
-
function existsSync(p) {
|
|
242
|
-
const s = String(p);
|
|
243
|
-
if (s === stubs.projectsJsonPath)
|
|
244
|
-
return stubs.getProjectsJson() !== null;
|
|
245
|
-
if (s.endsWith('/app.json') || s.endsWith('\\app.json')) {
|
|
246
|
-
const dir = s.replace(/[\\/]app\.json$/, '');
|
|
247
|
-
return stubs.projectsWithAppJson.has(dir);
|
|
248
|
-
}
|
|
249
|
-
return true;
|
|
250
|
-
}
|
|
251
|
-
function readFileSync(p, opts) {
|
|
252
|
-
const s = String(p);
|
|
253
|
-
if (s === stubs.projectsJsonPath) {
|
|
254
|
-
const content = stubs.getProjectsJson();
|
|
255
|
-
if (content === null)
|
|
256
|
-
throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' });
|
|
257
|
-
return content;
|
|
258
|
-
}
|
|
259
|
-
return real.readFileSync(p, opts);
|
|
260
|
-
}
|
|
261
|
-
function writeFileSync(p, data) {
|
|
262
|
-
const s = String(p);
|
|
263
|
-
if (s === stubs.projectsJsonPath) {
|
|
264
|
-
stubs.setProjectsJson(typeof data === 'string' ? data : Buffer.from(data).toString('utf8'));
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
const mocked = {
|
|
268
|
-
...real,
|
|
269
|
-
existsSync,
|
|
270
|
-
readFileSync,
|
|
271
|
-
writeFileSync,
|
|
272
|
-
mkdirSync: vi.fn(),
|
|
273
|
-
statSync: vi.fn(() => ({ isDirectory: () => true, isFile: () => false, size: 0, mtimeMs: 0 })),
|
|
274
|
-
watch: vi.fn(),
|
|
275
|
-
realpathSync: vi.fn((p) => p),
|
|
276
|
-
};
|
|
277
|
-
return { ...mocked, default: mocked };
|
|
278
|
-
});
|
|
279
|
-
const devkitStubs = vi.hoisted(() => ({
|
|
280
|
-
sessionClose: vi.fn(() => Promise.resolve()),
|
|
281
|
-
}));
|
|
282
|
-
vi.mock('@dimina-kit/devkit', () => ({
|
|
283
|
-
openProject: vi.fn(() => Promise.resolve({
|
|
284
|
-
port: 12345,
|
|
285
|
-
appInfo: { appId: 'fakeApp' },
|
|
286
|
-
close: devkitStubs.sessionClose,
|
|
287
|
-
})),
|
|
288
|
-
}));
|
|
18
|
+
import { stubs, devkitStubs } from './devtools-runtime-mock.harness.js';
|
|
289
19
|
// ── view-manager spy shim ───────────────────────────────────────────────
|
|
290
20
|
// `createDevtoolsBackend` keeps its assembled `instance` in a private
|
|
291
21
|
// closure — the returned `RuntimeBackend` exposes no getter for
|
|
@@ -309,7 +39,8 @@ vi.mock('../services/views/view-manager.js', async (importOriginal) => {
|
|
|
309
39
|
},
|
|
310
40
|
};
|
|
311
41
|
});
|
|
312
|
-
export { stubs, devkitStubs
|
|
42
|
+
export { stubs, devkitStubs } from './devtools-runtime-mock.harness.js';
|
|
43
|
+
export { viewManagerStubs };
|
|
313
44
|
export function registerBackendTestLifecycle() {
|
|
314
45
|
const state = {};
|
|
315
46
|
beforeEach(async () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { runDevtoolsBootstrap, createDevtoolsRuntime } from '../app/app.js';
|
|
2
2
|
import { isAppQuitting, registerAppLifecycle } from '../app/lifecycle.js';
|
|
3
|
+
import { closeAllCoiHosts } from '../services/workbench-coi-host.js';
|
|
3
4
|
/**
|
|
4
5
|
* Adapts the devtools runtime into a {@link RuntimeBackend} the framework
|
|
5
6
|
* (`@dimina-kit/electron-deck`) orchestrates. The framework owns the process
|
|
@@ -61,7 +62,7 @@ export function createDevtoolsBackend(config = {}) {
|
|
|
61
62
|
// handler closing an already-torn-down MessagePort segfaults natively.
|
|
62
63
|
// Safe to run again from `onShutdown`'s `instance.dispose()` afterwards
|
|
63
64
|
// — `views.disposeAll()` and its constituents are dispose-idempotent.
|
|
64
|
-
registerAppLifecycle(() => instance?.
|
|
65
|
+
registerAppLifecycle(() => instance?.disposeViews());
|
|
65
66
|
// `onInstanceCreated` (not the return value) is what assigns `instance`:
|
|
66
67
|
// `createDevtoolsRuntime` awaits the host's `config.onSetup(instance)`
|
|
67
68
|
// — which may run arbitrarily long and can itself load the host toolbar
|
|
@@ -74,7 +75,7 @@ export function createDevtoolsBackend(config = {}) {
|
|
|
74
75
|
// this instance existed, so the hook above ran with nothing to
|
|
75
76
|
// dispose. Self-heal: run the same teardown now that there is.
|
|
76
77
|
if (isAppQuitting())
|
|
77
|
-
instance.
|
|
78
|
+
instance.disposeViews();
|
|
78
79
|
}).then(() => { });
|
|
79
80
|
await assembling;
|
|
80
81
|
},
|
|
@@ -94,7 +95,17 @@ export function createDevtoolsBackend(config = {}) {
|
|
|
94
95
|
// not a reason to skip disposing whatever DID get constructed.
|
|
95
96
|
onShutdown: async () => {
|
|
96
97
|
await assembling?.catch(() => { });
|
|
97
|
-
|
|
98
|
+
// The workbench COI listener is deliberately kept alive across project
|
|
99
|
+
// windows (its port IS the workbench origin, see workbench-coi-host.ts),
|
|
100
|
+
// so no window teardown ever closes it. Process shutdown is the one place
|
|
101
|
+
// that must — after the windows above have released their routes, and
|
|
102
|
+
// even if one of their disposers threw on the way.
|
|
103
|
+
try {
|
|
104
|
+
await instance?.dispose();
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
await closeAllCoiHosts();
|
|
108
|
+
}
|
|
98
109
|
},
|
|
99
110
|
};
|
|
100
111
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare const stubs: {
|
|
2
|
+
handlers: Map<string, (...args: unknown[]) => unknown>;
|
|
3
|
+
projectsJsonPath: string;
|
|
4
|
+
getProjectsJson(): string | null;
|
|
5
|
+
setProjectsJson(v: string | null): void;
|
|
6
|
+
projectsWithAppJson: Set<string>;
|
|
7
|
+
makeEmitter: () => {
|
|
8
|
+
listeners: Record<string, Set<(...args: unknown[]) => unknown>>;
|
|
9
|
+
on(event: string, fn: (...args: unknown[]) => unknown): /*elided*/ any;
|
|
10
|
+
once(event: string, fn: (...args: unknown[]) => unknown): /*elided*/ any;
|
|
11
|
+
off(event: string, fn: (...args: unknown[]) => unknown): /*elided*/ any;
|
|
12
|
+
removeListener(event: string, fn: (...args: unknown[]) => unknown): /*elided*/ any;
|
|
13
|
+
emit(event: string, ...args: unknown[]): void;
|
|
14
|
+
};
|
|
15
|
+
reset: () => void;
|
|
16
|
+
};
|
|
17
|
+
declare const devkitStubs: {
|
|
18
|
+
sessionClose: import("vitest").Mock<() => Promise<void>>;
|
|
19
|
+
};
|
|
20
|
+
export { stubs, devkitStubs };
|
|
21
|
+
//# sourceMappingURL=devtools-runtime-mock.harness.d.ts.map
|