Commit Graph

318 Commits

Author SHA1 Message Date
Andreas Kling
2abbf99a95 LibWeb: Add opt-in tracing of set_needs_layout() calls with reason 2025-03-08 03:37:38 +01:00
Andreas Kling
415079bc11 LibWeb: Add opt-in tracing of invalidate_layout_tree() calls with reason 2025-03-08 03:37:38 +01:00
Andreas Kling
c333042e63 LibWeb: Add opt-in tracing of update_layout() calls with reason 2025-03-08 03:37:38 +01:00
Aliaksandr Kalenik
9b26f7eb0f LibWeb: Use partial layout tree rebuild in element's style invalidation
This allows us to avoid a full layout tree rebuild after change of
"display" property, which happens frequently in practice. It also
allows us to avoid a full rebuild after DOM node insertion, since
previously, computing styles for newly inserted nodes would trigger a
complete layout tree rebuild.
2025-03-06 23:48:34 +01:00
Aliaksandr Kalenik
80c0a16597 LibWeb: Don't invalidate style for animations in idle state 2025-03-04 18:06:46 +01:00
Aliaksandr Kalenik
c769271e82 LibWeb: Don't invalidate display list in update_animated_style_if_needed
All necessary invalidations are issued while invalidating animated
style. There is no need to drop display list simply because there are
some animations that might need an update.
2025-03-03 21:45:23 +01:00
Aliaksandr Kalenik
1ce1a8f8f1 LibWeb: Reset and update animated style in a single pass
...and skip resetting animated style of finished animations.
2025-03-03 21:45:23 +01:00
Aliaksandr Kalenik
8e481f65f5 LibWeb: Don't invalidate style of finished animations
Removes lots of completely unnecessary work, especially when animated
property affects layout.
2025-03-03 21:45:23 +01:00
Timothy Flynn
b11ba4cc90 LibWeb: Clear the document's page's focused navigable upon destruction
We set the page's focused navigable upon mouse-down events from the UI.
However, we neglected to ever clear that focused navigable upon events
such as subsequent page navigations. This left the page with a stale
reference to a no-longer-active navigable. The effect was that any key
events from the UI would not be sent to the new page until either the
reference was collected by GC, or another mouse-down event occurred.

In the test added here, without this fix, the text sent to the input
element would not be received, and the change event would not fire.
2025-03-02 17:27:24 -05:00
Andreas Kling
043e96946f LibWeb: Block rendering until linked stylesheets are loaded
This commit implements the main "render blocking" behavior for link
elements, drastically reducing the amount of FOUC (flash of unstyled
content) we subject our users to.

The document will now block rendering until linked style sheets
referenced by parser-created link elements have loaded (or failed).

Note that we don't yet extend the blocking period until "critical
subresources" such as imported style sheets have been downloaded
as well.
2025-02-27 21:36:40 +01:00
Aliaksandr Kalenik
b8af3fccf6 LibWeb: Wait until child navigable's SHE is ready before navigating
This change fixes a bug that can be reproduced with the following steps:
```js
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframe.contentWindow.location.href = ("http://localhost:8080/demo.html");
```

These steps are executed in the following order:
1. Create iframe and schedule session history traversal task that adds
   session history entry for the iframe.
2. Generate navigation id for scheduled navigation to
   `http://localhost:8080/demo.html`.
3. Execute the scheduled session history traversal task, which adds
   session history entry for the iframe.
4. Ooops, navigation to `http://localhost:8080/demo.html` is aborted
   because addings SHE for the iframe resets the navigation id.

This change fixes this by delaying all navigations until SHE for a
navigable is created.
2025-02-27 14:31:41 +01:00
Luke Wilde
12a07b4fad LibWeb: Close WebSockets when document is unloaded
Previously, they would stay open for the entire WebContent lifetime,
or until the server closed the connection. This was particularly
noticeable on collaborative websites/games such as
https://jigsawpuzzles.io/, where the user using Ladybird would stick
around even after they had navigated away.
2025-02-26 11:47:32 +01:00
Sam Atkins
03a058ba5e LibWeb: Update Document.write spec steps
The spec changes seem to mostly be about introducing a TrustedHTML type
which we do not yet support, so we have a couple of FIXMEs.

