Skip to main content

script/dom/css/
cssgroupingrule.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::context::JSContext;
7use servo_arc::Arc;
8use style::shared_lock::{Locked, SharedRwLock, SharedRwLockReadGuard};
9use style::stylesheets::CssRules;
10
11use super::cssconditionrule::CSSConditionRule;
12use super::csslayerblockrule::CSSLayerBlockRule;
13use super::cssrule::CSSRule;
14use super::cssrulelist::{CSSRuleList, RulesSource};
15use super::cssstylerule::CSSStyleRule;
16use super::cssstylesheet::CSSStyleSheet;
17use crate::dom::bindings::codegen::Bindings::CSSGroupingRuleBinding::CSSGroupingRuleMethods;
18use crate::dom::bindings::error::{ErrorResult, Fallible};
19use crate::dom::bindings::inheritance::Castable;
20use crate::dom::bindings::reflector::DomGlobal;
21use crate::dom::bindings::root::{DomRoot, MutNullableDom};
22use crate::dom::bindings::str::DOMString;
23
24#[dom_struct]
25pub(crate) struct CSSGroupingRule {
26    css_rule: CSSRule,
27    rule_list: MutNullableDom<CSSRuleList>,
28}
29
30impl CSSGroupingRule {
31    pub(crate) fn new_inherited(
32        parent_rule: Option<&CSSGroupingRule>,
33        parent_stylesheet: &CSSStyleSheet,
34    ) -> CSSGroupingRule {
35        CSSGroupingRule {
36            css_rule: CSSRule::new_inherited(parent_rule, parent_stylesheet),
37            rule_list: MutNullableDom::new(None),
38        }
39    }
40
41    fn rulelist(&self, cx: &mut JSContext) -> DomRoot<CSSRuleList> {
42        let parent_stylesheet = self.upcast::<CSSRule>().parent_stylesheet();
43        self.rule_list.or_init(|| {
44            let rules = if let Some(rule) = self.downcast::<CSSConditionRule>() {
45                rule.clone_rules()
46            } else if let Some(rule) = self.downcast::<CSSLayerBlockRule>() {
47                rule.clone_rules()
48            } else if let Some(rule) = self.downcast::<CSSStyleRule>() {
49                rule.ensure_rules()
50            } else {
51                unreachable!()
52            };
53            CSSRuleList::new(
54                cx,
55                self.global().as_window(),
56                Some(self),
57                parent_stylesheet,
58                RulesSource::Rules(rules),
59            )
60        })
61    }
62
63    pub(crate) fn parent_stylesheet(&self) -> &CSSStyleSheet {
64        self.css_rule.parent_stylesheet()
65    }
66
67    pub(crate) fn shared_lock(&self) -> &SharedRwLock {
68        self.css_rule.shared_lock()
69    }
70
71    pub(crate) fn update_rules(
72        &self,
73        rules: &Arc<Locked<CssRules>>,
74        guard: &SharedRwLockReadGuard,
75    ) {
76        if let Some(rulelist) = self.rule_list.get() {
77            rulelist.update_rules(RulesSource::Rules(rules.clone()), guard);
78        }
79    }
80}
81
82impl CSSGroupingRuleMethods<crate::DomTypeHolder> for CSSGroupingRule {
83    /// <https://drafts.csswg.org/cssom/#dom-cssgroupingrule-cssrules>
84    fn CssRules(&self, cx: &mut JSContext) -> DomRoot<CSSRuleList> {
85        // XXXManishearth check origin clean flag
86        self.rulelist(cx)
87    }
88
89    /// <https://drafts.csswg.org/cssom/#dom-cssgroupingrule-insertrule>
90    fn InsertRule(&self, cx: &mut JSContext, rule: DOMString, index: u32) -> Fallible<u32> {
91        self.rulelist(cx).insert_rule(cx, &rule, index)
92    }
93
94    /// <https://drafts.csswg.org/cssom/#dom-cssgroupingrule-deleterule>
95    fn DeleteRule(&self, cx: &mut JSContext, index: u32) -> ErrorResult {
96        self.rulelist(cx).remove_rule(cx, index)
97    }
98}