Commit Graph
9542 Commits
Author SHA1 Message Date
Karl Seguin b3dd5f7de1 Merge pull request #3456 from lightpanda-io/fix-v8-reentrancy-in-window
Fix V8 Reentry on unhandled promise
2026-09-09 07:11:40 +08:00
Karl Seguin 6fce5ac1f1 Merge pull request #3449 from lightpanda-io/css-selector-nth-cache
perf: improve nth-* CSS selector performance
2026-09-09 06:53:30 +08:00
Karl Seguin 5896eeb260 Merge pull request #3447 from lightpanda-io/global-scope
chore: refactor Execution and GlobalScope
2026-09-09 06:53:10 +08:00
Karl Seguin 91f596eba3 Merge pull request #3442 from lightpanda-io/wpt-fetch
webapi: improve various WPT fetch apis
2026-09-09 06:52:44 +08:00
Karl Seguin 816d9daa98 Merge pull request #3446 from lightpanda-io/performance-eventtarget
webapi: Performance is an EventTarget
2026-09-09 06:52:11 +08:00
Muki Kiboigo 6de56aedae wrap debugValue in try catch 2026-09-08 13:55:54 -07:00
Muki Kiboigo 3f6b0d2d4a fix notification use-after-free 2026-09-08 11:54:34 -07:00
Scott Taylor 37850aa84e fix: report dataset named property presence via query interceptor
Without a query callback on DOMStringMap's named property interceptor,
'name' in element.dataset and Object.hasOwn(element.dataset, name)
returned true for every name, because the getter intercepts absent
keys as undefined. Pages that feature-detect data-* attributes in
custom element constructors took the wrong branch; one observed
pattern (a constructor that reparents itself when a data attribute is
present) turned cloneNode(true) into an unbounded loop over a growing
live child list, ending in a watchdog termination.

Add a query callback that maps the camel-case name to its data-*
attribute and reports actual presence, matching spec and other
engines.
2026-09-08 14:31:06 -04:00
Adrià Arrufat a32d30fa65 cli: suggest the closest enum value on a typo
A misspelt value for an enum-typed flag now names the nearest tag as
did_you_mean. --dump's peeking validator treats a word within two
edits of a format name as that mistake rather than as the url, so
--dump htmx no longer becomes a second url.

tagNames moves from Config into cli so both can use it.
2026-09-08 17:33:48 +02:00
Adrià Arrufat 88d133a676 cli: suggest the closest flag or command on a typo
An unknown --flag now logs the nearest accepted spelling within two
edits as did_you_mean, painted green next to the red typo in the pretty
log format; logfmt stays plain. A bare first argument within two edits
of a command name is rejected with the same hint instead of being
fetched as a url.

The Levenshtein helper moves from SlashCommand into string.zig so the
agent REPL and the CLI share it, with the table widened to fit the
longest flag name.
2026-09-08 16:50:46 +02:00
Karl Seguin 1105aec02b perf: improve nth-* CSS selector performance
This adds an NthCache which will cache the ordinal position of elements. Only
nodes which have >= 32 sibblings are cached - the cache has performance/memory
overhead and for smaller nodes, walking is cheaper.

Using the new benchmark: https://github.com/lightpanda-io/demo/pull/245 under
particularly bad conditions (W=4000):

main:
  case                      match   iters    us/query
  :nth-child(2n)             2000       2     55862.5
  :nth-of-type(2n)           1999       2     57675.0
  :nth-last-of-type(2n)      1999       2     53935.0
  ancestor :nth-child(2n)    4000       1    111855.0
  list of two nth            2667       1    111180.0

PR:
  case                      match   iters    us/query
  :nth-child(2n)             2000     258       388.1
  :nth-of-type(2n)           1999     245       409.6
  :nth-last-of-type(2n)      1999     245       409.0
  ancestor :nth-child(2n)    4000     168       596.1
  list of two nth            2667     160       626.8

