Commit Graph
9542 Commits
Author SHA1 Message Date
Adrià Arrufat 1e1c19d543 css: implement URL tokenization
Implements unquoted URL tokenization per CSS Syntax Level 3 §4.3.6.
Adds bad URL recovery and an AX tree test fixture.
2026-04-17 09:06:36 +02:00
Karl Seguin ba947b8c76 Support more types in new Blob(...)
Gives the same treatment to Blob as https://github.com/lightpanda-io/browser/pull/2171
gave to Response.

Creating a blob from JS and creating a blob internally is different enough that
they now share little, and the ergonomics for creating a blob internally are
better / simpler.

Conversely, initializing a Response and Blob from a js.Value now share a
`js_val.toStringSmart()` which can probably be used in other places. Unlike
`toString()` which behaves like JavaScript (e.g. array_buffer.toString() ->
"[object ArrayBuffer]"), `toStringSmart` understands buffers and blobs.
2026-04-17 14:37:37 +08:00
Adrià Arrufat cee72cabb9 cdp: improve AX tree visibility and label resolution
Prunes hidden subtrees from the accessibility tree and implements
accessible name resolution via labels. Adds the `labels` property
to labellable HTML elements.
2026-04-17 08:33:13 +02:00
Karl Seguin e7c44d34f4 This updates html5ever and the other Rust dependencies.
Inspired by:
https://github.com/lightpanda-io/browser/security/dependabot/1
2026-04-17 12:39:15 +08:00
Karl Seguin 9b93ac690e Migrate more tests to new async (failing in CI)
Also improve test report failure on async failure.
2026-04-17 12:10:35 +08:00
Karl Seguin aac0a6e6b6 Websocket fixes.
This commit fixes a few serious issues with the Websocket implementation.

1 - libcurl recursive api calls
Creating a Websocket instance from within a libcurl callback results in libcurl
failing with a RecursiveApiCall error. I fixed this more generally by adding a
`ready_queue` which connections can use when the `HttpClient` is performing
actions. Once `perform` ends, this new `ready_queue` is processed. There might
be a more holistic solution to this (we seem to run into RecursiveApiCall
everywhere), but since HttpClient is going through heavy changes, this seemed
like the smallest possible change to fix it.

2 - "load" blocking
Load and IdleNetwork notifications should not block on Websocket connections. To
solve this, `HttpClient` now ha `http_active` and `ws_active` to replace `active`.
Only `http_active` is used for things like "load" triggering.

3 - The above change made the Runner's job more complicated. It used to be
binary: you either have active connections or not. Now there are different types
of active connections. To keep it simple, and I think probably more correct,
the "done-ness" (based on the `wait` parameter) is now independent of active
(or not) network activity. If the page's `load_state == .complete`, then the
`wait == .done` is considered successful, whether or not we have active
connections.

