Commit graph

196 commits

Author SHA1 Message Date
Gingeh
91e4fb248b LibWeb: Hide unrelated popovers when showing popovers
Also hides decendant popovers when hiding.
Also hides unrelated popovers when showing dialogs.
2025-02-16 19:40:07 +00:00
Andreas Kling
31a69ce887 LibWeb+LibGfx: Make IntersectionObserver checks edge-inclusive
This fixes an issue where 0x0 rectangles were not considered to be
intersecting, even when they fell inside (or were adjacent to) the
viewport.
2025-02-16 18:09:08 +01:00
Psychpsyo
f839f1b44b LibWeb: Make a elements honor base element's target 2025-02-16 09:21:52 +01:00
Shannon Booth
9072a7caef Everywhere: Use URL::about_XXX factory functions 2025-02-15 17:05:55 +00:00
Andreas Kling
c9cd795257 LibWeb: Don't lose change events on MediaQueryList internal state change
MediaQueryList will now remember if a state change occurred when
evaluating its match state. This memory can then be used by the document
later on when it's updating all queries, to ensure that we don't forget
to fire at least one change event.

This also required plumbing the system visibility state to initial
about:blank documents, since otherwise they would be stuck in "hidden"
state indefinitely and never evaluate their media queries.
2025-02-13 20:52:31 +01:00
Aliaksandr Kalenik
327dc8e82a LibWeb: Avoid full tree traversal for non-subject :has() invalidation
Instead of checking all elements in a document for containment in
`:has()` invalidation set, we could narrow this down to ancestors and
ancestor siblings, like we already do for subject `:has()` invalidation.

This change brings great improvement on GitHub that has selectors with
non-subject `:has()` and sibling combinators (e.g., `.a:has(.b) ~ .c`)
which prior to this change meant style invalidation for whole document.
2025-02-13 16:24:51 +01:00
Sam Atkins
a01a3b18f5 LibWeb: Fix CSP navigation request blocking
Corresponds to 304782ca57
2025-02-12 17:05:37 +00:00
Aliaksandr Kalenik
761e9aeaf7 LibWeb: Optimize inherited style update
This commit changes the strategy for updating inherited styles. Instead
of marking all potentially affected nodes during style invalidation, the
decision is now made on-the-fly during style recalculation. Child nodes
will only have their inherited styles recalculated if their parent's
properties have changed.

On Discord this allows to 1000x reduce number of nodes with recalculated
inherited style.
2025-02-11 19:23:12 +01:00
Aliaksandr Kalenik
875a7141a3 LibWeb: Skip pending :has() invalidations if there are no :has()
`invalidate_style()` already tries to avoid scheduling invalidation for
`:has()` by checking result of `may_have_has_selectors()`, but it might
still result in unnecessary work because `may_have_has_selectors()`
does not force building of rules cache. This change adds
`have_has_selectors()` that forces building of rules cache and is
invoked in `update_style()` to double-check whether we actually need to
process scheduled `:has()` invalidations.

This allows to skip ~100000 ancestor traversals on this WPT test:
https://wpt.live/html/select/options-length-too-large.html
2025-02-11 10:22:23 +01:00
Aliaksandr Kalenik
90ba4b16c2 LibWeb: Postpone :has() style invalidation until update_style()
This allows to do ancestors traversal only once even if
`invalidate_style()` was called multiple times for the same node.
2025-02-11 10:22:23 +01:00
Shannon Booth
c954d0be27 LibWeb/DOM: Add missing UTF-8 decode without BOM on fragment ID
We were previously crashing instead of using the replacement
character on invalid bytes.
2025-02-10 09:48:08 +00:00
Aliaksandr Kalenik
e677ab1699 LibWeb: Narrow :has() style invalidation to ancestor nodes
The current implementation of `:has()` style invalidation is divided
into two cases:
- When used in subject position (e.g., `.a:has(.b)`).
- When in a non-subject position (e.g., `.a > .b:has(.c)`).

