You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixed by #2523. Synthetic root navigations (about:blank, blob:) went through Session.initiateRootNavigation, which allocates a pending Page that is only promoted to active when HTTP response headers arrive (frameHeaderDoneCallback). about:blank makes no HTTP request, so the pending Page was never committed and the previous document stayed active. The fix routes synthetic URLs to the immediate-swap path (replaceRootImmediate) instead. The "Likely fix location" called out below was correct.
Summary
Page.navigate("about:blank") issued against a tab that's currently on a non-blank document fires the entire navigation event sequence (frameStartedNavigating, executionContextsCleared, frameNavigated, executionContextCreated, domContentEventFired, loadEventFired, frameStoppedLoading) but doesn't actually replace the document. After the events settle, window.location.href, document.URL, document.body.innerHTML, and Page.getFrameTree's main-frame URL all still report the previous page. Plain http→http navigation works correctly; the regression is specific to about:blank as a destination.
The behavior changed between build 6005 (HEAD 0420802f, public nightly 2026-05-04 03:44 UTC) and build 6051 (HEAD d360fcc0, public nightly 2026-05-05 ~03:30 UTC). The most plausible suspect is #2297 (replacement of replacePage with Session.initiateRootNavigation + the pending-pages model, merged 2026-05-04) — the new model creates a pending page for the about:blank navigation but never seems to commit it to active.
Today's behavior
sequenceDiagram
participant Client as CDP Client
participant LP as Lightpanda
participant Frame as main frame
Client->>LP: Page.navigate(http://example/)
LP->>Frame: navigate
Frame-->>LP: load complete
LP-->>Client: Page.loadEventFired
Client->>LP: Runtime.evaluate(window.location.href)
LP-->>Client: "http://example/" ✓
Client->>LP: Page.navigate(about:blank)
LP->>Frame: initiateRootNavigation pending
Frame-->>LP: events fire (frameNavigated x2, executionContextCreated, loadEventFired)
LP-->>Client: Page.loadEventFired
Client->>LP: Runtime.evaluate(window.location.href)
LP-->>Client: "http://example/" ✗ pending page never replaced active
Loading
Expected behavior
Per the HTML Living Standard navigation algorithm and Chrome behavior, Page.navigate("about:blank") should replace the active document with a fresh empty about:blank document. After loadEventFired, window.location.href should be "about:blank" and document.body should be empty.
sequenceDiagram
participant Client as CDP Client
participant LP as Lightpanda
participant Frame as main frame
Client->>LP: Page.navigate(about:blank)
LP->>Frame: replace with about:blank
Frame-->>LP: load complete
LP-->>Client: Page.loadEventFired
Client->>LP: Runtime.evaluate(window.location.href)
LP-->>Client: "about:blank" ✓
Loading
Reproducer
Self-contained Node script. Requires Node >= 22 (built-in WebSocket) and a running lightpanda serve --host 127.0.0.1 --port 9876. No external npm deps.
Run (with lightpanda serve --host 127.0.0.1 --port 9876 running in another terminal):
node aboutblank-repro.mjs
Today against build 6051: prints
After Page.navigate(http://127.0.0.1:NNNN/):
{"url":"http://127.0.0.1:NNNN/","body":"<h1>PAGE-A</h1>"}
After Page.navigate("about:blank"):
{"url":"http://127.0.0.1:NNNN/","body":"<h1>PAGE-A</h1>"}
expected: {"url":"about:blank","body":""}
FAIL (regression — page was not replaced)
and exits 1.
Expected after the fix: prints "url":"about:blank","body":"" and exits 0.
works correctly — about:blank navigation replaces the page
d360fcc0 (current main)
6051
broken — events fire, document not replaced
Validation of the 6005 baseline came from running the consumer's existing test suite (capybara-lightpanda's Driver#reset spec, which calls Page.navigate("about:blank") and then asserts window.location.href === "about:blank") against the public nightly that was at HEAD 0420802f — it passed there and breaks at HEAD d360fcc0. http→http navigation works on both builds.
Likely fix location
src/browser/Session.zig — initiateRootNavigation / pending-pages plumbing introduced by #2297. The pending page for the about:blank navigation appears to be created and torn down (its executionContextCreated fires) without ever being promoted to the active page, leaving the previous active document in place. Worth checking the special-casing of about:blank URLs in the new pending-pages flow — Chrome's about:blank handling is typically synchronous-ish and may not match the new pending-pages assumption that the navigation flows through the network stack.
Environment
Lightpanda: 1.0.0-nightly.6051+d360fcc0 (current public nightly, downloaded 2026-05-05) and 1.0.0-dev.6024+d360fcc0 (locally built from main HEAD)
OS: macOS aarch64 (darwin)
CDP client: Node 25 built-in WebSocket (no npm deps)
Note
Fixed by #2523. Synthetic root navigations (
about:blank,blob:) went throughSession.initiateRootNavigation, which allocates a pending Page that is only promoted to active when HTTP response headers arrive (frameHeaderDoneCallback).about:blankmakes no HTTP request, so the pending Page was never committed and the previous document stayed active. The fix routes synthetic URLs to the immediate-swap path (replaceRootImmediate) instead. The "Likely fix location" called out below was correct.Summary
Page.navigate("about:blank")issued against a tab that's currently on a non-blank document fires the entire navigation event sequence (frameStartedNavigating,executionContextsCleared,frameNavigated,executionContextCreated,domContentEventFired,loadEventFired,frameStoppedLoading) but doesn't actually replace the document. After the events settle,window.location.href,document.URL,document.body.innerHTML, andPage.getFrameTree's main-frame URL all still report the previous page. Plain http→http navigation works correctly; the regression is specific toabout:blankas a destination.The behavior changed between build 6005 (HEAD
0420802f, public nightly 2026-05-04 03:44 UTC) and build 6051 (HEADd360fcc0, public nightly 2026-05-05 ~03:30 UTC). The most plausible suspect is #2297 (replacement ofreplacePagewithSession.initiateRootNavigation+ the pending-pages model, merged 2026-05-04) — the new model creates a pending page for the about:blank navigation but never seems to commit it to active.Today's behavior
sequenceDiagram participant Client as CDP Client participant LP as Lightpanda participant Frame as main frame Client->>LP: Page.navigate(http://example/) LP->>Frame: navigate Frame-->>LP: load complete LP-->>Client: Page.loadEventFired Client->>LP: Runtime.evaluate(window.location.href) LP-->>Client: "http://example/" ✓ Client->>LP: Page.navigate(about:blank) LP->>Frame: initiateRootNavigation pending Frame-->>LP: events fire (frameNavigated x2, executionContextCreated, loadEventFired) LP-->>Client: Page.loadEventFired Client->>LP: Runtime.evaluate(window.location.href) LP-->>Client: "http://example/" ✗ pending page never replaced activeExpected behavior
Per the HTML Living Standard navigation algorithm and Chrome behavior,
Page.navigate("about:blank")should replace the active document with a fresh emptyabout:blankdocument. AfterloadEventFired,window.location.hrefshould be"about:blank"anddocument.bodyshould be empty.sequenceDiagram participant Client as CDP Client participant LP as Lightpanda participant Frame as main frame Client->>LP: Page.navigate(about:blank) LP->>Frame: replace with about:blank Frame-->>LP: load complete LP-->>Client: Page.loadEventFired Client->>LP: Runtime.evaluate(window.location.href) LP-->>Client: "about:blank" ✓Reproducer
Self-contained Node script. Requires Node >= 22 (built-in
WebSocket) and a runninglightpanda serve --host 127.0.0.1 --port 9876. No external npm deps.aboutblank-repro.mjs:Run (with
lightpanda serve --host 127.0.0.1 --port 9876running in another terminal):Today against build 6051: prints
and exits 1.
Expected after the fix: prints
"url":"about:blank","body":""and exits 0.Bisect
0420802f(just before #2297)about:blanknavigation replaces the paged360fcc0(current main)Validation of the 6005 baseline came from running the consumer's existing test suite (capybara-lightpanda's
Driver#resetspec, which callsPage.navigate("about:blank")and then assertswindow.location.href === "about:blank") against the public nightly that was at HEAD0420802f— it passed there and breaks at HEADd360fcc0. http→http navigation works on both builds.Likely fix location
src/browser/Session.zig—initiateRootNavigation/ pending-pages plumbing introduced by #2297. The pending page for theabout:blanknavigation appears to be created and torn down (itsexecutionContextCreatedfires) without ever being promoted to the active page, leaving the previous active document in place. Worth checking the special-casing ofabout:blankURLs in the new pending-pages flow — Chrome's about:blank handling is typically synchronous-ish and may not match the new pending-pages assumption that the navigation flows through the network stack.Environment
1.0.0-nightly.6051+d360fcc0(current public nightly, downloaded 2026-05-05) and1.0.0-dev.6024+d360fcc0(locally built from main HEAD)WebSocket(no npm deps)