TrustedTypes::InjectionSink is an attempt at matching the spec, but it's
not entirely clear to me how it should work. I'm sure it'll get
revisited once we start implementing trusted types.
2025-02-25 15:19:38 +01:00
Timothy Flynn
72905c84d5 LibWeb+LibWebView+WebContent: Support both inspecting/highlighting nodes
Our own Inspector differs from most other DevTools implementations with
regard to highlighting DOM nodes as you hover elements in the inspected
DOM tree. In other implementations, as you change the hovered node, the
browser will render a box model overlay onto the page for that node. We
currently don't do this; we wait until you click the node, at which
point we both paint the overlay and inspect the node's properties.

This patch does not change that behavior, but separates the IPCs and
internal tracking of inspected nodes to support the standard DevTools
behavior. So the DOM document now stores an inspected node and a
highlighted node. The former is used for features such as "$0" in the
JavaScript console, and the latter is used for the box model overlay.
Our Inspector continues to set these to the same node.
2025-02-24 12:05:29 -05:00
Sam Atkins
0fcd7f9aea LibWeb/DOM: Update an attribute's node document
Corresponds to b64559cc08
2025-02-23 22:36:42 +00:00
InvalidUsernameException
f7276bfab3 LibWeb: Reduced number of recompiled files for CSS property headers
This reduces the number of `.cpp` files that need to be recompiled when
one of the below header files changes as follows:

CSS/ComputedProperties.h: 1113 -> 49
CSS/ComputedValues.h: 1120 -> 209
2025-02-23 10:14:39 -05:00
Aliaksandr Kalenik
0ab61a94d7 LibWeb: Bucket hover rules using RuleCache
Analysis of selectors on modern websites shows that the `:hover`
pseudo-class is mostly used in the subject position within relatively
simple selectors like `.a:hover`. This suggests that we could greatly
benefit from segregating them by id/class/tag name, this way reducing
number of selectors tested during hover style invalidation.

With this change, hover invalidation on Discord goes down from 70ms to
3ms on my machine. I also tested GMail and GitHub where this change
shows nice 2x-3x speedup.
2025-02-22 10:12:24 +01:00
Luke Wilde
cae0ab2139 LibWeb: Make PolicyContainer GC allocated
This is required to store Content Security Policies, as their
Directives are implemented as subclasses with overridden virtual
functions. Thus, they cannot be stored as generic Directive classes, as
it'll lose the ability to call overridden functions when they are
copied.
2025-02-21 12:43:48 +00:00
Aliaksandr Kalenik
1843a54df7 LibWeb: Skip quick selector rejection using ancestor filter if possible
If selector does not have any descendant combinators then we know for
sure it won't be filtered out by ancestor filter, which means there is
no need to check for it.

This change makes hover style invalidation go faster on Discord where
with this change we spend 4-5% in `should_reject_with_ancestor_filter()`
instead of 20%.
2025-02-20 19:48:27 +01:00
Aliaksandr Kalenik
0f8050f0bd LibWeb: Break early from rule testing in hover style invalidation
Before this change, we did the following:
1. Created a bitmap with the matching state for each rule containing
   `:hover`.
2. Changed the actively hovered element in the document.
3. Created another bitmap with the matching state for each rule
   containing `:hover`.

With this change, we iterate rule by rule and compare the matching
state. This allows us to break early once we find the first rule whose
matching state changes after the hovered element update. Additionally,
this removes the need to allocate a bitmap.
2025-02-19 21:52:29 +01:00
Aliaksandr Kalenik
e1119023e9 LibWeb: Optimize pseudo elements presence check in hover style update
Instead of using `has_pseudo_elements()` that iterates over all pseudo
elements, only check if `::before` or `::after` are present.

