fix(browser): raise script-execution budget so heavy SPAs boot (#371)

The script-execution phase had a 10s soft deadline. On a heavy SPA the
remaining scripts were skipped before the app finished booting, so it
never fired its XHR/fetch calls and page.on('response') captured zero API
responses (issue #361). The knob to extend it, OBSCURA_SCRIPT_DEADLINE_MS,
existed but was undocumented, so it was undiscoverable.

Raise the default to 30s and document the env var. Only pages that keep
running past the deadline are affected; fast pages finish and return well
before it, so the larger budget costs them nothing, and the per-phase
watchdog (armed at deadline + 1s) still bounds a real synchronous hang.
Very heavy SPAs on slow networks can raise it further with
OBSCURA_SCRIPT_DEADLINE_MS, paired with a matching client nav timeout.

Fixes #361.
This commit is contained in:
SGavrl authored and GitHub committed 2026-07-09 11:07:34 +02:00
1 parent f5d7e11692
commit fa9ba7f13d
2 files changed
+20 -3

No files matched your search

+12 -3
View File
@@ -369,12 +369,21 @@ impl Page {
let document_base = self.resolve_base_url();
// Soft deadline on the entire script-execution phase. Heavy SPAs
// (GitHub, Linear, CodeSandbox) ship 50+ scripts and our serial
// fetch + execute loop can blow past a 25s Puppeteer goto timeout.
// Override via OBSCURA_SCRIPT_DEADLINE_MS for slow networks.
// fetch + execute loop can blow past a Puppeteer/Playwright goto
// timeout. The old 10s default was too tight: a heavy React/Vue/Angular
// SPA had its remaining scripts skipped before the app booted, so it
// never fired its XHR/fetch calls and page.on('response') saw nothing
// (issue #361). Only pages that actually run past the deadline are
// affected; fast pages finish and return well before it, so a larger
// budget costs them nothing. 30s gives an app room to initialize while
// the per-phase watchdog (armed at this + 1s) still bounds a real
// synchronous hang. Raise it further with OBSCURA_SCRIPT_DEADLINE_MS=<ms>
// for very heavy SPAs on slow networks (pair it with a matching client
// navigation timeout).
let script_deadline_ms: u64 = std::env::var("OBSCURA_SCRIPT_DEADLINE_MS")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(10_000);
.unwrap_or(30_000);
let script_deadline = tokio::time::Instant::now()
+ tokio::time::Duration::from_millis(script_deadline_ms);