LibWeb/CSS: Stop assuming CSSNestedDeclarations's parent is CSSStyleRule

This will no longer be true once we implement at-rules nested inside
style rules, for example:

```css
.foo {
  color: yellow;

  @media (min-width: 800px) {
    color: orange;
  }
}
```
This commit is contained in:
Sam Atkins 2024-11-06 17:43:30 +00:00 committed by Andreas Kling
parent 0b23dddb4b
commit ce947ff983
Notes: github-actions[bot] 2024-11-07 14:12:42 +00:00
3 changed files with 31 additions and 3 deletions

View file

@ -7,6 +7,7 @@
#include "CSSNestedDeclarations.h" #include "CSSNestedDeclarations.h"
#include <LibWeb/Bindings/CSSNestedDeclarationsPrototype.h> #include <LibWeb/Bindings/CSSNestedDeclarationsPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h> #include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/CSSStyleRule.h>
namespace Web::CSS { namespace Web::CSS {
@ -34,6 +35,7 @@ void CSSNestedDeclarations::visit_edges(Cell::Visitor& visitor)
{ {
Base::visit_edges(visitor); Base::visit_edges(visitor);
visitor.visit(m_declaration); visitor.visit(m_declaration);
visitor.visit(m_parent_style_rule);
} }
CSSStyleDeclaration* CSSNestedDeclarations::style() CSSStyleDeclaration* CSSNestedDeclarations::style()
@ -41,6 +43,22 @@ CSSStyleDeclaration* CSSNestedDeclarations::style()
return m_declaration; return m_declaration;
} }
CSSStyleRule const& CSSNestedDeclarations::parent_style_rule() const
{
if (m_parent_style_rule)
return *m_parent_style_rule;
for (auto* parent = parent_rule(); parent; parent = parent->parent_rule()) {
if (is<CSSStyleRule>(parent)) {
m_parent_style_rule = static_cast<CSSStyleRule const*>(parent);
return *m_parent_style_rule;
}
}
dbgln("CSSNestedDeclarations has no parent style rule!");
VERIFY_NOT_REACHED();
}
String CSSNestedDeclarations::serialized() const String CSSNestedDeclarations::serialized() const
{ {
// NOTE: There's no proper spec for this yet, only this note: // NOTE: There's no proper spec for this yet, only this note:
@ -50,4 +68,10 @@ String CSSNestedDeclarations::serialized() const
return m_declaration->serialized(); return m_declaration->serialized();
} }
void CSSNestedDeclarations::clear_caches()
{
Base::clear_caches();
m_parent_style_rule = nullptr;
}
} }

View file

@ -23,14 +23,18 @@ public:
CSSStyleDeclaration* style(); CSSStyleDeclaration* style();
CSSStyleRule const& parent_style_rule() const;
private: private:
CSSNestedDeclarations(JS::Realm&, PropertyOwningCSSStyleDeclaration&); CSSNestedDeclarations(JS::Realm&, PropertyOwningCSSStyleDeclaration&);
virtual void initialize(JS::Realm&) override; virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override; virtual void visit_edges(Cell::Visitor&) override;
virtual String serialized() const override; virtual String serialized() const override;
virtual void clear_caches() override;
JS::NonnullGCPtr<PropertyOwningCSSStyleDeclaration> m_declaration; JS::NonnullGCPtr<PropertyOwningCSSStyleDeclaration> m_declaration;
JS::GCPtr<CSSStyleRule const> mutable m_parent_style_rule;
}; };
template<> template<>

View file

@ -111,7 +111,7 @@ SelectorList const& MatchingRule::absolutized_selectors() const
if (rule->type() == CSSRule::Type::Style) if (rule->type() == CSSRule::Type::Style)
return static_cast<CSSStyleRule const&>(*rule).absolutized_selectors(); return static_cast<CSSStyleRule const&>(*rule).absolutized_selectors();
if (rule->type() == CSSRule::Type::NestedDeclarations) if (rule->type() == CSSRule::Type::NestedDeclarations)
return static_cast<CSSStyleRule const&>(*rule->parent_rule()).absolutized_selectors(); return static_cast<CSSNestedDeclarations const&>(*rule).parent_style_rule().absolutized_selectors();
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
@ -120,7 +120,7 @@ FlyString const& MatchingRule::qualified_layer_name() const
if (rule->type() == CSSRule::Type::Style) if (rule->type() == CSSRule::Type::Style)
return static_cast<CSSStyleRule const&>(*rule).qualified_layer_name(); return static_cast<CSSStyleRule const&>(*rule).qualified_layer_name();
if (rule->type() == CSSRule::Type::NestedDeclarations) if (rule->type() == CSSRule::Type::NestedDeclarations)
return static_cast<CSSStyleRule const&>(*rule->parent_rule()).qualified_layer_name(); return static_cast<CSSNestedDeclarations const&>(*rule).parent_style_rule().qualified_layer_name();
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
@ -2462,7 +2462,7 @@ NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_casca
if (rule.type() == CSSRule::Type::Style) if (rule.type() == CSSRule::Type::Style)
return static_cast<CSSStyleRule const&>(rule).absolutized_selectors(); return static_cast<CSSStyleRule const&>(rule).absolutized_selectors();
if (rule.type() == CSSRule::Type::NestedDeclarations) if (rule.type() == CSSRule::Type::NestedDeclarations)
return static_cast<CSSStyleRule const&>(*rule.parent_rule()).absolutized_selectors(); return static_cast<CSSNestedDeclarations const&>(rule).parent_style_rule().absolutized_selectors();
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
}(); }();
for (CSS::Selector const& selector : absolutized_selectors) { for (CSS::Selector const& selector : absolutized_selectors) {