Commit Graph

6658 Commits

Author SHA1 Message Date
Pierre Tachoire
b2002a8dca Merge pull request #2657 from rohitsux/feat/cdp-mouse-button-clickcount
feat(cdp): support mouse button and clickCount in Input.dispatchMouseEvent
2026-06-08 10:53:59 +02:00
Pierre Tachoire
fdf6276f39 cdp: use Frame.mouse_button consts from cdp.input.zig 2026-06-08 08:42:54 +02:00
Karl Seguin
8b16a5a650 Merge pull request #2661 from lightpanda-io/async_action_sequence
Fire actionSequence on the next tick
2026-06-08 06:39:31 +08:00
Karl Seguin
c8df32b98a Merge pull request #2659 from rohitsux/feat/element-scroll-into-view
feat(webapi): implement Element.scrollIntoView
2026-06-07 13:55:56 +08:00
Karl Seguin
6522615e21 zig fmt 2026-06-07 12:34:30 +08:00
Karl Seguin
1ffc84d947 implement the IfNeeded part of scrollIntoViewIfNeeded 2026-06-07 12:32:39 +08:00
Rohit
e68def97b3 refactor(cdp): use named constants for mouse button values
Address review: replace the bare 0/1/2 button values in the
mousedown/release switch (Frame.zig) and the CDP button mapping
(input.zig) with named constants so the code self-documents.
2026-06-06 19:03:45 +05:30
Karl Seguin
802163308e zig fmt 2026-06-06 19:04:15 +08:00
Karl Seguin
c55dcf0484 Fire actionSequence on the next tick
Apparently, that's what's expected and not doing this can break some tests
2026-06-06 19:01:16 +08:00
Pierre Tachoire
29b407bc30 Merge pull request #2653 from lightpanda-io/element_set_style
add Element.style setter
2026-06-06 09:24:13 +02:00
Karl Seguin
a68598fa5d Merge pull request #2650 from lightpanda-io/fix_arena_leaks
Fix two arena leaks
2026-06-06 07:21:39 +08:00
Karl Seguin
0406451750 Merge pull request #2596 from lightpanda-io/robots-next-tick-on-sync-deny
Robots Deny on Next Tick
2026-06-06 07:21:10 +08:00
Karl Seguin
b82af40453 Merge pull request #2655 from lightpanda-io/improve_import_fail_error
Better import error return
2026-06-06 07:20:23 +08:00
Karl Seguin
50e1003be5 Merge pull request #2651 from lightpanda-io/extend_cdp_test_timeout
Extend the TCP read/write timeout from 2 second to 10.
2026-06-06 07:20:09 +08:00
Karl Seguin
c7d8cb4bb9 Merge pull request #2656 from lightpanda-io/atob_btoa
Fix atob/btoa
2026-06-06 07:19:50 +08:00
Rohit
b77d0f8ed1 feat(webapi): implement Element.scrollIntoView
Element.scrollIntoView and scrollIntoViewIfNeeded were no-op stubs.
Implement them to scroll the window so the element's position is
brought into the viewport, using the element's document position (the
same source getBoundingClientRect uses) and Window.scrollTo.

This lets automation reach below-the-fold elements before interacting
with them.
2026-06-05 20:22:34 +05:30
Rohit
1776d0ea71 feat(cdp): support mouse button and clickCount in Input.dispatchMouseEvent
Input.dispatchMouseEvent ignored the button and clickCount params, and
mousePressed only fired a click event (never mousedown). Add them:

- mousePressed now fires mousedown carrying the pressed button.
- mouseReleased fires mouseup, then the button-appropriate activation
  event: click for the main button, auxclick for the auxiliary button,
  and contextmenu for the secondary (right) button.
- a clickCount of 2 additionally fires dblclick.

