diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp index d3a29d41f9..b2055922d9 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -30,6 +29,12 @@ CSSStyleSheet::CSSStyleSheet(JS::Realm& realm, CSSRuleList& rules, MediaList& me for (auto& rule : *m_rules) rule->set_parent_style_sheet(this); + + recalculate_namespaces(); + + m_rules->on_change = [this]() { + recalculate_namespaces(); + }; } JS::ThrowCompletionOr CSSStyleSheet::initialize(JS::Realm& realm) @@ -138,17 +143,40 @@ void CSSStyleSheet::set_style_sheet_list(Badge, StyleSheetList* m_style_sheet_list = list; } -Optional CSSStyleSheet::namespace_filter() const +Optional CSSStyleSheet::default_namespace() const { - for (JS::NonnullGCPtr rule : *m_rules) { - if (rule->type() == CSSRule::Type::Namespace) { - auto& namespace_rule = verify_cast(*rule); - if (!namespace_rule.namespace_uri().is_empty() && namespace_rule.prefix().is_empty()) - return namespace_rule.namespace_uri().view(); - } - } + if (m_default_namespace_rule) + return m_default_namespace_rule->namespace_uri().view(); return {}; } +void CSSStyleSheet::recalculate_namespaces() +{ + for (JS::NonnullGCPtr rule : *m_rules) { + // "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: + 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; + + // FIXME: Store qualified namespace rules. + } +} + } diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h index c6d031f71e..cffc45f0b8 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -48,7 +49,7 @@ public: void set_style_sheet_list(Badge, StyleSheetList*); - Optional namespace_filter() const; + Optional default_namespace() const; private: CSSStyleSheet(JS::Realm&, CSSRuleList&, MediaList&, Optional location); @@ -56,7 +57,10 @@ private: virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; + void recalculate_namespaces(); + JS::GCPtr m_rules; + JS::GCPtr m_default_namespace_rule; JS::GCPtr m_style_sheet_list; JS::GCPtr m_owner_css_rule; diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index e951d292f4..221c363a2d 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -225,7 +225,7 @@ Vector StyleComputer::filter_namespace_rules(DOM::Element const& e Vector filtered_rules; for (auto const& rule : rules) { - auto namespace_uri = rule.sheet->namespace_filter(); + auto namespace_uri = rule.sheet->default_namespace(); if (namespace_uri.has_value()) { if (namespace_uri.value() == element.namespace_uri()) filtered_rules.append(rule);