Commit Graph
8105 Commits
Author SHA1 Message Date
Karl Seguin dcd8a6ed07 fix: Prevent class selector from doing substring match
Previously, "aa" would have matched "baaa". Now the matching is strict equality
on tokenized words.
2026-07-16 16:07:20 +08:00
Karl Seguin f40fd3a0bc Merge pull request #2958 from lightpanda-io/dom-pr-17-testdriver-actions
webapi: wheel/touch actions, javascript: links, GamepadEvent, actionSequence timing
2026-07-16 15:34:58 +08:00
Karl Seguin 0fcda2635f Merge pull request #2978 from lightpanda-io/cdp-going-away-on-terminate-pending
cdp: send a going-away close frame (1001) on pending terminate
2026-07-16 15:23:49 +08:00
Karl Seguin d925b92cd7 Merge pull request #2976 from lightpanda-io/browser_context_session_id
cdp: support explicit browser context session_id
2026-07-16 15:21:16 +08:00
Karl Seguin 888d6fd52f free WebDriver actionSequence resolver 2026-07-16 15:17:17 +08:00
Pierre Tachoire fc45c0980f cdp: send a going-away close frame (1001) on pending terminate
Previously tick() tore the connection down without a WebSocket close
frame, so clients saw an abnormal closure (1006). Safe to send from
tick(): the worker thread is the sole writer of the socket.
2026-07-16 09:09:49 +02:00
Karl Seguin 9ff4fc2705 Merge pull request #2957 from lightpanda-io/dom-pr-16-range-clone-extract
webapi: Range cloneContents/extractContents; replaceChild live-range ordering
2026-07-16 13:51:14 +08:00
Karl Seguin 914bf027be Merge pull request #2941 from lightpanda-io/websocket-delivery
websocket: Process WebSocket message through delivery query
2026-07-16 13:17:18 +08:00
Francis BouvierandKarl Seguin 2d52bd4f8e webapi: resolve the element's frame in hasNonPassiveListener
Review pattern from #2944: an injected `frame` parameter is the frame of
the calling realm, not the frame owning the element. The wheel/touch
cancelability check consulted the caller's event manager and window; for
an element living in another frame (e.g. inside an iframe) its listeners
are registered in its own frame's event manager and its propagation path
ends at that frame's window. Resolve the frame through Element.ownerFrame
like the other cross-realm-safe paths.

Co-Authored-By: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-16 13:06:51 +08:00
Francis BouvierandClaude Fable 5 9bd5aa3885 webapi: replaceChild removes the old child before inserting the new one
Fixes the 21 failing subtests of WPT
/dom/ranges/Range-mutations-replaceChild.html (39/60 -> 60/60): live
range boundary points anchored on the parent were off by one because we
inserted the new child before removing the old one. Per the DOM
"replace" algorithm, the reference points are captured first (child's
next sibling, or node's own next sibling when they're adjacent), the
old child is removed, and only then is the new node inserted before the
reference - each step running the live-range update rules in that
order.

Self-replacement (replaceChild(c, c)) now also performs the actual
remove-and-reinsert instead of only queueing records, so ranges
anchored inside the node move to its old position, as the remove step
requires.

Node-replaceChild.html and MutationObserver-childList.html stay fully
green.

