@dimina-kit/devtools 0.4.0-dev.20260718095333 → 0.4.0-dev.20260728063215
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.d.ts +10 -1
- package/dist/main/app/app.js +78 -2
- package/dist/main/app/lifecycle.d.ts +12 -1
- package/dist/main/app/lifecycle.js +27 -1
- package/dist/main/index.bundle.js +1263 -206
- package/dist/main/index.js +49 -1
- package/dist/main/ipc/bridge-router.d.ts +36 -0
- package/dist/main/ipc/bridge-router.js +56 -0
- package/dist/main/ipc/index.d.ts +1 -0
- package/dist/main/ipc/index.js +1 -0
- package/dist/main/ipc/internal-devtools.d.ts +15 -0
- package/dist/main/ipc/internal-devtools.js +9 -0
- package/dist/main/runtime/devtools-backend-before-quit.harness.d.ts +61 -0
- package/dist/main/runtime/devtools-backend-before-quit.harness.js +356 -0
- package/dist/main/runtime/devtools-backend.js +49 -4
- package/dist/main/services/compile-standby.js +4 -0
- package/dist/main/services/console-forward/cdp-inject.d.ts +18 -0
- package/dist/main/services/console-forward/cdp-inject.js +30 -0
- package/dist/main/services/console-forward/global-console-mirror.d.ts +33 -0
- package/dist/main/services/console-forward/global-console-mirror.js +71 -0
- package/dist/main/services/console-forward/global-diagnostics-mirror.d.ts +33 -0
- package/dist/main/services/console-forward/global-diagnostics-mirror.js +73 -0
- package/dist/main/services/console-forward/index.d.ts +15 -1
- package/dist/main/services/console-forward/index.js +42 -2
- package/dist/main/services/console-forward/internal-log.d.ts +11 -0
- package/dist/main/services/console-forward/internal-log.js +23 -0
- package/dist/main/services/console-forward/open-gated-relay.d.ts +67 -0
- package/dist/main/services/console-forward/open-gated-relay.js +55 -0
- package/dist/main/services/diagnostics/index.d.ts +10 -0
- package/dist/main/services/elements-forward/index.js +14 -96
- package/dist/main/services/mcp/server.js +24 -2
- package/dist/main/services/network-forward/frontend-dispatch.d.ts +64 -0
- package/dist/main/services/network-forward/frontend-dispatch.js +113 -8
- package/dist/main/services/network-forward/global-body-gate.d.ts +46 -0
- package/dist/main/services/network-forward/global-body-gate.js +93 -0
- package/dist/main/services/network-forward/global-mirror-test-fixtures.d.ts +48 -0
- package/dist/main/services/network-forward/global-mirror-test-fixtures.js +96 -0
- package/dist/main/services/network-forward/index.d.ts +31 -0
- package/dist/main/services/network-forward/index.js +256 -8
- package/dist/main/services/network-forward/user-facing.d.ts +21 -0
- package/dist/main/services/network-forward/user-facing.js +50 -0
- package/dist/main/services/projects/create-project-service.js +10 -3
- package/dist/main/services/update/github-release-checker.js +22 -3
- package/dist/main/services/update/update-manager.d.ts +4 -1
- package/dist/main/services/update/update-manager.js +30 -5
- package/dist/main/services/views/console-filter.d.ts +145 -0
- package/dist/main/services/views/console-filter.js +233 -0
- package/dist/main/services/views/frontend-bootstrap-gate.d.ts +59 -0
- package/dist/main/services/views/frontend-bootstrap-gate.js +117 -0
- package/dist/main/services/views/native-simulator-devtools-host.js +138 -30
- package/dist/main/services/views/view-manager-devtools-host-test-fixtures.d.ts +76 -0
- package/dist/main/services/views/view-manager-devtools-host-test-fixtures.js +182 -0
- package/dist/main/services/workbench-context.d.ts +10 -0
- package/dist/main/utils/theme.d.ts +10 -6
- package/dist/main/utils/theme.js +10 -6
- package/dist/main/windows/internal-devtools-window/index.d.ts +66 -0
- package/dist/main/windows/internal-devtools-window/index.js +160 -0
- package/dist/native-host/render/render.js +89 -73
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +1 -1
- package/dist/preload/windows/simulator.cjs.map +1 -1
- package/dist/renderer/assets/index-M5NDq_vi.js +49 -0
- package/dist/renderer/assets/{input-c2OcrrZy.js → input-dsgeTmVX.js} +2 -2
- package/dist/renderer/assets/ipc-transport-BgFdT9bT.js +9 -0
- package/dist/renderer/assets/{popover-kv2qspWz.js → popover-Disfu1cx.js} +2 -2
- package/dist/renderer/assets/{select-DKqzMtTh.js → select-DAw1hzkl.js} +2 -2
- package/dist/renderer/assets/{settings-dJNKTGr8.js → settings-M_8GFW2M.js} +2 -2
- package/dist/renderer/assets/settings-api-DFR5eDl_.js +2 -0
- package/dist/renderer/assets/{workbenchSettings-DQ_VP5-W.js → workbenchSettings-CxdXeoOu.js} +2 -2
- package/dist/renderer/entries/main/index.html +5 -5
- package/dist/renderer/entries/popover/index.html +4 -4
- package/dist/renderer/entries/settings/index.html +4 -4
- package/dist/renderer/entries/workbench-settings/index.html +3 -3
- package/dist/service-host/sync-impls/menu-button-geometry.js +15 -5
- package/dist/service-host/sync-impls/menu-button.js +5 -3
- package/dist/shared/ipc-channels.d.ts +3 -0
- package/dist/shared/ipc-channels.js +6 -0
- package/dist/simulator/assets/device-shell-Cs-rmP1f.js +2 -0
- package/dist/simulator/assets/device-shell-DOy53Y0s.css +1 -0
- package/dist/simulator/assets/{simulator-Cy8c-eA2.js → simulator-BG-5CADK.js} +3 -3
- package/dist/simulator/device-shell/menu-button-geometry.js +15 -5
- package/dist/simulator/simulator.html +1 -1
- package/package.json +7 -7
- package/dist/renderer/assets/index-U9F8MrtV.js +0 -49
- package/dist/renderer/assets/ipc-transport-CuDJ07aE.js +0 -9
- package/dist/renderer/assets/settings-api-qpXKDRXt.js +0 -2
- package/dist/simulator/assets/device-shell-C-HZY3bL.css +0 -1
- package/dist/simulator/assets/device-shell-Cu1ZPLfe.js +0 -2
|
@@ -545,6 +545,11 @@ var AppChannel = {
|
|
|
545
545
|
var AutomationChannel = {
|
|
546
546
|
GetPort: "automation:port"
|
|
547
547
|
};
|
|
548
|
+
var InternalDevtoolsChannel = {
|
|
549
|
+
// Open (or focus, if already open) the internal debug DevTools, hosted in
|
|
550
|
+
// its own dedicated window (see internal-devtools-window/index.ts).
|
|
551
|
+
Open: "internal-devtools:open"
|
|
552
|
+
};
|
|
548
553
|
var SettingsChannel = {
|
|
549
554
|
SetVisible: "settings:setVisible",
|
|
550
555
|
ConfigChanged: "settings:configChanged",
|
|
@@ -892,9 +897,9 @@ function registerProjectFsIpc(ctx) {
|
|
|
892
897
|
}
|
|
893
898
|
|
|
894
899
|
// src/main/app/app.ts
|
|
895
|
-
import { app as app15, BrowserWindow as
|
|
896
|
-
import
|
|
897
|
-
import
|
|
900
|
+
import { app as app15, BrowserWindow as BrowserWindow9, nativeImage, session as session4 } from "electron";
|
|
901
|
+
import fs13 from "fs";
|
|
902
|
+
import path25 from "path";
|
|
898
903
|
|
|
899
904
|
// src/main/utils/paths.ts
|
|
900
905
|
import fs3 from "fs";
|
|
@@ -1074,13 +1079,268 @@ function wireMainWindowEvents(win, state = {}) {
|
|
|
1074
1079
|
return registry;
|
|
1075
1080
|
}
|
|
1076
1081
|
|
|
1082
|
+
// src/main/windows/internal-devtools-window/index.ts
|
|
1083
|
+
import { BrowserWindow as BrowserWindow3, View as View2, WebContentsView as WebContentsView2 } from "electron";
|
|
1084
|
+
function createInternalDevtoolsWindow(target, opts) {
|
|
1085
|
+
let win = null;
|
|
1086
|
+
let hostView = null;
|
|
1087
|
+
const hostChangedHandlers = /* @__PURE__ */ new Set();
|
|
1088
|
+
let currentHost = null;
|
|
1089
|
+
function notifyHostChanged(hostWc) {
|
|
1090
|
+
if (hostWc === currentHost) return;
|
|
1091
|
+
currentHost = hostWc;
|
|
1092
|
+
for (const handler of [...hostChangedHandlers]) {
|
|
1093
|
+
try {
|
|
1094
|
+
handler(hostWc);
|
|
1095
|
+
} catch (err2) {
|
|
1096
|
+
console.warn("[internal-devtools-window] onHostChanged handler threw, other handlers still ran:", err2 instanceof Error ? err2.message : String(err2));
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
function resizeHostView(hostWindow, view) {
|
|
1101
|
+
try {
|
|
1102
|
+
const [width, height] = hostWindow.getContentSize();
|
|
1103
|
+
view.setBounds({ x: 0, y: 0, width, height });
|
|
1104
|
+
} catch {
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
function buildOnce() {
|
|
1108
|
+
if (win) return;
|
|
1109
|
+
const hostWindow = new BrowserWindow3({
|
|
1110
|
+
width: 1e3,
|
|
1111
|
+
height: 700,
|
|
1112
|
+
title: "\u5168\u5C40\u8C03\u8BD5",
|
|
1113
|
+
show: false
|
|
1114
|
+
});
|
|
1115
|
+
win = hostWindow;
|
|
1116
|
+
const view = new WebContentsView2();
|
|
1117
|
+
hostView = view;
|
|
1118
|
+
const container = new View2();
|
|
1119
|
+
container.addChildView(view);
|
|
1120
|
+
hostWindow.contentView = container;
|
|
1121
|
+
resizeHostView(hostWindow, view);
|
|
1122
|
+
hostWindow.on("resize", () => resizeHostView(hostWindow, view));
|
|
1123
|
+
hostWindow.on("close", (event) => {
|
|
1124
|
+
if (opts?.isAppQuitting?.()) return;
|
|
1125
|
+
event.preventDefault();
|
|
1126
|
+
hostWindow.hide();
|
|
1127
|
+
notifyHostChanged(null);
|
|
1128
|
+
});
|
|
1129
|
+
hostWindow.on("closed", () => {
|
|
1130
|
+
if (win !== hostWindow) return;
|
|
1131
|
+
win = null;
|
|
1132
|
+
notifyHostChanged(null);
|
|
1133
|
+
});
|
|
1134
|
+
hostWindow.on("hide", () => notifyHostChanged(null));
|
|
1135
|
+
hostWindow.on("show", () => notifyHostChanged(view.webContents));
|
|
1136
|
+
if (!target.webContents.isDestroyed()) {
|
|
1137
|
+
target.webContents.setDevToolsWebContents(view.webContents);
|
|
1138
|
+
target.webContents.openDevTools({ mode: "detach", activate: false });
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
return {
|
|
1142
|
+
open() {
|
|
1143
|
+
buildOnce();
|
|
1144
|
+
if (process.env.NODE_ENV === "test") {
|
|
1145
|
+
win.showInactive();
|
|
1146
|
+
} else {
|
|
1147
|
+
win.show();
|
|
1148
|
+
win.focus();
|
|
1149
|
+
}
|
|
1150
|
+
if (hostView) notifyHostChanged(hostView.webContents);
|
|
1151
|
+
},
|
|
1152
|
+
dispose() {
|
|
1153
|
+
if (!win) return;
|
|
1154
|
+
const hostWindow = win;
|
|
1155
|
+
if (!hostWindow.isDestroyed()) hostWindow.destroy();
|
|
1156
|
+
if (win === hostWindow) {
|
|
1157
|
+
win = null;
|
|
1158
|
+
notifyHostChanged(null);
|
|
1159
|
+
}
|
|
1160
|
+
},
|
|
1161
|
+
onHostChanged(handler) {
|
|
1162
|
+
hostChangedHandlers.add(handler);
|
|
1163
|
+
if (currentHost) {
|
|
1164
|
+
queueMicrotask(() => {
|
|
1165
|
+
if (!hostChangedHandlers.has(handler)) return;
|
|
1166
|
+
if (!currentHost) return;
|
|
1167
|
+
try {
|
|
1168
|
+
handler(currentHost);
|
|
1169
|
+
} catch (err2) {
|
|
1170
|
+
console.warn("[internal-devtools-window] onHostChanged catch-up handler threw:", err2 instanceof Error ? err2.message : String(err2));
|
|
1171
|
+
}
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
return () => {
|
|
1175
|
+
hostChangedHandlers.delete(handler);
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// src/main/services/views/inject-when-ready.ts
|
|
1182
|
+
function isFrontendSettled(wc) {
|
|
1183
|
+
try {
|
|
1184
|
+
if (wc.isDestroyed()) return false;
|
|
1185
|
+
const url = wc.getURL();
|
|
1186
|
+
const mainFrameLoading = typeof wc.isLoadingMainFrame === "function" ? wc.isLoadingMainFrame() : wc.isLoading();
|
|
1187
|
+
return !mainFrameLoading && url !== "" && url !== "about:blank";
|
|
1188
|
+
} catch {
|
|
1189
|
+
return false;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
function createLoadDeferredInjector() {
|
|
1193
|
+
const pending = /* @__PURE__ */ new WeakMap();
|
|
1194
|
+
return function injectWhenReady(wc, kind, run) {
|
|
1195
|
+
if (wc.isDestroyed()) return;
|
|
1196
|
+
if (isFrontendSettled(wc)) {
|
|
1197
|
+
run();
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
let kinds = pending.get(wc);
|
|
1201
|
+
if (!kinds) {
|
|
1202
|
+
kinds = /* @__PURE__ */ new Map();
|
|
1203
|
+
pending.set(wc, kinds);
|
|
1204
|
+
}
|
|
1205
|
+
const alreadyHooked = kinds.has(kind);
|
|
1206
|
+
kinds.set(kind, run);
|
|
1207
|
+
if (alreadyHooked) return;
|
|
1208
|
+
wc.once("did-stop-loading", () => {
|
|
1209
|
+
const runner = kinds.get(kind);
|
|
1210
|
+
kinds.delete(kind);
|
|
1211
|
+
if (!runner || wc.isDestroyed()) return;
|
|
1212
|
+
runner();
|
|
1213
|
+
});
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
// src/main/services/console-forward/open-gated-relay.ts
|
|
1218
|
+
var DEFAULT_INJECT_TIMEOUT_MS = 1e4;
|
|
1219
|
+
function createOpenGatedRelay(onHostChanged, subscribe, inject, opts) {
|
|
1220
|
+
const injectTimeoutMs = opts?.injectTimeoutMs ?? DEFAULT_INJECT_TIMEOUT_MS;
|
|
1221
|
+
const state = /* @__PURE__ */ new WeakMap();
|
|
1222
|
+
let generationSeq = 0;
|
|
1223
|
+
const inFlightTimers = /* @__PURE__ */ new Set();
|
|
1224
|
+
let live = null;
|
|
1225
|
+
function deliver(entry) {
|
|
1226
|
+
if (state.has(entry)) return;
|
|
1227
|
+
const generation = ++generationSeq;
|
|
1228
|
+
state.set(entry, { phase: "pending", generation });
|
|
1229
|
+
const timer = setTimeout(() => {
|
|
1230
|
+
inFlightTimers.delete(timer);
|
|
1231
|
+
const cur = state.get(entry);
|
|
1232
|
+
if (cur && cur.phase === "pending" && cur.generation === generation) state.delete(entry);
|
|
1233
|
+
}, injectTimeoutMs);
|
|
1234
|
+
timer.unref?.();
|
|
1235
|
+
inFlightTimers.add(timer);
|
|
1236
|
+
const settle = (ok2) => {
|
|
1237
|
+
clearTimeout(timer);
|
|
1238
|
+
inFlightTimers.delete(timer);
|
|
1239
|
+
const cur = state.get(entry);
|
|
1240
|
+
if (!cur || cur.phase !== "pending" || cur.generation !== generation) return;
|
|
1241
|
+
if (ok2) state.set(entry, { phase: "done", generation });
|
|
1242
|
+
else state.delete(entry);
|
|
1243
|
+
};
|
|
1244
|
+
Promise.resolve().then(() => inject(entry)).then((ok2) => settle(ok2 === true), () => settle(false));
|
|
1245
|
+
}
|
|
1246
|
+
const unregister = onHostChanged((host) => {
|
|
1247
|
+
live?.dispose();
|
|
1248
|
+
live = host !== null ? subscribe(deliver, { replay: true }) : null;
|
|
1249
|
+
});
|
|
1250
|
+
return {
|
|
1251
|
+
dispose: () => {
|
|
1252
|
+
for (const timer of inFlightTimers) clearTimeout(timer);
|
|
1253
|
+
inFlightTimers.clear();
|
|
1254
|
+
live?.dispose();
|
|
1255
|
+
live = null;
|
|
1256
|
+
unregister();
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
// src/main/services/console-forward/cdp-inject.ts
|
|
1262
|
+
function injectViaCdp(broker, target, script, warnTag) {
|
|
1263
|
+
const lease = broker.acquire(target);
|
|
1264
|
+
if (!lease) return false;
|
|
1265
|
+
return lease.send("Runtime.evaluate", { expression: script }).then(
|
|
1266
|
+
(result) => {
|
|
1267
|
+
if (result?.exceptionDetails) {
|
|
1268
|
+
console.warn(`[${warnTag}] Runtime.evaluate reported an exception, will retry on next reopen`);
|
|
1269
|
+
return false;
|
|
1270
|
+
}
|
|
1271
|
+
return true;
|
|
1272
|
+
},
|
|
1273
|
+
(err2) => {
|
|
1274
|
+
console.warn(`[${warnTag}] injection failed, will retry on next reopen:`, err2 instanceof Error ? err2.message : String(err2));
|
|
1275
|
+
return false;
|
|
1276
|
+
}
|
|
1277
|
+
);
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
// src/main/services/console-forward/global-console-mirror.ts
|
|
1281
|
+
var FORWARDABLE_LEVELS = /* @__PURE__ */ new Set(["log", "warn", "error", "info", "debug"]);
|
|
1282
|
+
function buildMirrorScript(entry) {
|
|
1283
|
+
const method = FORWARDABLE_LEVELS.has(entry.level ?? "") ? entry.level : "log";
|
|
1284
|
+
const tag = entry.source === "render" ? "[render]" : "[service]";
|
|
1285
|
+
const argsJson = JSON.stringify(entry.args ?? []);
|
|
1286
|
+
return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});console[${JSON.stringify(method)}](${JSON.stringify(tag)},...a)}catch(_){}})()`;
|
|
1287
|
+
}
|
|
1288
|
+
function createGlobalConsoleMirror(forwarder, target, onHostChanged, opts) {
|
|
1289
|
+
function inject(entry) {
|
|
1290
|
+
if (target.isDestroyed()) return false;
|
|
1291
|
+
if (!isFrontendSettled(target)) return false;
|
|
1292
|
+
let script;
|
|
1293
|
+
try {
|
|
1294
|
+
script = buildMirrorScript(entry);
|
|
1295
|
+
} catch {
|
|
1296
|
+
return false;
|
|
1297
|
+
}
|
|
1298
|
+
return injectViaCdp(opts.broker, target, script, "global-console-mirror");
|
|
1299
|
+
}
|
|
1300
|
+
return createOpenGatedRelay(
|
|
1301
|
+
onHostChanged,
|
|
1302
|
+
(sink, opts2) => forwarder.subscribe(sink, opts2),
|
|
1303
|
+
inject
|
|
1304
|
+
);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
// src/main/services/console-forward/global-diagnostics-mirror.ts
|
|
1308
|
+
var DIAGNOSTIC_CONSOLE_CALL = {
|
|
1309
|
+
error: "console.error",
|
|
1310
|
+
warn: "console.warn",
|
|
1311
|
+
info: "console.info"
|
|
1312
|
+
};
|
|
1313
|
+
function buildMirrorScript2(severity, message) {
|
|
1314
|
+
const call = DIAGNOSTIC_CONSOLE_CALL[severity];
|
|
1315
|
+
const argsJson = JSON.stringify([`[dimina-kit] ${message}`]);
|
|
1316
|
+
return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});${call}(...a)}catch(_){}})()`;
|
|
1317
|
+
}
|
|
1318
|
+
function createGlobalDiagnosticsMirror(diagnostics, target, onHostChanged, opts) {
|
|
1319
|
+
function inject(d) {
|
|
1320
|
+
if (target.isDestroyed()) return false;
|
|
1321
|
+
if (!isFrontendSettled(target)) return false;
|
|
1322
|
+
let script;
|
|
1323
|
+
try {
|
|
1324
|
+
script = buildMirrorScript2(d.severity, d.message);
|
|
1325
|
+
} catch {
|
|
1326
|
+
return false;
|
|
1327
|
+
}
|
|
1328
|
+
return injectViaCdp(opts.broker, target, script, "global-diagnostics-mirror");
|
|
1329
|
+
}
|
|
1330
|
+
return createOpenGatedRelay(
|
|
1331
|
+
onHostChanged,
|
|
1332
|
+
(sink, opts2) => diagnostics.subscribe(sink, opts2),
|
|
1333
|
+
inject
|
|
1334
|
+
);
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1077
1337
|
// src/main/app/lifecycle.ts
|
|
1078
1338
|
import { app as app4, globalShortcut as globalShortcut2 } from "electron";
|
|
1079
1339
|
var appIsQuitting = false;
|
|
1080
1340
|
function isAppQuitting() {
|
|
1081
1341
|
return appIsQuitting;
|
|
1082
1342
|
}
|
|
1083
|
-
function registerAppLifecycle() {
|
|
1343
|
+
function registerAppLifecycle(onBeforeQuit) {
|
|
1084
1344
|
app4.on("window-all-closed", () => {
|
|
1085
1345
|
globalShortcut2.unregisterAll();
|
|
1086
1346
|
app4.quit();
|
|
@@ -1088,6 +1348,11 @@ function registerAppLifecycle() {
|
|
|
1088
1348
|
app4.on("before-quit", () => {
|
|
1089
1349
|
appIsQuitting = true;
|
|
1090
1350
|
globalShortcut2.unregisterAll();
|
|
1351
|
+
try {
|
|
1352
|
+
onBeforeQuit?.();
|
|
1353
|
+
} catch (err2) {
|
|
1354
|
+
console.error("[lifecycle] onBeforeQuit handler threw:", err2);
|
|
1355
|
+
}
|
|
1091
1356
|
});
|
|
1092
1357
|
}
|
|
1093
1358
|
|
|
@@ -1569,7 +1834,7 @@ function createPlacementReconciler(ctx) {
|
|
|
1569
1834
|
}
|
|
1570
1835
|
|
|
1571
1836
|
// src/main/services/views/workbench-view.ts
|
|
1572
|
-
import { nativeTheme as nativeTheme3, WebContentsView as
|
|
1837
|
+
import { nativeTheme as nativeTheme3, WebContentsView as WebContentsView3 } from "electron";
|
|
1573
1838
|
|
|
1574
1839
|
// src/shared/view-ids.ts
|
|
1575
1840
|
var VIEW_ID = {
|
|
@@ -1626,7 +1891,7 @@ function createWorkbenchView(ctx, reconciler) {
|
|
|
1626
1891
|
}
|
|
1627
1892
|
async function attachWorkbench(url) {
|
|
1628
1893
|
if (workbenchView) return;
|
|
1629
|
-
const view = new
|
|
1894
|
+
const view = new WebContentsView3({
|
|
1630
1895
|
webPreferences: {
|
|
1631
1896
|
nodeIntegration: false,
|
|
1632
1897
|
contextIsolation: true,
|
|
@@ -1750,7 +2015,7 @@ function createWorkbenchView(ctx, reconciler) {
|
|
|
1750
2015
|
}
|
|
1751
2016
|
|
|
1752
2017
|
// src/main/services/views/native-simulator-devtools-host.ts
|
|
1753
|
-
import { WebContentsView as
|
|
2018
|
+
import { WebContentsView as WebContentsView4, webContents as electronWebContents } from "electron";
|
|
1754
2019
|
|
|
1755
2020
|
// src/shared/open-in-editor-resource-path.ts
|
|
1756
2021
|
function decodePathname(pathname) {
|
|
@@ -2211,40 +2476,146 @@ function buildCustomizeTabsScript(keptIds = DEVTOOLS_KEPT_VIEW_IDS) {
|
|
|
2211
2476
|
}catch(_){}})()`;
|
|
2212
2477
|
}
|
|
2213
2478
|
|
|
2214
|
-
// src/main/services/views/
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
return
|
|
2223
|
-
|
|
2479
|
+
// src/main/services/views/console-filter.ts
|
|
2480
|
+
var DEFAULT_INTERNAL_LOG_FILTER = "-/^\\[service\\]/";
|
|
2481
|
+
function buildConsoleFilterScript(negativeFilter = DEFAULT_INTERNAL_LOG_FILTER) {
|
|
2482
|
+
const keyJson = JSON.stringify("console.text-filter");
|
|
2483
|
+
const markKeyJson = JSON.stringify("console.text-filter.dimina-default");
|
|
2484
|
+
const valueJsonLiteral = JSON.stringify(JSON.stringify(negativeFilter));
|
|
2485
|
+
return `(function(){try{
|
|
2486
|
+
var IFH = globalThis.InspectorFrontendHost;
|
|
2487
|
+
if (!IFH || typeof IFH.getPreferences !== 'function' || typeof IFH.setPreference !== 'function') return;
|
|
2488
|
+
IFH.getPreferences(function(prefs){
|
|
2489
|
+
try {
|
|
2490
|
+
var KEY = ${keyJson};
|
|
2491
|
+
var MARK_KEY = ${markKeyJson};
|
|
2492
|
+
var VALUE = ${valueJsonLiteral};
|
|
2493
|
+
var existing = prefs ? prefs[KEY] : undefined;
|
|
2494
|
+
var mark = prefs ? prefs[MARK_KEY] : undefined;
|
|
2495
|
+
var isUnset = existing === undefined || existing === null || existing === '' || existing === '""';
|
|
2496
|
+
var isOurStaleDefault = !isUnset && mark !== undefined && mark !== null && existing === mark;
|
|
2497
|
+
if (isUnset || isOurStaleDefault) {
|
|
2498
|
+
IFH.setPreference(KEY, VALUE);
|
|
2499
|
+
IFH.setPreference(MARK_KEY, VALUE);
|
|
2500
|
+
}
|
|
2501
|
+
} catch(_){}
|
|
2502
|
+
});
|
|
2503
|
+
}catch(_){}})()`;
|
|
2224
2504
|
}
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
}
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2505
|
+
var LIVE_FILTER_POLL_MAX_ATTEMPTS = 100;
|
|
2506
|
+
var LIVE_FILTER_POLL_INTERVAL_MS = 100;
|
|
2507
|
+
function buildLiveConsoleFilterScript(negativeFilter = DEFAULT_INTERNAL_LOG_FILTER) {
|
|
2508
|
+
const filterJson = JSON.stringify(negativeFilter);
|
|
2509
|
+
const maxAttempts = JSON.stringify(LIVE_FILTER_POLL_MAX_ATTEMPTS);
|
|
2510
|
+
const intervalMs = JSON.stringify(LIVE_FILTER_POLL_INTERVAL_MS);
|
|
2511
|
+
return `(function(){
|
|
2512
|
+
var VALUE = ${filterJson};
|
|
2513
|
+
var attempts = 0;
|
|
2514
|
+
function bootstrapReady() {
|
|
2515
|
+
try {
|
|
2516
|
+
var eui = globalThis.EUI;
|
|
2517
|
+
if (!eui || !eui.ShortcutRegistry || !eui.ShortcutRegistry.ShortcutRegistry) return false;
|
|
2518
|
+
eui.ShortcutRegistry.ShortcutRegistry.instance();
|
|
2519
|
+
return true;
|
|
2520
|
+
} catch (_) { return false; }
|
|
2521
|
+
}
|
|
2522
|
+
function tryApply() {
|
|
2523
|
+
attempts++;
|
|
2524
|
+
var scheduleRetry = attempts < ${maxAttempts};
|
|
2525
|
+
// In-realm bootstrap probe FIRST (defense in depth on top of the
|
|
2526
|
+
// main-process whenFrontendBootstrapped gate): touching
|
|
2527
|
+
// Console.ConsoleView.instance() before the front-end's own
|
|
2528
|
+
// MainImpl bootstrap completes constructs IssuesManager early and
|
|
2529
|
+
// permanently kills that bootstrap (ensureFirst conflict) \u2014 the probe
|
|
2530
|
+
// throws BEFORE constructing anything, so a not-ready tick costs
|
|
2531
|
+
// nothing and never touches ConsoleView.
|
|
2532
|
+
if (!bootstrapReady()) {
|
|
2533
|
+
if (scheduleRetry) { setTimeout(tryApply, ${intervalMs}); return; }
|
|
2534
|
+
console.warn('[console-filter] gave up applying the live Console filter after ' + attempts + ' attempts \u2014 the front-end bootstrap never completed');
|
|
2535
|
+
return;
|
|
2536
|
+
}
|
|
2537
|
+
try {
|
|
2538
|
+
var ConsoleNS = globalThis.Console;
|
|
2539
|
+
var view = ConsoleNS && ConsoleNS.ConsoleView ? ConsoleNS.ConsoleView.instance() : null;
|
|
2540
|
+
var f = view ? view.filter : null;
|
|
2541
|
+
if (!f || !f.textFilterUI || typeof f.textFilterUI.setValue !== 'function' || typeof f.textFilterUI.value !== 'function') {
|
|
2542
|
+
if (scheduleRetry) { setTimeout(tryApply, ${intervalMs}); return; }
|
|
2543
|
+
console.warn('[console-filter] gave up applying the live Console filter after ' + attempts + ' attempts \u2014 Console.ConsoleView never became usable');
|
|
2544
|
+
return;
|
|
2545
|
+
}
|
|
2546
|
+
var current = f.textFilterUI.value();
|
|
2547
|
+
var isUnset = current === undefined || current === null || current === '';
|
|
2548
|
+
var isOurDefault = current === VALUE;
|
|
2549
|
+
if (isUnset || isOurDefault) {
|
|
2550
|
+
f.textFilterUI.setValue(VALUE);
|
|
2551
|
+
if (typeof f.updateCurrentFilter === 'function') f.updateCurrentFilter();
|
|
2552
|
+
if (typeof f.onFilterChanged === 'function') f.onFilterChanged();
|
|
2553
|
+
}
|
|
2554
|
+
// Either applied, or a real user customization was detected \u2014 both
|
|
2555
|
+
// are terminal: nothing left for a later retry to accomplish.
|
|
2556
|
+
} catch(_) {
|
|
2557
|
+
if (scheduleRetry) setTimeout(tryApply, ${intervalMs});
|
|
2558
|
+
}
|
|
2237
2559
|
}
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2560
|
+
tryApply();
|
|
2561
|
+
})()`;
|
|
2562
|
+
}
|
|
2563
|
+
|
|
2564
|
+
// src/main/services/views/frontend-bootstrap-gate.ts
|
|
2565
|
+
var FRONTEND_BOOTSTRAP_PROBE_SCRIPT = `(() => {
|
|
2566
|
+
try {
|
|
2567
|
+
const eui = globalThis.EUI
|
|
2568
|
+
if (!eui || !eui.ShortcutRegistry || !eui.ShortcutRegistry.ShortcutRegistry) return false
|
|
2569
|
+
eui.ShortcutRegistry.ShortcutRegistry.instance()
|
|
2570
|
+
return true
|
|
2571
|
+
} catch (_) {
|
|
2572
|
+
return false
|
|
2573
|
+
}
|
|
2574
|
+
})()`;
|
|
2575
|
+
var DEFAULT_TIMEOUT_MS = 45e3;
|
|
2576
|
+
var DEFAULT_INTERVAL_MS = 150;
|
|
2577
|
+
function whenFrontendBootstrapped(wc, opts) {
|
|
2578
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
2579
|
+
const intervalMs = opts?.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
2580
|
+
return new Promise((resolve) => {
|
|
2581
|
+
let timer = null;
|
|
2582
|
+
let settled = false;
|
|
2583
|
+
const finish = (ready) => {
|
|
2584
|
+
if (settled) return;
|
|
2585
|
+
settled = true;
|
|
2586
|
+
clearTimeout(deadline);
|
|
2587
|
+
if (timer) {
|
|
2588
|
+
clearTimeout(timer);
|
|
2589
|
+
timer = null;
|
|
2590
|
+
}
|
|
2591
|
+
resolve(ready);
|
|
2592
|
+
};
|
|
2593
|
+
const deadline = setTimeout(() => {
|
|
2594
|
+
console.warn(`[frontend-bootstrap-gate] front-end bootstrap probe never reported ready within ${timeoutMs}ms \u2014 bootstrap-gated injections stay skipped for this host`);
|
|
2595
|
+
finish(false);
|
|
2596
|
+
}, timeoutMs);
|
|
2597
|
+
deadline.unref?.();
|
|
2598
|
+
const attempt = () => {
|
|
2599
|
+
if (wc.isDestroyed()) {
|
|
2600
|
+
finish(false);
|
|
2601
|
+
return;
|
|
2602
|
+
}
|
|
2603
|
+
Promise.resolve().then(() => wc.executeJavaScript(FRONTEND_BOOTSTRAP_PROBE_SCRIPT)).then((ready) => ready === true, () => false).then((ready) => {
|
|
2604
|
+
if (settled) return;
|
|
2605
|
+
if (wc.isDestroyed()) {
|
|
2606
|
+
finish(false);
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
if (ready) {
|
|
2610
|
+
finish(true);
|
|
2611
|
+
return;
|
|
2612
|
+
}
|
|
2613
|
+
timer = setTimeout(attempt, intervalMs);
|
|
2614
|
+
timer.unref?.();
|
|
2615
|
+
});
|
|
2616
|
+
};
|
|
2617
|
+
attempt();
|
|
2618
|
+
});
|
|
2248
2619
|
}
|
|
2249
2620
|
|
|
2250
2621
|
// src/main/services/network-forward/index.ts
|
|
@@ -2393,15 +2764,174 @@ var PrefetchCache = class {
|
|
|
2393
2764
|
total -= e.size;
|
|
2394
2765
|
}
|
|
2395
2766
|
}
|
|
2396
|
-
};
|
|
2397
|
-
|
|
2398
|
-
// src/main/services/network-forward/frontend-dispatch.ts
|
|
2399
|
-
var PROBE_DEVTOOLS_API = `(window.DevToolsAPI && typeof window.DevToolsAPI.dispatchMessage === 'function')`;
|
|
2400
|
-
var MAX_SINGLE_DISPATCH_CHARS = 1e6;
|
|
2401
|
-
var CHUNK_CHARS = 256 * 1024;
|
|
2402
|
-
function buildChunkedDispatchScript(chunks, totalSize) {
|
|
2403
|
-
const arr = JSON.stringify(chunks);
|
|
2404
|
-
return `(()=>{try{if(!(window.DevToolsAPI&&typeof window.DevToolsAPI.dispatchMessageChunk==='function'))return false;const cs=JSON.parse(${JSON.stringify(arr)});for(let i=0;i<cs.length;i++){try{if(i===0){window.DevToolsAPI.dispatchMessageChunk(cs[i], ${totalSize})}else{window.DevToolsAPI.dispatchMessageChunk(cs[i])}}catch(_){}}return true;}catch(_){return false}})()`;
|
|
2767
|
+
};
|
|
2768
|
+
|
|
2769
|
+
// src/main/services/network-forward/frontend-dispatch.ts
|
|
2770
|
+
var PROBE_DEVTOOLS_API = `(window.DevToolsAPI && typeof window.DevToolsAPI.dispatchMessage === 'function')`;
|
|
2771
|
+
var MAX_SINGLE_DISPATCH_CHARS = 1e6;
|
|
2772
|
+
var CHUNK_CHARS = 256 * 1024;
|
|
2773
|
+
function buildChunkedDispatchScript(chunks, totalSize) {
|
|
2774
|
+
const arr = JSON.stringify(chunks);
|
|
2775
|
+
return `(()=>{try{if(!(window.DevToolsAPI&&typeof window.DevToolsAPI.dispatchMessageChunk==='function'))return false;const cs=JSON.parse(${JSON.stringify(arr)});for(let i=0;i<cs.length;i++){try{if(i===0){window.DevToolsAPI.dispatchMessageChunk(cs[i], ${totalSize})}else{window.DevToolsAPI.dispatchMessageChunk(cs[i])}}catch(_){}}return true;}catch(_){return false}})()`;
|
|
2776
|
+
}
|
|
2777
|
+
function buildSingleDispatchScript(message) {
|
|
2778
|
+
return `(()=>{try{if(!${PROBE_DEVTOOLS_API})return false;window.DevToolsAPI.dispatchMessage(JSON.parse(${JSON.stringify(message)}));return true;}catch(_){return false}})()`;
|
|
2779
|
+
}
|
|
2780
|
+
function createFrontendReplyChannel(hostWc, isDisposed) {
|
|
2781
|
+
function dispatchToFrontend(message) {
|
|
2782
|
+
if (isDisposed() || hostWc.isDestroyed()) return;
|
|
2783
|
+
if (!isFrontendSettled(hostWc)) return;
|
|
2784
|
+
let json;
|
|
2785
|
+
try {
|
|
2786
|
+
json = JSON.stringify(message);
|
|
2787
|
+
} catch {
|
|
2788
|
+
return;
|
|
2789
|
+
}
|
|
2790
|
+
if (json.length > MAX_SINGLE_DISPATCH_CHARS) {
|
|
2791
|
+
const chunks = [];
|
|
2792
|
+
for (let i = 0; i < json.length; i += CHUNK_CHARS) chunks.push(json.slice(i, i + CHUNK_CHARS));
|
|
2793
|
+
let script2;
|
|
2794
|
+
try {
|
|
2795
|
+
script2 = buildChunkedDispatchScript(chunks, json.length);
|
|
2796
|
+
} catch {
|
|
2797
|
+
return;
|
|
2798
|
+
}
|
|
2799
|
+
hostWc.executeJavaScript(script2, true).catch(() => {
|
|
2800
|
+
});
|
|
2801
|
+
return;
|
|
2802
|
+
}
|
|
2803
|
+
let script;
|
|
2804
|
+
try {
|
|
2805
|
+
script = buildSingleDispatchScript(json);
|
|
2806
|
+
} catch {
|
|
2807
|
+
return;
|
|
2808
|
+
}
|
|
2809
|
+
hostWc.executeJavaScript(script, true).catch(() => {
|
|
2810
|
+
});
|
|
2811
|
+
}
|
|
2812
|
+
function replyResult(cmd, result) {
|
|
2813
|
+
const msg = { id: cmd.id, result };
|
|
2814
|
+
if (cmd.sessionId) msg.sessionId = cmd.sessionId;
|
|
2815
|
+
dispatchToFrontend(msg);
|
|
2816
|
+
}
|
|
2817
|
+
function replyError(cmd, message) {
|
|
2818
|
+
const msg = { id: cmd.id, error: { code: -32e3, message } };
|
|
2819
|
+
if (cmd.sessionId) msg.sessionId = cmd.sessionId;
|
|
2820
|
+
dispatchToFrontend(msg);
|
|
2821
|
+
}
|
|
2822
|
+
return { dispatchToFrontend, replyResult, replyError };
|
|
2823
|
+
}
|
|
2824
|
+
function drainOutboundBatch(batch, handle) {
|
|
2825
|
+
if (!Array.isArray(batch)) return;
|
|
2826
|
+
for (const raw of batch) {
|
|
2827
|
+
if (!raw || typeof raw !== "object") continue;
|
|
2828
|
+
const cmd = raw;
|
|
2829
|
+
if (typeof cmd.method !== "string") continue;
|
|
2830
|
+
handle(cmd);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
function answerNetworkBodyCommand(cmd, provider, reply) {
|
|
2834
|
+
const requestId = cmd.params?.requestId;
|
|
2835
|
+
if (!provider || typeof requestId !== "string") {
|
|
2836
|
+
reply.replyError(cmd, "No resource with given identifier found");
|
|
2837
|
+
return;
|
|
2838
|
+
}
|
|
2839
|
+
const lookup = cmd.method === "Network.getRequestPostData" ? provider.getRequestPostData(requestId) : provider.getResponseBody(requestId);
|
|
2840
|
+
lookup.then(
|
|
2841
|
+
(result) => reply.replyResult(cmd, result),
|
|
2842
|
+
(err2) => reply.replyError(cmd, err2 instanceof Error ? err2.message : String(err2))
|
|
2843
|
+
);
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2846
|
+
// src/main/services/network-forward/user-facing.ts
|
|
2847
|
+
var USER_FACING_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:", "ws:", "wss:"]);
|
|
2848
|
+
function isUserFacingRequest(url, internalOrigins) {
|
|
2849
|
+
let parsed;
|
|
2850
|
+
try {
|
|
2851
|
+
parsed = new URL(url);
|
|
2852
|
+
} catch {
|
|
2853
|
+
return true;
|
|
2854
|
+
}
|
|
2855
|
+
if (!USER_FACING_SCHEMES.has(parsed.protocol)) return false;
|
|
2856
|
+
for (const baseUrl of internalOrigins ?? []) {
|
|
2857
|
+
if (!baseUrl) continue;
|
|
2858
|
+
try {
|
|
2859
|
+
if (parsed.origin === new URL(baseUrl).origin) return false;
|
|
2860
|
+
} catch {
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
return true;
|
|
2864
|
+
}
|
|
2865
|
+
|
|
2866
|
+
// src/main/services/network-forward/global-body-gate.ts
|
|
2867
|
+
var NETWORK_BODY_METHODS = ["Network.getResponseBody", "Network.getRequestPostData"];
|
|
2868
|
+
var DRAIN_INTERVAL_MS = 150;
|
|
2869
|
+
function buildNetworkOnlyHookScript() {
|
|
2870
|
+
const netMethods = JSON.stringify(NETWORK_BODY_METHODS);
|
|
2871
|
+
const vprefix = JSON.stringify(VIRTUAL_REQUEST_ID_PREFIX);
|
|
2872
|
+
return `(function(){try{
|
|
2873
|
+
if (globalThis.__diminaGlobalNetworkHookInstalled) return 'already';
|
|
2874
|
+
var OUT = (globalThis.__diminaGlobalNetworkOutbound = globalThis.__diminaGlobalNetworkOutbound || []);
|
|
2875
|
+
var NET_METHODS = ${netMethods};
|
|
2876
|
+
var VPREFIX = ${vprefix};
|
|
2877
|
+
function isNetworkBody(m){
|
|
2878
|
+
if (!m || !m.method) return false;
|
|
2879
|
+
if (NET_METHODS.indexOf(m.method) < 0) return false;
|
|
2880
|
+
return !!(m.params && typeof m.params.requestId === 'string' && m.params.requestId.indexOf(VPREFIX) === 0);
|
|
2881
|
+
}
|
|
2882
|
+
var IFH = globalThis.InspectorFrontendHost;
|
|
2883
|
+
if (IFH && typeof IFH.sendMessageToBackend === 'function' && !IFH.__diminaGlobalNetworkWrapped){
|
|
2884
|
+
var origSend = IFH.sendMessageToBackend.bind(IFH);
|
|
2885
|
+
IFH.sendMessageToBackend = function(message){
|
|
2886
|
+
try {
|
|
2887
|
+
var m = (typeof message === 'string') ? JSON.parse(message) : message;
|
|
2888
|
+
if (isNetworkBody(m)){
|
|
2889
|
+
OUT.push({ id: (m && typeof m.id === 'number') ? m.id : null,
|
|
2890
|
+
method: m.method, params: m.params || {},
|
|
2891
|
+
sessionId: (m && m.sessionId) ? m.sessionId : null });
|
|
2892
|
+
return;
|
|
2893
|
+
}
|
|
2894
|
+
} catch(_){ /* fall through to original on any parse hiccup */ }
|
|
2895
|
+
return origSend(message);
|
|
2896
|
+
};
|
|
2897
|
+
IFH.__diminaGlobalNetworkWrapped = true;
|
|
2898
|
+
globalThis.__diminaGlobalNetworkHookInstalled = true;
|
|
2899
|
+
return 'installed';
|
|
2900
|
+
}
|
|
2901
|
+
return 'partial';
|
|
2902
|
+
}catch(e){ return 'error:' + (e && e.message); }})()`;
|
|
2903
|
+
}
|
|
2904
|
+
function buildReconcileScript() {
|
|
2905
|
+
return `(function(){var status; try { status = ${buildNetworkOnlyHookScript()}; } catch(e){ status = 'error:'+(e&&e.message); }var batch = []; try { if (globalThis.__diminaGlobalNetworkOutbound) batch = globalThis.__diminaGlobalNetworkOutbound.splice(0); } catch(_){}return { status: status, batch: batch };})()`;
|
|
2906
|
+
}
|
|
2907
|
+
function installGlobalNetworkBodyGate(hostWc, bodies) {
|
|
2908
|
+
let disposed = false;
|
|
2909
|
+
let reconcileTimer = null;
|
|
2910
|
+
const reply = createFrontendReplyChannel(hostWc, () => disposed);
|
|
2911
|
+
function handleOutbound(batch) {
|
|
2912
|
+
drainOutboundBatch(batch, (cmd) => answerNetworkBodyCommand(cmd, bodies, reply));
|
|
2913
|
+
}
|
|
2914
|
+
reconcileTimer = setInterval(() => {
|
|
2915
|
+
if (disposed || hostWc.isDestroyed()) {
|
|
2916
|
+
stop();
|
|
2917
|
+
return;
|
|
2918
|
+
}
|
|
2919
|
+
if (!isFrontendSettled(hostWc)) return;
|
|
2920
|
+
hostWc.executeJavaScript(buildReconcileScript()).then((res) => {
|
|
2921
|
+
if (disposed) return;
|
|
2922
|
+
const r = res ?? {};
|
|
2923
|
+
handleOutbound(r.batch);
|
|
2924
|
+
}).catch(() => {
|
|
2925
|
+
});
|
|
2926
|
+
}, DRAIN_INTERVAL_MS);
|
|
2927
|
+
function stop() {
|
|
2928
|
+
disposed = true;
|
|
2929
|
+
if (reconcileTimer) {
|
|
2930
|
+
clearInterval(reconcileTimer);
|
|
2931
|
+
reconcileTimer = null;
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
return stop;
|
|
2405
2935
|
}
|
|
2406
2936
|
|
|
2407
2937
|
// src/main/services/network-forward/index.ts
|
|
@@ -2561,6 +3091,122 @@ function createNetworkForwarder(bridge) {
|
|
|
2561
3091
|
const broker = bridge.broker ?? createCdpSessionBroker({ connections: bridge.connections });
|
|
2562
3092
|
let devtoolsWc = null;
|
|
2563
3093
|
let devtoolsHostDisposable = null;
|
|
3094
|
+
let globalDevtoolsWc = null;
|
|
3095
|
+
let globalDevtoolsHostDisposable = null;
|
|
3096
|
+
let globalBodyGateStop = null;
|
|
3097
|
+
const MAX_GLOBAL_PENDING_QUEUE = 2e3;
|
|
3098
|
+
let globalPendingQueue = [];
|
|
3099
|
+
let globalPendingOverflowWarned = false;
|
|
3100
|
+
let globalFlushTimer = null;
|
|
3101
|
+
const GLOBAL_FLUSH_POLL_MAX_MS = 6e4;
|
|
3102
|
+
function clearGlobalPending() {
|
|
3103
|
+
globalPendingQueue = [];
|
|
3104
|
+
globalPendingOverflowWarned = false;
|
|
3105
|
+
if (globalFlushTimer) {
|
|
3106
|
+
clearTimeout(globalFlushTimer);
|
|
3107
|
+
globalFlushTimer = null;
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
function scheduleGlobalFlush(startedAt = Date.now()) {
|
|
3111
|
+
if (globalFlushTimer) return;
|
|
3112
|
+
if (Date.now() - startedAt >= GLOBAL_FLUSH_POLL_MAX_MS) return;
|
|
3113
|
+
globalFlushTimer = setTimeout(() => {
|
|
3114
|
+
globalFlushTimer = null;
|
|
3115
|
+
if (globalPendingQueue.length === 0) return;
|
|
3116
|
+
if (!globalDevtoolsWc || globalDevtoolsWc.isDestroyed()) {
|
|
3117
|
+
clearGlobalPending();
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
if (!isFrontendSettled(globalDevtoolsWc)) {
|
|
3121
|
+
scheduleGlobalFlush(startedAt);
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
flushGlobalPending();
|
|
3125
|
+
}, READY_RETRY_MS);
|
|
3126
|
+
globalFlushTimer.unref?.();
|
|
3127
|
+
}
|
|
3128
|
+
function flushGlobalPending() {
|
|
3129
|
+
if (globalPendingQueue.length === 0) return;
|
|
3130
|
+
const target = globalDevtoolsWc;
|
|
3131
|
+
if (!target || target.isDestroyed()) {
|
|
3132
|
+
clearGlobalPending();
|
|
3133
|
+
return;
|
|
3134
|
+
}
|
|
3135
|
+
while (globalPendingQueue.length > 0) {
|
|
3136
|
+
const { batch, chunked, remaining } = packDispatchBatch(globalPendingQueue, MAX_SINGLE_DISPATCH_CHARS, MAX_BATCH_CHARS);
|
|
3137
|
+
globalPendingQueue = remaining;
|
|
3138
|
+
for (const msg of chunked) dispatchChunked(target, msg);
|
|
3139
|
+
if (batch.length > 0) {
|
|
3140
|
+
target.executeJavaScript(buildDispatchScript(batch), true).catch(() => {
|
|
3141
|
+
});
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
globalPendingOverflowWarned = false;
|
|
3145
|
+
}
|
|
3146
|
+
function enqueueGlobalPending(json) {
|
|
3147
|
+
if (globalPendingQueue.length >= MAX_GLOBAL_PENDING_QUEUE) {
|
|
3148
|
+
globalPendingQueue.shift();
|
|
3149
|
+
if (!globalPendingOverflowWarned) {
|
|
3150
|
+
globalPendingOverflowWarned = true;
|
|
3151
|
+
console.warn(`[network-forward] global mirror queue overflow (cap ${MAX_GLOBAL_PENDING_QUEUE}): dropping oldest events while the debug window front-end is still loading`);
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
globalPendingQueue.push(json);
|
|
3155
|
+
scheduleGlobalFlush();
|
|
3156
|
+
}
|
|
3157
|
+
function applyGlobalDevtoolsHost(host) {
|
|
3158
|
+
globalDevtoolsHostDisposable?.dispose();
|
|
3159
|
+
globalDevtoolsHostDisposable = null;
|
|
3160
|
+
globalBodyGateStop?.();
|
|
3161
|
+
globalBodyGateStop = null;
|
|
3162
|
+
clearGlobalPending();
|
|
3163
|
+
globalDevtoolsWc = host && !host.isDestroyed() ? host : null;
|
|
3164
|
+
if (!globalDevtoolsWc) return;
|
|
3165
|
+
const target = globalDevtoolsWc;
|
|
3166
|
+
const onHostDestroyed = () => {
|
|
3167
|
+
if (globalDevtoolsWc === target) globalDevtoolsWc = null;
|
|
3168
|
+
globalBodyGateStop?.();
|
|
3169
|
+
globalBodyGateStop = null;
|
|
3170
|
+
clearGlobalPending();
|
|
3171
|
+
};
|
|
3172
|
+
const reg = bridge.connections;
|
|
3173
|
+
if (reg && typeof target.once === "function") {
|
|
3174
|
+
const owned = reg.acquire(target).own(onHostDestroyed);
|
|
3175
|
+
globalDevtoolsHostDisposable = toDisposable3(() => owned.dispose());
|
|
3176
|
+
} else {
|
|
3177
|
+
if (typeof target.once === "function") target.once("destroyed", onHostDestroyed);
|
|
3178
|
+
globalDevtoolsHostDisposable = toDisposable3(() => {
|
|
3179
|
+
try {
|
|
3180
|
+
target.removeListener?.("destroyed", onHostDestroyed);
|
|
3181
|
+
} catch {
|
|
3182
|
+
}
|
|
3183
|
+
});
|
|
3184
|
+
}
|
|
3185
|
+
globalBodyGateStop = installGlobalNetworkBodyGate(target, {
|
|
3186
|
+
getResponseBody: (requestId) => bodyCache.lookup(requestId),
|
|
3187
|
+
getRequestPostData: (requestId) => postDataCache.lookup(requestId)
|
|
3188
|
+
});
|
|
3189
|
+
}
|
|
3190
|
+
function dispatchToGlobal(method, params) {
|
|
3191
|
+
if (!globalDevtoolsWc || globalDevtoolsWc.isDestroyed()) return;
|
|
3192
|
+
let json;
|
|
3193
|
+
try {
|
|
3194
|
+
json = JSON.stringify({ method, params });
|
|
3195
|
+
} catch {
|
|
3196
|
+
return;
|
|
3197
|
+
}
|
|
3198
|
+
if (!isFrontendSettled(globalDevtoolsWc)) {
|
|
3199
|
+
enqueueGlobalPending(json);
|
|
3200
|
+
return;
|
|
3201
|
+
}
|
|
3202
|
+
flushGlobalPending();
|
|
3203
|
+
if (json.length > MAX_SINGLE_DISPATCH_CHARS) {
|
|
3204
|
+
dispatchChunked(globalDevtoolsWc, json);
|
|
3205
|
+
return;
|
|
3206
|
+
}
|
|
3207
|
+
globalDevtoolsWc.executeJavaScript(buildDispatchScript([json]), true).catch(() => {
|
|
3208
|
+
});
|
|
3209
|
+
}
|
|
2564
3210
|
let sink = "idle";
|
|
2565
3211
|
let probeConsoleBuffer = [];
|
|
2566
3212
|
let readyTimeoutTimer = null;
|
|
@@ -2770,10 +3416,12 @@ function createNetworkForwarder(bridge) {
|
|
|
2770
3416
|
function wireNetworkCapture(wc, source, attach, epoch) {
|
|
2771
3417
|
const ns = new RequestIdNamespace(epoch);
|
|
2772
3418
|
const pending = /* @__PURE__ */ new Map();
|
|
3419
|
+
const userFacingByRawId = /* @__PURE__ */ new Map();
|
|
2773
3420
|
const postDataWanted = /* @__PURE__ */ new Set();
|
|
2774
3421
|
const prefetchBodies = (rawId, encodedDataLength) => {
|
|
2775
|
-
|
|
2776
|
-
|
|
3422
|
+
const userSinkUsable = sink !== "degraded" && !(sink === "idle" && !resolveDevtoolsWc());
|
|
3423
|
+
const globalUsable = globalDevtoolsWc !== null && !globalDevtoolsWc.isDestroyed();
|
|
3424
|
+
if (!userSinkUsable && !globalUsable) return;
|
|
2777
3425
|
const virtualId = ns.resolve(rawId);
|
|
2778
3426
|
const knownOversized = typeof encodedDataLength === "number" && encodedDataLength > DEFAULT_PER_ENTRY_MAX_CHARS;
|
|
2779
3427
|
if (!knownOversized) {
|
|
@@ -2807,20 +3455,25 @@ function createNetworkForwarder(bridge) {
|
|
|
2807
3455
|
const req = pending.get(p.requestId);
|
|
2808
3456
|
if (req) req.status = p.response?.status ?? 0;
|
|
2809
3457
|
}
|
|
3458
|
+
function retirePending(rawId) {
|
|
3459
|
+
userFacingByRawId.delete(rawId);
|
|
3460
|
+
const req = pending.get(rawId);
|
|
3461
|
+
if (!req) return void 0;
|
|
3462
|
+
pending.delete(rawId);
|
|
3463
|
+
return req;
|
|
3464
|
+
}
|
|
2810
3465
|
function onLoadingFinished(params) {
|
|
2811
3466
|
const p = params;
|
|
2812
3467
|
if (typeof p?.requestId === "string") prefetchBodies(p.requestId, p.encodedDataLength);
|
|
2813
|
-
const req =
|
|
3468
|
+
const req = retirePending(p?.requestId);
|
|
2814
3469
|
if (!req) return;
|
|
2815
|
-
pending.delete(p.requestId);
|
|
2816
3470
|
maybeFallback({ source, url: req.url, method: req.method, status: req.status });
|
|
2817
3471
|
}
|
|
2818
3472
|
function onLoadingFailed(params) {
|
|
2819
3473
|
const p = params;
|
|
2820
3474
|
postDataWanted.delete(p?.requestId);
|
|
2821
|
-
const req =
|
|
3475
|
+
const req = retirePending(p?.requestId);
|
|
2822
3476
|
if (!req) return;
|
|
2823
|
-
pending.delete(p.requestId);
|
|
2824
3477
|
maybeFallback({
|
|
2825
3478
|
source,
|
|
2826
3479
|
url: req.url,
|
|
@@ -2835,10 +3488,29 @@ function createNetworkForwarder(bridge) {
|
|
|
2835
3488
|
"Network.loadingFinished": onLoadingFinished,
|
|
2836
3489
|
"Network.loadingFailed": onLoadingFailed
|
|
2837
3490
|
};
|
|
3491
|
+
function resolveUserFacing(method, params, rawId) {
|
|
3492
|
+
if (method === "Network.requestWillBeSent") {
|
|
3493
|
+
const url = params?.request?.url;
|
|
3494
|
+
const verdict = typeof url === "string" ? isUserFacingRequest(url, [bridge.getResourceServerBaseUrl?.(), bridge.getSimulatorServerBaseUrl?.()]) : true;
|
|
3495
|
+
if (rawId) {
|
|
3496
|
+
if (userFacingByRawId.size >= MAX_PENDING) userFacingByRawId.clear();
|
|
3497
|
+
userFacingByRawId.set(rawId, verdict);
|
|
3498
|
+
}
|
|
3499
|
+
return verdict;
|
|
3500
|
+
}
|
|
3501
|
+
if (rawId && userFacingByRawId.has(rawId)) return userFacingByRawId.get(rawId);
|
|
3502
|
+
if (method === "Network.requestWillBeSentExtraInfo") return false;
|
|
3503
|
+
return true;
|
|
3504
|
+
}
|
|
2838
3505
|
const onMessage = (_event, method, params) => {
|
|
2839
3506
|
if (FORWARDED_METHODS.has(method)) {
|
|
2840
3507
|
const rewritten = rewriteRequestId(method, params, ns);
|
|
2841
|
-
|
|
3508
|
+
dispatchToGlobal(rewritten.method, rewritten.params);
|
|
3509
|
+
const rawId = params?.requestId;
|
|
3510
|
+
const userFacing = resolveUserFacing(method, params, typeof rawId === "string" ? rawId : void 0);
|
|
3511
|
+
if (userFacing) {
|
|
3512
|
+
enqueueNative(rewritten.method, rewritten.params);
|
|
3513
|
+
}
|
|
2842
3514
|
} else if (REWRITE_REQUEST_ID_METHODS.has(method)) {
|
|
2843
3515
|
rewriteRequestId(method, params, ns);
|
|
2844
3516
|
}
|
|
@@ -2999,6 +3671,14 @@ function createNetworkForwarder(bridge) {
|
|
|
2999
3671
|
readyRetryTimer = null;
|
|
3000
3672
|
}
|
|
3001
3673
|
});
|
|
3674
|
+
registry.add(() => {
|
|
3675
|
+
globalDevtoolsHostDisposable?.dispose();
|
|
3676
|
+
globalDevtoolsHostDisposable = null;
|
|
3677
|
+
globalBodyGateStop?.();
|
|
3678
|
+
globalBodyGateStop = null;
|
|
3679
|
+
globalDevtoolsWc = null;
|
|
3680
|
+
clearGlobalPending();
|
|
3681
|
+
});
|
|
3002
3682
|
registry.add(() => {
|
|
3003
3683
|
bodyCache.clear();
|
|
3004
3684
|
postDataCache.clear();
|
|
@@ -3015,6 +3695,7 @@ function createNetworkForwarder(bridge) {
|
|
|
3015
3695
|
detachSimulator,
|
|
3016
3696
|
attachRenderGuest,
|
|
3017
3697
|
setDevtoolsHost: (wc) => applyDevtoolsHost(wc),
|
|
3698
|
+
setGlobalDevtoolsHost: (wc) => applyGlobalDevtoolsHost(wc),
|
|
3018
3699
|
// report() has no observing debugger, so there's no live CDP event to push
|
|
3019
3700
|
// natively — surface it via the console fallback line.
|
|
3020
3701
|
report: (record) => forwardToConsole(record),
|
|
@@ -3043,13 +3724,13 @@ function routeByDomain(method) {
|
|
|
3043
3724
|
function isRenderEventMethod(method) {
|
|
3044
3725
|
return routeByDomain(method) === "render";
|
|
3045
3726
|
}
|
|
3046
|
-
var
|
|
3727
|
+
var NETWORK_BODY_METHODS2 = [
|
|
3047
3728
|
"Network.getResponseBody",
|
|
3048
3729
|
"Network.getRequestPostData"
|
|
3049
3730
|
];
|
|
3050
3731
|
function buildElementsHookScript() {
|
|
3051
3732
|
const prefixes = JSON.stringify(RENDER_DOMAIN_PREFIXES);
|
|
3052
|
-
const netMethods = JSON.stringify(
|
|
3733
|
+
const netMethods = JSON.stringify(NETWORK_BODY_METHODS2);
|
|
3053
3734
|
const vprefix = JSON.stringify(VIRTUAL_REQUEST_ID_PREFIX);
|
|
3054
3735
|
return `(function(){try{
|
|
3055
3736
|
if (globalThis.__diminaElementsHookInstalled) return 'already';
|
|
@@ -3097,17 +3778,14 @@ function buildElementsHookScript() {
|
|
|
3097
3778
|
return 'partial';
|
|
3098
3779
|
}catch(e){ return 'error:' + (e && e.message); }})()`;
|
|
3099
3780
|
}
|
|
3100
|
-
function
|
|
3781
|
+
function buildReconcileScript2() {
|
|
3101
3782
|
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 };})()`;
|
|
3102
3783
|
}
|
|
3103
|
-
function buildDispatchScript2(message) {
|
|
3104
|
-
return `(()=>{try{if(!${PROBE_DEVTOOLS_API})return false;window.DevToolsAPI.dispatchMessage(JSON.parse(${JSON.stringify(message)}));return true;}catch(_){return false}})()`;
|
|
3105
|
-
}
|
|
3106
3784
|
function buildDocumentUpdatedScript() {
|
|
3107
3785
|
const msg = JSON.stringify({ method: "DOM.documentUpdated", params: {} });
|
|
3108
|
-
return
|
|
3786
|
+
return buildSingleDispatchScript(msg);
|
|
3109
3787
|
}
|
|
3110
|
-
var
|
|
3788
|
+
var DRAIN_INTERVAL_MS2 = 150;
|
|
3111
3789
|
function installElementsForward(deps) {
|
|
3112
3790
|
const { devtoolsWc, bridge } = deps;
|
|
3113
3791
|
const ownsBroker = !deps.broker;
|
|
@@ -3143,39 +3821,7 @@ function installElementsForward(deps) {
|
|
|
3143
3821
|
}
|
|
3144
3822
|
}
|
|
3145
3823
|
};
|
|
3146
|
-
|
|
3147
|
-
if (disposed || devtoolsWc.isDestroyed()) return;
|
|
3148
|
-
if (!isFrontendSettled(devtoolsWc)) return;
|
|
3149
|
-
let json;
|
|
3150
|
-
try {
|
|
3151
|
-
json = JSON.stringify(message);
|
|
3152
|
-
} catch {
|
|
3153
|
-
return;
|
|
3154
|
-
}
|
|
3155
|
-
if (json.length > MAX_SINGLE_DISPATCH_CHARS) {
|
|
3156
|
-
const chunks = [];
|
|
3157
|
-
for (let i = 0; i < json.length; i += CHUNK_CHARS) {
|
|
3158
|
-
chunks.push(json.slice(i, i + CHUNK_CHARS));
|
|
3159
|
-
}
|
|
3160
|
-
let script2;
|
|
3161
|
-
try {
|
|
3162
|
-
script2 = buildChunkedDispatchScript(chunks, json.length);
|
|
3163
|
-
} catch {
|
|
3164
|
-
return;
|
|
3165
|
-
}
|
|
3166
|
-
devtoolsWc.executeJavaScript(script2, true).catch(() => {
|
|
3167
|
-
});
|
|
3168
|
-
return;
|
|
3169
|
-
}
|
|
3170
|
-
let script;
|
|
3171
|
-
try {
|
|
3172
|
-
script = buildDispatchScript2(json);
|
|
3173
|
-
} catch {
|
|
3174
|
-
return;
|
|
3175
|
-
}
|
|
3176
|
-
devtoolsWc.executeJavaScript(script, true).catch(() => {
|
|
3177
|
-
});
|
|
3178
|
-
}
|
|
3824
|
+
const { dispatchToFrontend, replyResult, replyError } = createFrontendReplyChannel(devtoolsWc, () => disposed);
|
|
3179
3825
|
function pushDocumentUpdated() {
|
|
3180
3826
|
if (disposed || devtoolsWc.isDestroyed()) return;
|
|
3181
3827
|
if (!isFrontendSettled(devtoolsWc)) return;
|
|
@@ -3188,16 +3834,6 @@ function installElementsForward(deps) {
|
|
|
3188
3834
|
devtoolsWc.executeJavaScript(script, true).catch(() => {
|
|
3189
3835
|
});
|
|
3190
3836
|
}
|
|
3191
|
-
function replyResult(cmd, result) {
|
|
3192
|
-
const msg = { id: cmd.id, result };
|
|
3193
|
-
if (cmd.sessionId) msg.sessionId = cmd.sessionId;
|
|
3194
|
-
dispatchToFrontend(msg);
|
|
3195
|
-
}
|
|
3196
|
-
function replyError(cmd, message) {
|
|
3197
|
-
const msg = { id: cmd.id, error: { code: -32e3, message } };
|
|
3198
|
-
if (cmd.sessionId) msg.sessionId = cmd.sessionId;
|
|
3199
|
-
dispatchToFrontend(msg);
|
|
3200
|
-
}
|
|
3201
3837
|
function activeRenderWc() {
|
|
3202
3838
|
try {
|
|
3203
3839
|
const wc = bridge.getActiveRenderWc(deps.appId);
|
|
@@ -3270,34 +3906,16 @@ function installElementsForward(deps) {
|
|
|
3270
3906
|
});
|
|
3271
3907
|
}
|
|
3272
3908
|
function answerNetworkCommand(cmd) {
|
|
3273
|
-
|
|
3274
|
-
const requestId = cmd.params?.requestId;
|
|
3275
|
-
if (!provider || typeof requestId !== "string") {
|
|
3276
|
-
replyError(cmd, "No resource with given identifier found");
|
|
3277
|
-
return;
|
|
3278
|
-
}
|
|
3279
|
-
const lookup = cmd.method === "Network.getRequestPostData" ? provider.getRequestPostData(requestId) : provider.getResponseBody(requestId);
|
|
3280
|
-
lookup.then(
|
|
3281
|
-
(result) => {
|
|
3282
|
-
if (!disposed) replyResult(cmd, result);
|
|
3283
|
-
},
|
|
3284
|
-
(err2) => {
|
|
3285
|
-
if (!disposed) replyError(cmd, err2 instanceof Error ? err2.message : String(err2));
|
|
3286
|
-
}
|
|
3287
|
-
);
|
|
3909
|
+
answerNetworkBodyCommand(cmd, deps.network, { replyResult, replyError });
|
|
3288
3910
|
}
|
|
3289
3911
|
function handleOutbound(batch) {
|
|
3290
|
-
|
|
3291
|
-
for (const raw of batch) {
|
|
3292
|
-
if (!raw || typeof raw !== "object") continue;
|
|
3293
|
-
const cmd = raw;
|
|
3294
|
-
if (typeof cmd.method !== "string") continue;
|
|
3912
|
+
drainOutboundBatch(batch, (cmd) => {
|
|
3295
3913
|
if (cmd.route === "network") {
|
|
3296
3914
|
answerNetworkCommand(cmd);
|
|
3297
|
-
|
|
3915
|
+
return;
|
|
3298
3916
|
}
|
|
3299
3917
|
routeCommand(cmd);
|
|
3300
|
-
}
|
|
3918
|
+
});
|
|
3301
3919
|
}
|
|
3302
3920
|
const onRenderEvent = (event) => {
|
|
3303
3921
|
if (disposed) return;
|
|
@@ -3320,7 +3938,7 @@ function installElementsForward(deps) {
|
|
|
3320
3938
|
return;
|
|
3321
3939
|
}
|
|
3322
3940
|
if (!isFrontendSettled(devtoolsWc)) return;
|
|
3323
|
-
devtoolsWc.executeJavaScript(
|
|
3941
|
+
devtoolsWc.executeJavaScript(buildReconcileScript2()).then((res) => {
|
|
3324
3942
|
if (disposed) return;
|
|
3325
3943
|
const r = res ?? {};
|
|
3326
3944
|
if (r.status === "installed") {
|
|
@@ -3331,7 +3949,7 @@ function installElementsForward(deps) {
|
|
|
3331
3949
|
handleOutbound(r.batch);
|
|
3332
3950
|
}).catch(() => {
|
|
3333
3951
|
});
|
|
3334
|
-
},
|
|
3952
|
+
}, DRAIN_INTERVAL_MS2);
|
|
3335
3953
|
};
|
|
3336
3954
|
devtoolsWc.on("dom-ready", onReady);
|
|
3337
3955
|
onReady();
|
|
@@ -3551,6 +4169,7 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3551
4169
|
let nativeDevtoolsSourceWc = null;
|
|
3552
4170
|
let devtoolsHostUsed = false;
|
|
3553
4171
|
let unsubscribeNativeRenderEvents = null;
|
|
4172
|
+
let unsubscribeNativeServiceHostReady = null;
|
|
3554
4173
|
let stopElementsForward = null;
|
|
3555
4174
|
let stopServiceConsole = null;
|
|
3556
4175
|
let nativeDevtoolsRetryTimer = null;
|
|
@@ -3589,6 +4208,13 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3589
4208
|
}
|
|
3590
4209
|
unsubscribeNativeRenderEvents = null;
|
|
3591
4210
|
}
|
|
4211
|
+
if (unsubscribeNativeServiceHostReady) {
|
|
4212
|
+
try {
|
|
4213
|
+
unsubscribeNativeServiceHostReady();
|
|
4214
|
+
} catch {
|
|
4215
|
+
}
|
|
4216
|
+
unsubscribeNativeServiceHostReady = null;
|
|
4217
|
+
}
|
|
3592
4218
|
closeNativeDevtoolsSource();
|
|
3593
4219
|
}
|
|
3594
4220
|
function injectOpenResourceHandler(serviceWc, devtoolsWc) {
|
|
@@ -3619,6 +4245,25 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3619
4245
|
} catch {
|
|
3620
4246
|
}
|
|
3621
4247
|
}
|
|
4248
|
+
function applyConsoleFilter(devtoolsWc) {
|
|
4249
|
+
try {
|
|
4250
|
+
if (devtoolsWc.isDestroyed()) return;
|
|
4251
|
+
const inject = () => {
|
|
4252
|
+
void whenFrontendBootstrapped(devtoolsWc).then((ready) => {
|
|
4253
|
+
if (!ready || devtoolsWc.isDestroyed()) return;
|
|
4254
|
+
try {
|
|
4255
|
+
void devtoolsWc.executeJavaScript(buildConsoleFilterScript()).catch(() => {
|
|
4256
|
+
});
|
|
4257
|
+
void devtoolsWc.executeJavaScript(buildLiveConsoleFilterScript()).catch(() => {
|
|
4258
|
+
});
|
|
4259
|
+
} catch {
|
|
4260
|
+
}
|
|
4261
|
+
});
|
|
4262
|
+
};
|
|
4263
|
+
injectWhenReady(devtoolsWc, "console-filter", inject);
|
|
4264
|
+
} catch {
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
3622
4267
|
function wireOpenInEditor(serviceWc, devtoolsWc) {
|
|
3623
4268
|
if (!devtoolsWc.isDestroyed()) {
|
|
3624
4269
|
injectWhenReady(devtoolsWc, "open-in-editor", () => injectOpenResourceHandler(serviceWc, devtoolsWc));
|
|
@@ -3664,6 +4309,7 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3664
4309
|
devtoolsHostUsed = true;
|
|
3665
4310
|
wireOpenInEditor(next, simulatorView.webContents);
|
|
3666
4311
|
customizeDevtoolsTabs(simulatorView.webContents);
|
|
4312
|
+
applyConsoleFilter(simulatorView.webContents);
|
|
3667
4313
|
try {
|
|
3668
4314
|
stopServiceConsole?.();
|
|
3669
4315
|
} catch {
|
|
@@ -3689,8 +4335,10 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3689
4335
|
if (!wc || wc.isDestroyed()) return false;
|
|
3690
4336
|
return pointNativeDevtoolsAtServiceWc(wc);
|
|
3691
4337
|
}
|
|
3692
|
-
|
|
3693
|
-
|
|
4338
|
+
const NATIVE_DEVTOOLS_FALLBACK_POLL_MAX_MS = 6e4;
|
|
4339
|
+
const NATIVE_DEVTOOLS_FALLBACK_POLL_INTERVAL_MS = 50;
|
|
4340
|
+
function scheduleNativeDevtoolsFollow(appId, startedAt = Date.now()) {
|
|
4341
|
+
if (Date.now() - startedAt >= NATIVE_DEVTOOLS_FALLBACK_POLL_MAX_MS) return;
|
|
3694
4342
|
if (!ctx.bridge?.isNativeHost()) return;
|
|
3695
4343
|
const token = nativeDevtoolsRetryToken;
|
|
3696
4344
|
if (nativeDevtoolsRetryTimer) clearTimeout(nativeDevtoolsRetryTimer);
|
|
@@ -3698,14 +4346,27 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3698
4346
|
nativeDevtoolsRetryTimer = null;
|
|
3699
4347
|
if (token !== nativeDevtoolsRetryToken) return;
|
|
3700
4348
|
if (pointNativeDevtoolsAtActiveServiceHost(appId)) return;
|
|
3701
|
-
scheduleNativeDevtoolsFollow(appId,
|
|
3702
|
-
},
|
|
4349
|
+
scheduleNativeDevtoolsFollow(appId, startedAt);
|
|
4350
|
+
}, NATIVE_DEVTOOLS_FALLBACK_POLL_INTERVAL_MS);
|
|
3703
4351
|
}
|
|
3704
4352
|
function followNativeDevtoolsServiceHost(appId) {
|
|
3705
4353
|
clearNativeDevtoolsRetry();
|
|
3706
4354
|
if (pointNativeDevtoolsAtActiveServiceHost(appId)) return;
|
|
3707
4355
|
scheduleNativeDevtoolsFollow(appId);
|
|
3708
4356
|
}
|
|
4357
|
+
function onNativeServiceHostReady(event) {
|
|
4358
|
+
if (!ctx.bridge?.isNativeHost()) return;
|
|
4359
|
+
if (!simulatorView || simulatorView.webContents.isDestroyed()) return;
|
|
4360
|
+
const wc = electronWebContents.fromId(event.serviceWcId);
|
|
4361
|
+
if (!wc || wc.isDestroyed()) return;
|
|
4362
|
+
const current = ctx.bridge.getServiceWc(event.appId);
|
|
4363
|
+
if (current && current.id !== event.serviceWcId) return;
|
|
4364
|
+
if (pointNativeDevtoolsAtServiceWc(wc)) {
|
|
4365
|
+
clearNativeDevtoolsRetry();
|
|
4366
|
+
return;
|
|
4367
|
+
}
|
|
4368
|
+
scheduleNativeDevtoolsFollow(event.appId);
|
|
4369
|
+
}
|
|
3709
4370
|
function onNativeRenderEvent(event) {
|
|
3710
4371
|
if (event.kind !== "activePage" && event.kind !== "domReady") return;
|
|
3711
4372
|
followNativeDevtoolsServiceHost(event.appId);
|
|
@@ -3721,7 +4382,7 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3721
4382
|
}
|
|
3722
4383
|
simulatorView = null;
|
|
3723
4384
|
}
|
|
3724
|
-
simulatorView = new
|
|
4385
|
+
simulatorView = new WebContentsView4();
|
|
3725
4386
|
const devtoolsWc = simulatorView.webContents;
|
|
3726
4387
|
raiseExecuteJavaScriptListenerCeiling(devtoolsWc);
|
|
3727
4388
|
ctx.networkForward?.setDevtoolsHost(devtoolsWc);
|
|
@@ -3752,27 +4413,21 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3752
4413
|
});
|
|
3753
4414
|
}
|
|
3754
4415
|
injectWhenReady(devtoolsWc, "console-default", () => {
|
|
3755
|
-
devtoolsWc.
|
|
3756
|
-
(
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
const timer = setInterval(() => {
|
|
3760
|
-
tries++
|
|
4416
|
+
void whenFrontendBootstrapped(devtoolsWc).then((ready) => {
|
|
4417
|
+
if (!ready || devtoolsWc.isDestroyed()) return;
|
|
4418
|
+
devtoolsWc.executeJavaScript(`
|
|
4419
|
+
(function() {
|
|
3761
4420
|
try {
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
4421
|
+
var EUI = globalThis.EUI
|
|
4422
|
+
var vm = EUI && EUI.ViewManager && EUI.ViewManager.ViewManager
|
|
4423
|
+
&& typeof EUI.ViewManager.ViewManager.instance === 'function'
|
|
4424
|
+
? EUI.ViewManager.ViewManager.instance()
|
|
3765
4425
|
: null
|
|
3766
|
-
if (vm && typeof vm.showView === 'function')
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
} catch {}
|
|
3772
|
-
if (tries > 80) clearInterval(timer)
|
|
3773
|
-
}, 50)
|
|
3774
|
-
})()
|
|
3775
|
-
`).catch(() => {
|
|
4426
|
+
if (vm && typeof vm.showView === 'function') void vm.showView('console')
|
|
4427
|
+
} catch (_) {}
|
|
4428
|
+
})()
|
|
4429
|
+
`).catch(() => {
|
|
4430
|
+
});
|
|
3776
4431
|
});
|
|
3777
4432
|
});
|
|
3778
4433
|
reconciler.reconcileNow();
|
|
@@ -3783,6 +4438,7 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3783
4438
|
rebuildDevtoolsHostView();
|
|
3784
4439
|
if (ctx.bridge?.isNativeHost()) {
|
|
3785
4440
|
unsubscribeNativeRenderEvents = ctx.bridge.onRenderEvent(onNativeRenderEvent);
|
|
4441
|
+
unsubscribeNativeServiceHostReady = ctx.bridge.onServiceHostReady(onNativeServiceHostReady);
|
|
3786
4442
|
followNativeDevtoolsServiceHost();
|
|
3787
4443
|
}
|
|
3788
4444
|
}
|
|
@@ -3824,7 +4480,7 @@ function createDevtoolsHost(ctx, reconciler, deps) {
|
|
|
3824
4480
|
}
|
|
3825
4481
|
|
|
3826
4482
|
// src/main/services/views/host-toolbar-view.ts
|
|
3827
|
-
import { WebContentsView as
|
|
4483
|
+
import { WebContentsView as WebContentsView5 } from "electron";
|
|
3828
4484
|
|
|
3829
4485
|
// src/main/services/views/host-toolbar-session-runtime.ts
|
|
3830
4486
|
import { session } from "electron";
|
|
@@ -4020,7 +4676,7 @@ function createHostToolbarView(ctx, reconciler, deps) {
|
|
|
4020
4676
|
if (hostToolbarPreloadOverride !== null) {
|
|
4021
4677
|
webPreferences.preload = hostToolbarPreloadOverride;
|
|
4022
4678
|
}
|
|
4023
|
-
const view = new
|
|
4679
|
+
const view = new WebContentsView5({ webPreferences });
|
|
4024
4680
|
hostToolbarView = view;
|
|
4025
4681
|
hostToolbarPort.attach(view.webContents);
|
|
4026
4682
|
try {
|
|
@@ -4068,8 +4724,8 @@ function createHostToolbarView(ctx, reconciler, deps) {
|
|
|
4068
4724
|
hide() {
|
|
4069
4725
|
hideHostToolbar();
|
|
4070
4726
|
},
|
|
4071
|
-
setPreloadPath(
|
|
4072
|
-
hostToolbarPreloadOverride =
|
|
4727
|
+
setPreloadPath(path26) {
|
|
4728
|
+
hostToolbarPreloadOverride = path26;
|
|
4073
4729
|
},
|
|
4074
4730
|
setHeightMode(mode) {
|
|
4075
4731
|
if (mode !== "auto" && !(Number.isFinite(mode.fixed) && mode.fixed >= 0)) {
|
|
@@ -4122,7 +4778,7 @@ function createHostToolbarView(ctx, reconciler, deps) {
|
|
|
4122
4778
|
}
|
|
4123
4779
|
|
|
4124
4780
|
// src/main/services/views/overlay-panels-view.ts
|
|
4125
|
-
import { WebContentsView as
|
|
4781
|
+
import { WebContentsView as WebContentsView6 } from "electron";
|
|
4126
4782
|
import path8 from "path";
|
|
4127
4783
|
|
|
4128
4784
|
// src/main/services/layout/index.ts
|
|
@@ -4190,7 +4846,7 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
4190
4846
|
}
|
|
4191
4847
|
async function showSettings() {
|
|
4192
4848
|
if (!settingsView) {
|
|
4193
|
-
settingsView = new
|
|
4849
|
+
settingsView = new WebContentsView6({
|
|
4194
4850
|
webPreferences: {
|
|
4195
4851
|
nodeIntegration: false,
|
|
4196
4852
|
contextIsolation: true,
|
|
@@ -4212,7 +4868,7 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
4212
4868
|
}
|
|
4213
4869
|
function showPopover(data) {
|
|
4214
4870
|
hidePopover();
|
|
4215
|
-
const popover = new
|
|
4871
|
+
const popover = new WebContentsView6({
|
|
4216
4872
|
webPreferences: {
|
|
4217
4873
|
nodeIntegration: false,
|
|
4218
4874
|
contextIsolation: true,
|
|
@@ -4279,7 +4935,7 @@ function createOverlayPanelsView(ctx, reconciler, deps) {
|
|
|
4279
4935
|
}
|
|
4280
4936
|
|
|
4281
4937
|
// src/main/services/views/native-simulator-view.ts
|
|
4282
|
-
import { ipcMain as ipcMain2, nativeTheme as nativeTheme4, shell as shell2, WebContentsView as
|
|
4938
|
+
import { ipcMain as ipcMain2, nativeTheme as nativeTheme4, shell as shell2, WebContentsView as WebContentsView7, webContents as webContents2 } from "electron";
|
|
4283
4939
|
|
|
4284
4940
|
// src/main/services/simulator/custom-apis.ts
|
|
4285
4941
|
async function handleCustomApiBridgeRequest(apis, req) {
|
|
@@ -4608,7 +5264,7 @@ function createNativeSimulatorView(ctx, reconciler, deps) {
|
|
|
4608
5264
|
const route = parseRoute(simulatorUrl);
|
|
4609
5265
|
const partition = miniappPartition(route?.appId, ctx.workspace?.getProjectPath());
|
|
4610
5266
|
configureMiniappSession(partition);
|
|
4611
|
-
const view = new
|
|
5267
|
+
const view = new WebContentsView7({
|
|
4612
5268
|
webPreferences: {
|
|
4613
5269
|
nodeIntegration: false,
|
|
4614
5270
|
contextIsolation: false,
|
|
@@ -4847,10 +5503,10 @@ function createWindowService(mainWindow) {
|
|
|
4847
5503
|
}
|
|
4848
5504
|
|
|
4849
5505
|
// src/main/windows/settings-window/create.ts
|
|
4850
|
-
import { BrowserWindow as
|
|
5506
|
+
import { BrowserWindow as BrowserWindow4 } from "electron";
|
|
4851
5507
|
import path9 from "path";
|
|
4852
5508
|
async function createSettingsWindow(parent, rendererDir2) {
|
|
4853
|
-
const win = new
|
|
5509
|
+
const win = new BrowserWindow4({
|
|
4854
5510
|
width: 420,
|
|
4855
5511
|
height: 560,
|
|
4856
5512
|
minWidth: 380,
|
|
@@ -5535,7 +6191,11 @@ function setupCompileWorkerStandby(ctx, deps = {}) {
|
|
|
5535
6191
|
ctx.diagnostics?.report({
|
|
5536
6192
|
severity: EVENT_SEVERITY[ev.type] ?? "info",
|
|
5537
6193
|
code: "compile-standby",
|
|
5538
|
-
message: detail
|
|
6194
|
+
message: detail,
|
|
6195
|
+
// Devtools-tooling-only state, unrelated to the inspected mini-program
|
|
6196
|
+
// — must never reach the right-panel (user-facing) Console panel; see
|
|
6197
|
+
// console-forward/index.ts's audience gate and global-diagnostics-mirror.ts.
|
|
6198
|
+
audience: "internal"
|
|
5539
6199
|
});
|
|
5540
6200
|
} catch {
|
|
5541
6201
|
}
|
|
@@ -5867,7 +6527,7 @@ async function materializeTemplate(target, template, name) {
|
|
|
5867
6527
|
`Template source missing on disk: ${template.source.path}`
|
|
5868
6528
|
);
|
|
5869
6529
|
}
|
|
5870
|
-
fs7.
|
|
6530
|
+
await fs7.promises.cp(template.source.path, target, {
|
|
5871
6531
|
recursive: true,
|
|
5872
6532
|
force: true
|
|
5873
6533
|
});
|
|
@@ -6134,6 +6794,13 @@ var settingsModule = {
|
|
|
6134
6794
|
setup: (ctx) => registerSettingsIpc(ctx)
|
|
6135
6795
|
};
|
|
6136
6796
|
|
|
6797
|
+
// src/main/ipc/internal-devtools.ts
|
|
6798
|
+
function registerInternalDevtoolsIpc(ctx) {
|
|
6799
|
+
return new IpcRegistry(ctx.senderPolicy).handle(InternalDevtoolsChannel.Open, () => {
|
|
6800
|
+
ctx.internalDevtoolsWindow?.open();
|
|
6801
|
+
});
|
|
6802
|
+
}
|
|
6803
|
+
|
|
6137
6804
|
// src/main/ipc/simulator-module.ts
|
|
6138
6805
|
import { DisposableRegistry as DisposableRegistry5 } from "@dimina-kit/electron-deck/main";
|
|
6139
6806
|
|
|
@@ -6292,7 +6959,7 @@ function setCorsHeaders(res) {
|
|
|
6292
6959
|
}
|
|
6293
6960
|
|
|
6294
6961
|
// src/main/windows/service-host-window/create.ts
|
|
6295
|
-
import { app as app10, BrowserWindow as
|
|
6962
|
+
import { app as app10, BrowserWindow as BrowserWindow5 } from "electron";
|
|
6296
6963
|
import path16 from "node:path";
|
|
6297
6964
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
6298
6965
|
var SERVICE_HOST_PARTITION = SHARED_MINIAPP_PARTITION;
|
|
@@ -6301,7 +6968,7 @@ var serviceHostHtmlPath = path16.join(devtoolsPackageRoot, "dist/service-host/se
|
|
|
6301
6968
|
function constructServiceHostWindow(opts = {}) {
|
|
6302
6969
|
const partition = opts.partition ?? SERVICE_HOST_PARTITION;
|
|
6303
6970
|
configureMiniappSession(partition);
|
|
6304
|
-
return new
|
|
6971
|
+
return new BrowserWindow5({
|
|
6305
6972
|
width: 980,
|
|
6306
6973
|
height: 720,
|
|
6307
6974
|
show: false,
|
|
@@ -6382,7 +7049,7 @@ function createServiceHostWindow(opts) {
|
|
|
6382
7049
|
}
|
|
6383
7050
|
|
|
6384
7051
|
// src/main/services/service-host-pool/pool.ts
|
|
6385
|
-
import { BrowserWindow as
|
|
7052
|
+
import { BrowserWindow as BrowserWindow6 } from "electron";
|
|
6386
7053
|
var BLANK_URL = "about:blank";
|
|
6387
7054
|
var HARD_MAX_POOL_SIZE = 4;
|
|
6388
7055
|
var RESET_STORAGES = [
|
|
@@ -6579,7 +7246,7 @@ var ServiceHostPool = class {
|
|
|
6579
7246
|
}
|
|
6580
7247
|
}
|
|
6581
7248
|
createWindow(spec) {
|
|
6582
|
-
return new
|
|
7249
|
+
return new BrowserWindow6({
|
|
6583
7250
|
show: false,
|
|
6584
7251
|
width: spec.size?.width,
|
|
6585
7252
|
height: spec.size?.height,
|
|
@@ -6687,20 +7354,32 @@ var ServiceHostPool = class {
|
|
|
6687
7354
|
|
|
6688
7355
|
// src/main/services/console-forward/index.ts
|
|
6689
7356
|
import { DisposableRegistry as DisposableRegistry3, toDisposable as toDisposable4 } from "@dimina-kit/electron-deck/main";
|
|
6690
|
-
|
|
7357
|
+
|
|
7358
|
+
// src/main/services/console-forward/internal-log.ts
|
|
7359
|
+
var SERVICE_PREFIX = "[service]";
|
|
7360
|
+
var RENDER_PREFIX = "[system]";
|
|
7361
|
+
function isInternalLogMessage(entry) {
|
|
7362
|
+
const first = entry.args?.[0];
|
|
7363
|
+
if (typeof first !== "string") return false;
|
|
7364
|
+
if (first === RENDER_PREFIX) return true;
|
|
7365
|
+
return first === SERVICE_PREFIX || first.startsWith(`${SERVICE_PREFIX} `);
|
|
7366
|
+
}
|
|
7367
|
+
|
|
7368
|
+
// src/main/services/console-forward/index.ts
|
|
7369
|
+
var FORWARDABLE_LEVELS2 = /* @__PURE__ */ new Set(["log", "warn", "error", "info", "debug"]);
|
|
6691
7370
|
function buildForwardScript2(level, args) {
|
|
6692
|
-
const method =
|
|
7371
|
+
const method = FORWARDABLE_LEVELS2.has(level) ? level : "log";
|
|
6693
7372
|
const argsJson = JSON.stringify(args ?? []);
|
|
6694
7373
|
return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});console[${JSON.stringify(method)}]('[\u89C6\u56FE]',...a)}catch(_){}})()
|
|
6695
7374
|
//# sourceURL=${RENDER_FORWARD_SOURCE_URL}`;
|
|
6696
7375
|
}
|
|
6697
|
-
var
|
|
7376
|
+
var DIAGNOSTIC_CONSOLE_CALL2 = {
|
|
6698
7377
|
error: "console.error",
|
|
6699
7378
|
warn: "console.warn",
|
|
6700
7379
|
info: "console.info"
|
|
6701
7380
|
};
|
|
6702
7381
|
function buildDiagnosticScript(severity, message) {
|
|
6703
|
-
const call =
|
|
7382
|
+
const call = DIAGNOSTIC_CONSOLE_CALL2[severity];
|
|
6704
7383
|
const argsJson = JSON.stringify([`[dimina-kit] ${message}`]);
|
|
6705
7384
|
return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});${call}(...a)}catch(_){}})()
|
|
6706
7385
|
//# sourceURL=${RENDER_FORWARD_SOURCE_URL}`;
|
|
@@ -6708,6 +7387,8 @@ function buildDiagnosticScript(severity, message) {
|
|
|
6708
7387
|
function createConsoleForwarder(bridge, diagnostics) {
|
|
6709
7388
|
const sinks = /* @__PURE__ */ new Set();
|
|
6710
7389
|
const registry = new DisposableRegistry3();
|
|
7390
|
+
const CONSOLE_BUFFER_CAP = 200;
|
|
7391
|
+
const buffer = [];
|
|
6711
7392
|
const pendingBySession = /* @__PURE__ */ new Map();
|
|
6712
7393
|
const pendingGlobal = [];
|
|
6713
7394
|
const readySessions = /* @__PURE__ */ new Set();
|
|
@@ -6716,6 +7397,7 @@ function createConsoleForwarder(bridge, diagnostics) {
|
|
|
6716
7397
|
});
|
|
6717
7398
|
}
|
|
6718
7399
|
function handleDiagnostic(d) {
|
|
7400
|
+
if (d.audience === "internal") return;
|
|
6719
7401
|
if (d.appSessionId) {
|
|
6720
7402
|
const wc2 = readySessions.has(d.appSessionId) && bridge.getServiceWcForBridge ? bridge.getServiceWcForBridge(d.appSessionId) : null;
|
|
6721
7403
|
if (wc2 && !wc2.isDestroyed()) {
|
|
@@ -6738,6 +7420,7 @@ function createConsoleForwarder(bridge, diagnostics) {
|
|
|
6738
7420
|
registry.add(diagnostics.subscribe(handleDiagnostic, { replay: true }));
|
|
6739
7421
|
}
|
|
6740
7422
|
function forwardRenderToServiceHost(entry) {
|
|
7423
|
+
if (isInternalLogMessage(entry)) return;
|
|
6741
7424
|
let wc = null;
|
|
6742
7425
|
if (entry.bridgeId && bridge.getServiceWcForBridge) {
|
|
6743
7426
|
wc = bridge.getServiceWcForBridge(entry.bridgeId);
|
|
@@ -6759,6 +7442,8 @@ function createConsoleForwarder(bridge, diagnostics) {
|
|
|
6759
7442
|
// (render only — see loop-safety invariant in the module header).
|
|
6760
7443
|
emit(raw) {
|
|
6761
7444
|
const entry = raw ?? {};
|
|
7445
|
+
buffer.push(entry);
|
|
7446
|
+
if (buffer.length > CONSOLE_BUFFER_CAP) buffer.shift();
|
|
6762
7447
|
for (const sink of sinks) {
|
|
6763
7448
|
try {
|
|
6764
7449
|
sink(entry);
|
|
@@ -6767,7 +7452,15 @@ function createConsoleForwarder(bridge, diagnostics) {
|
|
|
6767
7452
|
}
|
|
6768
7453
|
if (entry.source === "render") forwardRenderToServiceHost(entry);
|
|
6769
7454
|
},
|
|
6770
|
-
subscribe(sink) {
|
|
7455
|
+
subscribe(sink, opts) {
|
|
7456
|
+
if (opts?.replay) {
|
|
7457
|
+
for (const entry of buffer) {
|
|
7458
|
+
try {
|
|
7459
|
+
sink(entry);
|
|
7460
|
+
} catch {
|
|
7461
|
+
}
|
|
7462
|
+
}
|
|
7463
|
+
}
|
|
6771
7464
|
sinks.add(sink);
|
|
6772
7465
|
return registry.add(toDisposable4(() => {
|
|
6773
7466
|
sinks.delete(sink);
|
|
@@ -6789,6 +7482,7 @@ function createConsoleForwarder(bridge, diagnostics) {
|
|
|
6789
7482
|
},
|
|
6790
7483
|
dispose() {
|
|
6791
7484
|
sinks.clear();
|
|
7485
|
+
buffer.length = 0;
|
|
6792
7486
|
pendingBySession.clear();
|
|
6793
7487
|
pendingGlobal.length = 0;
|
|
6794
7488
|
readySessions.clear();
|
|
@@ -7462,6 +8156,9 @@ function installBridgeRouter(ctx) {
|
|
|
7462
8156
|
pool: null,
|
|
7463
8157
|
emitRenderEvent: () => {
|
|
7464
8158
|
},
|
|
8159
|
+
emitServiceHostReady: () => {
|
|
8160
|
+
},
|
|
8161
|
+
lastServiceHostReady: null,
|
|
7465
8162
|
connections: ctx.connections,
|
|
7466
8163
|
debugTap: createDebugTap({ enabled: resolveDebugTapEnabled() }),
|
|
7467
8164
|
appLifecycle: createAppLifecycleController(),
|
|
@@ -7509,6 +8206,18 @@ function installBridgeRouter(ctx) {
|
|
|
7509
8206
|
}
|
|
7510
8207
|
};
|
|
7511
8208
|
state.emitRenderEvent = emitRenderEvent;
|
|
8209
|
+
const serviceHostReadyListeners = /* @__PURE__ */ new Set();
|
|
8210
|
+
const emitServiceHostReady = (event) => {
|
|
8211
|
+
state.lastServiceHostReady = event;
|
|
8212
|
+
for (const listener of serviceHostReadyListeners) {
|
|
8213
|
+
try {
|
|
8214
|
+
listener(event);
|
|
8215
|
+
} catch (error) {
|
|
8216
|
+
console.warn("[bridge-router] service-host-ready listener threw:", error);
|
|
8217
|
+
}
|
|
8218
|
+
}
|
|
8219
|
+
};
|
|
8220
|
+
state.emitServiceHostReady = emitServiceHostReady;
|
|
7512
8221
|
const bridgeHandle = {
|
|
7513
8222
|
isNativeHost: () => true,
|
|
7514
8223
|
resolveRenderWc: (bridgeId) => {
|
|
@@ -7534,6 +8243,10 @@ function installBridgeRouter(ctx) {
|
|
|
7534
8243
|
const ap = resolveCurrentApp(state, ctx, appId);
|
|
7535
8244
|
return ap?.pageStack ?? null;
|
|
7536
8245
|
},
|
|
8246
|
+
getResourceBaseUrl: (appId) => {
|
|
8247
|
+
const ap = resolveCurrentApp(state, ctx, appId);
|
|
8248
|
+
return ap?.resourceBaseUrl ?? null;
|
|
8249
|
+
},
|
|
7537
8250
|
getActiveRenderWc: (appId) => {
|
|
7538
8251
|
const ap = resolveCurrentApp(state, ctx, appId);
|
|
7539
8252
|
if (!ap) return null;
|
|
@@ -7544,6 +8257,23 @@ function installBridgeRouter(ctx) {
|
|
|
7544
8257
|
renderEventListeners.add(listener);
|
|
7545
8258
|
return () => renderEventListeners.delete(listener);
|
|
7546
8259
|
},
|
|
8260
|
+
onServiceHostReady: (listener) => {
|
|
8261
|
+
serviceHostReadyListeners.add(listener);
|
|
8262
|
+
const candidate = state.lastServiceHostReady;
|
|
8263
|
+
if (candidate) {
|
|
8264
|
+
queueMicrotask(() => {
|
|
8265
|
+
if (!serviceHostReadyListeners.has(listener)) return;
|
|
8266
|
+
const ap = state.appSessions.get(candidate.appSessionId);
|
|
8267
|
+
if (!ap || ap.serviceWc.isDestroyed() || ap.serviceWc.id !== candidate.serviceWcId) return;
|
|
8268
|
+
try {
|
|
8269
|
+
listener(candidate);
|
|
8270
|
+
} catch (error) {
|
|
8271
|
+
console.warn("[bridge-router] service-host-ready catch-up listener threw:", error);
|
|
8272
|
+
}
|
|
8273
|
+
});
|
|
8274
|
+
}
|
|
8275
|
+
return () => serviceHostReadyListeners.delete(listener);
|
|
8276
|
+
},
|
|
7547
8277
|
getDevice: () => currentDevice,
|
|
7548
8278
|
setDevice: (device) => {
|
|
7549
8279
|
currentDevice = device;
|
|
@@ -8073,6 +8803,7 @@ function handleNavCallback(state, sender, payload) {
|
|
|
8073
8803
|
async function bootServiceHost(state, ap, ctx) {
|
|
8074
8804
|
if (state.appSessions.get(ap.appSessionId) !== ap) return;
|
|
8075
8805
|
ctx.consoleForwarder?.notifyServiceHostReady?.(ap.appSessionId);
|
|
8806
|
+
state.emitServiceHostReady({ appId: ap.appId, appSessionId: ap.appSessionId, serviceWcId: ap.serviceWc.id });
|
|
8076
8807
|
ap.logicInjected = await injectLogicBundle(ap);
|
|
8077
8808
|
if (!ap.logicInjected) {
|
|
8078
8809
|
const reason = reportLogicLoadFailure(ap, ctx);
|
|
@@ -10250,7 +10981,6 @@ function startMcpServer(resolvedCdpPort, mcpPort) {
|
|
|
10250
10981
|
});
|
|
10251
10982
|
connectTarget("workbench").catch(() => {
|
|
10252
10983
|
});
|
|
10253
|
-
const server = buildServer();
|
|
10254
10984
|
const transports = /* @__PURE__ */ new Map();
|
|
10255
10985
|
const httpServer = createServer(async (req, res) => {
|
|
10256
10986
|
const url = new URL(req.url ?? "/", `http://localhost`);
|
|
@@ -10258,7 +10988,14 @@ function startMcpServer(resolvedCdpPort, mcpPort) {
|
|
|
10258
10988
|
const transport = new SSEServerTransport("/message", res);
|
|
10259
10989
|
transports.set(transport.sessionId, transport);
|
|
10260
10990
|
res.on("close", () => transports.delete(transport.sessionId));
|
|
10261
|
-
|
|
10991
|
+
try {
|
|
10992
|
+
await buildServer().connect(transport);
|
|
10993
|
+
} catch (err2) {
|
|
10994
|
+
transports.delete(transport.sessionId);
|
|
10995
|
+
if (!res.headersSent) res.writeHead(500).end("MCP connect failed");
|
|
10996
|
+
else res.end();
|
|
10997
|
+
console.error("[MCP] SSE connect failed:", err2);
|
|
10998
|
+
}
|
|
10262
10999
|
} else if (req.method === "POST" && url.pathname === "/message") {
|
|
10263
11000
|
const sessionId = url.searchParams.get("sessionId") ?? "";
|
|
10264
11001
|
const transport = transports.get(sessionId);
|
|
@@ -10607,13 +11344,13 @@ function createRenderInspector(options = {}) {
|
|
|
10607
11344
|
import { toDisposable as toDisposable6 } from "@dimina-kit/electron-deck/main";
|
|
10608
11345
|
|
|
10609
11346
|
// src/main/services/simulator-temp-files/store.ts
|
|
10610
|
-
function registerTempFile(store,
|
|
11347
|
+
function registerTempFile(store, path26, mime, bytes) {
|
|
10611
11348
|
const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(new Uint8Array(bytes));
|
|
10612
|
-
store.delete(
|
|
10613
|
-
store.set(
|
|
11349
|
+
store.delete(path26);
|
|
11350
|
+
store.set(path26, { bytes: buf, mime });
|
|
10614
11351
|
}
|
|
10615
|
-
function revokeTempFile(store,
|
|
10616
|
-
store.delete(
|
|
11352
|
+
function revokeTempFile(store, path26) {
|
|
11353
|
+
store.delete(path26);
|
|
10617
11354
|
}
|
|
10618
11355
|
function revokeAllTempFiles(store) {
|
|
10619
11356
|
store.clear();
|
|
@@ -11041,10 +11778,10 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
11041
11778
|
const store = /* @__PURE__ */ new Map();
|
|
11042
11779
|
const pendingWaiters = /* @__PURE__ */ new Map();
|
|
11043
11780
|
let disposed = false;
|
|
11044
|
-
function drainWaiters(
|
|
11045
|
-
const list = pendingWaiters.get(
|
|
11781
|
+
function drainWaiters(path26) {
|
|
11782
|
+
const list = pendingWaiters.get(path26);
|
|
11046
11783
|
if (!list) return;
|
|
11047
|
-
pendingWaiters.delete(
|
|
11784
|
+
pendingWaiters.delete(path26);
|
|
11048
11785
|
for (const fn of list) fn();
|
|
11049
11786
|
}
|
|
11050
11787
|
function drainAllWaiters() {
|
|
@@ -11057,15 +11794,15 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
11057
11794
|
const registry = new IpcRegistry(simulatorOnlyPolicy);
|
|
11058
11795
|
registry.on("simulator:temp-file:write", (_event, payload) => {
|
|
11059
11796
|
if (disposed) return;
|
|
11060
|
-
const { path:
|
|
11061
|
-
registerTempFile(store,
|
|
11797
|
+
const { path: path26, mime, bytes } = payload;
|
|
11798
|
+
registerTempFile(store, path26, mime, bytes);
|
|
11062
11799
|
enforceStoreCap(store);
|
|
11063
|
-
drainWaiters(
|
|
11800
|
+
drainWaiters(path26);
|
|
11064
11801
|
});
|
|
11065
11802
|
registry.on("simulator:temp-file:revoke", (_event, payload) => {
|
|
11066
11803
|
if (disposed) return;
|
|
11067
|
-
const { path:
|
|
11068
|
-
revokeTempFile(store,
|
|
11804
|
+
const { path: path26 } = payload;
|
|
11805
|
+
revokeTempFile(store, path26);
|
|
11069
11806
|
});
|
|
11070
11807
|
registry.on("simulator:temp-file:revoke-all", () => {
|
|
11071
11808
|
if (disposed) return;
|
|
@@ -11619,8 +12356,9 @@ var UpdateManager = class {
|
|
|
11619
12356
|
const currentVersion = this.getCurrentVersion();
|
|
11620
12357
|
const info = await this.checker.checkForUpdates(currentVersion);
|
|
11621
12358
|
if (info) {
|
|
12359
|
+
const isSameUpdate = this.latestUpdate?.version === info.version && this.latestUpdate?.downloadUrl === info.downloadUrl;
|
|
11622
12360
|
this.latestUpdate = info;
|
|
11623
|
-
this.downloadedPath = null;
|
|
12361
|
+
if (!isSameUpdate) this.downloadedPath = null;
|
|
11624
12362
|
return { hasUpdate: true, info };
|
|
11625
12363
|
}
|
|
11626
12364
|
return { hasUpdate: false };
|
|
@@ -11644,11 +12382,17 @@ var UpdateManager = class {
|
|
|
11644
12382
|
return { success: false, error: String(err2) };
|
|
11645
12383
|
}
|
|
11646
12384
|
}
|
|
11647
|
-
install() {
|
|
11648
|
-
if (this.downloadedPath) {
|
|
11649
|
-
|
|
11650
|
-
app13.quit();
|
|
12385
|
+
async install() {
|
|
12386
|
+
if (!this.downloadedPath) {
|
|
12387
|
+
return { success: false, error: "No update downloaded" };
|
|
11651
12388
|
}
|
|
12389
|
+
const failure = await shell3.openPath(this.downloadedPath);
|
|
12390
|
+
if (failure) {
|
|
12391
|
+
console.warn("[UpdateManager] install failed:", failure);
|
|
12392
|
+
return { success: false, error: failure };
|
|
12393
|
+
}
|
|
12394
|
+
app13.quit();
|
|
12395
|
+
return { success: true };
|
|
11652
12396
|
}
|
|
11653
12397
|
/**
|
|
11654
12398
|
* Tear down timers + IPC handlers. Returns a Promise so callers that need
|
|
@@ -11681,7 +12425,249 @@ var UpdateManager = class {
|
|
|
11681
12425
|
};
|
|
11682
12426
|
|
|
11683
12427
|
// src/main/services/update/github-release-checker.ts
|
|
12428
|
+
import fs12 from "fs";
|
|
12429
|
+
import path24 from "path";
|
|
12430
|
+
import https from "https";
|
|
11684
12431
|
import { app as app14 } from "electron";
|
|
12432
|
+
function createGitHubReleaseChecker(opts) {
|
|
12433
|
+
const releaseUrl = opts.includePrereleases ? `https://api.github.com/repos/${opts.owner}/${opts.repo}/releases` : `https://api.github.com/repos/${opts.owner}/${opts.repo}/releases/latest`;
|
|
12434
|
+
const parseVersion = opts.parseVersion ?? schemeParser(opts.versionScheme ?? "semver");
|
|
12435
|
+
return {
|
|
12436
|
+
async checkForUpdates(currentVersion) {
|
|
12437
|
+
const release = await fetchRelease(releaseUrl, opts);
|
|
12438
|
+
if (!release) return null;
|
|
12439
|
+
const latestVersion = parseVersion(release);
|
|
12440
|
+
if (!latestVersion) return null;
|
|
12441
|
+
if (compareSemver(latestVersion, stripV(currentVersion)) <= 0) return null;
|
|
12442
|
+
const asset = (opts.pickAsset ?? defaultPickAsset)(release.assets, {
|
|
12443
|
+
platform: process.platform,
|
|
12444
|
+
arch: process.arch
|
|
12445
|
+
});
|
|
12446
|
+
if (!asset) return null;
|
|
12447
|
+
return {
|
|
12448
|
+
version: latestVersion,
|
|
12449
|
+
downloadUrl: asset.browser_download_url,
|
|
12450
|
+
releaseNotes: release.body,
|
|
12451
|
+
mandatory: opts.mandatory
|
|
12452
|
+
};
|
|
12453
|
+
},
|
|
12454
|
+
async downloadUpdate(info, onProgress) {
|
|
12455
|
+
const tmpDir = path24.join(app14.getPath("temp"), `${opts.repo}-update`);
|
|
12456
|
+
if (!fs12.existsSync(tmpDir)) fs12.mkdirSync(tmpDir, { recursive: true });
|
|
12457
|
+
const fileName = path24.basename(new URL(info.downloadUrl).pathname);
|
|
12458
|
+
const filePath = path24.join(tmpDir, fileName);
|
|
12459
|
+
await downloadFile(info.downloadUrl, filePath, opts.token, onProgress);
|
|
12460
|
+
return filePath;
|
|
12461
|
+
}
|
|
12462
|
+
};
|
|
12463
|
+
}
|
|
12464
|
+
function defaultPickAsset(assets, ctx) {
|
|
12465
|
+
const candidates = platformMatchers(ctx.platform, ctx.arch);
|
|
12466
|
+
for (const match of candidates) {
|
|
12467
|
+
const hit = assets.find((a) => match(a.name));
|
|
12468
|
+
if (hit) return hit;
|
|
12469
|
+
}
|
|
12470
|
+
return void 0;
|
|
12471
|
+
}
|
|
12472
|
+
function platformMatchers(platform, arch) {
|
|
12473
|
+
const lc = (s) => s.toLowerCase();
|
|
12474
|
+
const archTags = archAliases(arch);
|
|
12475
|
+
const hasArch = (name) => archTags.some((tag) => lc(name).includes(tag));
|
|
12476
|
+
const endsWith = (name, ext) => lc(name).endsWith(ext);
|
|
12477
|
+
switch (platform) {
|
|
12478
|
+
case "darwin":
|
|
12479
|
+
return [
|
|
12480
|
+
(n) => endsWith(n, ".dmg") && hasArch(n),
|
|
12481
|
+
(n) => endsWith(n, ".dmg"),
|
|
12482
|
+
// mac builds are often universal / unarch-tagged
|
|
12483
|
+
(n) => endsWith(n, ".zip") && (lc(n).includes("mac") || lc(n).includes("darwin"))
|
|
12484
|
+
];
|
|
12485
|
+
case "win32":
|
|
12486
|
+
return [
|
|
12487
|
+
(n) => endsWith(n, ".exe") && hasArch(n),
|
|
12488
|
+
(n) => endsWith(n, ".zip") && (lc(n).includes("win") || lc(n).includes("windows")) && hasArch(n),
|
|
12489
|
+
(n) => endsWith(n, ".exe"),
|
|
12490
|
+
(n) => endsWith(n, ".zip") && (lc(n).includes("win") || lc(n).includes("windows"))
|
|
12491
|
+
];
|
|
12492
|
+
case "linux":
|
|
12493
|
+
return [
|
|
12494
|
+
(n) => endsWith(n, ".appimage") && hasArch(n),
|
|
12495
|
+
(n) => endsWith(n, ".tar.gz") && lc(n).includes("linux") && hasArch(n),
|
|
12496
|
+
(n) => endsWith(n, ".appimage"),
|
|
12497
|
+
(n) => endsWith(n, ".tar.gz") && lc(n).includes("linux"),
|
|
12498
|
+
(n) => endsWith(n, ".deb") && hasArch(n)
|
|
12499
|
+
];
|
|
12500
|
+
default:
|
|
12501
|
+
return [];
|
|
12502
|
+
}
|
|
12503
|
+
}
|
|
12504
|
+
function archAliases(arch) {
|
|
12505
|
+
switch (arch) {
|
|
12506
|
+
case "x64":
|
|
12507
|
+
return ["x64", "x86_64", "amd64"];
|
|
12508
|
+
case "arm64":
|
|
12509
|
+
return ["arm64", "aarch64"];
|
|
12510
|
+
case "ia32":
|
|
12511
|
+
return ["ia32", "x86", "i386"];
|
|
12512
|
+
default:
|
|
12513
|
+
return [arch];
|
|
12514
|
+
}
|
|
12515
|
+
}
|
|
12516
|
+
var SEMVER_RE = /(\d+)\.(\d+)\.(\d+)(?:[-+]([0-9A-Za-z.-]+))?/;
|
|
12517
|
+
var TRAILING_NUMBER_RE = /-(\d+)$/;
|
|
12518
|
+
function schemeParser(scheme) {
|
|
12519
|
+
if (scheme === "trailing-number") {
|
|
12520
|
+
return (release) => {
|
|
12521
|
+
const m = release.tag_name.match(TRAILING_NUMBER_RE);
|
|
12522
|
+
return m ? m[1] : null;
|
|
12523
|
+
};
|
|
12524
|
+
}
|
|
12525
|
+
return defaultParseVersion;
|
|
12526
|
+
}
|
|
12527
|
+
function defaultParseVersion(release) {
|
|
12528
|
+
const fromTag = extractSemver(release.tag_name);
|
|
12529
|
+
if (fromTag) return fromTag;
|
|
12530
|
+
if (release.name) {
|
|
12531
|
+
const fromName = extractSemver(release.name);
|
|
12532
|
+
if (fromName) return fromName;
|
|
12533
|
+
}
|
|
12534
|
+
for (const asset of release.assets) {
|
|
12535
|
+
const hit = extractSemver(asset.name);
|
|
12536
|
+
if (hit) return hit;
|
|
12537
|
+
}
|
|
12538
|
+
return null;
|
|
12539
|
+
}
|
|
12540
|
+
function extractSemver(input) {
|
|
12541
|
+
const m = input.match(SEMVER_RE);
|
|
12542
|
+
if (!m) return null;
|
|
12543
|
+
const [, major, minor, patch, pre] = m;
|
|
12544
|
+
return pre ? `${major}.${minor}.${patch}-${pre}` : `${major}.${minor}.${patch}`;
|
|
12545
|
+
}
|
|
12546
|
+
function stripV(version) {
|
|
12547
|
+
return version.replace(/^v/i, "");
|
|
12548
|
+
}
|
|
12549
|
+
function compareSemver(a, b) {
|
|
12550
|
+
const [aCore, aPre] = splitPre(a);
|
|
12551
|
+
const [bCore, bPre] = splitPre(b);
|
|
12552
|
+
const [a1, a2, a3] = parseCore(aCore);
|
|
12553
|
+
const [b1, b2, b3] = parseCore(bCore);
|
|
12554
|
+
if (a1 !== b1) return a1 - b1;
|
|
12555
|
+
if (a2 !== b2) return a2 - b2;
|
|
12556
|
+
if (a3 !== b3) return a3 - b3;
|
|
12557
|
+
if (!aPre && bPre) return 1;
|
|
12558
|
+
if (aPre && !bPre) return -1;
|
|
12559
|
+
if (!aPre && !bPre) return 0;
|
|
12560
|
+
return aPre.localeCompare(bPre);
|
|
12561
|
+
}
|
|
12562
|
+
function splitPre(v) {
|
|
12563
|
+
const i = v.indexOf("-");
|
|
12564
|
+
return i < 0 ? [v, null] : [v.slice(0, i), v.slice(i + 1)];
|
|
12565
|
+
}
|
|
12566
|
+
function parseCore(core) {
|
|
12567
|
+
const parts = core.split(".").map((s) => parseInt(s, 10) || 0);
|
|
12568
|
+
return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
|
|
12569
|
+
}
|
|
12570
|
+
function ghHeaders(token) {
|
|
12571
|
+
const headers = {
|
|
12572
|
+
"User-Agent": "dimina-kit-updater",
|
|
12573
|
+
"Accept": "application/vnd.github+json",
|
|
12574
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
12575
|
+
};
|
|
12576
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
12577
|
+
return headers;
|
|
12578
|
+
}
|
|
12579
|
+
async function fetchRelease(url, opts) {
|
|
12580
|
+
const body = await httpGetText(url, { headers: ghHeaders(opts.token) });
|
|
12581
|
+
if (!body) return null;
|
|
12582
|
+
if (opts.includePrereleases) {
|
|
12583
|
+
const list = JSON.parse(body);
|
|
12584
|
+
const first = list.find((r) => !r.draft);
|
|
12585
|
+
return first ?? null;
|
|
12586
|
+
}
|
|
12587
|
+
const release = JSON.parse(body);
|
|
12588
|
+
return release.draft ? null : release;
|
|
12589
|
+
}
|
|
12590
|
+
function httpGetText(url, init) {
|
|
12591
|
+
return new Promise((resolve, reject) => {
|
|
12592
|
+
const req = https.get(url, { headers: init.headers }, (res) => {
|
|
12593
|
+
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
12594
|
+
res.resume();
|
|
12595
|
+
resolve(httpGetText(res.headers.location, init));
|
|
12596
|
+
return;
|
|
12597
|
+
}
|
|
12598
|
+
if (res.statusCode !== 200) {
|
|
12599
|
+
res.resume();
|
|
12600
|
+
resolve(null);
|
|
12601
|
+
return;
|
|
12602
|
+
}
|
|
12603
|
+
let body = "";
|
|
12604
|
+
res.setEncoding("utf8");
|
|
12605
|
+
res.on("data", (chunk) => {
|
|
12606
|
+
body += chunk;
|
|
12607
|
+
});
|
|
12608
|
+
res.on("end", () => resolve(body));
|
|
12609
|
+
});
|
|
12610
|
+
req.on("error", reject);
|
|
12611
|
+
});
|
|
12612
|
+
}
|
|
12613
|
+
function downloadFile(url, dest, token, onProgress) {
|
|
12614
|
+
return new Promise((resolve, reject) => {
|
|
12615
|
+
const headers = ghHeaders(token);
|
|
12616
|
+
const cleanup = () => fs12.promises.unlink(dest).catch(() => {
|
|
12617
|
+
});
|
|
12618
|
+
const attempt = (target, redirectsLeft) => {
|
|
12619
|
+
const req = https.get(target, { headers }, (res) => {
|
|
12620
|
+
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
12621
|
+
res.resume();
|
|
12622
|
+
if (redirectsLeft <= 0) {
|
|
12623
|
+
reject(new Error("Too many redirects"));
|
|
12624
|
+
return;
|
|
12625
|
+
}
|
|
12626
|
+
attempt(res.headers.location, redirectsLeft - 1);
|
|
12627
|
+
return;
|
|
12628
|
+
}
|
|
12629
|
+
if (res.statusCode !== 200) {
|
|
12630
|
+
res.resume();
|
|
12631
|
+
reject(new Error(`HTTP ${res.statusCode} while downloading update`));
|
|
12632
|
+
return;
|
|
12633
|
+
}
|
|
12634
|
+
const total = parseInt(res.headers["content-length"] || "0", 10);
|
|
12635
|
+
let received = 0;
|
|
12636
|
+
const out = fs12.createWriteStream(dest);
|
|
12637
|
+
res.on("data", (chunk) => {
|
|
12638
|
+
received += chunk.length;
|
|
12639
|
+
if (total > 0 && onProgress) {
|
|
12640
|
+
onProgress(received / total * 100);
|
|
12641
|
+
}
|
|
12642
|
+
});
|
|
12643
|
+
res.on("error", async (err2) => {
|
|
12644
|
+
out.destroy();
|
|
12645
|
+
await cleanup();
|
|
12646
|
+
reject(err2);
|
|
12647
|
+
});
|
|
12648
|
+
res.pipe(out);
|
|
12649
|
+
out.on("finish", async () => {
|
|
12650
|
+
out.close();
|
|
12651
|
+
if (total > 0 && received !== total) {
|
|
12652
|
+
await cleanup();
|
|
12653
|
+
reject(new Error(`Downloaded ${received} bytes, expected ${total} \u2014 update download was truncated`));
|
|
12654
|
+
return;
|
|
12655
|
+
}
|
|
12656
|
+
resolve();
|
|
12657
|
+
});
|
|
12658
|
+
out.on("error", async (err2) => {
|
|
12659
|
+
await cleanup();
|
|
12660
|
+
reject(err2);
|
|
12661
|
+
});
|
|
12662
|
+
});
|
|
12663
|
+
req.on("error", async (err2) => {
|
|
12664
|
+
await cleanup();
|
|
12665
|
+
reject(err2);
|
|
12666
|
+
});
|
|
12667
|
+
};
|
|
12668
|
+
attempt(url, 5);
|
|
12669
|
+
});
|
|
12670
|
+
}
|
|
11685
12671
|
|
|
11686
12672
|
// src/main/app/app.ts
|
|
11687
12673
|
import { toDisposable as toDisposable8 } from "@dimina-kit/electron-deck/main";
|
|
@@ -11752,7 +12738,7 @@ async function disposeContext(ctx) {
|
|
|
11752
12738
|
function createConfiguredMainWindow(config, rendererDir2) {
|
|
11753
12739
|
const mainWindow = createMainWindow({
|
|
11754
12740
|
title: config.appName ?? "Dimina DevTools",
|
|
11755
|
-
indexHtml:
|
|
12741
|
+
indexHtml: path25.join(rendererDir2, "entries/main/index.html"),
|
|
11756
12742
|
width: config.window?.width,
|
|
11757
12743
|
height: config.window?.height,
|
|
11758
12744
|
minWidth: config.window?.minWidth,
|
|
@@ -11865,10 +12851,10 @@ function enableDevRendererAutoReload(rendererDir2) {
|
|
|
11865
12851
|
});
|
|
11866
12852
|
}
|
|
11867
12853
|
let reloadTimer = null;
|
|
11868
|
-
const watcher =
|
|
12854
|
+
const watcher = fs13.watch(rendererDir2, { recursive: true }, () => {
|
|
11869
12855
|
if (reloadTimer) clearTimeout(reloadTimer);
|
|
11870
12856
|
reloadTimer = setTimeout(() => {
|
|
11871
|
-
for (const win of
|
|
12857
|
+
for (const win of BrowserWindow9.getAllWindows()) {
|
|
11872
12858
|
win.webContents.reload();
|
|
11873
12859
|
}
|
|
11874
12860
|
}, 300);
|
|
@@ -11895,7 +12881,7 @@ function runDevtoolsBootstrap(config = {}) {
|
|
|
11895
12881
|
} catch {
|
|
11896
12882
|
}
|
|
11897
12883
|
}
|
|
11898
|
-
async function createDevtoolsRuntime(config = {}) {
|
|
12884
|
+
async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
|
|
11899
12885
|
await app15.whenReady();
|
|
11900
12886
|
applyTheme(loadWorkbenchSettings().theme);
|
|
11901
12887
|
const rendererDir2 = config.rendererDir ?? rendererDir;
|
|
@@ -11904,10 +12890,33 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
11904
12890
|
context.connections.acquire(mainWindow.webContents);
|
|
11905
12891
|
context.registry.add(registerAppIpc(context));
|
|
11906
12892
|
context.registry.add(registerProjectFsIpc(context));
|
|
12893
|
+
context.internalDevtoolsWindow = createInternalDevtoolsWindow(mainWindow, { isAppQuitting });
|
|
12894
|
+
context.registry.add(toDisposable8(() => context.internalDevtoolsWindow?.dispose()));
|
|
12895
|
+
context.registry.add(registerInternalDevtoolsIpc(context));
|
|
11907
12896
|
context.registry.add(setupSimulatorSessionPolicy());
|
|
11908
12897
|
context.registry.add(installThemeBackgroundSync());
|
|
11909
12898
|
if (!config.adapter) context.registry.add(setupCompileWorkerStandby(context));
|
|
11910
12899
|
registerBuiltinModules(config, context);
|
|
12900
|
+
if (context.consoleForwarder && context.internalDevtoolsWindow) {
|
|
12901
|
+
const consoleMirror = createGlobalConsoleMirror(
|
|
12902
|
+
context.consoleForwarder,
|
|
12903
|
+
mainWindow.webContents,
|
|
12904
|
+
context.internalDevtoolsWindow.onHostChanged,
|
|
12905
|
+
// CDP transport (never executeJavaScript) — see the mirror's inject()
|
|
12906
|
+
// doc for the setDevToolsWebContents + external-CDP double-attach hang.
|
|
12907
|
+
{ broker: context.cdpSessionBroker }
|
|
12908
|
+
);
|
|
12909
|
+
context.registry.add(toDisposable8(() => consoleMirror.dispose()));
|
|
12910
|
+
}
|
|
12911
|
+
if (context.diagnostics && context.internalDevtoolsWindow) {
|
|
12912
|
+
const diagnosticsMirror = createGlobalDiagnosticsMirror(
|
|
12913
|
+
context.diagnostics,
|
|
12914
|
+
mainWindow.webContents,
|
|
12915
|
+
context.internalDevtoolsWindow.onHostChanged,
|
|
12916
|
+
{ broker: context.cdpSessionBroker }
|
|
12917
|
+
);
|
|
12918
|
+
context.registry.add(toDisposable8(() => diagnosticsMirror.dispose()));
|
|
12919
|
+
}
|
|
11911
12920
|
const simSession = session4.fromPartition(SHARED_MINIAPP_PARTITION);
|
|
11912
12921
|
context.registry.add(setupSimulatorTempFiles(simSession));
|
|
11913
12922
|
installMenu(config, mainWindow, context);
|
|
@@ -11924,6 +12933,7 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
11924
12933
|
registerSimulatorApi: (name, handler) => context.registry.add(toDisposable8(context.simulatorApis.register(name, handler))),
|
|
11925
12934
|
dispose: () => disposeContext(context)
|
|
11926
12935
|
};
|
|
12936
|
+
onInstanceCreated?.(instance);
|
|
11927
12937
|
instance.registerSimulatorApi("login", async () => {
|
|
11928
12938
|
return "hello";
|
|
11929
12939
|
});
|
|
@@ -12006,6 +13016,17 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
12006
13016
|
if (context.bridge?.isNativeHost()) {
|
|
12007
13017
|
const networkForward = createNetworkForwarder({
|
|
12008
13018
|
getServiceWc: (appId) => context.bridge?.getServiceWc(appId) ?? null,
|
|
13019
|
+
getResourceServerBaseUrl: () => context.bridge?.getResourceBaseUrl?.() ?? null,
|
|
13020
|
+
// The simulator shell's own static-asset server (serves simulator.html
|
|
13021
|
+
// + its JS/CSS, independent from the resource server above — see
|
|
13022
|
+
// NetworkForwarderBridge.getSimulatorServerBaseUrl's doc). Host is
|
|
13023
|
+
// always 'localhost' — see shared/simulator-route.ts's
|
|
13024
|
+
// buildSimulatorUrlFromSpec default. Absent (null port) when no
|
|
13025
|
+
// project is open.
|
|
13026
|
+
getSimulatorServerBaseUrl: () => {
|
|
13027
|
+
const port = context.workspace?.getSession()?.port;
|
|
13028
|
+
return typeof port === "number" ? `http://localhost:${port}/` : null;
|
|
13029
|
+
},
|
|
12009
13030
|
connections: context.connections,
|
|
12010
13031
|
broker: context.cdpSessionBroker
|
|
12011
13032
|
});
|
|
@@ -12014,6 +13035,12 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
12014
13035
|
context.registry.add(() => {
|
|
12015
13036
|
context.networkForward = void 0;
|
|
12016
13037
|
});
|
|
13038
|
+
context.registry.add(toDisposable8(
|
|
13039
|
+
context.internalDevtoolsWindow?.onHostChanged((hostWc) => {
|
|
13040
|
+
context.networkForward?.setGlobalDevtoolsHost(hostWc);
|
|
13041
|
+
}) ?? (() => {
|
|
13042
|
+
})
|
|
13043
|
+
));
|
|
12017
13044
|
context.registry.add(setupSimulatorWxml(mainWindow.webContents, {
|
|
12018
13045
|
senderPolicy: context.senderPolicy,
|
|
12019
13046
|
bridge: context.bridge,
|
|
@@ -12036,8 +13063,8 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
12036
13063
|
bridge: context.bridge
|
|
12037
13064
|
}));
|
|
12038
13065
|
}
|
|
12039
|
-
const bundleDir = config.editorViewConfig?.bundleDir ??
|
|
12040
|
-
if (!
|
|
13066
|
+
const bundleDir = config.editorViewConfig?.bundleDir ?? path25.join(devtoolsPackageRoot, "dist/vscode-workbench");
|
|
13067
|
+
if (!fs13.existsSync(path25.join(bundleDir, "index.html"))) {
|
|
12041
13068
|
console.warn(
|
|
12042
13069
|
`[workbench] editor bundle not found at ${bundleDir} \u2014 skipping embedded editor assembly`
|
|
12043
13070
|
);
|
|
@@ -12074,6 +13101,7 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
12074
13101
|
// src/main/runtime/devtools-backend.ts
|
|
12075
13102
|
function createDevtoolsBackend(config = {}) {
|
|
12076
13103
|
let instance = null;
|
|
13104
|
+
let assembling = null;
|
|
12077
13105
|
return {
|
|
12078
13106
|
// The backend builds the devtools main window itself (framework skips its own).
|
|
12079
13107
|
// Its only construction-time needs are the host preload + `sandbox:false`
|
|
@@ -12095,15 +13123,33 @@ function createDevtoolsBackend(config = {}) {
|
|
|
12095
13123
|
// Setup (post-whenReady): app lifecycle (window-all-closed → quit) + the
|
|
12096
13124
|
// full devtools assembly.
|
|
12097
13125
|
assemble: async () => {
|
|
12098
|
-
registerAppLifecycle();
|
|
12099
|
-
|
|
13126
|
+
registerAppLifecycle(() => instance?.context.views.disposeAll());
|
|
13127
|
+
assembling = createDevtoolsRuntime(config, (created) => {
|
|
13128
|
+
instance = created;
|
|
13129
|
+
if (isAppQuitting()) instance.context.views.disposeAll();
|
|
13130
|
+
}).then(() => {
|
|
13131
|
+
});
|
|
13132
|
+
await assembling;
|
|
12100
13133
|
},
|
|
12101
13134
|
// Dispose the devtools context during the framework's deterministic shutdown
|
|
12102
13135
|
// (app.on('will-quit') → shutdown() → runShutdownCleanup(), awaited once).
|
|
12103
13136
|
// Without this, the compile session (a child process, torn down by
|
|
12104
13137
|
// closeProject) and the IPC registry would leak on exit. The framework awaits
|
|
12105
13138
|
// this hook, so teardown is no longer a best-effort before-quit reach-around.
|
|
12106
|
-
|
|
13139
|
+
//
|
|
13140
|
+
// Waits for `assembling` first: `instance` can be non-null (published
|
|
13141
|
+
// early, above) while `createDevtoolsRuntime`'s own async body — the
|
|
13142
|
+
// host's `onSetup` and everything scheduled after it — is still running
|
|
13143
|
+
// and still adding entries to `instance.context.registry`. Disposing
|
|
13144
|
+
// that registry out from under an in-flight assembly throws instead of
|
|
13145
|
+
// tearing down cleanly (`DisposableRegistry.add` rejects post-dispose).
|
|
13146
|
+
// `.catch()` here: assembly failing is `assemble`'s problem to surface,
|
|
13147
|
+
// not a reason to skip disposing whatever DID get constructed.
|
|
13148
|
+
onShutdown: async () => {
|
|
13149
|
+
await assembling?.catch(() => {
|
|
13150
|
+
});
|
|
13151
|
+
await instance?.dispose();
|
|
13152
|
+
}
|
|
12107
13153
|
};
|
|
12108
13154
|
}
|
|
12109
13155
|
|
|
@@ -12113,7 +13159,18 @@ function launch(config = {}) {
|
|
|
12113
13159
|
}
|
|
12114
13160
|
|
|
12115
13161
|
// src/main/index.ts
|
|
12116
|
-
|
|
13162
|
+
var updateChecker = app16.isPackaged && !app16.getVersion().includes("-dev.") ? createGitHubReleaseChecker({
|
|
13163
|
+
owner: "EchoTechFE",
|
|
13164
|
+
repo: "dimina-kit",
|
|
13165
|
+
parseVersion: (release) => {
|
|
13166
|
+
for (const asset of release.assets) {
|
|
13167
|
+
const match = /^dimina-devtools-(\d+\.\d+\.\d+)-/.exec(asset.name);
|
|
13168
|
+
if (match) return match[1];
|
|
13169
|
+
}
|
|
13170
|
+
return null;
|
|
13171
|
+
}
|
|
13172
|
+
}) : void 0;
|
|
13173
|
+
launch({ updateChecker }).catch((err2) => {
|
|
12117
13174
|
console.error("[devtools] fatal: launch() failed during boot", err2);
|
|
12118
13175
|
app16.exit(1);
|
|
12119
13176
|
});
|