Commit Graph
9542 Commits
Author SHA1 Message Date
Pierre Tachoire f2169836e5 Merge pull request #3256 from lightpanda-io/mcp-origin
mcp: enforce HTTP conditions
2026-08-26 09:42:29 +02:00
Karl Seguin 7ff12215b7 webapi: improve hover events
The Page now tracks the element currently being hovered. We need to track this
so that subsequent mouse events can fire the correct events. This is largely a
WebDriver (WPT) change, but it's also triggered from CDP's
`input.dispatchMouseEvent`.

So, for example, if CDP `dispatchMouseEvent` with a mouseMoved to element1
we'll fire a mouseenter. If the same command is issue for the same element, we
should NOT trigger a mouseout and mouseenter.
2026-08-26 15:31:24 +08:00
Karl Seguin f65ff762b8 webapi: URLSerachParams @@iterator init
This has been on my TODO for a long time. https://github.com/lightpanda-io/browser/pull/3238
added support for the @@iterator protocol and now URLSearchParams' init can
use it.

We used to only support a v8::Array, but now any type that implements the
@@iterator protocol can be passed into URLSearchParams.

This also fixes and simplifies the js.Object iterator. It now yields name +
value (so callers don't need to get the name then lookup the value). But it
isn't just about making it easier to use. The name can be a lossy UTF-8
conversion, so the value lookup can fail. By internalizing the value lookup we
can use the v8::String directly for the lookup.

Fixes a handful of WPT /url/ cases
2026-08-26 14:57:02 +08:00
Adrià Arrufat 48551d241a mcp: navigation and waits are not read-only; consoleLogs is not idempotent
Review feedback: navigation writes cookies and storage and a wait lets page
scripts mutate state, so neither can be auto-approved as read-only.
consoleLogs drains its buffer, so repeated calls differ.
2026-08-26 08:44:57 +02:00
Adrià Arrufat 8f2d1de266 Merge pull request #3279 from lightpanda-io/interactive-visibility
interactive: skip hidden elements
2026-08-26 08:42:56 +02:00
Karl Seguin 8c5b684760 Optimize visibility check
Since all children of an invisible element are skipped, the visibility cache
serves no purpose AND we can assume that any element we do visit has a visible
parent and thus just need to check the element's own visibility.
2026-08-26 14:14:03 +08:00
Adrià Arrufat b814af122d interactive: skip hidden elements
interactiveElements and findElement returned elements under display:none
or [hidden], so agents were offered controls no user could reach and the
list disagreed with tree, which already filters on visibility. Reuse the
same cached check and skip the hidden subtree.
2026-08-26 14:02:56 +08:00
Karl Seguin 2fbfbea955 Merge pull request #3269 from lightpanda-io/markdown-hidden-content
markdown: skip hidden elements
2026-08-26 13:54:49 +08:00
Karl Seguin fc7b53b59c Merge pull request #3275 from lightpanda-io/interactive-role-tokens
interactive: read the role attribute as a token list
2026-08-26 13:54:29 +08:00
Karl Seguin 51279b80c2 Merge pull request #3274 from lightpanda-io/mcp-protocol-version
mcp: negotiate the protocol version on initialize
2026-08-26 13:41:40 +08:00
Karl Seguin ff9adc4202 Merge pull request #3277 from lightpanda-io/html-tool-maxbytes
tools: add maxBytes and strip to the html tool
2026-08-26 13:38:13 +08:00
Karl Seguin 66ac8d33e3 zig fmt -_- 2026-08-26 13:23:38 +08:00
Karl Seguin 29d1ae8f0f fix build, sorry 2026-08-26 13:23:37 +08:00
Karl Seguin e4a36552b8 mem: Optional CSSStyleDeclaration materialization
StyleManager ultimately ends up calling el.getOrCreateStyle() which either
returns the element's CSSStyleProperties OR (creates it AND stores it in the
Frame._element_styles for future lookups).

The goal behind this caching is twofold:
1 - Performance of not having to reparse the "style" attribute
2 - Identity: two calls from JS to get the properties should return the same
    value

(2) is non-negotiable, so the 'getOrCreate' _has_ to exist for JS-facing APIs.

