From dd3b011f159fdf46b09341bcec4c73e28bb53471 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 23 Aug 2024 16:46:33 +0100 Subject: [PATCH] LibWeb: Keep track of each CSSStyleSheet's CSSImportRules This will be used to gather up a list of all loaded style sheets for the inspector. --- .../Libraries/LibWeb/CSS/CSSStyleSheet.cpp | 40 ++++++++++++------- Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h | 5 ++- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp index 59a58565a29..70a6f386583 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2019-2022, Andreas Kling + * Copyright (c) 2022-2024, Sam Atkins * Copyright (c) 2024, Tim Ledbetter * * SPDX-License-Identifier: BSD-2-Clause @@ -7,6 +8,7 @@ #include #include +#include #include #include #include @@ -101,10 +103,10 @@ CSSStyleSheet::CSSStyleSheet(JS::Realm& realm, CSSRuleList& rules, MediaList& me for (auto& rule : *m_rules) rule->set_parent_style_sheet(this); - recalculate_namespaces(); + recalculate_rule_caches(); m_rules->on_change = [this]() { - recalculate_namespaces(); + recalculate_rule_caches(); }; } @@ -123,6 +125,7 @@ void CSSStyleSheet::visit_edges(Cell::Visitor& visitor) visitor.visit(m_default_namespace_rule); visitor.visit(m_constructor_document); visitor.visit(m_namespace_rules); + visitor.visit(m_import_rules); } // https://www.w3.org/TR/cssom/#dom-cssstylesheet-insertrule @@ -340,34 +343,43 @@ Optional CSSStyleSheet::namespace_uri(StringView namespace_prefix) co }); } -void CSSStyleSheet::recalculate_namespaces() +void CSSStyleSheet::recalculate_rule_caches() { m_default_namespace_rule = nullptr; m_namespace_rules.clear(); + m_import_rules.clear(); - for (JS::NonnullGCPtr rule : *m_rules) { + for (auto const& rule : *m_rules) { + // "Any @import rules must precede all other valid at-rules and style rules in a style sheet + // (ignoring @charset and @layer statement rules) and must not have any other valid at-rules + // or style rules between it and previous @import rules, or else the @import rule is invalid." + // https://drafts.csswg.org/css-cascade-5/#at-import + // // "Any @namespace rules must follow all @charset and @import rules and precede all other // non-ignored at-rules and style rules in a style sheet. // ... // A syntactically invalid @namespace rule (whether malformed or misplaced) must be ignored." // https://drafts.csswg.org/css-namespaces/#syntax switch (rule->type()) { - case CSSRule::Type::Import: - continue; - - case CSSRule::Type::Namespace: + case CSSRule::Type::Import: { + // @import rules must appear before @namespace rules, so skip this if we've seen @namespace. + if (!m_namespace_rules.is_empty()) + continue; + m_import_rules.append(verify_cast(*rule)); break; + } + case CSSRule::Type::Namespace: { + auto& namespace_rule = verify_cast(*rule); + if (!namespace_rule.namespace_uri().is_empty() && namespace_rule.prefix().is_empty()) + m_default_namespace_rule = namespace_rule; + m_namespace_rules.set(namespace_rule.prefix(), namespace_rule); + break; + } default: // Any other types mean that further @namespace rules are invalid, so we can stop here. return; } - - auto& namespace_rule = verify_cast(*rule); - if (!namespace_rule.namespace_uri().is_empty() && namespace_rule.prefix().is_empty()) - m_default_namespace_rule = namespace_rule; - - m_namespace_rules.set(namespace_rule.prefix(), namespace_rule); } } diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h index 1ea007dcebf..90383b9834e 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h @@ -68,6 +68,8 @@ public: Optional namespace_uri(StringView namespace_prefix) const; + Vector> const& import_rules() const { return m_import_rules; } + Optional base_url() const { return m_base_url; } void set_base_url(Optional base_url) { m_base_url = move(base_url); } @@ -87,7 +89,7 @@ private: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; - void recalculate_namespaces(); + void recalculate_rule_caches(); void set_constructed(bool constructed) { m_constructed = constructed; } void set_disallow_modification(bool disallow_modification) { m_disallow_modification = disallow_modification; } @@ -97,6 +99,7 @@ private: JS::GCPtr m_rules; JS::GCPtr m_default_namespace_rule; HashMap> m_namespace_rules; + Vector> m_import_rules; JS::GCPtr m_style_sheet_list; JS::GCPtr m_owner_css_rule;