@dimina-kit/devtools 0.4.0-dev.20260703051110 → 0.4.0-dev.20260706064107
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 +6 -0
- package/dist/main/index.bundle.js +445 -49
- package/dist/main/ipc/bridge-router.d.ts +8 -0
- package/dist/main/ipc/bridge-router.js +352 -38
- package/dist/main/services/compile-standby.d.ts +26 -0
- package/dist/main/services/compile-standby.js +57 -0
- package/dist/main/services/console-forward/index.d.ts +12 -1
- package/dist/main/services/console-forward/index.js +99 -1
- package/dist/main/services/diagnostics/index.d.ts +49 -0
- package/dist/main/services/diagnostics/index.js +61 -0
- package/dist/main/services/network-forward/index.js +32 -0
- package/dist/main/services/notifications/renderer-notifier.d.ts +39 -0
- package/dist/main/services/notifications/renderer-notifier.js +4 -1
- package/dist/main/services/projects/project-repository.js +2 -1
- package/dist/main/services/views/simulator-session-policy.js +17 -0
- package/dist/main/services/workbench-context.d.ts +10 -0
- package/dist/main/services/workspace/workspace-service.js +12 -3
- package/dist/main/windows/service-host-window/create.d.ts +15 -1
- package/dist/main/windows/service-host-window/create.js +11 -3
- package/dist/preload/shared/api-compat.js +18 -55
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs.map +1 -1
- package/dist/preload/windows/simulator.cjs +117 -44
- package/dist/preload/windows/simulator.cjs.map +3 -3
- package/dist/preload/windows/simulator.js +117 -44
- package/dist/renderer/assets/index-BwzPwCmM.js +49 -0
- package/dist/renderer/assets/{input-Cjk0wSEh.js → input-CTb_le7F.js} +2 -2
- package/dist/renderer/assets/ipc-transport-BPWIV5hA.css +1 -0
- package/dist/renderer/assets/{ipc-transport-OZS-KmOW.js → ipc-transport-Ck5Xa8Tu.js} +2 -2
- package/dist/renderer/assets/popover-B1Zu2UQu.js +2 -0
- package/dist/renderer/assets/{select-BQDXi5ih.js → select-ozSk5Pt6.js} +2 -2
- package/dist/renderer/assets/{settings-tP3Px2KR.js → settings-CNwGOI22.js} +2 -2
- package/dist/renderer/assets/settings-api-DMbMp1Eq.js +2 -0
- package/dist/renderer/assets/{workbenchSettings-COhuFF-i.js → workbenchSettings-Cr4EHo5w.js} +2 -2
- package/dist/renderer/entries/main/index.html +6 -6
- package/dist/renderer/entries/popover/index.html +5 -5
- package/dist/renderer/entries/settings/index.html +5 -5
- package/dist/renderer/entries/workbench-settings/index.html +4 -4
- package/dist/shared/bridge-channels.d.ts +22 -0
- package/dist/shared/ipc-channels.d.ts +3 -0
- package/dist/shared/ipc-channels.js +9 -0
- package/dist/shared/request-core.d.ts +84 -0
- package/dist/shared/request-core.js +168 -0
- package/dist/shared/simulator-api-metadata.d.ts +22 -17
- package/dist/shared/simulator-api-metadata.js +36 -0
- package/dist/shared/types.d.ts +7 -4
- package/dist/simulator/assets/{device-shell-CiLAPa0I.js → device-shell-C-wcFq3Z.js} +2 -2
- package/dist/simulator/assets/{jsx-runtime-CDK-o-S0.js → jsx-runtime-BDTY6fEq.js} +2 -2
- package/dist/simulator/assets/simulator-DU3-fS3v.js +10 -0
- package/dist/simulator/assets/simulator-mini-app-DzfMfnVM.js +2 -0
- package/dist/simulator/simulator.html +2 -2
- package/package.json +5 -5
- package/dist/renderer/assets/index-D-ksyN1p.js +0 -49
- package/dist/renderer/assets/ipc-transport-D5dKIti1.css +0 -1
- package/dist/renderer/assets/popover-CQVvOe90.js +0 -2
- package/dist/renderer/assets/settings-api-B6x2mhaD.js +0 -2
- package/dist/simulator/assets/simulator-Dvnxry3y.js +0 -10
- package/dist/simulator/assets/simulator-mini-app-Bt639XL_.js +0 -2
|
@@ -393,6 +393,9 @@ var ProjectChannel = {
|
|
|
393
393
|
CaptureThumbnail: "project:captureThumbnail",
|
|
394
394
|
GetThumbnail: "project:getThumbnail"
|
|
395
395
|
};
|
|
396
|
+
var SessionChannel = {
|
|
397
|
+
RuntimeStatus: "session:runtimeStatus"
|
|
398
|
+
};
|
|
396
399
|
var ProjectFsChannel = {
|
|
397
400
|
GetRoot: "project:fs:getRoot",
|
|
398
401
|
ReadFile: "project:fs:readFile",
|
|
@@ -1105,6 +1108,9 @@ function createRendererNotifier(ctx) {
|
|
|
1105
1108
|
projectStatus(payload) {
|
|
1106
1109
|
sendToMain(ProjectChannel.Status, payload);
|
|
1107
1110
|
},
|
|
1111
|
+
sessionRuntimeStatus(payload) {
|
|
1112
|
+
sendToMain(SessionChannel.RuntimeStatus, payload);
|
|
1113
|
+
},
|
|
1108
1114
|
compileLog(payload) {
|
|
1109
1115
|
sendToMain(ProjectChannel.CompileLog, payload);
|
|
1110
1116
|
},
|
|
@@ -3927,7 +3933,8 @@ function getProjectPages(dirPath) {
|
|
|
3927
3933
|
pages: appJson.pages || [],
|
|
3928
3934
|
entryPagePath: appJson.entryPagePath || appJson.pages?.[0] || ""
|
|
3929
3935
|
};
|
|
3930
|
-
} catch {
|
|
3936
|
+
} catch (err2) {
|
|
3937
|
+
log2.warn(`Failed to read project pages from ${appJsonPath}`, err2);
|
|
3931
3938
|
return { pages: [], entryPagePath: "" };
|
|
3932
3939
|
}
|
|
3933
3940
|
}
|
|
@@ -4029,8 +4036,8 @@ function createWorkspaceService(ctx) {
|
|
|
4029
4036
|
let lastClosedProjectPath = "";
|
|
4030
4037
|
let logGeneration = 0;
|
|
4031
4038
|
const opLock = createOpLock();
|
|
4032
|
-
function sendStatus(status2, message, hotReload) {
|
|
4033
|
-
ctx.notify.projectStatus(
|
|
4039
|
+
function sendStatus(status2, message, hotReload, pages, watcherDead) {
|
|
4040
|
+
ctx.notify.projectStatus({ status: status2, message, ...hotReload ? { hotReload: true } : {}, ...pages ? { pages } : {}, ...watcherDead ? { watcher: "dead" } : {} });
|
|
4034
4041
|
}
|
|
4035
4042
|
function bestEffort(label, fn) {
|
|
4036
4043
|
try {
|
|
@@ -4091,8 +4098,13 @@ function createWorkspaceService(ctx) {
|
|
|
4091
4098
|
sourcemap: true,
|
|
4092
4099
|
fileTypes: ctx.fileTypes,
|
|
4093
4100
|
watch: compile.watch,
|
|
4094
|
-
onRebuild: () =>
|
|
4101
|
+
onRebuild: () => {
|
|
4102
|
+
const { pages } = getProjectPages(projectPath);
|
|
4103
|
+
sendStatus("ready", "\u7F16\u8BD1\u5B8C\u6210\uFF0C\u5DF2\u91CD\u542F", true, pages.length ? pages : void 0);
|
|
4104
|
+
},
|
|
4095
4105
|
onBuildError: (err2) => sendStatus("error", String(err2)),
|
|
4106
|
+
// Watcher died mid-session (EMFILE, permission loss, …): non-fatal, so 'ready' stays but `watcher: 'dead'` flags that saves no longer auto-rebuild.
|
|
4107
|
+
onWatcherError: () => sendStatus("ready", "\u6587\u4EF6\u76D1\u542C\u5DF2\u505C\u6B62\uFF0C\u4FDD\u5B58\u4E0D\u518D\u89E6\u53D1\u81EA\u52A8\u7F16\u8BD1", false, void 0, true),
|
|
4096
4108
|
onLog: (entry) => {
|
|
4097
4109
|
if (sessionGeneration !== logGeneration) return;
|
|
4098
4110
|
ctx.notify.compileLog({ stream: entry.stream, text: entry.text, at: Date.now() });
|
|
@@ -4379,6 +4391,55 @@ function createWorkbenchContext(opts) {
|
|
|
4379
4391
|
return ctx;
|
|
4380
4392
|
}
|
|
4381
4393
|
|
|
4394
|
+
// src/main/services/compile-standby.ts
|
|
4395
|
+
var EVENT_SEVERITY = {
|
|
4396
|
+
"spawned": "info",
|
|
4397
|
+
"prewarmed": "info",
|
|
4398
|
+
"adopted": "info",
|
|
4399
|
+
"died": "warn",
|
|
4400
|
+
"health-check-failed": "warn",
|
|
4401
|
+
"degraded": "error"
|
|
4402
|
+
};
|
|
4403
|
+
function setupCompileWorkerStandby(ctx, deps = {}) {
|
|
4404
|
+
const loadDevkit = deps.loadDevkit ?? (() => import("@dimina-kit/devkit"));
|
|
4405
|
+
let manager = null;
|
|
4406
|
+
let disposed = false;
|
|
4407
|
+
const forward = (ev) => {
|
|
4408
|
+
try {
|
|
4409
|
+
const detail = [
|
|
4410
|
+
`compile standby ${ev.type}`,
|
|
4411
|
+
typeof ev.pid === "number" ? `pid=${ev.pid}` : null,
|
|
4412
|
+
ev.reason ? `\u2014 ${ev.reason}` : null
|
|
4413
|
+
].filter(Boolean).join(" ");
|
|
4414
|
+
ctx.diagnostics?.report({
|
|
4415
|
+
severity: EVENT_SEVERITY[ev.type] ?? "info",
|
|
4416
|
+
code: "compile-standby",
|
|
4417
|
+
message: detail
|
|
4418
|
+
});
|
|
4419
|
+
} catch {
|
|
4420
|
+
}
|
|
4421
|
+
};
|
|
4422
|
+
void (async () => {
|
|
4423
|
+
let enable;
|
|
4424
|
+
try {
|
|
4425
|
+
const devkit = await loadDevkit();
|
|
4426
|
+
enable = devkit.enableCompileWorkerStandby;
|
|
4427
|
+
} catch {
|
|
4428
|
+
return;
|
|
4429
|
+
}
|
|
4430
|
+
if (typeof enable !== "function") return;
|
|
4431
|
+
manager = enable({ onEvent: forward });
|
|
4432
|
+
if (disposed) void manager.dispose();
|
|
4433
|
+
})();
|
|
4434
|
+
return {
|
|
4435
|
+
dispose: async () => {
|
|
4436
|
+
if (disposed) return;
|
|
4437
|
+
disposed = true;
|
|
4438
|
+
await manager?.dispose();
|
|
4439
|
+
}
|
|
4440
|
+
};
|
|
4441
|
+
}
|
|
4442
|
+
|
|
4382
4443
|
// src/main/menu/index.ts
|
|
4383
4444
|
import { Menu } from "electron";
|
|
4384
4445
|
function installAppMenu(ctx) {
|
|
@@ -4957,11 +5018,30 @@ import { app as app12, ipcMain as ipcMain3, protocol as protocol2, session as el
|
|
|
4957
5018
|
import path17 from "node:path";
|
|
4958
5019
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
4959
5020
|
|
|
5021
|
+
// src/shared/request-core.ts
|
|
5022
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
|
|
5023
|
+
var MAX_TIMEOUT_MS = 2147483647;
|
|
5024
|
+
function resolveTimeoutBudgetMs(timeout) {
|
|
5025
|
+
const t = Number(timeout);
|
|
5026
|
+
return Number.isFinite(t) && t > 0 && t <= MAX_TIMEOUT_MS ? t : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
5027
|
+
}
|
|
5028
|
+
|
|
4960
5029
|
// src/shared/simulator-api-metadata.ts
|
|
4961
5030
|
var PERSISTENT_SIMULATOR_APIS = /* @__PURE__ */ new Set(["audioListen"]);
|
|
4962
5031
|
function isPersistentSimulatorApi(name) {
|
|
4963
5032
|
return PERSISTENT_SIMULATOR_APIS.has(name);
|
|
4964
5033
|
}
|
|
5034
|
+
var NETWORK_BUDGET_SIMULATOR_APIS = /* @__PURE__ */ new Set([
|
|
5035
|
+
"request",
|
|
5036
|
+
"downloadFile",
|
|
5037
|
+
"uploadFile"
|
|
5038
|
+
]);
|
|
5039
|
+
var API_CALL_WATCHDOG_MS = 5e3;
|
|
5040
|
+
function apiCallWatchdogMs(name, params) {
|
|
5041
|
+
if (!NETWORK_BUDGET_SIMULATOR_APIS.has(name)) return API_CALL_WATCHDOG_MS;
|
|
5042
|
+
const budget = resolveTimeoutBudgetMs(params?.timeout);
|
|
5043
|
+
return Math.min(budget + API_CALL_WATCHDOG_MS, MAX_TIMEOUT_MS);
|
|
5044
|
+
}
|
|
4965
5045
|
|
|
4966
5046
|
// src/main/ipc/session-listener-bag.ts
|
|
4967
5047
|
function createSessionListenerBag() {
|
|
@@ -5128,10 +5208,13 @@ function buildServiceHostSpawnUrl(opts) {
|
|
|
5128
5208
|
}
|
|
5129
5209
|
return url.toString();
|
|
5130
5210
|
}
|
|
5131
|
-
function navigateServiceHost(win, url) {
|
|
5211
|
+
function navigateServiceHost(win, url, opts) {
|
|
5132
5212
|
const loaded = Promise.resolve(win.loadURL(url)).then(
|
|
5133
5213
|
() => void 0,
|
|
5134
|
-
() =>
|
|
5214
|
+
(err2) => {
|
|
5215
|
+
opts?.onLoadFailed?.(err2);
|
|
5216
|
+
return void 0;
|
|
5217
|
+
}
|
|
5135
5218
|
);
|
|
5136
5219
|
if (!app10.isPackaged && process.env.NODE_ENV !== "test") {
|
|
5137
5220
|
const w = win;
|
|
@@ -5170,7 +5253,7 @@ function serviceHostSpec(appId, projectPath) {
|
|
|
5170
5253
|
}
|
|
5171
5254
|
function createServiceHostWindow(opts) {
|
|
5172
5255
|
const win = constructServiceHostWindow({ appId: opts.appId, partition: miniappPartition(opts.appId, opts.projectPath) });
|
|
5173
|
-
void navigateServiceHost(win, buildServiceHostSpawnUrl(opts));
|
|
5256
|
+
void navigateServiceHost(win, buildServiceHostSpawnUrl(opts), { onLoadFailed: opts.onLoadFailed });
|
|
5174
5257
|
return win;
|
|
5175
5258
|
}
|
|
5176
5259
|
|
|
@@ -5487,9 +5570,49 @@ function buildForwardScript(level, args) {
|
|
|
5487
5570
|
return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});console[${JSON.stringify(method)}]('[\u89C6\u56FE]',...a)}catch(_){}})()
|
|
5488
5571
|
//# sourceURL=${RENDER_FORWARD_SOURCE_URL}`;
|
|
5489
5572
|
}
|
|
5490
|
-
|
|
5573
|
+
var DIAGNOSTIC_CONSOLE_CALL = {
|
|
5574
|
+
error: "console.error",
|
|
5575
|
+
warn: "console.warn",
|
|
5576
|
+
info: "console.info"
|
|
5577
|
+
};
|
|
5578
|
+
function buildDiagnosticScript(severity, message) {
|
|
5579
|
+
const call = DIAGNOSTIC_CONSOLE_CALL[severity];
|
|
5580
|
+
const argsJson = JSON.stringify([`[dimina-kit] ${message}`]);
|
|
5581
|
+
return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});${call}(...a)}catch(_){}})()
|
|
5582
|
+
//# sourceURL=${RENDER_FORWARD_SOURCE_URL}`;
|
|
5583
|
+
}
|
|
5584
|
+
function createConsoleForwarder(bridge, diagnostics) {
|
|
5491
5585
|
const sinks = /* @__PURE__ */ new Set();
|
|
5492
5586
|
const registry = new DisposableRegistry4();
|
|
5587
|
+
const pendingBySession = /* @__PURE__ */ new Map();
|
|
5588
|
+
const pendingGlobal = [];
|
|
5589
|
+
const readySessions = /* @__PURE__ */ new Set();
|
|
5590
|
+
function injectDiagnostic(wc, d) {
|
|
5591
|
+
wc.executeJavaScript(buildDiagnosticScript(d.severity, d.message), true).catch(() => {
|
|
5592
|
+
});
|
|
5593
|
+
}
|
|
5594
|
+
function handleDiagnostic(d) {
|
|
5595
|
+
if (d.appSessionId) {
|
|
5596
|
+
const wc2 = readySessions.has(d.appSessionId) && bridge.getServiceWcForBridge ? bridge.getServiceWcForBridge(d.appSessionId) : null;
|
|
5597
|
+
if (wc2 && !wc2.isDestroyed()) {
|
|
5598
|
+
injectDiagnostic(wc2, d);
|
|
5599
|
+
return;
|
|
5600
|
+
}
|
|
5601
|
+
const bucket = pendingBySession.get(d.appSessionId);
|
|
5602
|
+
if (bucket) bucket.push(d);
|
|
5603
|
+
else pendingBySession.set(d.appSessionId, [d]);
|
|
5604
|
+
return;
|
|
5605
|
+
}
|
|
5606
|
+
const wc = bridge.getServiceWc();
|
|
5607
|
+
if (wc && !wc.isDestroyed()) {
|
|
5608
|
+
injectDiagnostic(wc, d);
|
|
5609
|
+
return;
|
|
5610
|
+
}
|
|
5611
|
+
pendingGlobal.push(d);
|
|
5612
|
+
}
|
|
5613
|
+
if (diagnostics) {
|
|
5614
|
+
registry.add(diagnostics.subscribe(handleDiagnostic, { replay: true }));
|
|
5615
|
+
}
|
|
5493
5616
|
function forwardRenderToServiceHost(entry) {
|
|
5494
5617
|
let wc = null;
|
|
5495
5618
|
if (entry.bridgeId && bridge.getServiceWcForBridge) {
|
|
@@ -5526,13 +5649,84 @@ function createConsoleForwarder(bridge) {
|
|
|
5526
5649
|
sinks.delete(sink);
|
|
5527
5650
|
}));
|
|
5528
5651
|
},
|
|
5652
|
+
notifyServiceHostReady(appSessionId) {
|
|
5653
|
+
readySessions.add(appSessionId);
|
|
5654
|
+
const wc = bridge.getServiceWcForBridge ? bridge.getServiceWcForBridge(appSessionId) : null;
|
|
5655
|
+
if (!wc) return;
|
|
5656
|
+
const sessionEntries = pendingBySession.get(appSessionId);
|
|
5657
|
+
if (sessionEntries) {
|
|
5658
|
+
for (const d of sessionEntries) injectDiagnostic(wc, d);
|
|
5659
|
+
pendingBySession.delete(appSessionId);
|
|
5660
|
+
}
|
|
5661
|
+
if (pendingGlobal.length) {
|
|
5662
|
+
for (const d of pendingGlobal) injectDiagnostic(wc, d);
|
|
5663
|
+
pendingGlobal.length = 0;
|
|
5664
|
+
}
|
|
5665
|
+
},
|
|
5529
5666
|
dispose() {
|
|
5530
5667
|
sinks.clear();
|
|
5668
|
+
pendingBySession.clear();
|
|
5669
|
+
pendingGlobal.length = 0;
|
|
5670
|
+
readySessions.clear();
|
|
5531
5671
|
return registry.disposeAll();
|
|
5532
5672
|
}
|
|
5533
5673
|
};
|
|
5534
5674
|
}
|
|
5535
5675
|
|
|
5676
|
+
// src/main/services/diagnostics/index.ts
|
|
5677
|
+
var DEFAULT_BUFFER_CAP = 200;
|
|
5678
|
+
var CONSOLE_METHOD = {
|
|
5679
|
+
error: "error",
|
|
5680
|
+
warn: "warn",
|
|
5681
|
+
info: "info"
|
|
5682
|
+
};
|
|
5683
|
+
function createDiagnosticsBus(opts) {
|
|
5684
|
+
const bufferCap = opts?.bufferCap && opts.bufferCap > 0 ? opts.bufferCap : DEFAULT_BUFFER_CAP;
|
|
5685
|
+
const buffer = [];
|
|
5686
|
+
const sinks = /* @__PURE__ */ new Set();
|
|
5687
|
+
let disposed = false;
|
|
5688
|
+
return {
|
|
5689
|
+
report(d) {
|
|
5690
|
+
if (disposed) return;
|
|
5691
|
+
const entry = { ...d, ts: Date.now() };
|
|
5692
|
+
buffer.push(entry);
|
|
5693
|
+
if (buffer.length > bufferCap) buffer.shift();
|
|
5694
|
+
console[CONSOLE_METHOD[entry.severity]](`[dimina-kit:${entry.code}] ${entry.message}`);
|
|
5695
|
+
for (const sink of sinks) {
|
|
5696
|
+
try {
|
|
5697
|
+
sink(entry);
|
|
5698
|
+
} catch {
|
|
5699
|
+
}
|
|
5700
|
+
}
|
|
5701
|
+
},
|
|
5702
|
+
subscribe(sink, subOpts) {
|
|
5703
|
+
const replay = subOpts?.replay ?? true;
|
|
5704
|
+
if (replay) {
|
|
5705
|
+
for (const entry of buffer) {
|
|
5706
|
+
try {
|
|
5707
|
+
sink(entry);
|
|
5708
|
+
} catch {
|
|
5709
|
+
}
|
|
5710
|
+
}
|
|
5711
|
+
}
|
|
5712
|
+
sinks.add(sink);
|
|
5713
|
+
let released = false;
|
|
5714
|
+
return {
|
|
5715
|
+
dispose() {
|
|
5716
|
+
if (released) return;
|
|
5717
|
+
released = true;
|
|
5718
|
+
sinks.delete(sink);
|
|
5719
|
+
}
|
|
5720
|
+
};
|
|
5721
|
+
},
|
|
5722
|
+
dispose() {
|
|
5723
|
+
disposed = true;
|
|
5724
|
+
sinks.clear();
|
|
5725
|
+
buffer.length = 0;
|
|
5726
|
+
}
|
|
5727
|
+
};
|
|
5728
|
+
}
|
|
5729
|
+
|
|
5536
5730
|
// src/main/services/simulator-storage/index.ts
|
|
5537
5731
|
import { app as app11, webContents as wcStatic } from "electron";
|
|
5538
5732
|
import { DisposableRegistry as DisposableRegistry5 } from "@dimina-kit/electron-deck/main";
|
|
@@ -6103,6 +6297,7 @@ function rewriteSourceMappingUrl(source, scriptUrl) {
|
|
|
6103
6297
|
//# sourceMappingURL=${absolute}`;
|
|
6104
6298
|
}
|
|
6105
6299
|
var STACK_ID = "stack_0";
|
|
6300
|
+
var LAUNCH_TIMEOUT_MS = 2e4;
|
|
6106
6301
|
var PREWARM_MAX_POOL_SIZE = 4;
|
|
6107
6302
|
function resolvePrewarmPoolSize() {
|
|
6108
6303
|
if (process.env.DIMINA_PREWARM_DISABLE === "1") return 0;
|
|
@@ -6124,7 +6319,6 @@ function summarizeBridgeMsg(payload) {
|
|
|
6124
6319
|
const parts = [type, bridgeId ? `bridge=${bridgeId}` : void 0].filter(Boolean);
|
|
6125
6320
|
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
6126
6321
|
}
|
|
6127
|
-
var API_CALL_TIMEOUT_MS = 5e3;
|
|
6128
6322
|
function findAppSessionByAppId(state, appId) {
|
|
6129
6323
|
let match;
|
|
6130
6324
|
for (const ap of state.appSessions.values()) if (ap.appId === appId) match = ap;
|
|
@@ -6294,13 +6488,20 @@ function installBridgeRouter(ctx) {
|
|
|
6294
6488
|
;
|
|
6295
6489
|
globalThis.__diminaResourceCensus = () => bridgeHandle.census?.();
|
|
6296
6490
|
}
|
|
6297
|
-
const
|
|
6491
|
+
const ownsDiagnosticsBus = ctx.diagnostics === void 0;
|
|
6492
|
+
const diagnosticsBus = ctx.diagnostics ?? createDiagnosticsBus();
|
|
6493
|
+
ctx.diagnostics = diagnosticsBus;
|
|
6494
|
+
const consoleForwarder = createConsoleForwarder(bridgeHandle, diagnosticsBus);
|
|
6298
6495
|
ctx.consoleForwarder = consoleForwarder;
|
|
6299
6496
|
ctx.guestConsole = consoleForwarder;
|
|
6300
6497
|
ctx.registry.add(() => {
|
|
6301
6498
|
void consoleForwarder.dispose();
|
|
6302
6499
|
ctx.consoleForwarder = void 0;
|
|
6303
6500
|
ctx.guestConsole = void 0;
|
|
6501
|
+
if (ownsDiagnosticsBus) {
|
|
6502
|
+
diagnosticsBus.dispose();
|
|
6503
|
+
ctx.diagnostics = void 0;
|
|
6504
|
+
}
|
|
6304
6505
|
});
|
|
6305
6506
|
const onActivePage = (event, payload) => {
|
|
6306
6507
|
const ap = state.appSessions.get(payload.appSessionId);
|
|
@@ -6460,6 +6661,39 @@ function installBridgeRouter(ctx) {
|
|
|
6460
6661
|
);
|
|
6461
6662
|
});
|
|
6462
6663
|
}
|
|
6664
|
+
function clearLaunchTimer(ap) {
|
|
6665
|
+
if (ap.launchTimer === null) return;
|
|
6666
|
+
clearTimeout(ap.launchTimer);
|
|
6667
|
+
ap.launchTimer = null;
|
|
6668
|
+
}
|
|
6669
|
+
function startLaunchTimer(state, ctx, ap) {
|
|
6670
|
+
ap.launchTimer = setTimeout(() => {
|
|
6671
|
+
ap.launchTimer = null;
|
|
6672
|
+
if (ap.running) return;
|
|
6673
|
+
if (state.appSessions.get(ap.appSessionId) !== ap) return;
|
|
6674
|
+
const reason = `Service host did not report readiness within ${LAUNCH_TIMEOUT_MS}ms`;
|
|
6675
|
+
ctx.diagnostics?.report({
|
|
6676
|
+
severity: "error",
|
|
6677
|
+
code: "launch-timeout",
|
|
6678
|
+
message: reason,
|
|
6679
|
+
appSessionId: ap.appSessionId
|
|
6680
|
+
});
|
|
6681
|
+
pushRuntimeStatus(ctx, ap, { phase: "launch-failed", code: "timeout", reason });
|
|
6682
|
+
}, LAUNCH_TIMEOUT_MS);
|
|
6683
|
+
}
|
|
6684
|
+
function markSessionRunning(ctx, ap, page) {
|
|
6685
|
+
if (!page.isRoot || ap.running) return;
|
|
6686
|
+
ap.running = true;
|
|
6687
|
+
clearLaunchTimer(ap);
|
|
6688
|
+
pushRuntimeStatus(ctx, ap, { phase: "running" });
|
|
6689
|
+
}
|
|
6690
|
+
function pushRuntimeStatus(ctx, session5, status2) {
|
|
6691
|
+
ctx.notify?.sessionRuntimeStatus?.({
|
|
6692
|
+
appId: session5.appId,
|
|
6693
|
+
...status2,
|
|
6694
|
+
...session5.pageFallback ? { pageFallback: session5.pageFallback } : {}
|
|
6695
|
+
});
|
|
6696
|
+
}
|
|
6463
6697
|
async function handleSpawn(state, ctx, event, opts) {
|
|
6464
6698
|
const appId = opts.appId;
|
|
6465
6699
|
if (!appId) throw new Error("[bridge-router] spawn requires appId");
|
|
@@ -6485,20 +6719,48 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
6485
6719
|
...selectedDevice ? deviceInfoToHostEnv(selectedDevice) : {}
|
|
6486
6720
|
});
|
|
6487
6721
|
const appConfig = await loadAppConfig(
|
|
6488
|
-
resourceServer ? resourceServer.baseUrl : `${resourceBaseUrl}${appId}/${root}
|
|
6722
|
+
resourceServer ? resourceServer.baseUrl : `${resourceBaseUrl}${appId}/${root}/`,
|
|
6723
|
+
({ url, error }) => {
|
|
6724
|
+
ctx.diagnostics?.report({
|
|
6725
|
+
severity: "error",
|
|
6726
|
+
code: "app-config-unreachable",
|
|
6727
|
+
message: `app-config.json unreachable at ${url}: ${String(error)}`,
|
|
6728
|
+
appSessionId
|
|
6729
|
+
});
|
|
6730
|
+
}
|
|
6489
6731
|
);
|
|
6490
6732
|
const manifest = buildAppManifest(appConfig, pagePath);
|
|
6491
|
-
const
|
|
6492
|
-
|
|
6733
|
+
const { resolvedPagePath, pageFallbackApplied } = resolveRootPagePath(manifest, pagePath);
|
|
6734
|
+
if (pageFallbackApplied) {
|
|
6735
|
+
reportPageNotFound(ctx, appSessionId, pagePath, resolvedPagePath);
|
|
6736
|
+
}
|
|
6737
|
+
const rootWindowConfig = resolvePageWindowConfig(appConfig, resolvedPagePath);
|
|
6738
|
+
const isTab = isTabPage(appConfig, resolvedPagePath);
|
|
6493
6739
|
const usedPool = state.pool !== null;
|
|
6494
6740
|
let poolEntryId = null;
|
|
6495
6741
|
let serviceWindow;
|
|
6742
|
+
const reportServiceHostNavigationFailed = (spawnUrl, err2) => {
|
|
6743
|
+
const message = `Failed to navigate service host to ${spawnUrl}: ${String(err2)}`;
|
|
6744
|
+
ctx.diagnostics?.report({
|
|
6745
|
+
severity: "error",
|
|
6746
|
+
code: "service-host-navigation-failed",
|
|
6747
|
+
message,
|
|
6748
|
+
appSessionId
|
|
6749
|
+
});
|
|
6750
|
+
const ap = state.appSessions.get(appSessionId);
|
|
6751
|
+
if (ap) clearLaunchTimer(ap);
|
|
6752
|
+
pushRuntimeStatus(
|
|
6753
|
+
ctx,
|
|
6754
|
+
ap ?? { appId, pageFallback: pageFallbackApplied ? { requested: pagePath, resolved: resolvedPagePath } : null },
|
|
6755
|
+
{ phase: "launch-failed", code: "service-host-navigation-failed", reason: message }
|
|
6756
|
+
);
|
|
6757
|
+
};
|
|
6496
6758
|
if (state.pool) {
|
|
6497
6759
|
const acquired = await state.pool.acquire(serviceHostSpec());
|
|
6498
6760
|
serviceWindow = acquired.win;
|
|
6499
6761
|
poolEntryId = acquired.entryId;
|
|
6500
6762
|
} else {
|
|
6501
|
-
|
|
6763
|
+
const freshWindowOptions = {
|
|
6502
6764
|
bridgeId,
|
|
6503
6765
|
appId,
|
|
6504
6766
|
// Same (appId, projectPath) pair the simulator WCV uses, so this project's
|
|
@@ -6508,12 +6770,16 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
6508
6770
|
// awaits above would otherwise give the service host a different path than
|
|
6509
6771
|
// the simulator WCV was built with, splitting the partition.
|
|
6510
6772
|
projectPath: workspaceProjectPath || void 0,
|
|
6511
|
-
pagePath,
|
|
6773
|
+
pagePath: resolvedPagePath,
|
|
6512
6774
|
pkgRoot,
|
|
6513
6775
|
root,
|
|
6514
6776
|
resourceBaseUrl,
|
|
6515
6777
|
hostEnvSnapshot: hostEnv,
|
|
6516
6778
|
apiNamespaces
|
|
6779
|
+
};
|
|
6780
|
+
serviceWindow = createServiceHostWindow({
|
|
6781
|
+
...freshWindowOptions,
|
|
6782
|
+
onLoadFailed: (err2) => reportServiceHostNavigationFailed(buildServiceHostSpawnUrl(freshWindowOptions), err2)
|
|
6517
6783
|
});
|
|
6518
6784
|
}
|
|
6519
6785
|
const appSession = {
|
|
@@ -6537,12 +6803,15 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
6537
6803
|
poolEntryId,
|
|
6538
6804
|
onServiceBoot: null,
|
|
6539
6805
|
listenerBag: createSessionListenerBag(),
|
|
6540
|
-
registryHandle: null
|
|
6806
|
+
registryHandle: null,
|
|
6807
|
+
running: false,
|
|
6808
|
+
launchTimer: null,
|
|
6809
|
+
pageFallback: pageFallbackApplied ? { requested: pagePath, resolved: resolvedPagePath } : null
|
|
6541
6810
|
};
|
|
6542
6811
|
const rootPage = {
|
|
6543
6812
|
bridgeId,
|
|
6544
6813
|
appSessionId,
|
|
6545
|
-
pagePath,
|
|
6814
|
+
pagePath: resolvedPagePath,
|
|
6546
6815
|
query: opts.query ?? {},
|
|
6547
6816
|
isRoot: true,
|
|
6548
6817
|
isTab,
|
|
@@ -6587,28 +6856,43 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
6587
6856
|
};
|
|
6588
6857
|
appSession.onServiceBoot = bootOnServiceLoad;
|
|
6589
6858
|
serviceWindow.webContents.on("did-finish-load", bootOnServiceLoad);
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
);
|
|
6859
|
+
const spawnUrl = buildServiceHostSpawnUrl({
|
|
6860
|
+
bridgeId,
|
|
6861
|
+
appId,
|
|
6862
|
+
pagePath: resolvedPagePath,
|
|
6863
|
+
pkgRoot,
|
|
6864
|
+
root,
|
|
6865
|
+
resourceBaseUrl,
|
|
6866
|
+
hostEnvSnapshot: hostEnv,
|
|
6867
|
+
apiNamespaces
|
|
6868
|
+
});
|
|
6869
|
+
void navigateServiceHost(serviceWindow, spawnUrl, {
|
|
6870
|
+
onLoadFailed: (err2) => reportServiceHostNavigationFailed(spawnUrl, err2)
|
|
6871
|
+
});
|
|
6603
6872
|
} else {
|
|
6604
6873
|
serviceWindow.webContents.once("did-finish-load", () => {
|
|
6605
6874
|
void bootServiceHost(state, appSession, ctx);
|
|
6606
6875
|
});
|
|
6607
6876
|
}
|
|
6877
|
+
const onServiceCrashed = () => {
|
|
6878
|
+
clearLaunchTimer(appSession);
|
|
6879
|
+
ctx.diagnostics?.report({
|
|
6880
|
+
severity: "error",
|
|
6881
|
+
code: "service-host-crashed",
|
|
6882
|
+
message: `Service host renderer process gone for appSessionId=${appSessionId}`,
|
|
6883
|
+
appSessionId
|
|
6884
|
+
});
|
|
6885
|
+
pushRuntimeStatus(ctx, appSession, { phase: "crashed", code: "service-host-crashed" });
|
|
6886
|
+
};
|
|
6887
|
+
appSession.listenerBag.on(serviceWindow.webContents, "render-process-gone", onServiceCrashed);
|
|
6888
|
+
pushRuntimeStatus(ctx, appSession, { phase: "launching" });
|
|
6889
|
+
startLaunchTimer(state, ctx, appSession);
|
|
6608
6890
|
return {
|
|
6609
6891
|
appSessionId,
|
|
6610
6892
|
bridgeId,
|
|
6611
6893
|
pagePath,
|
|
6894
|
+
resolvedPagePath,
|
|
6895
|
+
pageFallbackApplied,
|
|
6612
6896
|
serviceWcId: serviceWindow.webContents.id,
|
|
6613
6897
|
resourceBaseUrl,
|
|
6614
6898
|
manifest,
|
|
@@ -6622,6 +6906,9 @@ async function handlePageOpen(state, event, opts) {
|
|
|
6622
6906
|
throw new Error("[bridge-router] PAGE_OPEN rejected: caller not bound to app session");
|
|
6623
6907
|
}
|
|
6624
6908
|
const pagePath = normalizePagePath(opts.pagePath);
|
|
6909
|
+
if (ap.manifest.source === "app-config" && !ap.manifest.pages.includes(pagePath)) {
|
|
6910
|
+
throw new Error(`[bridge-router] PAGE_OPEN rejected: page-not-found "${pagePath}" is not in the compiled manifest`);
|
|
6911
|
+
}
|
|
6625
6912
|
const bridgeId = opts.bridgeId || newBridgeId();
|
|
6626
6913
|
const windowConfig = resolvePageWindowConfig(ap.appConfig, pagePath);
|
|
6627
6914
|
const isTab = isTabPage(ap.appConfig, pagePath);
|
|
@@ -6681,15 +6968,18 @@ function handleNavCallback(state, sender, payload) {
|
|
|
6681
6968
|
}
|
|
6682
6969
|
async function bootServiceHost(state, ap, ctx) {
|
|
6683
6970
|
if (state.appSessions.get(ap.appSessionId) !== ap) return;
|
|
6971
|
+
ctx.consoleForwarder?.notifyServiceHostReady?.(ap.appSessionId);
|
|
6684
6972
|
ap.logicInjected = await injectLogicBundle(ap);
|
|
6685
6973
|
if (!ap.logicInjected) {
|
|
6686
|
-
reportLogicLoadFailure(ap, ctx);
|
|
6974
|
+
const reason = reportLogicLoadFailure(ap, ctx);
|
|
6975
|
+
clearLaunchTimer(ap);
|
|
6976
|
+
pushRuntimeStatus(ctx, ap, { phase: "launch-failed", code: "logic-bundle-unreachable", reason });
|
|
6687
6977
|
return;
|
|
6688
6978
|
}
|
|
6689
6979
|
const rootPage = ap.pages.get(ap.appSessionId);
|
|
6690
6980
|
const rootMissing = !!rootPage && !pageInManifest(ap, rootPage.pagePath);
|
|
6691
6981
|
if (rootMissing) {
|
|
6692
|
-
reportPageNotFound(
|
|
6982
|
+
reportPageNotFound(ctx, ap.appSessionId, rootPage.pagePath);
|
|
6693
6983
|
} else if (rootPage) {
|
|
6694
6984
|
forwardToService(ap, makeLoadResource(ap, rootPage, "service"));
|
|
6695
6985
|
}
|
|
@@ -6723,16 +7013,30 @@ async function injectLogicBundle(ap) {
|
|
|
6723
7013
|
}
|
|
6724
7014
|
function reportLogicLoadFailure(ap, ctx) {
|
|
6725
7015
|
const hint = ap.appId === "unknown" ? ' appId could not be resolved (it fell back to "unknown") \u2014 the mini-program likely failed to compile or its project manifest/app config is missing.' : "";
|
|
6726
|
-
const
|
|
6727
|
-
|
|
7016
|
+
const shortReason = `[dimina-kit] Failed to load the mini-program logic bundle from ${logicBundleUrl(ap)}.`;
|
|
7017
|
+
const message = `${shortReason} The service runtime has no registered modules, so no page can mount.` + hint + ` Verify the project compiled successfully and that the resource server serves "${ap.appId}/${ap.root}/".`;
|
|
7018
|
+
ctx.diagnostics?.report({
|
|
7019
|
+
severity: "error",
|
|
7020
|
+
code: "logic-bundle-unreachable",
|
|
7021
|
+
message,
|
|
7022
|
+
appSessionId: ap.appSessionId
|
|
7023
|
+
});
|
|
6728
7024
|
ctx.guestConsole?.emit({ source: "service", level: "error", args: [message] });
|
|
7025
|
+
return shortReason;
|
|
6729
7026
|
}
|
|
6730
7027
|
function pageInManifest(ap, pagePath) {
|
|
7028
|
+
if (ap.manifest.source !== "app-config") return true;
|
|
6731
7029
|
return ap.manifest.pages.includes(normalizePagePath(pagePath));
|
|
6732
7030
|
}
|
|
6733
|
-
function reportPageNotFound(
|
|
6734
|
-
const
|
|
6735
|
-
|
|
7031
|
+
function reportPageNotFound(ctx, appSessionId, pagePath, fallbackTo) {
|
|
7032
|
+
const base = `Page[${pagePath}] not found. May be caused by: 1. Forgetting to add page route in app.json. 2. Invoking Page() in async task.`;
|
|
7033
|
+
const message = fallbackTo ? `${base} Falling back to "${fallbackTo}".` : base;
|
|
7034
|
+
ctx.diagnostics?.report({
|
|
7035
|
+
severity: "error",
|
|
7036
|
+
code: "page-not-found",
|
|
7037
|
+
message,
|
|
7038
|
+
appSessionId
|
|
7039
|
+
});
|
|
6736
7040
|
ctx.guestConsole?.emit({ source: "service", level: "error", args: [message] });
|
|
6737
7041
|
}
|
|
6738
7042
|
function maybeSendResourceLoaded(ap, page) {
|
|
@@ -6789,6 +7093,11 @@ function routeFromRender(state, ap, page, msg, ctx) {
|
|
|
6789
7093
|
handleContainerMsg(ap, page, msg, ctx, state);
|
|
6790
7094
|
}
|
|
6791
7095
|
}
|
|
7096
|
+
function reportServiceUncaughtError(ctx, ap, body) {
|
|
7097
|
+
const severity = body.level === "error" ? "error" : body.level === "warn" ? "warn" : "info";
|
|
7098
|
+
const message = Array.isArray(body.args) ? body.args.map((a) => String(a)).join(" ") : String(body.args ?? "");
|
|
7099
|
+
ctx.diagnostics?.report({ severity, code: "service-uncaught-error", message, appSessionId: ap.appSessionId });
|
|
7100
|
+
}
|
|
6792
7101
|
function handleContainerMsg(ap, page, msg, ctx, state) {
|
|
6793
7102
|
switch (msg.type) {
|
|
6794
7103
|
case "serviceResourceLoaded":
|
|
@@ -6807,22 +7116,31 @@ function handleContainerMsg(ap, page, msg, ctx, state) {
|
|
|
6807
7116
|
ap.simulatorWc.send(SIMULATOR_EVENTS.DOM_READY, { bridgeId: page.bridgeId });
|
|
6808
7117
|
}
|
|
6809
7118
|
state.emitRenderEvent({ kind: "domReady", appId: ap.appId, bridgeId: page.bridgeId });
|
|
7119
|
+
markSessionRunning(ctx, ap, page);
|
|
6810
7120
|
break;
|
|
6811
7121
|
case "invokeAPI":
|
|
6812
7122
|
void handleSimulatorApi(state, ap, page, msg.body, ctx);
|
|
6813
7123
|
break;
|
|
6814
7124
|
case "serviceHostError": {
|
|
6815
|
-
console.warn("[bridge-router] service host error:", msg.body);
|
|
6816
7125
|
const errBody = msg.body;
|
|
6817
7126
|
const errArg = errBody?.message ?? msg.body;
|
|
7127
|
+
ctx.diagnostics?.report({
|
|
7128
|
+
severity: "error",
|
|
7129
|
+
code: "service-host-error",
|
|
7130
|
+
message: String(errArg),
|
|
7131
|
+
appSessionId: ap.appSessionId
|
|
7132
|
+
});
|
|
6818
7133
|
for (const id of state.appLifecycle.listeners(ap.appSessionId, "onError")) {
|
|
6819
7134
|
sendCallback(ap, id, errArg);
|
|
6820
7135
|
}
|
|
6821
7136
|
break;
|
|
6822
7137
|
}
|
|
6823
|
-
case "consoleLog":
|
|
7138
|
+
case "consoleLog": {
|
|
6824
7139
|
ctx.guestConsole?.emit(msg.body);
|
|
7140
|
+
const body = msg.body;
|
|
7141
|
+
if (body?.source === "service") reportServiceUncaughtError(ctx, ap, body);
|
|
6825
7142
|
break;
|
|
7143
|
+
}
|
|
6826
7144
|
case "storageChanged":
|
|
6827
7145
|
ctx.onServiceStorageChanged?.(ap.appId, msg.body);
|
|
6828
7146
|
break;
|
|
@@ -6903,16 +7221,44 @@ function handleNavBarApi(ap, page, name, params) {
|
|
|
6903
7221
|
sendCallback(ap, params.success, successResult);
|
|
6904
7222
|
sendCallback(ap, params.complete, successResult);
|
|
6905
7223
|
}
|
|
7224
|
+
function failActionCallback(ap, params, errMsg) {
|
|
7225
|
+
const fail = { errMsg };
|
|
7226
|
+
sendCallback(ap, params.fail, fail);
|
|
7227
|
+
sendCallback(ap, params.complete, fail);
|
|
7228
|
+
}
|
|
6906
7229
|
function sendActionOrFail(ap, eventName, payload, name, params) {
|
|
6907
7230
|
if (!ap.simulatorWc.isDestroyed()) {
|
|
6908
7231
|
ap.simulatorWc.send(eventName, payload);
|
|
6909
7232
|
return;
|
|
6910
7233
|
}
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
7234
|
+
failActionCallback(ap, params, `${name}:fail simulator window destroyed`);
|
|
7235
|
+
}
|
|
7236
|
+
function extractNavTargetPagePath(params) {
|
|
7237
|
+
const raw = params.url;
|
|
7238
|
+
if (typeof raw !== "string" || !raw) return void 0;
|
|
7239
|
+
return normalizePagePath(raw.split("?")[0] ?? raw);
|
|
7240
|
+
}
|
|
7241
|
+
function checkNavTarget(ap, name, targetPagePath) {
|
|
7242
|
+
if (ap.manifest.source !== "app-config") return { ok: true };
|
|
7243
|
+
if (!ap.manifest.pages.includes(targetPagePath)) {
|
|
7244
|
+
return { ok: false, errMsg: `${name}:fail page "${targetPagePath}" is not found`, reportNotFound: true };
|
|
7245
|
+
}
|
|
7246
|
+
if (name === "switchTab") {
|
|
7247
|
+
const inTabBar = ap.manifest.tabBar?.list.some((item) => normalizePagePath(item.pagePath) === targetPagePath) ?? false;
|
|
7248
|
+
if (!inTabBar) return { ok: false, errMsg: "switchTab:fail can not switch to no-tabBar page" };
|
|
7249
|
+
}
|
|
7250
|
+
return { ok: true };
|
|
6914
7251
|
}
|
|
6915
|
-
function handleNavActionApi(ap, page, name, params) {
|
|
7252
|
+
function handleNavActionApi(ap, ctx, page, name, params) {
|
|
7253
|
+
const targetPagePath = extractNavTargetPagePath(params);
|
|
7254
|
+
if (targetPagePath !== void 0) {
|
|
7255
|
+
const verdict = checkNavTarget(ap, name, targetPagePath);
|
|
7256
|
+
if (!verdict.ok) {
|
|
7257
|
+
if (verdict.reportNotFound) reportPageNotFound(ctx, ap.appSessionId, targetPagePath);
|
|
7258
|
+
failActionCallback(ap, params, verdict.errMsg);
|
|
7259
|
+
return;
|
|
7260
|
+
}
|
|
7261
|
+
}
|
|
6916
7262
|
const payload = {
|
|
6917
7263
|
appSessionId: ap.appSessionId,
|
|
6918
7264
|
bridgeId: page.bridgeId,
|
|
@@ -6974,7 +7320,7 @@ async function handleSimulatorApi(state, ap, page, body, ctx) {
|
|
|
6974
7320
|
return;
|
|
6975
7321
|
}
|
|
6976
7322
|
if (NAV_ACTION_NAMES.has(name)) {
|
|
6977
|
-
handleNavActionApi(ap, page, name, params);
|
|
7323
|
+
handleNavActionApi(ap, ctx, page, name, params);
|
|
6978
7324
|
return;
|
|
6979
7325
|
}
|
|
6980
7326
|
if (TAB_ACTION_NAMES.has(name)) {
|
|
@@ -7016,7 +7362,7 @@ function forwardApiCallToSimulator(state, ap, page, name, params) {
|
|
|
7016
7362
|
const fail = { errMsg: `${pending.name}:fail no handler (timeout)` };
|
|
7017
7363
|
sendCallback(target, pending.callbacks.fail, fail);
|
|
7018
7364
|
sendCallback(target, pending.callbacks.complete, fail);
|
|
7019
|
-
},
|
|
7365
|
+
}, apiCallWatchdogMs(name, params));
|
|
7020
7366
|
state.pendingApiCalls.set(requestId, {
|
|
7021
7367
|
appSessionId: ap.appSessionId,
|
|
7022
7368
|
callbacks,
|
|
@@ -7065,7 +7411,12 @@ function handleApiResponse(state, sender, payload) {
|
|
|
7065
7411
|
sendCallback(ap, pending.callbacks.success, payload.result);
|
|
7066
7412
|
sendCallback(ap, pending.callbacks.complete, payload.result ?? { errMsg: `${pending.name}:ok` });
|
|
7067
7413
|
} else {
|
|
7068
|
-
const
|
|
7414
|
+
const result = payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? payload.result : void 0;
|
|
7415
|
+
const resultErrMsg = typeof result?.errMsg === "string" ? result.errMsg : void 0;
|
|
7416
|
+
const fail = {
|
|
7417
|
+
...result,
|
|
7418
|
+
errMsg: payload.errMsg || resultErrMsg || `${pending.name}:fail`
|
|
7419
|
+
};
|
|
7069
7420
|
sendCallback(ap, pending.callbacks.fail, fail);
|
|
7070
7421
|
sendCallback(ap, pending.callbacks.complete, fail);
|
|
7071
7422
|
}
|
|
@@ -7259,6 +7610,7 @@ async function disposeAppSession(state, appSessionId, opts = {}) {
|
|
|
7259
7610
|
const ap = state.appSessions.get(appSessionId);
|
|
7260
7611
|
if (!ap) return;
|
|
7261
7612
|
state.appSessions.delete(appSessionId);
|
|
7613
|
+
clearLaunchTimer(ap);
|
|
7262
7614
|
const registryHandle = ap.registryHandle;
|
|
7263
7615
|
ap.registryHandle = null;
|
|
7264
7616
|
void registryHandle?.dispose();
|
|
@@ -7276,25 +7628,45 @@ async function disposeAppSession(state, appSessionId, opts = {}) {
|
|
|
7276
7628
|
});
|
|
7277
7629
|
}
|
|
7278
7630
|
}
|
|
7279
|
-
async function loadAppConfig(resourceBase) {
|
|
7631
|
+
async function loadAppConfig(resourceBase, onUnreachable) {
|
|
7280
7632
|
const cfgUrl = new URL("app-config.json", resourceBase.endsWith("/") ? resourceBase : `${resourceBase}/`).toString();
|
|
7281
7633
|
try {
|
|
7282
7634
|
const res = await fetch(cfgUrl);
|
|
7283
7635
|
if (!res.ok) {
|
|
7636
|
+
const error = new Error(`app-config.json fetch ${res.status} at ${cfgUrl}`);
|
|
7284
7637
|
console.warn(`[bridge-router] no app-config.json at ${cfgUrl} (${res.status})`);
|
|
7638
|
+
onUnreachable?.({ url: cfgUrl, error });
|
|
7285
7639
|
return {};
|
|
7286
7640
|
}
|
|
7287
7641
|
return await res.json();
|
|
7288
7642
|
} catch (error) {
|
|
7289
7643
|
console.warn("[bridge-router] failed to fetch/parse app-config.json:", error);
|
|
7644
|
+
onUnreachable?.({ url: cfgUrl, error });
|
|
7290
7645
|
return {};
|
|
7291
7646
|
}
|
|
7292
7647
|
}
|
|
7293
7648
|
function buildAppManifest(appConfig, fallbackEntry) {
|
|
7294
7649
|
const entry = appConfig.app?.entryPagePath || fallbackEntry;
|
|
7295
|
-
const
|
|
7650
|
+
const hasCompiledPages = !!appConfig.app?.pages?.length;
|
|
7651
|
+
const pages = hasCompiledPages ? appConfig.app.pages : [entry];
|
|
7296
7652
|
const tabBar = appConfig.app?.tabBar && Array.isArray(appConfig.app.tabBar.list) && appConfig.app.tabBar.list.length > 0 ? appConfig.app.tabBar : void 0;
|
|
7297
|
-
return {
|
|
7653
|
+
return {
|
|
7654
|
+
entryPagePath: normalizePagePath(entry),
|
|
7655
|
+
pages: pages.map(normalizePagePath),
|
|
7656
|
+
tabBar,
|
|
7657
|
+
// 'app-config' means `pages` above is the real compiled list mount gates
|
|
7658
|
+
// can trust; 'fallback' means app-config.json was unreachable and `pages`
|
|
7659
|
+
// is just the single requested page — nothing to validate membership
|
|
7660
|
+
// against, so every gate keyed on this source lets it through unchanged.
|
|
7661
|
+
source: hasCompiledPages ? "app-config" : "fallback"
|
|
7662
|
+
};
|
|
7663
|
+
}
|
|
7664
|
+
function resolveRootPagePath(manifest, requestedPagePath) {
|
|
7665
|
+
if (manifest.source !== "app-config" || manifest.pages.includes(requestedPagePath)) {
|
|
7666
|
+
return { resolvedPagePath: requestedPagePath, pageFallbackApplied: false };
|
|
7667
|
+
}
|
|
7668
|
+
const resolvedPagePath = manifest.pages.includes(manifest.entryPagePath) ? manifest.entryPagePath : manifest.pages[0];
|
|
7669
|
+
return { resolvedPagePath, pageFallbackApplied: true };
|
|
7298
7670
|
}
|
|
7299
7671
|
function resolvePageWindowConfig(appConfig, pagePath) {
|
|
7300
7672
|
const normalized = normalizePagePath(pagePath);
|
|
@@ -8971,6 +9343,7 @@ function createNetworkForwarder(bridge) {
|
|
|
8971
9343
|
let sink = "idle";
|
|
8972
9344
|
let probeConsoleBuffer = [];
|
|
8973
9345
|
let readyTimeoutTimer = null;
|
|
9346
|
+
let probeDeadline = null;
|
|
8974
9347
|
let dispatchQueue = [];
|
|
8975
9348
|
let flushScheduled = false;
|
|
8976
9349
|
let readyRetryTimer = null;
|
|
@@ -8981,6 +9354,7 @@ function createNetworkForwarder(bridge) {
|
|
|
8981
9354
|
function beginProbing() {
|
|
8982
9355
|
if (sink === "probing") return;
|
|
8983
9356
|
sink = "probing";
|
|
9357
|
+
probeDeadline = Date.now() + DEVTOOLS_READY_TIMEOUT_MS;
|
|
8984
9358
|
if (readyTimeoutTimer) clearTimeout(readyTimeoutTimer);
|
|
8985
9359
|
readyTimeoutTimer = setTimeout(() => {
|
|
8986
9360
|
readyTimeoutTimer = null;
|
|
@@ -8989,6 +9363,7 @@ function createNetworkForwarder(bridge) {
|
|
|
8989
9363
|
}
|
|
8990
9364
|
function markReady() {
|
|
8991
9365
|
sink = "ready";
|
|
9366
|
+
probeDeadline = null;
|
|
8992
9367
|
if (readyTimeoutTimer) {
|
|
8993
9368
|
clearTimeout(readyTimeoutTimer);
|
|
8994
9369
|
readyTimeoutTimer = null;
|
|
@@ -9001,6 +9376,7 @@ function createNetworkForwarder(bridge) {
|
|
|
9001
9376
|
}
|
|
9002
9377
|
function degradeToConsole() {
|
|
9003
9378
|
sink = "degraded";
|
|
9379
|
+
probeDeadline = null;
|
|
9004
9380
|
dispatchQueue = [];
|
|
9005
9381
|
if (readyTimeoutTimer) {
|
|
9006
9382
|
clearTimeout(readyTimeoutTimer);
|
|
@@ -9105,9 +9481,17 @@ function createNetworkForwarder(bridge) {
|
|
|
9105
9481
|
}
|
|
9106
9482
|
function scheduleReadyRetry() {
|
|
9107
9483
|
if (readyRetryTimer || sink === "ready" || sink === "degraded") return;
|
|
9484
|
+
if (probeDeadline !== null && Date.now() >= probeDeadline) {
|
|
9485
|
+
degradeToConsole();
|
|
9486
|
+
return;
|
|
9487
|
+
}
|
|
9108
9488
|
readyRetryTimer = setTimeout(() => {
|
|
9109
9489
|
readyRetryTimer = null;
|
|
9110
9490
|
if (sink === "degraded") return;
|
|
9491
|
+
if (probeDeadline !== null && Date.now() >= probeDeadline) {
|
|
9492
|
+
degradeToConsole();
|
|
9493
|
+
return;
|
|
9494
|
+
}
|
|
9111
9495
|
if (dispatchQueue.length > 0) scheduleFlush();
|
|
9112
9496
|
}, READY_RETRY_MS);
|
|
9113
9497
|
}
|
|
@@ -9146,6 +9530,7 @@ function createNetworkForwarder(bridge) {
|
|
|
9146
9530
|
dispatchQueue = [];
|
|
9147
9531
|
probeConsoleBuffer = [];
|
|
9148
9532
|
sink = "idle";
|
|
9533
|
+
probeDeadline = null;
|
|
9149
9534
|
if (readyRetryTimer) {
|
|
9150
9535
|
clearTimeout(readyRetryTimer);
|
|
9151
9536
|
readyRetryTimer = null;
|
|
@@ -9296,6 +9681,7 @@ function createNetworkForwarder(bridge) {
|
|
|
9296
9681
|
clearTimeout(readyRetryTimer);
|
|
9297
9682
|
readyRetryTimer = null;
|
|
9298
9683
|
}
|
|
9684
|
+
probeDeadline = null;
|
|
9299
9685
|
probeConsoleBuffer = [];
|
|
9300
9686
|
if (!devtoolsWc) {
|
|
9301
9687
|
sink = "idle";
|
|
@@ -9319,6 +9705,7 @@ function createNetworkForwarder(bridge) {
|
|
|
9319
9705
|
}
|
|
9320
9706
|
});
|
|
9321
9707
|
}
|
|
9708
|
+
sink = "idle";
|
|
9322
9709
|
beginProbing();
|
|
9323
9710
|
if (dispatchQueue.length > 0) scheduleFlush();
|
|
9324
9711
|
}
|
|
@@ -10388,6 +10775,11 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
10388
10775
|
// src/main/services/views/simulator-session-policy.ts
|
|
10389
10776
|
import { session as session3 } from "electron";
|
|
10390
10777
|
import { toDisposable as toDisposable7 } from "@dimina-kit/electron-deck/main";
|
|
10778
|
+
var CORS_OVERRIDE_HEADERS = /* @__PURE__ */ new Set([
|
|
10779
|
+
"access-control-allow-origin",
|
|
10780
|
+
"access-control-allow-headers",
|
|
10781
|
+
"access-control-allow-methods"
|
|
10782
|
+
]);
|
|
10391
10783
|
function applySimulatorWebRequestPolicy(simulatorSession) {
|
|
10392
10784
|
simulatorSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
|
10393
10785
|
const forcedReferer = getSimulatorServicewechatReferer();
|
|
@@ -10398,6 +10790,9 @@ function applySimulatorWebRequestPolicy(simulatorSession) {
|
|
|
10398
10790
|
});
|
|
10399
10791
|
simulatorSession.webRequest.onHeadersReceived((details, callback) => {
|
|
10400
10792
|
const headers = details.responseHeaders ?? {};
|
|
10793
|
+
for (const key of Object.keys(headers)) {
|
|
10794
|
+
if (CORS_OVERRIDE_HEADERS.has(key.toLowerCase())) delete headers[key];
|
|
10795
|
+
}
|
|
10401
10796
|
headers["access-control-allow-origin"] = ["*"];
|
|
10402
10797
|
headers["access-control-allow-headers"] = ["*"];
|
|
10403
10798
|
headers["access-control-allow-methods"] = ["*"];
|
|
@@ -11033,6 +11428,7 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
11033
11428
|
context.registry.add(registerProjectFsIpc(context));
|
|
11034
11429
|
context.registry.add(setupSimulatorSessionPolicy());
|
|
11035
11430
|
context.registry.add(installThemeBackgroundSync());
|
|
11431
|
+
if (!config.adapter) context.registry.add(setupCompileWorkerStandby(context));
|
|
11036
11432
|
registerBuiltinModules(config, context);
|
|
11037
11433
|
const simSession = session4.fromPartition(SHARED_MINIAPP_PARTITION);
|
|
11038
11434
|
context.registry.add(setupSimulatorTempFiles(simSession));
|