Commit Graph

34 Commits

Author SHA1 Message Date
Aliaksandr Kalenik
b3231ea2a0 LibWeb: Make foreignObject establish a containing block for abspos
Absolutely positioned elements inside SVG foreignObject were being
positioned relative to an ancestor containing block outside the SVG,
instead of relative to the foreignObject itself. Per a W3C resolution
and the behavior of other browsers, foreignObject should establish a
containing block for absolutely and fixed positioned elements.

With this fix, the `has_abspos_with_external_containing_block` check
in `set_needs_layout_update()` and the abspos preservation loop in
`relayout_svg_root()` become dead code — remove both and simplify the
ancestor loops. Rename related tests to reflect the new behavior.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/3241
2026-02-17 15:59:59 +01:00
Aliaksandr Kalenik
79e9cea8cb Tests: Add failing test for SVG partial relayout paintable leak
The test triggers repeated partial relayout inside a nested SVG and
checks paintables on an outside-subtree SVG ancestor via
`internals.dumpPaintableTree()`. The count should stay stable, but
currently grows, revealing that partial relayout is creating extra
ancestor paintables instead of preserving existing ones.

No fix in this commit; this commit only captures the failing behavior.
2026-02-15 17:47:30 +01:00
Aliaksandr Kalenik
085cf42712 LibWeb: Fix SVG partial relayout skipping abspos sibling updates
When a CharacterData mutation inside a foreignObject triggered partial
SVG relayout, sibling absolutely positioned elements whose containing
block is outside the SVG were not being repositioned. This happened
because the check only walked ancestors of the changed node looking for
abspos elements — it never saw abspos siblings.

Fix by querying contained_abspos_children() on boxes outside the SVG
subtree, which finds all abspos elements regardless of their position
in the tree relative to the changed node.
2026-02-14 03:20:34 +01:00
Aliaksandr Kalenik
01334c4481 LibWeb: Fix partial relayout of abspos with containing block outside SVG
When a text node changes inside an absolutely positioned element within
an SVG <foreignObject>, and the abspos element's containing block is
outside the SVG subtree, the layout invalidation was incorrectly
stopping at the SVG root boundary. This triggered partial SVG relayout,
which cannot re-layout the abspos element since it's laid out by its
containing block's formatting context (outside the SVG).

The previous check only tested whether `this` (the node triggering
invalidation, e.g. a text node) was absolutely positioned, missing the
case where an abspos *ancestor* in the path has its containing block
outside the SVG. Fix this by walking from `this` up to the SVG root and
checking every abspos node in the path. If any has a containing block
outside the SVG subtree, skip the SVG boundary so layout propagation
continues upward and a full layout runs.
2026-02-13 17:47:49 +01:00
Aliaksandr Kalenik
36a74feb61 Tests: Abspos size change in fO with ancestor containing block
This is a regression test for partial SVG relayout. When an absolutely
positioned element inside foreignObject has its containing block outside
the SVG subtree, changing its size should trigger a correct relayout.
2026-02-09 03:02:49 +01:00
Aliaksandr Kalenik
1e2a4cd7b6 Tests: Add test for SVG relayout with ancestor graphics element
Regression test for SVG partial layout that will be introduced in the
upcoming changes.
2026-02-09 03:02:49 +01:00
Aliaksandr Kalenik
b1921f60ce Tests: Add test for abspos in foreignObject with ancestor containing box
This test covers the case where an absolutely positioned element inside
<foreignObject> has a containing block that is an ancestor of the <svg>.
It serves as a regression test for partial SVG relayout that is going
to be introduced in the upcoming changes.
2026-02-09 03:02:49 +01:00
Aliaksandr Kalenik
12ba454a5b LibWeb: Stop intrinsic size cache invalidation at SVG root boundaries
SVG root elements (SVGSVGBox) have intrinsic sizes determined solely
by their own attributes (width, height, viewBox), not by their
children. SVGFormattingContext::automatic_content_width/height() both
return 0 unconditionally, confirming children never contribute to the
SVG root's intrinsic size from the CSS layout perspective.

This means changes inside an SVG subtree cannot affect ancestor
intrinsic sizes, so we can stop the cache invalidation traversal at
SVG root boundaries, just like we already do for absolutely positioned
elements.
2026-02-05 20:26:30 +01:00
Andreas Kling
a64ea670fd LibWeb: Fix excessive recursion when removing SVG elements from use tree
When an SVGElement is removed from a <use> element's shadow tree, we
need to check if it was in a use element's shadow root to avoid
notifying use elements about the removal of their own clones.

The check was incorrectly using root() instead of old_root. Since the
element has already been detached when removed_from() is called,
root() no longer returns the shadow root, causing the early-return
check to fail.

This led to O(n) recursion depth when clearing a use element's shadow
tree, as each removed clone would trigger another round of
remove_all_children() on use elements referencing the same ID.
2026-01-14 11:46:23 +01:00
Pavel Shliak
88500580e6 LibWeb: Make getBBox() throw error for non-rendered elements
Per SVG2 spec (§ Geometry Properties: getBBox), getBBox() must throw
InvalidStateError if the element is not rendered and its geometry cannot
be computed. Previously we would crash on null paintables; now we throw
with a clear error instead.
2025-10-06 00:14:04 +02:00
Erik Kurzinger
21ff66c6cb LibWeb/SVG: Parse comma-separated SVG viewBox
From the SVG spec

The value of the ‘viewBox’ attribute is a list of four numbers <min-x>,
<min-y>, <width> and <height>, separated by whitespace and/or a comma...

Currently try_parse_view_box will fail to parse the attribute if the
values are separated by commas.

