fix(browser): avoid bundling optional cloakbrowser import (#3460)

Integrated into release/v3.8.17
This commit is contained in:
Randi
2026-06-08 22:34:07 -04:00
committed by GitHub
parent 4f38167964
commit 49c11f0cea
2 changed files with 40 additions and 2 deletions

View File

@@ -78,11 +78,17 @@ const state: PoolState = {
cloakLaunchResolved: false,
};
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("");
}
async function resolveCloakLaunch(): Promise<((opts: unknown) => Promise<Browser>) | 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<Browser>;
};
state.cloakLaunch = mod.launch ?? null;
@@ -110,7 +116,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(() => {});
}

View File

@@ -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\(""\);/);
});
});