Before this change, `has_pseudo_elements()` was 10% of profiles on
Discord while now it's 1-2%.
2025-02-19 19:56:52 +01:00
Piotr
c9edb6ffc4 LibWeb: Support for Content-Language HTTP header 2025-02-19 10:53:31 +00:00
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
Shannon Booth
1f4c7ac62b LibWeb/DOM: Remove uneccessary ExceptionOr for NodeIterator::create 2025-01-10 08:08:46 +00:00
Shannon Booth
17c92d7c2b LibWeb/DOM: Create TreeWalker in document's realm 2025-01-10 08:08:46 +00:00
Shannon Booth
84f22cb6b3 LibWeb/DOM: Create NodeIterator in document's realm 2025-01-10 08:08:46 +00:00
Gingeh
4a0ac312cc LibWeb: Obtain theme-color on meta element removal and modification 2025-01-08 11:18:13 +00:00
Gingeh
df70455d3f LibWeb: Implement the color-scheme meta tag name 2025-01-08 11:18:13 +00:00
Gingeh
ce5cd012b9 LibWeb/CSS: Implement the color-scheme CSS property 2025-01-08 11:18:13 +00:00
Aliaksandr Kalenik
5cac301bb7 LibWeb: Optimize hover style invalidation for shadow trees
With this change we skip all :hover selectors that don't belong to a
"style scope" (document or shadow root) of old/new hovered node.
2025-01-06 12:15:06 +01:00
Aliaksandr Kalenik
482e5deb85 LibWeb: Further optimize :hover style invalidation
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.
2025-01-04 20:32:35 +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
Shannon Booth
2066ed2318 LibWeb: Correctly initialize Storage objects on the Document
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.
2025-01-02 11:31:15 +01:00
Lucas CHOLLET
abc0418710 LibWeb/DOM: Convert elapsedTime to seconds when firing AnimationEvents
This makes all three subtests from this test to pass:
 - css/css-animations/animationevent-types.html
2024-12-30 11:05:37 +01:00
Lucas CHOLLET
61b444d538 LibWeb/DOM: Allow the animationiteration event to be fired
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
2024-12-30 11:05:37 +01:00
Lucas CHOLLET
906b7bf4e3 LibWeb/DOM: Conserve references to pending animations
This fixes a crash in:
 - css/css-animations/CSSAnimation-effect.tentative.html
2024-12-30 11:04:55 +01:00
Lucas CHOLLET
9585aeafda LibWeb/DOM: Don't assume that Animations have an associated effect
Fixes a crash on:
 - css/css-transitions/CSSTransition-effect.tentative.html
2024-12-28 10:37:44 +01:00
Lucas CHOLLET
589538ec8f LibWeb/DOM: Visit the animation of Document's pending animations 2024-12-27 11:50:11 -08: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
Lucas CHOLLET
1c61ccef40 LibWeb/DOM: Fire transition[cancel,start,run,end] events 2024-12-25 17:14:08 +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
Tim Ledbetter
7a41ab960c LibWeb: Report exceptions when invoking intersection observer callback 2024-12-19 15:25:08 +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
Sam Atkins
5651c6fd9b LibWeb: Match spec changes for "custom element registry" concept
Corresponds to https://github.com/whatwg/html/pull/10845 and
https://github.com/whatwg/html/pull/10865
2024-12-18 19:22:44 +00:00
Timothy Flynn
a2419b5f4e LibWeb: Add a document observer to be notified upon becoming active 2024-12-11 17:38:31 -07:00
Timothy Flynn
9a62e33517 LibWeb: Protect document observers from GC during observer invocation
We currently (sometimes) copy the observer map to a vector for iteration
to ensure we are not iterating over the map if the callback happens to
remove the observer. But that list was not protected from GC.

This patch ensures we protect that list, and makes all document observer
notifiers protected from removal during iteration.
2024-12-11 17:38:31 -07:00
Timothy Flynn
fe891727dc LibWeb: Use correct URL parsing methods throughout LibWeb
There are essentially 3 URL parsing AOs defined by the spec:
1. Parse a URL
2. Encoding parse a URL
3. Encoding parse a URL and serialize the result

Further, these are replicated between the Document and the ESO.

This patch defines these methods in accordance with the spec and updates
existing users to invoke the correct method. In places where the correct
method is ambiguous, we use the encoding parser to preserve existing ad-
hoc behavior.
2024-12-10 10:37:01 -08:00
Jelle Raaijmakers
1c55153d43 LibWeb: Refactor "editable" and "editing host" concepts
The DOM spec defines what it means for an element to be an "editing
host", and the Editing spec does the same for the "editable" concept.
Replace our `Node::is_editable()` implementation with these
spec-compliant algorithms.

An editing host is an element that has the properties to make its
contents effectively editable. Editable elements are descendants of an
editing host. Concepts like the inheritable contenteditable attribute
are propagated through the editable algorithm.
2024-12-10 14:54:19 +01:00
Andrew Kaster
6ed2bf2bb1 LibWeb: Mark local variables captured in GC functions as ignored
These variables are all captured in queued events or other event loop
tasks, but are all guarded by event loop spins later in the function.

