Commit Graph
6711 Commits
Author SHA1 Message Date
Karl Seguin 2babfad486 minor: Create ViewPort type
Move logic that was added to MediaQuery into its own ViewPort.
2026-06-12 09:19:48 +08:00
Rohit 331aa6a71a refactor(viewport): source hardcoded 1920x1080 from MediaQuery.Viewport.default
The default viewport dimensions were duplicated across six independent
sites. Point window.innerWidth/innerHeight, screen.width/height/availWidth,
visualViewport.width/height, Page.getLayoutMetrics and the
IntersectionObserver root rect at the single MediaQuery.Viewport.default
(which already documents itself as the rewire point).

No behavior change: every site keeps the same 1920x1080 values, now from
one source. This is the groundwork requested on #2664 so a future
Emulation.setDeviceMetricsOverride can move all of them together.
2026-06-11 11:59:51 +05:30
Karl Seguin d695ce10c3 Merge pull request #2690 from lightpanda-io/log_shrink
log, mem: Reduce generated code size of logger
2026-06-11 13:52:38 +08:00
Karl Seguin b145519fc3 Merge pull request #2688 from lightpanda-io/script_reentrency_too_strict
script: Force pending script evaluation after evalutate finishes
2026-06-11 12:32:13 +08:00
Karl Seguin 93346ef5a6 mem: reduce generic use in log
Experiment to see if this shrinks the build by any significant amount. Some
investigation did surface this as some of the code we control directly which
did stand out.
2026-06-11 10:21:57 +08:00
Karl Seguin 96becbd296 log, mem: Make scope and msg runtime values to shrink generated code size 2026-06-11 08:41:57 +08:00
Karl Seguin def62ebfa0 Apply endEvaluationWindow in more places 2026-06-11 07:18:14 +08:00
Karl Seguin b0426bab9b Merge pull request #2685 from lightpanda-io/shadow-dom
wpt, shadowdom: Improve shadowdom
2026-06-11 06:45:24 +08:00
Karl Seguin e8e9b0356a script: Force pending script evaluation after evalutate finishes
This commit is in the same vein as 0d9482ccbf. A
dynamic async script which completes during an evalute() does not evaluate if
`is_evaluating == true`. That's good, but we need to make sure that it _does_
eventually get evaluated. As-is, we rely on a done callback to call evaluate()
again which works for all but the last script.

This commit creates a more robust reentrancy flow. is_evaluating still guards
against reentrancy, but a new flag, `evaluate_pending` is set to true. Whenever
`is_evaluating` is set to false if `evaluate_pending` is true, we evaluate().

Similalry, during evaluate(), we better handle completed scripts during
evaluate() and process them immediately (via an outer loop).
2026-06-10 20:14:05 +08:00
Pierre Tachoire e2fc3918a0 Merge pull request #2683 from lightpanda-io/mcp-ping-object 2026-06-10 13:56:29 +02:00
Karl Seguin d1f4c40920 Merge pull request #2671 from navidemad/datatransfer-api
webapi: DataTransfer / DataTransferItem / DataTransferItemList + DragEvent (drag-and-drop file upload)
2026-06-10 19:08:07 +08:00
Navid EMAD fefc1931b9 webapi: address DataTransfer review feedback
- DataTransferItem/DataTransferItemList/Iterator forward acquireRef/releaseRef
  to the owning DataTransfer, so its pooled arena outlives any JS-held wrapper
  (fixes a potential use-after-free when JS keeps an item/list/iterator alive
  past the DataTransfer).
- addItem reads strings straight into the persistent arena via
  toStringSliceWithAlloc, removing the intermediate call_arena copy.
- normalizeFormat uses std.ascii.allocLowerString instead of dupe + lowerString.
- setData: rename dup -> owned_data for clarity.
2026-06-10 12:33:22 +02:00
Karl Seguin caeb359f75 wpt, shadowdom: Improve shadowdom
This was driven by various WPT tests in the /shadow-dom/ category. There are
4 distinct changes.

1. Template hooks into "cloned" to include the _content. This change required
   passing `deep: bool` which is why TextArea and Input are also changed (they
   ignore that new parameter)

2. Node.getRootNode and Node.ownerDocument will now traverse through the
   ShadowRoot to find the root/document

3. DOM events won't gain the Window when triggered from within a ShadowRoot

4. attachShadow now takes a full option, not just a string mode. This also
   touched a few different places since it's called internally too.
