mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-24 05:22:22 +02:00
[eric] electron+e2e: close the init-script race - main reads OPENSWARM_E2E env on startup and appends an --openswarm-e2e chromium switch, preload reads the switch BEFORE any page script parses and contextBridge-exposes __OPENSWARM_E2E__=true so the production store-on-window gate fires deterministically rather than racing addInitScript against bundle parse
This commit is contained in:
+11
-6
@@ -79,12 +79,17 @@ export function hasAnyProviderKey(): boolean {
|
||||
|
||||
export async function launchApp(): Promise<ElectronApplication> {
|
||||
seedTestUserIfClean();
|
||||
const app = await electron.launch({ executablePath: packagedAppPath(), args: [] });
|
||||
// The frontend bundle gates `__OPENSWARM_STORE__` exposure on
|
||||
// `__OPENSWARM_E2E__` being truthy at module-load time. Adding an init
|
||||
// script BEFORE the main page navigates guarantees the flag is set before
|
||||
// bundle.js parses, so specs that read the Redux store directly work
|
||||
// against the production build.
|
||||
// OPENSWARM_E2E=1 is read by electron/main.js BEFORE the renderer launches; it
|
||||
// appends a Chromium switch the preload reads to set window.__OPENSWARM_E2E__
|
||||
// before bundle.js parses, so the production store-on-window gate fires
|
||||
// deterministically (no addInitScript race).
|
||||
const app = await electron.launch({
|
||||
executablePath: packagedAppPath(),
|
||||
args: [],
|
||||
env: { ...process.env, OPENSWARM_E2E: '1' },
|
||||
});
|
||||
// Belt-and-braces: addInitScript ALSO sets the flag in case a future Electron
|
||||
// changes the cmdline propagation. If either path works, the spec succeeds.
|
||||
try { await app.context().addInitScript({ content: '(window).__OPENSWARM_E2E__ = true;' }); } catch { /* best effort */ }
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
const { app, components, BrowserWindow, ipcMain, shell, session, dialog, crashReporter } = require('electron');
|
||||
|
||||
// E2E flag: when OPENSWARM_E2E=1, append a Chromium command-line switch the
|
||||
// renderer reads at startup to set window.__OPENSWARM_E2E__ = true BEFORE any
|
||||
// page script parses, so the production-build store-on-window gate fires
|
||||
// deterministically. Normal user launches never set the env var so this is a
|
||||
// no-op for them; only Playwright's electron.launch({env}) flips it on.
|
||||
if (process.env.OPENSWARM_E2E === '1') {
|
||||
try { app.commandLine.appendSwitch('openswarm-e2e', '1'); } catch {}
|
||||
}
|
||||
|
||||
// Local-only crash reporter. Captures native renderer crashes that escape JS-level error handlers and don't otherwise surface in Crashpad. uploadToServer=false keeps minidumps on disk under %APPDATA%/OpenSwarm/Crashpad so we can inspect them post-mortem without sending anywhere.
|
||||
try {
|
||||
crashReporter.start({
|
||||
|
||||
@@ -3,6 +3,17 @@ const { contextBridge, ipcRenderer } = require('electron');
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][preload] start, ua=', navigator.userAgent);
|
||||
|
||||
// E2E gate: set the renderer flag BEFORE any page script parses so the
|
||||
// production-build store-on-window expose fires deterministically when
|
||||
// Playwright launches with OPENSWARM_E2E=1. Read from the Chromium switch
|
||||
// the main process appended; no-op for normal user launches.
|
||||
try {
|
||||
const args = (typeof process !== 'undefined' && process.argv) ? process.argv : [];
|
||||
if (args.some((a) => /--openswarm-e2e(=1)?$/.test(a))) {
|
||||
contextBridge.exposeInMainWorld('__OPENSWARM_E2E__', true);
|
||||
}
|
||||
} catch (e) { console.log('[diag][preload] e2e-flag setup failed:', e && e.message); }
|
||||
|
||||
// Synchronous exposure. The previous async IIFE (await ipcRenderer.invoke) raced React mount: any code reading window.openswarm during the gap (BrowserCard's Electron-detection falling back to iframe mode, AgentChat's auth-token call throwing) saw undefined. sendSync blocks the renderer for one IPC round-trip during preload before any user-visible paint, so window.openswarm is guaranteed to exist before the first frontend bundle evaluates.
|
||||
const port = ipcRenderer.sendSync('get-backend-port-sync');
|
||||
const webviewPreloadPath = ipcRenderer.sendSync('get-webview-preload-path-sync');
|
||||
|
||||
Reference in New Issue
Block a user