This unblocks right-click, middle-click and double-click interactions
for Playwright/Puppeteer scripts. Follows the mouse event work in
#2636, #2640 and #2641.
2026-06-05 20:08:46 +05:30
Muki Kiboigo
22410510db Synthetic runNextTick takes null as ctx 2026-06-05 07:26:40 -07:00
Muki Kiboigo
572267802d fire RobotsBlocked in nextTickRun 2026-06-05 07:25:32 -07:00
Muki Kiboigo
ffcdcc6e09 add optional ctx to runNextTick 2026-06-05 07:25:29 -07:00
Karl Seguin
c4e859d735 fix tests 2026-06-05 21:19:46 +08:00
Karl Seguin
b0ebbf7b35 zig fmt 2026-06-05 20:46:48 +08:00
Karl Seguin
14aec37652 Fix atob/btoa
Passes WPT /html/webappapis/atob/base64.html

Two changes
1 - Use the forgiving decoder already in data_url
2 - Coerce input (3 => "3")

The 2nd change was more interesting. These take a js.String.OneByte as an
optimization, which doesn't coerce. To preserve this optimization a union was
used with a `raw: []const u8` fallback (and our bridge always coerces to
a `[]const u8`)
2026-06-05 20:44:19 +08:00
Karl Seguin
c21c683474 Better import error return
Just a random test I happen to see in WPT, 0/99 -> 99/99:

