@dimina-kit/devtools 0.4.0-dev.20260801163345 → 0.4.0-dev.20260824071518
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main/app/app.js +12 -1
- package/dist/main/index.bundle.js +584 -323
- package/dist/main/ipc/index.d.ts +1 -0
- package/dist/main/ipc/index.js +1 -0
- package/dist/main/ipc/session.js +11 -0
- package/dist/main/ipc/tooltip.d.ts +13 -0
- package/dist/main/ipc/tooltip.js +28 -0
- package/dist/main/services/layout/index.d.ts +11 -0
- package/dist/main/services/layout/index.js +23 -0
- package/dist/main/services/network-forward/frontend-dispatch.js +2 -1
- package/dist/main/services/notifications/renderer-notifier.d.ts +2 -0
- package/dist/main/services/notifications/renderer-notifier.js +7 -1
- package/dist/main/services/simulator-current-page/index.d.ts +5 -3
- package/dist/main/services/simulator-current-page/index.js +8 -1
- package/dist/main/services/views/clear-console-filter.d.ts +44 -0
- package/dist/main/services/views/clear-console-filter.js +86 -0
- package/dist/main/services/views/console-filter-test-fixtures.d.ts +94 -0
- package/dist/main/services/views/console-filter-test-fixtures.js +82 -0
- package/dist/main/services/views/console-filter.d.ts +79 -130
- package/dist/main/services/views/console-filter.js +140 -183
- package/dist/main/services/views/devtools-tabs.d.ts +24 -4
- package/dist/main/services/views/devtools-tabs.js +40 -21
- package/dist/main/services/views/host-toolbar-view.js +5 -18
- package/dist/main/services/views/native-simulator-devtools-host.js +64 -45
- package/dist/main/services/views/native-simulator-view.js +6 -24
- package/dist/main/services/views/native-view-tree.d.ts +25 -0
- package/dist/main/services/views/native-view-tree.js +69 -0
- package/dist/main/services/views/overlay-panels-view.d.ts +27 -4
- package/dist/main/services/views/overlay-panels-view.js +138 -109
- package/dist/main/services/views/placement-reconciler.d.ts +4 -16
- package/dist/main/services/views/placement-reconciler.js +64 -29
- package/dist/main/services/views/placement-test-driver.d.ts +26 -0
- package/dist/main/services/views/placement-test-driver.js +26 -0
- package/dist/main/services/views/view-manager.d.ts +5 -9
- package/dist/main/services/views/view-manager.js +7 -1
- package/dist/main/services/views/workbench-view.js +27 -20
- package/dist/main/services/workbench-coi-server.d.ts +11 -0
- package/dist/main/services/workbench-coi-server.js +32 -0
- package/dist/main/services/workspace/rebuild-status.d.ts +21 -8
- package/dist/main/services/workspace/rebuild-status.js +24 -8
- package/dist/main/utils/sender-policy.d.ts +1 -1
- package/dist/main/utils/sender-policy.js +6 -1
- package/dist/main/utils/theme.d.ts +7 -2
- package/dist/main/utils/theme.js +8 -3
- package/dist/native-host/container/pageFrame.css +1 -1
- package/dist/native-host/render/render.js +1966 -1816
- package/dist/native-host/service/service.js +1 -1
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs +3176 -14
- package/dist/preload/windows/main.cjs.map +4 -4
- package/dist/preload/windows/main.css +428 -0
- package/dist/preload/windows/main.css.map +7 -0
- package/dist/preload/windows/simulator.cjs +5 -2
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +5 -2
- package/dist/renderer/assets/constants-Bdz0LHdy.js +2 -0
- package/dist/renderer/assets/index-CtznrmHR.js +49 -0
- package/dist/renderer/assets/{input-xdmfv-eH.js → input-Dmm6nob5.js} +2 -2
- package/dist/renderer/assets/ipc-transport-BOg0gR9W.js +9 -0
- package/dist/renderer/assets/ipc-transport-DgQhZaE9.css +1 -0
- package/dist/renderer/assets/popover-Cd1FEGOX.js +2 -0
- package/dist/renderer/assets/select-BaYox7If.js +2 -0
- package/dist/renderer/assets/settings-BXvwuFaz.js +2 -0
- package/dist/renderer/assets/settings-api-Bo9GbYqs.js +2 -0
- package/dist/renderer/assets/settings-tab-bar-Beia6lMr.js +2 -0
- package/dist/renderer/assets/tooltip-DfQqK3Sk.js +2 -0
- package/dist/renderer/assets/view-api-nn69je7A.js +2 -0
- package/dist/renderer/assets/workbenchSettings-oq_EyfKf.js +8 -0
- package/dist/renderer/entries/main/index.html +8 -7
- package/dist/renderer/entries/popover/index.html +7 -6
- package/dist/renderer/entries/settings/index.html +7 -5
- package/dist/renderer/entries/tooltip/index.html +20 -0
- package/dist/renderer/entries/workbench-settings/index.html +7 -5
- package/dist/service-host/sync-impls/menu-button-geometry.js +1 -0
- package/dist/shared/ipc-channels.d.ts +11 -0
- package/dist/shared/ipc-channels.js +28 -2
- package/dist/shared/ipc-schemas.d.ts +19 -0
- package/dist/shared/ipc-schemas.js +23 -0
- package/dist/shared/simulator-route.d.ts +8 -0
- package/dist/shared/simulator-route.js +15 -0
- package/dist/shared/types.d.ts +7 -0
- package/dist/shared/view-ids.d.ts +2 -0
- package/dist/shared/view-ids.js +11 -0
- package/dist/simulator/assets/device-shell-CmtM1QxP.js +2 -0
- package/dist/simulator/assets/device-shell-iFZo1igL.css +1 -0
- package/dist/simulator/assets/{simulator-COIE6R49.js → simulator-CIobn3Mh.js} +6 -6
- package/dist/simulator/assets/{simulator-mini-app-BLn7XV8e.js → simulator-mini-app-CRe6n9br.js} +2 -2
- package/dist/simulator/assets/simulator-ui-BupATgKo.css +1 -0
- package/dist/simulator/assets/simulator-ui-C_cP602X.js +2 -0
- package/dist/simulator/simulator.html +3 -2
- package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +1 -0
- package/dist/vscode-workbench/assets/{dist-oHcwN53f.js → dist-CMfmHflW.js} +3 -3
- package/dist/vscode-workbench/assets/{iconv-lite-umd-CLMLpdGm.js → iconv-lite-umd-Bx8CgaZq.js} +1 -1
- package/dist/vscode-workbench/assets/{index-BE3UJdoH.js → index-CdG6YWhW.js} +436 -436
- package/dist/vscode-workbench/assets/{jschardet-BICW8PLJ.js → jschardet-M0qgd2lN.js} +1 -1
- package/dist/vscode-workbench/index.html +21 -1
- package/package.json +7 -6
- package/dist/main/services/views/destroy-child-view.d.ts +0 -9
- package/dist/main/services/views/destroy-child-view.js +0 -23
- package/dist/renderer/assets/constants-EAMiwL9_.js +0 -2
- package/dist/renderer/assets/index-BBg3YI5b.js +0 -49
- package/dist/renderer/assets/ipc-transport-B3EpmfNS.js +0 -9
- package/dist/renderer/assets/ipc-transport-Blac3sOj.css +0 -1
- package/dist/renderer/assets/popover-B88e2hkg.js +0 -2
- package/dist/renderer/assets/select-CD9CJyhI.js +0 -2
- package/dist/renderer/assets/settings-44hf0QtO.js +0 -2
- package/dist/renderer/assets/settings-api-pJKPuP1M.js +0 -2
- package/dist/renderer/assets/workbenchSettings-DKD5U1Ql.js +0 -8
- package/dist/simulator/assets/device-shell-Cw7c-IkG.js +0 -2
- package/dist/simulator/assets/device-shell-DbC5ccs8.css +0 -1
- package/dist/simulator/assets/jsx-runtime-DkKmJyBb.js +0 -2
- package/dist/simulator/device-shell/menu-button-geometry.js +0 -18
- package/dist/vscode-workbench/assets/__vite-browser-external-BON7qP59.js +0 -1
package/dist/main/ipc/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { registerAppIpc } from './app.js';
|
|
2
2
|
export { registerSimulatorIpc } from './simulator.js';
|
|
3
3
|
export { registerPopoverIpc, popoverModule } from './popover.js';
|
|
4
|
+
export { registerTooltipIpc, tooltipModule } from './tooltip.js';
|
|
4
5
|
export { registerProjectsIpc, projectsModule } from './projects.js';
|
|
5
6
|
export { registerSessionIpc, sessionModule } from './session.js';
|
|
6
7
|
export { registerSettingsIpc, settingsModule } from './settings.js';
|
package/dist/main/ipc/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { registerAppIpc } from './app.js';
|
|
2
2
|
export { registerSimulatorIpc } from './simulator.js';
|
|
3
3
|
export { registerPopoverIpc, popoverModule } from './popover.js';
|
|
4
|
+
export { registerTooltipIpc, tooltipModule } from './tooltip.js';
|
|
4
5
|
export { registerProjectsIpc, projectsModule } from './projects.js';
|
|
5
6
|
export { registerSessionIpc, sessionModule } from './session.js';
|
|
6
7
|
export { registerSettingsIpc, settingsModule } from './settings.js';
|
package/dist/main/ipc/session.js
CHANGED
|
@@ -22,6 +22,17 @@ export function registerSessionIpc(ctx) {
|
|
|
22
22
|
})
|
|
23
23
|
.handle(ProjectChannel.Close, () => {
|
|
24
24
|
return ctx.workspace.closeProject();
|
|
25
|
+
})
|
|
26
|
+
.handle(ProjectChannel.Rebuild, async () => {
|
|
27
|
+
const session = ctx.workspace.getSession();
|
|
28
|
+
if (!session)
|
|
29
|
+
throw new Error('project:rebuild — no active project session');
|
|
30
|
+
// A host CompilationAdapter predating session.rebuild must not break:
|
|
31
|
+
// degrade discernibly so the renderer falls back to reattach-only.
|
|
32
|
+
if (typeof session.rebuild !== 'function')
|
|
33
|
+
return { supported: false };
|
|
34
|
+
await session.rebuild();
|
|
35
|
+
return { supported: true };
|
|
25
36
|
})
|
|
26
37
|
.handle(ProjectChannel.CaptureThumbnail, (_, ...args) => {
|
|
27
38
|
const [projectPath] = validate(ProjectChannel.CaptureThumbnail, ProjectCaptureThumbnailSchema, args);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { WorkbenchModule } from '../services/module.js';
|
|
2
|
+
import type { ViewManager } from '../services/views/view-manager.js';
|
|
3
|
+
import type { Disposable } from '@dimina-kit/electron-deck/main';
|
|
4
|
+
import { type SenderPolicy } from '../utils/ipc-registry.js';
|
|
5
|
+
/** Module-local narrow deps — deliberately NOT `Pick<WorkbenchContext, ...>`
|
|
6
|
+
* (the gate in eslint.config.* is shrink-only; see its message). */
|
|
7
|
+
export interface TooltipIpcDeps {
|
|
8
|
+
views: Pick<ViewManager, 'prepareTooltip' | 'showTooltip' | 'hideTooltip' | 'markOverlayReady' | 'applyTooltipMeasurement'>;
|
|
9
|
+
senderPolicy?: SenderPolicy;
|
|
10
|
+
}
|
|
11
|
+
export declare function registerTooltipIpc(ctx: TooltipIpcDeps): Disposable;
|
|
12
|
+
export declare const tooltipModule: WorkbenchModule;
|
|
13
|
+
//# sourceMappingURL=tooltip.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { OverlayChannel, TooltipChannel } from '../../shared/ipc-channels.js';
|
|
2
|
+
import { TooltipMeasuredSchema, TooltipShowSchema } from '../../shared/ipc-schemas.js';
|
|
3
|
+
import { validate } from '../utils/ipc-schema.js';
|
|
4
|
+
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
5
|
+
export function registerTooltipIpc(ctx) {
|
|
6
|
+
return new IpcRegistry(ctx.senderPolicy)
|
|
7
|
+
.on(TooltipChannel.Prepare, () => {
|
|
8
|
+
ctx.views.prepareTooltip();
|
|
9
|
+
})
|
|
10
|
+
.on(TooltipChannel.Show, (_event, ...args) => {
|
|
11
|
+
const [data] = validate(TooltipChannel.Show, TooltipShowSchema, args);
|
|
12
|
+
ctx.views.showTooltip(data);
|
|
13
|
+
})
|
|
14
|
+
.on(TooltipChannel.Hide, () => {
|
|
15
|
+
ctx.views.hideTooltip();
|
|
16
|
+
})
|
|
17
|
+
.on(OverlayChannel.Ready, (event) => {
|
|
18
|
+
ctx.views.markOverlayReady(event.sender.id);
|
|
19
|
+
})
|
|
20
|
+
.on(TooltipChannel.Measured, (event, ...args) => {
|
|
21
|
+
const [measurement] = validate(TooltipChannel.Measured, TooltipMeasuredSchema, args);
|
|
22
|
+
ctx.views.applyTooltipMeasurement(event.sender.id, measurement);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export const tooltipModule = {
|
|
26
|
+
setup: (ctx) => registerTooltipIpc(ctx),
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=tooltip.js.map
|
|
@@ -41,4 +41,15 @@ export declare const SETTINGS_W = 320;
|
|
|
41
41
|
*/
|
|
42
42
|
export declare function computeSettingsBounds(contentWidth: number, contentHeight: number, headerHeight: number): Bounds;
|
|
43
43
|
export declare function computePopoverBounds(contentWidth: number, contentHeight: number, headerHeight: number): Bounds;
|
|
44
|
+
export declare function computeTooltipMaxWidth(contentWidth: number): number;
|
|
45
|
+
/**
|
|
46
|
+
* Position the tooltip overlay relative to its trigger's own bounding rect
|
|
47
|
+
* (both in main-window content coordinates). Prefers directly below the
|
|
48
|
+
* anchor, flips above when there isn't room; always clamped horizontally
|
|
49
|
+
* inside the content area.
|
|
50
|
+
*/
|
|
51
|
+
export declare function computeTooltipBounds(anchor: Bounds, contentWidth: number, contentHeight: number, measured: {
|
|
52
|
+
width: number;
|
|
53
|
+
height: number;
|
|
54
|
+
}): Bounds;
|
|
44
55
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -52,4 +52,27 @@ export function computePopoverBounds(contentWidth, contentHeight, headerHeight)
|
|
|
52
52
|
height: contentHeight - headerHeight,
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
+
const TOOLTIP_GAP = 6;
|
|
56
|
+
const TOOLTIP_EDGE_MARGIN = 4;
|
|
57
|
+
export function computeTooltipMaxWidth(contentWidth) {
|
|
58
|
+
return Math.max(1, contentWidth - TOOLTIP_EDGE_MARGIN * 2);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Position the tooltip overlay relative to its trigger's own bounding rect
|
|
62
|
+
* (both in main-window content coordinates). Prefers directly below the
|
|
63
|
+
* anchor, flips above when there isn't room; always clamped horizontally
|
|
64
|
+
* inside the content area.
|
|
65
|
+
*/
|
|
66
|
+
export function computeTooltipBounds(anchor, contentWidth, contentHeight, measured) {
|
|
67
|
+
const availableWidth = computeTooltipMaxWidth(contentWidth);
|
|
68
|
+
const width = Math.min(availableWidth, Math.max(1, Math.ceil(measured.width)));
|
|
69
|
+
const height = Math.max(1, Math.ceil(measured.height));
|
|
70
|
+
const below = anchor.y + anchor.height + TOOLTIP_GAP;
|
|
71
|
+
const fitsBelow = below + height <= contentHeight;
|
|
72
|
+
const y = fitsBelow ? below : Math.max(0, anchor.y - TOOLTIP_GAP - height);
|
|
73
|
+
const centeredX = anchor.x + anchor.width / 2 - width / 2;
|
|
74
|
+
const maxX = Math.max(TOOLTIP_EDGE_MARGIN, contentWidth - width - TOOLTIP_EDGE_MARGIN);
|
|
75
|
+
const x = Math.min(maxX, Math.max(TOOLTIP_EDGE_MARGIN, centeredX));
|
|
76
|
+
return { x, y, width, height };
|
|
77
|
+
}
|
|
55
78
|
//# sourceMappingURL=index.js.map
|
|
@@ -113,7 +113,8 @@ export function createFrontendReplyChannel(hostWc, isDisposed) {
|
|
|
113
113
|
export function drainOutboundBatch(batch, handle) {
|
|
114
114
|
if (!Array.isArray(batch))
|
|
115
115
|
return;
|
|
116
|
-
|
|
116
|
+
const entries = batch;
|
|
117
|
+
for (const raw of entries) {
|
|
117
118
|
if (!raw || typeof raw !== 'object')
|
|
118
119
|
continue;
|
|
119
120
|
const cmd = raw;
|
|
@@ -123,6 +123,8 @@ export interface RendererNotifier {
|
|
|
123
123
|
popoverInit(popoverView: WebContentsView, payload: unknown): void;
|
|
124
124
|
/** Initialise the currently shown settings overlay (no-op if hidden). */
|
|
125
125
|
settingsInit(payload: SettingsInitPayload): void;
|
|
126
|
+
/** Push the label text (+ anchor) into the tooltip overlay's own renderer. */
|
|
127
|
+
tooltipInit(tooltipView: WebContentsView, payload: unknown): void;
|
|
126
128
|
/** Initialise the standalone workbench-settings window. */
|
|
127
129
|
workbenchSettingsInit(window: BrowserWindow, payload: WorkbenchSettingsInitPayload): void;
|
|
128
130
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ProjectChannel, SessionChannel, WindowChannel, SettingsChannel, PopoverChannel, WorkbenchSettingsChannel, EditorChannel, ViewChannel, } from '../../../shared/ipc-channels.js';
|
|
1
|
+
import { ProjectChannel, SessionChannel, WindowChannel, SettingsChannel, PopoverChannel, TooltipChannel, WorkbenchSettingsChannel, EditorChannel, ViewChannel, } from '../../../shared/ipc-channels.js';
|
|
2
2
|
/** Safely resolve a WebContents, skipping destroyed / missing targets. */
|
|
3
3
|
function liveWebContents(wc) {
|
|
4
4
|
if (!wc)
|
|
@@ -54,6 +54,12 @@ export function createRendererNotifier(ctx) {
|
|
|
54
54
|
return;
|
|
55
55
|
wc.send(PopoverChannel.Init, payload);
|
|
56
56
|
},
|
|
57
|
+
tooltipInit(tooltipView, payload) {
|
|
58
|
+
const wc = liveWebContents(tooltipView.webContents);
|
|
59
|
+
if (!wc)
|
|
60
|
+
return;
|
|
61
|
+
wc.send(TooltipChannel.Init, payload);
|
|
62
|
+
},
|
|
57
63
|
settingsInit(payload) {
|
|
58
64
|
const wc = liveWebContents(ctx.views.getSettingsWebContents());
|
|
59
65
|
if (!wc)
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* page a nested render-host `<webview>`), not a renderer `<webview>` the main
|
|
7
7
|
* window can observe — so in-app navigation (navigateTo / switchTab / back)
|
|
8
8
|
* never reaches the renderer's `<webview>` did-navigate events. This service
|
|
9
|
-
* taps the bridge's active-page signal and pushes the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* taps the bridge's active-page signal and pushes the route — page path plus
|
|
10
|
+
* its launch query, so the simulator's page-path bar shows params just like
|
|
11
|
+
* WeChat DevTools and a recompile can restore them — to the main-window
|
|
12
|
+
* renderer (`SimulatorChannel.CurrentPage`), keeping the toolbar in sync
|
|
13
|
+
* without polling.
|
|
12
14
|
*
|
|
13
15
|
* Inert on the default dimina-fe path (which derives the current page from the
|
|
14
16
|
* simulator `<webview>`'s navigation events); app.ts gates the call on
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SimulatorChannel } from '../../../shared/ipc-channels.js';
|
|
2
|
+
import { encodePageSpec } from '../../../shared/simulator-route.js';
|
|
2
3
|
import { DisposableRegistry } from '@dimina-kit/electron-deck/main';
|
|
3
4
|
export function setupSimulatorCurrentPage(host, options) {
|
|
4
5
|
const registry = new DisposableRegistry();
|
|
@@ -11,7 +12,13 @@ export function setupSimulatorCurrentPage(host, options) {
|
|
|
11
12
|
return;
|
|
12
13
|
if (host.isDestroyed())
|
|
13
14
|
return;
|
|
14
|
-
|
|
15
|
+
// Bridge queries are `Record<string, unknown>` (they may hold numbers from
|
|
16
|
+
// the URL); the route format wants strings. encodePageSpec re-encodes with
|
|
17
|
+
// `?k=v&…` so the renderer can decode it back into { pagePath, query }.
|
|
18
|
+
const query = {};
|
|
19
|
+
for (const [k, v] of Object.entries(ev.query ?? {}))
|
|
20
|
+
query[k] = String(v);
|
|
21
|
+
host.send(SimulatorChannel.CurrentPage, encodePageSpec({ pagePath: ev.pagePath, query }));
|
|
15
22
|
});
|
|
16
23
|
registry.add(off);
|
|
17
24
|
return registry;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clears the right-panel Console panel's text-filter box on a FRESH project
|
|
3
|
+
* open, together with the stale persisted keys behind it.
|
|
4
|
+
*
|
|
5
|
+
* ── Why this exists ──────────────────────────────────────────────────────
|
|
6
|
+
* The Console filter text is a DevTools-owned setting that DevTools itself
|
|
7
|
+
* persists: it lives on the `devtools://` origin's localStorage, backed by the
|
|
8
|
+
* default session's on-disk storage (verified on disk:
|
|
9
|
+
* `~/Library/Application Support/Dimina DevTools/Local Storage/leveldb` holds a
|
|
10
|
+
* `console.textFilter` entry). An earlier implementation of the internal-log
|
|
11
|
+
* hiding wrote `-/^\[service\]/`-style negative filters straight into the box
|
|
12
|
+
* (see console-filter.ts's header for that history); that value still sits in
|
|
13
|
+
* localStorage and is restored on every project reopen / app restart. We do NOT
|
|
14
|
+
* fight DevTools' persistence mechanism here — instead, on each fresh project
|
|
15
|
+
* open we remove the stale keys and reset the visible box, so a project starts
|
|
16
|
+
* with the developer's own filter surface genuinely empty.
|
|
17
|
+
*
|
|
18
|
+
* ── When it runs ─────────────────────────────────────────────────────────
|
|
19
|
+
* Only the PROJECT-OPEN path arms this (see native-simulator-devtools-host.ts:
|
|
20
|
+
* `attach()` sets the flag; the injection consumes it once). Service-host pool
|
|
21
|
+
* swaps (hot-reload respawn) rebuild the front-end host too, but deliberately do
|
|
22
|
+
* NOT clear — the developer may legitimately have typed a filter during the
|
|
23
|
+
* session and a respawn must not drop in-flight work.
|
|
24
|
+
*
|
|
25
|
+
* ── Discipline (mirrors console-filter.ts) ────────────────────────────────
|
|
26
|
+
* In-realm bootstrap probe before touching `Console.ConsoleView.instance()` (an
|
|
27
|
+
* early construction transitively creates IssuesManager and permanently kills
|
|
28
|
+
* the front-end's own bootstrap — see frontend-bootstrap-gate.ts); bounded
|
|
29
|
+
* retry; silent degradation on any failure. The main process additionally holds
|
|
30
|
+
* this whole injection behind `whenFrontendBootstrapped`.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Build the `executeJavaScript` source that clears the Console filter box.
|
|
34
|
+
*
|
|
35
|
+
* Two levers, belt-and-suspenders:
|
|
36
|
+
* 1. remove the stale persisted keys (`console.textFilter` — the on-disk
|
|
37
|
+
* leftover we actually observed, and its kebab-case sibling) so a Console
|
|
38
|
+
* view constructed after this script reads an empty setting;
|
|
39
|
+
* 2. reset the already-constructed panel's visible box via
|
|
40
|
+
* `filter.textFilterUI.setValue('')`, which persists the empty value back
|
|
41
|
+
* through the panel's own setting path.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildClearConsoleFilterScript(): string;
|
|
44
|
+
//# sourceMappingURL=clear-console-filter.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clears the right-panel Console panel's text-filter box on a FRESH project
|
|
3
|
+
* open, together with the stale persisted keys behind it.
|
|
4
|
+
*
|
|
5
|
+
* ── Why this exists ──────────────────────────────────────────────────────
|
|
6
|
+
* The Console filter text is a DevTools-owned setting that DevTools itself
|
|
7
|
+
* persists: it lives on the `devtools://` origin's localStorage, backed by the
|
|
8
|
+
* default session's on-disk storage (verified on disk:
|
|
9
|
+
* `~/Library/Application Support/Dimina DevTools/Local Storage/leveldb` holds a
|
|
10
|
+
* `console.textFilter` entry). An earlier implementation of the internal-log
|
|
11
|
+
* hiding wrote `-/^\[service\]/`-style negative filters straight into the box
|
|
12
|
+
* (see console-filter.ts's header for that history); that value still sits in
|
|
13
|
+
* localStorage and is restored on every project reopen / app restart. We do NOT
|
|
14
|
+
* fight DevTools' persistence mechanism here — instead, on each fresh project
|
|
15
|
+
* open we remove the stale keys and reset the visible box, so a project starts
|
|
16
|
+
* with the developer's own filter surface genuinely empty.
|
|
17
|
+
*
|
|
18
|
+
* ── When it runs ─────────────────────────────────────────────────────────
|
|
19
|
+
* Only the PROJECT-OPEN path arms this (see native-simulator-devtools-host.ts:
|
|
20
|
+
* `attach()` sets the flag; the injection consumes it once). Service-host pool
|
|
21
|
+
* swaps (hot-reload respawn) rebuild the front-end host too, but deliberately do
|
|
22
|
+
* NOT clear — the developer may legitimately have typed a filter during the
|
|
23
|
+
* session and a respawn must not drop in-flight work.
|
|
24
|
+
*
|
|
25
|
+
* ── Discipline (mirrors console-filter.ts) ────────────────────────────────
|
|
26
|
+
* In-realm bootstrap probe before touching `Console.ConsoleView.instance()` (an
|
|
27
|
+
* early construction transitively creates IssuesManager and permanently kills
|
|
28
|
+
* the front-end's own bootstrap — see frontend-bootstrap-gate.ts); bounded
|
|
29
|
+
* retry; silent degradation on any failure. The main process additionally holds
|
|
30
|
+
* this whole injection behind `whenFrontendBootstrapped`.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Build the `executeJavaScript` source that clears the Console filter box.
|
|
34
|
+
*
|
|
35
|
+
* Two levers, belt-and-suspenders:
|
|
36
|
+
* 1. remove the stale persisted keys (`console.textFilter` — the on-disk
|
|
37
|
+
* leftover we actually observed, and its kebab-case sibling) so a Console
|
|
38
|
+
* view constructed after this script reads an empty setting;
|
|
39
|
+
* 2. reset the already-constructed panel's visible box via
|
|
40
|
+
* `filter.textFilterUI.setValue('')`, which persists the empty value back
|
|
41
|
+
* through the panel's own setting path.
|
|
42
|
+
*/
|
|
43
|
+
export function buildClearConsoleFilterScript() {
|
|
44
|
+
return `(function(){
|
|
45
|
+
var attempts = 0;
|
|
46
|
+
var MAX = 100;
|
|
47
|
+
function bootstrapReady() {
|
|
48
|
+
try {
|
|
49
|
+
var eui = globalThis.EUI;
|
|
50
|
+
if (!eui || !eui.ShortcutRegistry || !eui.ShortcutRegistry.ShortcutRegistry) return false;
|
|
51
|
+
eui.ShortcutRegistry.ShortcutRegistry.instance();
|
|
52
|
+
return true;
|
|
53
|
+
} catch (_) { return false; }
|
|
54
|
+
}
|
|
55
|
+
function tryClear() {
|
|
56
|
+
attempts++;
|
|
57
|
+
var scheduleRetry = attempts < MAX;
|
|
58
|
+
if (!bootstrapReady()) {
|
|
59
|
+
if (scheduleRetry) { setTimeout(tryClear, 100); return; }
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
try { localStorage.removeItem('console.textFilter'); } catch(_) {}
|
|
64
|
+
try { localStorage.removeItem('console.text-filter'); } catch(_) {}
|
|
65
|
+
var ConsoleNS = globalThis.Console;
|
|
66
|
+
var view = ConsoleNS && ConsoleNS.ConsoleView ? ConsoleNS.ConsoleView.instance() : null;
|
|
67
|
+
var f = view ? view.filter : null;
|
|
68
|
+
var box = f && f.textFilterUI;
|
|
69
|
+
if (!box || typeof box.setValue !== 'function' || typeof box.value !== 'function') {
|
|
70
|
+
if (scheduleRetry) { setTimeout(tryClear, 100); return; }
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
var current = box.value();
|
|
74
|
+
if (current) {
|
|
75
|
+
box.setValue('');
|
|
76
|
+
if (typeof f.updateCurrentFilter === 'function') f.updateCurrentFilter();
|
|
77
|
+
if (typeof f.onFilterChanged === 'function') f.onFilterChanged();
|
|
78
|
+
}
|
|
79
|
+
} catch(_) {
|
|
80
|
+
if (scheduleRetry) setTimeout(tryClear, 100);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
tryClear();
|
|
84
|
+
})()`;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=clear-console-filter.js.map
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fakes shaped like the Chrome DevTools front-end objects
|
|
3
|
+
* `buildInternalLogHideScript()`'s generated source talks to, shared by
|
|
4
|
+
* console-filter.test.ts (what the hook does) and
|
|
5
|
+
* console-filter-degradation.test.ts (what happens when the panel is not there
|
|
6
|
+
* or the front-end API has moved).
|
|
7
|
+
*
|
|
8
|
+
* These are STUBS OF A FOREIGN API, not a second implementation: every test
|
|
9
|
+
* runs the real generated script string through `new Function`, so the fakes
|
|
10
|
+
* only have to expose the handful of members the script reaches for. What they
|
|
11
|
+
* cannot prove is that the real front-end still has those members — that is
|
|
12
|
+
* e2e/console-filter-live.spec.ts's job.
|
|
13
|
+
*/
|
|
14
|
+
import { type Mock } from 'vitest';
|
|
15
|
+
export interface FakeViewMessage {
|
|
16
|
+
consoleMessage: () => {
|
|
17
|
+
messageText: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export type ShouldBeVisible = (this: unknown, viewMessage: FakeViewMessage) => boolean;
|
|
21
|
+
export interface FakeConsoleFilterClass {
|
|
22
|
+
original: Mock<ShouldBeVisible>;
|
|
23
|
+
prototype: {
|
|
24
|
+
shouldBeVisible?: ShouldBeVisible;
|
|
25
|
+
};
|
|
26
|
+
newInstance: () => {
|
|
27
|
+
shouldBeVisible: ShouldBeVisible;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface FakeConsoleView {
|
|
31
|
+
view: {
|
|
32
|
+
filter: {
|
|
33
|
+
currentFilter: object;
|
|
34
|
+
textFilterUI: {
|
|
35
|
+
value: () => string;
|
|
36
|
+
setValue: Mock<(next: string) => void>;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
onFilterChanged: Mock<() => void>;
|
|
40
|
+
};
|
|
41
|
+
setValue: Mock<(next: string) => void>;
|
|
42
|
+
onFilterChanged: Mock<() => void>;
|
|
43
|
+
filterText: () => string;
|
|
44
|
+
}
|
|
45
|
+
/** A ConsoleViewMessage stub exposing the single field the hook inspects. */
|
|
46
|
+
export declare function createViewMessage(messageText: string): FakeViewMessage;
|
|
47
|
+
/**
|
|
48
|
+
* A ConsoleFilter "class": one shared prototype carrying `shouldBeVisible`,
|
|
49
|
+
* plus a factory for further instances off that same prototype — what
|
|
50
|
+
* `ConsoleFilter.clone()` produces. `original` is the pre-existing
|
|
51
|
+
* implementation the hook must delegate to.
|
|
52
|
+
*/
|
|
53
|
+
export declare function createConsoleFilterClass(verdict?: boolean | ShouldBeVisible): FakeConsoleFilterClass;
|
|
54
|
+
/** A ConsoleFilter whose prototype chain carries no `shouldBeVisible` at all. */
|
|
55
|
+
export declare function createConsoleFilterClassWithoutHook(): {
|
|
56
|
+
prototype: Record<string, unknown>;
|
|
57
|
+
newInstance: () => object;
|
|
58
|
+
};
|
|
59
|
+
/** The ConsoleView surface the script reaches through: filter + refresh entry point. */
|
|
60
|
+
export declare function createConsoleView(currentFilter: object, initialFilterText?: string): FakeConsoleView;
|
|
61
|
+
/** A front end whose bootstrap has finished: the probe returns instead of throwing. */
|
|
62
|
+
export declare function createReadyEui(): {
|
|
63
|
+
ShortcutRegistry: {
|
|
64
|
+
ShortcutRegistry: {
|
|
65
|
+
instance: () => {};
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
export declare function createGlobalThis(view: unknown): {
|
|
70
|
+
EUI: {
|
|
71
|
+
ShortcutRegistry: {
|
|
72
|
+
ShortcutRegistry: {
|
|
73
|
+
instance: () => {};
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
Console: {
|
|
78
|
+
ConsoleView: {
|
|
79
|
+
instance: () => unknown;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
export declare function run(script: string, fakeGlobalThis: object): void;
|
|
84
|
+
/**
|
|
85
|
+
* Collect `console.warn` output as plain strings for the whole test file.
|
|
86
|
+
*
|
|
87
|
+
* Reading `warnSpy.mock.calls` instead would hand every assertion an untyped
|
|
88
|
+
* `any[]`; the degradation tests care about WHICH warning was emitted, so the
|
|
89
|
+
* text has to survive into the assertion with its type intact.
|
|
90
|
+
*/
|
|
91
|
+
export declare function recordWarnings(): {
|
|
92
|
+
messages: string[];
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=console-filter-test-fixtures.d.ts.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fakes shaped like the Chrome DevTools front-end objects
|
|
3
|
+
* `buildInternalLogHideScript()`'s generated source talks to, shared by
|
|
4
|
+
* console-filter.test.ts (what the hook does) and
|
|
5
|
+
* console-filter-degradation.test.ts (what happens when the panel is not there
|
|
6
|
+
* or the front-end API has moved).
|
|
7
|
+
*
|
|
8
|
+
* These are STUBS OF A FOREIGN API, not a second implementation: every test
|
|
9
|
+
* runs the real generated script string through `new Function`, so the fakes
|
|
10
|
+
* only have to expose the handful of members the script reaches for. What they
|
|
11
|
+
* cannot prove is that the real front-end still has those members — that is
|
|
12
|
+
* e2e/console-filter-live.spec.ts's job.
|
|
13
|
+
*/
|
|
14
|
+
import { vi } from 'vitest';
|
|
15
|
+
/** A ConsoleViewMessage stub exposing the single field the hook inspects. */
|
|
16
|
+
export function createViewMessage(messageText) {
|
|
17
|
+
return { consoleMessage: () => ({ messageText }) };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A ConsoleFilter "class": one shared prototype carrying `shouldBeVisible`,
|
|
21
|
+
* plus a factory for further instances off that same prototype — what
|
|
22
|
+
* `ConsoleFilter.clone()` produces. `original` is the pre-existing
|
|
23
|
+
* implementation the hook must delegate to.
|
|
24
|
+
*/
|
|
25
|
+
export function createConsoleFilterClass(verdict = true) {
|
|
26
|
+
const impl = typeof verdict === 'function' ? verdict : () => verdict;
|
|
27
|
+
const original = vi.fn(impl);
|
|
28
|
+
const prototype = { shouldBeVisible: original };
|
|
29
|
+
return {
|
|
30
|
+
original,
|
|
31
|
+
prototype,
|
|
32
|
+
newInstance: () => Object.create(prototype),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** A ConsoleFilter whose prototype chain carries no `shouldBeVisible` at all. */
|
|
36
|
+
export function createConsoleFilterClassWithoutHook() {
|
|
37
|
+
const prototype = Object.create(null);
|
|
38
|
+
return { prototype, newInstance: () => Object.create(prototype) };
|
|
39
|
+
}
|
|
40
|
+
/** The ConsoleView surface the script reaches through: filter + refresh entry point. */
|
|
41
|
+
export function createConsoleView(currentFilter, initialFilterText = '') {
|
|
42
|
+
let filterText = initialFilterText;
|
|
43
|
+
const setValue = vi.fn((next) => { filterText = next; });
|
|
44
|
+
const onFilterChanged = vi.fn();
|
|
45
|
+
return {
|
|
46
|
+
view: {
|
|
47
|
+
filter: {
|
|
48
|
+
currentFilter,
|
|
49
|
+
textFilterUI: { value: () => filterText, setValue },
|
|
50
|
+
},
|
|
51
|
+
onFilterChanged,
|
|
52
|
+
},
|
|
53
|
+
setValue,
|
|
54
|
+
onFilterChanged,
|
|
55
|
+
filterText: () => filterText,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** A front end whose bootstrap has finished: the probe returns instead of throwing. */
|
|
59
|
+
export function createReadyEui() {
|
|
60
|
+
return { ShortcutRegistry: { ShortcutRegistry: { instance: () => ({}) } } };
|
|
61
|
+
}
|
|
62
|
+
export function createGlobalThis(view) {
|
|
63
|
+
return { EUI: createReadyEui(), Console: { ConsoleView: { instance: () => view } } };
|
|
64
|
+
}
|
|
65
|
+
export function run(script, fakeGlobalThis) {
|
|
66
|
+
new Function('globalThis', script)(fakeGlobalThis);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Collect `console.warn` output as plain strings for the whole test file.
|
|
70
|
+
*
|
|
71
|
+
* Reading `warnSpy.mock.calls` instead would hand every assertion an untyped
|
|
72
|
+
* `any[]`; the degradation tests care about WHICH warning was emitted, so the
|
|
73
|
+
* text has to survive into the assertion with its type intact.
|
|
74
|
+
*/
|
|
75
|
+
export function recordWarnings() {
|
|
76
|
+
const record = { messages: [] };
|
|
77
|
+
vi.spyOn(console, 'warn').mockImplementation((...args) => {
|
|
78
|
+
record.messages.push(args.map((arg) => String(arg)).join(' '));
|
|
79
|
+
});
|
|
80
|
+
return record;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=console-filter-test-fixtures.js.map
|