9463 Commits
Author SHA1 Message Date
Pierre Tachoire 614c1640af Merge pull request #3524 from lightpanda-io/orderfile-ci
ci: regenerate the orderfile nightly and open a PR
0.4.1
2026-09-15 14:51:17 +02:00
Pierre Tachoire 4bef9e95d2 Merge pull request #3525 from lightpanda-io/orderfile-regen
orderfile: regenerate the hot-code profile
2026-09-15 14:28:52 +02:00
Pierre Tachoire ac84bdf764 ci: revert orderfil generation on release 2026-09-15 14:25:28 +02:00
github-actions[bot] 4569fa6e59 orderfile: regenerate the hot-code profile
hot set 14876KB resident at 4KB fault-around: 21417 text, 21799 rodata symbols
2026-09-15 14:21:44 +02:00
Pierre Tachoire 2a17635332 ci: allow orderfile to push on branch 2026-09-15 14:15:46 +02:00
Pierre Tachoire f9ef67d283 ci: Use GH app to publish PR 2026-09-15 14:15:45 +02:00
Pierre Tachoire 8fc4598ff9 ci: generate orderfile before release 2026-09-15 14:15:45 +02:00
Pierre Tachoire 4b1f22ba23 ci: regenerate the orderfile nightly and open a PR 2026-09-15 14:15:45 +02:00
Karl Seguin 5f73e07cd6 Merge pull request #3520 from lightpanda-io/page-lookups
webapi: better frame integrity
2026-09-15 17:21:43 +08:00
Karl Seguin 143c395a28 Merge pull request #3519 from staylor/fix/custom-element-clone-identity
Upgrade autonomous custom-element clones in place
2026-09-15 14:13:27 +08:00
Karl Seguin ad7f644e5b Merge pull request #3517 from staylor/investigate/yj-close-timeout
Snapshot child lists during deep cloning
2026-09-15 14:13:17 +08:00
Karl Seguin 1163096946 handle constructor that disconnect itself 2026-09-15 13:43:16 +08:00
Karl Seguin 48dc72cd49 webapi: better frame integrity
Follow up to  https://github.com/lightpanda-io/browser/pull/3510

Moves the element/node lookups, e.g. `element_class_lists` from Frame to Page.
Elements and nodes can outlive a Frame (it's the reason the identity map lives
on the Page, not the frame). These maps are merely properties on Node/Elements
optimized for a specific usage-pattern (i.e. most Node/Elements don't have these
or they are never materialized from JS). So if a Node/Element can outlive the
Frame, than so too can all of their properties. And, even when an frame is alive
the properties belong to the *Node* or *Element*, NOT the Frame...accessing
those properties across frames should yield the same value / identity.

More mechanically, frame._page => frame.page and all of these lookups lose their
_ prefix. Short summary of _ prefix is:

1 - It's used to deal with Zig not allowing shadowing. This is particularly true
    in the WebApis were it happens a bit more often

2 - Early prototype was built as a stand-alone library, and the _ was used to
    signal "private" (again, working around Zig). Frame.page shouldn't be
    "private" and neither should these lookups (if we aren't going to provide
    getter/setters for them).
2026-09-15 11:26:04 +08:00
Scott Taylor c0ae2ea137 dom: upgrade autonomous custom-element clones in place
Cloning reused the synchronous createElement construction path, which
rejects a result with a parent, attributes, or children. A reparenting
constructor left its instance in the source tree while the clone received
an HTMLUnknownElement fallback with different identity.

Queue an upgrade reaction for autonomous clones instead. Their copied
attributes and descendants are present when construction runs, and super()
returns the copied node. A failed upgrade retains that node rather than
substituting a second element. Keep synchronous createElement validation.

Capture initial upgrade reactions before construction and distinguish the
precustomized state so constructor-time DOM mutations do not enqueue
custom-element lifecycle reactions prematurely.

