From 1f9a663e259a46f99cfb20fb0abde05268904b0c Mon Sep 17 00:00:00 2001 From: "R.D." Date: Mon, 8 Jun 2026 20:45:27 -0400 Subject: [PATCH 1/2] fix(browser): avoid bundling optional cloakbrowser import --- open-sse/services/browserPool.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/open-sse/services/browserPool.ts b/open-sse/services/browserPool.ts index 9523edc912b7..ccde38b5d7c7 100644 --- a/open-sse/services/browserPool.ts +++ b/open-sse/services/browserPool.ts @@ -78,11 +78,15 @@ const state: PoolState = { cloakLaunchResolved: false, }; +function getCloakbrowserModuleId(): string { + return ["cloak", "browser"].join(""); +} + async function resolveCloakLaunch(): Promise<((opts: unknown) => Promise) | null> { if (state.cloakLaunchResolved) return state.cloakLaunch; state.cloakLaunchResolved = true; try { - const mod = (await import("cloakbrowser")) as unknown as { + const mod = (await import(getCloakbrowserModuleId())) as unknown as { launch?: (opts: unknown) => Promise; }; state.cloakLaunch = mod.launch ?? null; @@ -110,7 +114,12 @@ function evictStaleContexts(): void { const now = Date.now(); for (const [key, pooled] of state.contexts) { if (now - pooled.lastUsed > CONTEXT_TTL_MS) { - console.log("[BrowserPool] Evicted stale context:", key, "(idle", ((now - pooled.lastUsed) / 1000).toFixed(0) + "s)"); + console.log( + "[BrowserPool] Evicted stale context:", + key, + "(idle", + ((now - pooled.lastUsed) / 1000).toFixed(0) + "s)" + ); state.contexts.delete(key); pooled.context.close().catch(() => {}); } From 3e2fcca1202f7cec2dcb8735dad7edb733e2c94a Mon Sep 17 00:00:00 2001 From: "R.D." Date: Mon, 8 Jun 2026 20:50:39 -0400 Subject: [PATCH 2/2] test(browser): cover optional cloakbrowser import --- open-sse/services/browserPool.ts | 2 ++ .../unit/browser-pool-optional-import.test.ts | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/unit/browser-pool-optional-import.test.ts diff --git a/open-sse/services/browserPool.ts b/open-sse/services/browserPool.ts index ccde38b5d7c7..e72862e8057e 100644 --- a/open-sse/services/browserPool.ts +++ b/open-sse/services/browserPool.ts @@ -79,6 +79,8 @@ const state: PoolState = { }; function getCloakbrowserModuleId(): string { + // Keep this computed: cloakbrowser is an optional runtime enhancer, and a literal + // dynamic import with the package name makes Turbopack resolve it during route compilation. return ["cloak", "browser"].join(""); } diff --git a/tests/unit/browser-pool-optional-import.test.ts b/tests/unit/browser-pool-optional-import.test.ts new file mode 100644 index 000000000000..2e9f68390f89 --- /dev/null +++ b/tests/unit/browser-pool-optional-import.test.ts @@ -0,0 +1,27 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import path from "node:path"; +import { describe, it } from "node:test"; +import { fileURLToPath } from "node:url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const REPO_ROOT = path.resolve(__dirname, "../.."); +const BROWSER_POOL_PATH = path.join(REPO_ROOT, "open-sse/services/browserPool.ts"); + +describe("browserPool optional cloakbrowser import", () => { + it("keeps cloakbrowser out of static dynamic import resolution", () => { + const source = readFileSync(BROWSER_POOL_PATH, "utf8"); + + assert.equal( + /import\(\s*["']cloakbrowser["']\s*\)/.test(source), + false, + "cloakbrowser must remain runtime-optional; static dynamic import triggers Turbopack resolution" + ); + assert.match( + source, + /Turbopack resolve it during route compilation/, + "the computed import rationale should stay documented near the helper" + ); + assert.match(source, /return \["cloak", "browser"\]\.join\(""\);/); + }); +});