Commit Graph

2313 Commits

Author SHA1 Message Date
Jelle Raaijmakers
ded42e649b LibWeb: Do not scroll cursor into view on programmatic selection changes
We were mimicking Firefox' behavior that whenever a programmatic change
to an <input>'s or <textarea>'s selection happened, the new selection
focus is brought into view by scrolling. Currently we run a layout
update synchronously for that to make sure we have the fragment's
correct dimensions, which caused a significant performance regression in
Speedometer.

Since this is non-standard behavior, let's mimic Chromium instead which
does not scroll at all - only for direct user initiated input such as
typing.

Relevant issues:

* https://github.com/whatwg/html/issues/6217
* https://bugzilla.mozilla.org/show_bug.cgi?id=232405
* https://issues.chromium.org/issues/41081857
2026-02-17 10:24:00 +01:00
Aliaksandr Kalenik
3c73457b26 LibWeb: Implement CSS Grid dense packing and fix span placement
Implement the `dense` keyword for `grid-auto-flow` so auto-placed items
backfill earlier gaps in the grid. The sparse/dense cursor logic is now
centralized in `place_grid_items()` step 4: dense resets the cursor to
the grid start before each search, while sparse keeps advancing forward.

Also fix a pre-existing bug where `find_unoccupied_place()` and several
placement helpers only checked if a single cell was unoccupied, ignoring
multi-cell spans. Add `OccupationGrid::is_area_occupied()` and use it
throughout to correctly verify the entire rectangular area is available.
2026-02-16 20:00:17 +01:00
Shannon Booth
a0d4344d4e Tests/LibWeb: Import some more webstorage WPT tests
Which were helpful in determining property behaviour for the Storage
object.
2026-02-16 18:49:15 +01:00
Psychpsyo
68f27e9bbc LibWeb: Don't select text when multi-clicking user-select:none node 2026-02-16 15:57:55 +01:00
Callum Law
caa5705edf LibWeb: Clamp blur() calculated values 2026-02-16 12:09:23 +00:00
Callum Law
68c596942c LibWeb: Store FilterOperation::Color::amount as StyleValue
This simplifies handling and means we now support tree counting
functions.
2026-02-16 12:09:23 +00:00
Psychpsyo
30c1f2f938 LibWeb: Do not re-target hits to fragments with user-select:none
This makes text selection more usable around them, as demonstrated in
the added test case.
2026-02-16 08:39:28 +01:00
Callum Law
33e590dddb LibWeb: Ensure that computation context cache is always cleared
Previously we didn't clear the computation context caches after:
 - Recomputing inherited style
 - Computing keyframe values

We now clear the caches in those two cases and verify it has been
cleared before using it.

Fixes #7959
2026-02-15 17:52:11 +01:00
Aliaksandr Kalenik
79e9cea8cb Tests: Add failing test for SVG partial relayout paintable leak
The test triggers repeated partial relayout inside a nested SVG and
checks paintables on an outside-subtree SVG ancestor via
`internals.dumpPaintableTree()`. The count should stay stable, but
currently grows, revealing that partial relayout is creating extra
ancestor paintables instead of preserving existing ones.

No fix in this commit; this commit only captures the failing behavior.
2026-02-15 17:47:30 +01:00
Aliaksandr Kalenik
0bec9a1e5d LibWeb: Add dumpPaintableTree() to Internals API
Expose the paintable tree dump through the internals object, analogous
to the existing dumpLayoutTree(). This is useful for testing and
debugging painting behavior.
2026-02-15 17:47:30 +01:00
Psychpsyo
6e1f2c10d6 LibWeb: Implement basics of the WebXR testing framework 2026-02-15 10:50:25 +01:00
Callum Law
9b0263f029 Tests: Use Internals::mouseMove instead of Internals::movePointerTo
This method was renamed in f55fe69.

Fixes a test failure on master
2026-02-15 04:17:41 +00:00
Tim Ledbetter
8d0afda9f7 LibWeb: Dispatch pointer boundary events when hovered node changes 2026-02-15 02:36:01 +00:00
Psychpsyo
a7267f711b LibWeb: Add overflow-clip-margin-* properties
The corner radius isn't quite right yet, but this gives us
another couple WPT passes for these.
2026-02-14 22:58:21 +01:00
Shannon Booth
bc93ba4530 LibWeb/Bindings: Implement [SecureContext] extended attribute
Unfortunately this is a bit of a pain to test as it is surprisingly
difficult to create a non secure context in our test harness.
This is because both file scheme URLs and localhost are considered
secure contexts.