Coverage: /dom/ranges/Range-mutations-replaceChild.html 39/60 -> 60/60
(fully green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 13:06:51 +08:00
Francis BouvierandClaude Fable 5 65e4b3c612 webapi: WebDriver.actionSequence resolves when the actions have run
Fixes WPT /dom/events/focus-event-document-move.html: testdriver's
Actions().send() promise resolved immediately (the vendor glue returned
Promise.resolve()) while the action sequence runs on the next scheduler
tick, so tests asserting right after `await ...send()` observed the
pre-action state.

actionSequence now returns a promise that a persisted resolver settles
once the input sources have been performed; the testdriver vendor glue
returns it. The persisted resolver handle is page-managed (persist
tracks it on the context), so the task does not reset it itself - doing
so double-freed the v8 global at page teardown.

Coverage: /dom/events/focus-event-document-move.html 0/1 -> 1/1 (fully
green); /dom/events regression clean (201 files).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 13:06:51 +08:00
Francis BouvierandClaude Fable 5 18df15959b webapi: add the GamepadEvent interface
Fixes WPT /dom/events/Event-timestamp-high-resolution.https.html
("window[eventType] is not a constructor"): the test constructs a
GamepadEvent and checks its timeStamp against performance.now().

GamepadEvent is a plain Event subclass with a gamepad member that is
always null - there are no gamepads in a headless browser - following
the DeviceMotionEvent pattern.

Coverage: /dom/events/Event-timestamp-high-resolution.https.html
0/1 -> 1/1 (fully green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 13:06:51 +08:00
Francis BouvierandClaude Fable 5 1187621f1b webapi: clicking a javascript: link runs the script
Fixes the last failing subtest of WPT /dom/events/Event-dispatch-click.html
("pick the first with activation behavior <a href>", 32/33 -> 33/33):
following a link whose href is a javascript: URL must evaluate the URL
body as script in the link's frame. We explicitly ignored such hrefs,
so the test's completion callback never ran.

Anchor activation now schedules the script on the frame's JS scheduler
(navigation is a queued task) and compiles/runs it in the frame's
context, ignoring the completion value (a string result would replace
the document, which nothing relies on here). The URL body should be
percent-decoded per spec; markup hrefs rarely are, so that's left as a
TODO.

Coverage: /dom/events/Event-dispatch-click.html 32/33 -> 33/33 (fully
green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 13:06:51 +08:00
Francis BouvierandClaude Fable 5 8ff4711c21 webapi: wheel/touch testdriver actions; passive-listener cancelability
Fixes all 29 failing files under /dom/events/non-cancelable-when-passive/
(13/42 -> 42/42 files passing):

- WebDriver wheel actions only worked with an element origin;
  testdriver's Actions().scroll() uses the viewport origin, so nothing
  was dispatched. Viewport origins now resolve their target through the
  faux layout (a new vertical-axis-only elementFromPoint variant, since
  the faux layout gives elements no useful horizontal extent), falling
  back to the document element. The faux dimensions also learn
  vh/vw units (resolved against the page viewport), which the tests'
  200vh scroll containers rely on.
- Wheel dispatch also fires the legacy mousewheel event, like Blink.
- Touch pointer sources (Actions().addPointer("touch")) now dispatch
  touchstart/touchmove/touchend (with pointer events, without mouse
  events) instead of being treated as a mouse.
- Per the cancelability rules for scroll-blocking events, wheel,
  mousewheel and touch events are dispatched cancelable only when some
  listener on the propagation path (target chain plus window) is
  non-passive: the UA knows preventDefault can't be called otherwise.

Coverage: /dom/events/non-cancelable-when-passive/: all 42 files pass
(29 newly passing, 1 subtest each); no regressions across /dom/events/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 13:06:51 +08:00
Francis BouvierandClaude Fable 5 7e97e77bab webapi: spec algorithms for Range.cloneContents and extractContents
Fixes all remaining failures of WPT /dom/ranges/Range-cloneContents.html
(171/187 -> 187/187) and Range-extractContents.html (153/187 ->
187/187):

- cloneContents only handled same-container and sibling-boundary
  ranges. It now implements the DOM "clone the contents" algorithm on
  explicit boundary points: partially contained CharacterData
  boundaries are cloned with the substring, partially contained
  elements are cloned shallow with the subrange recursed into the
  clone, contained nodes are cloned deep, and a contained doctype
  throws HierarchyRequestError.
- extractContents was cloneContents + deleteContents, which recreated
  the extracted nodes ("you created or detached nodes when you weren't
  supposed to"). It now implements the "extract" algorithm: contained
  nodes MOVE into the fragment preserving identity; only the boundary
  CharacterData substrings and the partially contained element shells
  are cloned, with the originals truncated via replaceData. Children
  are classified before anything moves, since moving a contained child
  shifts the indices the boundary comparisons rely on. The range then
  collapses to the same new node/new offset rule as deleteContents.

Coverage:
- /dom/ranges/Range-cloneContents.html 171/187 -> 187/187 (fully green)
- /dom/ranges/Range-extractContents.html 153/187 -> 187/187 (fully green)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 13:06:50 +08:00
Karl Seguin 1a3d7594a3 Merge pull request #2956 from lightpanda-io/dom-pr-15-range-basics
webapi: quirks-mode class matching; Range createRange/collapse/deleteContents
2026-07-16 13:06:13 +08:00
Karl Seguin 41823f06c4 limit range collection to container range 2026-07-16 12:41:20 +08:00
Karl Seguin 1c24379c9f Merge pull request #2955 from lightpanda-io/dom-pr-14-insertion-validity
webapi: pre-insert validity, Attr adoption, fragment/replaceChild mutation records
2026-07-16 11:36:11 +08:00
Francis BouvierandKarl Seguin 60abfbc4f9 webapi: move getCompatMode out of the JsApi bridge block
Review pattern: the JsApi struct is for JS/v8 bridging only; getters
with actual logic belong on the type. getCompatMode moves next to
isQuirksMode and the bridge accessor just references it.

Co-Authored-By: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-16 11:19:10 +08:00
Francis BouvierandClaude Fable 5 5bc2d8ede2 webapi: implement the spec algorithm for Range.deleteContents
Fixes the 20 failing subtests of WPT /dom/ranges/Range-deleteContents.html
(105/125 -> 125/125) and 12 of Range-extractContents.html (which
delegates its deletion half): deleteContents only handled same-container
ranges and the "boundary containers are siblings" case, and always
collapsed to the start point.

It now follows the DOM algorithm:

- same-CharacterData ranges replace the data in place (replaceData, so
  live ranges update);
- the top-most contained nodes (contained per boundary-point comparison,
  with no contained parent) are collected before any mutation and
  removed wherever they live in the tree, not just among siblings;
- partially contained CharacterData boundaries are truncated with
  replaceData;
- the range collapses to the spec's "new node/new offset": the start
  point when the start node is an inclusive ancestor of the end node,
  otherwise just after the highest partially-contained ancestor of the
  start node.

Coverage:
- /dom/ranges/Range-deleteContents.html 105/125 -> 125/125 (fully green)
- /dom/ranges/Range-extractContents.html 141/187 -> 153/187

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:19:10 +08:00
Francis BouvierandClaude Fable 5 70ed3170a7 webapi: Range.collapse() defaults to collapsing to the end
Fixes the 44 failing subtests of WPT /dom/ranges/Range-collapse.html
(142/186 -> 186/186): per the DOM IDL, collapse(optional boolean
toStart = false) collapses the range to its END point when the argument
is omitted; we defaulted to the start.

Internal callers (deleteContents) already pass an explicit true and are
unaffected.

Coverage: /dom/ranges/Range-collapse.html 142/186 -> 186/186 (fully
green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:19:10 +08:00
Francis BouvierandClaude Fable 5 aa12ed5e99 webapi: createRange() boundary points start in the document it's called on
Fixes the 22 failing subtests of WPT /dom/ranges/Range-cloneRange.html
(40/62 -> 62/62): per the DOM spec, document.createRange() returns a
range whose start and end are (document, 0) - the document the method
was called on. The range factory hardcoded the frame's main document,
so foreignDoc.createRange() produced a range rooted in the main
document.

Factory.abstractRangeIn takes the initial container; createRange passes
its own document, and Range.init keeps the main-document default for
internal callers.

Coverage: /dom/ranges/Range-cloneRange.html 40/62 -> 62/62 (fully
green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:19:10 +08:00
Francis BouvierandClaude Fable 5 c03a8a3376 webapi: quirks-mode documents match class names case-insensitively
Fixes WPT /dom/nodes/getElementsByClassName-14.htm: in quirks mode
getElementsByClassName must match class names ASCII
case-insensitively (class="a A" matches "a" twice), while Unicode case
stays significant.

The document had no notion of quirks mode at all (compatMode was
hardcoded to "CSS1Compat"). Document.isQuirksMode approximates the
HTML parser's mode: an HTML document without a doctype child is in
quirks mode (legacy doctypes that also trigger quirks are not
detected). compatMode now reports BackCompat accordingly, and
getElementsByClassName bakes the mode into its live-collection filter
(ClassNameFilter), with classAttributeContainsCase doing the
ASCII-case-insensitive token scan.

Coverage: /dom/nodes/getElementsByClassName-14.htm 1/2 -> 2/2 (fully
green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:19:10 +08:00
Karl SeguinandClaude Fable 5 c0ac3afecd webapi: spec-exact replaceChild records: fragment removal record, sibling capture
- replaceChild with a DocumentFragment still queues the fragment's own
  removal record (the spec's insert algorithm queues it regardless of
  suppressObservers); only the parent-side addition record is suppressed
  in favor of the combined record.
- The combined record's previousSibling/nextSibling are captured before
  new_child is removed from its old position, per the replace algorithm's
  step order, so replacing a child with its immediate previous sibling
  reports that sibling.
- The fragment-into-document validity check treats CDATASection as a
  Text node, matching the direct-node check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:18:55 +08:00
Karl Seguin acf7ea5115 cdp: support explicit browser context session_id
Goal is to better support attachToBrowserTarget by giving the browser context
its own session_id. Without this calls to attachToBrowserTarget clobber the
bc.session_id which is the page/target session_id.
2026-07-16 10:38:37 +08:00
Francis BouvierandClaude Fable 5 5c79bc4804 webapi: parser insertions into the document notify mutation observers
Fixes "parser insertion mutations" in WPT
/dom/nodes/MutationObserver-document.html (1/4 -> 2/4): a script running
during the initial document parse can observe the document with
{subtree, childList} and must receive records for the nodes the parser
inserts after it. We suppressed all notifications for main-document
parser insertions.

Parser insertions now notify per inserted node. Fragment parses
(innerHTML et al.) stay silent, since Node.setHTML queues a single
combined "replace all" record. There is no overhead in the common case:
notifyChildInserted is gated on any observer existing, which is never
true during a parse unless an earlier script registered one.

The remaining two subtests need synchronous execution of scripts
inserted by other scripts during parsing (record batching across the
two) and parser insertions into a parent removed mid-parse; both are
script-scheduling semantics, not observer plumbing.

Coverage: /dom/nodes/MutationObserver-document.html 1/4 -> 2/4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 10:29:14 +08:00
Francis BouvierandClaude Fable 5 c6b592e782 webapi: spec mutation records for fragment insertion and replaceChild
Fixes the remaining 8 failing subtests of WPT
/dom/nodes/MutationObserver-childList.html (30/38 -> 38/38, fully
green):

- Inserting a DocumentFragment emitted one record per child for both
  the removals from the fragment and the insertions into the parent.
  Per the DOM insert algorithm observers get exactly two records: one
  on the fragment with all removedNodes and one on the parent with all
  addedNodes. appendAllChildren/insertAllChildrenBefore now share
  moveAllChildren, which suppresses per-node notification and queues
  the two combined records (or none, in the silent mode replaceChild
  uses).
- replaceChild emitted separate insertion and removal records; the
  "replace" algorithm queues one combined record {addedNodes,
  removedNodes}. Removing the new child from its previous position
  still notifies separately (internal replacement), and replacing a
  node with itself reports a removal record followed by an addition
  record with no tree change, matching browsers.
- Range.insertNode into a Text container rebuilt the text as new
  before/after nodes (replaceChild + two insertBefores, three records).
  It now uses splitText and inserts before the second half: two
  records, and live ranges are updated by the split as a bonus
  (Range-mutations-replaceChild 37/60 -> 39/60).

The unit test mutation_observer/childlist.html asserted the old
two-record replaceChild; updated to the spec's single combined record.

Coverage:
- /dom/nodes/MutationObserver-childList.html 30/38 -> 38/38 (fully green)
- /dom/ranges/Range-mutations-replaceChild.html 37/60 -> 39/60

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 10:29:13 +08:00
Francis BouvierandClaude Fable 5 91a2bbcfe3 webapi: Attr.ownerDocument follows the owning element
Fixes the failing subtest of WPT /dom/nodes/Node-mutation-adoptNode.html
("Adopting an element ... owner docs of it's attributes"): after
adopting an element into another document, its attribute nodes'
ownerDocument must report the new document.

Attribute nodes are parent-less, so ownerDocument fell through to the
detached-node fallback (the per-frame owner map / main document), which
never changes on adoption. An attribute node with an owning element now
delegates to that element's ownerDocument; detached Attr nodes keep the
old resolution.

Coverage:
- /dom/nodes/Node-mutation-adoptNode.html 1/2 -> 2/2 (fully green)
- /dom/nodes/attributes-namednodemap-cross-document.window.html 0/2 -> 1/2

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 10:29:13 +08:00
Francis BouvierandClaude Fable 5 bf3c858b35 webapi: spec-ordered, complete pre-insert validity for node insertion
Fixes the remaining failures of WPT /dom/nodes/Node-insertBefore.html
(16/40), Node-replaceChild.html (15/29) and Node-appendChild.html
(9/11) - all three are now fully green.

The insertion validity checks were incomplete and ran in the wrong
order:

- The reference-child NotFoundError check ran before the parent-type
  and cycle checks, but per "ensure pre-insert validity" the
  HierarchyRequestError checks for the parent kind and for node being
  an inclusive ancestor of parent come first.
- Inserting a Document node was not rejected.
- DocumentFragment insertion into a document skipped validation
  entirely: fragments with multiple elements, with a Text child, or
  whose element joins an existing document element now throw.
- The doctype rules were missing: a second doctype, a doctype inserted
  after an element, and an element inserted before a doctype all throw,
  with replaceChild's variants (the replaced child doesn't count).
- replaceChild threw HierarchyRequestError for a child with the wrong
  parent; the spec requires NotFoundError (unit test updated
  accordingly).
- insertBefore's reference-child argument is required-but-nullable per
  WebIDL: omitting it is now a TypeError (js.Nullable), while passing
  null still appends.

appendChild/insertBefore/replaceChild now share ensurePreInsertValidity
(insert and replace modes); replaceChildren keeps its replace-all
validation.

Coverage:
- /dom/nodes/Node-insertBefore.html 16/40 -> 40/40 (fully green)
- /dom/nodes/Node-replaceChild.html 15/29 -> 29/29 (fully green)
- /dom/nodes/Node-appendChild.html 9/11 -> 11/11 (fully green)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 10:29:13 +08:00
Karl Seguin 581eafcf7e Merge pull request #2954 from lightpanda-io/dom-pr-13-traversal
webapi: TreeWalker, NodeFilter and NodeIterator spec conformance
2026-07-16 10:28:26 +08:00
Karl Seguin fe5012c482 fix potential UAF 2026-07-16 09:55:40 +08:00
Karl Seguin 268a487719 Merge pull request #2975 from lightpanda-io/eventsoruce-relative
Fix: Allow EventSource with relative URLs
2026-07-16 08:30:34 +08:00
Karl Seguin 3e51547350 Merge pull request #2968 from rohitsux/feat/cdp-get-partial-ax-tree
feat(cdp): implement Accessibility.getPartialAXTree
2026-07-16 08:16:58 +08:00
Karl Seguin 8ec64547e7 Fix: Allow EventSource with relative URLs 2026-07-16 08:06:43 +08:00
Karl Seguin 10c46aabc8 Merge pull request #2921 from lightpanda-io/request-finalizer
mem: Make Request, URLSearchParams finalized
2026-07-16 07:53:46 +08:00
Karl Seguin aa8bcb67e1 log not implemented on fetchRelatives == true (default) 2026-07-16 07:53:01 +08:00
Francis BouvierandClaude Fable 5 20df3d5820 webapi: implement NodeIterator pre-removing steps
Fixes WPT /dom/traversal/NodeIterator-removal.html (0/23 -> 23/23) and
/dom/nodes/moveBefore/moveBefore-nodeiterator.html: removing a node
that is an inclusive ancestor of a live NodeIterator's reference node
must move the reference per the DOM pre-removing steps. We never
adjusted iterators, so the reference kept pointing into the detached
subtree.

The frame keeps an intrusive list of live NodeIterators (mirroring
_live_ranges; iterators are slab-allocated for the frame lifetime, so
they are never unlinked) and Frame.removeNode runs the steps while the
tree is still intact:

- removing the root or an ancestor of the root leaves the iterator
  untouched (matching browsers and the WPT model);
- with the pointer before the reference, the reference moves to the
  first node following the removed subtree, if any;
- otherwise (or when there is no such node) it moves to the node
  immediately preceding the removed node in tree order, clearing the
  before-pointer in the fallthrough case.

Coverage:
- /dom/traversal/NodeIterator-removal.html 0/23 -> 23/23 (fully green)
- /dom/nodes/moveBefore/moveBefore-nodeiterator.html 0/1 -> 1/1

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:49:28 +08:00
Francis BouvierandClaude Fable 5 f64952bd35 webapi: NodeFilter follows WebIDL callback interface semantics
Fixes the 5 failing subtests of WPT
/dom/traversal/TreeWalker-acceptNode-filter.html (7/12 -> 12/12):

- A filter object was converted eagerly at createTreeWalker time, so an
  object without a callable acceptNode threw "invalid argument" at
  creation. Per WebIDL any object converts to the NodeFilter callback
  interface; the TypeError belongs at invocation time.
- The acceptNode member was cached at conversion. Per "call a user
  object's operation" it must be looked up with a fresh Get on every
  traversal, rethrowing errors from a throwing getter.
- The callback was invoked with the default this; the spec requires the
  filter object itself as the this value.

NodeFilter now stores the raw function or object (js.Object.Global) and
performs the per-invocation lookup, callability check and this-binding
in acceptNode.

Coverage: /dom/traversal/TreeWalker-acceptNode-filter.html 7/12 ->
12/12 (fully green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:49:27 +08:00
Francis BouvierandClaude Fable 5 7581db26d4 webapi: TreeWalker methods throw when called from their own filter
Fixes the last failing subtest of WPT /dom/traversal/TreeWalker.html
("Recursive filters need to throw"): per the DOM traversal "filter"
algorithm, a NodeFilter that re-enters the walker (calling parentNode()
etc. from inside the callback) must get an InvalidStateError.

DOMTreeWalker tracks an active flag around the filter invocation and
throws InvalidStateError when a traversal starts while it is set.

Coverage: /dom/traversal/TreeWalker.html 760/761 -> 761/761 (fully
green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:49:27 +08:00
Francis BouvierandClaude Fable 5 ee97f3b888 webapi: TreeWalker sibling traversal follows the spec algorithm
Fixes WPT /dom/traversal/TreeWalker-previousSiblingLastChildSkip.html
and 59 subtests of TreeWalker.html (701/761 -> 760/761):
TreeWalker.previousSibling()/nextSibling() only scanned the current
node's direct siblings, but the spec's "traverse siblings" algorithm
also:

- descends into a skipped (FILTER_SKIP) sibling's children - only a
  rejected sibling excludes its whole subtree - so from B2 with B1
  skipped, previousSibling() must return B1's last child;
- climbs to the parent when the siblings are exhausted and continues
  from the parent's siblings, stopping at the root or at an accepted
  parent.

Both directions now share the spec's traverseSiblings implementation.

Coverage:
- /dom/traversal/TreeWalker-previousSiblingLastChildSkip.html 0/1 -> 1/1
  (fully green)
- /dom/traversal/TreeWalker.html 701/761 -> 760/761

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:49:27 +08:00
Karl Seguin df94585d0a Merge pull request #2953 from lightpanda-io/dom-pr-12-text-and-tokens
webapi: class-token whitespace, table row collections, wholeText, UTF-16 offsets
2026-07-16 07:46:32 +08:00
Karl Seguin 9e52b779a0 Merge pull request #2971 from lightpanda-io/cdp-expose-lightpanda-version
cdp: expose lightpanda version
2026-07-16 07:28:47 +08:00
Karl Seguin 978636f7be Extract common logic
Add infallible utf16OffsetToUtf8 variant (utf16OffsetToUtf8Floor)
2026-07-16 07:25:34 +08:00
Karl Seguin 84c72eae7f Merge pull request #2973 from lightpanda-io/htmlcollection-rc-size
crash: increase HTMLCollection's RC from u8 to u32
2026-07-15 23:07:23 +08:00
Karl Seguin d2cb58a7d1 crash: increase HTMLCollection's RC from u8 to u32 2026-07-15 22:42:14 +08:00
Pierre Tachoire 447a340366 expose LP.version including Lightpanda's version 2026-07-15 15:38:13 +02:00
Pierre Tachoire fb6e0b751b expose Lightpanda-Version into /json/version endpoint 2026-07-15 15:37:45 +02:00
Karl Seguin 4365e01530 table deleteRow without full collection + add tests 2026-07-15 20:56:28 +08:00
Rohit d75ef37d42 feat(cdp): implement Accessibility.getPartialAXTree
The Accessibility domain handled getFullAXTree and queryAXTree but not
getPartialAXTree, so a client asking for the accessibility subtree rooted at
a specific node got UnknownMethod. Tools like Playwright/Puppeteer and
axe-core use getPartialAXTree for scoped a11y snapshots.

Add it by mirroring the existing methods: resolve the node via dom.getNode
(like queryAXTree) and emit its unfiltered AX subtree via bc.axnodeWriter
(like getFullAXTree). fetchRelatives is accepted for protocol compatibility;
subtree emission matches queryAXTree's scope. Adds tests for the missing-id
and unknown-id error paths.
2026-07-15 16:36:20 +05:30
Karl Seguin 9d138c1780 Merge pull request #2952 from lightpanda-io/dom-pr-11-mutation-records
webapi: insert-adjacent semantics; combined mutation records
2026-07-15 18:18:37 +08:00