Add Chromium-checked regressions for identity, reparenting, copied state,
attribute reaction order, importNode and failed upgrades.
2026-09-14 22:30:25 -04:00
Scott Taylor 5ab9f69b44 dom: clone a snapshot of children, not the live list
A custom element constructor can append itself to the source parent
while that parent's children are being cloned. With two trailing
self-appending elements, the live iterator reaches those new instances
and keeps cloning indefinitely, until the watchdog terminates execution.

Snapshot each child list before traversing it. Apply the same handling
to element, shadow root, fragment and document clone paths, retaining
the document path's existing appendChild behavior.

Add a bounded two-sibling regression so a broken traversal fails
without hanging the test process.
2026-09-14 22:13:56 -04:00
Karl Seguin baf45f03e9 Merge pull request #3515 from lightpanda-io/scroll-tool-container
Scroll the nearest scroll container from the scroll tool
2026-09-15 08:58:15 +08:00
Karl Seguin 8bc4cf6877 Merge pull request #3514 from lightpanda-io/loopback-secure-cookies
cookies: accept Secure and __Host- cookies on loopback origins
2026-09-15 07:54:53 +08:00
Pierre Tachoire b3c327970f Merge pull request #3335 from lightpanda-io/nikneym/lax-exception-RFC6265bis
Apply `SameSite=Lax` exception only on safe methods
2026-09-14 18:09:01 +02:00
Adrià Arrufat 1e67c6fc91 Scroll the nearest scroll container from the scroll tool
The scroll tool (MCP, agent, LP.scrollNode) wrote scrollTop on the exact
node it was given, so a leaf inside an overflow:auto panel stored an
offset on a non-scroller, the panel's own scroll listener never ran, and
the tool reported the requested coordinates as if it had worked. It also
fired a synchronous bubbling scroll on top of the async non-bubbling
scroll/scrollend the setters already schedule.

actions.scroll now resolves the nearest ancestor-or-self scroll
container, falls back to the node itself, and returns the node that
moved plus the read-back position. The tool and LP.scrollNode report
that instead of the request.

The container query moves from user_input.zig onto Element as
scrollContainer(axes), so the wheel path, the tool and WebDriver share
one resolver. WebDriver's wheel scrolled the hit-test element directly
and fired its own bubbling scroll; it now goes through
user_input.wheelScroll like CDP and BiDi wheel.

Window and Element share one ScrollToOpts. Its offsets() helper
normalizes the positional and dictionary forms once, and an omitted axis
in the dictionary form leaves that axis untouched for the window too,
matching browsers, so scrolling the window on one axis no longer resets
the other.
2026-09-14 17:48:25 +02:00
Adrià Arrufat 7f451a5c34 Merge pull request #3513 from lightpanda-io/docker-orderfile
mem: apply the orderfile to the Docker image build
2026-09-14 17:33:31 +02:00
Adrià Arrufat 1ede559ff9 cookies: accept Secure and __Host- cookies on loopback origins
Browsers treat http://localhost, *.localhost, 127.0.0.0/8 and [::1] as
potentially trustworthy, so Secure and prefixed cookies work there over
plain http. We required an https scheme, which broke cookie-auth logins
under Playwright in local development.