To test this, add a very specific internals setter to change the
top level origin of the environment for the current realm.
2026-02-14 20:22:40 +01:00
Tim Ledbetter
5060a61081 LibWeb: Align Navigable::reload() with the specification 2026-02-14 20:21:53 +01:00
Tim Ledbetter
dc649a7e46 LibWeb: Use reject_the_finished_promise() in abort_a_navigate_event()
This aligns our implementation with the specification. Doing this
fixes a number of WPT tests because this sets
`m_ongoing_api_method_tracker` to null, avoiding an assertion that
previously caused a crash.
2026-02-14 20:21:53 +01:00
Aliaksandr Kalenik
085cf42712 LibWeb: Fix SVG partial relayout skipping abspos sibling updates
When a CharacterData mutation inside a foreignObject triggered partial
SVG relayout, sibling absolutely positioned elements whose containing
block is outside the SVG were not being repositioned. This happened
because the check only walked ancestors of the changed node looking for
abspos elements — it never saw abspos siblings.

Fix by querying contained_abspos_children() on boxes outside the SVG
subtree, which finds all abspos elements regardless of their position
in the tree relative to the changed node.
2026-02-14 03:20:34 +01:00
Jelle Raaijmakers
83913fef84 LibWeb: Queue animation phase events as part of updating animations
Move the dispatch_events_for_animation_if_necessary() calls into step 1
of update_animations_and_send_events(), where the spec note says
updating timelines involves "Queueing animation events for any such
animations." Previously, these calls ran after step 7 (event dispatch),
causing newly queued events to be deferred by an extra rendering update.

This meant that e.g. a CSS transition triggered during an earlier
rendering step would not have its transitionrun event fired until the
next frame, instead of the current one.
2026-02-13 22:44:17 +01:00
Praise-Garfield
56287ca90f LibWeb: Clear textarea with empty string for WebDriver
The WebDriver clear handler for textarea elements sets the raw
value to child_text_content() instead of an empty string. This
is a copy-paste from the adjacent reset handler, which correctly
uses child_text_content() per its own spec. The clear spec says
"set the raw value of element to an empty string".
2026-02-13 15:29:02 -05:00
Aliaksandr Kalenik
01334c4481 LibWeb: Fix partial relayout of abspos with containing block outside SVG
When a text node changes inside an absolutely positioned element within
an SVG <foreignObject>, and the abspos element's containing block is
outside the SVG subtree, the layout invalidation was incorrectly
stopping at the SVG root boundary. This triggered partial SVG relayout,
which cannot re-layout the abspos element since it's laid out by its
containing block's formatting context (outside the SVG).

The previous check only tested whether `this` (the node triggering
invalidation, e.g. a text node) was absolutely positioned, missing the
case where an abspos *ancestor* in the path has its containing block
outside the SVG. Fix this by walking from `this` up to the SVG root and
checking every abspos node in the path. If any has a containing block
outside the SVG subtree, skip the SVG boundary so layout propagation
continues upward and a full layout runs.
2026-02-13 17:47:49 +01:00
Niccolo Antonelli Dziri
bd76078f97 LibWeb: Add constructor for Notification and getter methods
The full constructor for NotificationsAPI::Notification is implemented
along with the getter methods.
It is now possible to call the elements of Notification in JS without
getting undefined but the default values (or the ones passed in
options).

The method `current_wall_time` is added in EnvironmentSettingsObject.

This passes a least a few more tests because of the getter methods
that are created.

https://wpt.live/notifications/constructor-basic.https.html

https://wpt.live/notifications/idlharness.https.any.html
2026-02-13 16:47:42 +00:00
Andreas Kling
9e8e568b43 LibWeb: Use structural sharing for CSS custom properties
Replace per-element OrderedHashMap storage for custom properties with
a RefCounted chain (CustomPropertyData) that enables structural
sharing. Each chain node stores only the properties declared directly
on its element, with a parent pointer to the inherited chain.

Elements that don't override any custom properties share the parent's
data directly (just a RefPtr copy). During cascade, only entries that
actually differ from the parent are stored in own_values - the rest
are inherited through the chain. During var() resolution, resolved
values are compared against the parent's and matching entries are
dropped, enabling further sharing.

The chain uses a depth limit (max 32) with flattening, plus
absorption of small parent nodes (threshold 8) to keep lookups fast.

This reduces custom property memory from ~79 MB to ~5.7 MB on
cloudflare.com.
2026-02-13 14:57:15 +01:00
Shannon Booth
0b839a9e2d Tests/LibWeb: Sync WPT test for WASM global attribute setter
The regression in 932a204 turned out to be the specified
behaviour changed as part of: whatwg/webidl#1498