Firefox
  case                      match   iters    us/query
  :nth-child(2n)             2000     460       217.4
  :nth-of-type(2n)           1999     445       224.7
  :nth-last-of-type(2n)      1999     260       384.6
  ancestor :nth-child(2n)    4000     246       406.5
  list of two nth            2667     294       340.1

With no regressions in the other cases.
2026-09-08 20:43:30 +08:00
Karl Seguin 3061930153 chore: refactor Execution and GlobalScope
The js.Execution is the API behind the Frame/WGS split, but the split is
actually held by the underlying js.GlobalScope. Most Execution methods are:

```zig
    return switch (self.js.global) {
        inline else => |g| g.isSameOrigin(url),
    };
```

And that works well, except that in some cases, code has a js.Context, not an
js.Execution, and they need to do the same inline switch.

This commit moves GlobalScope from src/browser/js to src/browser (there's
nothing JS/v8 about it), and moves all those inline switches into it. The
js.Execution API stays the same (it forwards the call to js.global)
but all callers that directly inlined switched the js.global no longer do.
2026-09-08 17:46:11 +08:00
Karl Seguin 1c9ec1b2c7 webapi: Performance is an EventTarget
Raises "resourcetimingbufferfull" when full.
2026-09-08 17:18:52 +08:00
Karl Seguin 5d732eb8f1 Merge pull request #3445 from lightpanda-io/timer-caps
stability: raise timer caps
2026-09-08 16:27:37 +08:00
Karl Seguin 57d6436a46 Merge pull request #3436 from lightpanda-io/nikneym/ws-msg-int-overflow
`WS`: guard against integer overflow when parsing message length
2026-09-08 16:09:18 +08:00
Adrià Arrufat 328af59215 stability: raise timer caps
A paginated storefront listing holds ~2.7k pending timers, which crosses
the 2048 table cap. Past it setTimeout throws TooManyTimeout into the
framework's scheduler, which turns a busy page into a retry storm. No
browser throws there: raise the combined cap to 8192 and repeating timers
to 2048 so it stays a runaway backstop, not a budget.
2026-09-08 09:56:34 +02:00
Halil Durak 56c1694175 WS: guard against integer overflow when parsing message lengths
Tried to not to change function signature by relying on saturating addition; could've implemented differently, though I'm not sure if returning an error here would make a huge difference.
2026-09-08 10:46:25 +03:00
Pierre Tachoire 8cb0d4ca34 Merge pull request #3443 from agilgur5/fix-docs-typo-benchmark
docs: fix typo in benchmark summary
2026-09-08 07:51:23 +02:00
Anton Gilgur c18d46c5cc docs: fix typo in benchmark summary
- missing "x" for multiple: it said "16 less" when it should be "16x less"
  - this also matches the style for the line below which says "9x faster"
2026-09-08 01:34:46 -04:00
Ramiro_quai e2d878eee8 fix(input): mousedown focuses tabindex targets, not only contenteditable
focusEditingHostForMouseDown only walked contenteditable hosts, so a
div[tabindex=0] stayed unfocused after click. Replace it with
focusForMouseDown: still prefer the outermost editing host, then focus
the nearest mouse-focusable element (including tabindex=-1).

Call sites: actions.click, CDP triggerMousePress, WebDriver pointerDown.

Tests cover the MCP selector path, agent Page.click on the HTML fixture,
and a runtime-created child click (ancestor walk, non-focusable must not
steal focus, tabindex=-1 is mouse-focusable).
2026-09-07 23:31:09 -06:00
Karl Seguin b633dc4b16 webapi: improve various WPT fetch apis
Headers strip whitespace and guard against invalid characters

Headers iterator sorts and combines PER step, so that mutations are picked up.
Not the most efficient, but this is a short list, and how often are these being
iterated?

XMLHttpRequest: has its own extra header validation

Mime support for multiple Content-Type headers (or a header with multiple values)
last value wins.

Add BufferSource js bridge type that accepts various types -> []const u8 (at the
cost of losing the actual type). Useful in fetch, where various types can be a
body, but we only care about the underlying bytes (e.g. we didn't support A
rrayBufferView before this)

