From 18a4455d4317eefc940f469a5e9ecc4f788fd41f Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 3 Dec 2023 14:34:53 -0500 Subject: [PATCH] LibWeb: Do not assume a shadow root has a host After commit ff48b7333cd608f36c5841618dd74d2126cfaac2, we remove shadow roots from elements that are removed from the DOM. Setting a node's shadow root to null also sets that shadow root's host to null. Thus, the comment in Node::is_shadow_including_descendant_of that assumes the host is always non-null is not true. The test added here would previously crash when interacting with a node that is a descendant of a removed shadow root. --- ...w-tree-removed-from-dom-receives-event.txt | 20 +++++++++++++++++++ ...-tree-removed-from-dom-receives-event.html | 14 +++++++++++++ Userland/Libraries/LibWeb/DOM/Node.cpp | 3 +-- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/shadow-tree-removed-from-dom-receives-event.txt create mode 100644 Tests/LibWeb/Layout/input/shadow-tree-removed-from-dom-receives-event.html diff --git a/Tests/LibWeb/Layout/expected/shadow-tree-removed-from-dom-receives-event.txt b/Tests/LibWeb/Layout/expected/shadow-tree-removed-from-dom-receives-event.txt new file mode 100644 index 00000000000..ea0d47fed36 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/shadow-tree-removed-from-dom-receives-event.txt @@ -0,0 +1,20 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x17.46875 children: not-inline + BlockContainer at (8,8) content-size 784x17.46875 children: inline + line 0 width: 43.421875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 5, rect: [8,8 43.421875x17.46875] + "Pass!" + InlineNode + TextNode <#text> + BlockContainer <(anonymous)> at (8,25.46875) content-size 784x0 children: inline + TextNode <#text> + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x600] + PaintableWithLines (BlockContainer) [8,8 784x17.46875] + PaintableWithLines (BlockContainer
#container) [8,8 784x17.46875] + InlinePaintable (InlineNode) + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer(anonymous)) [8,25.46875 784x0] diff --git a/Tests/LibWeb/Layout/input/shadow-tree-removed-from-dom-receives-event.html b/Tests/LibWeb/Layout/input/shadow-tree-removed-from-dom-receives-event.html new file mode 100644 index 00000000000..f8899717e6d --- /dev/null +++ b/Tests/LibWeb/Layout/input/shadow-tree-removed-from-dom-receives-event.html @@ -0,0 +1,14 @@ +
+
+ summary + +
+
+ diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index 609d4467b33..9e2b891f30d 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -1259,8 +1259,7 @@ bool Node::is_shadow_including_descendant_of(Node const& other) const // and A’s root’s host is a shadow-including inclusive descendant of B. auto& shadow_root = verify_cast(root()); - // NOTE: While host is nullable because of inheriting from DocumentFragment, shadow roots always have a host. - return shadow_root.host()->is_shadow_including_inclusive_descendant_of(other); + return shadow_root.host() && shadow_root.host()->is_shadow_including_inclusive_descendant_of(other); } // https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant