Commit graph

79 commits

Author SHA1 Message Date
Aliaksandr Kalenik
e0051db62e LibWeb: Use invalidation sets for "style" attribute invalidation 2025-01-20 18:23:34 +01:00
Aliaksandr Kalenik
34bf833a0a LibWeb: Expand invalidation sets usage to any attribute change
Before this change invalidation sets were only used for "class" and "id"
attribute changes.
2025-01-19 19:54:38 +01:00
Aliaksandr Kalenik
039e0d478a LibWeb: Use invalidation sets for id attribute style invalidation 2025-01-19 19:54:38 +01:00
Aliaksandr Kalenik
c5f2a88f69 LibWeb: Use invalidation sets to reduce style recalculation
Implements idea described in
https://docs.google.com/document/d/1vEW86DaeVs4uQzNFI5R-_xS9TcS1Cs_EUsHRSgCHGu8

Invalidation sets are used to reduce the number of elements marked for
style recalculation by collecting metadata from style rules about the
dependencies between properties that could affect an element’s style.

Currently, this optimization is only applied to style invalidation
triggered by class list mutations on an element.
2025-01-19 19:54:38 +01:00
Andreas Kling
e5d521bef8 LibWeb: Enable partial layout tree update in a bunch of cases
These common cases now cause us to invalidate the layout tree starting
at the relevant parent node instead of invalidating the entire tree.

- DOM node insertion
- DOM node removal
- innerHTML setter
- textContent setter

This makes a lot of dynamic content much faster. For example, demos
on shadertoy.com go from ~18 fps to ~28 fps on my machine.
2025-01-18 21:01:01 +01:00
Shannon Booth
64eeda6450 LibWeb: Return a representation of an 'Agent' in 'relevant agent'
This makes it more convenient to use the 'relvant agent' concept,
instead of the awkward dynamic casts we needed to do for every call
site.

mutation_observers is also changed to hold a GC::Root instead of raw
GC::Ptr. Somehow this was not causing problems before, but trips up CI
after these changes.
2025-01-11 10:39:48 -05:00
Sam Atkins
89296b88a0 LibWeb: Bring fragment parsing up to spec
Corresponds to https://github.com/whatwg/html/pull/10874

Also, parse_fragment() returns ExceptionOr, so stop voiding the error
from append_child().
2025-01-07 16:05:59 +01:00
Aliaksandr Kalenik
e465e922bd LibWeb: Optimize :hover style invalidation
Instead of recalculating styles for all nodes in the common ancestor of
the new and old hovered nodes' subtrees, this change introduces the
following approach:
- While calculating ComputedProperties, a flag is saved if any rule
  applied to an element is affected by the hover state during the
  execution of SelectorEngine::matches().
- When the hovered element changes, styles are marked for recalculation
  only if the flag saved in ComputedProperties indicates that the
  element could be affected by the hover state.
2025-01-04 20:32:35 +01:00
Sam Atkins
938ffe183e LibWeb/DOM: Update validate_and_extract to latest spec
The "strictly split" infra algorithm feels like an inefficient way of
doing basically what our existing split() does, except working with
code points instead of bytes. It didn't seem worth it to implement now.
2025-01-04 18:08:15 +00:00
Psychpsyo
331b1b22f5 LibWeb: Implement some viewport proximity features 2025-01-04 11:53:39 +00:00
sideshowbarker
1be55fe793 LibWeb: Support the ariaActiveDescendantElement IDL attribute 2025-01-01 11:00:53 +00:00
Andreas Kling
ceefe7d858 LibWeb: Make CustomElementDefinition relationship with GC more sane
1. Stop using GC::Root in member variables, since that usually creates
   a realm leak.

2. Stop putting OrderedHashMap<FlyString, GC::Ptr> on the stack while
   setting these up, since that won't protect the objects from GC.
2024-12-27 10:02:58 +01:00
Andreas Kling
3bfb0534be LibGC: Rename MarkedVector => RootVector
Let's try to make it a bit more clear that this is a Vector of GC roots.
2024-12-26 19:10:44 +01:00
Andreas Kling
f45e24864b LibWeb: Skip unneeded style invalidation on custom element state change
If there are no :defined pseudo-class selectors anywhere in the
document, we don't have to invalidate style at all when an element's
custom element state changes.
2024-12-25 13:26:51 +01:00
Andreas Kling
b981e6f7bc LibWeb: Avoid many style invalidations on DOM attribute mutation
Many times, attribute mutation doesn't necessitate a full style
invalidation on the element. However, the conditions are pretty
elaborate, so this first version has a lot of false positives.

We only need to invalidate style when any of these things apply:

1. The change may affect the match state of a selector somewhere.
2. The change may affect presentational hints applied to the element.

For (1) in this first version, we have a fixed list of attribute names
that may affect selectors. We also collect all names referenced by
attribute selectors anywhere in the document.