And WPT has now been updated accordingly.
2026-02-13 12:12:23 +01:00
Chase Knowlden
b8f31179b2 LibWeb: Use dimension image source for images
Fixes tiny images on Wikipedia
2026-02-13 10:42:38 +00:00
Andreas Kling
31cbe2061a LibWeb: Add comprehensive tests for slot style inheritance
Test that slotted elements correctly inherit styles from their
assigned slot in various scenarios: inline styles, CSS rules,
named slots, nested shadow hosts, own style overrides, deep
inheritance chains, dynamic slot reassignment, JS-created shadow
DOM, class toggles on slots, and moving elements between hosts.
2026-02-13 10:22:30 +01:00
Andreas Kling
fb11732526 LibWeb: Fix style inheritance for slotted elements
Two issues prevented slotted elements from correctly inheriting
styles from their assigned slot:

1. Element::element_to_inherit_style_from() was skipping the slot
   element and returning the shadow host instead. This meant slotted
   elements inherited from the host, completely ignoring any styles
   on the slot itself.

2. When a slot element's style changed during the style tree walk,
   its assigned (slotted) nodes were never marked for recomputation.
   The tree walk follows the DOM tree, but slotted elements are DOM
   children of the shadow host, not the slot, so they were missed.

Fix (1) by returning the slot directly as the inheritance parent.
Fix (2) by marking assigned nodes dirty in update_style_recursively
when a slot's style changes.
2026-02-13 10:22:30 +01:00
Andreas Kling
8804eb89e0 LibWeb: Add test for targeted style update in getComputedStyle
Cover various scenarios: element's own style change, ancestor style
change affecting inheritance, sibling changes not affecting our element,
shadow DOM elements, pseudo-elements, and repeated reads.

Also documents a pre-existing bug where slotted elements don't pick up
inherited style changes from their assigned slot.
2026-02-13 10:22:30 +01:00
Sam Atkins
b21a05d290 LibWeb/CSS: Wait for resources to load to fire <style> load event
Previously, we fired the load event immediately, without waiting for
anything. This was good for not timing out, but bad for anything that
wanted to wait for the load to complete.

CSSStyleSheet now maintains a list of critical subresources, and waits
for all of them to complete before it then tells its owner that it is
ready. "Complete" here means the network request completed with or
without an error. This is done by having those subresources (just
`@import` for now) notify their style sheet when they complete. This
then propagates up as an `@import` tells its style sheet, which then
would tell its parent `@import` if it had one.

There are other subresources we should wait for (specifically fonts and
background images) but this commit just adds `@import` as a first step.
2026-02-12 16:23:12 +01:00
Callum Law
9de3ddf8f9 Tests: Import some counter style tests 2026-02-12 10:33:09 +00:00
Tim Ledbetter
910a8c78ec LibWeb: Preserve event properties in label activation behavior
Previously, the label called `HTMLElement::click()` which dispatched a
synthetic event with all properties set to their default values. We now
preserve the properties of the original mouse event.
2026-02-12 10:06:39 +00:00
Callum Law
b0274268f8 LibWeb: Support calculated values in @counter-style range descriptor
Calculated values are resolved and confirmed to be valid (in line with
non-calculated values) at parse time
2026-02-12 01:26:52 +01:00
Callum Law
a541c09d61 LibWeb: Support calculated value in additive-symbols descriptor
Calculated weight values are resolved and verified to be in strictly
decreasing order (as with non-calculated values) at parse time.
2026-02-12 01:26:52 +01:00
Callum Law
3783dd96a3 LibWeb: Support calculated value in @counter-style pad descriptor 2026-02-12 01:26:52 +01:00
Tim Ledbetter
7577fd2a57 LibWeb: Implement timer nesting level throttling
This clamps the interval of repeating timers to 4ms after they have run
5 times. This prevents CPU spinning for `setInterval()` calls with low
timeouts.
2026-02-11 16:32:20 +00:00
Praise-Garfield
ebd312689e LibWeb: Support :placeholder-shown pseudo-class for textarea elements
Previously only input elements were matched. Add placeholder_value()
to HTMLTextAreaElement mirroring the HTMLInputElement API and update
both selector matching code paths to handle textarea.
2026-02-11 16:11:11 +01:00
Callum Law
046dfdd192 LibWeb: Parse CSS timeline-scope property 2026-02-11 11:27:16 +01:00
Jelle Raaijmakers
b07a576c22 LibWeb: Select contents of <input> when tabbing through fields
Browsers seem to make it convenient to replace an <input>'s contents by
selecting all text on focusing, but only if you used keyboard
navigation. Programmatic focus and clicking on the field do not show
this behavior.
2026-02-11 11:17:27 +01:00
Jelle Raaijmakers
d3a2e4bbbb LibWeb: Draw caret for empty contenteditable elements
We don't have a text node in these, so no fragments either. Maintaining
a special case for this situation seems much simpler than reworking
`contenteditable`s to always have a fragment.
2026-02-11 11:17:27 +01:00
Jelle Raaijmakers
3bc4374344 LibWeb: Draw caret for empty <input>s and <textarea>s
Our change to generate spans in PaintableWithLines from fragments also
broke drawing the caret for empty <input>s and <textarea>s, since spans
was empty in that case.