4 - As a consequence of the above, and seemingly unrelated to all of these
changes, a number of html tests now use the "new" robust async framework. Most
of these tests were using the `testing.onload` (aka `testing.eventually`) which
had somewhat...unclear semantics. These tests passed more of a consequence of
how we processed a page and being very simple (e.g. just needing 1 micro or
macrotask tick). But `eventually` never worked for more complicated cases, and
the previous `testing.async` didn't work well. Now, the test runner waits for
.load (which, as per #3, can fire more aggressively), which caused many
`eventually` tests to fail. Moving these tests to the new `async` is more
robust and works with the new aggressive "load".
2026-04-17 11:20:27 +08:00
Karl Seguin 6caca237fd Merge pull request #2172 from lightpanda-io/replaceChild_safety
Improve safety of Node.replaceChild and Element.replaceWith
2026-04-17 07:05:48 +08:00
Karl Seguin 13f5406d1d Merge pull request #2171 from lightpanda-io/Response_init_body
Expand body types new Response(...) can be created with
2026-04-17 07:05:37 +08:00
Karl Seguin 838b79d19a Merge pull request #2170 from lightpanda-io/decoder_double_free
Avoid double free on decoder error
2026-04-17 07:05:25 +08:00
Pierre Tachoire 472c2c1a4c Merge pull request #2146 from Gujiassh/docs/npm-package-name-clarity
docs: suggest verifying nightly binary
2026-04-16 11:12:34 -04:00
Adrià Arrufat 8f7c86042c agent: add --task flag for one-shot execution 2026-04-16 16:16:02 +02:00
Pierre Tachoire 8de5267cd0 Merge pull request #2169 from lightpanda-io/feat/cookies-file
Feat/cookies file
2026-04-16 08:21:53 -04:00
Karl Seguin 1bffde8808 Improve safety of Node.replaceChild and Element.replaceWith
We've seen this sort of thing before - an assumption we make about the state of
the DOM through a transition is broken by CustomElement callbacks.

Here we see replaceChild which (a) inserts the new nodes and (b) removes the
old one. As part of removing, our page.removeNode has an assertion that the
child belongs to the parent. This is a guarantee that the Page is asking the
caller (Node.replaceChild in this case) to make. But, if the node being inserted
is a custom element, it can have a callback so step (a) can cause changes to
the document, including removing/moving the node being replaced.

TL;DR - CustomElement callbacks means that we have to check that the child to
be replaced is still a child of the parent after our insert.
2026-04-16 16:09:01 +08:00
Adrià Arrufat bbe1b40c41 Merge branch 'main' into agent 2026-04-16 09:21:48 +02:00
Karl Seguin d66cdcbf71 Merge pull request #2164 from lightpanda-io/Page_createIsolatedWorld
Fix Page.createIsolatedWorld
2026-04-16 15:16:51 +08:00
Karl Seguin 0adb482bae update v8 dep 2026-04-16 15:02:58 +08:00
Karl Seguin 7da63432ec Expand body types new Response(...) can be created with
Was originally just a []const u8, but now allows for Blob, BufferArray (and
related) and Stream.

I saw this being used on http://www.github.com/ (homepage). Unfortunately its
using the data for webgl stuff that we don't support, but it does move the
processing a step further.
2026-04-16 14:48:59 +08:00
gujishh 68ca3907ec docs: suggest verifying nightly binary 2026-04-16 15:20:30 +09:00
Karl Seguin 84bb395c02 Avoid double free on decoder error
Fixes WPT crash: /encoding/textdecoder-fatal-streaming.any.html
2026-04-16 11:10:41 +08:00
Karl Seguin 3ca1f230b9 Serialize sameSite
Tweak ergonomics (public functions log internally and are infallible). Use
readFileAlloc directly. Fix possible memory leak with cookie arena - I don't
think you can make a copy of the arena, and then dupe with the original.
2026-04-16 10:35:34 +08:00
Karl Seguin 09dab74ed0 Merge pull request #2167 from lightpanda-io/finalizer_fingers_crossed
Improve finalizer code
2026-04-16 07:20:52 +08:00
Karl Seguin 51a3835a4a Use flag to protect against resolve_ptr_reuse
The point of this change is that v8 might call these finalizers after we've
cleared things (e.g. because it's already queued it). We need to make the
FC.Identity self-contained and not rely on any external state (like the
finalizer_callback lookup) which might have new entries.
2026-04-16 07:00:26 +08:00
Karl Seguin c7313af3b9 Merge pull request #2163 from lightpanda-io/media_play_promise
Return promise on media.play()
2026-04-16 06:57:06 +08:00
Karl Seguin 2aa668c200 Merge pull request #2165 from lightpanda-io/isolated_world_identity_reset
On page reset, reset IsolatedWorld identity
2026-04-16 06:56:51 +08:00
Karl Seguin f043935ae6 Merge pull request #2168 from lightpanda-io/quiet_test_warnings
quiet a couple test warnings
2026-04-16 06:56:35 +08:00
Pierre Tachoire d2785603f3 Merge pull request #2147 from Gujiassh/docs/windows-wsl-instructions
Clarify Windows WSL installation notes
2026-04-15 10:58:45 -04:00
Pierre Tachoire e922bf7369 update help for --cookies and --cookie-jar option 2026-04-15 10:48:23 -04:00
Pierre Tachoire a24fcc6a5c use session arg to load cookies from file 2026-04-15 10:29:53 -04:00
Pierre Tachoire cc4bd417d2 save cookies at the end of fetch 2026-04-15 10:09:14 -04:00
Pierre Tachoire de3404dfc5 fix zig syntax 2026-04-15 10:09:13 -04:00
Matt Van HornandClaude Opus 4.6 35991a1b32 refactor: split --cookies-file into --cookie/--cookie-jar per curl convention
Split the single --cookies-file flag into two flags following curl's
convention as requested by @krichprollsch:

- --cookie (read-only): loads cookies at startup for fetch, mcp, and
  serve/CDP commands
- --cookie-jar (write-only): saves cookies on exit for fetch and mcp
  only (CDP cookie-jar deferred per maintainer guidance)

Add cookie integration to MCP server (load in init, save in deinit)
and CDP session creation (load only). The serve command now rejects
--cookie-jar with a clear error message.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:09:13 -04:00
Matt Van HornandClaude Opus 4.6 494ef345a1 fix: resolve Zig 0.15 compilation errors in cookies and config
- Escape braces in help text format string to avoid std.debug.print
  interpreting them as format specifiers
- Use writer.interface for std.Io.Writer methods (writeAll, stringify)
  instead of calling them directly on fs.File.Writer
- Replace writer.flush() with writer.end() per codebase convention

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:09:13 -04:00
Matt Van HornandClaude Opus 4.6 242851249d fix: use file.writer() instead of std.io.bufferedWriter
std.io.bufferedWriter doesn't exist in Zig 0.15.2. Use the
file.writer(&buf) pattern that matches the rest of the codebase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:09:13 -04:00
Matt Van HornandClaude Opus 4.6 4d384dfe01 feat: add --cookies-file flag for session persistence
Add a --cookies-file CLI option that loads cookies from a JSON file
at startup and saves them back on exit. This enables AI agents to
maintain login sessions across multiple Lightpanda invocations.

The cookie format matches CDP Network.Cookie (compatible with
Puppeteer's page.cookies() export):
  [{"name":"sid","value":"abc","domain":".example.com","path":"/",
    "expires":1234567890,"secure":true,"httpOnly":true}]

Closes #335

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:09:12 -04:00
Karl Seguin 55791932f8 quiet a couple test warnings 2026-04-15 19:30:46 +08:00
Karl Seguin 8ab5f1b21f Improve finalizer code
2 small changes:
1 - Ensure that isolated world identity is always reset. Not clear how we can
have identity without a context, but very little harm in doing it this way.

2 - Clear finalizer_callback map _before_ finalizing an instance. Finalizing
an instance could (a) release an arena (they almost all do) and (b) create an
object with the newly released arena. I don't think anything does that now, but
they could. That object could even be passed into v8 during finalization. In
which case, we'd temporarily have 2 "live" instances (one being finalized, one
jsut created) at the same address. Don't think we have any code that does this,
but switching the order (remove from map, then finalize) protects against this
address re-use.

1 big change:
Not really big, but more likely to actually fix things. A finalizer can still
be called _after_ we've cleared the finalizer callback. This can happen if
v8 has queued the finalizer prior to us clearing it. We do see some evidence
that this might be an issue, as many extra releaseRefs are happening in
the message loop or microtasks. This makes that scenario safer. First, it moves
the finalizer identity to a dedicated MemoryPool that can outlive the page.
Second, it uses the finalizer_callback map itself to tell whether or not
anything has to happen.
2026-04-15 19:06:10 +08:00
Karl Seguin 513af82751 On page reset, reset IsolatedWorld identity
This is an attempt to fix reference counting issues. When Session.replacePage
is called, isolated worlds survive. This appears to be the correct behavior, but
it means that their identity outlives the page reset, which can result in a
use-after-free. The idea is that, on reset, IsolatedWorld persist, but their
identity is cleared.
2026-04-15 17:40:33 +08:00
Karl Seguin 5dc059cbb3 maintain isolated world name 2026-04-15 17:16:42 +08:00
Adrià Arrufat 7fed6e18ad build(deps): switch zenai dependency to remote git
Updates the zenai dependency from a local relative path to a specific
git commit on the remote repository.
2026-04-15 11:13:57 +02:00
Karl Seguin dd7fbf17ed fix default-ness 2026-04-15 16:11:35 +08:00
Karl Seguin 0b72826cab Fix Page.createIsolatedWorld
Depends on https://github.com/lightpanda-io/zig-v8-fork/pull/170

Gets the correct executeContextId from the v8 inspector.
2026-04-15 16:02:24 +08:00
gujishh b15fc158c2 docs: expand WSL installation guidance 2026-04-15 15:08:53 +09:00
Karl Seguin 9654bc9afe Return promise on media.play() 2026-04-15 10:27:00 +08:00
Karl Seguin 87a48dea28 Merge pull request #2162 from lightpanda-io/cache_safety_check
Add safety check around cache get
2026-04-15 09:42:45 +08:00
Karl Seguin 16686c13af Add safety check around cache get
It should be impossible for a internal cache get to have an incorrect # of
internal fields. But we're seeing this exact scenario in production.
https://github.com/lightpanda-io/browser/pull/1991 was meant to help with this,
but you can do some pretty weird things in JavaScript and it's possible there's
some combination of JavaScript which still allows calling these methods on a
different receiver.
2026-04-15 09:02:38 +08:00
Karl Seguin 1f94312086 Merge pull request #2161 from lightpanda-io/crash_fix
Various crash fixes
2026-04-15 07:09:14 +08:00
Karl Seguin beb6069ce5 Merge pull request #2160 from lightpanda-io/fix_fetch_cleanup_order
Remove unnecessary flag clear
2026-04-15 07:09:02 +08:00
Karl Seguin 5de092f662 Merge pull request #2159 from lightpanda-io/document_font_lifecycle
acquire reference on document font
2026-04-15 07:08:52 +08:00
Karl Seguin 5c33c8fc3c Merge pull request #2158 from lightpanda-io/websocket_tweaks
WS.close returns DOMException
2026-04-15 07:08:37 +08:00
Karl Seguin ada235a8c8 Various crash fixes
1. Double buffer to_load list so that load callback which register more loadable
elements don't invalid the list while we're iterating

2. Switch to debug-only assertion for opaque origin. Not clear how this
assertion is failing, but isn't worth failing release builds for it.

3. on worker terminate, don't remove worker from page tracking. This results in
a leaking context, which causes numerous problems.

4. On page.init error, cleanly shutdown context
2026-04-15 01:14:26 +08:00