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