Fix this by moving caret drawing to PaintableWithLines, and only
invoking it if we have a cursor position set.
2026-02-11 11:17:27 +01:00
Jelle Raaijmakers
6c2583eade LibWeb: Implement mouse auto scrolling of scrollable containers
When the mouse is dragged from inside a scrollable container to outside
of it, we now automatically scroll the container so the selection can be
extended. Scroll speed scales with the distance past the scrollport
edge, capped at a maximum. Edges close to the viewport boundary get a
wider activation zone so the speed ramp works predictably even when the
mouse has limited room to move.

The logic is encapsulated in AutoScrollHandler, which EventHandler
creates lazily on mouse selection start.
2026-02-11 11:04:53 +01:00
Jelle Raaijmakers
b6deacf6b0 LibWeb: Support hit testing fully above fragments
This allows us to consider fragments for hit testing even though the
cursor moved fully above them. This will allow us to select all the
contents in a <textarea> when you drag the mouse all the way to the top,
beyond the <textarea>'s top edge.
2026-02-11 11:04:53 +01:00
Jelle Raaijmakers
1f61ed0f79 LibWeb: Scroll selection's focus node into view when updated
When a selection is changed via keyboard or script, scroll the focus
node into view within the nearest scrollable ancestor.
2026-02-11 11:04:53 +01:00
Jelle Raaijmakers
2d4728d353 LibWeb: Keep cursor in view for text controls
When editing or changing the selection inside an <input> or <textarea>,
we should scroll the container so the cursor is always visible. Note
that currently the cursor might still become invisible at the end of the
container since we do not reserve enough space for it to be made
visible.
2026-02-11 11:04:53 +01:00
Jelle Raaijmakers
2558d80288 LibWeb: Apply AVC for descendants when hit testing fragments
We were not applying the descendants' transformation when hit testing on
fragments, which meant selection offsets on scrolled containers were
off.
2026-02-11 11:04:53 +01:00
Callum Law
2f135e0e63 LibWeb: Import some animation-timeline related tests 2026-02-11 10:49:34 +01:00
Andreas Kling
aafe3658fd Tests/LibWeb: Add text tests for image loading after document destroy
Add 6 text tests that verify correct behavior when image loading
callbacks fire after a document has been destroyed. These tests
check that load/error events are properly suppressed and that
no additional network activity occurs after the document becomes
inactive.
2026-02-10 21:19:35 +01:00
Timothy Flynn
d97a3d9b5a LibHTTP+RequestServer: Send revalidation attributes without parsing
The caching RFC is quite strict about the format of date strings. If we
received a revalidation attribute with an invalid date string, we would
previously fail a runtime assertion. This was because to start a
revalidation request, we would simply check for the presence of any
revalidation header; but then when we issued the request, we would fail
to parse the header, and end up with all attributes being null.

We now don't parse the revalidation attributes at all. Whatever we
receive in the Last-Modified response header is what we will send in the
If-Modified-Since request header, verbatim. For better or worse, this is
how other browsers behave. So if the server sends us an invalid date
string, it can receive its own date format for revalidation.
2026-02-10 09:09:53 -05:00
Andreas Kling
803e71ba9f Tests/LibWeb: Add comprehensive abspos height constraint solving test
Test all major code paths in the CSS2 10.6.4 algorithm for computing
height of absolutely positioned non-replaced elements:

- Rules 4, 5, 6 (one auto among top/height/bottom)
- Over-constrained case (none auto)
- Auto margin solving (one auto, both auto)
- Min-height and max-height re-solve for rules 4, 5, 6
- Min/max with auto margins
- Borders and padding interaction with min-height
2026-02-10 11:58:15 +01:00
Praise-Garfield
e2cdd84fcb LibWeb: Throw NotFoundError in MediaList::delete_medium()
Per the CSSOM specification, throw a NotFoundError DOMException when
the specified medium is not found in the collection. Invalid input
that fails to parse continues to return silently per step 2.
2026-02-09 21:44:47 +01:00