But (1) is CPU vs memory optimization that we've decided should always favor the
CPU. But, in any case where we dump an entire tree, that memory cost can be
significant (# of elements with a style attribute) and the CPU gains are
questionable (it isn't like a JS loop re-checking an element's properties, it's
a one-time dump). So, the StyleManager now takes a comptime `InlineAccess` which
is either `.scan` or `.materialize`. When it's `.materialize` it behaves as
before. When it's `.scan` is will use an existing `_element_styles` if available
else it will re-parse but not store the value.
2026-08-26 13:23:11 +08:00
Adrià Arrufat e76cc816c0 markdown: skip hidden elements
The renderer's only visibility test was the tag (metadata/svg), so
display:none, [hidden], aria-hidden="true", closed <details> content and
closed <dialog>s all ended up in the output.

Check each element's own computed display:none through StyleManager plus
aria-hidden="true"; the dump root is exempt so a scoped dump of a hidden
subtree still renders it. analyzeContent/isStandaloneAnchor use the same
predicate so an anchor whose only content is hidden falls back to its label.

Also adds the missing dialog:not([open]) { display: none } UA rule.
2026-08-26 13:22:50 +08:00
Karl Seguin 67a5b23dc6 Merge pull request #3270 from lightpanda-io/css-keyword-case
css: compare visibility keyword values case-insensitively
2026-08-26 13:22:03 +08:00
Karl Seguin c8abf899ef mem: include v8 functions in binary layout optimization
https://github.com/lightpanda-io/browser/pull/3271 introduce an orderfile so
that hot sections of code were grouped together in the binary, resulting in more
efficient loading. But, it excluded v8 functions because v8 is compiled with
`-fno-unique-section-names` so each section gets the same name. Because of this
the orderfile can't target specific "hot" or "cold" functions.

As a follow up to 3271, I thought we'd be able to re-compile v8 without that
flag, but:

1 - The flag isn't directly exposed by v8, so we'd need to change v8's own build
    BUILD.gn in our build process
2 - It would make the .a file ~ 40MB larger (though the final lightpanda binary
    would stay the same size
3 - If we wanted to created two .a files (one with -fno-unique-section-names and
    one without), it would require a full rebuild (for both x86-64 and arm).

I didn't love those compromises, so I asked Claude if the sections names could
be generated in a separate file and then that could be used when generating out
lightpanda.ld. What claude came up with was a small Zig script
(mark_hot_sections.zig) which is now run as part of the build. It takes the
v8.a file (which still has `-fno-unique-section-names`), it takes a text list
of hot functions, and it re-generates v8.a with a special .text.hot and
.rodata.hot sections. lightpanda.ld can include these.

This PR depends on https://github.com/lightpanda-io/zig-v8-fork/pull/202 but
202 doesn't require a v8 rebuild. It merely allows prebuilt_v8_path to be
a lazypath, which we need because the prebuilt_v8_path that we pass is now
generated from this build script.
2026-08-26 12:53:45 +08:00
Muki Kiboigo 18d928faf7 silently ignore invalid responseType in XHR 2026-08-25 21:12:35 -07:00
Muki Kiboigo fd11c1ad46 better error throwing in sync XHR 2026-08-25 20:43:20 -07:00
Scott Taylor 6ea37f4dcc Handle immediate meta refresh navigation
Assisted-By: devx/cb5edaca-b259-4956-a65f-f2168ea91830
2026-08-25 23:24:45 -04:00
Muki Kiboigo 821bef8896 remove response header management in sync XHR 2026-08-25 20:04:33 -07:00
Muki Kiboigo 947f48dece defer release self ref on sync XHR path 2026-08-25 20:04:20 -07:00
Muki Kiboigo 026c56b740 NetworkError on failed sync XHR 2026-08-25 19:54:18 -07:00
Adrià Arrufat 0590bd0f80 Merge pull request #3265 from lightpanda-io/search-cleanup
search: default to Keenable's keyless endpoint, drop the DuckDuckGo scrape
2026-08-26 03:45:54 +02:00
Karl Seguin fa36fb5a69 Merge pull request #3280 from lightpanda-io/dev-fast-host-glibc
build: pin dev_fast to the host's glibc version
2026-08-26 09:40:14 +08:00
Pierre Tachoire 78fda6779f allow localhost host to connect to CDP and MCP 2026-08-26 09:24:01 +08:00
Pierre TachoireandAdrià Arrufat a0e3da6a6b Update src/mcp/HttpServer.zig
Co-authored-by: Adrià Arrufat <1671644+arrufat@users.noreply.github.com>
2026-08-26 09:24:01 +08:00
Pierre Tachoire 9db3c1bb94 mcp: enforce HTTP conditions
Apply same conditions than CDP for MCP HTTP conns:
* refuse requests including Origin header
* accept only ip as host
* ensure content-type is json for POST
2026-08-26 09:24:00 +08:00
Karl Seguin 3f155f2c4b Merge pull request #3281 from lightpanda-io/fix-orderfile-debug-build
Build: Fix linux debug build
2026-08-26 09:22:14 +08:00
Karl Seguin b8c9fa3d76 Build: Fix linux debug build
https://github.com/lightpanda-io/browser/pull/3271 broke linux debug builds
2026-08-26 09:10:49 +08:00
Muki Kiboigo de4b993749 throw InvalidAccessError if timeout with sync XHR 2026-08-25 17:43:04 -07:00
Muki Kiboigo 68af3a264d properly add lengthComputable flag to XHR sync path 2026-08-25 17:43:04 -07:00
Muki Kiboigo 8bd0febda6 only emit done event on sync XHR 2026-08-25 17:43:04 -07:00
Muki Kiboigo 4171078568 fix crash in sync path of XHR 2026-08-25 17:43:04 -07:00
Muki Kiboigo 35edb2b190 add the ability to do sync requests with XMLHttpRequest 2026-08-25 17:43:04 -07:00
Muki Kiboigo 234d47d0e2 syncRequest -> submitSync on Transfer 2026-08-25 17:43:03 -07:00
Karl Seguin a3ab6b0b7e glibc build version
So we're trying to limit glibc to 2.43.0 do to an issue in Zig's self-hosted
compiler. I'm on 2.44.0 and I hard-coded 2.43.0. But for anyone on a version
prior to 2.43.0, that causes issues. So this takes the host version but limits
it to 2.43.0
2026-08-26 06:47:17 +08:00
Karl Seguin 53e1db66d0 Merge pull request #3273 from lightpanda-io/driver-guidance-rendering
tools: drop the 'no rendering' claim from the driver guidance
2026-08-26 06:36:32 +08:00
Karl Seguin 64cdead237 Merge pull request #3271 from lightpanda-io/mem-vmhwm
mem: On linux CI builds, use an orderfile
2026-08-26 06:35:25 +08:00
Karl Seguin a9d93a87df Merge pull request #3264 from lightpanda-io/wpt-webdriver-keyboard
webdriver: Improve WebDriver keyboard handling
2026-08-26 06:33:59 +08:00
Karl Seguin 22e02f5070 Merge pull request #3263 from lightpanda-io/usp-invalid-escapes
webapi: URLSearchParams passes invalid percent-escapes through
2026-08-26 06:33:49 +08:00
Adrià Arrufat 5dc2535aae build: pin dev_fast to the host's glibc version, not 2.43
The explicit version only exists to force Zig's bundled CRT (zig#31272),
but it also selects symbol versions. PR #3231 added tiny-skia, which
calls acosf, and glibc 2.43 re-versioned that symbol, so the binary now
fails to load on hosts with an older glibc:

  libm.so.6: version `GLIBC_2.43' not found

Use the detected host glibc instead: still an explicit version, so the
bundled CRT is still used, but never newer than what the binary runs on.
2026-08-25 17:02:18 +02:00
Adrià Arrufat f05789353b tools: add maxBytes and strip to the html tool
An unscoped html call returned the whole document, inline scripts and
stylesheets included, with no way to cap it; markdown already had
maxBytes. The byte-capping writer moves out of markdown.zig into a shared
LimitedWriter so both tools use it, and strip reuses dump.Opts.Strip.
2026-08-25 15:53:11 +02:00
Adrià Arrufat ade731cb0b mcp: add title and annotations to tools/list
Every tool already had a short summary and a natural read-only /
destructive classification, but tools/list exposed neither, so clients
had to prompt for every call, including pure reads like getUrl.
2026-08-25 15:46:30 +02:00
Pierre Tachoire a01e148ab0 Merge pull request #3268 from lightpanda-io/mcp-http-close-after-reject
mcp: close the connection after a keep_alive=false response
2026-08-25 15:38:12 +02:00
Adrià Arrufat 4140792162 interactive: read the role attribute as a token list
ARIA `role` is a space-separated fallback list (`role="switch checkbox"`),
but interactive.zig and AXNode compared the raw attribute whole, so a
fallback list or padded value was neither interactive nor findable by
role, and the semantic tree reported the raw string as the role.

One explicitRole helper takes the first token; a blank attribute now
falls through to the implicit role.
2026-08-25 15:34:37 +02:00
Adrià Arrufat 3e8b836680 mcp: negotiate the protocol version on initialize
initialize always answered 2024-11-05 regardless of what the client asked
for. Per the spec, echo the requested version when we support it and
otherwise reply with the newest we do (2025-11-25).
2026-08-25 15:30:26 +02:00
Karl Seguin 2929660ae7 Merge pull request #3272 from lightpanda-io/fix-make-test-filter
Makefile: fix test filtering
2026-08-25 21:24:19 +08:00
Adrià Arrufat 4583066b2f tools: drop the 'no rendering' claim from the driver guidance
The engine renders PNGs since #3231. What is still true for the model is
that no tool exposes pixels, so say that instead.
2026-08-25 15:24:01 +02:00
Adrià Arrufat 04484f287f Makefile: fix test filtering
- Stop re-exporting command-line variables via MAKEFLAGS: tikv-jemalloc-sys's
  build script appends its jobserver flags after the inherited "-- F=..."
  separator, so a cold cargo cache failed with "No rule to make target '-j'"
  whenever any VAR=value was passed to make.
- `TEST_FILTER=... make test` was silently clobbered by the empty F and ran
  the full suite; fall back to the environment value when F is unset.
2026-08-25 15:16:02 +02:00