script/dom/css/
cssgroupingrule.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
7use servo_arc::Arc;
8use style::shared_lock::{Locked, SharedRwLock, SharedRwLockReadGuard};
9use style::stylesheets::{CssRuleType, CssRuleTypes, 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;
23use crate::script_runtime::CanGc;
24
25#[dom_struct]
26pub(crate) struct CSSGroupingRule {
27 css_rule: CSSRule,
28 rule_list: MutNullableDom<CSSRuleList>,
29}
30
31impl CSSGroupingRule {
32 pub(crate) fn new_inherited(parent_stylesheet: &CSSStyleSheet) -> CSSGroupingRule {
33 CSSGroupingRule {
34 css_rule: CSSRule::new_inherited(parent_stylesheet),
35 rule_list: MutNullableDom::new(None),
36 }
37 }
38
39 fn rulelist(&self, cx: &mut JSContext) -> DomRoot<CSSRuleList> {
40 let parent_stylesheet = self.upcast::<CSSRule>().parent_stylesheet();
41 self.rule_list.or_init(|| {
42 let rules = if let Some(rule) = self.downcast::<CSSConditionRule>() {
43 rule.clone_rules()
44 } else if let Some(rule) = self.downcast::<CSSLayerBlockRule>() {
45 rule.clone_rules()
46 } else if let Some(rule) = self.downcast::<CSSStyleRule>() {
47 rule.ensure_rules()
48 } else {
49 unreachable!()
50 };
51 CSSRuleList::new(
52 self.global().as_window(),
53 parent_stylesheet,
54 RulesSource::Rules(rules),
55 CanGc::from_cx(cx),
56 )
57 })
58 }
59
60 pub(crate) fn parent_stylesheet(&self) -> &CSSStyleSheet {
61 self.css_rule.parent_stylesheet()
62 }
63
64 pub(crate) fn shared_lock(&self) -> &SharedRwLock {
65 self.css_rule.shared_lock()
66 }
67
68 pub(crate) fn update_rules(
69 &self,
70 rules: &Arc<Locked<CssRules>>,
71 guard: &SharedRwLockReadGuard,
72 ) {
73 if let Some(rulelist) = self.rule_list.get() {
74 rulelist.update_rules(RulesSource::Rules(rules.clone()), guard);
75 }
76 }
77}
78
79impl CSSGroupingRuleMethods<crate::DomTypeHolder> for CSSGroupingRule {
80 fn CssRules(&self, cx: &mut JSContext) -> DomRoot<CSSRuleList> {
82 self.rulelist(cx)
84 }
85
86 fn InsertRule(&self, cx: &mut JSContext, rule: DOMString, index: u32) -> Fallible<u32> {
88 let rule_type = self.css_rule.as_specific().ty();
90 let containing_rule_types = CssRuleTypes::from(rule_type);
91 let parse_relative_rule_type = match rule_type {
92 CssRuleType::Style | CssRuleType::Scope => Some(rule_type),
93 _ => None,
94 };
95 self.rulelist(cx).insert_rule(
96 &rule,
97 index,
98 containing_rule_types,
99 parse_relative_rule_type,
100 CanGc::from_cx(cx),
101 )
102 }
103
104 fn DeleteRule(&self, cx: &mut JSContext, index: u32) -> ErrorResult {
106 self.rulelist(cx).remove_rule(index)
107 }
108}