For (2), we add a new Element::is_presentational_hint() virtual that
tells us whether a given attribute name is a presentational hint.

This drastically reduces style work on many websites. As an example,
https://cnn.com/ is once again browseable.
2024-12-24 17:17:09 +01:00
Andreas Kling
d5bbf8dcf8 LibWeb: Do lighter style invalidation for style attribute changes
When the `style` attribute changes, we only need to update style on the
element itself (unless there are [style] attribute selectors somewhere).

Descendants of the element don't need a full style update, a simple
inheritance propagation is enough.
2024-12-23 17:05:09 +01:00
Andreas Kling
dc8343cc23 LibWeb: Add mechanism to invalidate only inherited styles
We can now mark an element as needing an "inherited style update" rather
than a full "style update". This effectively means that the next style
update will visit the element and pull all of its inherited properties
from the relevant ancestor element.

This is now used for descendants of elements with animated style.
2024-12-23 17:05:09 +01:00
Andreas Kling
74469a0c1f LibWeb: Make CSS::ComputedProperties GC-allocated 2024-12-22 10:12:49 +01:00
Andreas Kling
c1cad8fa0e LibWeb: Rename CSS::StyleProperties => CSS::ComputedProperties
Now that StyleProperties is only used to hold computed properties, let's
name it ComputedProperties.
2024-12-22 10:12:49 +01:00
Andreas Kling
ed7f4664c2 LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.

This worked great, but it meant we had to do all the work of selector
matching and cascading every time.

To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.

The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.

Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-22 10:12:49 +01:00
Totto16
d21bfda900 LibWeb: Handle special cases of PseudoElement::Type correctly
There are some special values for CSS::Selector::PseudoElement::Type
which are after `KnownPseudoElementCount` and therefore not present in
various arrays of pseudo elements, this leads to some errors, if a type
after `KnownPseudoElementCount` is used without checking first. This
adds explicit checks to all usages
2024-12-19 19:35:57 +00:00
Sam Atkins
4c5a40579a LibWeb: Match spec changes to "create an element" algorithm
Corresponds to https://github.com/whatwg/html/pull/10857

No code changes, only comments.
2024-12-18 19:22:44 +00:00
sideshowbarker
314e5d6bb7 LibWeb: Compute accessible names for hidden/hidden-but-referenced nodes
This change implements full support for the “A. Hidden Not Referenced”
step at https://w3c.github.io/accname/#step2A in the “Accessible Name
and Description Computation” spec — including handling all hidden nodes
that must be ignored, as well as handling hidden nodes that, for the
purposes of accessible-name computation, must not be ignored (due to
having aria-labelledby/aria-describedby references from other nodes).

Otherwise, without this change, not all cases of hidden nodes get
ignored as expected, while cases of nodes that are hidden but that have
aria-labelledby/aria-describedby references from other nodes get
unexpectedly ignored.
2024-11-29 12:18:28 +00:00
Milo van der Tier
aa33acf3a2 LibWeb: Update existing style object when setting style attribute
Previously any existing ElementInlineCSSStyleDeclaration would get
overwritten by e.setAttribute("style", ...), while it should be updated
instead.

This fixes 2 WPT subtests.
2024-11-25 17:16:29 +01:00
Shannon Booth
f87041bf3a LibGC+Everywhere: Factor out a LibGC from LibJS
Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:

 * JS::NonnullGCPtr -> GC::Ref
 * JS::GCPtr -> GC::Ptr
 * JS::HeapFunction -> GC::Function
 * JS::CellImpl -> GC::Cell
 * JS::Handle -> GC::Root
2024-11-15 14:49:20 +01:00
Timothy Flynn
d4f8b598cb LibWeb: Consolidate the attribute change handlers
We currently have 2 virtual methods to inform DOM::Element subclasses
when an attribute has changed, one of which is spec-compliant. This
patch removes the non-compliant variant.
2024-11-14 15:39:02 +01:00
Shannon Booth
1e54003cb1 LibJS+LibWeb: Rename Heap::allocate_without_realm to Heap::allocate
Now that the heap has no knowledge about a JavaScript realm and is
purely for managing the memory of the heap, it does not make sense
to name this function to say that it is a non-realm variant.
2024-11-13 16:51:44 -05:00
Shannon Booth
9b79a686eb LibJS+LibWeb: Use realm.create<T> instead of heap.allocate<T>
The main motivation behind this is to remove JS specifics of the Realm
from the implementation of the Heap.

As a side effect of this change, this is a bit nicer to read than the
previous approach, and in my opinion, also makes it a little more clear
that this method is specific to a JavaScript Realm.
2024-11-13 16:51:44 -05:00
Timothy Flynn
93712b24bf Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Andreas Kling
1d75e82101 LibWeb: Coalesce layouts that happen in response to style changes
Instead of doing a forced layout synchronously whenever an element's
style is changed, use a zero-timer to do the forced relayout on next
event loop iteration.