2026-06-10 15:28:11 +08:00
Karl Seguin 6bead7becd Merge pull request #2676 from lightpanda-io/intersection_observer_perf
perf; Optimize IntersectionObserver
2026-06-10 07:43:59 +08:00
Karl Seguin 843de5cd0e Merge pull request #2675 from lightpanda-io/script_preload
perf,http: Support for script preloading
2026-06-10 07:43:42 +08:00
Pierre Tachoire a52c45f309 mcp: ping's response must be an object not an array
The array returned breaks the mcp keep alive feature implemented by the
official mcp client in Go.
2026-06-09 17:40:08 +02:00
Karl Seguin d24832ee08 Move preloads out of async_scripts
async_scripts is used to block the "load" event, and preload scripts (a)
shouldn't block this and (b) might never be used.  The `preloaded_scripts` map
itself can be cleaned up on shutdown/reset.
2026-06-09 20:13:41 +08:00
Karl Seguin aa32dbeb1b clean: Map -> Set since value isn't needed
Swap `_previous_states: Map(*Element, Bool)` to `_tracked: Set(*Element)` since
we only care about membership (the value was previous always bool). This better
captures the intent.
2026-06-09 19:02:10 +08:00
Pierre Tachoire 02d6c45dad Merge pull request #2677 from lightpanda-io/agent-build-cache-invalidation
ci: fix cache invalidation for agent-build
2026-06-09 11:42:13 +02:00
Karl Seguin fa4a60680e Merge pull request #2672 from lightpanda-io/element_scroll
Add Element.scroll (and scrollTo and scrollBy)
2026-06-09 17:35:58 +08:00
Pierre Tachoire a899fbaec0 ci: fix cache invalidation for agent-build 2026-06-09 11:18:23 +02:00
Karl Seguin c77f57d476 perf; Optimize IntersectionObserver
`checkIntersection` can be called a lot...on every domChanged. And it can call
a known expensive API: `getBoundingClientRect`.

This commit reworks the code to be able to exit from checkIntersection early.
`_previous_states` is now seeded with the target so that, once reported, the
lack of entry can be used to quickly exit.

When profiling airbnb, `checkIntersection` was reported 841 times. With this
change, it was reported twice.
2026-06-09 16:57:19 +08:00
Karl Seguin c81b4d13d9 perf,http: Support for script preloading
Implement <link rel=preload as=script href=...>. The implementation is similar
to preloadImport / waitForImport. Consider a website that does something like:

```
// pseudo html
<head>
<link preload script1.js>
<link preload script2.js>
<link preload script3.js>
<link preload script4.js>

<script script1.js></script>
<script script2.js></script>
<script script3.js></script>
<script script4.js></script>
```

Then, without preloading, we hit <script script1.js></script> and block while we
load it + execute it. Repeat for 2, 3, 4 ...

With preloading, by the time we block on <script script1.js></script> all the
scripts are already being downloaded in the background.

I opted to remove the script on first use. If a script happens to be used twice
(we have seen this happen for imports, but I guess it's more rare on blocking
scripts), then it'll get re-downloaded the 2nd time, just like before (and just
like before, the http cache is a better mechanism to rely on here).

airbnb preloads 41 scripts.
2026-06-09 15:16:34 +08:00
Pierre Tachoire a06967d54a Merge pull request #2674 from lightpanda-io/test_performance_fix
test,perf: Fix leaky thread in test runner
2026-06-09 08:47:21 +02:00
Karl Seguin db260fe029 test,perf: Fix leaky thread in test runner
The TestHTTPServer leaks a thread for every connection that shuts down. This
commit correctly releases it. It also closes a leaking CDP socket.

Full test went from 20s -> 10s for me
2026-06-09 11:42:31 +08:00
Karl Seguin 80df8d2bab Merge pull request #2673 from lightpanda-io/formdata_uaf
webapi, gc: Give FormData its own arena
2026-06-09 11:04:02 +08:00
Karl Seguin 72770cf438 webapi, gc: Give FormData its own arena
Rather than relying on the frame_arena, use a distinct arena for FormData. This
generally results in tighter memory usage, but more importantly it ensures that
if FormData outlives the frame, we don't get a UAF. This can happen if the
FormData is refernced in v8 and finalized late (e.g. after the frame would
appear to still be needed).

Also, in Frame.submitForm use the explicit acquireRef and releaseRef. This
FormData can [in theory] be passed to JS, via the `formdata` event that we fire.
2026-06-09 10:45:55 +08:00
Karl Seguin 1e68d7693b Add Element.scroll (and scrollTo and scrollBy)
Needed by bluesky to render
2026-06-09 08:57:23 +08:00
Karl Seguin f4774f1ac2 Merge pull request #2668 from lightpanda-io/fix-newsession-init-failure
browser: clear session slot when Session.init fails
2026-06-09 07:09:04 +08:00
Karl Seguin 4784c29287 Merge pull request #2666 from lightpanda-io/crypto
WPT /WebCryptoAPI/
2026-06-09 07:07:12 +08:00
Navid EMAD ff1fb2dc0d webapi: add DragEvent carrying dataTransfer; wire InputEvent.dataTransfer
DragEvent extends MouseEvent (new drag_event arm in the MouseEvent type union)
and exposes a nullable dataTransfer, so JS can build a DataTransfer and dispatch
a drop/dragover event whose .dataTransfer.files is readable. Also resolves the
InputEvent dataTransfer TODO with a real field + accessor.

