From 9651969708bf46feb5d53bdcd9925d65a549fcb6 Mon Sep 17 00:00:00 2001 From: Callum Law Date: Wed, 15 Oct 2025 23:45:38 +1300 Subject: [PATCH] LibWeb: Propagate CSSStyleSheet owning documents and shadow roots Previously these were only stored on the root style sheet and were accessed by imported stylesheets via their owner rule. Propagating these to imported style sheets allows us to more easily know when they change for said imported style sheets. --- Libraries/LibWeb/CSS/CSSImportRule.cpp | 16 ++++++++++++++-- Libraries/LibWeb/CSS/CSSStyleSheet.cpp | 15 ++++++++++----- Libraries/LibWeb/CSS/CSSStyleSheet.h | 1 + 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Libraries/LibWeb/CSS/CSSImportRule.cpp b/Libraries/LibWeb/CSS/CSSImportRule.cpp index 61b2f541a1a..def42517e11 100644 --- a/Libraries/LibWeb/CSS/CSSImportRule.cpp +++ b/Libraries/LibWeb/CSS/CSSImportRule.cpp @@ -53,6 +53,12 @@ void CSSImportRule::visit_edges(Cell::Visitor& visitor) void CSSImportRule::set_parent_style_sheet(CSSStyleSheet* parent_style_sheet) { Base::set_parent_style_sheet(parent_style_sheet); + + if (m_style_sheet && parent_style_sheet) { + for (auto owning_document_or_shadow_root : parent_style_sheet->owning_documents_or_shadow_roots()) + m_style_sheet->add_owning_document_or_shadow_root(*owning_document_or_shadow_root); + } + // Crude detection of whether we're already fetching. if (m_style_sheet || m_document_load_event_delayer.has_value()) return; @@ -174,9 +180,15 @@ void CSSImportRule::set_style_sheet(GC::Ref style_sheet) { m_style_sheet = style_sheet; m_style_sheet->set_owner_css_rule(this); - m_document->style_computer().invalidate_rule_cache(); + m_document->style_computer().load_fonts_from_sheet(*m_style_sheet); - m_document->invalidate_style(DOM::StyleInvalidationReason::CSSImportRule); + + if (m_parent_style_sheet) { + for (auto owning_document_or_shadow_root : m_parent_style_sheet->owning_documents_or_shadow_roots()) + m_style_sheet->add_owning_document_or_shadow_root(*owning_document_or_shadow_root); + } + + m_style_sheet->invalidate_owners(DOM::StyleInvalidationReason::CSSImportRule); } // https://drafts.csswg.org/cssom/#dom-cssimportrule-media diff --git a/Libraries/LibWeb/CSS/CSSStyleSheet.cpp b/Libraries/LibWeb/CSS/CSSStyleSheet.cpp index 577565ced71..8f40d6e6453 100644 --- a/Libraries/LibWeb/CSS/CSSStyleSheet.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleSheet.cpp @@ -321,11 +321,21 @@ void CSSStyleSheet::add_owning_document_or_shadow_root(DOM::Node& document_or_sh { VERIFY(document_or_shadow_root.is_document() || document_or_shadow_root.is_shadow_root()); m_owning_documents_or_shadow_roots.set(document_or_shadow_root); + + for (auto const& import_rule : m_import_rules) { + if (import_rule->loaded_style_sheet()) + import_rule->loaded_style_sheet()->add_owning_document_or_shadow_root(document_or_shadow_root); + } } void CSSStyleSheet::remove_owning_document_or_shadow_root(DOM::Node& document_or_shadow_root) { m_owning_documents_or_shadow_roots.remove(document_or_shadow_root); + + for (auto const& import_rule : m_import_rules) { + if (import_rule->loaded_style_sheet()) + import_rule->loaded_style_sheet()->remove_owning_document_or_shadow_root(document_or_shadow_root); + } } void CSSStyleSheet::invalidate_owners(DOM::StyleInvalidationReason reason) @@ -342,11 +352,6 @@ GC::Ptr CSSStyleSheet::owning_document() const if (!m_owning_documents_or_shadow_roots.is_empty()) return (*m_owning_documents_or_shadow_roots.begin())->document(); - if (m_owner_css_rule && m_owner_css_rule->parent_style_sheet()) { - if (auto document = m_owner_css_rule->parent_style_sheet()->owning_document()) - return document; - } - if (auto* element = const_cast(this)->owner_node()) return element->document(); diff --git a/Libraries/LibWeb/CSS/CSSStyleSheet.h b/Libraries/LibWeb/CSS/CSSStyleSheet.h index da5e7e55ed2..638b3896984 100644 --- a/Libraries/LibWeb/CSS/CSSStyleSheet.h +++ b/Libraries/LibWeb/CSS/CSSStyleSheet.h @@ -66,6 +66,7 @@ public: bool evaluate_media_queries(DOM::Document const&); void for_each_effective_keyframes_at_rule(Function const& callback) const; + HashTable> owning_documents_or_shadow_roots() const { return m_owning_documents_or_shadow_roots; } void add_owning_document_or_shadow_root(DOM::Node& document_or_shadow_root); void remove_owning_document_or_shadow_root(DOM::Node& document_or_shadow_root); void invalidate_owners(DOM::StyleInvalidationReason);