This effectively coalesces a lot of layouts and makes many pages such
as GitHub spend way less time doing redundant layout work.
2021-01-09 15:22:23 +01:00
Andreas Kling
d3046a2649 LibWeb: Allow anonymous table, table-row and table-cell layout nodes 2021-01-07 17:33:29 +01:00
Andreas Kling
29a4da30b7 LibWeb: Make DOM::Node::create_layout_node() not need parent's style
The StyleResolver can find the specified CSS values for the parent
element via the DOM. Forcing everyone to locate specified values for
their parent was completely unnecessary.
2021-01-06 14:58:48 +01:00
Andreas Kling
d9b2650dcc LibWeb: Remove specified style from layout nodes
Layout nodes now only carry CSS computer values with them. The main
idea here is to give them only what they need to perform layout, and
leave the rest back in the DOM.
2021-01-06 14:58:48 +01:00
Andreas Kling
981758a8b1 LibWeb: Use the specified CSS values from element in more places
Instead of using the specified style stored on Layout::Node, use the
specified CSS values kept by the DOM::Element in more places.
2021-01-06 14:58:48 +01:00
Andreas Kling
ba8990fb6c LibWeb: Rename Element::resolved_style() => specified_css_values()
This object represents the specified CSS values, so let's call it that.
2021-01-06 14:58:48 +01:00
Andreas Kling
07dd73c351 LibWeb: Remove hand-rolled is_foo() helpers in Layout::Node classes 2021-01-01 18:56:49 +01:00
Linus Groh
3436317c08 LibWeb: Escape text nodes in innerHTML getter 2020-12-17 19:39:48 +01:00
Linus Groh
4833f0066e LibWeb: Include element attributes in innerHTML getter 2020-12-17 19:39:48 +01:00
Andreas Kling
613764b83c LibWeb: Actually apply recomputed style to element's layout node
Otherwise fetching stuff via LayoutNode::style() will have stale values
since we were only updating the specified_style() here.

LayoutNode::specified_style() should eventually go away since there's
no need to carry those uncooked values around with the layout tree.
2020-12-15 20:49:11 +01:00
Andreas Kling
4a9dcd974a LibWeb: Remove unused Element::set_attributes() 2020-12-15 19:33:53 +01:00
Linus Groh
5e7945e26f LibWeb: Add a simple StyleInvalidator class
This patch adds a simple, naive & inefficient class for document-wide
style invalidation, e.g. after element attribute updates. During
construction it collects a HashMap of a document's elements and their
matching rules, during destruction it does the same and then compares
the results; dirtying all elements that have a different number or order
of matching rules afterwards.

Much room for improvement, but it solves the problem of stale element
styling after attribute updates for now :^)

Fixes #4404.
2020-12-14 23:38:08 +01:00
Andreas Kling
59afcddcfe LibWeb: Mark element style dirty on style/id attribute change too 2020-12-13 15:22:41 +01:00
Andreas Kling
294ec3b6a5 LibWeb: Mark element style dirty when class attribute changes
Fixes #4403.
2020-12-13 15:22:22 +01:00
Andreas Kling
6af55a234f LibWeb: Make DOM::Node::set_needs_style_update() schedule the update
After you mark a node as needing new style, there's no situation in
which we don't want a style update to happen, so just take care of
scheduling it automatically.
2020-12-13 15:19:42 +01:00
Andreas Kling
d65bebd8cf LibWeb: Cache parsed inline style of DOM elements
Instead of invoking the CSS parser every time we compute the style for
an element that has a "style" attribute, we now cache the result of
parsing the inline style whenever the "style" attribute is set.

This is a nice boost to relayout performance since we no longer hit the
CSS parser at all.
2020-12-07 20:00:27 +01:00
Andreas Kling
d477039abc LibWeb: Rename Layout::LayoutTreeBuilder => Layout::TreeBuilder 2020-11-25 21:27:18 +01:00
Andreas Kling
5aeab9878e LibWeb: Rename LayoutNode classes and move them into Layout namespace
Bring the names of various boxes closer to spec language. This should
hopefully make things easier to understand and hack on. :^)

Some notable changes:

- LayoutNode -> Layout::Node
- LayoutBox -> Layout::Box
- LayoutBlock -> Layout::BlockBox
- LayoutReplaced -> Layout::ReplacedBox
- LayoutDocument -> Layout::InitialContainingBlockBox
- LayoutText -> Layout::TextNode
- LayoutInline -> Layout::InlineNode

Note that this is not strictly a "box tree" as we also hang inline/text
nodes in the same tree, and they don't generate boxes. (Instead, they
contribute line box fragments to their containing block!)
2020-11-22 15:56:27 +01:00
Luke
397049aae8 LibWeb: Move innerText from DOM::Element to HTML::HTMLElement 2020-11-11 12:15:05 +01:00
Luke
e8a9e8aed5 LibWeb: Add namespace to Element 2020-10-22 15:24:42 +02:00