mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-31 17:55:59 -04:00
Replaces the 1 (+1 inflight) page design of session for an unlimited number of pages. The main goal is to support a more efficient async goto (1). Without this commit, async goto has two implementation: multiple browser, which is resource intensive (thread + isolate per page), bolting it onto sub-frames (like iframe or popups). The issue with the 2nd version (which I originally suggested) is that most resources are tied to the Page. So even if an async goto "page" (which would map to a Frame) is released, most things stay in memory, including the DOM (page.factory) and the V8::Context. This new approach adds multiple page support to sessions. The advantage is pretty clear: the existing memory model (page-tied resources) becomes a strength of the design, rather than a weakness. This change is not tirivla, but the diff is inflated by 2 large mechanial changes, so it isn't _that_ big either. That said, I'd divide this into four parts. 1 - The old concept of _active/_pending is now baked into the Page itself. A Page has a `replaces: ?*Page = null` and `replacement: ?*Page = null` field. 2 - Because of #1 above, the Session now just has an `pages: ArrayList(*Page)`. As much as possible, single-page APIs, like `removePage` no longer exists. We're trying to present a consistent multi-page API. See #3. 3 - References to *Page and *Frame have always been dangerous. For example, `lightpanda.fetch` has a block to scope `frame`: ```zig { const frame = try session.createPage(); // frame isn't safe to use after navigate, it can be swapped out _ = try frame.navigate(...) } ``` While we still hand out *Page and *Frame (user-beware), some of the more important APIs now take a frame_id which Session can resolve. Furthermore, createPage now returns a PageHandle which is a safe wrapper around a page/frame. 4 - Two large mechanical changes were made: a - Many tests were superficially changed to account for new naming or use a new test-helper to preserve the single-page illusion (because 99% of tests _are_ single-page) b - Many CDP changes where `bc.session.currentFrame()` -> `bc.mainFrame()`). This isn't to say CDP changes are meaningless, but it's mostly 1 change about how the "main" target/frame_id is tracked (by CDP itself, rather than the Session) that required a number of superficial changes to accomodate `Runner` remains largely single-page focused. Runner and some MCP/Agent tools continue to be tied to the "currentFrame" or "primaryPage". The Runner is something I want to address in a follow-up PR, but we need to figure out what it means to "wait" for multiple pages. As much as possible, Session becomes multi-page native and has no concept of a special/first/primary/main page. Users of session become responsible for tracking pages of interest. This change is not trivial, but the diff is inflated by 2 large mechanical changes: 1 - Many tests (1) https://github.com/lightpanda-io/browser/pull/2759