Commit graph

128 commits

Author SHA1 Message Date
Psychpsyo
56739b4b16 LibWeb: Implement plumbing for view transitions
This implements large parts of the CSS view-transitions-1 spec.
2025-09-07 13:58:05 +01:00
Callum Law
58431603ca LibWeb: Remove unused Element::resolved_css_values 2025-08-26 12:17:55 +02:00
Tim Ledbetter
cb1a1a5cb5 LibWeb: Replace is<T>() with as_if<T>() where possible
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
2025-08-25 18:45:00 +02:00
ayeteadoe
3df8e00d91 LibWeb: Enable EXPLICIT_SYMBOL_EXPORT 2025-08-23 16:04:36 -06:00
Andreas Kling
9208a54b0b LibWeb: Allow style inheritance through slots
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
When a subtree is projected through a slot, its root now inherits style
from the slot's parent, rather than the parent of the unprojected root.

This fixes a ton of subtle issues, and is very noticeable on Reddit.
2025-08-16 21:03:31 +02:00
Sam Atkins
911274a84d LibWeb/CSS: Implement ElementCSSInlineStyle.attributeStyleMap
Again, this isn't yet very usable, but it does appease some tests.
2025-08-13 09:47:50 +01:00
Sam Atkins
c768cc7208 LibWeb/CSS: Implement Element.computedStyleMap()
Currently the map doesn't return any values, so it's not very useful,
but this does make a few tests pass just by existing. :^)
2025-08-13 09:47:50 +01:00
Glenn Skrzypczak
3dd8b3230e LibWeb/HTML: Only include direction if dirname applies
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run
This commit changes form data to only include the direction of auto
directionality form associated elements.
2025-08-02 18:27:35 +01:00
Aliaksandr Kalenik
d1fbb7b51e LibWeb: Invalidate less elements affected by CSS custom properties
Before this change, whenever element's attributes changed, we would add
a flag to "pending invalidation", indicating that all descendants whose
style uses CSS custom properties needed to be recomputed. This resulted
in severe overinvalidation, because we would run invalidation regardless
of whether any custom property on affected element actually changed.

This change takes another approach, and now we decide whether
descendant's style needs to be recomputed based on whether ancestor's
style recomputation results in a change of custom properties, though
this approach adds a little overhead to style computation as now we have
to compare old vs new hashmap of custom properties.

This brings substantial improvement on discord and x.com where, before
this change, advantage of using invalidation sets was lost and we had
to recompute all descendants, because almost all of them use custom
properties.
2025-07-30 11:06:05 +02:00
Timothy Flynn
e7b08cf291 LibWeb: Add a DOM::Element::set_attribute override for UTF-16 strings
This just transcodes to UTF-8 for now, but primarily serves to to keep
compatibility with generated IDL definitions.
2025-07-28 12:25:11 +02:00
Timothy Flynn
8b6e3cb735 LibWeb+LibUnicode+WebContent: Port DOM:CharacterData to UTF-16
This replaces the underlying storage of CharacterData with Utf16String
and deals with the fallout.
2025-07-24 19:00:20 +02:00
Aliaksandr Kalenik
2fc405f1b2 LibWeb: Allow to pass pseudo-element type in computed properties getter
...and setter. We had lots of places where we check if pseudo-element
type is specified and then use `pseudo_element_computed_properties()` or
`computed_properties()`. This change moves these checks from caller side
to the getter and setter.
2025-07-18 21:19:37 +02:00
Sam Atkins
632ce9523b LibWeb/CSS: Add :unchecked pseudo-class
This just got added to the Selectors spec:

b78c97c19d

It's thus missing from the HTML spec and WPT, but I figured it was
simple enough to add.
2025-07-15 21:27:44 +02:00
Luke Wilde
2368641de5 LibWeb: Track if element was created from token with dupe attributes
This is required for CSP to ignore the nonce attribute to prevent
duplicate attributes hijacking the attribute.

See https://w3c.github.io/webappsec-csp/#security-nonce-hijacking
2025-07-09 15:52:54 -06:00
Andreas Kling
b3fd939628 LibWeb: Make sure we run selectors for mixed-case tag names
Before this change, we would never apply CSS rules where the selector
had a mixed-case tag name. This happened because our rule caches would
key them on the lowercased tag name, but we didn't lowercase the tag
name when fetching things from the cache.