Add URL.isPotentiallyTrustworthy (Chromium's net::IsLocalhost rule) and
use it for the cookie prefix gates, the send-path check and cookieStore.

Closes #3477
2026-09-14 16:02:26 +02:00
Adrià Arrufat 21afa0948e mem: apply the orderfile to the Docker image build
The Linux release artifacts and the e2e bench build link with
-Dorderfile=orderfile/lightpanda.ld, but the Dockerfile runs its own
zig build without it, so the published image shipped an unordered binary.

CDP bench (demo/puppeteer/cdp.js, RUNS=100), release builds with and
without the flag, 3 alternating reps each:

  tmpfs: VmHWM 28.8MB -> 24.2MB
  ext4:  VmHWM 38.6MB -> 30.1MB

RssAnon is unchanged (~3.0MB) and avg run duration is within noise, as
expected from a link-order-only change. Cost is ~2s of link time in the
builder stage.
2026-09-14 13:34:23 +02:00
Halil Durak 93381010f1 Merge branch 'main' into nikneym/lax-exception-RFC6265bis 2026-09-14 14:27:55 +03:00
Karl Seguin 72a05c7efa Merge pull request #3510 from lightpanda-io/node-document
internal: store document in every node
2026-09-14 17:41:55 +08:00
Karl Seguin fbbfae2d29 assert node has a non-null document 2026-09-14 17:23:13 +08:00
Karl Seguin eb82e71403 Merge pull request #3511 from lightpanda-io/parser-chunked-microtasks
internal: run microtasks during parsing
2026-09-14 16:05:10 +08:00
Karl Seguin fa2e21cb57 Minor cleanup
?*Element -> *Element to getAttribute, getOrCreateAttribute, and toAttribute
which never need the option.

Assert that document._page == page.

Text use asCData() instead of constantly calling Factory.protoOf.
2026-09-14 14:53:16 +08:00
Karl Seguin 5068f6c811 Merge pull request #3509 from lightpanda-io/css-class-name
webapi: (minor) CSS WebApi should be called "CSS" not "Css"
2026-09-14 14:35:37 +08:00
Karl Seguin 2927799cd3 Merge pull request #3508 from lightpanda-io/improve-js-memory-metric
ops: improve v8 memory metric reporting
2026-09-14 14:35:12 +08:00
Karl Seguin 7382efe688 Merge pull request #3501 from lightpanda-io/frameless-documents
webapi: better handling of frameless documents
2026-09-14 14:35:00 +08:00
Karl Seguin 729051b279 internal: run microtasks during parsing
Runs microtasks during parsing, rather than waiting for parsing to complete.

We see some sites that setup MutationObserver on the root, early in a document's
code. These then get thousands (4K-10K) of MutationRecords for every added node.
We deliver these as a single batch at the end of parsing. Chrome delivers it
based on some elapsed time calculation (I think).

Both are correct, as far as I can tell. And, I don't really expect this to
change anything. But, because the batch size is fixed:

1 - the inflight metric should be flatter
2 - there could be some small reduction in retained memory (e.g. MO's
    `_pending_records` might not grow so much)
3 - `call_arena` doesn't need to dupe such a large array

Related to (1), when we do special builds that log arena usage and eliminating /
reducing this known OK behavior helps remove some noise (Or, put it this way:
I spent some time debugging this, it's more or less nothing, but it still
looks like something that needs fixing, this commit reduces that noise).
2026-09-14 13:38:05 +08:00
Karl Seguin ef18e0e1cd internal: store document in every node
Follow up to https://github.com/lightpanda-io/browser/pull/3501.

To recap: many apis use the injected-frame, when, for cross-frame operations,
can be wrong. We've been moving to using the Node's Document's Frame on a case-
by-case basis. The goal with this series of PRs is to more holistically fix it.

The main goal of this commit is to make Node.getDocument fast. Previously,
Node.nodeDocument (renamed to Node.getDocument) and Node.ownerFrame had to walk
up the _parent tree to find the document. Now there's a DocumentRegistry on
the Browser, and every Node has a `_document: u32` index. Thus, Node -> Document
is O(1). This makes it so we can have correctness without a performance cost.

The DocumentRegistry is held on the Browser because of shared CDP nodes. A
follow up should be able to move this to the Page and change the index to u16.

Adding a DocumentRegistry to Browser, and a document: u32 to Document is easy.
The reason this PR is so big is because every `node_factory` and many Factory
methods need to be aware of all of this. You can't create an HTMLDivElement
without the document it belongs to. I incorporated more expected future changes
into the node_factory/factory mechanism so that  [hopefully] the next PRs
don't have to touch any of this code (e.g. I removed Frame as a parameter and
added a *Page to every Document so that documents have access to factory/arena/
etc..because a `*Document` might not have a `*Frame`, but it will always have a
`*Page`.

Give every document an index (u32), and store that index in Node.
2026-09-14 12:05:52 +08:00
Karl Seguin 5163c6d385 Merge pull request #3506 from lightpanda-io/silence-test-logs
chore: silence expected error log in MO test
2026-09-14 08:57:19 +08:00
Karl Seguin ea1ce09753 webapi: (minor) CSS WebApi should be called "CSS" not "Css" 2026-09-14 08:56:24 +08:00
Karl Seguin 19b165d099 Merge pull request #3502 from lightpanda-io/selected-options
chore: cleanup selected / selected options
2026-09-14 08:19:34 +08:00
Karl Seguin 3adacb6900 Merge pull request #3505 from staylor/fix/window-tostringtag
Fix Symbol.toStringTag inheritance for globals and elements
2026-09-14 08:19:09 +08:00
Karl Seguin f2abadbb0e Merge pull request #3484 from lightpanda-io/xhr_cors
XHR changes for CORS WPT tests
2026-09-14 08:18:44 +08:00
Karl Seguin dcd5c796ed ops: improve v8 memory metric reporting
Report the v8 memory every 1 second during tick. The previous model only
reported at four points and would fail to correct capture memory growth between
those points.
2026-09-14 08:15:40 +08:00
Karl Seguin 27b16af770 zig fmt *eyeroll* 2026-09-14 08:05:12 +08:00
Karl Seguin 4316454979 Merge pull request #3504 from staylor/fix/link-reentrant-send
Fix CDP message lifetimes and console argument serialization
2026-09-14 08:01:39 +08:00
Karl Seguin adb2b21ccf chore: silence expected error log in MO test 2026-09-14 08:01:00 +08:00
Muki Kiboigo 22e095370b add unit test for XMLHttpRequest parseMethod 2026-09-14 07:58:57 +08:00
Muki Kiboigo 00c98313c2 use curl no body option for head requests 2026-09-14 07:58:56 +08:00
Muki Kiboigo b3655f5918 shortcut default/text getResponse instead of caching path 2026-09-14 07:58:07 +08:00
Muki Kiboigo 8bbe1907b0 parseMethod for HEAD requests in XHR 2026-09-14 07:58:07 +08:00
Muki Kiboigo 3a7b3f9e1f XHR response can return before done on text/default 2026-09-14 07:58:07 +08:00
Karl Seguin 47eb1b8581 make acquireArena names more consistent with each other 2026-09-14 07:44:21 +08:00
Scott Taylor f8183e2168 js: inherit Symbol.toStringTag from interface prototypes
Web IDL defines Symbol.toStringTag on interface prototype objects, not
instances. Setting it on instance templates left globals and internal
custom/generic element subclasses without a tag, so they reported
[object Object]. Interface prototypes also reported the wrong class string.

Deep-clone helpers that recurse into plain objects consequently traverse
host objects and their cyclic references. Locally, a storefront theme's
store cloner classified custom/generic elements as plain objects and
exhausted the JS heap, terminating the CDP connection.

Set the tag on the member template: interface prototypes for inheritance,
while namespace objects keep their existing own-property behavior.
Test class strings, property descriptors, namespace ownership, and bounded
deep cloning that preserves host-object identity.
2026-09-13 19:27:18 -04:00
Scott Taylor c284fce11a cdp: preserve message storage across reentrant notifications
Runtime.consoleAPICalled serialized object arguments with JSON.stringify,
which can run getters and toJSON callbacks. A callback can log again or
navigate, emitting further CDP events while the outer event is being built.
Resetting send_arena after each send and notification_arena after each
handler then invalidates the outer message's buffers. This produces
use-after-free in debug builds or malformed JSON that disconnects clients.

Scope both arenas to the outermost send or notification handler, including
inspector messages and error paths. Also match Chrome's console argument
representation: objects remain remote handles, primitives carry value,
and non-JSON numbers and bigints use unserializableValue. Console logging
must not invoke object getters or toJSON as a serialization side effect.

Test complete nested WebSocket messages, failure recovery, nested legacy
Console notifications, and primitive/object protocol shapes.
2026-09-13 19:27:18 -04:00
Karl Seguin 7a60c6b947 Merge pull request #3503 from lightpanda-io/curl-pipewait
Enable CURLOPT_PIPEWAIT on every easy handle
2026-09-14 06:30:43 +08:00