The IGNORE_USE_IN_ESCAPING_LAMBDA will soon be required for all locals
that are captured by ref in GC::Function as well as AK::Function.
2024-12-10 07:13:00 +01:00
Glenn Skrzypczak
156f9fff32 LibWeb: Support the X-Frame-Options header
Navigation responses are now checked for adherence to the
`X-Frame-Options` header and an error is shown accordingly.
2024-12-07 08:38:02 +00:00
Shannon Booth
0fa54c2327 LibURL+LibWeb: Make URL::serialize return a String
Simplifying a bunch of uneeded error handling around the place.
2024-12-04 16:34:13 +00:00
Jelle Raaijmakers
7bb865052a LibWeb: Implement document.execCommand("delete")
To facilitate the implementation of "delete" and all associated
algorithms, split off this piece of `Document` into a separate
directory.

This sets up the infrastructure for arbitrary commands to be supported.
2024-11-30 17:35:45 +01:00
Sam Atkins
63688148b9 LibURL: Promote Host to a proper class
This lets us move a few Host-related functions (like serialization and
checks for what the Host is) into Host instead of having them dotted
around the codebase.

For now, the interface is still very Variant-like, to avoid having to
change quite so much in one go.
2024-11-30 12:07:39 +01:00
Gingeh
0adf261c32 LibWeb: Don't end parsing after reaching the insertion point 2024-11-26 23:50:18 +01:00
Sam Atkins
310cdc35f0 LibWeb: Fill-in some fixmes around sandboxing flag sets
...Including a couple of steps in
obtain_a_browsing_context_to_use_for_a_navigation_response() which
didn't have FIXMEs.

No apparent changes on WPT.
2024-11-26 10:59:50 +01:00
Shannon Booth
9724c67be2 LibWeb: Default initialize StructuredDeserialize memory argument
This is optional in the spec, so let's make it actually optional at the
call site.
2024-11-23 16:43:55 +01:00
Jonne Ransijn
f093a8af67 LibWeb: Copy m_resize_observers before iterating
An inopportune garbage collection may cause collected `ResizeObserver`s
to unregister themselves from `m_resize_observers` while we are
iterating over it, resulting in a use-after-free.
2024-11-21 19:18:26 +01:00
Shannon Booth
d6bcd3fb0b LibWeb: Make CallbackType take a realm instead of settings object
In line with the ShadowRealm proposal changes in the WebIDL spec:
webidl#1437 and supporting changes in HTML spec.

This is required for ShadowRealms as they have no relevant settings
object on the shadow realm, so fixes a crash in the QueueingStrategy
test in this commit.
2024-11-20 18:01:21 -07: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
Aliaksandr Kalenik
1a1fb14e26 LibWeb: Recompute selection state in Document::update_layout()
Fixes a bug when text selection disappears after relayout.
2024-11-14 19:48:43 +01:00
Aliaksandr Kalenik
d7caa426a0 LibWeb: Delete m_selected flag from Paintable
This was redundant when Paintable already has `m_selection_state` that
could be none.
2024-11-14 19:48:43 +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
Andreas Kling
b397a0d535 LibWeb: Make Document::m_intersection_observers a weak mapping
These registrations are not meant to keep the observers alive.
This fixes a handful of world leaks on Speedometer.
2024-11-11 21:40:56 +01: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
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
2cc39cfb0e LibWeb: Copy some properties from specified style into layout node
Another step towards not having to carry the full specified style with
us everywhere. This isn't the ideal final layout, since we're mixing
computed and used values a bit randomly here, but one step at a time.
2021-01-06 14:58:48 +01:00
Andreas Kling
5721b2a3da LibWeb: Rename LayoutStyle => CSS::ComputedValues
This object represents the CSS "computed values" so let's call it that.
2021-01-06 14:58:48 +01:00
Andreas Kling
c630ae517e LibWeb: Put final foreground/background colors in LayoutStyle
This way we don't have to look them up in the CSS::StyleProperties
every time we want to paint with them.
2020-12-15 19:33:53 +01:00
Andreas Kling
bceb5b60f7 LibWeb: Add a little assertion in Document::detach_from_frame()
Let's just assert that we're detaching from the frame we thought we
were in.. just in case.
2020-12-14 13:47:07 +01:00
Andreas Kling
34d0141da3 LibWeb: Simplify <iframe> content frame construction
Now that documents are attached to their frame *before* parsing, we can
create the content frame of <iframe> elements right away, instead of
waiting for the host frame attachment.

