1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use script_bindings::reflector::Reflector;
10use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard};
11use style::stylesheets::{CssRule as StyleCssRule, CssRuleType};
12
13use super::cssfontfacerule::CSSFontFaceRule;
14use super::cssfontfeaturevaluesrule::CSSFontFeatureValuesRule;
15use super::cssimportrule::CSSImportRule;
16use super::csskeyframerule::CSSKeyframeRule;
17use super::csskeyframesrule::CSSKeyframesRule;
18use super::csslayerblockrule::CSSLayerBlockRule;
19use super::csslayerstatementrule::CSSLayerStatementRule;
20use super::cssmediarule::CSSMediaRule;
21use super::cssnamespacerule::CSSNamespaceRule;
22use super::cssnesteddeclarations::CSSNestedDeclarations;
23use super::csspropertyrule::CSSPropertyRule;
24use super::cssstylerule::CSSStyleRule;
25use super::cssstylesheet::CSSStyleSheet;
26use super::csssupportsrule::CSSSupportsRule;
27use crate::dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleMethods;
28use crate::dom::bindings::inheritance::Castable;
29use crate::dom::bindings::root::{Dom, DomRoot};
30use crate::dom::bindings::str::DOMString;
31use crate::dom::window::Window;
32
33#[dom_struct]
34pub(crate) struct CSSRule {
35 reflector_: Reflector,
36 parent_stylesheet: Dom<CSSStyleSheet>,
37
38 parent_stylesheet_removed: Cell<bool>,
42}
43
44impl CSSRule {
45 pub(crate) fn new_inherited(parent_stylesheet: &CSSStyleSheet) -> CSSRule {
46 CSSRule {
47 reflector_: Reflector::new(),
48 parent_stylesheet: Dom::from_ref(parent_stylesheet),
49 parent_stylesheet_removed: Cell::new(false),
50 }
51 }
52
53 pub(crate) fn as_specific(&self) -> &dyn SpecificCSSRule {
54 if let Some(rule) = self.downcast::<CSSStyleRule>() {
55 rule as &dyn SpecificCSSRule
56 } else if let Some(rule) = self.downcast::<CSSFontFaceRule>() {
57 rule as &dyn SpecificCSSRule
58 } else if let Some(rule) = self.downcast::<CSSKeyframesRule>() {
59 rule as &dyn SpecificCSSRule
60 } else if let Some(rule) = self.downcast::<CSSMediaRule>() {
61 rule as &dyn SpecificCSSRule
62 } else if let Some(rule) = self.downcast::<CSSNamespaceRule>() {
63 rule as &dyn SpecificCSSRule
64 } else if let Some(rule) = self.downcast::<CSSKeyframeRule>() {
65 rule as &dyn SpecificCSSRule
66 } else if let Some(rule) = self.downcast::<CSSImportRule>() {
67 rule as &dyn SpecificCSSRule
68 } else if let Some(rule) = self.downcast::<CSSSupportsRule>() {
69 rule as &dyn SpecificCSSRule
70 } else if let Some(rule) = self.downcast::<CSSLayerBlockRule>() {
71 rule as &dyn SpecificCSSRule
72 } else if let Some(rule) = self.downcast::<CSSLayerStatementRule>() {
73 rule as &dyn SpecificCSSRule
74 } else if let Some(rule) = self.downcast::<CSSNestedDeclarations>() {
75 rule as &dyn SpecificCSSRule
76 } else if let Some(rule) = self.downcast::<CSSPropertyRule>() {
77 rule as &dyn SpecificCSSRule
78 } else if let Some(rule) = self.downcast::<CSSFontFeatureValuesRule>() {
79 rule as &dyn SpecificCSSRule
80 } else {
81 unreachable!()
82 }
83 }
84
85 pub(crate) fn new_specific(
88 cx: &mut JSContext,
89 window: &Window,
90 parent_stylesheet: &CSSStyleSheet,
91 rule: StyleCssRule,
92 ) -> DomRoot<CSSRule> {
93 match rule {
95 StyleCssRule::Import(s) => {
96 DomRoot::upcast(CSSImportRule::new(cx, window, parent_stylesheet, s))
97 },
98 StyleCssRule::Style(s) => {
99 DomRoot::upcast(CSSStyleRule::new(cx, window, parent_stylesheet, s))
100 },
101 StyleCssRule::FontFace(s) => {
102 DomRoot::upcast(CSSFontFaceRule::new(cx, window, parent_stylesheet, s))
103 },
104 StyleCssRule::FontFeatureValues(rule) => DomRoot::upcast(
105 CSSFontFeatureValuesRule::new(cx, window, parent_stylesheet, rule),
106 ),
107 StyleCssRule::CounterStyle(_) => unimplemented!(),
108 StyleCssRule::Keyframes(s) => {
109 DomRoot::upcast(CSSKeyframesRule::new(cx, window, parent_stylesheet, s))
110 },
111 StyleCssRule::Media(s) => {
112 DomRoot::upcast(CSSMediaRule::new(cx, window, parent_stylesheet, s))
113 },
114 StyleCssRule::Namespace(s) => {
115 DomRoot::upcast(CSSNamespaceRule::new(cx, window, parent_stylesheet, s))
116 },
117 StyleCssRule::Supports(s) => {
118 DomRoot::upcast(CSSSupportsRule::new(cx, window, parent_stylesheet, s))
119 },
120 StyleCssRule::Page(_) => unreachable!(),
121 StyleCssRule::Container(_) => unimplemented!(), StyleCssRule::Document(_) => unimplemented!(), StyleCssRule::LayerBlock(s) => {
124 DomRoot::upcast(CSSLayerBlockRule::new(cx, window, parent_stylesheet, s))
125 },
126 StyleCssRule::LayerStatement(s) => {
127 DomRoot::upcast(CSSLayerStatementRule::new(cx, window, parent_stylesheet, s))
128 },
129 StyleCssRule::FontPaletteValues(_) => unimplemented!(), StyleCssRule::Property(s) => {
131 DomRoot::upcast(CSSPropertyRule::new(cx, window, parent_stylesheet, s))
132 },
133 StyleCssRule::Margin(_) => unimplemented!(), StyleCssRule::Scope(_) => unimplemented!(), StyleCssRule::StartingStyle(_) => unimplemented!(), StyleCssRule::PositionTry(_) => unimplemented!(), StyleCssRule::CustomMedia(_) => unimplemented!(), StyleCssRule::NestedDeclarations(s) => {
139 DomRoot::upcast(CSSNestedDeclarations::new(cx, window, parent_stylesheet, s))
140 },
141 StyleCssRule::AppearanceBase(_) => unimplemented!(), StyleCssRule::ViewTransition(_) => unimplemented!(), }
144 }
145
146 pub(crate) fn detach(&self) {
148 self.deparent();
149 }
151
152 pub(crate) fn deparent(&self) {
154 self.parent_stylesheet_removed.set(true);
155 self.as_specific().deparent_children();
159 }
160
161 pub(crate) fn parent_stylesheet(&self) -> &CSSStyleSheet {
162 &self.parent_stylesheet
163 }
164
165 pub(crate) fn shared_lock(&self) -> &SharedRwLock {
166 self.parent_stylesheet.shared_lock()
167 }
168
169 pub(crate) fn update_rule(&self, style_rule: &StyleCssRule, guard: &SharedRwLockReadGuard) {
170 match style_rule {
171 StyleCssRule::Import(s) => {
172 if let Some(rule) = self.downcast::<CSSImportRule>() {
173 rule.update_rule(s.clone());
174 }
175 },
176 StyleCssRule::Style(s) => {
177 if let Some(rule) = self.downcast::<CSSStyleRule>() {
178 rule.update_rule(s.clone(), guard);
179 }
180 },
181 StyleCssRule::FontFace(s) => {
182 if let Some(rule) = self.downcast::<CSSFontFaceRule>() {
183 rule.update_rule(s.clone());
184 }
185 },
186 StyleCssRule::FontFeatureValues(_) => unimplemented!(),
187 StyleCssRule::CounterStyle(_) => unimplemented!(),
188 StyleCssRule::Keyframes(s) => {
189 if let Some(rule) = self.downcast::<CSSKeyframesRule>() {
190 rule.update_rule(s.clone(), guard);
191 }
192 },
193 StyleCssRule::Media(s) => {
194 if let Some(rule) = self.downcast::<CSSMediaRule>() {
195 rule.update_rule(s.clone(), guard);
196 }
197 },
198 StyleCssRule::Namespace(s) => {
199 if let Some(rule) = self.downcast::<CSSNamespaceRule>() {
200 rule.update_rule(s.clone());
201 }
202 },
203 StyleCssRule::Supports(s) => {
204 if let Some(rule) = self.downcast::<CSSSupportsRule>() {
205 rule.update_rule(s.clone(), guard);
206 }
207 },
208 StyleCssRule::Page(_) => unreachable!(),
209 StyleCssRule::Container(_) => unimplemented!(), StyleCssRule::Document(_) => unimplemented!(), StyleCssRule::LayerBlock(s) => {
212 if let Some(rule) = self.downcast::<CSSLayerBlockRule>() {
213 rule.update_rule(s.clone(), guard);
214 }
215 },
216 StyleCssRule::LayerStatement(s) => {
217 if let Some(rule) = self.downcast::<CSSLayerStatementRule>() {
218 rule.update_rule(s.clone());
219 }
220 },
221 StyleCssRule::FontPaletteValues(_) => unimplemented!(), StyleCssRule::Property(s) => {
223 if let Some(rule) = self.downcast::<CSSPropertyRule>() {
224 rule.update_rule(s.clone());
225 }
226 },
227 StyleCssRule::Margin(_) => unimplemented!(), StyleCssRule::Scope(_) => unimplemented!(), StyleCssRule::StartingStyle(_) => unimplemented!(), StyleCssRule::PositionTry(_) => unimplemented!(), StyleCssRule::CustomMedia(_) => unimplemented!(), StyleCssRule::NestedDeclarations(s) => {
233 if let Some(rule) = self.downcast::<CSSNestedDeclarations>() {
234 rule.update_rule(s.clone(), guard);
235 }
236 },
237 StyleCssRule::AppearanceBase(_) => unimplemented!(), StyleCssRule::ViewTransition(_) => unimplemented!(), }
240 }
241}
242
243impl CSSRuleMethods<crate::DomTypeHolder> for CSSRule {
244 fn Type(&self) -> u16 {
246 let rule_type = self.as_specific().ty() as u16;
247 if rule_type > 15 { 0 } else { rule_type }
250 }
251
252 fn GetParentStyleSheet(&self) -> Option<DomRoot<CSSStyleSheet>> {
254 if self.parent_stylesheet_removed.get() {
255 None
256 } else {
257 Some(DomRoot::from_ref(&*self.parent_stylesheet))
258 }
259 }
260
261 fn CssText(&self) -> DOMString {
263 self.as_specific().get_css()
264 }
265
266 fn SetCssText(&self, _: DOMString) {
268 }
270}
271
272pub(crate) trait SpecificCSSRule {
273 fn ty(&self) -> CssRuleType;
274 fn get_css(&self) -> DOMString;
275 fn deparent_children(&self) {
277 }
279}