Refactored response body getters so that they all go through the same consume
and resolve logic
2026-09-08 13:12:20 +08:00
Ramiro_quaiandClaude Sonnet 5 46ac5094c5 fix(actions): address review on click's mouse/pointer sequence
Round-1 review feedback on the pointerdown/mousedown/pointerup/mouseup/
click sequence added in 3e8ff142e:

- Guard disabled elements up front (el.isDisabled()), matching the checks
  WebDriver.click and HtmlElement.click already have — otherwise a
  disabled checkbox/button still activates.
- A cancelled pointerdown now suppresses both mousedown and mouseup for
  the gesture (one check, not two independent ones — see below).
- mousedown now calls Frame.user_input.focusEditingHostForMouseDown,
  matching the CDP path in frame/user_input.zig, so clicking a
  contenteditable host or tabindex target actually focuses it.
- updateHoverTarget(..., .{ .with_pointer = true }) fires before the
  first pointerdown, matching the hover step both other click paths take.
- click is now dispatched as a PointerEvent (pointerType "mouse",
  pointerId 1), matching HTMLElement.click(), with pressure 0.5 while a
  button is down.
- Dropped the always-0 `button` param from both dispatch helpers, merged
  the duplicated dispatch/log code into one dispatch() helper, dropped
  the restated clientX/clientY = 0 defaults, trimmed the doc comment.

Test coverage: the click assertion in tools.zig now checks the exact
five-event sequence (type:button:buttons:pointerType:isTrusted) instead
of a single boolean. Two new fixtures in mcp_actions.html close the gaps
the weaker test couldn't see: a button whose pointerdown listener calls
preventDefault() (asserts the sequence collapses to exactly pointerdown,
pointerup, click — no mousedown/mouseup), and a disabled button (asserts
mousedown never fires).

The first draft of the suppression fix wrongly gated mouseup on
pointerup's own preventDefault() instead of pointerdown's; the new
preventDefault fixture catches that regression too, confirmed by
reintroducing it and watching the assertion fail before restoring the
correct version.

