From c6e69d501f81fec6492a3ee183fe555a52670553 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sun, 19 Mar 2023 15:13:45 +0100 Subject: [PATCH] LibWeb: Add style sheets to the shadow root if applicable If a style element belongs to a shadow tree, its CSSStyleSheet is now added to the corresponding ShadowRoot instead of the document. Co-authored-by: Simon Wanner --- .../Text/expected/shadow-root-style-sheets.txt | 2 ++ .../Text/input/shadow-root-style-sheets.html | 18 ++++++++++++++++++ Userland/Libraries/LibWeb/DOM/Element.cpp | 9 +++++++++ Userland/Libraries/LibWeb/DOM/Element.h | 2 ++ .../Libraries/LibWeb/DOM/StyleElementUtils.cpp | 16 ++++++++-------- .../Libraries/LibWeb/DOM/StyleElementUtils.h | 6 +++--- .../Libraries/LibWeb/HTML/HTMLLinkElement.cpp | 5 +++-- 7 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/shadow-root-style-sheets.txt create mode 100644 Tests/LibWeb/Text/input/shadow-root-style-sheets.html diff --git a/Tests/LibWeb/Text/expected/shadow-root-style-sheets.txt b/Tests/LibWeb/Text/expected/shadow-root-style-sheets.txt new file mode 100644 index 0000000000..a254fbf7ca --- /dev/null +++ b/Tests/LibWeb/Text/expected/shadow-root-style-sheets.txt @@ -0,0 +1,2 @@ + shadow.styleSheets.length=1 +document.styleSheets.length=0 diff --git a/Tests/LibWeb/Text/input/shadow-root-style-sheets.html b/Tests/LibWeb/Text/input/shadow-root-style-sheets.html new file mode 100644 index 0000000000..7b1d361a24 --- /dev/null +++ b/Tests/LibWeb/Text/input/shadow-root-style-sheets.html @@ -0,0 +1,18 @@ + + + diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 2199d6c80c..8f32b12102 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -2380,4 +2380,13 @@ auto Element::ensure_custom_element_reaction_queue() -> CustomElementReactionQue return *m_custom_element_reaction_queue; } +CSS::StyleSheetList& Element::document_or_shadow_root_style_sheets() +{ + auto& root_node = root(); + if (is(root_node)) + return static_cast(root_node).style_sheets(); + + return document().style_sheets(); +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 884e6c7001..904de8fe33 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -183,6 +183,8 @@ public: CSS::CSSStyleDeclaration* style_for_bindings(); + CSS::StyleSheetList& document_or_shadow_root_style_sheets(); + WebIDL::ExceptionOr inner_html() const; WebIDL::ExceptionOr set_inner_html(StringView); diff --git a/Userland/Libraries/LibWeb/DOM/StyleElementUtils.cpp b/Userland/Libraries/LibWeb/DOM/StyleElementUtils.cpp index 377d9775f3..8e24e58fcd 100644 --- a/Userland/Libraries/LibWeb/DOM/StyleElementUtils.cpp +++ b/Userland/Libraries/LibWeb/DOM/StyleElementUtils.cpp @@ -33,7 +33,7 @@ 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) { - remove_a_css_style_sheet(style_element.document(), *m_associated_css_style_sheet); + remove_a_css_style_sheet(style_element.document_or_shadow_root_style_sheets(), *m_associated_css_style_sheet); // FIXME: This should probably be handled by StyleSheet::set_owner_node(). m_associated_css_style_sheet = nullptr; @@ -61,7 +61,7 @@ void StyleElementUtils::update_a_style_block(DOM::Element& style_element) // 6. Create a CSS style sheet with the following properties... create_a_css_style_sheet( - style_element.document(), + style_element.document_or_shadow_root_style_sheets(), "text/css"_string, &style_element, style_element.attribute(HTML::AttributeNames::media).value_or({}), @@ -77,10 +77,10 @@ void StyleElementUtils::update_a_style_block(DOM::Element& style_element) } // https://www.w3.org/TR/cssom/#remove-a-css-style-sheet -void StyleElementUtils::remove_a_css_style_sheet(DOM::Document& document, CSS::CSSStyleSheet& sheet) +void StyleElementUtils::remove_a_css_style_sheet(CSS::StyleSheetList& style_sheets, CSS::CSSStyleSheet& sheet) { // 1. Remove the CSS style sheet from the list of document or shadow root CSS style sheets. - document.style_sheets().remove_sheet(sheet); + style_sheets.remove_sheet(sheet); // 2. Set the CSS style sheet’s parent CSS style sheet, owner node and owner CSS rule to null. sheet.set_parent_css_style_sheet(nullptr); @@ -89,7 +89,7 @@ void StyleElementUtils::remove_a_css_style_sheet(DOM::Document& document, CSS::C } // https://www.w3.org/TR/cssom/#create-a-css-style-sheet -void StyleElementUtils::create_a_css_style_sheet(DOM::Document& document, String type, DOM::Element* owner_node, String media, String title, bool alternate, bool origin_clean, Optional location, CSS::CSSStyleSheet* parent_style_sheet, CSS::CSSRule* owner_rule, CSS::CSSStyleSheet& sheet) +void StyleElementUtils::create_a_css_style_sheet(CSS::StyleSheetList& style_sheets, String type, DOM::Element* owner_node, String media, String title, bool alternate, bool origin_clean, Optional location, CSS::CSSStyleSheet* parent_style_sheet, CSS::CSSRule* owner_rule, CSS::CSSStyleSheet& sheet) { // 1. Create a new CSS style sheet object and set its properties as specified. // FIXME: We receive `sheet` from the caller already. This is weird. @@ -105,14 +105,14 @@ void StyleElementUtils::create_a_css_style_sheet(DOM::Document& document, String sheet.set_location(move(location)); // 2. Then run the add a CSS style sheet steps for the newly created CSS style sheet. - add_a_css_style_sheet(document, sheet); + add_a_css_style_sheet(style_sheets, sheet); } // https://www.w3.org/TR/cssom/#add-a-css-style-sheet -void StyleElementUtils::add_a_css_style_sheet(DOM::Document& document, CSS::CSSStyleSheet& sheet) +void StyleElementUtils::add_a_css_style_sheet(CSS::StyleSheetList& style_sheets, CSS::CSSStyleSheet& sheet) { // 1. Add the CSS style sheet to the list of document or shadow root CSS style sheets at the appropriate location. The remainder of these steps deal with the disabled flag. - document.style_sheets().add_sheet(sheet); + style_sheets.add_sheet(sheet); // 2. If the disabled flag is set, then return. if (sheet.disabled()) diff --git a/Userland/Libraries/LibWeb/DOM/StyleElementUtils.h b/Userland/Libraries/LibWeb/DOM/StyleElementUtils.h index c2298a657b..cfa5771934 100644 --- a/Userland/Libraries/LibWeb/DOM/StyleElementUtils.h +++ b/Userland/Libraries/LibWeb/DOM/StyleElementUtils.h @@ -20,9 +20,9 @@ public: CSS::CSSStyleSheet const* sheet() const { return m_associated_css_style_sheet; } private: - void remove_a_css_style_sheet(DOM::Document& document, CSS::CSSStyleSheet& sheet); - void create_a_css_style_sheet(DOM::Document& document, String type, DOM::Element* owner_node, String media, String title, bool alternate, bool origin_clean, Optional location, CSS::CSSStyleSheet* parent_style_sheet, CSS::CSSRule* owner_rule, CSS::CSSStyleSheet& sheet); - void add_a_css_style_sheet(DOM::Document& document, CSS::CSSStyleSheet& sheet); + void remove_a_css_style_sheet(CSS::StyleSheetList&, CSS::CSSStyleSheet& sheet); + void create_a_css_style_sheet(CSS::StyleSheetList&, String type, DOM::Element* owner_node, String media, String title, bool alternate, bool origin_clean, Optional location, CSS::CSSStyleSheet* parent_style_sheet, CSS::CSSRule* owner_rule, CSS::CSSStyleSheet& sheet); + void add_a_css_style_sheet(CSS::StyleSheetList&, CSS::CSSStyleSheet& sheet); // https://www.w3.org/TR/cssom/#associated-css-style-sheet JS::GCPtr m_associated_css_style_sheet; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp index a199e2450b..5d1e03db36 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -112,7 +113,7 @@ void HTMLLinkElement::attribute_changed(FlyString const& name, Optional // FIXME: Handle alternate stylesheets properly if (m_relationship & Relationship::Stylesheet && !(m_relationship & Relationship::Alternate)) { if (name == HTML::AttributeNames::disabled && m_loaded_style_sheet) - document().style_sheets().remove_sheet(*m_loaded_style_sheet); + document_or_shadow_root_style_sheets().remove_sheet(*m_loaded_style_sheet); // https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet:fetch-and-process-the-linked-resource // The appropriate times to fetch and process this type of link are: @@ -311,7 +312,7 @@ void HTMLLinkElement::process_stylesheet_resource(bool success, Fetch::Infrastru // 3. If el has an associated CSS style sheet, remove the CSS style sheet. if (m_loaded_style_sheet) { - document().style_sheets().remove_sheet(*m_loaded_style_sheet); + document_or_shadow_root_style_sheets().remove_sheet(*m_loaded_style_sheet); m_loaded_style_sheet = nullptr; }