Fixes #4408.
2020-12-14 13:45:57 +01:00
Andreas Kling
6809be436b LibWeb: Limit style update tree traversal to dirty subtrees
This patch adds a second style dirty bit that tracks whether a DOM node
has one or more children with dirty style. This allows the style update
to skip over entire subtrees where all nodes are clean.
2020-12-14 12:04:30 +01:00
Andreas Kling
3c9dcec442 LibWeb: Merge Document::layout() and Document::update_layout()
There is now only Document::update_layout().
2020-12-14 10:39:57 +01:00
Andreas Kling
253aa7aa7d LibWeb: Make document.title accessible from JavaScript :^) 2020-12-06 21:39:36 +01:00
Andreas Kling
d22512a024 LibWeb: Strip and collapse whitespace in document.title
I didn't generalize this into a helper since the HTML spec doesn't
seem to use this particular algorithm for anything else.

This makes the ACID1 test title show up correctly. :^)
2020-12-06 21:22:31 +01:00
Andreas Kling
59de4adb60 LibWeb: Pass current target box to BFC::run()
The BFC "context box" is now the outer box of the block formatting
context. Previously the context box was always the current target box,
which made it hard to reason about who was really the containing block
of whom in various places.

Note that IFC still has the containing block as its context box, this
change only affects BFC. However, to clarify the situation in IFC,
I've added a containing_block() getter than returns the context_box().
2020-12-06 20:05:04 +01:00
Andreas Kling
7c4c706ebe LibWeb: Implement Document.getElementsByClassName()
Note that we're taking a shortcut here and returning the elements as an
Array instead of HTMLCollection. One day we'll have to bite the bullet
and deal with HTMLCollection, but not today.
2020-12-01 16:53:10 +01:00
Andreas Kling
01c8765519 LibJS+LibWeb: Log JavaScript exceptions raised by web content
Instead of hiding JS exceptions raised on the web, we now print them to
the debug log. This will make it a bit easier to work out why some web
pages aren't working right. :^)
2020-11-29 16:50:32 +01:00
Andreas Kling
d477039abc LibWeb: Rename Layout::LayoutTreeBuilder => Layout::TreeBuilder 2020-11-25 21:27:18 +01:00
Andreas Kling
b1e75437c9 LibWeb: Keep track of the parent of each formatting context
This will allow us to find the containing block formatting context
when needed later on.
2020-11-25 21:26:58 +01:00
Luke
9950270808 LibWeb: Add HTML::EventNames and UIEvents::EventNames 2020-11-22 18:20:56 +01:00
Luke
e8b3a65581 LibWeb: Make event dispatching spec-compliant
Specification: https://dom.spec.whatwg.org/#concept-event-dispatch

This also introduces shadow roots due to it being a requirement of
the event dispatcher.

However, it does not introduce the full shadow DOM, that can be
left for future work.

This changes some event dispatches which require certain attributes
to be initialised to a value.
2020-11-22 18:20:56 +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
Andreas Kling
e1a24edfa9 LibWeb: Reorganize layout system in terms of formatting contexts
This is a first (huge) step towards modernizing the layout architecture
and bringing it closer to spec language.

Layout is now performed by a stack of formatting contexts, operating on
the box tree (or layout tree, if you will.)

There are currently three types of formatting context:

- BlockFormattingContext (BFC)
- InlineFormattingContext (IFC)
- TableFormattingContext (TFC)

Document::layout() creates the initial BlockFormattingContext (BFC)
which lays out the initial containing block (ICB), and then we recurse
through the tree, creating BFC, IFC or TFC as appropriate and handing
over control at the context boundaries.

The majority of this patch is just refactoring the old logic spread out
in LayoutBlock and LayoutTableRowGroup, and turning into these context
classes instead. A lot more cleanup will be needed.

There are many architectural wins here, the main one being that layout
is no longer performed by boxes themselves, which gives us much greater
flexibility in the outer/inner layout of a given box.
2020-11-22 14:36:56 +01:00
Luke
dcb21b0c3a LibWeb: Add initial implementation of document.implementation 2020-11-13 09:51:07 +01:00
Andreas Kling
81add73955 LibWeb: Make Frame point weakly to Page
This patch makes Page weakable and allows page-less frames to exist.

Page is single-owner, and Frame is multiple-owner, so it's not sound
for Frame to assume its containing Page will stick around for its own
entire lifetime.