This change focuses on improving the first case. For non-subject usage,
we still perform a full tree traversal and invalidate all elements
affected by the `:has()` pseudo-class invalidation set.

We already optimize subject `:has()` invalidations by limiting
invalidated elements to ones that were tested against `has()` selectors
during selector matching. However, selectors like `div:has(.a)`
currently cause every div element in the document to be invalidated.
By modifying the invalidation traversal to consider only ancestor nodes
(and, optionally, their siblings), we can drastically reduce the number
of invalidated elements for broad selectors like the example above.

On Discord, when scrolling through message history, this change allows
to reduce number of invalidated elements from ~1k to ~5.
2025-02-10 01:13:53 +01:00
Andreas Kling
187f8c5460 LibWeb: Run queued HTML tasks after associated document is destroyed
Before this change, tasks associated with a destroyed document would get
stuck in the task queue forever, since document-associated tasks are not
allowed to run when their document isn't fully active (and destroyed
documents never become fully active again). This caused everything
captured by task callbacks to leak.

We now treat tasks for destroyed documents as runnable immediately,
which gets them out of the queue.

This fixes another massive GC leak on Speedometer.
2025-02-07 16:53:11 +01:00
Sam Atkins
6a4d80b9b6 LibWeb/CSS: Integrate ParsingContext into the Parser
This is not really a context, but more of a set of parameters for
creating a Parser. So, treat it as such: Rename it to ParsingParams,
and store its values and methods directly in the Parser instead of
keeping the ParsingContext around.