This uncovered the fact that the SVG2 spec has a bunch of style applied
to non-rendered elements in a way that doesn't match other browsers.
Instead of blindly following the spec, we now match other browsers.
2025-07-09 14:36:08 +02:00
Sam Atkins
b6ffea8990 LibWeb: Give Element a CustomStateSet, exposed by ElementInternals 2025-07-04 18:10:28 +01:00
Sam Atkins
ffd5503dcb LibWeb/DOM: Serialize pseudo-elements in the correct order
Make Element responsible for serializing all its children, so it can put
them in order.
2025-07-03 09:56:56 +01:00
Sam Atkins
f98312d022 LibWeb/DOM: Move pseudo-element scroll offsets into PseudoElement 2025-06-19 12:35:31 +01:00
Sam Atkins
c1d4323cf7 LibWeb: Support counter-* properties on pseudo-elements
There are multiple things happening here which are interconnected:

- We now use AbstractElement to refer to the source of a counter, which
  means we also need to pass that around to compute `content`.

- Give AbstractElement new helper methods that are needed by
  CountersSet, so it doesn't have to care whether it's dealing with a
  true Element or PseudoElement.

- The CountersSet algorithms now walk the layout tree instead of DOM
  tree, so TreeBuilder needs to wait until the layout node exists
  before it resolves counters for it.

- Resolve counters when creating a pseudo-element's layout node. We
  awkwardly compute the `content` value up to twice: Once to figure out
  what kind of node we need to make, and then if it's a string, we do
  so again after counters are resolved so we can get the true value of
  any `counter()` functions. This will need adjusting in the future but
  it works for now.
2025-06-19 12:35:31 +01:00
Sam Atkins
46e95db355 LibWeb: Make Element::get_pseudo_element() public 2025-06-19 12:35:31 +01:00
Sam Atkins
a57595faf5 LibWeb: Make [resolve,inherit]_counters() take AbstractElement
This is one of those cases where the spec says "element" and
means "element or pseudo-element". The easiest way to handle both is to
make these be free functions that take an AbstractElement, and then
give AbstractElement some helper methods so that the caller doesn't
have to care which it's dealing with.

There are some FIXMEs here because PseudoElement doesn't have a
CountersSet yet, and because the CountersSet currently uses a
UniqueNodeID to identify counter sources, which doesn't support
pseudo-elements.
2025-06-19 12:35:31 +01:00
Sam Atkins
e7c2f0dd52 LibWeb: Make PseudoElement a class in its own right
It's getting a bit large and complicated to be a struct hidden in
DOM::Element.
2025-06-19 12:35:31 +01:00
Tim Ledbetter
4593c28769 LibWeb: Update validate_and_extract and its users to the latest spec 2025-06-19 11:00:53 +01:00
Jelle Raaijmakers
e8e6dbcee0 LibWeb: Fix document element's .scrollHeight and .scrollWidth
We were using the viewport's size as the viewport scrolling area, but
those are completely different things.
2025-06-17 17:17:34 +01:00
Manuel Zahariev
00d43b39d1 LibWeb: Retain calculated Element::ordinal_value for lists
`Element::ordinal_value` is called for every `li` element in
a list (ul, ol, menu).

Before:
  `ordinal_value` iterates through all of the children of the list
  owner. It is called once for each element: complexity $O(n^2)$.

After:
  - Save the result of the first calculation in `m_ordinal_value`
  then return it in subsequent calls.
  - Tree modifications are intercepted and trigger invalidation
    of the first node's `m_ordinal_value`:
    - insert_before
    - append
    - remove
  Results in noticeable performance improvement rendering' large
  lists: from 20s to 4s for 20K elements.