Fixes #3976.
2020-11-12 18:29:55 +01:00
Tom
75f61fe3d9 AK: Make RefPtr, NonnullRefPtr, WeakPtr thread safe
This makes most operations thread safe, especially so that they
can safely be used in the Kernel. This includes obtaining a strong
reference from a weak reference, which now requires an explicit
call to WeakPtr::strong_ref(). Another major change is that
Weakable::make_weak_ref() may require the explicit target type.
Previously we used reinterpret_cast in WeakPtr, assuming that it
can be properly converted. But WeakPtr does not necessarily have
the knowledge to be able to do this. Instead, we now ask the class
itself to deliver a WeakPtr to the type that we want.

Also, WeakLink is no longer specific to a target type. The reason
for this is that we want to be able to safely convert e.g. WeakPtr<T>
to WeakPtr<U>, and before this we just reinterpret_cast the internal
WeakLink<T> to WeakLink<U>, which is a bold assumption that it would
actually produce the correct code. Instead, WeakLink now operates
on just a raw pointer and we only make those constructors/operators
available if we can verify that it can be safely cast.

In order to guarantee thread safety, we now use the least significant
bit in the pointer for locking purposes. This also means that only
properly aligned pointers can be used.
2020-11-10 19:11:52 +01:00
Andreas Kling
f79e28bd65 LibWeb: Break reference cycles so DOM::Document actually gets deleted
When a document reaches ref_count==0, we will now remove all of the
descendant nodes from the document, and also break all the explicit
links (such as the currently hovered element.)

Basically, DOM nodes will keep the document alive even after the
document reaches ref_count==0. This allows JS wrappers to stay alive
and keep the document alive as well. This matches the behavior of
at least some other browsers.

This patch also adds a bunch of sanity checking assertions around
DOM teardown, to help catch mistakes in the future.

Fixes #3771.
2020-10-22 23:41:32 +02:00
Luke
e8a9e8aed5 LibWeb: Add namespace to Element 2020-10-22 15:24:42 +02:00
Andreas Kling
0af2795662 LibWeb: Tear down layout trees properly
Instead of just ripping out the root of the layout tree from its RefPtr
in Document, actually go through the DOM and gather up all the layout
nodes. Then destroy them all in one swoop.

Also, make sure to do this when detaching Document from Frame,
to enforce the invariant that layout only occurs in framed documents.
2020-10-20 18:08:37 +02:00
Andreas Kling
f68ed6d25b LibWeb: Make DOM Nodes keep their Document alive
In addition to being reference-counted, all nodes that are part of a
document must also keep the document alive.

This is achieved by adding a second ref-count to the Document object
and incrementing/decrementing it whenever a node is created/destroyed
in that document.

This brings us much closer to a proper DOM lifetime model, although
the JS bindings still need more work.
2020-10-11 21:52:59 +02:00
Andreas Kling
99acbbe86b LibWeb: Remove unused Document::fixup()
This was some naive fixup mechanism we used before implementing a spec
compliant HTML parser.
2020-10-11 21:24:14 +02:00
Andreas Kling
51dbea3a0e LibWeb: Use RefPtrs more in getElementById() and getElementsByName()
Passing around Vector<Element*> is not a great idea long-term.
2020-10-07 12:47:17 +02:00
Ben Wiederhake
08f9bc26a6 Meta+LibHTTP through LibWeb: Make clang-format-10 clean 2020-09-25 21:18:17 +02:00
Andreas Kling
4a8bfcdd1c LibJS: Move the current exception from Interpreter to VM
This will allow us to throw exceptions even when there is no active
interpreter in the VM.
2020-09-22 20:10:20 +02:00
Andreas Kling
1c43442be4 LibJS+Clients: Add JS::VM object, separate Heap from Interpreter
Taking a big step towards a world of multiple global object, this patch
adds a new JS::VM object that houses the JS::Heap.

This means that the Heap moves out of Interpreter, and the same Heap
can now be used by multiple Interpreters, and can also outlive them.

The VM keeps a stack of Interpreter pointers. We push/pop on this
stack when entering/exiting execution with a given Interpreter.
This allows us to make this change without disturbing too much of
the existing code.

There is still a 1-to-1 relationship between Interpreter and the
global object. This will change in the future.

Ultimately, the goal here is to make Interpreter a transient object
that only needs to exist while you execute some code. Getting there
will take a lot more work though. :^)

Note that in LibWeb, the global JS::VM is called main_thread_vm(),
to distinguish it from future worker VM's.
2020-09-20 19:24:44 +02:00
Luke
124c52b3b5 LibWeb: Implement document ready state 2020-08-31 23:05:51 +02:00