diff --git a/Tests/LibWeb/Text/expected/css/style-declaration-parent-rule.txt b/Tests/LibWeb/Text/expected/css/style-declaration-parent-rule.txt
new file mode 100644
index 00000000000..4bce08e27ca
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/css/style-declaration-parent-rule.txt
@@ -0,0 +1,4 @@
+spanRule: [object CSSStyleRule] ~ span { color: rgb(128, 0, 128); }
+spanRule.style: [object CSSStyleDeclaration] ~ span { color: rgb(128, 0, 128); }
+spanRule.style.parentRule: [object CSSStyleRule] ~ span { color: rgb(128, 0, 128); }
+spanRule.style.parentRule === spanRule: true
diff --git a/Tests/LibWeb/Text/input/css/style-declaration-parent-rule.html b/Tests/LibWeb/Text/input/css/style-declaration-parent-rule.html
new file mode 100644
index 00000000000..36c9bdef673
--- /dev/null
+++ b/Tests/LibWeb/Text/input/css/style-declaration-parent-rule.html
@@ -0,0 +1,15 @@
+
+
+
diff --git a/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.cpp
index 31583fe7003..fb0f666a770 100644
--- a/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.cpp
+++ b/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.cpp
@@ -13,11 +13,19 @@ namespace Web::CSS {
JS_DEFINE_ALLOCATOR(CSSKeyframeRule);
-JS::NonnullGCPtr CSSKeyframeRule::create(JS::Realm& realm, CSS::Percentage key, Web::CSS::CSSStyleDeclaration& declarations)
+JS::NonnullGCPtr CSSKeyframeRule::create(JS::Realm& realm, CSS::Percentage key, Web::CSS::PropertyOwningCSSStyleDeclaration& declarations)
{
return realm.heap().allocate(realm, realm, key, declarations);
}
+CSSKeyframeRule::CSSKeyframeRule(JS::Realm& realm, CSS::Percentage key, PropertyOwningCSSStyleDeclaration& declarations)
+ : CSSRule(realm)
+ , m_key(key)
+ , m_declarations(declarations)
+{
+ m_declarations->set_parent_rule(*this);
+}
+
void CSSKeyframeRule::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
diff --git a/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h b/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h
index 90017913b20..bac207ead9d 100644
--- a/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h
+++ b/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h
@@ -21,7 +21,7 @@ class CSSKeyframeRule final : public CSSRule {
JS_DECLARE_ALLOCATOR(CSSKeyframeRule);
public:
- static JS::NonnullGCPtr create(JS::Realm&, CSS::Percentage key, CSSStyleDeclaration&);
+ static JS::NonnullGCPtr create(JS::Realm&, CSS::Percentage key, PropertyOwningCSSStyleDeclaration&);
virtual ~CSSKeyframeRule() = default;
@@ -41,19 +41,14 @@ public:
}
private:
- CSSKeyframeRule(JS::Realm& realm, CSS::Percentage key, CSSStyleDeclaration& declarations)
- : CSSRule(realm)
- , m_key(key)
- , m_declarations(declarations)
- {
- }
+ CSSKeyframeRule(JS::Realm&, CSS::Percentage, PropertyOwningCSSStyleDeclaration&);
virtual void visit_edges(Visitor&) override;
virtual void initialize(JS::Realm&) override;
virtual String serialized() const override;
CSS::Percentage m_key;
- JS::NonnullGCPtr m_declarations;
+ JS::NonnullGCPtr m_declarations;
};
template<>
diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp
index a05ec01a000..8529d76c5f3 100644
--- a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp
+++ b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp
@@ -31,6 +31,11 @@ void CSSStyleDeclaration::initialize(JS::Realm& realm)
WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSStyleDeclaration);
}
+JS::GCPtr CSSStyleDeclaration::parent_rule() const
+{
+ return nullptr;
+}
+
JS::NonnullGCPtr PropertyOwningCSSStyleDeclaration::create(JS::Realm& realm, Vector properties, HashMap custom_properties)
{
return realm.heap().allocate(realm, realm, move(properties), move(custom_properties));
@@ -46,6 +51,7 @@ PropertyOwningCSSStyleDeclaration::PropertyOwningCSSStyleDeclaration(JS::Realm&
void PropertyOwningCSSStyleDeclaration::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
+ visitor.visit(m_parent_rule);
for (auto& property : m_properties) {
if (property.value->is_image())
property.value->as_image().visit_edges(visitor);
@@ -482,4 +488,14 @@ WebIDL::ExceptionOr ElementInlineCSSStyleDeclaration::set_css_text(StringV
return {};
}
+JS::GCPtr PropertyOwningCSSStyleDeclaration::parent_rule() const
+{
+ return m_parent_rule;
+}
+
+void PropertyOwningCSSStyleDeclaration::set_parent_rule(JS::NonnullGCPtr rule)
+{
+ m_parent_rule = rule;
+}
+
}
diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h
index 0eee4969e86..79a81877889 100644
--- a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h
+++ b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h
@@ -45,6 +45,8 @@ public:
virtual JS::ThrowCompletionOr internal_get(JS::PropertyKey const&, JS::Value receiver, JS::CacheablePropertyMetadata*, PropertyLookupPhase) const override;
virtual JS::ThrowCompletionOr internal_set(JS::PropertyKey const&, JS::Value value, JS::Value receiver, JS::CacheablePropertyMetadata*) override;
+ virtual JS::GCPtr parent_rule() const;
+
protected:
explicit CSSStyleDeclaration(JS::Realm&);
};
@@ -77,6 +79,9 @@ public:
virtual String serialized() const final override;
virtual WebIDL::ExceptionOr set_css_text(StringView) override;
+ virtual JS::GCPtr parent_rule() const override;
+ void set_parent_rule(JS::NonnullGCPtr);
+
protected:
PropertyOwningCSSStyleDeclaration(JS::Realm&, Vector, HashMap);
@@ -90,6 +95,7 @@ private:
virtual void visit_edges(Cell::Visitor&) override;
+ JS::GCPtr m_parent_rule;
Vector m_properties;
HashMap m_custom_properties;
};
diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.idl b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.idl
index 2501475d735..9440fbbfa3c 100644
--- a/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.idl
+++ b/Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.idl
@@ -13,7 +13,7 @@ interface CSSStyleDeclaration {
[CEReactions] undefined setProperty(CSSOMString property, [LegacyNullToEmptyString] CSSOMString value, optional [LegacyNullToEmptyString] CSSOMString priority = "");
[CEReactions] CSSOMString removeProperty(CSSOMString property);
- [FIXME] readonly attribute CSSRule? parentRule;
+ readonly attribute CSSRule? parentRule;
[FIXME, CEReactions, LegacyNullToEmptyString] attribute CSSOMString cssFloat;
};
diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp
index 97ce852febd..87b0ca12eb7 100644
--- a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp
+++ b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp
@@ -25,6 +25,7 @@ CSSStyleRule::CSSStyleRule(JS::Realm& realm, Vector>&& s
, m_selectors(move(selectors))
, m_declaration(declaration)
{
+ m_declaration->set_parent_rule(*this);
}
void CSSStyleRule::initialize(JS::Realm& realm)