fix(agent-browser): bound crashed preview cleanup

This commit is contained in:
2026-08-27 03:01:59 +08:00
parent 23c49aa3d2
commit c52a559b46
3 changed files with 146 additions and 10 deletions

View File

@@ -36,6 +36,7 @@ const DEFAULT_CDP_TIMEOUT_MS = 10_000;
const MAX_CDP_TIMEOUT_MS = 30_000;
const OPEN_TIMEOUT_MS = 30_000;
const RENDERER_PRIME_URL = 'about:blank';
const PREVIEW_CLEANUP_TIMEOUT_MS = 1_000;
const PUBLISH_PREFLIGHT_TIMEOUT_MS = 30_000;
const PUBLISH_PREFLIGHT_SETTLE_MS = 500;
const PUBLISH_PREFLIGHT_VIEWPORTS = [
@@ -927,21 +928,17 @@ export class AgentBrowserModule {
record.previewDataRequested = false;
const scripts = binding.scripts.splice(0);
await Promise.all(scripts.map(async ({ identifier, sessionRef }) => {
try {
await record.view.webContents.debugger.sendCommand(
await bestEffortDebuggerCommand(() => record.view.webContents.debugger.sendCommand(
'Page.removeScriptToEvaluateOnNewDocument',
{ identifier },
sessionRef,
);
} catch {
// The debugger or child target may already be detached.
}
));
if (sessionRef) {
await record.view.webContents.debugger.sendCommand(
await bestEffortDebuggerCommand(() => record.view.webContents.debugger.sendCommand(
'Runtime.runIfWaitingForDebugger',
undefined,
sessionRef,
).catch(() => undefined);
));
}
}));
if (
@@ -949,11 +946,11 @@ export class AgentBrowserModule {
&& !record.view.webContents.isDestroyed()
&& record.view.webContents.debugger.isAttached()
) {
await record.view.webContents.debugger.sendCommand('Target.setAutoAttach', {
await bestEffortDebuggerCommand(() => record.view.webContents.debugger.sendCommand('Target.setAutoAttach', {
autoAttach: true,
waitForDebuggerOnStart: false,
flatten: true,
}).catch(() => undefined);
}));
}
if (record.previewData === binding) record.previewData = undefined;
})();
@@ -1994,6 +1991,20 @@ function delay(milliseconds: number): Promise<void> {
});
}
async function bestEffortDebuggerCommand(operation: () => Promise<unknown>): Promise<void> {
let timer: ReturnType<typeof setTimeout> | undefined;
try {
await Promise.race([
Promise.resolve().then(operation).catch(() => undefined),
new Promise<void>((resolvePromise) => {
timer = setTimeout(resolvePromise, PREVIEW_CLEANUP_TIMEOUT_MS);
}),
]);
} finally {
if (timer) clearTimeout(timer);
}
}
function isTimeoutError(error: unknown): boolean {
return error instanceof Error && error.message === 'PUBLISH_PREFLIGHT_TIMEOUT';
}