2025-06-16 12:44:58 +01:00
Jelle Raaijmakers
15c436b332 LibWeb: Implement basic focus indication for :focus-visible
This causes links to no longer show an outline when clicked; only when
using keyboard navigation with the tab key will the outline show up.
2025-06-13 17:39:11 +02:00
Aliaksandr Kalenik
6a029fb6d9 LibWeb: Reset animated CSS properties for pseudo elements
Previously we were resetting animated properties if animation effect's
target is not a pseudo element.
2025-05-28 17:35:59 +01:00
Callum Law
279913a223 LibWeb: Implement the translate attribute 2025-05-23 14:34:06 +02:00
Psychpsyo
a0be82b2cb LibWeb: Move containment checks to Layout::Node
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
It fits better there and avoids having to reach into the Element
all the time.
2025-05-13 15:30:14 +03:00
Psychpsyo
31301ef08b LibWeb: Add support for trees of pseudo-elements
This is needed for CSS view transitions.
2025-05-13 12:38:42 +01:00
Andreas Kling
096eed35cc LibWeb: Avoid O(n^2) traversal in play-or-cancel-animations logic
Some checks are pending
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
The play_or_cancel_animations_after_display_property_change() helper
was being called by Node::inserted() and Node::removed_from() and then
recursing into the shadow-including subtree.

This had quadratic complexity since inserted() and removed_from() are
themselves already invoked recursively for everything in the
shadow-including subtree.

Only one caller of this API actually needed the recursive behavior,
so this patch moves that responsibility to the caller and puts the logic
in style recomputation instead.

1.02x speedup on Speedometer's TodoMVC-jQuery.
2025-05-11 20:22:17 +02:00
InvalidUsernameException
029bcf13fd Libweb: Invalidate layout for the value-attribute of li-elements 2025-05-11 01:14:31 +02:00
Jelle Raaijmakers
c56f7d9cde LibWeb: Invalidate sibling style for :only-child and :*-of-type
After f7a3f785a8, sibling nodes' styles
were no longer invalidated after a node was removed. This reuses the
flag for `:first-child` and `:last-child` to indicate that a node's
style might be affected by any structural change in its siblings.

Fixes #4631.

Resolves the `:only-child` ACID3 failure as documented in #1231.
2025-05-07 14:55:12 +03:00
Shannon Booth
31a3bc3681 LibWeb: Implement 'State-preserving atomic move integration'
This was recently added to both the HTML and DOM specifications,
introducing the new moveBefore DOM API, as well as the new internal
'removing steps'.

See:

 * 432e8fb
 * eaf2ac7