Both events hold a refcount on the DataTransfer for their lifetime and release
it in deinit (via the leaf acquireRef/releaseRef/deinit trio, like MessageEvent
holds a Blob), so the store's arena can't be freed out from under an event whose
JS wrapper is collected first.

Refs #2043
2026-06-08 23:05:49 +02:00
Navid EMAD 42ecdf4d02 webapi: add DataTransfer, DataTransferItem, DataTransferItemList
Implements the constructible DataTransfer interface and its item views over a
single drag-data-store: string- and file-kind items, with .files (FileList) and
.types derived from the file items so items.add(file) is visible immediately.
File refs are acquired on add and released on remove/clear; the backing FileList
is frame-tracked and the DataTransfer arena is refcounted so the GC finalizer
reclaims it, leaving no leaks.

Refs #2043
2026-06-08 22:46:59 +02:00
Karl Seguin 6d8c4e9ca6 Merge pull request #2670 from lightpanda-io/websocket_double_free
websocket,gc: Don't call cleanup from websocket.deinit
2026-06-08 22:36:42 +08:00
Pierre Tachoire bf9df04509 Merge pull request #2669 from lightpanda-io/fix-integration-cache
Fix integration cache
2026-06-08 14:24:08 +02:00
Karl Seguin 86cb0b1820 websocket,gc: Don't call cleanup from websocket.deinit
Don't call cleanup from WebSocket.deinit, since cleanup can result in deinit
being called (via rc release). This results in a double free.
2026-06-08 18:23:08 +08:00
Pierre Tachoire 8d98d7aa99 ci: add missing cache key for integration test 2026-06-08 12:05:44 +02:00
Pierre Tachoire 22d1c5ecd1 Merge pull request #2654 from lightpanda-io/form-upload-file
form: encode file inputs as multipart/form-data on submit
2026-06-08 11:47:54 +02:00
Karl Seguin 4fc0ba7dcb Merge pull request #2667 from lightpanda-io/arena_pool_debug_cleanup
Improve ArenaPool release debug reporting
2026-06-08 17:32:52 +08:00
Pierre Tachoire 3ec0c25dde Merge pull request #2665 from mvanhorn/fix/2610-axnode-password-input-textbox-role
fix: map password inputs to textbox accessibility role
2026-06-08 11:21:32 +02:00
Pierre Tachoire a7705abde0 Merge pull request #2660 from lightpanda-io/ci-save-cache
ci: save LP cache for integration tests
2026-06-08 11:20:28 +02:00
Pierre Tachoire 41cff18e75 ci: save LP cache for integration tests 2026-06-08 10:56:26 +02:00
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 530a9e0765 deinit FormData to release files 2026-06-08 10:26:02 +02:00
Adrià Arrufat bf7992f904 browser: clear session slot when Session.init fails
newSession set self.session to undefined, but left it non-null if
Session.init failed. closeSession() then ran deinit() on garbage:

- double-released the arena
- read undefined fields on the never-assigned path

Add an errdefer to null the slot on failure.
2026-06-08 10:18:48 +02:00
Karl Seguin e64aa70c34 Improve ArenaPool release debug reporting
Cherry-picked from https://github.com/lightpanda-io/browser/pull/2623 since the
main issue in that PR was directly solved by https://github.com/lightpanda-io/browser/pull/2625
but the ArenaPool change is still worth keeping. The change is: that we
check for a double-release BEFORE resetting the arena, which would cause the
invalid flow to appear in a harder-to-debug spot.
2026-06-08 15:24:27 +08:00
Karl Seguin d11d7fdbd4 zig fmt 2026-06-08 15:10:54 +08:00
Pierre Tachoire 845dac86ba FormData: fix file leak on deletion 2026-06-08 09:10:01 +02:00
Pierre Tachoire 6aa4ef074f call the ref count release after releasing coupled data 2026-06-08 08:51:01 +02:00
Pierre TachoireandKarl Seguin 4c06cfb17c use u8 for reference counter
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-06-08 08:49:07 +02:00
Matt Van Horn e7cce250d3 fix: map password inputs to textbox accessibility role 2026-06-07 23:45:20 -07:00