diff --git a/Tests/LibWeb/Text/expected/ShadowDOM/remove-style-element-inside-shadow-tree.txt b/Tests/LibWeb/Text/expected/ShadowDOM/remove-style-element-inside-shadow-tree.txt new file mode 100644 index 00000000000..b5528437c81 --- /dev/null +++ b/Tests/LibWeb/Text/expected/ShadowDOM/remove-style-element-inside-shadow-tree.txt @@ -0,0 +1,4 @@ + hello [object StyleSheetList] +Before remove, sheet count: 1 +After remove, sheet count: 0 +After setting innerText of removed sheet, we're still alive! diff --git a/Tests/LibWeb/Text/input/ShadowDOM/remove-style-element-inside-shadow-tree.html b/Tests/LibWeb/Text/input/ShadowDOM/remove-style-element-inside-shadow-tree.html new file mode 100644 index 00000000000..c5642083f25 --- /dev/null +++ b/Tests/LibWeb/Text/input/ShadowDOM/remove-style-element-inside-shadow-tree.html @@ -0,0 +1,20 @@ +
+ +
+ + diff --git a/Userland/Libraries/LibWeb/DOM/StyleElementUtils.cpp b/Userland/Libraries/LibWeb/DOM/StyleElementUtils.cpp index 539fa45d26c..fea12d0583b 100644 --- a/Userland/Libraries/LibWeb/DOM/StyleElementUtils.cpp +++ b/Userland/Libraries/LibWeb/DOM/StyleElementUtils.cpp @@ -7,11 +7,21 @@ #include #include #include +#include #include #include namespace Web::DOM { +static CSS::StyleSheetList& relevant_style_sheet_list_for_node(DOM::Node& node) +{ + auto& root_node = node.root(); + if (is(root_node)) + return static_cast(root_node).style_sheets(); + + return node.document().style_sheets(); +} + // The user agent must run the "update a style block" algorithm whenever one of the following conditions occur: // FIXME: The element is popped off the stack of open elements of an HTML parser or XML parser. // @@ -22,7 +32,7 @@ namespace Web::DOM { // The element is not on the stack of open elements of an HTML parser or XML parser, and it becomes connected or disconnected. // // https://html.spec.whatwg.org/multipage/semantics.html#update-a-style-block -void StyleElementUtils::update_a_style_block(DOM::Element& style_element) +void StyleElementUtils::update_a_style_block(DOM::Element& style_element, JS::GCPtr old_parent_if_removed_from) { // OPTIMIZATION: Skip parsing CSS if we're in the middle of parsing a HTML fragment. // The style block will be parsed upon insertion into a proper document. @@ -33,7 +43,13 @@ void StyleElementUtils::update_a_style_block(DOM::Element& style_element) // 2. If element has an associated CSS style sheet, remove the CSS style sheet in question. if (m_associated_css_style_sheet) { - style_element.document_or_shadow_root_style_sheets().remove_a_css_style_sheet(*m_associated_css_style_sheet); + // NOTE: If we're here in response to a node being removed from the tree, we need to remove the stylesheet from the style scope + // of the old parent, not the style scope of the node itself, since it's too late to find it that way! + if (old_parent_if_removed_from) { + relevant_style_sheet_list_for_node(*old_parent_if_removed_from).remove_a_css_style_sheet(*m_associated_css_style_sheet); + } else { + style_element.document_or_shadow_root_style_sheets().remove_a_css_style_sheet(*m_associated_css_style_sheet); + } // FIXME: This should probably be handled by StyleSheet::set_owner_node(). m_associated_css_style_sheet = nullptr; diff --git a/Userland/Libraries/LibWeb/DOM/StyleElementUtils.h b/Userland/Libraries/LibWeb/DOM/StyleElementUtils.h index 14d3d06db57..f0879ff36c1 100644 --- a/Userland/Libraries/LibWeb/DOM/StyleElementUtils.h +++ b/Userland/Libraries/LibWeb/DOM/StyleElementUtils.h @@ -14,7 +14,7 @@ namespace Web::DOM { class StyleElementUtils { public: - void update_a_style_block(DOM::Element& style_element); + void update_a_style_block(DOM::Element& style_element, JS::GCPtr old_parent_if_removed_from = nullptr); CSS::CSSStyleSheet* sheet() { return m_associated_css_style_sheet; } CSS::CSSStyleSheet const* sheet() const { return m_associated_css_style_sheet; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp index c3ab7b4e060..33126fb0bb0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLStyleElement.cpp @@ -46,7 +46,7 @@ void HTMLStyleElement::inserted() void HTMLStyleElement::removed_from(Node* old_parent) { - m_style_element_utils.update_a_style_block(*this); + m_style_element_utils.update_a_style_block(*this, old_parent); Base::removed_from(old_parent); } diff --git a/Userland/Libraries/LibWeb/SVG/SVGStyleElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGStyleElement.cpp index 983e9bd7081..86ee2fd8b4c 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGStyleElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGStyleElement.cpp @@ -44,7 +44,7 @@ void SVGStyleElement::inserted() void SVGStyleElement::removed_from(Node* old_parent) { - m_style_element_utils.update_a_style_block(*this); + m_style_element_utils.update_a_style_block(*this, old_parent); Base::removed_from(old_parent); }