1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-08 05:27:14 +09:00
Commit graph

235 commits

Author SHA1 Message Date
Timothy Flynn
0a256b0a9a AK+Everywhere: Change StringView case conversions to return String
There's a bit of a UTF-8 assumption with this change. But nearly every
caller of these methods were immediately creating a String from the
resulting ByteString anyways.
2025-04-07 17:44:38 +02:00
Kenneth Myhra
82a2ae99c8 Everywhere: Remove DeprecatedFlyString + any remaining references to it
This reverts commit 7c32d1e8a5.
2025-04-02 11:43:13 +02:00
Andreas Kling
7c32d1e8a5 Revert "Everywhere: Remove DeprecatedFlyString + any remaining references to it"
This reverts commit 3131e6369f.

Greatly regressed JavaScript benchmark performance.
2025-04-01 15:40:27 +02:00
Kenneth Myhra
3131e6369f Everywhere: Remove DeprecatedFlyString + any remaining references to it 2025-04-01 12:50:00 +02:00
Luke Wilde
c7d25301d3 LibWeb: Implement the LegacyUnforgeable attribute
This fixes the frame-ancestors WPT tests from crashing when an iframe
is blocked from loading. This is because it would get an undefined
location.href from the cross-origin iframe, which causes a crash as it
expects it to be there.
2025-03-27 23:50:35 +00:00
Aliaksandr Kalenik
7cae4fadbc LibWeb: Cache "has size containment" flag in Layout::Box
Allows us to avoid DOM node lookup whenever we need to query natural
size of a box during layout.

Makes 3-4% of `Box::preferred_aspect_ratio()` go away from profiles on
www.nyan.cat
2025-03-26 17:52:02 +00: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
Aliaksandr Kalenik
275985ff3d LibWeb: Ignore non-box element while collecting abspos nodes for layout
All abspos boxes are expected to be blockified, so we are certain that
we can ignore non-box elements when collecting abspos nodes for layout.

Fixes a crash caused by an attempt to cast a BreakNode to a Box while
performing abspos layout.
2025-03-26 00:17:53 +00:00
Andreas Kling
46a5710238 LibJS: Use FlyString in PropertyKey instead of DeprecatedFlyString
This required dealing with *substantial* fallout.
2025-03-24 22:27:17 +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
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
Sam Atkins
70e3a48892 LibWeb: Stub out "focus-without-user-activation" feature policy
For now this always returns that focus is allowed, as that matches our
previous behavior.

Corresponds to d7053d86ad
2025-03-14 20:33:25 +00:00
Luke Wilde
819bff9ec0 LibWeb: Create policy containers from responses and then run CSP init
This allows us to parse the Content-Security-Policy header and
Referrer-Policy header from navigation responses and actually allow
them to start having an effect.
2025-03-13 16:19:22 +01:00
Andreas Kling
067d21b8a4 LibWeb: Don't drop entire layout tree on media query state change
This isn't actually necessary, since we already invalidate style for the
entire document, and the subsequent style update will discover any
additional layout invalidation needed as well.
2025-03-08 20:22:01 +01:00
Aliaksandr Kalenik
a4463c45b9 LibWeb: Bring back cache of intrinsic sizes across layout runs
12c6ac78e2 with fixed mistake when cache
slot is copied instead of being referenced:
```cpp
auto cache =
    box.cached_intrinsic_sizes().min_content_height.ensure(width);
```
while it should've been:
```cpp
auto& cache =
    box.cached_intrinsic_sizes().min_content_height.ensure(width);
```
2025-03-08 14:52:33 +01:00
Andreas Kling
73a4b176cf Revert "LibWeb: Cache intrinsic sizes across layout runs"
This reverts commit 12c6ac78e2.

Very large performance regression when viewing GitHub repository pages.
2025-03-08 12:08:51 +01:00
Aliaksandr Kalenik
12c6ac78e2 LibWeb: Cache intrinsic sizes across layout runs
This change moves intrinsic sizes cache from
LayoutState, which is local to current layout run,
to layout nodes, so it could be reused between
layout runs. This optimization is possible because
we can guarantee that these measurements will
remain unchanged unless the style of the element
or any of its descendants changes.

For now, invalidation is implemented simply by
resetting cache on whole ancestors chain once we
figured that element needs layout update.
The case when layout is invalidated by DOM's
structural changes is covered by layout tree
invalidation that drops intrinsic sizes cache
along with layout nodes.

I measured improvement on couple websites:
- Mail list on GMail 28ms -> 6ms
- GitHub large code page 47ms -> 36ms
- Discord chat history 15ms -> 8ms
(Time does not include `commit()`)
2025-03-08 11:45:36 +01:00
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