@dimina-kit/devtools 0.3.2-dev.20260611063505 → 0.4.0-dev.20260612025610
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/README.md +56 -41
- package/dist/main/api.d.ts +4 -2
- package/dist/main/api.js +5 -1
- package/dist/main/app/app.d.ts +1 -5
- package/dist/main/app/app.js +25 -30
- package/dist/main/app/launch.d.ts +4 -4
- package/dist/main/app/launch.js +5 -17
- package/dist/main/index.bundle.js +535 -593
- package/dist/main/ipc/app.d.ts +1 -1
- package/dist/main/ipc/app.js +0 -7
- package/dist/main/ipc/index.d.ts +0 -2
- package/dist/main/ipc/index.js +0 -2
- package/dist/main/ipc/settings.d.ts +1 -1
- package/dist/main/ipc/settings.js +1 -13
- package/dist/main/ipc/simulator-module.d.ts +3 -3
- package/dist/main/ipc/simulator-module.js +3 -7
- package/dist/main/ipc/simulator.js +1 -12
- package/dist/main/menu/index.d.ts +2 -2
- package/dist/main/menu/index.js +4 -2
- package/dist/main/runtime/miniapp-runtime.d.ts +206 -28
- package/dist/main/runtime/miniapp-runtime.js +6 -11
- package/dist/main/services/layout/index.d.ts +0 -11
- package/dist/main/services/layout/index.js +0 -23
- package/dist/main/services/notifications/renderer-notifier.d.ts +0 -6
- package/dist/main/services/notifications/renderer-notifier.js +1 -10
- package/dist/main/services/service-host-pool/pool.d.ts +5 -4
- package/dist/main/services/views/host-toolbar-port-channel.d.ts +103 -0
- package/dist/main/services/views/host-toolbar-port-channel.js +248 -0
- package/dist/main/services/views/host-toolbar-session-runtime.d.ts +35 -0
- package/dist/main/services/views/host-toolbar-session-runtime.js +55 -0
- package/dist/main/services/views/view-manager.d.ts +80 -39
- package/dist/main/services/views/view-manager.js +153 -182
- package/dist/main/services/workbench-context.d.ts +13 -26
- package/dist/main/services/workbench-context.js +5 -14
- package/dist/main/services/workspace/workspace-service.d.ts +3 -7
- package/dist/main/services/workspace/workspace-service.js +34 -13
- package/dist/main/utils/paths.d.ts +11 -2
- package/dist/main/utils/paths.js +11 -2
- package/dist/main/windows/settings-window/index.d.ts +33 -0
- package/dist/main/windows/settings-window/index.js +59 -0
- package/dist/preload/index.d.ts +15 -0
- package/dist/preload/index.js +15 -0
- package/dist/preload/runtime/host-toolbar-port.d.ts +49 -0
- package/dist/preload/runtime/host-toolbar-port.js +151 -0
- package/dist/preload/runtime/host-toolbar-runtime.d.ts +41 -0
- package/dist/preload/runtime/host-toolbar-runtime.js +49 -0
- package/dist/preload/windows/{host-toolbar.cjs → host-toolbar-runtime.cjs} +103 -3
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +7 -0
- package/dist/preload/windows/host-toolbar-runtime.d.ts +2 -0
- package/dist/preload/windows/host-toolbar-runtime.js +13 -0
- package/dist/preload/windows/simulator.cjs +0 -2
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +0 -2
- package/dist/renderer/assets/constants-DI382mTP.js +2 -0
- package/dist/renderer/assets/index-DLzjz1wv.js +50 -0
- package/dist/renderer/assets/{input-CFHmbOgz.js → input-6fpCXV-n.js} +2 -2
- package/dist/renderer/assets/ipc-transport-Bs8Sf1B2.css +1 -0
- package/dist/renderer/assets/{ipc-transport-BkKKww3u.js → ipc-transport-D22e4dv7.js} +6 -6
- package/dist/renderer/assets/popover-CdGdKkkc.js +2 -0
- package/dist/renderer/assets/select-X0sbjwdP.js +2 -0
- package/dist/renderer/assets/{settings-Cl4IcWnG.js → settings-CS4jYaCw.js} +2 -2
- package/dist/renderer/assets/settings-api-CCWTAao_.js +2 -0
- package/dist/renderer/assets/workbenchSettings-Bpzaj3bm.js +8 -0
- package/dist/renderer/entries/main/index.html +7 -6
- package/dist/renderer/entries/popover/index.html +6 -6
- package/dist/renderer/entries/settings/index.html +5 -5
- package/dist/renderer/entries/workbench-settings/index.html +5 -5
- package/dist/shared/constants.d.ts +18 -0
- package/dist/shared/constants.js +18 -0
- package/dist/shared/ipc-channels.d.ts +10 -23
- package/dist/shared/ipc-channels.js +13 -34
- package/dist/shared/ipc-schemas.d.ts +0 -12
- package/dist/shared/ipc-schemas.js +0 -12
- package/dist/shared/types.d.ts +60 -76
- package/package.json +6 -6
- package/dist/main/ipc/panels.d.ts +0 -4
- package/dist/main/ipc/panels.js +0 -46
- package/dist/main/ipc/toolbar.d.ts +0 -4
- package/dist/main/ipc/toolbar.js +0 -21
- package/dist/main/services/toolbar/toolbar-store.d.ts +0 -23
- package/dist/main/services/toolbar/toolbar-store.js +0 -40
- package/dist/preload/windows/host-toolbar.cjs.map +0 -7
- package/dist/preload/windows/host-toolbar.d.ts +0 -2
- package/dist/preload/windows/host-toolbar.js +0 -12
- package/dist/renderer/assets/constants-CLAQX6VZ.js +0 -2
- package/dist/renderer/assets/index-CZQOpCvg.js +0 -50
- package/dist/renderer/assets/ipc-transport-Bv_BVu4T.css +0 -1
- package/dist/renderer/assets/popover-h1M7n3tt.js +0 -2
- package/dist/renderer/assets/select-kj0n1oYf.js +0 -2
- package/dist/renderer/assets/settings-api-CCwo2eOi.js +0 -2
- package/dist/renderer/assets/workbenchSettings-BzlpQnve.js +0 -8
|
@@ -4,31 +4,19 @@ import { defaultAdapter } from './default-adapter.js';
|
|
|
4
4
|
import { createRendererNotifier, } from './notifications/renderer-notifier.js';
|
|
5
5
|
import { createViewManager } from './views/view-manager.js';
|
|
6
6
|
import { createWindowService } from './window-service.js';
|
|
7
|
+
import { openSettingsWindow } from '../windows/settings-window/index.js';
|
|
7
8
|
import { createWorkspaceService, } from './workspace/workspace-service.js';
|
|
8
9
|
import { createLocalProjectsProvider } from './projects/local-provider.js';
|
|
9
10
|
import { createSimulatorApiRegistry, } from './simulator/custom-apis.js';
|
|
10
|
-
import { createToolbarStore } from './toolbar/toolbar-store.js';
|
|
11
11
|
import { resolveTemplates, sanitizeTemplates } from './projects/templates.js';
|
|
12
12
|
import { BUILTIN_TEMPLATES } from './projects/builtin-templates.js';
|
|
13
|
-
export function hasBuiltinPanel(ctx, panelId) {
|
|
14
|
-
return ctx.panels.includes(panelId);
|
|
15
|
-
}
|
|
16
|
-
export function getDefaultTab(ctx) {
|
|
17
|
-
if (hasBuiltinPanel(ctx, 'console'))
|
|
18
|
-
return 'simulator';
|
|
19
|
-
if (ctx.panels.length > 0)
|
|
20
|
-
return ctx.panels[0];
|
|
21
|
-
return 'simulator';
|
|
22
|
-
}
|
|
23
13
|
export function createWorkbenchContext(opts) {
|
|
24
14
|
const ctx = {
|
|
25
15
|
adapter: opts.adapter ?? defaultAdapter,
|
|
26
16
|
preloadPath: opts.preloadPath,
|
|
27
17
|
rendererDir: opts.rendererDir,
|
|
28
|
-
panels: opts.panels ?? ['wxml', 'console', 'appdata', 'storage'],
|
|
29
18
|
apiNamespaces: opts.apiNamespaces ?? [],
|
|
30
19
|
appName: opts.appName ?? 'Dimina DevTools',
|
|
31
|
-
headerHeight: opts.headerHeight ?? 40,
|
|
32
20
|
brandingProvider: opts.brandingProvider,
|
|
33
21
|
};
|
|
34
22
|
ctx.registry = new DisposableRegistry();
|
|
@@ -39,10 +27,13 @@ export function createWorkbenchContext(opts) {
|
|
|
39
27
|
ctx.connections = createConnectionRegistry();
|
|
40
28
|
ctx.trustedWindowSenderIds = new Map();
|
|
41
29
|
ctx.simulatorApis = createSimulatorApiRegistry();
|
|
42
|
-
ctx.toolbar = createToolbarStore();
|
|
43
30
|
ctx.windows = createWindowService(opts.mainWindow);
|
|
44
31
|
ctx.views = createViewManager(ctx);
|
|
45
32
|
ctx.notify = createRendererNotifier(ctx);
|
|
33
|
+
// Lazy closure (not a bound snapshot): reads ctx.windows/notify/rendererDir
|
|
34
|
+
// at call time through the live context, which structurally satisfies the
|
|
35
|
+
// helper's narrow OpenSettingsWindowDeps.
|
|
36
|
+
ctx.openSettings = () => openSettingsWindow(ctx);
|
|
46
37
|
ctx.projectsProvider = opts.projectsProvider ?? createLocalProjectsProvider();
|
|
47
38
|
ctx.projectTemplates = resolveTemplates(BUILTIN_TEMPLATES, opts.projectTemplates ?? [], opts.builtinTemplates ?? 'all');
|
|
48
39
|
ctx.customCreateProjectDialog = opts.customCreateProjectDialog;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompileConfig } from '../../../shared/types.js';
|
|
1
|
+
import type { AppInfo, CompileConfig, ProjectSession } from '../../../shared/types.js';
|
|
2
2
|
import type { WorkbenchContext } from '../workbench-context.js';
|
|
3
3
|
import type { Project, ProjectPages, ProjectSettings } from '../projects/project-repository.js';
|
|
4
4
|
/**
|
|
@@ -9,7 +9,7 @@ import type { Project, ProjectPages, ProjectSettings } from '../projects/project
|
|
|
9
9
|
export interface OpenProjectResult {
|
|
10
10
|
success: boolean;
|
|
11
11
|
port?: number;
|
|
12
|
-
appInfo?:
|
|
12
|
+
appInfo?: AppInfo;
|
|
13
13
|
error?: string;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
@@ -32,11 +32,7 @@ export interface WorkspaceService {
|
|
|
32
32
|
validateProjectDir(dirPath: string): Promise<string | null>;
|
|
33
33
|
openProject(projectPath: string): Promise<OpenProjectResult>;
|
|
34
34
|
closeProject(): Promise<void>;
|
|
35
|
-
getSession():
|
|
36
|
-
close: () => Promise<void>;
|
|
37
|
-
port: number;
|
|
38
|
-
appInfo: unknown;
|
|
39
|
-
} | null;
|
|
35
|
+
getSession(): ProjectSession | null;
|
|
40
36
|
getProjectPath(): string;
|
|
41
37
|
/**
|
|
42
38
|
* The project path most recently torn down by `closeProject`, or '' if none
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
1
2
|
import * as repo from '../projects/project-repository.js';
|
|
2
3
|
import { DEFAULT_COMPILE_CONFIG } from '../projects/types.js';
|
|
3
4
|
import { clearSimulatorServicewechatReferer, setSimulatorServicewechatReferer, } from '../simulator/referer.js';
|
|
4
5
|
import { loadWorkbenchSettings } from '../settings/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Runtime guard for the adapter-return boundary: `session.appInfo` must be an
|
|
8
|
+
* object carrying a string `appId` (the renderer derives its IPC scoping from
|
|
9
|
+
* it; a session without one cannot be driven). Loose: extra fields pass
|
|
10
|
+
* through untouched — only the contract-critical `appId` is enforced.
|
|
11
|
+
*/
|
|
12
|
+
const SessionAppInfoSchema = z.looseObject({ appId: z.string() });
|
|
5
13
|
/** Build a workspace service bound to the given workbench context. */
|
|
6
14
|
export function createWorkspaceService(ctx) {
|
|
7
15
|
let currentSession = null;
|
|
@@ -62,6 +70,12 @@ export function createWorkspaceService(ctx) {
|
|
|
62
70
|
? provider.validateProjectDir(dirPath)
|
|
63
71
|
: null,
|
|
64
72
|
async openProject(projectPath) {
|
|
73
|
+
clearSimulatorServicewechatReferer();
|
|
74
|
+
await disposeSession();
|
|
75
|
+
currentProjectPath = '';
|
|
76
|
+
// A fresh open starts a clean sandbox window — drop any previously
|
|
77
|
+
// recorded last-closed root so it can't accept writes after this point.
|
|
78
|
+
lastClosedProjectPath = '';
|
|
65
79
|
// Reject obviously broken projects up front so we never spin up a
|
|
66
80
|
// compile/server that the simulator will then fetch asset-by-asset.
|
|
67
81
|
// Without this guard, deleted recent-list entries and typo'd CLI paths
|
|
@@ -76,18 +90,6 @@ export function createWorkspaceService(ctx) {
|
|
|
76
90
|
sendStatus('error', dirError);
|
|
77
91
|
return { success: false, error: dirError };
|
|
78
92
|
}
|
|
79
|
-
const gate = ctx.beforeOpenProject ? await ctx.beforeOpenProject(projectPath) : undefined;
|
|
80
|
-
if (gate && !gate.allow) {
|
|
81
|
-
const message = gate.userMessage ?? gate.reason;
|
|
82
|
-
sendStatus('error', message);
|
|
83
|
-
return { success: false, error: message };
|
|
84
|
-
}
|
|
85
|
-
clearSimulatorServicewechatReferer();
|
|
86
|
-
await disposeSession();
|
|
87
|
-
currentProjectPath = '';
|
|
88
|
-
// A fresh open starts a clean sandbox window — drop any previously
|
|
89
|
-
// recorded last-closed root so it can't accept writes after this point.
|
|
90
|
-
lastClosedProjectPath = '';
|
|
91
93
|
sendStatus('compiling', '正在编译...');
|
|
92
94
|
const { compile } = loadWorkbenchSettings();
|
|
93
95
|
let session;
|
|
@@ -105,13 +107,32 @@ export function createWorkspaceService(ctx) {
|
|
|
105
107
|
sendStatus('error', String(err));
|
|
106
108
|
return { success: false, error: String(err) };
|
|
107
109
|
}
|
|
110
|
+
// Adapter-return boundary: enforce the AppInfo producer contract the
|
|
111
|
+
// moment the adapter resolves, BEFORE the session is recorded. A
|
|
112
|
+
// session without a string appId cannot be driven by the renderer, so
|
|
113
|
+
// it must never become the active session. The adapter already spun up
|
|
114
|
+
// live resources (compile watcher, dev-server port) — close them
|
|
115
|
+
// best-effort before reporting; the validation report is the law and a
|
|
116
|
+
// failing close() must not mask it (or escape as a throw).
|
|
117
|
+
if (!SessionAppInfoSchema.safeParse(session.appInfo).success) {
|
|
118
|
+
try {
|
|
119
|
+
await session.close();
|
|
120
|
+
}
|
|
121
|
+
catch (closeErr) {
|
|
122
|
+
console.warn('[workspace] closing appId-less adapter session failed (non-fatal):', closeErr);
|
|
123
|
+
}
|
|
124
|
+
const error = 'adapter returned session.appInfo without a string appId — ' +
|
|
125
|
+
'the CompilationAdapter must supply appInfo.appId';
|
|
126
|
+
sendStatus('error', error);
|
|
127
|
+
return { success: false, error };
|
|
128
|
+
}
|
|
108
129
|
currentSession = session;
|
|
109
130
|
currentProjectPath = projectPath;
|
|
110
131
|
bestEffort('updateLastOpened', () => {
|
|
111
132
|
if (provider.updateLastOpened)
|
|
112
133
|
provider.updateLastOpened(projectPath);
|
|
113
134
|
});
|
|
114
|
-
bestEffort('sendStatus', () => sendStatus('ready',
|
|
135
|
+
bestEffort('sendStatus', () => sendStatus('ready', '编译完成'));
|
|
115
136
|
bestEffort('applyReferer', () => applyRefererFromSession(session));
|
|
116
137
|
return {
|
|
117
138
|
success: true,
|
|
@@ -20,8 +20,17 @@ export declare function cjsSiblingPreloadPath(preloadPath: string): string;
|
|
|
20
20
|
* contextBridge so the renderer never needs `window.require('electron')`.
|
|
21
21
|
*/
|
|
22
22
|
export declare const mainPreloadPath: string;
|
|
23
|
-
/**
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Session-registered toolbar-runtime preload bundle (the reverse
|
|
25
|
+
* size-advertiser, self-guarded by the `--dimina-host-toolbar` marker +
|
|
26
|
+
* `isMainFrame`). Registered on `session.defaultSession` via
|
|
27
|
+
* `registerPreloadScript({ type: 'frame', filePath })` — see
|
|
28
|
+
* `src/main/services/views/host-toolbar-session-runtime.ts`. Session preloads
|
|
29
|
+
* are always loaded as CommonJS, so this points at the `.cjs` bundle (same
|
|
30
|
+
* rule `cjsSiblingPreloadPath` exists for). Resolved from the package root so
|
|
31
|
+
* npm/pnpm node_modules and ASAR packaging alike get an absolute, correct path.
|
|
32
|
+
*/
|
|
33
|
+
export declare const hostToolbarRuntimePreloadPath: string;
|
|
25
34
|
export declare const simulatorDir: string;
|
|
26
35
|
export declare function getRendererDir(): string;
|
|
27
36
|
export declare function getPreloadDir(): string;
|
package/dist/main/utils/paths.js
CHANGED
|
@@ -48,8 +48,17 @@ export function cjsSiblingPreloadPath(preloadPath) {
|
|
|
48
48
|
* contextBridge so the renderer never needs `window.require('electron')`.
|
|
49
49
|
*/
|
|
50
50
|
export const mainPreloadPath = path.join(devtoolsPackageRoot, 'dist/preload/windows/main.cjs');
|
|
51
|
-
/**
|
|
52
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Session-registered toolbar-runtime preload bundle (the reverse
|
|
53
|
+
* size-advertiser, self-guarded by the `--dimina-host-toolbar` marker +
|
|
54
|
+
* `isMainFrame`). Registered on `session.defaultSession` via
|
|
55
|
+
* `registerPreloadScript({ type: 'frame', filePath })` — see
|
|
56
|
+
* `src/main/services/views/host-toolbar-session-runtime.ts`. Session preloads
|
|
57
|
+
* are always loaded as CommonJS, so this points at the `.cjs` bundle (same
|
|
58
|
+
* rule `cjsSiblingPreloadPath` exists for). Resolved from the package root so
|
|
59
|
+
* npm/pnpm node_modules and ASAR packaging alike get an absolute, correct path.
|
|
60
|
+
*/
|
|
61
|
+
export const hostToolbarRuntimePreloadPath = path.join(devtoolsPackageRoot, 'dist/preload/windows/host-toolbar-runtime.cjs');
|
|
53
62
|
export const simulatorDir = path.join(devtoolsPackageRoot, 'dist/simulator');
|
|
54
63
|
export function getRendererDir() {
|
|
55
64
|
return rendererDir;
|
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
import type { BrowserWindow } from 'electron';
|
|
2
|
+
import { type WorkbenchSettings } from '../../services/settings/index.js';
|
|
1
3
|
export { createSettingsWindow } from './create.js';
|
|
2
4
|
export { wireSettingsWindowEvents } from './events.js';
|
|
5
|
+
/**
|
|
6
|
+
* Exactly what `openSettingsWindow` needs — its OWN narrow deps interface,
|
|
7
|
+
* not a `Pick<WorkbenchContext, …>`: picking from the full context couples
|
|
8
|
+
* this helper to the whole context type (and made the contract's old
|
|
9
|
+
* `windows: object` pass-through promise unfulfillable). A full
|
|
10
|
+
* `WorkbenchContext` satisfies this structurally, so assembly points pass
|
|
11
|
+
* the context straight through.
|
|
12
|
+
*/
|
|
13
|
+
export interface OpenSettingsWindowDeps {
|
|
14
|
+
/** Absolute path to the renderer dist directory (settings entry HTML). */
|
|
15
|
+
rendererDir: string;
|
|
16
|
+
windows: {
|
|
17
|
+
readonly mainWindow: BrowserWindow;
|
|
18
|
+
readonly settingsWindow: BrowserWindow | null;
|
|
19
|
+
setSettingsWindow(win: BrowserWindow | null): void;
|
|
20
|
+
};
|
|
21
|
+
notify: {
|
|
22
|
+
workbenchSettingsInit(window: BrowserWindow, payload: {
|
|
23
|
+
settings: WorkbenchSettings;
|
|
24
|
+
}): void;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Open (or re-focus) the standalone workbench-settings window. Reuses the
|
|
29
|
+
* live window when one is already registered; otherwise creates it, registers
|
|
30
|
+
* it on the window service, and wires its `closed` cleanup. Concurrent calls
|
|
31
|
+
* share a single in-flight creation (exactly one window; every caller still
|
|
32
|
+
* gets the show/focus/snapshot semantics). Always shows + focuses, then
|
|
33
|
+
* pushes the current settings snapshot into it.
|
|
34
|
+
*/
|
|
35
|
+
export declare function openSettingsWindow(deps: OpenSettingsWindowDeps): Promise<void>;
|
|
3
36
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,3 +1,62 @@
|
|
|
1
|
+
import { createSettingsWindow } from './create.js';
|
|
2
|
+
import { wireSettingsWindowEvents } from './events.js';
|
|
3
|
+
import { loadWorkbenchSettings, } from '../../services/settings/index.js';
|
|
1
4
|
export { createSettingsWindow } from './create.js';
|
|
2
5
|
export { wireSettingsWindowEvents } from './events.js';
|
|
6
|
+
/**
|
|
7
|
+
* In-flight creation guard, keyed by the windows registry (the identity that
|
|
8
|
+
* owns the `settingsWindow` slot). Overlapping `openSettingsWindow` calls
|
|
9
|
+
* before the first creation lands must share ONE creation — without this,
|
|
10
|
+
* both observe `settingsWindow === null` across the async construction
|
|
11
|
+
* boundary, build two BrowserWindows, and the loser is orphaned (alive,
|
|
12
|
+
* unreachable, never reused).
|
|
13
|
+
*/
|
|
14
|
+
const inFlightCreations = new WeakMap();
|
|
15
|
+
async function getOrCreateSettingsWindow(deps) {
|
|
16
|
+
const existing = deps.windows.settingsWindow;
|
|
17
|
+
if (existing && !existing.isDestroyed())
|
|
18
|
+
return existing;
|
|
19
|
+
const inFlight = inFlightCreations.get(deps.windows);
|
|
20
|
+
if (inFlight)
|
|
21
|
+
return inFlight;
|
|
22
|
+
const creation = (async () => {
|
|
23
|
+
const win = await createSettingsWindow(deps.windows.mainWindow, deps.rendererDir);
|
|
24
|
+
deps.windows.setSettingsWindow(win);
|
|
25
|
+
wireSettingsWindowEvents(win, () => {
|
|
26
|
+
// Electron delivers 'closed' asynchronously: a just-destroyed window's
|
|
27
|
+
// late callback may arrive AFTER a successor was registered. Only the
|
|
28
|
+
// CURRENT registration's own close may clear the slot — a stale
|
|
29
|
+
// window's close must not drop a live successor.
|
|
30
|
+
if (deps.windows.settingsWindow === win) {
|
|
31
|
+
deps.windows.setSettingsWindow(null);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return win;
|
|
35
|
+
})();
|
|
36
|
+
inFlightCreations.set(deps.windows, creation);
|
|
37
|
+
try {
|
|
38
|
+
return await creation;
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
if (inFlightCreations.get(deps.windows) === creation) {
|
|
42
|
+
inFlightCreations.delete(deps.windows);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Open (or re-focus) the standalone workbench-settings window. Reuses the
|
|
48
|
+
* live window when one is already registered; otherwise creates it, registers
|
|
49
|
+
* it on the window service, and wires its `closed` cleanup. Concurrent calls
|
|
50
|
+
* share a single in-flight creation (exactly one window; every caller still
|
|
51
|
+
* gets the show/focus/snapshot semantics). Always shows + focuses, then
|
|
52
|
+
* pushes the current settings snapshot into it.
|
|
53
|
+
*/
|
|
54
|
+
export async function openSettingsWindow(deps) {
|
|
55
|
+
const win = await getOrCreateSettingsWindow(deps);
|
|
56
|
+
win.show();
|
|
57
|
+
win.focus();
|
|
58
|
+
deps.notify.workbenchSettingsInit(win, {
|
|
59
|
+
settings: loadWorkbenchSettings(),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
3
62
|
//# sourceMappingURL=index.js.map
|
package/dist/preload/index.d.ts
CHANGED
|
@@ -12,7 +12,22 @@
|
|
|
12
12
|
export { installConsoleInstrumentation } from './instrumentation/console.js';
|
|
13
13
|
export { createAppDataSource } from './instrumentation/app-data.js';
|
|
14
14
|
export type { AppDataSnapshot } from './instrumentation/app-data.js';
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated Will be removed in the next minor. Under the native-host (sole)
|
|
17
|
+
* runtime the simulator top frame is a top-level WebContentsView — the page DOM
|
|
18
|
+
* lives in child render-host `<webview>` guests, so this top-frame DOM observer
|
|
19
|
+
* only ever publishes `null`. Panel WXML flows over the main-process
|
|
20
|
+
* `SimulatorWxmlChannel` (`src/main/services/simulator-wxml`) instead.
|
|
21
|
+
*/
|
|
15
22
|
export { createWxmlSource } from './instrumentation/wxml.js';
|
|
23
|
+
/**
|
|
24
|
+
* @deprecated Will be removed in the next minor. The host's
|
|
25
|
+
* `miniapp-snapshot:push/pull` IPC has no receiving end under the native-host
|
|
26
|
+
* (sole) runtime: the simulator is a top-level WebContentsView without an
|
|
27
|
+
* embedder (its `sendToHost` fires into the void) and the renderer-side puller
|
|
28
|
+
* was removed. Panel data flows over the main-process `SimulatorWxmlChannel` /
|
|
29
|
+
* `SimulatorAppDataChannel` / `SimulatorStorageChannel` instead.
|
|
30
|
+
*/
|
|
16
31
|
export { createMiniappSnapshotHost } from './miniapp-snapshot/host.js';
|
|
17
32
|
export type { MiniappSnapshotHost, MiniappSnapshotSource, SnapshotEnvelope, SnapshotSourceId, } from './miniapp-snapshot/types.js';
|
|
18
33
|
export { installSimulatorBridge } from './runtime/bridge.js';
|
package/dist/preload/index.js
CHANGED
|
@@ -11,7 +11,22 @@
|
|
|
11
11
|
*/
|
|
12
12
|
export { installConsoleInstrumentation } from './instrumentation/console.js';
|
|
13
13
|
export { createAppDataSource } from './instrumentation/app-data.js';
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated Will be removed in the next minor. Under the native-host (sole)
|
|
16
|
+
* runtime the simulator top frame is a top-level WebContentsView — the page DOM
|
|
17
|
+
* lives in child render-host `<webview>` guests, so this top-frame DOM observer
|
|
18
|
+
* only ever publishes `null`. Panel WXML flows over the main-process
|
|
19
|
+
* `SimulatorWxmlChannel` (`src/main/services/simulator-wxml`) instead.
|
|
20
|
+
*/
|
|
14
21
|
export { createWxmlSource } from './instrumentation/wxml.js';
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Will be removed in the next minor. The host's
|
|
24
|
+
* `miniapp-snapshot:push/pull` IPC has no receiving end under the native-host
|
|
25
|
+
* (sole) runtime: the simulator is a top-level WebContentsView without an
|
|
26
|
+
* embedder (its `sendToHost` fires into the void) and the renderer-side puller
|
|
27
|
+
* was removed. Panel data flows over the main-process `SimulatorWxmlChannel` /
|
|
28
|
+
* `SimulatorAppDataChannel` / `SimulatorStorageChannel` instead.
|
|
29
|
+
*/
|
|
15
30
|
export { createMiniappSnapshotHost } from './miniapp-snapshot/host.js';
|
|
16
31
|
export { installSimulatorBridge } from './runtime/bridge.js';
|
|
17
32
|
export { installCustomApisBridge } from './runtime/custom-apis.js';
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preload side of the host-toolbar gated narrow channel.
|
|
3
|
+
*
|
|
4
|
+
* ── PUBLIC SURFACE EVOLUTION RULE ───────────────────────────────────────────
|
|
5
|
+
* `window.diminaHostToolbar` is a published page-facing API, typed by the
|
|
6
|
+
* exported `DiminaHostToolbarPageBridge` (src/main/runtime/miniapp-runtime.ts)
|
|
7
|
+
* — arbitrary host toolbar pages compile against it. Members may only be
|
|
8
|
+
* ADDED, never changed: any semantic change to an existing member (signature,
|
|
9
|
+
* return shape, queueing/throw behavior) ships under a NEW name instead.
|
|
10
|
+
* Exception: security fixes / compliance corrections may change existing
|
|
11
|
+
* member semantics, and MUST be called out in the release's version notes.
|
|
12
|
+
* Keep the exported bridge type in lockstep with what is exposed here.
|
|
13
|
+
*
|
|
14
|
+
* Receives the per-load MessagePort main transfers on `did-finish-load`
|
|
15
|
+
* (`ViewChannel.HostToolbarPort`, `event.ports[0]`) and bridges it to the page
|
|
16
|
+
* as `window.diminaHostToolbar` — EXACTLY `{ send, onMessage }`, functions
|
|
17
|
+
* only. The raw MessagePort never crosses into the main world: the page only
|
|
18
|
+
* ever talks through these two functions, so the `{ channel, payload }`
|
|
19
|
+
* envelope stays the single waist (same posture as the main side's
|
|
20
|
+
* host-toolbar-port-channel.ts).
|
|
21
|
+
*
|
|
22
|
+
* Ordering reality this module absorbs (spike .repro/wave3-spike):
|
|
23
|
+
* - The page script runs BEFORE the handshake can complete (the port is
|
|
24
|
+
* posted on did-finish-load). Page `send()`s issued before the port
|
|
25
|
+
* arrives go into a PENDING QUEUE and flush in order on handshake —
|
|
26
|
+
* without it the first message of every load is silently dropped. The
|
|
27
|
+
* queue is BOUNDED at `HOST_TOOLBAR_PENDING_LIMIT` (128): the toolbar page
|
|
28
|
+
* is arbitrary host content, and a page whose handshake never arrives must
|
|
29
|
+
* not grow main-world-driven memory without limit. Overflow drops the
|
|
30
|
+
* NEWEST send (boot sequences front-load their important messages; the
|
|
31
|
+
* first-comers survive), warns ONCE per load, and never throws into page
|
|
32
|
+
* code.
|
|
33
|
+
* - Page handlers likewise register before the port exists; the registry is
|
|
34
|
+
* module-level (per-load — the preload re-runs on every navigation) and is
|
|
35
|
+
* re-attached to each newly delivered port, so a same-load re-handshake
|
|
36
|
+
* keeps existing handlers alive. The LATER port wins for sends.
|
|
37
|
+
* - Inbound dispatch uses `addEventListener('message')` + `start()`
|
|
38
|
+
* (without `start()` a DOM MessagePort never delivers) and DROPS malformed
|
|
39
|
+
* envelopes without throwing.
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* Cap on pre-handshake queued sends. 128 comfortably covers any sane toolbar
|
|
43
|
+
* boot sequence while bounding what a page whose handshake never completes
|
|
44
|
+
* can make the isolated world retain. Overflow policy: drop the NEWEST
|
|
45
|
+
* envelope (queued first-comers survive), one console.warn per load.
|
|
46
|
+
*/
|
|
47
|
+
export declare const HOST_TOOLBAR_PENDING_LIMIT = 128;
|
|
48
|
+
export declare function installHostToolbarPortBridge(): void;
|
|
49
|
+
//# sourceMappingURL=host-toolbar-port.d.ts.map
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preload side of the host-toolbar gated narrow channel.
|
|
3
|
+
*
|
|
4
|
+
* ── PUBLIC SURFACE EVOLUTION RULE ───────────────────────────────────────────
|
|
5
|
+
* `window.diminaHostToolbar` is a published page-facing API, typed by the
|
|
6
|
+
* exported `DiminaHostToolbarPageBridge` (src/main/runtime/miniapp-runtime.ts)
|
|
7
|
+
* — arbitrary host toolbar pages compile against it. Members may only be
|
|
8
|
+
* ADDED, never changed: any semantic change to an existing member (signature,
|
|
9
|
+
* return shape, queueing/throw behavior) ships under a NEW name instead.
|
|
10
|
+
* Exception: security fixes / compliance corrections may change existing
|
|
11
|
+
* member semantics, and MUST be called out in the release's version notes.
|
|
12
|
+
* Keep the exported bridge type in lockstep with what is exposed here.
|
|
13
|
+
*
|
|
14
|
+
* Receives the per-load MessagePort main transfers on `did-finish-load`
|
|
15
|
+
* (`ViewChannel.HostToolbarPort`, `event.ports[0]`) and bridges it to the page
|
|
16
|
+
* as `window.diminaHostToolbar` — EXACTLY `{ send, onMessage }`, functions
|
|
17
|
+
* only. The raw MessagePort never crosses into the main world: the page only
|
|
18
|
+
* ever talks through these two functions, so the `{ channel, payload }`
|
|
19
|
+
* envelope stays the single waist (same posture as the main side's
|
|
20
|
+
* host-toolbar-port-channel.ts).
|
|
21
|
+
*
|
|
22
|
+
* Ordering reality this module absorbs (spike .repro/wave3-spike):
|
|
23
|
+
* - The page script runs BEFORE the handshake can complete (the port is
|
|
24
|
+
* posted on did-finish-load). Page `send()`s issued before the port
|
|
25
|
+
* arrives go into a PENDING QUEUE and flush in order on handshake —
|
|
26
|
+
* without it the first message of every load is silently dropped. The
|
|
27
|
+
* queue is BOUNDED at `HOST_TOOLBAR_PENDING_LIMIT` (128): the toolbar page
|
|
28
|
+
* is arbitrary host content, and a page whose handshake never arrives must
|
|
29
|
+
* not grow main-world-driven memory without limit. Overflow drops the
|
|
30
|
+
* NEWEST send (boot sequences front-load their important messages; the
|
|
31
|
+
* first-comers survive), warns ONCE per load, and never throws into page
|
|
32
|
+
* code.
|
|
33
|
+
* - Page handlers likewise register before the port exists; the registry is
|
|
34
|
+
* module-level (per-load — the preload re-runs on every navigation) and is
|
|
35
|
+
* re-attached to each newly delivered port, so a same-load re-handshake
|
|
36
|
+
* keeps existing handlers alive. The LATER port wins for sends.
|
|
37
|
+
* - Inbound dispatch uses `addEventListener('message')` + `start()`
|
|
38
|
+
* (without `start()` a DOM MessagePort never delivers) and DROPS malformed
|
|
39
|
+
* envelopes without throwing.
|
|
40
|
+
*/
|
|
41
|
+
import { contextBridge, ipcRenderer } from 'electron';
|
|
42
|
+
import { ViewChannel } from '../../shared/ipc-channels.js';
|
|
43
|
+
const BRIDGE_KEY = 'diminaHostToolbar';
|
|
44
|
+
/**
|
|
45
|
+
* Cap on pre-handshake queued sends. 128 comfortably covers any sane toolbar
|
|
46
|
+
* boot sequence while bounding what a page whose handshake never completes
|
|
47
|
+
* can make the isolated world retain. Overflow policy: drop the NEWEST
|
|
48
|
+
* envelope (queued first-comers survive), one console.warn per load.
|
|
49
|
+
*/
|
|
50
|
+
export const HOST_TOOLBAR_PENDING_LIMIT = 128;
|
|
51
|
+
/**
|
|
52
|
+
* Subscribe the handshake channel and expose the page bridge. Call ONLY from
|
|
53
|
+
* a passing toolbar-runtime guard (`activateHostToolbarRuntime`) — a failing
|
|
54
|
+
* guard must leave zero footprint (no bridge key, no IPC listener).
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* Entry-waist channel validation, parity with the main side's
|
|
58
|
+
* `hostToolbar.onMessage` guard (same TypeError, message names `channel`).
|
|
59
|
+
* Runs BEFORE any state is touched (no queue slot, no registry entry), in
|
|
60
|
+
* both port states — a page author's typo throws at the call site instead of
|
|
61
|
+
* vanishing into main's silent inbound drop.
|
|
62
|
+
*/
|
|
63
|
+
function assertValidChannel(method, channel) {
|
|
64
|
+
if (typeof channel !== 'string' || channel === '') {
|
|
65
|
+
throw new TypeError(`diminaHostToolbar.${method}: channel must be a non-empty string`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function installHostToolbarPortBridge() {
|
|
69
|
+
let activePort = null;
|
|
70
|
+
const pending = [];
|
|
71
|
+
// One overflow warning per load (this installer runs once per document) —
|
|
72
|
+
// a runaway page send-loop must not get per-drop console spam.
|
|
73
|
+
let warnedPendingOverflow = false;
|
|
74
|
+
const handlers = [];
|
|
75
|
+
const dispatch = (data) => {
|
|
76
|
+
// Defensive symmetry with main: drop anything that is not an object
|
|
77
|
+
// envelope with a string channel — never throw in the dispatcher.
|
|
78
|
+
if (typeof data !== 'object' || data === null)
|
|
79
|
+
return;
|
|
80
|
+
const { channel, payload } = data;
|
|
81
|
+
if (typeof channel !== 'string')
|
|
82
|
+
return;
|
|
83
|
+
for (const entry of [...handlers]) {
|
|
84
|
+
if (entry.channel === channel)
|
|
85
|
+
entry.handler(payload);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const onPortMessage = (event) => {
|
|
89
|
+
dispatch(event.data);
|
|
90
|
+
};
|
|
91
|
+
ipcRenderer.on(ViewChannel.HostToolbarPort, (event) => {
|
|
92
|
+
const port = event.ports[0];
|
|
93
|
+
if (!port)
|
|
94
|
+
return;
|
|
95
|
+
// Same-load duplicate handshake: the LATER port wins. Main closed (or is
|
|
96
|
+
// about to close) its end of the old pair — detach and stop writing to it.
|
|
97
|
+
if (activePort) {
|
|
98
|
+
try {
|
|
99
|
+
activePort.removeEventListener('message', onPortMessage);
|
|
100
|
+
activePort.close();
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
/* already dead */
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
activePort = port;
|
|
107
|
+
// addEventListener (not onmessage) keeps the handler removable on
|
|
108
|
+
// re-handshake; it REQUIRES start() or inbound never delivers.
|
|
109
|
+
port.addEventListener('message', onPortMessage);
|
|
110
|
+
port.start();
|
|
111
|
+
// Flush sends issued before the port arrived, in order.
|
|
112
|
+
while (pending.length > 0) {
|
|
113
|
+
const envelope = pending.shift();
|
|
114
|
+
port.postMessage(envelope);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// EXACTLY { send, onMessage } — functions only; the port stays in the
|
|
118
|
+
// isolated world.
|
|
119
|
+
contextBridge.exposeInMainWorld(BRIDGE_KEY, {
|
|
120
|
+
send(channel, payload) {
|
|
121
|
+
assertValidChannel('send', channel);
|
|
122
|
+
const envelope = { channel, payload };
|
|
123
|
+
if (activePort) {
|
|
124
|
+
activePort.postMessage(envelope);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Bounded queue: drop the NEWEST send on overflow (FIFO first-comers
|
|
128
|
+
// survive), warn once per load, never throw into page code.
|
|
129
|
+
if (pending.length >= HOST_TOOLBAR_PENDING_LIMIT) {
|
|
130
|
+
if (!warnedPendingOverflow) {
|
|
131
|
+
warnedPendingOverflow = true;
|
|
132
|
+
console.warn(`[dimina-devtools] host-toolbar pending queue full (${HOST_TOOLBAR_PENDING_LIMIT}); ` +
|
|
133
|
+
'dropping further pre-handshake send() calls until the port arrives');
|
|
134
|
+
}
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
pending.push(envelope);
|
|
138
|
+
},
|
|
139
|
+
onMessage(channel, handler) {
|
|
140
|
+
assertValidChannel('onMessage', channel);
|
|
141
|
+
const entry = { channel, handler };
|
|
142
|
+
handlers.push(entry);
|
|
143
|
+
return () => {
|
|
144
|
+
const i = handlers.indexOf(entry);
|
|
145
|
+
if (i >= 0)
|
|
146
|
+
handlers.splice(i, 1);
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=host-toolbar-port.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-resident host-toolbar framework runtime: GUARD + ACTIVATION.
|
|
3
|
+
*
|
|
4
|
+
* The toolbar-runtime preload is registered on `session.defaultSession` via
|
|
5
|
+
* `registerPreloadScript({ type: 'frame', … })`, so it executes in EVERY
|
|
6
|
+
* defaultSession renderer — the main window, settings/popover overlays, and
|
|
7
|
+
* (with `nodeIntegrationInSubFrames`) even subframes. This module is the guard
|
|
8
|
+
* that keeps it inert everywhere except the host-toolbar WCV's main frame:
|
|
9
|
+
*
|
|
10
|
+
* - the toolbar WCV's creation injects `HOST_TOOLBAR_RUNTIME_MARKER` into its
|
|
11
|
+
* process argv via `webPreferences.additionalArguments`;
|
|
12
|
+
* - the marker is PROCESS-level (subframes of the toolbar window carry it
|
|
13
|
+
* too — spike .repro/wave3-spike/RESULTS.md item 3), so the guard needs
|
|
14
|
+
* BOTH wings: `isMainFrame` AND `argv.includes(marker)`;
|
|
15
|
+
* - a renderer that fails the guard returns immediately with ZERO footprint
|
|
16
|
+
* (no advertiser, no listeners, no globals — spike item 4).
|
|
17
|
+
*
|
|
18
|
+
* Why session-resident at all: the advertiser used to ride the toolbar WCV's
|
|
19
|
+
* `webPreferences.preload`, so a host calling `setPreloadPath(<its own
|
|
20
|
+
* preload>)` REPLACED it and the strip height collapsed to 0. With the runtime
|
|
21
|
+
* on the session layer, the host preload and the framework runtime coexist.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Pure guard predicate: should the toolbar runtime activate in a renderer with
|
|
25
|
+
* this `argv` / `isMainFrame`? True only for the MAIN frame of a process whose
|
|
26
|
+
* argv carries the `'--dimina-host-toolbar'` marker.
|
|
27
|
+
*/
|
|
28
|
+
export declare function shouldActivateHostToolbarRuntime(argv: readonly string[], isMainFrame: boolean): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Run the guard; only when it passes, install the height advertiser
|
|
31
|
+
* (`installHostToolbarAdvertiserWhenReady`) and the narrow-channel page
|
|
32
|
+
* bridge (`installHostToolbarPortBridge` — `window.diminaHostToolbar` +
|
|
33
|
+
* the MessagePort handshake listener). Returns whether the runtime
|
|
34
|
+
* activated. A failed guard installs NOTHING (zero footprint in non-toolbar
|
|
35
|
+
* windows and subframes: no advertiser, no bridge key, no IPC listener).
|
|
36
|
+
*/
|
|
37
|
+
export declare function activateHostToolbarRuntime(env: {
|
|
38
|
+
argv: readonly string[];
|
|
39
|
+
isMainFrame: boolean;
|
|
40
|
+
}): boolean;
|
|
41
|
+
//# sourceMappingURL=host-toolbar-runtime.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-resident host-toolbar framework runtime: GUARD + ACTIVATION.
|
|
3
|
+
*
|
|
4
|
+
* The toolbar-runtime preload is registered on `session.defaultSession` via
|
|
5
|
+
* `registerPreloadScript({ type: 'frame', … })`, so it executes in EVERY
|
|
6
|
+
* defaultSession renderer — the main window, settings/popover overlays, and
|
|
7
|
+
* (with `nodeIntegrationInSubFrames`) even subframes. This module is the guard
|
|
8
|
+
* that keeps it inert everywhere except the host-toolbar WCV's main frame:
|
|
9
|
+
*
|
|
10
|
+
* - the toolbar WCV's creation injects `HOST_TOOLBAR_RUNTIME_MARKER` into its
|
|
11
|
+
* process argv via `webPreferences.additionalArguments`;
|
|
12
|
+
* - the marker is PROCESS-level (subframes of the toolbar window carry it
|
|
13
|
+
* too — spike .repro/wave3-spike/RESULTS.md item 3), so the guard needs
|
|
14
|
+
* BOTH wings: `isMainFrame` AND `argv.includes(marker)`;
|
|
15
|
+
* - a renderer that fails the guard returns immediately with ZERO footprint
|
|
16
|
+
* (no advertiser, no listeners, no globals — spike item 4).
|
|
17
|
+
*
|
|
18
|
+
* Why session-resident at all: the advertiser used to ride the toolbar WCV's
|
|
19
|
+
* `webPreferences.preload`, so a host calling `setPreloadPath(<its own
|
|
20
|
+
* preload>)` REPLACED it and the strip height collapsed to 0. With the runtime
|
|
21
|
+
* on the session layer, the host preload and the framework runtime coexist.
|
|
22
|
+
*/
|
|
23
|
+
import { HOST_TOOLBAR_RUNTIME_MARKER } from '../../shared/constants.js';
|
|
24
|
+
import { installHostToolbarAdvertiserWhenReady } from './host-toolbar-advertiser.js';
|
|
25
|
+
import { installHostToolbarPortBridge } from './host-toolbar-port.js';
|
|
26
|
+
/**
|
|
27
|
+
* Pure guard predicate: should the toolbar runtime activate in a renderer with
|
|
28
|
+
* this `argv` / `isMainFrame`? True only for the MAIN frame of a process whose
|
|
29
|
+
* argv carries the `'--dimina-host-toolbar'` marker.
|
|
30
|
+
*/
|
|
31
|
+
export function shouldActivateHostToolbarRuntime(argv, isMainFrame) {
|
|
32
|
+
return isMainFrame && argv.includes(HOST_TOOLBAR_RUNTIME_MARKER);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Run the guard; only when it passes, install the height advertiser
|
|
36
|
+
* (`installHostToolbarAdvertiserWhenReady`) and the narrow-channel page
|
|
37
|
+
* bridge (`installHostToolbarPortBridge` — `window.diminaHostToolbar` +
|
|
38
|
+
* the MessagePort handshake listener). Returns whether the runtime
|
|
39
|
+
* activated. A failed guard installs NOTHING (zero footprint in non-toolbar
|
|
40
|
+
* windows and subframes: no advertiser, no bridge key, no IPC listener).
|
|
41
|
+
*/
|
|
42
|
+
export function activateHostToolbarRuntime(env) {
|
|
43
|
+
if (!shouldActivateHostToolbarRuntime(env.argv, env.isMainFrame))
|
|
44
|
+
return false;
|
|
45
|
+
installHostToolbarAdvertiserWhenReady();
|
|
46
|
+
installHostToolbarPortBridge();
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=host-toolbar-runtime.js.map
|