2025-04-26 08:45:37 -06:00
Timothy Flynn
13ac6c4fde LibWeb: Implement ariaActiveDescendantElement spiritually closer to spec
Some checks are pending
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Lint Code / lint (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
We are meant to store a weak reference to the element indicated by this
attribute, rather than a GC-protected strong reference. This also hoists
the "get the attr-associated element" AO into its own function, rather
than being hidden in IDL, to match "get the attr-associated elements".
2025-04-25 01:20:12 +01:00
Timothy Flynn
f985ac8884 LibWeb: Implement element-referencing ARIA attributes
There are ARIA attributes, e.g. ariaControlsElements, which refer to a
list of elements by their ID. For example:

    <div aria-controls="item1 item2">

The div.ariaControlsElements attribute would be a list of elements whose
ID matches the values in the aria-controls attribute.
2025-04-25 01:20:12 +01:00
Timothy Flynn
0289df9357 LibWeb: Move ariaActiveDescendantElement to ARIAMixin
Not an issue right now, but all IDL types that include the ARIA mixin
will need this.
2025-04-25 01:20:12 +01:00
Timothy Flynn
a7b1f2c800 LibWeb: Make ARIAMixin::to_element return a reference
Let's avoid confusion on whether this method can return null. It can't.
This also adds a non-const override, as that will be needed soon.
2025-04-25 01:20:12 +01:00
Andreas Kling
7884e58b5c LibWeb: Make Element::html_uppercased_qualified_name() lazy
Many elements never end up needing this string, so instead of eagerly
generating it in the Element constructor, let's defer it until someone
actually requests it.

Knocks off a ~1% profile item on Speedometer3's jQuery test.
2025-04-20 18:43:11 +02:00
Andreas Kling
94cc4adefd LibWeb: Create Element::attributes (NamedNodeMap) lazily
Many elements have zero attributes, and they don't need a NamedNodeMap
until someone asks for it.
2025-04-20 18:43:11 +02:00
Andreas Kling
0c0650e60a LibWeb: Implement more of the "script-blocking style sheet" mechanism
The basic idea is that style sheets can block script execution under
some circumstances. With this commit, we now handle the simplest cases
where a parser-inserted link element gets to download its style sheet
before script execution continues.

This improves performance on Speedometer 3 where JavaScript APIs that
depend on layout results (like Element.scrollIntoView()) would get
called too early (before the relevant CSS was downloaded), and so we'd
perform premature layout work. This work then had to be redone after
downloading the CSS anyway, wasting time.

Note that our Text/input/link-re-enable-crash.html test had to be
tweaked after these changes, since it relied on the old, incorrect,
behavior where scripts would run before downloading CSS.
2025-04-20 14:54:21 +02:00
Shannon Booth
3e17b1c9ae LibWeb: Make Node::parent_element return GC::Ptr
This is useful for people like myself who run with debug mode to
more reliably get stacktraces without spinning up a debugger.
2025-04-18 10:49:02 +02:00
Andreas Kling
e1777f6e79 LibWeb: Make :hover invalidation logic reusable for all pseudo classes
We achieve this by keeping track of all checked pseudo class selectors
in the SelectorEngine code. We also give StyleComputer per-pseudo-class
rule caches.
2025-04-17 19:45:55 +02:00
Sam Atkins
6ff2324f26 LibWeb/DOM: Actually stub out pointer-capture API
For real this time.

This makes panning the KendoReact map widget actually work:
https://www.telerik.com/kendo-react-ui/components/map
2025-04-14 12:55:44 +02:00
Andrew Kaster
8fd81c3338 LibGC+LibWeb+LibJS: Remove workaround for Swift boolean bitfield issue
We're using a main snapshot everywhere, so we can yeet the workaround.
2025-04-04 13:06:53 -06:00
Andrew Kaster
e4c88915ab LibGC+LibJS+LibWeb: Add workaround for Swift boolean bitfield issue
This patch adds a workaround for a Swift issue where boolean bitfields
with getters and setters in SWIFT_UNSAFE_REFERENCE types are improperly
imported, causing an ICE.
2025-04-03 16:47:48 -06:00
Aliaksandr Kalenik
8cae20af1b LibWeb: Maintain a mapping for fast lookup in getElementById()
With this change we maintain a data structure that maps ids to
corresponding elements. This allows us to avoid tree traversal in
getElementById() in all cases except ones when lookup happens for
unconnected elements.
2025-03-26 08:36:25 +00:00
Andreas Kling
d856858015 LibWeb: Cache and reuse inline style for text input shadow trees
Instead of reparsing the style attributes every time we instantiate
the internal shadow tree for a text input element, we now parse them
once (in the internal CSS realm) and reuse them for all elements.

Roughly a ~10% speedup on Speedometer 2.1 :^)
2025-03-25 23:57:00 +00:00
Sam Atkins
0ed2e71801 LibWeb/CSS: Move and rename PseudoElement types to prep for code gen
The upcoming generated types will match those for pseudo-classes: A
PseudoElementSelector type, that then holds a PseudoElement enum
defining what it is. That enum will be at the top level in the Web::CSS
namespace.

In order to keep the diffs clearer, this commit renames and moves the
types, and then a following one will replace the handwritten enum with
a generated one.
2025-03-24 09:49:50 +00:00
Andreas Kling
f0abf5a43b LibWeb: Avoid allocating DOMRect objects for internal engine use
Some checks failed
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Build Dev Container Image / build (push) Has been cancelled
Instead of bothering the GC heap with a bunch of DOMRect allocations,
we can just pass around CSSPixelRect internally in many cases.

Before this change, we were generating so much DOMRect garbage that
we had to do a garbage collection *every frame* on the Immich demo.
This was due to the large number of intersection observers checked.

We still need to relax way more when idle, but for comparison, before
this change, when doing nothing for 10 seconds on Immich, we'd spend
2.5 seconds updating intersection observers. After this change, we now
spend 600 ms.
2025-03-22 14:33:59 -05:00