/html/semantics/scripting-1/the-script-element/json-module/invalid-content-type.any.worker.html
2026-06-05 19:21:43 +08:00
Karl Seguin
f0060dd677 add Element.style setter 2026-06-05 18:46:05 +08:00
Karl Seguin
37f5a8c819 Merge pull request #2648 from lightpanda-io/worker_isolate_terminate
Make worker more robust in the face of a disconnected CDP client
2026-06-05 18:27:01 +08:00
Karl Seguin
6ecf54fc32 Merge pull request #2649 from lightpanda-io/fix/deferred-context-uaf-on-teardown
fix: drop orphaned deferred contexts on frame teardown
2026-06-05 18:22:58 +08:00
Karl Seguin
c3233867c8 Extend the TCP read/write timeout from 2 second to 10.
This limit isn't about correctness,it's just about making sure a test doesn't
block forever. 2 seconds does seem like plenty of time, but I'm thinking it's a
slow/busy CI. If it still happens after this bump, could mean there's an actual
issue.
2026-06-05 18:13:24 +08:00
Karl Seguin
5db5969c92 Merge pull request #2647 from staylor/fix/synwait-teardown-interrupt
fix(http): abort blocking-script sync wait when a teardown command is queued (#2646)
2026-06-05 17:55:51 +08:00
Karl Seguin
995efd57e6 Fix two arena leaks
The first is with WGS not flushing the deferring layer after its synchronous
importScripts call, see: https://github.com/lightpanda-io/browser/pull/2329#discussion_r3271068955

The second is from the ability of an XHR request to be re-used. This was gated
on a boolean, but the ordering means that the 1st requests' released gets
blocked by the gate, and thus we're always 1 release short. The solution is to
use a counter instead of a boolean.
2026-06-05 17:32:21 +08:00
Adrià Arrufat
ee21138bde fix: drop orphaned deferred contexts on frame teardown
A fetch() deferred behind a parser-blocking script keeps a DeferredContext
in the DeferringLayer whose forward.ctx points at the Fetch struct, which
lives in a page/session arena. If the transfer completes while deferred,
it is deinited and unlinked from the frame owner, so abortTransfers ->
abortOwner can't reach the now-orphaned context. It lingers in the active
list, and when the page is torn down its Fetch arena is freed; a later
flushFrame (e.g. the next page's parser-blocking script popping) replays
the buffered header callback into the freed Fetch -> use-after-free.

Add DeferringLayer.cancelFrame to drop these orphaned (terminal) contexts
during Frame.abortTransfers. Non-terminal contexts still have a live
transfer that cleans them up through its own callback path, so they are
left alone.
2026-06-05 09:47:15 +02:00
Karl Seguin
86b9e8675e Make worker more robust in the face of a disconnected CDP client
When a CDP client disconnects, through a series of step, we call `Isolate::
TerminateExecution`. The problem is that this only terminates the currently
executing script. If scripts are nested, or another script runs immediately
after the terminated one, the worker keeps running.

I was specifically trying to fix some 100% endless loop in a few WPT tests, e.g
Worker-terminate-forever-during-evaluation.html

The first is the issue described above. We potentially need to guard every entry
into script executing with `if (!env.is_terminated)`. AND/OR we need to bubble
an error when a script _is_ terminated (right now, most JS errors map to
error.JsException which makes this hard). For the specific WPT failures, I opted
for a more targeted fix directly in the Worker. But I think we need to keep an
eye out on other cases where this can happen.

I also discovered another issue, which is not addressed is this commit:

var worker = new Worker("endlessloop.js");
worker.terminate(); <-- never gets called

Given our current architecture, the only solution I can think of is a watcher
thread (or re-using the main/network thread).
2026-06-05 13:00:35 +08:00
Scott Taylor
0bfd0222f2 fix(http): abort blocking-script sync wait when a teardown command is queued
A blocking <script src> loads via HttpClient.syncRequest, which spins on
tick(200, .sync_wait). That drain mode only dispatches Fetch-interception
methods (it can't free Page/Frame state mid-parse), so Target.closeTarget /
Target.disposeBrowserContext / Page.close sit undispatched until the blocking
fetch completes — i.e. up to the per-request timeout, per blocking script.

For storefronts with slow/never-completing third-party subresources this
stalls page.close()/context dispose for tens of seconds and collapses CDP
throughput under concurrency (the process stays up; other connections are
unaffected).

Fix: while waiting, peek the inbox; if a teardown/close command (or a
client close/disconnect) is queued, abort the in-flight blocking transfer.
syncRequest then returns the same way it already does on a fetch failure,
the parser unwinds to the next safe .all drain, and the queued command
runs there. No command is dispatched mid-parse, so no UAF.

Repro: 8 workers looping newContext->goto(commit)->page.close against a page
with 15 never-answered subresources went from 0.1 ctx/s (page.close stalling
~30-60s) to ~25 ctx/s; a no-hanging-subresource baseline is unchanged.

Fixes #2646
2026-06-04 23:17:24 -04:00
Karl Seguin
0e12790397 Merge pull request #2635 from Ar-maan05/feat-implement-file-api
Implement input type=file support (FileList, input.files/value, DOM.setFileInputFiles)
2026-06-05 10:52:23 +08:00
Karl Seguin
129d014479 Make FileList iterable / indexable
Small formatting tweaks
2026-06-05 08:27:38 +08:00
Karl Seguin
23120885be Merge pull request #2641 from rohitsux/feat/cdp-dispatch-mouse-wheel
feat(cdp): fire wheel events on Input.dispatchMouseEvent mouseWheel
2026-06-05 07:34:21 +08:00
Karl Seguin
9068a7583b Merge pull request #2638 from lightpanda-io/xhr-upload
Implement XMLHttpRequest.upload
2026-06-05 07:34:06 +08:00
Karl Seguin
0971f74a4c fix XMLHttpRequestUpload release 2026-06-05 07:01:01 +08:00
Karl Seguin
62acf1c640 Merge pull request #2643 from lightpanda-io/mime_fix
Fix Mime.
2026-06-05 06:55:16 +08:00
Karl Seguin
a9374a0254 Merge pull request #2642 from lightpanda-io/dommatrix
Add DOMMatrix and DOMMatrixReadOnly
2026-06-05 06:54:54 +08:00
Karl Seguin
5d95b55d87 Merge pull request #2637 from lightpanda-io/xhr-override-mimetype
Implement XMLHttpRequest.overrideMimeType()
2026-06-05 06:31:26 +08:00
Pierre Tachoire
cb73e43926 couple XMLHttpRequestUpload lifecycle w/ parent's XMLHttpRequest 2026-06-04 18:20:38 +02:00
Rohit
e05074dbf5 feat(cdp): fire wheel events on Input.dispatchMouseEvent mouseWheel
Wire the CDP Input.dispatchMouseEvent "mouseWheel" type to a new
Frame.triggerMouseWheel, which hit-tests the point via elementFromPoint
and dispatches a wheel event (with deltaX/deltaY) on the target. When
the wheel event is not cancelled, it applies the scroll offset and
fires a scroll event, mirroring the wheel handling in WebDriver.zig.

Previously mouseWheel was silently ignored. Follow-up to #2636.
2026-06-04 19:27:56 +05:30
Pierre Tachoire
426c167470 Merge pull request #2640 from rohitsux/feat/cdp-dispatch-mouse-released
feat(cdp): fire mouseup on Input.dispatchMouseEvent mouseReleased
2026-06-04 15:48:05 +02:00
Karl Seguin
0ec92bedbb Merge pull request #2639 from lightpanda-io/form-no-validate
Validate form constraints on interactive submit; add HTMLFormElement.…
2026-06-04 21:19:04 +08:00
Karl Seguin
121167e44e Fix Mime.
It has somehow acquired (or always had?) multiple dangling pointers. Luckily
(or worse?) they aren't used anywhere. Remove mime.params (dangles off the
input) and the content_type `.other` values (dangles off the local mime var).

Also, remove double lowerCase.
2026-06-04 20:55:11 +08:00
Karl Seguin
fb720766a1 Fix XHR document identity
Cache the xml document so that subsequent calls to getResponseXML return the
same document.

Fix testing.js harness - reject multiple testing.async() calls per block. This
isn't reliable since the runner can temporarily see the count reach 0 before
the next async block starts.
2026-06-04 20:41:54 +08:00
Karl Seguin
d7eb6d697a Add DOMMatrix and DOMMatrixReadOnly
These are needed for apple.com, completely broken without.

Obviously Claude wrote most of this code. The test that it wrote _does_ pass
in FireFox and a reasonable number of WPT *DOMMatrix* test pass.

A relatively small subset of this was needed for Apple, but there was plenty
of low-hanging fruit in the WPT tests.

Also, some of these WPT tests uncovered a name collision in our WPT reporter:
https://github.com/lightpanda-io/wpt/pull/70
2026-06-04 19:49:20 +08:00
Rohit
f697013540 feat(cdp): fire mouseup on Input.dispatchMouseEvent mouseReleased
Wire the CDP Input.dispatchMouseEvent "mouseReleased" type to a new
Frame.triggerMouseRelease, which hit-tests the point via
elementFromPoint and dispatches a mouseup event on the target,
mirroring triggerMouseClick / triggerMouseMove and the mouseup
semantics already used by WebDriver.zig.

Previously mouseReleased was silently ignored. Follow-up to #2636.
2026-06-04 16:39:25 +05:30
Pierre Tachoire
b405bed660 Validate form constraints on interactive submit; add HTMLFormElement.noValidate
Until now Frame.submitForm performed no constraint validation: requestSubmit()
and interactive submits (Enter, clicking a submit button) fired the `submit`
event and proceeded regardless of control validity — a `<form><input required>`
would submit with the field empty.

Implement the HTML "submit a form element" interactive-validation step: in the
fire_event branch, run form.checkValidity() as a gate before dispatching
`submit`, abort submission when it fails (checkValidity fires `invalid` on the
offending controls), and skip the gate when the form is in the no-validate
state. form.submit() keeps bypassing validation, per spec.

To drive the no-validate state, add the HTMLFormElement.noValidate IDL
attribute reflecting the `novalidate` content attribute, and honor a submitter's
`formnovalidate`. noValidate gates submission only — checkValidity()/
reportValidity() still validate unconditionally.
2026-06-04 12:49:14 +02:00