This change replaces try_parse_view_box with a more correct
implementation. It will reside in the AttributeParser.cpp. This new
implementation correctly handles comma-separated viewBox values, and is
also more robust against invalid inputs.

Additionally, it adds a new test case to ensure viewBox values with
various syntax are parsed correctly and invalid values are rejected.
2025-08-30 15:49:11 +02:00
Jelle Raaijmakers
676f5837b3 LibWeb: Implement SVGLength's read-only property
An SVGLength can be read-only, e.g. all animVal values cannot be
modified. Implement this for all instantiations of SVGLength.

While we're here, add `fake_animated_length_fixme()` so we can easily
find all sites where we need to improve our animated length game.
2025-08-27 11:50:27 +02:00
Andreas Kling
34ec33d71c LibWeb: Don't treat SVG "use clone" removals as "use source" removals
We were failing to discriminate between DOM removals happening to SVG
elements cloned as part of an SVG use element instantiation.

When a "use source" element is removed, all clones of that source must
be updated to reflect the change. But when a "use clone" element is
removed, that's fine.

This was causing the surprising disappearance of use element subtrees,
seen for example on https://cal.com/
2025-08-07 22:15:36 +02:00
Andreas Kling
42802b0785 LibWeb: SVG use element shadow roots should be closed, not open
This goes against the spec but matches all other browser engines.
2025-08-07 22:15:36 +02:00
Tim Ledbetter
488333aa4b Tests: Convert an SVG text test to a crash test
This should have been a crash test, but the test runner previously
didn't wait long enough for the test to crash.
2025-07-14 13:05:17 -04:00
Jelle Raaijmakers
97fa0be16e LibWeb: Implement SVGAnimatedNumber 2025-07-11 11:25:59 +01:00
Tim Ledbetter
438bb56160 LibWeb/SVG: Don't crash when a filter has no valid effects 2025-07-10 00:18:25 +02:00
Psychpsyo
b3487d8994 Meta: Add DOCTYPEs to most text tests 2025-03-20 11:50:49 +01:00
Tim Ledbetter
a187d5f28f LibWeb/SVG: Process script element when its text content changes 2025-02-26 16:08:35 +01:00
Andreas Kling
96e074b38f LibWeb: Make SVGSVGElement.getElementById() return Element? (nullable)
This is wrong in the spec, and there's already a bug open.
2025-01-21 02:06:33 +01:00
Jelle Raaijmakers
614b93beca Meta: Set constructor prototype in IDLGenerators
Without this, retrieving `__proto__` from any interface will always
yield an instance of `FunctionPrototype`.
2024-11-26 12:44:05 +00:00
Tim Ledbetter
b140206a91 LibWeb: Don't crash when calling getBBox() on the outermost SVG element 2024-09-07 14:35:02 +02:00
Tim Ledbetter
d417b75683 LibWeb/SVG: Ensure SVG transform has an inverse before using it
This avoids a crash that occurred when calling `getBBox()` on an SVG
element that had a transform with no inverse.

Found by Domato.
2024-07-22 09:13:25 +02:00
Jamie Mansfield
6f3c5f5ae9 LibWeb/SVG: Implement SVGElement.ownerSVGElement 2024-07-16 21:43:53 +02:00
Jamie Mansfield
9d1ea4c7e0 LibWeb: Implement SVGElement.className 2024-07-10 10:28:43 +02:00
Andreas Kling
4db05ecf69 LibWeb: Set the correct prototype for SVGAElement instances 2024-06-28 17:10:52 +02:00
Tim Ledbetter
3518f39b60 LibWeb: Don't crash when querying detached circle element properties 2024-03-23 20:56:26 +01:00
Tim Ledbetter
e9383b9c86 LibWeb: Avoid division by zero when calculating SVG viewbox aspect ratio 2024-03-17 12:54:02 +01:00
Andreas Kling
2e0297d703 LibWeb: Handle reference cycles in SVG gradient linking
Since SVG gradients can reference each other, we have to keep track of
visited gradients when traversing the link chain, or we will recurse
infinitely when there's a reference cycle.
2024-03-11 18:29:10 +01:00
Andreas Kling
b12541b286 LibWeb: Add SVGSVGElement.viewBox attribute
This attribute has some compatbility issues...
- The spec says it should be an SVGAnimatedRect which contains
  a DOMRect and a DOMReadOnlyRect.
- Blink gives you an SVGAnimatedRect with 2x SVGRect
- Gecko gives you an SVGAnimatedRect with 2x SVGRect? (nullable)

I ended up with something similar to Gecko, an SVGAnimatedRect
with 2x DOMRect? (nullable)

With this fixed, we can now load https://polar.sh/ :^)
2024-01-25 08:23:41 +01:00
Luke Wilde
54972e3ceb LibWeb: Implement SVGUseElement#href
Required by Ruffle.
b196c8d1bc/web/packages/core/src/shadow-template.ts (L601-L602)
2023-12-30 18:50:29 +01:00
Shannon Booth
4821d284c6 LibWeb: Add support for inline SVG element scripts 2023-11-05 11:16:16 +00:00
Shannon Booth
e5d45eeeb1 LibWeb: Properly append attributes to element when creating an Element
The main behavioural difference here is that the full qualified name is
appended to the element, rather than just the local name and value.
2023-11-05 11:16:16 +00:00
Shannon Booth
07b332e17c LibWeb: Add IDL definition for SVGScriptElement
It does not currently handle any of the actual scripting, but this
should at least allow us to create an instance of the element.

The test being added here isn't actually testing much, but before the
previous commit we used to crash parsing the page due to a TODO().
2023-09-23 11:41:57 +02:00