Commit Graph
7616 Commits
Author SHA1 Message Date
Halil Durak f6fb653a35 prefer resolveNavigation at page, target and fetch 2026-06-25 18:06:08 +03:00
Halil Durak 67cc2be817 URL.zig: update tests 2026-06-25 18:05:49 +03:00
Halil Durak 6bd4fddf62 URL: add resolveNavigation
This is needed for schemeless "address bar" style URLs. Would love to have a path that doesn't allocate for this...
2026-06-25 18:05:49 +03:00
Halil Durak 82d78ecd00 Node: add resolveURLReflect 2026-06-25 18:05:49 +03:00
Halil Durak a499c0cb92 URL: update tests 2026-06-25 18:05:48 +03:00
Halil Durak 7d5553238e URL: changes on host(name) setter, introduce clean_hostname_input 2026-06-25 18:05:48 +03:00
Halil Durak 0c4f6f0d87 getProtocol(Anchor, Area): return : if resolved href is null 2026-06-25 18:05:48 +03:00
Halil Durak 84fe33c679 URL(EncodeSet): bring back component value
Lost and found.
2026-06-25 18:05:48 +03:00
Halil Durak a12d781d4a KeyValueList.zig: update tests 2026-06-25 18:05:48 +03:00
Halil Durak 2cdcecaba4 KeyValueList(urlEncodeUnreserved): drop ~ case 2026-06-25 18:05:48 +03:00
Halil Durak 84870d5524 URL: include leading '?' in search/query 2026-06-25 18:05:48 +03:00
Halil Durak 8d41c6e221 KeyValueList: write = between key and value at all modes 2026-06-25 18:05:48 +03:00
Halil Durak 20c9a873fd URL: update tests 2026-06-25 18:05:47 +03:00
Halil Durak e223827789 URL: reintroduce parse static method 2026-06-25 18:05:47 +03:00
Halil Durak 3c91f3b3e2 URL: fix missing port problem in setter 2026-06-25 18:05:47 +03:00
Halil Durak 7bf68a484d URL: replace ensureEncoded with resolve
Both essentially do the same; we can stick to `resolve` for further IDNA compat.
2026-06-25 18:05:47 +03:00
Halil Durak 9732c33c3c URL: remove always_dupe option from all call sites 2026-06-25 18:05:08 +03:00
Halil Durak 3512f1fb1a update URL-involving tests 2026-06-25 18:05:08 +03:00
Halil Durak be6f1c9155 Caller: remove error.Idna case 2026-06-25 18:05:08 +03:00
Halil Durak fc00421870 URL: retake on resolve function 2026-06-25 18:05:08 +03:00
Halil Durak 0ddca754a4 URL: move resolver functions to Rust
Implements `url_resolve_with_encoding` and `url_resolve_without_encoding` in Rust; that way, we don't pay the cost of extra `Box`es we allocate during resolving.
2026-06-25 18:05:08 +03:00
Karl Seguin dcab57cd05 Merge pull request #2813 from lightpanda-io/fix-handlescope-corruption
crash: Fix handlescope corruption on iframe load
2026-06-25 17:42:42 +08:00
Pierre Tachoire 4faed74af0 Merge pull request #2809 from lightpanda-io/intercepted_abort_double_free
uaf: Prevent double-free on BrowserContext deinit with pending interc…
2026-06-25 09:26:37 +00:00
Karl Seguin 0fd73650fc Merge pull request #2801 from lightpanda-io/document-setDomain
webapi: Expose document.domain setter
2026-06-25 14:13:59 +08:00
Karl Seguin 5c902b6cfe crash: Fix handlescope corruption on iframe load
In trying to fuzz test a different issue, I ran into a reproducible case where
we end up with a broken handlescope stack. The issue requires a large number
of handlescopes created with aggressive GC, so hopefully it isn't something
that too many users have run into.

The issue is that a single HandleScope address is used to initialize two
HandleScopes. The fix could just be to create a 2nd HS variable (to get a 2nd
address), but the first initialization is unnecessary and can just be removed.

(Note that EventManager dispatch creates its own HandleScope, so the one
removed in frameCompletedLoading really did nothing)
2026-06-25 10:52:39 +08:00
Karl Seguin f2eaeb1c9a uaf: Prevent double-free on BrowserContext deinit with pending interception
Adds a abortParked (to be used instead of abort for a parked transfer) which
guards against a double-free by setting the state to .completing BEFORE running
the requestFailed callback. Without this, requestFail could itself cause the
transfer to be cleared.

