This ad-hoc code informs the client of a potentially changed page title.
But because we always update the title element (either the SVG or HTML
title) the client was already informed, causing the code to run twice.
Before this change, checking if fast selector matching could be used was
only enabled in style recalculation and hover invalidation. With this
change it's enabled for all callers of SelectorEngine::matches() by
default. This way APIs like `Element.matches()` and `querySelector()`
could take advantage of this optimization.
This is "update document for history step application" but that's too
long for the commit title. :^)
No code changes, just adding more FIXME comments for the new steps.
(And indented step 7's substeps for clarity.)
Corresponds to https://github.com/whatwg/html/pull/10910
Before this change, `m_needs_repaint` was reset in
`Document::record_display_list()` only when the cached display list was
absent. This meant that if the last triggered repaint used the cached
display list, we would keep repainting indefinitely until the display
list was invalidated (We schedule a task that checks if repainting is
required 60/s).
This change also moves `m_needs_repaint` from Document to
TraversableNavigable as we only ever need to repaint a document that
belongs to traversable.
Several interfaces that return a high resolution time require that
time to be coarsened, in order to prevent timing attacks. This
implementation simply reduces the resolution of the returned timestamp
to the minimum values given in the specification. Further work may be
needed to make our implementation more robust to the kind of attacks
that this mechanism is designed to prevent.
...until Document::update_style(). This allows to avoid doing full
document DOM tree traversal on each Node::invalidate_style() call.
Fixes performance regression on wpt.fyi
...in hover style invalidation. Instead, pass down a flag that indicates
all subsequent nodes in tree traversal have to be marked for inherited
style update.
By using ancestor filters some selectors could be early rejected
skipping selector engine invocation. According to my measurements it's
30-80% hover selectors depending on the website.
Instead of allocating 3 vectors with size equal to the number of
elements potentially affected by hover:
- for the elements themselves
- for selector match state of each element before hovered node change
- for selector match state of each element after hovered node change
now we allocate none of them, but mark element for style recalculation
as we traverse the tree.
This currently uses a non spec-compliant property on the Response
object, which represents the time that the Response was created.
Setting this value allows `Performance.timeOrigin` to return a
reasonable value.
Instead of traversing the entire DOM subtrees and marking nodes for
style update, this patch adds a new mechanism where we can mark a
subtree root as "entire subtree needs style update".
A new pass in Document::update_style() then takes care of coalescing
all these invalidations in a single traversal of the DOM.
This shaves *minutes* of loading time off of https://wpt.fyi/ subpages.
Instead, change the APIs from "has :foo" to "may have :foo" and return
true if we don't have a valid rule cache at the moment.
This allows us to defer the rebuilding of the rule cache until a later
time, for the cost of a wider invalidation at the moment.
Do note that if our rule cache is invalid, the whole document has
invalid style anyway! So this is actually always less work. :^)
Knocks ~1 second of loading time off of https://wpt.fyi/
Instead of ignoring any paintable immediately when they're invisible to
hit-testing, consider every candidate and while the most specific
candidate is invisible to hit-testing, traverse up to its parent
paintable.
This more closely reflects the behavior expected when wrapping block
elements inside inline elements, where although the block element might
have `pointer-events: none`, it still becomes part of the hit-test body
of the inline parent.
This makes the following link work as expected:
<a href="https://ladybird.org">
<div style="pointer-events: none">Ladybird</div>
</a>
DOM nodes now have two additional flags:
- Needs layout tree update
- Child needs layout tree update
These work similarly to the needs-style-update flags, but instead signal
the need to rebuild the corresponding part of the layout tree.
When a specific DOM node needs a layout tree update, we try to create
a new subtree starting at that node, and then replace the subtree in the
old layout tree with the newly created subtree.
This required some refactoring in TreeBuilder so that we can skip over
entire subtrees during a tree update.
Note that no partial updates happen yet (as of this commit) since we
always invalidate the full layout tree still. That will change in the
next commit.
The use of this HashMap looks very spooky, but let's at least use
finalize when cleaning them up on destruction to make things slightly
less dangerous looking.
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.
Previously, we optimized hover style invalidation to mark for style
updates only those elements that were matched by :hover selectors in the
last style calculation.
This change takes it a step further by invalidating only the elements
where the set of selectors that use :hover changes after hovered element
is modified. The implementation is as follows:
1. Collect all elements whose styles might be affected by a change in
the hovered element.
2. Retrieve a list of all selectors that use :hover.
3. Test each selector against each element and record which selectors
match.
4. Update m_hovered_node to the newly hovered element.
5. Repeat step 3.
6. For each element, compare the previous and current sets of matched
selectors. If they differ, mark the element for style recalculation.
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.
Instead of storing all storage objects in static memory, we now
follow the the spec by lazily creating a unique Storage object
on each document object.
Each Storage object now holds a 'proxy' to the underlying backing
storage. For now, this proxy is simply a reference to the backing
object. In the future, it will need to be some type of interface
object that stores on a SQLite database or similar.
Session storage is now correctly stored / tracked as part of the
TraversableNavigable object.
Local storage is still stored in a static map, but eventually this
should be factored into something that is stored at the user agent
level.
This event is fired while both the previous and the current phase are
active.
This prevents this test from timing out:
- css/css-animations/animationevent-types.txt