This has a nice side-effect of not including DOM/Document.h everywhere
that needs a Parser.
2025-02-06 16:47:25 +00:00
Psychpsyo
9b8120d8e8 Meta: Disallow links to single-page HTML spec 2025-02-05 16:04:50 -07:00
Aliaksandr Kalenik
da579e11b0 LibWeb: Start implementing render-blocking mechanism from HTML spec
This change implements enough spec steps to block rendering until
execution of sync scripts inserted from HTML parser is complete.
2025-02-05 18:28:46 +01:00
Aliaksandr Kalenik
a5e4a51b52 LibWeb: Change animation to schedule repaint only when necessary
Animation should trigger repaint only if it's required by animated style
update.
2025-02-05 14:34:41 +01:00
Jelle Raaijmakers
314f4ff0da LibWeb: Prevent double page title update in DOM::Document
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.
2025-02-03 18:34:22 +01:00
Aliaksandr Kalenik
0f17ad9ebc LibWeb: Use fast CSS selector matching in default matches() code path
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.
2025-02-03 10:28:08 +01:00
Tim Ledbetter
6d7b7e7822 LibWeb: Use as to cast global object to WindowOrWorkerGlobalScopeMixin
No functional changes.
2025-02-02 17:18:56 +01:00
Sam Atkins
3794665b0b LibWeb/DOM: Add spec steps for WebDriver BiDi to document history algo
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
2025-02-01 23:32:39 +01:00
Aliaksandr Kalenik
0c5b61b7e1 LibWeb: Fix infinite repaint loop when cached display list is used
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.
2025-02-01 23:31:16 +01:00
Gingeh
108f3a9aac LibWeb: Implement popovertarget buttons 2025-01-30 15:46:52 -07:00
Tim Ledbetter
39445d6dd6 LibWeb: Implement basic high resolution time coarsening
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.
2025-01-30 18:37:53 +01:00
Sam Atkins
3775f3399c LibWeb: Fix various typos
Corresponds to:
- https://github.com/whatwg/html/pull/10934
- https://github.com/whatwg/html/pull/10950
2025-01-30 15:00:16 +00:00
Sam Atkins
3e4b1056b5 LibWeb: Consistently use navigables for WebDriver BiDi
Corresponds to https://github.com/whatwg/html/pull/10909
2025-01-30 15:00:16 +00:00
Aliaksandr Kalenik
7da3b06e3e LibWeb: Postpone invalidating style of elements affected by :has()
...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
2025-01-29 17:21:47 +01:00
Luke Wilde
18b75afef8 LibWeb: Fire resize event at VisualViewport in the resize steps
Used on x.com to determine the layout to use on resize.
2025-01-29 09:23:52 +01:00
Luke Wilde
d21bac8028 LibWeb: Mark the Window resize event as trusted 2025-01-29 09:23:52 +01:00
Aliaksandr Kalenik
748d316973 LibWeb: Avoid separate tree traversal to mark for inherited style update
...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.
2025-01-28 18:55:42 +01:00
Aliaksandr Kalenik
db47fa3db1 LibWeb: Use ancestor filters for hover style invalidation
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.
2025-01-28 18:55:42 +01:00
Aliaksandr Kalenik
b153420feb LibWeb: Reduce memory usage in hover style invalidation
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.
2025-01-28 18:55:42 +01:00
Psychpsyo
67ed676831 LibWeb: Implement CSS 'contain' property 2025-01-28 11:24:40 +00:00
Tim Ledbetter
a8904451ff LibWeb: Set navigation start time when creating a new Document
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.
2025-01-27 14:53:33 +01:00
Shannon Booth
22a7cd9700 LibWeb: Port Document encoding_parse_url and parse_url to Optional<URL>
This ports two more APIs away from URL::is_valid.
2025-01-27 00:03:07 +00:00
Andreas Kling
f35152cf61 LibWeb: Defer entire-subtree style invalidations
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.
2025-01-26 22:58:42 +01:00
Andreas Kling
e03aedbdf0 LibWeb: Add direct pointer to CSS::Selector in MatchingRule struct
This avoids looking up the selector by index repeatedly, giving us a
~400ms reduction in load time on https://wpt.fyi/
2025-01-26 15:07:23 +01:00
Andreas Kling
4bef0d0aea LibWeb: Don't rebuild rule cache so eagerly to check for :has/:defined
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/
2025-01-24 17:54:34 +01:00
Jelle Raaijmakers
b7a554d1f2 LibWeb: Reorder paintable hit-testing to account for pointer-events
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>
2025-01-23 09:33:10 +01:00
Shannon Booth
fd27eef0d1 LibWeb: Return OptionalNone from DOMURL::parse on failure
This ports one more function away from needing to use the awkward
valid state of the URL class.
2025-01-22 12:33:55 +00:00
Sam Atkins
6f8d3014ea LibWeb/HTML: Update Document::create_and_initialize() to latest spec
This corresponds to part of https://github.com/whatwg/html/pull/10818
2025-01-21 18:17:18 +01:00
Sam Atkins
c073127b99 LibWeb/DOM: Return Document's Origin by reference
We don't want to have to copy these unnecessarily.
2025-01-21 18:17:18 +01:00
Timothy Flynn
85b424464a AK+Everywhere: Rename verify_cast to as
Follow-up to fc20e61e72.
2025-01-21 11:34:06 -05:00
Andreas Kling
c01d810e5a LibWeb: Implement partial layout tree updates
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.
2025-01-18 21:01:01 +01:00
Shannon Booth
76397c9ecd LibWeb: Use finalize for cleaning up all navigables
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.
2025-01-17 10:08:42 +01:00
Gingeh
403cda5cd6 LibWeb: Allow color keywords in theme-color metadata 2025-01-12 19:47:01 +00:00
Gingeh
9f2ce259ad LibWeb: Check for missing node or invalid query in obtain_theme_color 2025-01-12 19:47:01 +00: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
97616fa108 LibWeb/DOM: Move "stop intersection observing..." code into a method
We'll need to call it from elsewhere.

Also add a missing step 5 from where we previously called it.
2025-01-11 11:10:43 +01:00
Jelle Raaijmakers
e21ee10b3c LibWeb: Add command state & value overrides to DOM::Document 2025-01-10 23:33:35 +01:00