@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
|
@@ -128,6 +128,23 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
128
128
|
pushData: (view, data) => ctx.notify.updateAvailable(view, data),
|
|
129
129
|
readyMode: 'manual',
|
|
130
130
|
});
|
|
131
|
+
const devicePickerPanel = createOverlayPanel({
|
|
132
|
+
electron: { createWebContentsView: (opts) => new WebContentsView(opts) },
|
|
133
|
+
rendererDir: ctx.rendererDir,
|
|
134
|
+
entry: 'entries/device-picker/index.html',
|
|
135
|
+
webPreferences: {
|
|
136
|
+
nodeIntegration: false,
|
|
137
|
+
contextIsolation: true,
|
|
138
|
+
sandbox: false,
|
|
139
|
+
preload: mainPreloadPath,
|
|
140
|
+
},
|
|
141
|
+
hardenNavigation: (wc) => applyNavigationHardening(wc, ctx.rendererDir),
|
|
142
|
+
setDesired: overlayDesiredSetter(VIEW_ID.devicePicker, VIEW_LAYER.dialog),
|
|
143
|
+
registerView: (getView) => reconciler.registerView(VIEW_ID.devicePicker, { getView }),
|
|
144
|
+
destroyView: (view) => reconciler.destroyView(VIEW_ID.devicePicker, view),
|
|
145
|
+
pushData: (view, data) => ctx.notify.devicePickerInit(view, data),
|
|
146
|
+
readyMode: 'manual',
|
|
147
|
+
});
|
|
131
148
|
let tooltipRequestId = 0;
|
|
132
149
|
let activeTooltip = null;
|
|
133
150
|
async function showSettings() {
|
|
@@ -183,6 +200,12 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
183
200
|
function hideUpdateDialog() {
|
|
184
201
|
updateDialogPanel.hide();
|
|
185
202
|
}
|
|
203
|
+
function showDevicePicker(data) {
|
|
204
|
+
devicePickerPanel.show(data, fullWindowBounds());
|
|
205
|
+
}
|
|
206
|
+
function hideDevicePicker() {
|
|
207
|
+
devicePickerPanel.hide();
|
|
208
|
+
}
|
|
186
209
|
function notifyUpdateDownloadProgress(percent) {
|
|
187
210
|
const wc = updateDialogPanel.getWebContents();
|
|
188
211
|
if (!wc)
|
|
@@ -195,6 +218,7 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
195
218
|
tooltipPanel.markReady(webContentsId);
|
|
196
219
|
projectCreateDialogPanel.markReady(webContentsId);
|
|
197
220
|
updateDialogPanel.markReady(webContentsId);
|
|
221
|
+
devicePickerPanel.markReady(webContentsId);
|
|
198
222
|
}
|
|
199
223
|
function applyTooltipMeasurement(webContentsId, measurement) {
|
|
200
224
|
const active = activeTooltip;
|
|
@@ -222,6 +246,9 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
222
246
|
if (updateDialogPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.updateDialog)) {
|
|
223
247
|
updateDialogPanel.reposition(fullWindowBounds());
|
|
224
248
|
}
|
|
249
|
+
if (devicePickerPanel.isPresent() && reconciler.hasOverlayDesired(VIEW_ID.devicePicker)) {
|
|
250
|
+
devicePickerPanel.reposition(fullWindowBounds());
|
|
251
|
+
}
|
|
225
252
|
}
|
|
226
253
|
function applySettingsBoundsIfPresent() {
|
|
227
254
|
// See reapplyPresentOverlays() above for why this swallows a rejection.
|
|
@@ -237,6 +264,7 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
237
264
|
function destroyDialogs() {
|
|
238
265
|
projectCreateDialogPanel.destroy();
|
|
239
266
|
updateDialogPanel.destroy();
|
|
267
|
+
devicePickerPanel.destroy();
|
|
240
268
|
}
|
|
241
269
|
return {
|
|
242
270
|
showSettings,
|
|
@@ -253,6 +281,8 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
253
281
|
showUpdateDialog,
|
|
254
282
|
hideUpdateDialog,
|
|
255
283
|
notifyUpdateDownloadProgress,
|
|
284
|
+
showDevicePicker,
|
|
285
|
+
hideDevicePicker,
|
|
256
286
|
reapplyPresentOverlays,
|
|
257
287
|
applySettingsBoundsIfPresent,
|
|
258
288
|
destroySettings,
|
|
@@ -263,6 +293,7 @@ export function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
263
293
|
getTooltipWebContentsId: () => tooltipPanel.getWebContentsId(),
|
|
264
294
|
getProjectCreateDialogWebContentsId: () => projectCreateDialogPanel.getWebContentsId(),
|
|
265
295
|
getUpdateDialogWebContentsId: () => updateDialogPanel.getWebContentsId(),
|
|
296
|
+
getDevicePickerWebContentsId: () => devicePickerPanel.getWebContentsId(),
|
|
266
297
|
};
|
|
267
298
|
}
|
|
268
299
|
//# sourceMappingURL=overlay-panels-view.js.map
|
|
@@ -93,7 +93,7 @@ export interface ViewManagerContext {
|
|
|
93
93
|
* panels) and shares a single injected placement reconciler; this file wires
|
|
94
94
|
* them together and exposes their combined method surface.
|
|
95
95
|
*/
|
|
96
|
-
export interface ViewManager extends Pick<OverlayPanelsView, 'showSettings' | 'hideSettings' | 'showPopover' | 'hidePopover' | 'prepareTooltip' | 'showTooltip' | 'hideTooltip' | 'markOverlayReady' | 'applyTooltipMeasurement' | 'showProjectCreateDialog' | 'hideProjectCreateDialog' | 'showUpdateDialog' | 'hideUpdateDialog' | 'notifyUpdateDownloadProgress' | 'getProjectCreateDialogWebContentsId' | 'getUpdateDialogWebContentsId'>, HostSidebarViewManagerMembers, HostDialogViewManagerMembers {
|
|
96
|
+
export interface ViewManager extends Pick<OverlayPanelsView, 'showSettings' | 'hideSettings' | 'showPopover' | 'hidePopover' | 'prepareTooltip' | 'showTooltip' | 'hideTooltip' | 'markOverlayReady' | 'applyTooltipMeasurement' | 'showProjectCreateDialog' | 'hideProjectCreateDialog' | 'showUpdateDialog' | 'hideUpdateDialog' | 'notifyUpdateDownloadProgress' | 'showDevicePicker' | 'hideDevicePicker' | 'getProjectCreateDialogWebContentsId' | 'getUpdateDialogWebContentsId' | 'getDevicePickerWebContentsId'>, HostSidebarViewManagerMembers, HostDialogViewManagerMembers {
|
|
97
97
|
/**
|
|
98
98
|
* NATIVE-HOST ONLY. Create the simulator itself as a top-level
|
|
99
99
|
* WebContentsView (not a renderer `<webview>` guest) loading `simulatorUrl`,
|
|
@@ -100,8 +100,11 @@ export function createViewManager(ctx) {
|
|
|
100
100
|
showUpdateDialog: overlayPanels.showUpdateDialog,
|
|
101
101
|
hideUpdateDialog: overlayPanels.hideUpdateDialog,
|
|
102
102
|
notifyUpdateDownloadProgress: overlayPanels.notifyUpdateDownloadProgress,
|
|
103
|
+
showDevicePicker: overlayPanels.showDevicePicker,
|
|
104
|
+
hideDevicePicker: overlayPanels.hideDevicePicker,
|
|
103
105
|
getProjectCreateDialogWebContentsId: overlayPanels.getProjectCreateDialogWebContentsId,
|
|
104
106
|
getUpdateDialogWebContentsId: overlayPanels.getUpdateDialogWebContentsId,
|
|
107
|
+
getDevicePickerWebContentsId: overlayPanels.getDevicePickerWebContentsId,
|
|
105
108
|
repositionAll: () => {
|
|
106
109
|
overlayPanels.reapplyPresentOverlays();
|
|
107
110
|
hostDialog.reposition();
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { WebContents } from 'electron';
|
|
2
|
+
import { type Disposable } from '@dimina-kit/electron-deck/main';
|
|
3
|
+
import type { IpcContextSource } from '../../utils/ipc-context-source.js';
|
|
4
|
+
import type { SenderPolicy } from '../../utils/ipc-registry.js';
|
|
5
|
+
/**
|
|
6
|
+
* What the router needs of a window context to place an incoming sender.
|
|
7
|
+
* Kept to these two predicates so the router stays independent of the rest of
|
|
8
|
+
* the context; the concrete context type is supplied by the caller.
|
|
9
|
+
*/
|
|
10
|
+
export interface RoutableWindowContext {
|
|
11
|
+
/** Every sender this window accepts, app-shared trusted windows included. */
|
|
12
|
+
senderPolicy: SenderPolicy;
|
|
13
|
+
/** Only the senders this window structurally owns (see sender-policy.ts). */
|
|
14
|
+
ownsSender: SenderPolicy;
|
|
15
|
+
}
|
|
16
|
+
/** Registry of live window contexts, and the authority on which one owns a sender. */
|
|
17
|
+
export interface WindowContextRouter<T extends RoutableWindowContext = RoutableWindowContext> extends IpcContextSource<T> {
|
|
18
|
+
/** Register a window context; the returned Disposable unregisters it. */
|
|
19
|
+
register(ctx: T): Disposable;
|
|
20
|
+
/**
|
|
21
|
+
* The context owning `sender`, or null when no registered context claims it.
|
|
22
|
+
* A pure query: looking a sender up never changes which context is active.
|
|
23
|
+
*/
|
|
24
|
+
resolve(sender: WebContents): T | null;
|
|
25
|
+
/**
|
|
26
|
+
* The context last marked active by `setActive`. With none marked — or after
|
|
27
|
+
* the marked one unregisters — it falls back to the first still-registered
|
|
28
|
+
* context, and null when none are.
|
|
29
|
+
*/
|
|
30
|
+
active(): T | null;
|
|
31
|
+
/** Mark `ctx` active (on window focus). Ignored for unregistered contexts. */
|
|
32
|
+
setActive(ctx: T): void;
|
|
33
|
+
list(): T[];
|
|
34
|
+
}
|
|
35
|
+
export declare function createWindowContextRouter<T extends RoutableWindowContext = RoutableWindowContext>(): WindowContextRouter<T>;
|
|
36
|
+
//# sourceMappingURL=context-router.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { toDisposable } from '@dimina-kit/electron-deck/main';
|
|
2
|
+
export function createWindowContextRouter() {
|
|
3
|
+
const contexts = [];
|
|
4
|
+
let activeCtx = null;
|
|
5
|
+
const first = () => contexts[0] ?? null;
|
|
6
|
+
return {
|
|
7
|
+
register(ctx) {
|
|
8
|
+
contexts.push(ctx);
|
|
9
|
+
activeCtx ??= ctx;
|
|
10
|
+
return toDisposable(() => {
|
|
11
|
+
const at = contexts.indexOf(ctx);
|
|
12
|
+
if (at === -1)
|
|
13
|
+
return;
|
|
14
|
+
contexts.splice(at, 1);
|
|
15
|
+
if (activeCtx === ctx)
|
|
16
|
+
activeCtx = first();
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
resolve(sender) {
|
|
20
|
+
// Two passes, because the two predicates answer different questions.
|
|
21
|
+
// `senderPolicy` also accepts host windows registered through
|
|
22
|
+
// `registerTrustedWindow`, whose id map is app-wide — every context says
|
|
23
|
+
// yes to such a sender, so a single-pass scan would hand it to whichever
|
|
24
|
+
// window happened to register first. Pass one therefore only accepts a
|
|
25
|
+
// context that OWNS the sender (its own renderer, settings window or
|
|
26
|
+
// overlay views), which is unique by construction. Pass two covers the
|
|
27
|
+
// accepted-but-unowned senders that are left: they belong to the app
|
|
28
|
+
// rather than to a window, so the active window answers them.
|
|
29
|
+
//
|
|
30
|
+
// Neither pass moves "active": window focus is what decides which window
|
|
31
|
+
// an app-wide sender belongs to, and a background window handling its own
|
|
32
|
+
// IPC must not steal that answer from the focused one.
|
|
33
|
+
for (const ctx of contexts) {
|
|
34
|
+
if (ctx.ownsSender(sender))
|
|
35
|
+
return ctx;
|
|
36
|
+
}
|
|
37
|
+
for (const ctx of contexts) {
|
|
38
|
+
if (ctx.senderPolicy(sender))
|
|
39
|
+
return activeCtx ?? first();
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
},
|
|
43
|
+
active() {
|
|
44
|
+
return activeCtx ?? first();
|
|
45
|
+
},
|
|
46
|
+
setActive(ctx) {
|
|
47
|
+
if (contexts.includes(ctx))
|
|
48
|
+
activeCtx = ctx;
|
|
49
|
+
},
|
|
50
|
+
list() {
|
|
51
|
+
return contexts.slice();
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=context-router.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single http listener behind every project window's workbench bridge.
|
|
3
|
+
*
|
|
4
|
+
* Browser storage is keyed by ORIGIN: IndexedDB, OPFS, Cache Storage, service
|
|
5
|
+
* worker registrations, Web Locks and BroadcastChannel all live in a bucket
|
|
6
|
+
* named after scheme + host + PORT. A listener bound to port 0 gets a different
|
|
7
|
+
* port every time, so one http server per project window put every window on
|
|
8
|
+
* its own origin — the VS Code workspace- and global-scope mementos a window
|
|
9
|
+
* wrote (open editors, view state, explorer expansion) died with it, reopening
|
|
10
|
+
* the same project minted a fresh empty bucket, and each new port accumulated
|
|
11
|
+
* another service-worker registration and cache entry that nothing reclaimed.
|
|
12
|
+
*
|
|
13
|
+
* So the listener is shared by every window in the process and a window's
|
|
14
|
+
* bridge is addressed by an opaque path prefix (`/w/<token>/`) rather than by
|
|
15
|
+
* port: one origin for all workbenches, distinct `/__fs` + `/__project`
|
|
16
|
+
* routing per window. The prefix is routing, not a security boundary — pages
|
|
17
|
+
* on one origin can already reach each other's paths, which is the situation
|
|
18
|
+
* the app-wide server had before per-project windows existed.
|
|
19
|
+
*
|
|
20
|
+
* The listener also outlives the last window that used it, because closing
|
|
21
|
+
* every project and opening another one is an ordinary switch and must not
|
|
22
|
+
* move the origin. Only {@link closeAllCoiHosts} takes a listener down.
|
|
23
|
+
*/
|
|
24
|
+
import http from 'node:http';
|
|
25
|
+
export interface CoiHostSession {
|
|
26
|
+
/**
|
|
27
|
+
* Answers one request for this window. `url` has already had the window's
|
|
28
|
+
* `/w/<token>` prefix stripped, so the handler sees the same pathnames it
|
|
29
|
+
* would on a server of its own.
|
|
30
|
+
*/
|
|
31
|
+
handle: (req: http.IncomingMessage, res: http.ServerResponse, url: URL) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface CoiHostRegistration {
|
|
34
|
+
/** Scheme + host + port of the shared listener, with no trailing slash. */
|
|
35
|
+
origin: string;
|
|
36
|
+
port: number;
|
|
37
|
+
/** The path segment that routes to this session. */
|
|
38
|
+
token: string;
|
|
39
|
+
/** Drops the route, closing the shared listener when the last one goes. */
|
|
40
|
+
release: () => Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Tear down every listener. For process shutdown and for test isolation — a
|
|
44
|
+
* window's own teardown never gets here, because the origin has to survive it.
|
|
45
|
+
*/
|
|
46
|
+
export declare function closeAllCoiHosts(): Promise<void>;
|
|
47
|
+
export declare function registerCoiHostSession(opts: {
|
|
48
|
+
rootDir: string;
|
|
49
|
+
extensionsDir: string | null;
|
|
50
|
+
session: CoiHostSession;
|
|
51
|
+
}): Promise<CoiHostRegistration>;
|
|
52
|
+
//# sourceMappingURL=workbench-coi-host.d.ts.map
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single http listener behind every project window's workbench bridge.
|
|
3
|
+
*
|
|
4
|
+
* Browser storage is keyed by ORIGIN: IndexedDB, OPFS, Cache Storage, service
|
|
5
|
+
* worker registrations, Web Locks and BroadcastChannel all live in a bucket
|
|
6
|
+
* named after scheme + host + PORT. A listener bound to port 0 gets a different
|
|
7
|
+
* port every time, so one http server per project window put every window on
|
|
8
|
+
* its own origin — the VS Code workspace- and global-scope mementos a window
|
|
9
|
+
* wrote (open editors, view state, explorer expansion) died with it, reopening
|
|
10
|
+
* the same project minted a fresh empty bucket, and each new port accumulated
|
|
11
|
+
* another service-worker registration and cache entry that nothing reclaimed.
|
|
12
|
+
*
|
|
13
|
+
* So the listener is shared by every window in the process and a window's
|
|
14
|
+
* bridge is addressed by an opaque path prefix (`/w/<token>/`) rather than by
|
|
15
|
+
* port: one origin for all workbenches, distinct `/__fs` + `/__project`
|
|
16
|
+
* routing per window. The prefix is routing, not a security boundary — pages
|
|
17
|
+
* on one origin can already reach each other's paths, which is the situation
|
|
18
|
+
* the app-wide server had before per-project windows existed.
|
|
19
|
+
*
|
|
20
|
+
* The listener also outlives the last window that used it, because closing
|
|
21
|
+
* every project and opening another one is an ordinary switch and must not
|
|
22
|
+
* move the origin. Only {@link closeAllCoiHosts} takes a listener down.
|
|
23
|
+
*/
|
|
24
|
+
import http from 'node:http';
|
|
25
|
+
import path from 'node:path';
|
|
26
|
+
import { randomUUID } from 'node:crypto';
|
|
27
|
+
import { serveStaticFile, setIsolationHeaders } from './workbench-coi-static.js';
|
|
28
|
+
import { createCoiServerShutdown } from './workbench-coi-shutdown.js';
|
|
29
|
+
/**
|
|
30
|
+
* Tear down every listener. For process shutdown and for test isolation — a
|
|
31
|
+
* window's own teardown never gets here, because the origin has to survive it.
|
|
32
|
+
*/
|
|
33
|
+
export async function closeAllCoiHosts() {
|
|
34
|
+
if (closingAll)
|
|
35
|
+
return closingAll;
|
|
36
|
+
const pending = [...hosts.values()];
|
|
37
|
+
hosts.clear();
|
|
38
|
+
const run = (async () => {
|
|
39
|
+
await Promise.all(pending.map(async (p) => {
|
|
40
|
+
const host = await p.catch(() => null);
|
|
41
|
+
if (!host || host.closed)
|
|
42
|
+
return;
|
|
43
|
+
host.closed = true;
|
|
44
|
+
await host.shutdown.close(host.server);
|
|
45
|
+
}));
|
|
46
|
+
})();
|
|
47
|
+
closingAll = run;
|
|
48
|
+
try {
|
|
49
|
+
await run;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
if (closingAll === run)
|
|
53
|
+
closingAll = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* One host per bundle + extensions pair. Two hosts serving different bundles
|
|
58
|
+
* are genuinely different servers; every window of one app shares one entry.
|
|
59
|
+
*/
|
|
60
|
+
const hosts = new Map();
|
|
61
|
+
/**
|
|
62
|
+
* In-flight {@link closeAllCoiHosts}. A registration that was already waiting
|
|
63
|
+
* on `createHost` when a global close began must not hand its window an origin
|
|
64
|
+
* that close is about to take away, so it waits here and starts a fresh host.
|
|
65
|
+
*/
|
|
66
|
+
let closingAll = null;
|
|
67
|
+
const WINDOW_PREFIX = /^\/w\/([A-Za-z0-9-]+)(\/.*)?$/;
|
|
68
|
+
function notFound(res) {
|
|
69
|
+
res.writeHead(404);
|
|
70
|
+
res.end('Not Found');
|
|
71
|
+
}
|
|
72
|
+
function badRequest(res) {
|
|
73
|
+
res.writeHead(400);
|
|
74
|
+
res.end('Bad Request');
|
|
75
|
+
}
|
|
76
|
+
function serverError(res) {
|
|
77
|
+
res.writeHead(500);
|
|
78
|
+
res.end('Internal Server Error');
|
|
79
|
+
}
|
|
80
|
+
async function createHost(rootDir) {
|
|
81
|
+
const sessions = new Map();
|
|
82
|
+
const shutdown = createCoiServerShutdown();
|
|
83
|
+
const server = http.createServer((req, res) => {
|
|
84
|
+
setIsolationHeaders(res);
|
|
85
|
+
let url;
|
|
86
|
+
try {
|
|
87
|
+
url = new URL(req.url ?? '/', 'http://127.0.0.1');
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// A malformed request line must not become an uncaught exception in the
|
|
91
|
+
// main process.
|
|
92
|
+
badRequest(res);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const routed = WINDOW_PREFIX.exec(url.pathname);
|
|
96
|
+
if (routed) {
|
|
97
|
+
const session = sessions.get(routed[1]);
|
|
98
|
+
// A request for a window that has already been torn down. 404 rather
|
|
99
|
+
// than fall through to the bundle: the caller asked for one specific
|
|
100
|
+
// window's bridge, and answering with another window's data would be
|
|
101
|
+
// worse than not answering.
|
|
102
|
+
if (!session) {
|
|
103
|
+
notFound(res);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Strip the prefix by rewriting `pathname` on a copy. Re-parsing the
|
|
107
|
+
// remainder as a URL reference would read a leading `//` as an authority,
|
|
108
|
+
// so `/w/<token>//__project` would arrive as `/` on host `__project`.
|
|
109
|
+
const forwarded = new URL(url);
|
|
110
|
+
forwarded.pathname = routed[2] || '/';
|
|
111
|
+
try {
|
|
112
|
+
session.handle(req, res, forwarded);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
// One window's handler must not take the shared listener's process
|
|
116
|
+
// with it — an uncaught exception here would end every other project
|
|
117
|
+
// window too. A handler answers its own client errors (a malformed
|
|
118
|
+
// percent escape, say), so anything reaching this point is a defect in
|
|
119
|
+
// it: 500 rather than 400, and logged, because a silent 400 would read
|
|
120
|
+
// as the caller's fault and hide the bug for good.
|
|
121
|
+
console.error('[workbench-coi] session handler threw', err);
|
|
122
|
+
if (res.headersSent)
|
|
123
|
+
res.destroy();
|
|
124
|
+
else
|
|
125
|
+
serverError(res);
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// No window prefix. Every bridge endpoint has to know WHICH window asked,
|
|
130
|
+
// so answering one here would mean guessing a project — the ambiguity the
|
|
131
|
+
// prefix exists to remove. The bundle itself is project-independent and is
|
|
132
|
+
// still served, so an absolute asset URL inside it keeps working.
|
|
133
|
+
if (url.pathname.startsWith('/__')) {
|
|
134
|
+
notFound(res);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
let decoded;
|
|
138
|
+
try {
|
|
139
|
+
decoded = decodeURIComponent(url.pathname);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// A stray `%` in the path. Answering 400 keeps the listener alive; the
|
|
143
|
+
// throw would otherwise escape the request handler.
|
|
144
|
+
badRequest(res);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
shutdown.trackRequest(res);
|
|
148
|
+
serveStaticFile(res, rootDir, decoded);
|
|
149
|
+
});
|
|
150
|
+
await new Promise((resolve, reject) => {
|
|
151
|
+
server.once('error', reject);
|
|
152
|
+
server.listen(0, '127.0.0.1', () => {
|
|
153
|
+
server.off('error', reject);
|
|
154
|
+
resolve();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
const addr = server.address();
|
|
158
|
+
const port = typeof addr === 'object' && addr ? addr.port : 0;
|
|
159
|
+
return {
|
|
160
|
+
server,
|
|
161
|
+
origin: `http://127.0.0.1:${port}`,
|
|
162
|
+
port,
|
|
163
|
+
rootDir,
|
|
164
|
+
sessions,
|
|
165
|
+
shutdown,
|
|
166
|
+
closed: false,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
export async function registerCoiHostSession(opts) {
|
|
170
|
+
const rootDir = path.resolve(opts.rootDir);
|
|
171
|
+
// JSON, not a separator character: `('/a', '/b|/c')` and `('/a|/b', '/c')`
|
|
172
|
+
// are both legal path pairs and would otherwise collide onto one host, so two
|
|
173
|
+
// different bundles would serve each other's files.
|
|
174
|
+
const key = JSON.stringify([rootDir, opts.extensionsDir ?? null]);
|
|
175
|
+
// Loop rather than a single lookup: a release running concurrently can have
|
|
176
|
+
// marked the cached host closed without having removed it yet, and joining a
|
|
177
|
+
// closing server would hand back a dead origin.
|
|
178
|
+
for (;;) {
|
|
179
|
+
if (closingAll) {
|
|
180
|
+
await closingAll;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
let pending = hosts.get(key);
|
|
184
|
+
if (!pending) {
|
|
185
|
+
pending = createHost(rootDir);
|
|
186
|
+
hosts.set(key, pending);
|
|
187
|
+
}
|
|
188
|
+
let host;
|
|
189
|
+
try {
|
|
190
|
+
host = await pending;
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
if (hosts.get(key) === pending)
|
|
194
|
+
hosts.delete(key);
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
// `closingAll` is re-checked because it can have started while this
|
|
198
|
+
// registration was awaiting `pending`: the host may still read as open and
|
|
199
|
+
// yet be one `await` away from losing its port.
|
|
200
|
+
if (host.closed || closingAll || hosts.get(key) !== pending) {
|
|
201
|
+
if (hosts.get(key) === pending)
|
|
202
|
+
hosts.delete(key);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const token = randomUUID();
|
|
206
|
+
host.sessions.set(token, opts.session);
|
|
207
|
+
let released = false;
|
|
208
|
+
return {
|
|
209
|
+
origin: host.origin,
|
|
210
|
+
port: host.port,
|
|
211
|
+
token,
|
|
212
|
+
release: async () => {
|
|
213
|
+
if (released)
|
|
214
|
+
return;
|
|
215
|
+
released = true;
|
|
216
|
+
host.sessions.delete(token);
|
|
217
|
+
// The listener deliberately stays up with no windows on it. Closing it
|
|
218
|
+
// would release the port, and the next window would bind a different
|
|
219
|
+
// one — a different origin, so the storage the closed window wrote
|
|
220
|
+
// would be unreachable. Closing the last project and opening another
|
|
221
|
+
// is the ordinary way to switch projects, so the origin has to hold
|
|
222
|
+
// for the life of the process, not just while a window is open.
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=workbench-coi-host.js.map
|