diff --git a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp index 66eb4e1dae..725a2f09d6 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2021-2022, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -12,18 +12,21 @@ namespace Web::CSS { CSSGroupingRule::CSSGroupingRule(NonnullRefPtrVector&& rules) : m_rules(CSSRuleList::create(move(rules))) { + for (auto& rule : *m_rules) + rule.set_parent_rule(this); } -size_t CSSGroupingRule::insert_rule(StringView, size_t) +DOM::ExceptionOr CSSGroupingRule::insert_rule(StringView rule, u32 index) { - // https://www.w3.org/TR/cssom-1/#insert-a-css-rule - TODO(); + TRY(m_rules->insert_a_css_rule(rule, index)); + // NOTE: The spec doesn't say where to set the parent rule, so we'll do it here. + m_rules->item(index)->set_parent_rule(this); + return index; } -void CSSGroupingRule::delete_rule(size_t) +DOM::ExceptionOr CSSGroupingRule::delete_rule(u32 index) { - // https://www.w3.org/TR/cssom-1/#remove-a-css-rule - TODO(); + return m_rules->remove_a_css_rule(index); } void CSSGroupingRule::for_each_effective_style_rule(Function const& callback) const @@ -31,4 +34,11 @@ void CSSGroupingRule::for_each_effective_style_rule(Functionfor_each_effective_style_rule(callback); } +void CSSGroupingRule::set_parent_style_sheet(CSSStyleSheet* parent_style_sheet) +{ + CSSRule::set_parent_style_sheet(parent_style_sheet); + for (auto& rule : *m_rules) + rule.set_parent_style_sheet(parent_style_sheet); +} + } diff --git a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h index 4d28f42ee7..0f533b6c50 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h @@ -26,11 +26,13 @@ public: CSSRuleList const& css_rules() const { return m_rules; } CSSRuleList& css_rules() { return m_rules; } NonnullRefPtr css_rules_for_bindings() { return m_rules; } - size_t insert_rule(StringView rule, size_t index = 0); - void delete_rule(size_t index); + DOM::ExceptionOr insert_rule(StringView rule, u32 index = 0); + DOM::ExceptionOr delete_rule(u32 index); virtual void for_each_effective_style_rule(Function const& callback) const; + virtual void set_parent_style_sheet(CSSStyleSheet*) override; + protected: explicit CSSGroupingRule(NonnullRefPtrVector&&); diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSRule.cpp index e6a2aac960..aeeec6b7fb 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.cpp @@ -1,10 +1,12 @@ /* * Copyright (c) 2021, the SerenityOS developers. + * Copyright (c) 2022, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ #include +#include namespace Web::CSS { @@ -21,4 +23,20 @@ void CSSRule::set_css_text(StringView) // On setting the cssText attribute must do nothing. } +void CSSRule::set_parent_rule(CSSRule* parent_rule) +{ + if (parent_rule) + m_parent_rule = parent_rule->make_weak_ptr(); + else + m_parent_rule = nullptr; +} + +void CSSRule::set_parent_style_sheet(CSSStyleSheet* parent_style_sheet) +{ + if (parent_style_sheet) + m_parent_style_sheet = parent_style_sheet->make_weak_ptr(); + else + m_parent_style_sheet = nullptr; +} + } diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.h b/Userland/Libraries/LibWeb/CSS/CSSRule.h index ece51f8f14..986dc3a6e6 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.h @@ -39,11 +39,20 @@ public: String css_text() const; void set_css_text(StringView); + CSSRule* parent_rule() { return m_parent_rule; } + void set_parent_rule(CSSRule*); + + CSSStyleSheet* parent_style_sheet() { return m_parent_style_sheet; } + virtual void set_parent_style_sheet(CSSStyleSheet*); + template bool fast_is() const = delete; protected: virtual String serialized() const = 0; + + WeakPtr m_parent_rule; + WeakPtr m_parent_style_sheet; }; } diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.idl b/Userland/Libraries/LibWeb/CSS/CSSRule.idl index b2d416c6f8..bd40b41bd6 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.idl @@ -1,7 +1,13 @@ +#import + +[Exposed=Window] interface CSSRule { attribute CSSOMString cssText; + readonly attribute CSSRule? parentRule; + readonly attribute CSSStyleSheet? parentStyleSheet; + readonly attribute unsigned short type; const unsigned short STYLE_RULE = 1; diff --git a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp index 1a04ef0311..d92f9d72eb 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp @@ -80,7 +80,9 @@ DOM::ExceptionOr CSSRuleList::remove_a_css_rule(u32 index) // 5. Remove rule old rule from list at the zero-indexed position index. m_rules.remove(index); - // FIXME: 6. Set old rule’s parent CSS rule and parent CSS style sheet to null. + // 6. Set old rule’s parent CSS rule and parent CSS style sheet to null. + old_rule.set_parent_rule(nullptr); + old_rule.set_parent_style_sheet(nullptr); return {}; } diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp index f3ce3b9135..cecdb9ebe5 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp @@ -17,6 +17,9 @@ CSSStyleSheet::CSSStyleSheet(NonnullRefPtrVector rules, Optionalto_string()); + + for (auto& rule : *m_rules) + rule.set_parent_style_sheet(this); } // https://www.w3.org/TR/cssom/#dom-cssstylesheet-insertrule @@ -36,9 +39,13 @@ DOM::ExceptionOr CSSStyleSheet::insert_rule(StringView rule, unsigned // FIXME: 5. If parsed rule is an @import rule, and the constructed flag is set, throw a SyntaxError DOMException. // 6. Return the result of invoking insert a CSS rule rule in the CSS rules at index. - auto result = m_rules->insert_a_css_rule(parsed_rule.release_nonnull(), index); + auto parsed_rule_nonnull = parsed_rule.release_nonnull(); + auto result = m_rules->insert_a_css_rule(parsed_rule_nonnull, index); if (!result.is_exception()) { + // NOTE: The spec doesn't say where to set the parent style sheet, so we'll do it here. + parsed_rule_nonnull->set_parent_style_sheet(this); + if (m_style_sheet_list) { m_style_sheet_list->document().style_computer().invalidate_rule_cache(); m_style_sheet_list->document().invalidate_style();