Full suite (1339 tests) and zig fmt --check pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 13:42:58 -06:00
Pierre Tachoire 909108e293 Merge pull request #3435 from lightpanda-io/remove-beta 2026-09-07 13:57:14 +02:00
Karl Seguin 0f0abf02ea Merge pull request #3409 from lightpanda-io/contextless-custom-elements
webapi: don't upgrade custom elements in a windowless document
2026-09-07 17:46:11 +08:00
Karl Seguin 92d5f8f7ad Merge pull request #3412 from lightpanda-io/worker-cancelled-not-error
webapi: don't fire error event when a worker script fetch is aborted
2026-09-07 17:43:30 +08:00
Karl Seguin 3387310f6e Merge pull request #3426 from lightpanda-io/micro-pseudoclass-parse
perf: Micro-optimize pseudoclass parsing
2026-09-07 17:42:42 +08:00
Karl Seguin 82344c609f Merge pull request #3432 from lightpanda-io/tweak-http-timeouts
http: tweak http timeouts
2026-09-07 17:41:46 +08:00
Karl Seguin 403c5f99c0 Merge pull request #3430 from lightpanda-io/parse-context
webapi: Add context when parsing HTML
2026-09-07 17:41:29 +08:00
Pierre Tachoire 9355cd898b Merge pull request #3434 from lightpanda-io/cors-ci
ci: enable cors
2026-09-07 11:35:47 +02:00
Pierre Tachoire 1717db30b3 update features and and Bidi 2026-09-07 10:35:33 +02:00
Halil Durak 7175148ceb Merge pull request #3245 from lightpanda-io/nikneym/adblock-request-engine
`AdBlocker`: request engine
2026-09-07 11:29:05 +03:00
Pierre Tachoire e3b2696150 remove beta and add a link to WPT results 2026-09-07 10:28:44 +02:00
Halil Durak 7ad73d0a6d changes after rebase 2026-09-07 11:14:15 +03:00
Halil Durak 860c4950e2 first 128 tokens cached at init (common), rest streamed by each engine
Eager tokenization is ~7% of a ~2.1 µs match. A lazy fill saved nothing because every request reaches the first engine. Streaming from scratch per engine cost +10% capped and +16% uncapped, and stayed +10% even with exception gating. The 128 cap changed 1 verdict in 242,908. So we went with hybrid approach: no token is lost, and 97% of URLs still pay one tokenization.
2026-09-07 11:01:03 +03:00
Halil Durak fb58901604 pass *const Request where possible
* remove unnecessary `pub` marking
* metrics tracking cosmetic filters separately
2026-09-07 11:01:03 +03:00
Halil Durak 0a6d43c2bb HttpClient.isAdBlocked should just delegate Adblocker.isBlocked 2026-09-07 11:00:47 +03:00
Halil Durak 486c888080 drop is_subframe and notification 2026-09-07 11:00:47 +03:00
Halil Durak e696a29da7 metrics: make adblocker verdicts measurable 2026-09-07 11:00:05 +03:00
Halil Durak 085b4836ac Adblocker: parser semantics: follow uBO's behavior
* `@@…$important` -> `error.InvalidOption`
* `||host`, `||host^`, `||host|` (and bare `host|`/`|host` lines) all read as "hostname or subdomain" and land in the trie when option-free.
* Wildcard trimming now follows uBO's pointless-wildcard rules.
2026-09-07 10:57:36 +03:00
Halil Durak b60f790a03 Adblocker: changes on request construction & tokenization
* Engine.Request.fromHttp(req, source_url, buffers) now builds the adblock request straight from HttpClient.Request.
* The URL is tokenized once per request (hashed into the Request, shared by all engines); capped at 128 tokens (same as adblock-rust).
* Document hostname longer than 253 bytes now skips adblocking.
2026-09-07 10:57:36 +03:00
Halil Durak 6a85b1f386 handle all switch cases (emerged after rebase to main) 2026-09-07 10:57:36 +03:00
Halil Durak 53f513f1f8 remove unnecessary pub marking 2026-09-07 10:57:35 +03:00
Halil Durak 814a2ab549 update Config + help.zon 2026-09-07 10:57:35 +03:00
Halil Durak 8aa0dda4b3 integrate request engine to Adblocker, apply changes required for filter list in HttpClient 2026-09-07 10:57:35 +03:00
Halil Durak 0b2f14194e AdBlocker: initial implementation for request engine
`Parser`: don't drop cosmetic lines

introduce url pattern matcher

yet-another-url-parser
2026-09-07 10:57:11 +03:00
Pierre Tachoire d00e6e6e4f ci: enable cors 2026-09-07 09:43:26 +02:00
Karl Seguin 6904e9ee49 Merge pull request #3397 from lightpanda-io/isolatedworld-frames
CDP: create an context per isolated world per frame
2026-09-07 14:53:49 +08:00
Karl Seguin e1500338d7 Merge pull request #3424 from navidemad/fix-b5-caret-movement-keys
webapi: move the text entry cursor on caret movement keys
2026-09-07 14:29:14 +08:00
Karl Seguin ec61861b20 http: tweak http timeouts
change --http-timeout default to 15000 (up from 5000)
change --http-connect-timeout default to 8000 (down from 300000, curl's default)

5 second _total_ transfer time can be a little tight. I generally don't see a
good reason to overly limit this value.

Worth noting that help.zon said the default for --http-timeout was 10000, but
it was, in fact, 5000.

Hopefully this improve situations like https://github.com/lightpanda-io/browser/issues/3395
which I believe are due to slow proxies.
2026-09-07 13:19:52 +08:00
Karl Seguin 75b4490ca1 webapi: Add context when parsing HTML
Parsing HTML has different modes. Parsing HTML when setting innerHTML can be
different than parsing HTML inside a template, can be different than ...

html5ever handles this for us, provided we give it the correct context (the
tag name that the content is being parsed into). This adds an optional *Element
to the Parser which is fed into html5ever (its tagname).

Fixes: https://github.com/lightpanda-io/browser/issues/3336
2026-09-07 09:10:26 +08:00