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.
This commit is contained in:
Sam Atkins 2024-08-23 16:46:33 +01:00 committed by Sam Atkins
parent b00137df38
commit dd3b011f15
Notes: github-actions[bot] 2024-09-03 09:13:16 +00:00
2 changed files with 30 additions and 15 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2019-2022, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2024, Tim Ledbetter <timledbetter@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -7,6 +8,7 @@
#include <LibWeb/Bindings/CSSStyleSheetPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/CSSImportRule.h>
#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/CSS/StyleComputer.h>
@ -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<FlyString> 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<CSSRule> 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<CSSImportRule>(*rule));
break;
}
case CSSRule::Type::Namespace: {
auto& namespace_rule = verify_cast<CSSNamespaceRule>(*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<CSSNamespaceRule>(*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);
}
}

View file

@ -68,6 +68,8 @@ public:
Optional<FlyString> namespace_uri(StringView namespace_prefix) const;
Vector<JS::NonnullGCPtr<CSSImportRule>> const& import_rules() const { return m_import_rules; }
Optional<URL::URL> base_url() const { return m_base_url; }
void set_base_url(Optional<URL::URL> 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<CSSRuleList> m_rules;
JS::GCPtr<CSSNamespaceRule> m_default_namespace_rule;
HashMap<FlyString, JS::GCPtr<CSSNamespaceRule>> m_namespace_rules;
Vector<JS::NonnullGCPtr<CSSImportRule>> m_import_rules;
JS::GCPtr<StyleSheetList> m_style_sheet_list;
JS::GCPtr<CSSRule> m_owner_css_rule;