From 34ec33d71c750428ee7ddc0992f16c1c0081e511 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 7 Aug 2025 18:55:45 +0200 Subject: [PATCH] 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/ --- Libraries/LibWeb/SVG/SVGElement.cpp | 7 +++++ ...removeChild-on-ancestor-of-use-element.txt | 4 +++ ...emoveChild-on-ancestor-of-use-element.html | 31 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 Tests/LibWeb/Text/expected/SVG/removeChild-on-ancestor-of-use-element.txt create mode 100644 Tests/LibWeb/Text/input/SVG/removeChild-on-ancestor-of-use-element.html diff --git a/Libraries/LibWeb/SVG/SVGElement.cpp b/Libraries/LibWeb/SVG/SVGElement.cpp index 5336d4821bd..f2e8a47c8d9 100644 --- a/Libraries/LibWeb/SVG/SVGElement.cpp +++ b/Libraries/LibWeb/SVG/SVGElement.cpp @@ -240,6 +240,13 @@ void SVGElement::removed_from(Node* old_parent, Node& old_root) { Base::removed_from(old_parent, old_root); + if (auto* shadow_root = as_if(root())) { + // If this element is in a shadow root hosted by a use element, + // it already represents a clone and is not itself referenced. + if (shadow_root->host() && is(*shadow_root->host())) + return; + } + remove_from_use_element_that_reference_this(); } diff --git a/Tests/LibWeb/Text/expected/SVG/removeChild-on-ancestor-of-use-element.txt b/Tests/LibWeb/Text/expected/SVG/removeChild-on-ancestor-of-use-element.txt new file mode 100644 index 00000000000..4743ea19cc2 --- /dev/null +++ b/Tests/LibWeb/Text/expected/SVG/removeChild-on-ancestor-of-use-element.txt @@ -0,0 +1,4 @@ +use1 > [object SVGSVGElement] foo +use2 > [object SVGSVGElement] foo +no use1 +use2 > [object SVGSVGElement] foo diff --git a/Tests/LibWeb/Text/input/SVG/removeChild-on-ancestor-of-use-element.html b/Tests/LibWeb/Text/input/SVG/removeChild-on-ancestor-of-use-element.html new file mode 100644 index 00000000000..b38092554ce --- /dev/null +++ b/Tests/LibWeb/Text/input/SVG/removeChild-on-ancestor-of-use-element.html @@ -0,0 +1,31 @@ + + +
+ +
+
+ +
+ +