Also added a guard to try to catch double transfer deinit's in Debug. Because
the memory could get re-used between the first and second free, the lack of
failure doesn't prove there is no UAF. But it's cheap to do and debug only.
2026-06-24 20:09:00 +08:00
Pierre Tachoire 8ccbc4d730 Merge pull request #2790 from lightpanda-io/hash-change-event
webapi: add HashChangeEvent and Window hashchange event
2026-06-24 06:28:41 +00:00
Pierre Tachoire 72af3de5d0 Merge pull request #2805 from lightpanda-io/fix-homebrew-release
ci: fix homebrew release workflow name
2026-06-24 06:28:07 +00:00
Pierre Tachoire 4e97d1e2e9 ci: fix homebrew release workflow name 2026-06-24 08:13:36 +02:00
Karl Seguin 7b585df7ff Merge pull request #2789 from lightpanda-io/multi-page-sessions
design: multi-page session
2026-06-24 07:39:40 +08:00
Karl Seguin 6d1efd15e0 remove stale comment 2026-06-24 07:01:32 +08:00
Karl Seguin 9482a9af98 Cleanup sloppy tests, Fix potential UAF, smaller cleanup (PR feedback).
Cleanup sloppy tests, make sure pages are always closed after page tests - not
before and not never.

Fix a UAF in replaceRootImmediate..if a page is being retired, also retire its
replacement.

Give BrowserContext a Session.PageHandle rather than having a frame_id and re-
implementing PageHandle logic.
2026-06-24 07:01:31 +08:00
Karl Seguin da6cd66e36 design: multi-page session
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
2026-06-24 07:01:29 +08:00
Karl Seguin 48cb0848cc Merge pull request #2799 from lightpanda-io/moveBefore
webapi: moveBefore
2026-06-24 06:53:46 +08:00
Karl Seguin 068ad7b0b1 Merge pull request #2796 from lightpanda-io/strip-mode-invisible
cli: add strip-mode invisible
2026-06-24 06:53:17 +08:00
Karl Seguin 48ed689c20 Merge pull request #2795 from lightpanda-io/innerText-visibility
webapi: innerText  uses StyleManager's visibility
2026-06-24 06:51:14 +08:00
Pierre Tachoire 846d6fd816 fix: single source of truth for hashchange fragment decision
History.goInner re-derived the fragment-vs-document decision from the raw
entry._url, while navigateInner computes it from the resolved URL. These
diverge when an entry stores a non-canonical URL, queuing a spurious
hashchange (or missing one). Let navigateInner own the decision and queue
the event for all same-document navigations; drop goInner's duplicate.
2026-06-23 18:03:04 +02:00
Pierre Tachoire b989ea6b47 remove useless comment 2026-06-23 17:42:27 +02:00
Pierre Tachoire c450247b31 fix UAF: copy urls into event's arena 2026-06-23 17:31:12 +02:00
Pierre Tachoire 5b97450cfa Merge pull request #2802 from lightpanda-io/feat/cdp-viewport-browser-level
cdp: return browser's viewport on getLayoutMetrics
2026-06-23 15:28:32 +00:00
Pierre Tachoire 82cd61e75c cdp: return browser's viewport on getLayoutMetrics 2026-06-23 15:22:16 +02:00
Pierre Tachoire 55568907ba Merge pull request #2791 from rohitsux/feat/cdp-viewport-browser-level
refactor(cdp): store viewport override at the browser level
2026-06-23 13:14:39 +00:00
Karl Seguin b6d63a9c91 webapi: Expose document.domain setter
This is a deprecated API, but it's used in various WPT tests. I don't expect
WPT tests to necessarily improve, but they should get further than just failing
on the setter.

This also includes a change where BroadcastChannel now uses the origin string
rather than the js.Origin identity because BroadcastChannel should be based
on the actual frame's origin...which used to be captured in Context.origin but
which the new document.domain can change.
2026-06-23 20:02:49 +08:00
Pierre Tachoire 53962b675e Merge pull request #2800 from lightpanda-io/trigger-homebrew-formula
ci: trigger homebrew-browser formula update after release
2026-06-23 11:35:13 +00:00
Pierre Tachoire 4314148b70 ci: trigger homebrew-browser formula update after release 2026-06-23 11:58:22 +02:00
Karl Seguin 1e06ec918e webapi: innerText visibility fix
When "rendering" innerText, we don't care about the visibility of the entire
tree, we just care about the visibilty of the element itself and then all of
it's children. Or, put differently:

```
<div style=display:none>
  <div id=x>spice</div>
</div>
<script>
console.log(document.getElementById('x').innerText)
</script>
```

Should still print "spice"..even though 'x' is inside a hidden element. The
original version used the StyleManager's isHidden which fails this test - it
scans all the parents. This new version just considers the visibility of each
element being displayed. This is faster and more correct
2026-06-23 09:57:44 +08:00
Karl Seguin bedde28dde add unit tests for dump 2026-06-23 09:31:33 +08:00
Karl Seguin c14d2b4eef update help text 2026-06-23 08:17:09 +08:00
Karl Seguin ad9bbef2b8 webapi: moveBefore
Add Element/DocuemntFragment/Document moveBefore. The API is relatively
complicated compared to other node-moving APIs, so there are still some edge
cases. But this implementation should be at a level where having the API fixes
more things than it breaks.
2026-06-23 08:12:29 +08:00
Pierre Tachoire b78940d7f6 remove useless url duplications 2026-06-22 22:09:21 +02:00