@dimina-kit/devtools 0.3.2-dev.20260610082053 → 0.3.2-dev.20260611060732
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 +8 -1
- package/dist/main/index.bundle.js +286 -161
- package/dist/main/ipc/bridge-router.js +36 -3
- package/dist/main/ipc/simulator.js +1 -21
- package/dist/main/services/simulator-temp-files/index.js +38 -16
- package/dist/main/services/views/miniapp-partition.d.ts +80 -0
- package/dist/main/services/views/miniapp-partition.js +138 -0
- package/dist/main/services/views/simulator-session-policy.d.ts +28 -0
- package/dist/main/services/views/simulator-session-policy.js +82 -0
- package/dist/main/services/views/view-manager.js +22 -9
- package/dist/main/windows/main-window/create.js +1 -27
- package/dist/main/windows/service-host-window/create.d.ts +19 -4
- package/dist/main/windows/service-host-window/create.js +34 -8
- package/dist/native-host/container/pageFrame.css +1 -1
- package/dist/native-host/render/render.js +23 -15
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/windows/main.cjs.map +1 -1
- package/dist/preload/windows/simulator.cjs.map +1 -1
- package/dist/service-host/sync-impls/menu-button-geometry.js +8 -0
- package/dist/service-host/sync-impls/menu-button.js +1 -1
- package/dist/shared/bridge-channels.d.ts +14 -0
- package/dist/shared/bridge-channels.js +27 -0
- package/dist/simulator/assets/{device-shell-vwYSOVrh.js → device-shell-fH2cI-3q.js} +2 -2
- package/dist/simulator/assets/{simulator-DddliUL5.js → simulator-DHylZf9Z.js} +3 -3
- package/dist/simulator/simulator.html +1 -1
- package/package.json +6 -5
|
@@ -751,7 +751,7 @@ function registerProjectFsIpc(ctx) {
|
|
|
751
751
|
}
|
|
752
752
|
|
|
753
753
|
// src/main/app/app.ts
|
|
754
|
-
import { app as app14, BrowserWindow as BrowserWindow7, nativeImage, session as
|
|
754
|
+
import { app as app14, BrowserWindow as BrowserWindow7, nativeImage, session as session3 } from "electron";
|
|
755
755
|
import fs11 from "fs";
|
|
756
756
|
import path20 from "path";
|
|
757
757
|
|
|
@@ -808,28 +808,9 @@ function installThemeBackgroundSync() {
|
|
|
808
808
|
}
|
|
809
809
|
|
|
810
810
|
// src/main/windows/main-window/create.ts
|
|
811
|
-
import { app as app3, BrowserWindow as BrowserWindow2, View
|
|
811
|
+
import { app as app3, BrowserWindow as BrowserWindow2, View } from "electron";
|
|
812
812
|
import path5 from "path";
|
|
813
813
|
|
|
814
|
-
// src/main/services/simulator/referer.ts
|
|
815
|
-
var DEFAULT_VERSION = "develop";
|
|
816
|
-
var cachedRefererUrl = null;
|
|
817
|
-
function buildServicewechatPageFrameReferer(appId, version = DEFAULT_VERSION) {
|
|
818
|
-
return `https://servicewechat.com/${appId}/${version}/page-frame.html`;
|
|
819
|
-
}
|
|
820
|
-
function setSimulatorServicewechatReferer(appId, version) {
|
|
821
|
-
cachedRefererUrl = buildServicewechatPageFrameReferer(
|
|
822
|
-
appId,
|
|
823
|
-
version && version.length > 0 ? version : DEFAULT_VERSION
|
|
824
|
-
);
|
|
825
|
-
}
|
|
826
|
-
function clearSimulatorServicewechatReferer() {
|
|
827
|
-
cachedRefererUrl = null;
|
|
828
|
-
}
|
|
829
|
-
function getSimulatorServicewechatReferer() {
|
|
830
|
-
return cachedRefererUrl;
|
|
831
|
-
}
|
|
832
|
-
|
|
833
814
|
// src/main/windows/navigation-hardening.ts
|
|
834
815
|
import { shell } from "electron";
|
|
835
816
|
import path4 from "path";
|
|
@@ -866,28 +847,7 @@ function applyNavigationHardening(wc, rendererDir2) {
|
|
|
866
847
|
}
|
|
867
848
|
|
|
868
849
|
// src/main/windows/main-window/create.ts
|
|
869
|
-
var simulatorSessionConfigured = false;
|
|
870
|
-
function configureSimulatorSession() {
|
|
871
|
-
if (simulatorSessionConfigured) return;
|
|
872
|
-
simulatorSessionConfigured = true;
|
|
873
|
-
const simulatorSession = session.fromPartition("persist:simulator");
|
|
874
|
-
simulatorSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
|
875
|
-
const forcedReferer = getSimulatorServicewechatReferer();
|
|
876
|
-
if (forcedReferer) {
|
|
877
|
-
details.requestHeaders["Referer"] = forcedReferer;
|
|
878
|
-
}
|
|
879
|
-
callback({ requestHeaders: details.requestHeaders });
|
|
880
|
-
});
|
|
881
|
-
simulatorSession.webRequest.onHeadersReceived((details, callback) => {
|
|
882
|
-
const headers = details.responseHeaders ?? {};
|
|
883
|
-
headers["access-control-allow-origin"] = ["*"];
|
|
884
|
-
headers["access-control-allow-headers"] = ["*"];
|
|
885
|
-
headers["access-control-allow-methods"] = ["*"];
|
|
886
|
-
callback({ responseHeaders: headers });
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
850
|
function createMainWindow(opts) {
|
|
890
|
-
configureSimulatorSession();
|
|
891
851
|
const mainWindow = new BrowserWindow2({
|
|
892
852
|
width: opts.width ?? 1280,
|
|
893
853
|
height: opts.height ?? 980,
|
|
@@ -1652,6 +1612,93 @@ function createSimulatorApiRegistry() {
|
|
|
1652
1612
|
};
|
|
1653
1613
|
}
|
|
1654
1614
|
|
|
1615
|
+
// src/main/services/views/miniapp-partition.ts
|
|
1616
|
+
import * as electron from "electron";
|
|
1617
|
+
var SHARED_MINIAPP_PARTITION = "persist:simulator";
|
|
1618
|
+
var PARTITION_PREFIX = "persist:miniapp-";
|
|
1619
|
+
function miniappPartitionKey(appId) {
|
|
1620
|
+
const safe = appId.replace(/[^A-Za-z0-9_-]/g, "");
|
|
1621
|
+
if (safe === appId && safe.length > 0) return safe;
|
|
1622
|
+
const hash = djb2(appId).toString(36);
|
|
1623
|
+
return safe.length > 0 ? `${safe}-${hash}` : hash;
|
|
1624
|
+
}
|
|
1625
|
+
function miniappPartition(appId) {
|
|
1626
|
+
if (!appId) return SHARED_MINIAPP_PARTITION;
|
|
1627
|
+
return `${PARTITION_PREFIX}${miniappPartitionKey(appId)}`;
|
|
1628
|
+
}
|
|
1629
|
+
function djb2(input) {
|
|
1630
|
+
let h = 5381;
|
|
1631
|
+
for (let i = 0; i < input.length; i++) {
|
|
1632
|
+
h = (h << 5) + h + input.charCodeAt(i) >>> 0;
|
|
1633
|
+
}
|
|
1634
|
+
return h;
|
|
1635
|
+
}
|
|
1636
|
+
var configurators = /* @__PURE__ */ new Set();
|
|
1637
|
+
var configuredPartitions = /* @__PURE__ */ new Set();
|
|
1638
|
+
function registerMiniappSessionConfigurator(fn) {
|
|
1639
|
+
configurators.add(fn);
|
|
1640
|
+
for (const partition of configuredPartitions) {
|
|
1641
|
+
try {
|
|
1642
|
+
fn(electron.session.fromPartition(partition), partition);
|
|
1643
|
+
} catch (err) {
|
|
1644
|
+
console.warn("[miniapp-partition] configurator failed for", partition, err);
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
return () => {
|
|
1648
|
+
configurators.delete(fn);
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
function configureMiniappSession(partition) {
|
|
1652
|
+
const alreadyConfigured = configuredPartitions.has(partition);
|
|
1653
|
+
configuredPartitions.add(partition);
|
|
1654
|
+
if (configurators.size === 0) return null;
|
|
1655
|
+
const sess = electron.session.fromPartition(partition);
|
|
1656
|
+
if (alreadyConfigured) return sess;
|
|
1657
|
+
for (const fn of configurators) {
|
|
1658
|
+
try {
|
|
1659
|
+
fn(sess, partition);
|
|
1660
|
+
} catch (err) {
|
|
1661
|
+
console.warn("[miniapp-partition] configurator failed for", partition, err);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
return sess;
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
// src/shared/simulator-route.ts
|
|
1668
|
+
function decodePageSpec(value) {
|
|
1669
|
+
const qIdx = value.indexOf("?");
|
|
1670
|
+
if (qIdx < 0) return { pagePath: value, query: {} };
|
|
1671
|
+
const pagePath = value.slice(0, qIdx);
|
|
1672
|
+
const query = {};
|
|
1673
|
+
for (const pair of value.slice(qIdx + 1).split("&")) {
|
|
1674
|
+
if (!pair) continue;
|
|
1675
|
+
const eqIdx = pair.indexOf("=");
|
|
1676
|
+
const k = eqIdx >= 0 ? pair.slice(0, eqIdx) : pair;
|
|
1677
|
+
const v = eqIdx >= 0 ? pair.slice(eqIdx + 1) : "";
|
|
1678
|
+
if (k) query[decodeURIComponent(k)] = decodeURIComponent(v);
|
|
1679
|
+
}
|
|
1680
|
+
return { pagePath, query };
|
|
1681
|
+
}
|
|
1682
|
+
function parseLocationRoute(search) {
|
|
1683
|
+
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
|
|
1684
|
+
const appId = params.get("appId");
|
|
1685
|
+
const entryRaw = params.get("entry");
|
|
1686
|
+
if (!appId || !entryRaw) return null;
|
|
1687
|
+
const entry = decodePageSpec(entryRaw);
|
|
1688
|
+
const pageRaw = params.get("page");
|
|
1689
|
+
const current = pageRaw && pageRaw !== entryRaw ? decodePageSpec(pageRaw) : entry;
|
|
1690
|
+
return { appId, entry, current };
|
|
1691
|
+
}
|
|
1692
|
+
function parseRoute(url) {
|
|
1693
|
+
if (!url) return null;
|
|
1694
|
+
try {
|
|
1695
|
+
const u = new URL(url);
|
|
1696
|
+
return parseLocationRoute(u.search);
|
|
1697
|
+
} catch {
|
|
1698
|
+
return null;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1655
1702
|
// src/main/services/views/view-manager.ts
|
|
1656
1703
|
function createViewManager(ctx) {
|
|
1657
1704
|
const headerHeight = ctx.headerHeight ?? 40;
|
|
@@ -2164,6 +2211,9 @@ function createViewManager(ctx) {
|
|
|
2164
2211
|
}
|
|
2165
2212
|
nativeSimulatorView = null;
|
|
2166
2213
|
}
|
|
2214
|
+
const route = parseRoute(simulatorUrl);
|
|
2215
|
+
const partition = miniappPartition(route?.appId);
|
|
2216
|
+
configureMiniappSession(partition);
|
|
2167
2217
|
const view = new WebContentsView2({
|
|
2168
2218
|
webPreferences: {
|
|
2169
2219
|
nodeIntegration: false,
|
|
@@ -2171,7 +2221,7 @@ function createViewManager(ctx) {
|
|
|
2171
2221
|
sandbox: false,
|
|
2172
2222
|
webviewTag: true,
|
|
2173
2223
|
preload: cjsSiblingPreloadPath(ctx.preloadPath),
|
|
2174
|
-
partition
|
|
2224
|
+
partition
|
|
2175
2225
|
}
|
|
2176
2226
|
});
|
|
2177
2227
|
nativeSimulatorView = view;
|
|
@@ -2180,8 +2230,8 @@ function createViewManager(ctx) {
|
|
|
2180
2230
|
attachNativeCustomApiBridge(simWc);
|
|
2181
2231
|
simWc.on("will-attach-webview", (_event, webPreferences, params) => {
|
|
2182
2232
|
;
|
|
2183
|
-
webPreferences.partition =
|
|
2184
|
-
params.partition =
|
|
2233
|
+
webPreferences.partition = partition;
|
|
2234
|
+
params.partition = partition;
|
|
2185
2235
|
webPreferences.contextIsolation = false;
|
|
2186
2236
|
webPreferences.sandbox = false;
|
|
2187
2237
|
});
|
|
@@ -2641,6 +2691,25 @@ var DEFAULT_COMPILE_CONFIG = {
|
|
|
2641
2691
|
queryParams: []
|
|
2642
2692
|
};
|
|
2643
2693
|
|
|
2694
|
+
// src/main/services/simulator/referer.ts
|
|
2695
|
+
var DEFAULT_VERSION = "develop";
|
|
2696
|
+
var cachedRefererUrl = null;
|
|
2697
|
+
function buildServicewechatPageFrameReferer(appId, version = DEFAULT_VERSION) {
|
|
2698
|
+
return `https://servicewechat.com/${appId}/${version}/page-frame.html`;
|
|
2699
|
+
}
|
|
2700
|
+
function setSimulatorServicewechatReferer(appId, version) {
|
|
2701
|
+
cachedRefererUrl = buildServicewechatPageFrameReferer(
|
|
2702
|
+
appId,
|
|
2703
|
+
version && version.length > 0 ? version : DEFAULT_VERSION
|
|
2704
|
+
);
|
|
2705
|
+
}
|
|
2706
|
+
function clearSimulatorServicewechatReferer() {
|
|
2707
|
+
cachedRefererUrl = null;
|
|
2708
|
+
}
|
|
2709
|
+
function getSimulatorServicewechatReferer() {
|
|
2710
|
+
return cachedRefererUrl;
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2644
2713
|
// src/main/services/workspace/workspace-service.ts
|
|
2645
2714
|
function createWorkspaceService(ctx) {
|
|
2646
2715
|
let currentSession = null;
|
|
@@ -2658,11 +2727,11 @@ function createWorkspaceService(ctx) {
|
|
|
2658
2727
|
}
|
|
2659
2728
|
async function disposeSession() {
|
|
2660
2729
|
if (!currentSession) return;
|
|
2661
|
-
const
|
|
2730
|
+
const session4 = currentSession;
|
|
2662
2731
|
currentSession = null;
|
|
2663
2732
|
try {
|
|
2664
2733
|
await Promise.race([
|
|
2665
|
-
|
|
2734
|
+
session4.close(),
|
|
2666
2735
|
new Promise(
|
|
2667
2736
|
(_, reject) => setTimeout(() => reject(new Error("session close timed out")), 5e3)
|
|
2668
2737
|
)
|
|
@@ -2671,8 +2740,8 @@ function createWorkspaceService(ctx) {
|
|
|
2671
2740
|
console.error("[workspace] session close failed:", err);
|
|
2672
2741
|
}
|
|
2673
2742
|
}
|
|
2674
|
-
function applyRefererFromSession(
|
|
2675
|
-
const appInfo =
|
|
2743
|
+
function applyRefererFromSession(session4) {
|
|
2744
|
+
const appInfo = session4.appInfo;
|
|
2676
2745
|
if (appInfo && typeof appInfo.appId === "string" && appInfo.appId.length > 0) {
|
|
2677
2746
|
setSimulatorServicewechatReferer(
|
|
2678
2747
|
appInfo.appId,
|
|
@@ -2704,9 +2773,9 @@ function createWorkspaceService(ctx) {
|
|
|
2704
2773
|
}
|
|
2705
2774
|
sendStatus("compiling", "\u6B63\u5728\u7F16\u8BD1...");
|
|
2706
2775
|
const { compile } = loadWorkbenchSettings();
|
|
2707
|
-
let
|
|
2776
|
+
let session4;
|
|
2708
2777
|
try {
|
|
2709
|
-
|
|
2778
|
+
session4 = await ctx.adapter.openProject({
|
|
2710
2779
|
projectPath,
|
|
2711
2780
|
sourcemap: true,
|
|
2712
2781
|
watch: compile.watch,
|
|
@@ -2718,17 +2787,17 @@ function createWorkspaceService(ctx) {
|
|
|
2718
2787
|
sendStatus("error", String(err));
|
|
2719
2788
|
return { success: false, error: String(err) };
|
|
2720
2789
|
}
|
|
2721
|
-
currentSession =
|
|
2790
|
+
currentSession = session4;
|
|
2722
2791
|
currentProjectPath = projectPath;
|
|
2723
2792
|
bestEffort("updateLastOpened", () => {
|
|
2724
2793
|
if (provider.updateLastOpened) provider.updateLastOpened(projectPath);
|
|
2725
2794
|
});
|
|
2726
2795
|
bestEffort("sendStatus", () => sendStatus("ready", "\u7F16\u8BD1\u5B8C\u6210"));
|
|
2727
|
-
bestEffort("applyReferer", () => applyRefererFromSession(
|
|
2796
|
+
bestEffort("applyReferer", () => applyRefererFromSession(session4));
|
|
2728
2797
|
return {
|
|
2729
2798
|
success: true,
|
|
2730
|
-
port:
|
|
2731
|
-
appInfo:
|
|
2799
|
+
port: session4.port,
|
|
2800
|
+
appInfo: session4.appInfo
|
|
2732
2801
|
};
|
|
2733
2802
|
},
|
|
2734
2803
|
async closeProject() {
|
|
@@ -3134,7 +3203,59 @@ var PanelSelectSchema = z2.tuple([z2.string().min(1).max(200)]);
|
|
|
3134
3203
|
var ProjectCaptureThumbnailSchema = z2.tuple([AbsolutePath]);
|
|
3135
3204
|
var ProjectGetThumbnailSchema = z2.tuple([AbsolutePath]);
|
|
3136
3205
|
|
|
3137
|
-
// src/
|
|
3206
|
+
// src/shared/bridge-channels.ts
|
|
3207
|
+
var BRIDGE_CHANNELS = {
|
|
3208
|
+
SPAWN: "dmb:spawn",
|
|
3209
|
+
DISPOSE: "dmb:dispose",
|
|
3210
|
+
PAGE_OPEN: "dmb:page:open",
|
|
3211
|
+
PAGE_CLOSE: "dmb:page:close",
|
|
3212
|
+
PAGE_LIFECYCLE: "dmb:page:lifecycle",
|
|
3213
|
+
NAV_CALLBACK: "dmb:nav:callback",
|
|
3214
|
+
SERVICE_INVOKE: "dmb:service:invoke",
|
|
3215
|
+
SERVICE_PUBLISH: "dmb:service:publish",
|
|
3216
|
+
RENDER_INVOKE: "dmb:render:invoke",
|
|
3217
|
+
RENDER_PUBLISH: "dmb:render:publish",
|
|
3218
|
+
TO_SERVICE: "dmb:to-service",
|
|
3219
|
+
TO_RENDER: "dmb:to-render",
|
|
3220
|
+
SIMULATOR_API: "dmb:simulator-api",
|
|
3221
|
+
/** simulator → main: ack of an API_CALL request (carries success/fail args). */
|
|
3222
|
+
API_RESPONSE: "dmb:api:response",
|
|
3223
|
+
/**
|
|
3224
|
+
* simulator webview preload → main (sendSync): "is native-host mode on?".
|
|
3225
|
+
* The guest preload can't read the launch `process.env`, so it asks main
|
|
3226
|
+
* (which can) at install time. Reply is `e.returnValue = boolean`.
|
|
3227
|
+
*/
|
|
3228
|
+
NATIVE_HOST_ENABLED: "dmb:native-host-enabled",
|
|
3229
|
+
/**
|
|
3230
|
+
* simulator (DeviceShell) → main: the visible top-of-stack page bridgeId.
|
|
3231
|
+
* Main has no z-order concept — the active page lives only in DeviceShell's
|
|
3232
|
+
* ShellState — so devtools panels / automation that must target "the current
|
|
3233
|
+
* page's render webContents" resolve it through this signal. Fire-and-forget.
|
|
3234
|
+
*/
|
|
3235
|
+
ACTIVE_PAGE: "dmb:active-page",
|
|
3236
|
+
/**
|
|
3237
|
+
* simulator (DeviceShell) → main: the FULL ordered page stack (bottom→top)
|
|
3238
|
+
* whenever it changes. Main has no stack of its own (it only learns the
|
|
3239
|
+
* active bridgeId via ACTIVE_PAGE), so automation's `App.getPageStack` needs
|
|
3240
|
+
* this to report multi-page stacks. Fire-and-forget.
|
|
3241
|
+
*/
|
|
3242
|
+
PAGE_STACK: "dmb:page-stack"
|
|
3243
|
+
};
|
|
3244
|
+
var SIMULATOR_EVENTS = {
|
|
3245
|
+
DOM_READY: "simulator:dom-ready",
|
|
3246
|
+
NAV_BAR: "simulator:navigation-bar",
|
|
3247
|
+
NAV_ACTION: "simulator:nav-action",
|
|
3248
|
+
TAB_ACTION: "simulator:tab-action",
|
|
3249
|
+
/** main → simulator: invoke a wx.* API on the simulator-resident MiniApp. */
|
|
3250
|
+
API_CALL: "simulator:api-call",
|
|
3251
|
+
/**
|
|
3252
|
+
* main → simulator: the renderer toolbar picked a different device. Carries a
|
|
3253
|
+
* NativeDeviceInfo; DeviceShell resizes the bezel + re-renders status bar /
|
|
3254
|
+
* notch. The race-free INITIAL device rides NativeHostConfig.device (read
|
|
3255
|
+
* synchronously at preload bridge-install); this event covers live changes.
|
|
3256
|
+
*/
|
|
3257
|
+
DEVICE_CHANGE: "simulator:device-change"
|
|
3258
|
+
};
|
|
3138
3259
|
function deviceInfoToHostEnv(d) {
|
|
3139
3260
|
return {
|
|
3140
3261
|
brand: d.brand,
|
|
@@ -3149,6 +3270,8 @@ function deviceInfoToHostEnv(d) {
|
|
|
3149
3270
|
statusBarHeight: d.statusBarHeight
|
|
3150
3271
|
};
|
|
3151
3272
|
}
|
|
3273
|
+
|
|
3274
|
+
// src/main/ipc/simulator.ts
|
|
3152
3275
|
function registerSimulatorIpc(ctx) {
|
|
3153
3276
|
return new IpcRegistry(ctx.senderPolicy).handle(SimulatorChannel.AttachNative, (_, ...args) => {
|
|
3154
3277
|
const [simulatorUrl, simWidth] = validate(SimulatorChannel.AttachNative, SimulatorAttachNativeSchema, args);
|
|
@@ -3569,60 +3692,6 @@ import { app as app11, ipcMain as ipcMain3, protocol as protocol2, session as el
|
|
|
3569
3692
|
import path15 from "node:path";
|
|
3570
3693
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
3571
3694
|
|
|
3572
|
-
// src/shared/bridge-channels.ts
|
|
3573
|
-
var BRIDGE_CHANNELS = {
|
|
3574
|
-
SPAWN: "dmb:spawn",
|
|
3575
|
-
DISPOSE: "dmb:dispose",
|
|
3576
|
-
PAGE_OPEN: "dmb:page:open",
|
|
3577
|
-
PAGE_CLOSE: "dmb:page:close",
|
|
3578
|
-
PAGE_LIFECYCLE: "dmb:page:lifecycle",
|
|
3579
|
-
NAV_CALLBACK: "dmb:nav:callback",
|
|
3580
|
-
SERVICE_INVOKE: "dmb:service:invoke",
|
|
3581
|
-
SERVICE_PUBLISH: "dmb:service:publish",
|
|
3582
|
-
RENDER_INVOKE: "dmb:render:invoke",
|
|
3583
|
-
RENDER_PUBLISH: "dmb:render:publish",
|
|
3584
|
-
TO_SERVICE: "dmb:to-service",
|
|
3585
|
-
TO_RENDER: "dmb:to-render",
|
|
3586
|
-
SIMULATOR_API: "dmb:simulator-api",
|
|
3587
|
-
/** simulator → main: ack of an API_CALL request (carries success/fail args). */
|
|
3588
|
-
API_RESPONSE: "dmb:api:response",
|
|
3589
|
-
/**
|
|
3590
|
-
* simulator webview preload → main (sendSync): "is native-host mode on?".
|
|
3591
|
-
* The guest preload can't read the launch `process.env`, so it asks main
|
|
3592
|
-
* (which can) at install time. Reply is `e.returnValue = boolean`.
|
|
3593
|
-
*/
|
|
3594
|
-
NATIVE_HOST_ENABLED: "dmb:native-host-enabled",
|
|
3595
|
-
/**
|
|
3596
|
-
* simulator (DeviceShell) → main: the visible top-of-stack page bridgeId.
|
|
3597
|
-
* Main has no z-order concept — the active page lives only in DeviceShell's
|
|
3598
|
-
* ShellState — so devtools panels / automation that must target "the current
|
|
3599
|
-
* page's render webContents" resolve it through this signal. Fire-and-forget.
|
|
3600
|
-
*/
|
|
3601
|
-
ACTIVE_PAGE: "dmb:active-page",
|
|
3602
|
-
/**
|
|
3603
|
-
* simulator (DeviceShell) → main: the FULL ordered page stack (bottom→top)
|
|
3604
|
-
* whenever it changes. Main has no stack of its own (it only learns the
|
|
3605
|
-
* active bridgeId via ACTIVE_PAGE), so automation's `App.getPageStack` needs
|
|
3606
|
-
* this to report multi-page stacks. Fire-and-forget.
|
|
3607
|
-
*/
|
|
3608
|
-
PAGE_STACK: "dmb:page-stack"
|
|
3609
|
-
};
|
|
3610
|
-
var SIMULATOR_EVENTS = {
|
|
3611
|
-
DOM_READY: "simulator:dom-ready",
|
|
3612
|
-
NAV_BAR: "simulator:navigation-bar",
|
|
3613
|
-
NAV_ACTION: "simulator:nav-action",
|
|
3614
|
-
TAB_ACTION: "simulator:tab-action",
|
|
3615
|
-
/** main → simulator: invoke a wx.* API on the simulator-resident MiniApp. */
|
|
3616
|
-
API_CALL: "simulator:api-call",
|
|
3617
|
-
/**
|
|
3618
|
-
* main → simulator: the renderer toolbar picked a different device. Carries a
|
|
3619
|
-
* NativeDeviceInfo; DeviceShell resizes the bezel + re-renders status bar /
|
|
3620
|
-
* notch. The race-free INITIAL device rides NativeHostConfig.device (read
|
|
3621
|
-
* synchronously at preload bridge-install); this event covers live changes.
|
|
3622
|
-
*/
|
|
3623
|
-
DEVICE_CHANGE: "simulator:device-change"
|
|
3624
|
-
};
|
|
3625
|
-
|
|
3626
3695
|
// src/shared/simulator-api-metadata.ts
|
|
3627
3696
|
var PERSISTENT_SIMULATOR_APIS = /* @__PURE__ */ new Set(["audioListen"]);
|
|
3628
3697
|
function isPersistentSimulatorApi(name) {
|
|
@@ -3730,17 +3799,19 @@ function setCorsHeaders(res) {
|
|
|
3730
3799
|
import { app as app9, BrowserWindow as BrowserWindow3 } from "electron";
|
|
3731
3800
|
import path14 from "node:path";
|
|
3732
3801
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
3733
|
-
var SERVICE_HOST_PARTITION =
|
|
3802
|
+
var SERVICE_HOST_PARTITION = SHARED_MINIAPP_PARTITION;
|
|
3734
3803
|
var serviceHostPreloadPath = path14.join(devtoolsPackageRoot, "dist/service-host/preload.cjs");
|
|
3735
3804
|
var serviceHostHtmlPath = path14.join(devtoolsPackageRoot, "dist/service-host/service.html");
|
|
3736
3805
|
function constructServiceHostWindow(opts = {}) {
|
|
3806
|
+
const partition = opts.partition ?? SERVICE_HOST_PARTITION;
|
|
3807
|
+
configureMiniappSession(partition);
|
|
3737
3808
|
return new BrowserWindow3({
|
|
3738
3809
|
width: 980,
|
|
3739
3810
|
height: 720,
|
|
3740
3811
|
show: false,
|
|
3741
3812
|
title: opts.appId ? `Dimina Service Host: ${opts.appId}` : "Dimina Service Host",
|
|
3742
3813
|
webPreferences: {
|
|
3743
|
-
partition
|
|
3814
|
+
partition,
|
|
3744
3815
|
nodeIntegration: false,
|
|
3745
3816
|
contextIsolation: false,
|
|
3746
3817
|
sandbox: false,
|
|
@@ -3784,9 +3855,12 @@ function navigateServiceHost(win, url) {
|
|
|
3784
3855
|
}
|
|
3785
3856
|
return loaded;
|
|
3786
3857
|
}
|
|
3787
|
-
function serviceHostSpec() {
|
|
3858
|
+
function serviceHostSpec(appId) {
|
|
3788
3859
|
return {
|
|
3789
|
-
partition
|
|
3860
|
+
// Per-project partition when an appId is known (so this project's service
|
|
3861
|
+
// host shares storage ONLY with its own render side); the shared partition
|
|
3862
|
+
// for the pre-warm pool's default spec (no appId — see KNOWN BLOCKER below).
|
|
3863
|
+
partition: appId ? miniappPartition(appId) : SERVICE_HOST_PARTITION,
|
|
3790
3864
|
preloadPath: serviceHostPreloadPath,
|
|
3791
3865
|
size: { width: 980, height: 720 },
|
|
3792
3866
|
contextIsolation: false,
|
|
@@ -3796,7 +3870,7 @@ function serviceHostSpec() {
|
|
|
3796
3870
|
};
|
|
3797
3871
|
}
|
|
3798
3872
|
function createServiceHostWindow(opts) {
|
|
3799
|
-
const win = constructServiceHostWindow({ appId: opts.appId });
|
|
3873
|
+
const win = constructServiceHostWindow({ appId: opts.appId, partition: miniappPartition(opts.appId) });
|
|
3800
3874
|
void navigateServiceHost(win, buildServiceHostSpawnUrl(opts));
|
|
3801
3875
|
return win;
|
|
3802
3876
|
}
|
|
@@ -4973,7 +5047,11 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
4973
5047
|
resourceServer = await startDiminaResourceServer(path15.resolve(pkgRoot, root));
|
|
4974
5048
|
resourceBaseUrl = resourceServer.baseUrl;
|
|
4975
5049
|
}
|
|
4976
|
-
const
|
|
5050
|
+
const selectedDevice = ctx.bridge?.getDevice?.() ?? null;
|
|
5051
|
+
const hostEnv = makeHostEnv({
|
|
5052
|
+
...opts.hostEnvSnapshot,
|
|
5053
|
+
...selectedDevice ? deviceInfoToHostEnv(selectedDevice) : {}
|
|
5054
|
+
});
|
|
4977
5055
|
const appConfig = await loadAppConfig(
|
|
4978
5056
|
resourceServer ? resourceServer.baseUrl : `${resourceBaseUrl}${appId}/${root}/`
|
|
4979
5057
|
);
|
|
@@ -5639,7 +5717,7 @@ function installResourceProtocolHandlers(ctx, state) {
|
|
|
5639
5717
|
const target = new URL(url.pathname.replace(/^\/+/, "") + url.search, ap.resourceBaseUrl);
|
|
5640
5718
|
return fetch(target);
|
|
5641
5719
|
};
|
|
5642
|
-
const simulatorSession = electronSession.fromPartition(
|
|
5720
|
+
const simulatorSession = electronSession.fromPartition(SHARED_MINIAPP_PARTITION);
|
|
5643
5721
|
try {
|
|
5644
5722
|
protocol2.unhandle("dmb-resource");
|
|
5645
5723
|
} catch {
|
|
@@ -5650,7 +5728,18 @@ function installResourceProtocolHandlers(ctx, state) {
|
|
|
5650
5728
|
}
|
|
5651
5729
|
protocol2.handle("dmb-resource", handler);
|
|
5652
5730
|
simulatorSession.protocol.handle("dmb-resource", handler);
|
|
5731
|
+
const perProjectSessions = /* @__PURE__ */ new Set();
|
|
5732
|
+
const unregisterConfigurator = registerMiniappSessionConfigurator((sess) => {
|
|
5733
|
+
if (perProjectSessions.has(sess)) return;
|
|
5734
|
+
perProjectSessions.add(sess);
|
|
5735
|
+
try {
|
|
5736
|
+
sess.protocol.unhandle("dmb-resource");
|
|
5737
|
+
} catch {
|
|
5738
|
+
}
|
|
5739
|
+
sess.protocol.handle("dmb-resource", handler);
|
|
5740
|
+
});
|
|
5653
5741
|
ctx.registry.add(() => {
|
|
5742
|
+
unregisterConfigurator();
|
|
5654
5743
|
try {
|
|
5655
5744
|
protocol2.unhandle("dmb-resource");
|
|
5656
5745
|
} catch {
|
|
@@ -5659,6 +5748,12 @@ function installResourceProtocolHandlers(ctx, state) {
|
|
|
5659
5748
|
simulatorSession.protocol.unhandle("dmb-resource");
|
|
5660
5749
|
} catch {
|
|
5661
5750
|
}
|
|
5751
|
+
for (const sess of perProjectSessions) {
|
|
5752
|
+
try {
|
|
5753
|
+
sess.protocol.unhandle("dmb-resource");
|
|
5754
|
+
} catch {
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5662
5757
|
});
|
|
5663
5758
|
}
|
|
5664
5759
|
function makeHostEnv(snapshot) {
|
|
@@ -5787,32 +5882,6 @@ toolHandlers["Tool.close"] = async (ctx) => {
|
|
|
5787
5882
|
return {};
|
|
5788
5883
|
};
|
|
5789
5884
|
|
|
5790
|
-
// src/shared/simulator-route.ts
|
|
5791
|
-
function decodePageSpec(value) {
|
|
5792
|
-
const qIdx = value.indexOf("?");
|
|
5793
|
-
if (qIdx < 0) return { pagePath: value, query: {} };
|
|
5794
|
-
const pagePath = value.slice(0, qIdx);
|
|
5795
|
-
const query = {};
|
|
5796
|
-
for (const pair of value.slice(qIdx + 1).split("&")) {
|
|
5797
|
-
if (!pair) continue;
|
|
5798
|
-
const eqIdx = pair.indexOf("=");
|
|
5799
|
-
const k = eqIdx >= 0 ? pair.slice(0, eqIdx) : pair;
|
|
5800
|
-
const v = eqIdx >= 0 ? pair.slice(eqIdx + 1) : "";
|
|
5801
|
-
if (k) query[decodeURIComponent(k)] = decodeURIComponent(v);
|
|
5802
|
-
}
|
|
5803
|
-
return { pagePath, query };
|
|
5804
|
-
}
|
|
5805
|
-
function parseLocationRoute(search) {
|
|
5806
|
-
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
|
|
5807
|
-
const appId = params.get("appId");
|
|
5808
|
-
const entryRaw = params.get("entry");
|
|
5809
|
-
if (!appId || !entryRaw) return null;
|
|
5810
|
-
const entry = decodePageSpec(entryRaw);
|
|
5811
|
-
const pageRaw = params.get("page");
|
|
5812
|
-
const current = pageRaw && pageRaw !== entryRaw ? decodePageSpec(pageRaw) : entry;
|
|
5813
|
-
return { appId, entry, current };
|
|
5814
|
-
}
|
|
5815
|
-
|
|
5816
5885
|
// src/main/services/automation/wait-active-page.ts
|
|
5817
5886
|
function waitForActivePage(bridge, opts) {
|
|
5818
5887
|
const { since, timeoutMs, match, onTimeout } = opts;
|
|
@@ -8352,7 +8421,8 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
8352
8421
|
pendingWaiters.clear();
|
|
8353
8422
|
for (const list of lists) for (const fn of list) fn();
|
|
8354
8423
|
}
|
|
8355
|
-
const
|
|
8424
|
+
const trustedSessions = /* @__PURE__ */ new Set([simSession]);
|
|
8425
|
+
const simulatorOnlyPolicy = (sender) => !sender.isDestroyed() && trustedSessions.has(sender.session);
|
|
8356
8426
|
const registry = new IpcRegistry(simulatorOnlyPolicy);
|
|
8357
8427
|
registry.on("simulator:temp-file:write", (_event, payload) => {
|
|
8358
8428
|
if (disposed) return;
|
|
@@ -8370,11 +8440,7 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
8370
8440
|
if (disposed) return;
|
|
8371
8441
|
revokeAllTempFiles(store);
|
|
8372
8442
|
});
|
|
8373
|
-
|
|
8374
|
-
simSession.protocol.unhandle("difile");
|
|
8375
|
-
} catch {
|
|
8376
|
-
}
|
|
8377
|
-
simSession.protocol.handle("difile", async (req) => {
|
|
8443
|
+
const difileHandler = async (req) => {
|
|
8378
8444
|
const url = req.url;
|
|
8379
8445
|
const headers = {};
|
|
8380
8446
|
try {
|
|
@@ -8407,7 +8473,20 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
8407
8473
|
res = await handleDifileRequest(ctx, { url, headers });
|
|
8408
8474
|
}
|
|
8409
8475
|
return res;
|
|
8410
|
-
}
|
|
8476
|
+
};
|
|
8477
|
+
const installedSessions = /* @__PURE__ */ new Set();
|
|
8478
|
+
function installOnSession(sess) {
|
|
8479
|
+
trustedSessions.add(sess);
|
|
8480
|
+
if (installedSessions.has(sess)) return;
|
|
8481
|
+
installedSessions.add(sess);
|
|
8482
|
+
try {
|
|
8483
|
+
sess.protocol.unhandle("difile");
|
|
8484
|
+
} catch {
|
|
8485
|
+
}
|
|
8486
|
+
sess.protocol.handle("difile", difileHandler);
|
|
8487
|
+
}
|
|
8488
|
+
installOnSession(simSession);
|
|
8489
|
+
const unregisterConfigurator = registerMiniappSessionConfigurator((sess) => installOnSession(sess));
|
|
8411
8490
|
registry.handle(
|
|
8412
8491
|
"simulator:fs:read",
|
|
8413
8492
|
(_event, payload) => handleFsRead(payload)
|
|
@@ -8434,16 +8513,61 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
8434
8513
|
);
|
|
8435
8514
|
return toDisposable6(async () => {
|
|
8436
8515
|
disposed = true;
|
|
8516
|
+
unregisterConfigurator();
|
|
8437
8517
|
drainAllWaiters();
|
|
8438
8518
|
store.clear();
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
8519
|
+
for (const sess of installedSessions) {
|
|
8520
|
+
try {
|
|
8521
|
+
sess.protocol.unhandle("difile");
|
|
8522
|
+
} catch {
|
|
8523
|
+
}
|
|
8442
8524
|
}
|
|
8443
8525
|
await registry.dispose();
|
|
8444
8526
|
});
|
|
8445
8527
|
}
|
|
8446
8528
|
|
|
8529
|
+
// src/main/services/views/simulator-session-policy.ts
|
|
8530
|
+
import { session as session2 } from "electron";
|
|
8531
|
+
import { toDisposable as toDisposable7 } from "@dimina-kit/electron-deck/main";
|
|
8532
|
+
function applySimulatorWebRequestPolicy(simulatorSession) {
|
|
8533
|
+
simulatorSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
|
8534
|
+
const forcedReferer = getSimulatorServicewechatReferer();
|
|
8535
|
+
if (forcedReferer) {
|
|
8536
|
+
details.requestHeaders["Referer"] = forcedReferer;
|
|
8537
|
+
}
|
|
8538
|
+
callback({ requestHeaders: details.requestHeaders });
|
|
8539
|
+
});
|
|
8540
|
+
simulatorSession.webRequest.onHeadersReceived((details, callback) => {
|
|
8541
|
+
const headers = details.responseHeaders ?? {};
|
|
8542
|
+
headers["access-control-allow-origin"] = ["*"];
|
|
8543
|
+
headers["access-control-allow-headers"] = ["*"];
|
|
8544
|
+
headers["access-control-allow-methods"] = ["*"];
|
|
8545
|
+
callback({ responseHeaders: headers });
|
|
8546
|
+
});
|
|
8547
|
+
}
|
|
8548
|
+
function clearSimulatorWebRequestPolicy(simulatorSession) {
|
|
8549
|
+
try {
|
|
8550
|
+
simulatorSession.webRequest.onBeforeSendHeaders(null);
|
|
8551
|
+
simulatorSession.webRequest.onHeadersReceived(null);
|
|
8552
|
+
} catch {
|
|
8553
|
+
}
|
|
8554
|
+
}
|
|
8555
|
+
function setupSimulatorSessionPolicy() {
|
|
8556
|
+
const configured = /* @__PURE__ */ new Set();
|
|
8557
|
+
function install(sess) {
|
|
8558
|
+
if (configured.has(sess)) return;
|
|
8559
|
+
configured.add(sess);
|
|
8560
|
+
applySimulatorWebRequestPolicy(sess);
|
|
8561
|
+
}
|
|
8562
|
+
install(session2.fromPartition(SHARED_MINIAPP_PARTITION));
|
|
8563
|
+
const unregister = registerMiniappSessionConfigurator((sess) => install(sess));
|
|
8564
|
+
return toDisposable7(() => {
|
|
8565
|
+
unregister();
|
|
8566
|
+
for (const sess of configured) clearSimulatorWebRequestPolicy(sess);
|
|
8567
|
+
configured.clear();
|
|
8568
|
+
});
|
|
8569
|
+
}
|
|
8570
|
+
|
|
8447
8571
|
// src/main/services/update/update-manager.ts
|
|
8448
8572
|
import { app as app12, shell as shell3 } from "electron";
|
|
8449
8573
|
var UpdateManager = class {
|
|
@@ -8546,7 +8670,7 @@ var UpdateManager = class {
|
|
|
8546
8670
|
import { app as app13 } from "electron";
|
|
8547
8671
|
|
|
8548
8672
|
// src/main/app/app.ts
|
|
8549
|
-
import { toDisposable as
|
|
8673
|
+
import { toDisposable as toDisposable8 } from "@dimina-kit/electron-deck/main";
|
|
8550
8674
|
var DEFAULT_MODULES = {
|
|
8551
8675
|
projects: true,
|
|
8552
8676
|
session: true,
|
|
@@ -8580,7 +8704,7 @@ function registerTrustedWindow(context, win) {
|
|
|
8580
8704
|
else counts.set(senderId, count - 1);
|
|
8581
8705
|
}
|
|
8582
8706
|
win.once("closed", onClosed);
|
|
8583
|
-
return
|
|
8707
|
+
return toDisposable8(remove);
|
|
8584
8708
|
}
|
|
8585
8709
|
function parseAutoArgs() {
|
|
8586
8710
|
const argv = process.argv;
|
|
@@ -8710,7 +8834,7 @@ function wireAppWindowEvents(config, instance) {
|
|
|
8710
8834
|
}
|
|
8711
8835
|
function enableDevRendererAutoReload(rendererDir2) {
|
|
8712
8836
|
if (app14.isPackaged) {
|
|
8713
|
-
return
|
|
8837
|
+
return toDisposable8(() => {
|
|
8714
8838
|
});
|
|
8715
8839
|
}
|
|
8716
8840
|
let reloadTimer = null;
|
|
@@ -8722,7 +8846,7 @@ function enableDevRendererAutoReload(rendererDir2) {
|
|
|
8722
8846
|
}
|
|
8723
8847
|
}, 300);
|
|
8724
8848
|
});
|
|
8725
|
-
return
|
|
8849
|
+
return toDisposable8(() => {
|
|
8726
8850
|
if (reloadTimer) {
|
|
8727
8851
|
clearTimeout(reloadTimer);
|
|
8728
8852
|
reloadTimer = null;
|
|
@@ -8748,9 +8872,10 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
8748
8872
|
context.connections.acquire(mainWindow.webContents);
|
|
8749
8873
|
context.registry.add(registerAppIpc(context));
|
|
8750
8874
|
context.registry.add(registerProjectFsIpc(context));
|
|
8875
|
+
context.registry.add(setupSimulatorSessionPolicy());
|
|
8751
8876
|
context.registry.add(installThemeBackgroundSync());
|
|
8752
8877
|
registerBuiltinModules(config, context);
|
|
8753
|
-
const simSession =
|
|
8878
|
+
const simSession = session3.fromPartition(SHARED_MINIAPP_PARTITION);
|
|
8754
8879
|
context.registry.add(setupSimulatorTempFiles(simSession));
|
|
8755
8880
|
installMenu(config, mainWindow, context);
|
|
8756
8881
|
const hostIpc = new IpcRegistry(context.senderPolicy);
|
|
@@ -8763,7 +8888,7 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
8763
8888
|
// wrapper splices the registry entry out AND drives the underlying
|
|
8764
8889
|
// teardown, so a single dispose leaves no dead entry behind.
|
|
8765
8890
|
registerTrustedWindow: (win) => context.registry.add(registerTrustedWindow(context, win)),
|
|
8766
|
-
registerSimulatorApi: (name, handler) => context.registry.add(
|
|
8891
|
+
registerSimulatorApi: (name, handler) => context.registry.add(toDisposable8(context.simulatorApis.register(name, handler))),
|
|
8767
8892
|
toolbar: {
|
|
8768
8893
|
set: (actions) => {
|
|
8769
8894
|
context.toolbar.set(actions);
|
|
@@ -8790,8 +8915,8 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
8790
8915
|
const mcp = setupMcp();
|
|
8791
8916
|
if (mcp) context.registry.add(mcp);
|
|
8792
8917
|
const getActiveAppId = () => {
|
|
8793
|
-
const
|
|
8794
|
-
const appInfo =
|
|
8918
|
+
const session4 = context.workspace.getSession();
|
|
8919
|
+
const appInfo = session4?.appInfo;
|
|
8795
8920
|
return appInfo?.appId ?? null;
|
|
8796
8921
|
};
|
|
8797
8922
|
if (context.bridge?.isNativeHost()) {
|