From 7b25049deefe4415c5e86a557c8d8de8185d12ab Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Tue, 27 Oct 2026 11:24:09 +0800 Subject: [PATCH] refactor(browser): centralize passive source deadlines --- src/browser/CdpElectronScripts.ts | 64 ++++++------------------- src/browser/CdpPageCaptureScripts.ts | 69 +++++---------------------- src/browser/CdpScriptSourceCapture.ts | 52 ++++++++++++-------- 3 files changed, 60 insertions(+), 125 deletions(-) diff --git a/src/browser/CdpElectronScripts.ts b/src/browser/CdpElectronScripts.ts index eb2e5ec023..0e7aa45333 100644 --- a/src/browser/CdpElectronScripts.ts +++ b/src/browser/CdpElectronScripts.ts @@ -17,10 +17,7 @@ import { authorizedElectronFile } from "./ElectronFileScope.js"; import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js"; import { AnalysisCancelledError } from "../domain/analysisErrorCore.js"; import { selectedCdpCommandTimeoutMs } from "../domain/browserDeadline.js"; -import { - cdpScriptSourceDeadlineOmissionReason, - CdpScriptSourceBudget, -} from "./CdpScriptSourceBudget.js"; +import { CdpScriptSourceBudget } from "./CdpScriptSourceBudget.js"; interface ElectronScriptCaptureInput { readonly connection: CdpConnection; @@ -46,8 +43,6 @@ export const captureElectronScripts = async ( const commandTimeoutMs = selectedCdpCommandTimeoutMs( input.request.command_timeout_ms, ); - const deadlineOmission = - cdpScriptSourceDeadlineOmissionReason(commandTimeoutMs); const sourceBudget = input.request.include_script_sources && input.scripts.length > 0 ? new CdpScriptSourceBudget(input.signal, commandTimeoutMs) @@ -102,44 +97,21 @@ export const captureElectronScripts = async ( seen.add(scriptKey); metadataBytes += retainedBytes; total += 1; - let source: ElectronPageInspection["scripts"]["items"][number]["source"] = - input.request.include_script_sources + const source = + sourceBudget === undefined ? { - included: false, - reason: deadlineOmission, - } - : { - included: false, + included: false as const, reason: "source capture was not selected", - }; - if ( - input.request.include_script_sources && - isSourceDeadlineExpired(sourceBudget) - ) { - excludeScriptSource(input.completeness); - } else if ( - input.request.include_script_sources && - sourceBudget !== undefined - ) { - try { - source = await capturePassiveCdpScriptSource({ - connection: input.connection, - sessionId: input.sessionId, - signal: input.signal, - operation: "inspect_electron_page", - scriptId: script.scriptId, - sourceBudget, - completeness: input.completeness, - }); - } catch (cause: unknown) { - throwIfCallerCancelled(input.signal); - if (isSourceDeadlineExpired(sourceBudget)) { - excludeScriptSource(input.completeness); - } else { - throw cause; - } - } - } + } + : await capturePassiveCdpScriptSource({ + connection: input.connection, + sessionId: input.sessionId, + signal: input.signal, + operation: "inspect_electron_page", + scriptId: script.scriptId, + sourceBudget, + completeness: input.completeness, + }); items.push({ script_key: scriptKey, ...identity, source }); } } finally { @@ -155,17 +127,9 @@ export const captureElectronScripts = async ( }; }; -const excludeScriptSource = (completeness: CdpCaptureCompleteness): void => { - completeness.exclude("script_sources", "resource_budget_exhausted"); -}; - const throwIfCallerCancelled = (signal: AbortSignal | undefined): void => { if (signal?.aborted === true) throw new AnalysisCancelledError("inspect_electron_page", { cause: signal.reason, }); }; - -const isSourceDeadlineExpired = ( - sourceBudget: CdpScriptSourceBudget | undefined, -): boolean => sourceBudget?.timedOut === true; diff --git a/src/browser/CdpPageCaptureScripts.ts b/src/browser/CdpPageCaptureScripts.ts index 7db3a3cac4..7e8507e704 100644 --- a/src/browser/CdpPageCaptureScripts.ts +++ b/src/browser/CdpPageCaptureScripts.ts @@ -11,13 +11,8 @@ import { capturePassiveCdpScriptSource } from "./CdpScriptSourceCapture.js"; import type { CaptureContext } from "./CdpPageCapture.js"; import type { WebSourceMapRequest } from "./WebSourceMapFetcher.js"; import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js"; -import { AnalysisCancelledError } from "../domain/analysisErrorCore.js"; -import type { BrowserObservationOperation } from "../domain/browserObservationErrors.js"; import { selectedCdpCommandTimeoutMs } from "../domain/browserDeadline.js"; -import { - cdpScriptSourceDeadlineOmissionReason, - CdpScriptSourceBudget, -} from "./CdpScriptSourceBudget.js"; +import { CdpScriptSourceBudget } from "./CdpScriptSourceBudget.js"; export interface CapturedScripts { readonly inventory: WebPageInspection["scripts"]; @@ -63,8 +58,6 @@ export const captureScripts = async ( const commandTimeoutMs = selectedCdpCommandTimeoutMs( context.input.command_timeout_ms, ); - const deadlineOmission = - cdpScriptSourceDeadlineOmissionReason(commandTimeoutMs); const sourceBudget = context.input.include_script_sources && scripts.size > 0 ? new CdpScriptSourceBudget(context.signal, commandTimeoutMs) @@ -80,42 +73,18 @@ export const captureScripts = async ( resources, ), }; - let source: WebPageInspection["scripts"]["items"][number]["source"] = - context.input.include_script_sources - ? sourceExcluded(deadlineOmission) - : sourceExcluded("source capture was not selected"); - if ( - context.input.include_script_sources && - isSourceDeadlineExpired(sourceBudget) - ) { - events.completeness.exclude( - "script_sources", - "resource_budget_exhausted", - ); - } else if ( - context.input.include_script_sources && - sourceBudget !== undefined - ) { - try { - source = await capturePassiveCdpScriptSource({ - connection: context.connection, - sessionId: context.sessionId, - signal: context.signal, - operation: context.operation, - scriptId: script.scriptId, - sourceBudget, - completeness: events.completeness, - }); - } catch (cause: unknown) { - throwIfCallerCancelled(context.signal, context.operation); - if (isSourceDeadlineExpired(sourceBudget)) - events.completeness.exclude( - "script_sources", - "resource_budget_exhausted", - ); - else throw cause; - } - } + const source = + sourceBudget === undefined + ? sourceExcluded("source capture was not selected") + : await capturePassiveCdpScriptSource({ + connection: context.connection, + sessionId: context.sessionId, + signal: context.signal, + operation: context.operation, + scriptId: script.scriptId, + sourceBudget, + completeness: events.completeness, + }); drafts.push(buildScriptDraft(script, state, source)); } } finally { @@ -172,18 +141,6 @@ const buildScriptDraft = ( }; }; -const throwIfCallerCancelled = ( - signal: AbortSignal | undefined, - operation: BrowserObservationOperation, -): void => { - if (signal?.aborted === true) - throw new AnalysisCancelledError(operation, { cause: signal.reason }); -}; - -const isSourceDeadlineExpired = ( - sourceBudget: CdpScriptSourceBudget | undefined, -): boolean => sourceBudget?.timedOut === true; - const keyAndBuildInventory = ( drafts: readonly { readonly item: ScriptDraftItem; diff --git a/src/browser/CdpScriptSourceCapture.ts b/src/browser/CdpScriptSourceCapture.ts index 87058bffe5..ab4698d08d 100644 --- a/src/browser/CdpScriptSourceCapture.ts +++ b/src/browser/CdpScriptSourceCapture.ts @@ -25,25 +25,39 @@ export const capturePassiveCdpScriptSource = async (input: { }): Promise< ReturnType | ReturnType > => { - const response = await input.connection.send( - "Debugger.getScriptSource", - { scriptId: input.scriptId }, - input.sessionId, - input.sourceBudget.signal, - ); - if (input.signal?.aborted === true) - throw new AnalysisCancelledError(input.operation, { - cause: input.signal.reason, - }); - const text = requiredScriptSource(response, input.operation); - const reason = input.sourceBudget.timedOut - ? cdpScriptSourceDeadlineOmissionReason(input.sourceBudget.commandTimeoutMs) - : !input.sourceBudget.admit(text) - ? CDP_SCRIPT_SOURCE_BYTES_OMISSION_REASON - : undefined; - if (reason !== undefined) { + const omitForBudget = () => { input.completeness.exclude("script_sources", "resource_budget_exhausted"); - return sourceExcluded(reason); + return sourceExcluded( + input.sourceBudget.timedOut + ? cdpScriptSourceDeadlineOmissionReason( + input.sourceBudget.commandTimeoutMs, + ) + : CDP_SCRIPT_SOURCE_BYTES_OMISSION_REASON, + ); + }; + const throwIfCancelled = () => { + if (input.signal?.aborted === true) + throw new AnalysisCancelledError(input.operation, { + cause: input.signal.reason, + }); + }; + throwIfCancelled(); + if (input.sourceBudget.timedOut) return omitForBudget(); + try { + const response = await input.connection.send( + "Debugger.getScriptSource", + { scriptId: input.scriptId }, + input.sessionId, + input.sourceBudget.signal, + ); + throwIfCancelled(); + const text = requiredScriptSource(response, input.operation); + if (input.sourceBudget.timedOut || !input.sourceBudget.admit(text)) + return omitForBudget(); + return sourceResult(text); + } catch (cause: unknown) { + throwIfCancelled(); + if (input.sourceBudget.timedOut) return omitForBudget(); + throw cause; } - return sourceResult(text); };