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 <simon+git@skyrising.xyz>
This commit is contained in:
Aliaksandr Kalenik 2023-03-19 15:13:45 +01:00 committed by Andreas Kling
parent 8ce8697a66
commit c6e69d501f
Notes: sideshowbarker 2024-07-17 02:56:25 +09:00
7 changed files with 45 additions and 13 deletions

View file

@ -0,0 +1,2 @@
shadow.styleSheets.length=1
document.styleSheets.length=0

View file

@ -0,0 +1,18 @@
<script src="include.js"></script>
<my-custom-element></my-custom-element>
<script>
test(() => {
class MyCustomElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
const style = document.createElement('style');
shadow.appendChild(style);
println(`shadow.styleSheets.length=${shadow.styleSheets.length}`);
println(`document.styleSheets.length=${document.styleSheets.length}`);
}
}
customElements.define('my-custom-element', MyCustomElement);
});
</script>

View file

@ -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<DOM::ShadowRoot>(root_node))
return static_cast<DOM::ShadowRoot&>(root_node).style_sheets();
return document().style_sheets();
}
}

View file

@ -183,6 +183,8 @@ public:
CSS::CSSStyleDeclaration* style_for_bindings();
CSS::StyleSheetList& document_or_shadow_root_style_sheets();
WebIDL::ExceptionOr<String> inner_html() const;
WebIDL::ExceptionOr<void> set_inner_html(StringView);

View file

@ -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 sheets 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<String> 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<String> 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())

View file

@ -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<String> 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<String> 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<CSS::CSSStyleSheet> m_associated_css_style_sheet;

View file

@ -14,6 +14,7 @@
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/DOM/ShadowRoot.h>
#include <LibWeb/Fetch/Fetching/Fetching.h>
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
@ -112,7 +113,7 @@ void HTMLLinkElement::attribute_changed(FlyString const& name, Optional<String>
// 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;
}