@dimina-kit/devtools 0.4.0-dev.20260625063832 → 0.4.0-dev.20260630033804
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/dist/main/app/app.js +2 -0
- package/dist/main/index.bundle.js +241 -151
- package/dist/main/ipc/bridge-router.d.ts +21 -0
- package/dist/main/ipc/bridge-router.js +63 -3
- package/dist/main/services/automation/index.js +0 -1
- package/dist/main/services/elements-forward/index.js +81 -72
- package/dist/main/services/mcp/target-manager.d.ts +3 -3
- package/dist/main/services/views/miniapp-partition.d.ts +18 -8
- package/dist/main/services/views/miniapp-partition.js +34 -13
- package/dist/main/services/views/view-manager.js +76 -41
- package/dist/main/services/workbench-coi-server.d.ts +7 -0
- package/dist/main/services/workbench-coi-server.js +6 -0
- package/dist/main/services/workbench-context.d.ts +4 -2
- package/dist/main/services/workbench-context.js +1 -0
- package/dist/main/services/workspace/op-lock.d.ts +26 -0
- package/dist/main/services/workspace/op-lock.js +23 -0
- package/dist/main/services/workspace/workspace-service.d.ts +7 -0
- package/dist/main/services/workspace/workspace-service.js +197 -103
- package/dist/main/windows/service-host-window/create.d.ts +5 -1
- package/dist/main/windows/service-host-window/create.js +6 -3
- package/dist/native-host/render/render.js +485 -449
- package/dist/native-host/service/service.js +1 -1
- package/dist/renderer/assets/index-BMwmmaSp.js +46 -0
- package/dist/renderer/entries/main/index.html +1 -1
- package/dist/shared/types.d.ts +15 -0
- package/dist/vscode-workbench/assets/__vite-browser-external-B0DTNerG.js +1 -0
- package/dist/vscode-workbench/assets/__vite-browser-external-BuLjVMfN.js +1 -0
- package/dist/vscode-workbench/assets/__vite-browser-external-thkx7I19.js +1 -0
- package/dist/vscode-workbench/assets/{dist-SFZ2HNEz.js → dist-CS7SQP3K.js} +4 -4
- package/dist/vscode-workbench/assets/dist-VSgdjUlW.js +8 -0
- package/dist/vscode-workbench/assets/editor.worker-DmMg51ee.js +41 -0
- package/dist/vscode-workbench/assets/extensionHost.worker-BMpl1cpB.js +207 -0
- package/dist/vscode-workbench/assets/{iconv-lite-umd-izd5l6fa.js → iconv-lite-umd-D3q-1-o6.js} +1 -1
- package/dist/vscode-workbench/assets/{iconv-lite-umd-COfjYshr.js → iconv-lite-umd-Jn9RTrsv.js} +2 -2
- package/dist/vscode-workbench/assets/index-zjigpZ25.js +2842 -0
- package/dist/vscode-workbench/assets/{jschardet-Bf-VMK4F.js → jschardet-CjCVc2Gw.js} +1 -1
- package/dist/vscode-workbench/assets/{jschardet-Dh5TyKsQ.js → jschardet-Cu4ufeHq.js} +1 -1
- package/dist/vscode-workbench/assets/{layout.contribution.darwin-cz2ttHTW.js → layout.contribution.darwin-CoH1BZtz.js} +1 -1
- package/dist/vscode-workbench/assets/{layout.contribution.linux-fEtdzbcY.js → layout.contribution.linux-Di2FF-CG.js} +1 -1
- package/dist/vscode-workbench/assets/{layout.contribution.win-BFyOKI8c.js → layout.contribution.win-moiNStil.js} +1 -1
- package/dist/vscode-workbench/assets/{main-Bh8TI5LP.js → main-DzHL45xo.js} +4 -4
- package/dist/vscode-workbench/assets/{main2-Bds9Fhfn.js → main2-CWVd-Hyp.js} +1 -1
- package/dist/vscode-workbench/assets/{worker-D9ti6A0r.js → worker-CRTb-Arc.js} +7 -7
- package/dist/vscode-workbench/assets/{worker-DQtXDXIZ.js → worker-CVB8WPuM.js} +2 -2
- package/dist/vscode-workbench/index.html +1 -4
- package/package.json +8 -38
- package/dist/renderer/assets/index-6XUSo6Su.js +0 -46
- package/dist/vscode-workbench/assets/__vite-browser-external-BUwiolNy.js +0 -1
- package/dist/vscode-workbench/assets/__vite-browser-external-CmG9GjjO.js +0 -1
- package/dist/vscode-workbench/assets/__vite-browser-external-DGJPTKLg.js +0 -1
- package/dist/vscode-workbench/assets/_commonjsHelpers-qcUHfnrg.js +0 -1
- package/dist/vscode-workbench/assets/chunk-B3K2TuZy.js +0 -1
- package/dist/vscode-workbench/assets/chunk-DECur_0Z.js +0 -1
- package/dist/vscode-workbench/assets/dist-tesJ1Kd2.js +0 -8
- package/dist/vscode-workbench/assets/editor.worker-BC1qOyXG.js +0 -41
- package/dist/vscode-workbench/assets/extension.api-BWA2aPAU.js +0 -1
- package/dist/vscode-workbench/assets/extensionHost.worker-Dvu35anN.js +0 -207
- package/dist/vscode-workbench/assets/index-CQ5xP0pp.js +0 -1656
- package/dist/vscode-workbench/assets/localExtensionHost-Ccz7QUdA.js +0 -1188
- package/dist/vscode-workbench/assets/main-BDgdQmvs.js +0 -4
- package/dist/vscode-workbench/assets/main2-DwfDVleQ.js +0 -1
- package/dist/vscode-workbench/assets/preload-helper-xBbMyY7u.js +0 -1
- /package/dist/vscode-workbench/assets/{_.contribution-C9aS_G-o.js → _.contribution-B46wcGKQ.js} +0 -0
- /package/dist/vscode-workbench/assets/{_commonjsHelpers-BPKu-ps5.js → _commonjsHelpers-DMmVv2OA.js} +0 -0
package/dist/main/app/app.js
CHANGED
|
@@ -151,6 +151,7 @@ function createContext(config, mainWindow, rendererDir) {
|
|
|
151
151
|
rendererDir,
|
|
152
152
|
appName: config.appName,
|
|
153
153
|
apiNamespaces: config.apiNamespaces,
|
|
154
|
+
fileTypes: config.fileTypes,
|
|
154
155
|
brandingProvider: config.brandingProvider,
|
|
155
156
|
// The host-supplied ProjectsProvider / template types in `shared/types`
|
|
156
157
|
// are structurally compatible with the main-process equivalents —
|
|
@@ -558,6 +559,7 @@ export async function createDevtoolsRuntime(config = {}) {
|
|
|
558
559
|
rootDir: bundleDir,
|
|
559
560
|
getProjectRoot: () => context.workspace.getProjectPath(),
|
|
560
561
|
extensionsDir: config.editorViewConfig?.extensionsDir,
|
|
562
|
+
getFileTypes: () => context.fileTypes,
|
|
561
563
|
});
|
|
562
564
|
// Return the close promise so the registry awaits server shutdown on dispose
|
|
563
565
|
// instead of fire-and-forgetting it (a dangling http server would keep the
|
|
@@ -1653,6 +1653,9 @@ function buildElementsHookScript() {
|
|
|
1653
1653
|
return 'partial';
|
|
1654
1654
|
}catch(e){ return 'error:' + (e && e.message); }})()`;
|
|
1655
1655
|
}
|
|
1656
|
+
function buildReconcileScript() {
|
|
1657
|
+
return `(function(){var status; try { status = ${buildElementsHookScript()}; } catch(e){ status = 'error:'+(e&&e.message); }var batch = []; try { if (globalThis.__diminaElementsOutbound) batch = globalThis.__diminaElementsOutbound.splice(0); } catch(_){}return { status: status, batch: batch };})()`;
|
|
1658
|
+
}
|
|
1656
1659
|
var PROBE_DEVTOOLS_API = `(window.DevToolsAPI && typeof window.DevToolsAPI.dispatchMessage === 'function')`;
|
|
1657
1660
|
var MAX_SINGLE_DISPATCH_CHARS = 1e6;
|
|
1658
1661
|
var CHUNK_CHARS = 256 * 1024;
|
|
@@ -1668,13 +1671,11 @@ function buildDocumentUpdatedScript() {
|
|
|
1668
1671
|
return buildDispatchScript(msg);
|
|
1669
1672
|
}
|
|
1670
1673
|
var DRAIN_INTERVAL_MS = 150;
|
|
1671
|
-
var INSTALL_POLL_TRIES = 200;
|
|
1672
|
-
var INSTALL_POLL_INTERVAL_MS = 50;
|
|
1673
1674
|
function installElementsForward(deps) {
|
|
1674
1675
|
const { devtoolsWc, bridge } = deps;
|
|
1675
1676
|
let disposed = false;
|
|
1676
|
-
let
|
|
1677
|
-
let
|
|
1677
|
+
let reconcileTimer = null;
|
|
1678
|
+
let lateCleanup = null;
|
|
1678
1679
|
const isActiveWcId = (id) => {
|
|
1679
1680
|
const a = activeRenderWc();
|
|
1680
1681
|
return a != null && a.id === id;
|
|
@@ -1683,13 +1684,9 @@ function installElementsForward(deps) {
|
|
|
1683
1684
|
const selfAttached = /* @__PURE__ */ new Set();
|
|
1684
1685
|
const stop = () => {
|
|
1685
1686
|
disposed = true;
|
|
1686
|
-
if (
|
|
1687
|
-
clearInterval(
|
|
1688
|
-
|
|
1689
|
-
}
|
|
1690
|
-
if (drainTimer) {
|
|
1691
|
-
clearInterval(drainTimer);
|
|
1692
|
-
drainTimer = null;
|
|
1687
|
+
if (reconcileTimer) {
|
|
1688
|
+
clearInterval(reconcileTimer);
|
|
1689
|
+
reconcileTimer = null;
|
|
1693
1690
|
}
|
|
1694
1691
|
for (const cleanup of wiredGuests.values()) {
|
|
1695
1692
|
try {
|
|
@@ -1699,6 +1696,14 @@ function installElementsForward(deps) {
|
|
|
1699
1696
|
}
|
|
1700
1697
|
wiredGuests.clear();
|
|
1701
1698
|
detachSelfAttached();
|
|
1699
|
+
if (lateCleanup) {
|
|
1700
|
+
const c = lateCleanup;
|
|
1701
|
+
lateCleanup = null;
|
|
1702
|
+
try {
|
|
1703
|
+
c();
|
|
1704
|
+
} catch {
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1702
1707
|
};
|
|
1703
1708
|
function detachSelfAttached() {
|
|
1704
1709
|
for (const wcId of selfAttached) {
|
|
@@ -1908,46 +1913,26 @@ function installElementsForward(deps) {
|
|
|
1908
1913
|
const unsubscribeRenderEvents = bridge.onRenderEvent(onRenderEvent);
|
|
1909
1914
|
const onReady = () => {
|
|
1910
1915
|
if (disposed) return;
|
|
1911
|
-
if (
|
|
1912
|
-
clearInterval(
|
|
1913
|
-
|
|
1914
|
-
}
|
|
1915
|
-
if (drainTimer) {
|
|
1916
|
-
clearInterval(drainTimer);
|
|
1917
|
-
drainTimer = null;
|
|
1916
|
+
if (reconcileTimer) {
|
|
1917
|
+
clearInterval(reconcileTimer);
|
|
1918
|
+
reconcileTimer = null;
|
|
1918
1919
|
}
|
|
1919
|
-
|
|
1920
|
-
installTimer = setInterval(() => {
|
|
1921
|
-
tries++;
|
|
1920
|
+
reconcileTimer = setInterval(() => {
|
|
1922
1921
|
if (disposed || devtoolsWc.isDestroyed()) {
|
|
1923
1922
|
stop();
|
|
1924
1923
|
return;
|
|
1925
1924
|
}
|
|
1926
|
-
devtoolsWc.executeJavaScript(
|
|
1925
|
+
devtoolsWc.executeJavaScript(buildReconcileScript()).then((res) => {
|
|
1927
1926
|
if (disposed) return;
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
clearInterval(installTimer);
|
|
1931
|
-
installTimer = null;
|
|
1932
|
-
}
|
|
1927
|
+
const r = res ?? {};
|
|
1928
|
+
if (r.status === "installed") {
|
|
1933
1929
|
const wc = activeRenderWc();
|
|
1934
1930
|
if (wc) primeGuest(wc);
|
|
1935
1931
|
pushDocumentUpdated();
|
|
1936
1932
|
}
|
|
1933
|
+
handleOutbound(r.batch);
|
|
1937
1934
|
}).catch(() => {
|
|
1938
1935
|
});
|
|
1939
|
-
if (tries > INSTALL_POLL_TRIES && installTimer) {
|
|
1940
|
-
clearInterval(installTimer);
|
|
1941
|
-
installTimer = null;
|
|
1942
|
-
}
|
|
1943
|
-
}, INSTALL_POLL_INTERVAL_MS);
|
|
1944
|
-
drainTimer = setInterval(() => {
|
|
1945
|
-
if (disposed || devtoolsWc.isDestroyed()) {
|
|
1946
|
-
stop();
|
|
1947
|
-
return;
|
|
1948
|
-
}
|
|
1949
|
-
devtoolsWc.executeJavaScript("(globalThis.__diminaElementsOutbound ? __diminaElementsOutbound.splice(0) : [])").then(handleOutbound).catch(() => {
|
|
1950
|
-
});
|
|
1951
1936
|
}, DRAIN_INTERVAL_MS);
|
|
1952
1937
|
};
|
|
1953
1938
|
devtoolsWc.on("dom-ready", onReady);
|
|
@@ -1958,7 +1943,7 @@ function installElementsForward(deps) {
|
|
|
1958
1943
|
else devtoolsWc.once("destroyed", stop);
|
|
1959
1944
|
} catch {
|
|
1960
1945
|
}
|
|
1961
|
-
|
|
1946
|
+
lateCleanup = () => {
|
|
1962
1947
|
try {
|
|
1963
1948
|
unsubscribeRenderEvents();
|
|
1964
1949
|
} catch {
|
|
@@ -1971,8 +1956,8 @@ function installElementsForward(deps) {
|
|
|
1971
1956
|
devtoolsWc.removeListener("dom-ready", onReady);
|
|
1972
1957
|
} catch {
|
|
1973
1958
|
}
|
|
1974
|
-
stop();
|
|
1975
1959
|
};
|
|
1960
|
+
return stop;
|
|
1976
1961
|
}
|
|
1977
1962
|
|
|
1978
1963
|
// src/main/services/service-console/console-api.ts
|
|
@@ -2190,15 +2175,15 @@ function createSimulatorApiRegistry() {
|
|
|
2190
2175
|
import * as electron from "electron";
|
|
2191
2176
|
var SHARED_MINIAPP_PARTITION = "persist:simulator";
|
|
2192
2177
|
var PARTITION_PREFIX = "persist:miniapp-";
|
|
2193
|
-
function miniappPartitionKey(appId) {
|
|
2178
|
+
function miniappPartitionKey(appId, projectPath) {
|
|
2194
2179
|
const safe = appId.replace(/[^A-Za-z0-9_-]/g, "");
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
return
|
|
2180
|
+
const base = safe === appId && safe.length > 0 ? safe : safe.length > 0 ? `${safe}-${djb2(appId).toString(36)}` : djb2(appId).toString(36);
|
|
2181
|
+
if (!projectPath) return base;
|
|
2182
|
+
return `${base}-p${djb2(projectPath).toString(36)}`;
|
|
2198
2183
|
}
|
|
2199
|
-
function miniappPartition(appId) {
|
|
2184
|
+
function miniappPartition(appId, projectPath) {
|
|
2200
2185
|
if (!appId) return SHARED_MINIAPP_PARTITION;
|
|
2201
|
-
return `${PARTITION_PREFIX}${miniappPartitionKey(appId)}`;
|
|
2186
|
+
return `${PARTITION_PREFIX}${miniappPartitionKey(appId, projectPath)}`;
|
|
2202
2187
|
}
|
|
2203
2188
|
function djb2(input) {
|
|
2204
2189
|
let h = 5381;
|
|
@@ -2802,13 +2787,17 @@ function createViewManager(ctx) {
|
|
|
2802
2787
|
}
|
|
2803
2788
|
const openInEditorWiredWcIds = /* @__PURE__ */ new Set();
|
|
2804
2789
|
function injectOpenResourceHandler(serviceWc, devtoolsWc) {
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2790
|
+
if (serviceWc.isDestroyed() || devtoolsWc.isDestroyed()) return;
|
|
2791
|
+
try {
|
|
2792
|
+
const sourceContext = projectSourceContextFromServiceHostUrl(
|
|
2793
|
+
serviceWc.getURL(),
|
|
2794
|
+
ctx.workspace?.getProjectPath?.()
|
|
2795
|
+
);
|
|
2796
|
+
if (!sourceContext) return;
|
|
2797
|
+
devtoolsWc.executeJavaScript(buildDevtoolsProjectSourceLinksScript(sourceContext)).catch(() => {
|
|
2798
|
+
});
|
|
2799
|
+
} catch {
|
|
2800
|
+
}
|
|
2812
2801
|
}
|
|
2813
2802
|
function customizeDevtoolsTabs(devtoolsWc) {
|
|
2814
2803
|
try {
|
|
@@ -2938,13 +2927,14 @@ function createViewManager(ctx) {
|
|
|
2938
2927
|
stopElementsForward?.();
|
|
2939
2928
|
} catch {
|
|
2940
2929
|
}
|
|
2941
|
-
|
|
2930
|
+
const thisForward = installElementsForward({ devtoolsWc, bridge: ctx.bridge, connections: ctx.connections });
|
|
2931
|
+
stopElementsForward = thisForward;
|
|
2942
2932
|
devtoolsWc.once("destroyed", () => {
|
|
2943
2933
|
try {
|
|
2944
|
-
|
|
2934
|
+
thisForward();
|
|
2945
2935
|
} catch {
|
|
2946
2936
|
}
|
|
2947
|
-
stopElementsForward = null;
|
|
2937
|
+
if (stopElementsForward === thisForward) stopElementsForward = null;
|
|
2948
2938
|
});
|
|
2949
2939
|
}
|
|
2950
2940
|
devtoolsWc.once("dom-ready", () => {
|
|
@@ -2987,6 +2977,24 @@ function createViewManager(ctx) {
|
|
|
2987
2977
|
nativeCustomApiBridgeHandler = null;
|
|
2988
2978
|
}
|
|
2989
2979
|
}
|
|
2980
|
+
function tearDownNativeSimulatorView(label) {
|
|
2981
|
+
if (!nativeSimulatorView) return;
|
|
2982
|
+
if (nativeSimulatorViewAdded && !ctx.windows.mainWindow.isDestroyed()) {
|
|
2983
|
+
try {
|
|
2984
|
+
ctx.windows.mainWindow.contentView.removeChildView(nativeSimulatorView);
|
|
2985
|
+
} catch {
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
try {
|
|
2989
|
+
if (!nativeSimulatorView.webContents.isDestroyed()) {
|
|
2990
|
+
ctx.bridge?.disposeSessionsForSimulator?.(nativeSimulatorView.webContents.id)?.catch((err) => console.warn(`[view-manager] dispose sessions (${label}) failed:`, err));
|
|
2991
|
+
nativeSimulatorView.webContents.close();
|
|
2992
|
+
}
|
|
2993
|
+
} catch {
|
|
2994
|
+
}
|
|
2995
|
+
nativeSimulatorView = null;
|
|
2996
|
+
nativeSimulatorViewAdded = false;
|
|
2997
|
+
}
|
|
2990
2998
|
function attachNativeCustomApiBridge(simWc) {
|
|
2991
2999
|
detachNativeCustomApiBridge();
|
|
2992
3000
|
const apis = ctx.simulatorApis;
|
|
@@ -3015,27 +3023,14 @@ function createViewManager(ctx) {
|
|
|
3015
3023
|
settleNativeSimulatorReady = null;
|
|
3016
3024
|
if (nativeSimulatorView) {
|
|
3017
3025
|
detachNativeCustomApiBridge();
|
|
3018
|
-
|
|
3019
|
-
try {
|
|
3020
|
-
ctx.windows.mainWindow.contentView.removeChildView(nativeSimulatorView);
|
|
3021
|
-
} catch {
|
|
3022
|
-
}
|
|
3023
|
-
nativeSimulatorViewAdded = false;
|
|
3024
|
-
}
|
|
3025
|
-
try {
|
|
3026
|
-
if (!nativeSimulatorView.webContents.isDestroyed()) {
|
|
3027
|
-
nativeSimulatorView.webContents.close();
|
|
3028
|
-
}
|
|
3029
|
-
} catch {
|
|
3030
|
-
}
|
|
3031
|
-
nativeSimulatorView = null;
|
|
3026
|
+
tearDownNativeSimulatorView("relaunch");
|
|
3032
3027
|
}
|
|
3033
3028
|
nativeSimulatorProjectPath = null;
|
|
3034
3029
|
const ready = new Promise((resolve) => {
|
|
3035
3030
|
settleNativeSimulatorReady = resolve;
|
|
3036
3031
|
});
|
|
3037
3032
|
const route = parseRoute(simulatorUrl);
|
|
3038
|
-
const partition = miniappPartition(route?.appId);
|
|
3033
|
+
const partition = miniappPartition(route?.appId, ctx.workspace?.getProjectPath());
|
|
3039
3034
|
configureMiniappSession(partition);
|
|
3040
3035
|
const view = new WebContentsView2({
|
|
3041
3036
|
webPreferences: {
|
|
@@ -3145,22 +3140,7 @@ function createViewManager(ctx) {
|
|
|
3145
3140
|
stopElementsForward = null;
|
|
3146
3141
|
ctx.networkForward?.detachSimulator();
|
|
3147
3142
|
ctx.networkForward?.setDevtoolsHost(null);
|
|
3148
|
-
|
|
3149
|
-
if (nativeSimulatorViewAdded && !ctx.windows.mainWindow.isDestroyed()) {
|
|
3150
|
-
try {
|
|
3151
|
-
ctx.windows.mainWindow.contentView.removeChildView(nativeSimulatorView);
|
|
3152
|
-
} catch {
|
|
3153
|
-
}
|
|
3154
|
-
}
|
|
3155
|
-
try {
|
|
3156
|
-
if (!nativeSimulatorView.webContents.isDestroyed()) {
|
|
3157
|
-
nativeSimulatorView.webContents.close();
|
|
3158
|
-
}
|
|
3159
|
-
} catch {
|
|
3160
|
-
}
|
|
3161
|
-
nativeSimulatorView = null;
|
|
3162
|
-
nativeSimulatorViewAdded = false;
|
|
3163
|
-
}
|
|
3143
|
+
tearDownNativeSimulatorView("close");
|
|
3164
3144
|
hidePopover();
|
|
3165
3145
|
destroyViewInternal(settingsView);
|
|
3166
3146
|
settingsView = null;
|
|
@@ -3616,13 +3596,38 @@ function getSimulatorServicewechatReferer() {
|
|
|
3616
3596
|
return cachedRefererUrl;
|
|
3617
3597
|
}
|
|
3618
3598
|
|
|
3599
|
+
// src/main/services/workspace/op-lock.ts
|
|
3600
|
+
function createOpLock() {
|
|
3601
|
+
let chain = Promise.resolve();
|
|
3602
|
+
let requestSeq = 0;
|
|
3603
|
+
let ownerSeq = 0;
|
|
3604
|
+
return {
|
|
3605
|
+
nextSeq: () => ++requestSeq,
|
|
3606
|
+
takeOwnership: (seq) => {
|
|
3607
|
+
if (seq > ownerSeq) ownerSeq = seq;
|
|
3608
|
+
},
|
|
3609
|
+
isOwner: (seq) => seq === ownerSeq,
|
|
3610
|
+
acquire: () => {
|
|
3611
|
+
let release;
|
|
3612
|
+
const next = new Promise((resolve) => {
|
|
3613
|
+
release = resolve;
|
|
3614
|
+
});
|
|
3615
|
+
const prior = chain;
|
|
3616
|
+
chain = prior.then(() => next);
|
|
3617
|
+
return prior.then(() => release);
|
|
3618
|
+
}
|
|
3619
|
+
};
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3619
3622
|
// src/main/services/workspace/workspace-service.ts
|
|
3620
|
-
var SessionAppInfoSchema = z2.looseObject({ appId: z2.string() });
|
|
3623
|
+
var SessionAppInfoSchema = z2.looseObject({ appId: z2.string().min(1) });
|
|
3621
3624
|
function createWorkspaceService(ctx) {
|
|
3622
3625
|
let currentSession = null;
|
|
3623
3626
|
let currentProjectPath = "";
|
|
3627
|
+
let closing = false;
|
|
3624
3628
|
let lastClosedProjectPath = "";
|
|
3625
3629
|
let logGeneration = 0;
|
|
3630
|
+
const opLock = createOpLock();
|
|
3626
3631
|
function sendStatus(status2, message, hotReload) {
|
|
3627
3632
|
ctx.notify.projectStatus(hotReload ? { status: status2, message, hotReload: true } : { status: status2, message });
|
|
3628
3633
|
}
|
|
@@ -3648,6 +3653,65 @@ function createWorkspaceService(ctx) {
|
|
|
3648
3653
|
console.error("[workspace] session close failed:", err);
|
|
3649
3654
|
}
|
|
3650
3655
|
}
|
|
3656
|
+
async function runOpenTeardown(mySeq) {
|
|
3657
|
+
const release = await opLock.acquire();
|
|
3658
|
+
try {
|
|
3659
|
+
if (!opLock.isOwner(mySeq)) return true;
|
|
3660
|
+
clearSimulatorServicewechatReferer();
|
|
3661
|
+
if (currentSession !== null) {
|
|
3662
|
+
ctx.views.detachWorkbench();
|
|
3663
|
+
ctx.views.detachSimulator();
|
|
3664
|
+
}
|
|
3665
|
+
logGeneration++;
|
|
3666
|
+
await disposeSession();
|
|
3667
|
+
currentProjectPath = "";
|
|
3668
|
+
lastClosedProjectPath = "";
|
|
3669
|
+
return false;
|
|
3670
|
+
} finally {
|
|
3671
|
+
release();
|
|
3672
|
+
}
|
|
3673
|
+
}
|
|
3674
|
+
async function runOpenCommit(mySeq, session5, projectPath) {
|
|
3675
|
+
const release = await opLock.acquire();
|
|
3676
|
+
try {
|
|
3677
|
+
if (!opLock.isOwner(mySeq)) return false;
|
|
3678
|
+
currentSession = session5;
|
|
3679
|
+
currentProjectPath = projectPath;
|
|
3680
|
+
return true;
|
|
3681
|
+
} finally {
|
|
3682
|
+
release();
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
async function runCompile(projectPath, sessionGeneration) {
|
|
3686
|
+
const { compile } = loadWorkbenchSettings();
|
|
3687
|
+
try {
|
|
3688
|
+
const session5 = await ctx.adapter.openProject({
|
|
3689
|
+
projectPath,
|
|
3690
|
+
sourcemap: true,
|
|
3691
|
+
fileTypes: ctx.fileTypes,
|
|
3692
|
+
watch: compile.watch,
|
|
3693
|
+
onRebuild: () => sendStatus("ready", "\u7F16\u8BD1\u5B8C\u6210\uFF0C\u5DF2\u70ED\u66F4\u65B0", true),
|
|
3694
|
+
onBuildError: (err) => sendStatus("error", String(err)),
|
|
3695
|
+
onLog: (entry) => {
|
|
3696
|
+
if (sessionGeneration !== logGeneration) return;
|
|
3697
|
+
ctx.notify.compileLog({ stream: entry.stream, text: entry.text, at: Date.now() });
|
|
3698
|
+
}
|
|
3699
|
+
});
|
|
3700
|
+
return { session: session5 };
|
|
3701
|
+
} catch (err) {
|
|
3702
|
+
clearSimulatorServicewechatReferer();
|
|
3703
|
+
return { error: String(err) };
|
|
3704
|
+
}
|
|
3705
|
+
}
|
|
3706
|
+
async function rejectInvalidAppId(session5) {
|
|
3707
|
+
if (SessionAppInfoSchema.safeParse(session5.appInfo).success) return null;
|
|
3708
|
+
try {
|
|
3709
|
+
await session5.close();
|
|
3710
|
+
} catch (closeErr) {
|
|
3711
|
+
console.warn("[workspace] closing appId-less adapter session failed (non-fatal):", closeErr);
|
|
3712
|
+
}
|
|
3713
|
+
return "adapter returned session.appInfo without a string appId \u2014 the CompilationAdapter must supply appInfo.appId";
|
|
3714
|
+
}
|
|
3651
3715
|
function applyRefererFromSession(session5) {
|
|
3652
3716
|
const appInfo = session5.appInfo;
|
|
3653
3717
|
if (appInfo && typeof appInfo.appId === "string" && appInfo.appId.length > 0) {
|
|
@@ -3670,6 +3734,7 @@ function createWorkspaceService(ctx) {
|
|
|
3670
3734
|
},
|
|
3671
3735
|
validateProjectDir: async (dirPath) => provider.validateProjectDir ? provider.validateProjectDir(dirPath) : null,
|
|
3672
3736
|
async openProject(projectPath) {
|
|
3737
|
+
const mySeq = opLock.nextSeq();
|
|
3673
3738
|
if (ctx.onBeforeOpenProject) {
|
|
3674
3739
|
try {
|
|
3675
3740
|
await ctx.onBeforeOpenProject(projectPath);
|
|
@@ -3679,65 +3744,36 @@ function createWorkspaceService(ctx) {
|
|
|
3679
3744
|
return { success: false, error };
|
|
3680
3745
|
}
|
|
3681
3746
|
}
|
|
3682
|
-
|
|
3683
|
-
if (
|
|
3684
|
-
|
|
3747
|
+
opLock.takeOwnership(mySeq);
|
|
3748
|
+
if (await runOpenTeardown(mySeq)) {
|
|
3749
|
+
return { success: false, error: "superseded by a newer project open/close" };
|
|
3685
3750
|
}
|
|
3686
|
-
logGeneration++;
|
|
3687
|
-
await disposeSession();
|
|
3688
|
-
currentProjectPath = "";
|
|
3689
|
-
lastClosedProjectPath = "";
|
|
3690
3751
|
const dirError = provider.validateProjectDir ? await provider.validateProjectDir(projectPath) : null;
|
|
3691
3752
|
if (dirError) {
|
|
3692
3753
|
sendStatus("error", dirError);
|
|
3693
3754
|
return { success: false, error: dirError };
|
|
3694
3755
|
}
|
|
3695
3756
|
sendStatus("compiling", "\u6B63\u5728\u7F16\u8BD1...");
|
|
3696
|
-
const { compile } = loadWorkbenchSettings();
|
|
3697
3757
|
const sessionGeneration = ++logGeneration;
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
// (a closed/replaced session's worker flushing its buffers) are
|
|
3711
|
-
// dropped via the generation check.
|
|
3712
|
-
onLog: (entry) => {
|
|
3713
|
-
if (sessionGeneration !== logGeneration) return;
|
|
3714
|
-
ctx.notify.compileLog({
|
|
3715
|
-
stream: entry.stream,
|
|
3716
|
-
text: entry.text,
|
|
3717
|
-
at: Date.now()
|
|
3718
|
-
});
|
|
3719
|
-
}
|
|
3720
|
-
});
|
|
3721
|
-
} catch (err) {
|
|
3722
|
-
clearSimulatorServicewechatReferer();
|
|
3723
|
-
sendStatus("error", String(err));
|
|
3724
|
-
return { success: false, error: String(err) };
|
|
3725
|
-
}
|
|
3726
|
-
if (!SessionAppInfoSchema.safeParse(session5.appInfo).success) {
|
|
3758
|
+
const compiled = await runCompile(projectPath, sessionGeneration);
|
|
3759
|
+
if ("error" in compiled) {
|
|
3760
|
+
sendStatus("error", compiled.error);
|
|
3761
|
+
return { success: false, error: compiled.error };
|
|
3762
|
+
}
|
|
3763
|
+
const session5 = compiled.session;
|
|
3764
|
+
const appIdError = await rejectInvalidAppId(session5);
|
|
3765
|
+
if (appIdError) {
|
|
3766
|
+
sendStatus("error", appIdError);
|
|
3767
|
+
return { success: false, error: appIdError };
|
|
3768
|
+
}
|
|
3769
|
+
if (!await runOpenCommit(mySeq, session5, projectPath)) {
|
|
3727
3770
|
try {
|
|
3728
3771
|
await session5.close();
|
|
3729
3772
|
} catch (closeErr) {
|
|
3730
|
-
console.warn(
|
|
3731
|
-
"[workspace] closing appId-less adapter session failed (non-fatal):",
|
|
3732
|
-
closeErr
|
|
3733
|
-
);
|
|
3773
|
+
console.warn("[workspace] closing superseded open session failed (non-fatal):", closeErr);
|
|
3734
3774
|
}
|
|
3735
|
-
|
|
3736
|
-
sendStatus("error", error);
|
|
3737
|
-
return { success: false, error };
|
|
3775
|
+
return { success: false, error: "superseded by a newer project open/close" };
|
|
3738
3776
|
}
|
|
3739
|
-
currentSession = session5;
|
|
3740
|
-
currentProjectPath = projectPath;
|
|
3741
3777
|
bestEffort("updateLastOpened", () => {
|
|
3742
3778
|
if (provider.updateLastOpened) provider.updateLastOpened(projectPath);
|
|
3743
3779
|
});
|
|
@@ -3750,26 +3786,43 @@ function createWorkspaceService(ctx) {
|
|
|
3750
3786
|
};
|
|
3751
3787
|
},
|
|
3752
3788
|
async closeProject() {
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
await
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3789
|
+
const mySeq = opLock.nextSeq();
|
|
3790
|
+
opLock.takeOwnership(mySeq);
|
|
3791
|
+
const release = await opLock.acquire();
|
|
3792
|
+
try {
|
|
3793
|
+
if (!opLock.isOwner(mySeq)) return;
|
|
3794
|
+
closing = true;
|
|
3795
|
+
logGeneration++;
|
|
3796
|
+
clearSimulatorServicewechatReferer();
|
|
3797
|
+
await disposeSession();
|
|
3798
|
+
if (currentProjectPath !== "") lastClosedProjectPath = currentProjectPath;
|
|
3799
|
+
currentProjectPath = "";
|
|
3800
|
+
ctx.views.disposeAll();
|
|
3801
|
+
} finally {
|
|
3802
|
+
closing = false;
|
|
3803
|
+
release();
|
|
3804
|
+
}
|
|
3759
3805
|
},
|
|
3760
3806
|
getSession: () => currentSession,
|
|
3761
3807
|
getProjectPath: () => currentProjectPath,
|
|
3762
3808
|
getLastClosedProjectPath: () => lastClosedProjectPath,
|
|
3763
3809
|
hasActiveSession: () => currentSession !== null,
|
|
3810
|
+
isClosing: () => closing,
|
|
3764
3811
|
async captureThumbnail(projectPath) {
|
|
3765
3812
|
if (!currentSession || projectPath !== currentProjectPath) return null;
|
|
3766
|
-
const
|
|
3767
|
-
if (!
|
|
3813
|
+
const simulatorWc = ctx.views.getSimulatorWebContents();
|
|
3814
|
+
if (!simulatorWc) return null;
|
|
3768
3815
|
if (ctx.views.getSimulatorProjectPath() !== projectPath) return null;
|
|
3769
3816
|
const session5 = currentSession;
|
|
3817
|
+
const bridge = ctx.bridge;
|
|
3818
|
+
const nativeHost = bridge?.isNativeHost() ?? false;
|
|
3819
|
+
const renderGuest = nativeHost ? bridge?.getActiveRenderWc() ?? null : null;
|
|
3820
|
+
if (nativeHost && !renderGuest) return null;
|
|
3821
|
+
const captureTarget = renderGuest ?? simulatorWc;
|
|
3822
|
+
if (captureTarget.isDestroyed()) return null;
|
|
3770
3823
|
try {
|
|
3771
|
-
const image = await
|
|
3772
|
-
if (currentSession !== session5 || currentProjectPath !== projectPath || ctx.views.getSimulatorWebContents() !==
|
|
3824
|
+
const image = await captureTarget.capturePage();
|
|
3825
|
+
if (currentSession !== session5 || currentProjectPath !== projectPath || ctx.views.getSimulatorWebContents() !== simulatorWc || ctx.views.getSimulatorProjectPath() !== projectPath || (nativeHost ? bridge?.getActiveRenderWc() ?? null : simulatorWc) !== captureTarget) {
|
|
3773
3826
|
return null;
|
|
3774
3827
|
}
|
|
3775
3828
|
const dataUrl = `data:image/png;base64,${image.toPNG().toString("base64")}`;
|
|
@@ -3900,6 +3953,7 @@ function createWorkbenchContext(opts) {
|
|
|
3900
3953
|
preloadPath: opts.preloadPath,
|
|
3901
3954
|
rendererDir: opts.rendererDir,
|
|
3902
3955
|
apiNamespaces: opts.apiNamespaces ?? [],
|
|
3956
|
+
fileTypes: opts.fileTypes ?? {},
|
|
3903
3957
|
appName: opts.appName ?? "Dimina DevTools",
|
|
3904
3958
|
brandingProvider: opts.brandingProvider
|
|
3905
3959
|
};
|
|
@@ -4702,12 +4756,15 @@ function navigateServiceHost(win, url) {
|
|
|
4702
4756
|
}
|
|
4703
4757
|
return loaded;
|
|
4704
4758
|
}
|
|
4705
|
-
function serviceHostSpec(appId) {
|
|
4759
|
+
function serviceHostSpec(appId, projectPath) {
|
|
4706
4760
|
return {
|
|
4707
4761
|
// Per-project partition when an appId is known (so this project's service
|
|
4708
4762
|
// host shares storage ONLY with its own render side); the shared partition
|
|
4709
4763
|
// for the pre-warm pool's default spec (no appId — see KNOWN BLOCKER below).
|
|
4710
|
-
|
|
4764
|
+
// projectPath joins the key so same-appId/different-path projects isolate;
|
|
4765
|
+
// it must match the simulator WCV's partition (view-manager passes the same
|
|
4766
|
+
// (appId, projectPath)).
|
|
4767
|
+
partition: appId ? miniappPartition(appId, projectPath) : SERVICE_HOST_PARTITION,
|
|
4711
4768
|
preloadPath: serviceHostPreloadPath,
|
|
4712
4769
|
size: { width: 980, height: 720 },
|
|
4713
4770
|
contextIsolation: false,
|
|
@@ -4717,7 +4774,7 @@ function serviceHostSpec(appId) {
|
|
|
4717
4774
|
};
|
|
4718
4775
|
}
|
|
4719
4776
|
function createServiceHostWindow(opts) {
|
|
4720
|
-
const win = constructServiceHostWindow({ appId: opts.appId, partition: miniappPartition(opts.appId) });
|
|
4777
|
+
const win = constructServiceHostWindow({ appId: opts.appId, partition: miniappPartition(opts.appId, opts.projectPath) });
|
|
4721
4778
|
void navigateServiceHost(win, buildServiceHostSpawnUrl(opts));
|
|
4722
4779
|
return win;
|
|
4723
4780
|
}
|
|
@@ -5625,9 +5682,14 @@ function resolveCurrentApp(state, ctx, appId) {
|
|
|
5625
5682
|
for (const ap of state.appSessions.values()) if (ap.appId === activeAppId) match = ap;
|
|
5626
5683
|
if (match) return match;
|
|
5627
5684
|
}
|
|
5685
|
+
if (ctx.workspace?.isClosing?.()) return void 0;
|
|
5628
5686
|
let last;
|
|
5629
|
-
|
|
5630
|
-
|
|
5687
|
+
const distinctAppIds = /* @__PURE__ */ new Set();
|
|
5688
|
+
for (const ap of state.appSessions.values()) {
|
|
5689
|
+
last = ap;
|
|
5690
|
+
distinctAppIds.add(ap.appId);
|
|
5691
|
+
}
|
|
5692
|
+
return distinctAppIds.size <= 1 ? last : void 0;
|
|
5631
5693
|
}
|
|
5632
5694
|
function installBridgeRouter(ctx) {
|
|
5633
5695
|
const state = {
|
|
@@ -5731,6 +5793,14 @@ function installBridgeRouter(ctx) {
|
|
|
5731
5793
|
}
|
|
5732
5794
|
}
|
|
5733
5795
|
},
|
|
5796
|
+
disposeSessionsForSimulator: (simulatorWcId) => {
|
|
5797
|
+
const ids = [];
|
|
5798
|
+
for (const [id, ap] of state.appSessions) {
|
|
5799
|
+
if (ap.simulatorWc.id === simulatorWcId) ids.push(id);
|
|
5800
|
+
}
|
|
5801
|
+
return Promise.all(ids.map((id) => disposeAppSession(state, id))).then(() => {
|
|
5802
|
+
});
|
|
5803
|
+
},
|
|
5734
5804
|
debugTap: state.debugTap
|
|
5735
5805
|
};
|
|
5736
5806
|
ctx.bridge = bridgeHandle;
|
|
@@ -5944,6 +6014,13 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
5944
6014
|
serviceWindow = createServiceHostWindow({
|
|
5945
6015
|
bridgeId,
|
|
5946
6016
|
appId,
|
|
6017
|
+
// Same (appId, projectPath) pair the simulator WCV uses, so this project's
|
|
6018
|
+
// service host and render guests land on ONE partition while a different
|
|
6019
|
+
// project with the same appId is isolated. Use the path captured at spawn
|
|
6020
|
+
// ENTRY (workspaceProjectPath), not a re-read: a project switch during the
|
|
6021
|
+
// awaits above would otherwise give the service host a different path than
|
|
6022
|
+
// the simulator WCV was built with, splitting the partition.
|
|
6023
|
+
projectPath: workspaceProjectPath || void 0,
|
|
5947
6024
|
pagePath,
|
|
5948
6025
|
pkgRoot,
|
|
5949
6026
|
root,
|
|
@@ -6004,6 +6081,9 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
6004
6081
|
void disposeAppSession(state, appSessionId);
|
|
6005
6082
|
};
|
|
6006
6083
|
simulatorWc.once("destroyed", onSimulatorDestroyed);
|
|
6084
|
+
if (simulatorWc.isDestroyed()) {
|
|
6085
|
+
void disposeAppSession(state, appSessionId);
|
|
6086
|
+
}
|
|
6007
6087
|
if (usedPool) {
|
|
6008
6088
|
const bootOnServiceLoad = () => {
|
|
6009
6089
|
if (serviceWindow.isDestroyed()) return;
|
|
@@ -6518,6 +6598,10 @@ async function disposeAppSession(state, appSessionId, opts = {}) {
|
|
|
6518
6598
|
for (const page of ap.pages.values()) {
|
|
6519
6599
|
if (page.renderWc && !page.renderWc.isDestroyed()) {
|
|
6520
6600
|
state.wcIdToBridgeId.delete(page.renderWc.id);
|
|
6601
|
+
try {
|
|
6602
|
+
page.renderWc.close();
|
|
6603
|
+
} catch {
|
|
6604
|
+
}
|
|
6521
6605
|
}
|
|
6522
6606
|
state.pageSessions.delete(page.bridgeId);
|
|
6523
6607
|
}
|
|
@@ -9792,6 +9876,10 @@ async function startWorkbenchCoiServer(options) {
|
|
|
9792
9876
|
});
|
|
9793
9877
|
return;
|
|
9794
9878
|
}
|
|
9879
|
+
if (url.pathname === "/__filetypes") {
|
|
9880
|
+
jsonRes(res, 200, options.getFileTypes?.() ?? {});
|
|
9881
|
+
return;
|
|
9882
|
+
}
|
|
9795
9883
|
if (url.pathname.startsWith("/__contrib/")) {
|
|
9796
9884
|
if (!contribRoot) {
|
|
9797
9885
|
res.writeHead(404);
|
|
@@ -10017,6 +10105,7 @@ function createContext(config, mainWindow, rendererDir2) {
|
|
|
10017
10105
|
rendererDir: rendererDir2,
|
|
10018
10106
|
appName: config.appName,
|
|
10019
10107
|
apiNamespaces: config.apiNamespaces,
|
|
10108
|
+
fileTypes: config.fileTypes,
|
|
10020
10109
|
brandingProvider: config.brandingProvider,
|
|
10021
10110
|
// The host-supplied ProjectsProvider / template types in `shared/types`
|
|
10022
10111
|
// are structurally compatible with the main-process equivalents —
|
|
@@ -10291,7 +10380,8 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
10291
10380
|
const coiServer = await startWorkbenchCoiServer({
|
|
10292
10381
|
rootDir: bundleDir,
|
|
10293
10382
|
getProjectRoot: () => context.workspace.getProjectPath(),
|
|
10294
|
-
extensionsDir: config.editorViewConfig?.extensionsDir
|
|
10383
|
+
extensionsDir: config.editorViewConfig?.extensionsDir,
|
|
10384
|
+
getFileTypes: () => context.fileTypes
|
|
10295
10385
|
});
|
|
10296
10386
|
context.registry.add(() => coiServer.close());
|
|
10297
10387
|
context.registry.add(() => context.views.detachWorkbench());
|