33use std:: {
44 borrow:: { BorrowMut , Cow } ,
55 cell:: RefCell ,
6+ ops:: { Deref , DerefMut } ,
67 rc:: Rc ,
78} ;
89
@@ -47,7 +48,7 @@ impl OwnedStyleSheet {
4748// https://drafts.csswg.org/cssom/#the-cssstylesheet-interface
4849#[ napi( js_name = "CSSStyleSheet" ) ]
4950struct CSSStyleSheet {
50- stylesheet : Rc < RefCell < OwnedStyleSheet > > ,
51+ stylesheet : OwnedStyleSheet ,
5152 rules : Option < Reference < CSSRuleList > > ,
5253}
5354
@@ -56,27 +57,27 @@ impl CSSStyleSheet {
5657 #[ napi( constructor) ]
5758 pub fn new ( ) -> Self {
5859 CSSStyleSheet {
59- stylesheet : Rc :: new ( RefCell :: new ( OwnedStyleSheet :: new ( ) ) ) ,
60+ stylesheet : OwnedStyleSheet :: new ( ) ,
6061 rules : None ,
6162 }
6263 }
6364
6465 #[ napi]
6566 pub fn replace_sync ( & mut self , env : Env , code : String ) -> Result < ( ) > {
66- let mut stylesheet = ( * self . stylesheet ) . borrow_mut ( ) ;
67+ // let mut stylesheet = (*self.stylesheet).borrow_mut();
6768
6869 // Disconnect all existing rules from the stylesheet.
6970 if let Some ( rules) = & mut self . rules {
7071 let rules = & mut * * rules;
7172 for ( index, rule) in rules. rules . iter_mut ( ) . enumerate ( ) {
7273 if let Some ( rule) = rule {
7374 let rule: & mut CSSRule = get_reference ( env, rule) ?;
74- rule. inner = RuleInner :: Disconnected ( RefCell :: new ( stylesheet. stylesheet . rules . 0 [ index] . clone ( ) ) ) ;
75+ rule. inner = RuleInner :: Disconnected ( self . stylesheet . stylesheet . rules . 0 [ index] . clone ( ) ) ;
7576 }
7677 }
7778 }
7879
79- stylesheet. replace_sync ( code) ;
80+ self . stylesheet . replace_sync ( code) ;
8081 Ok ( ( ) )
8182 }
8283
@@ -87,7 +88,11 @@ impl CSSStyleSheet {
8788 }
8889
8990 let rules = CSSRuleList {
90- stylesheet : self . stylesheet . clone ( ) ,
91+ rule_list : RuleListReference :: StyleSheet (
92+ reference
93+ . clone ( env) ?
94+ . share_with ( env, |stylesheet| Ok ( & mut stylesheet. stylesheet . stylesheet . rules ) ) ?,
95+ ) ,
9196 rules : Vec :: new ( ) ,
9297 stylesheet_reference : reference,
9398 } ;
@@ -100,7 +105,8 @@ impl CSSStyleSheet {
100105 pub fn insert_rule ( & mut self , env : Env , rule : String , index : Option < u32 > ) -> Result < u32 > {
101106 // https://drafts.csswg.org/cssom/#insert-a-css-rule
102107 let index = index. unwrap_or ( 0 ) as usize ;
103- let stylesheet = & mut ( * self . stylesheet ) . borrow_mut ( ) . stylesheet ;
108+ // let stylesheet = &mut (*self.stylesheet).borrow_mut().stylesheet;
109+ let stylesheet = & mut self . stylesheet . stylesheet ;
104110 let rules = & mut stylesheet. rules . 0 ;
105111 if index > rules. len ( ) {
106112 return Err ( napi:: Error :: new (
@@ -148,7 +154,8 @@ impl CSSStyleSheet {
148154 pub fn delete_rule ( & mut self , env : Env , index : u32 ) -> Result < ( ) > {
149155 // https://drafts.csswg.org/cssom/#remove-a-css-rule
150156 let index = index as usize ;
151- let stylesheet = & mut ( * self . stylesheet ) . borrow_mut ( ) . stylesheet ;
157+ // let stylesheet = &mut (*self.stylesheet).borrow_mut().stylesheet;
158+ let stylesheet = & mut self . stylesheet . stylesheet ;
152159 let rules = & mut stylesheet. rules . 0 ;
153160 if index > rules. len ( ) {
154161 return Err ( napi:: Error :: new (
@@ -162,7 +169,7 @@ impl CSSStyleSheet {
162169 if index < rule_objects. rules . len ( ) {
163170 if let Some ( rule) = & rule_objects. rules [ index] {
164171 let rule: & mut CSSRule = get_reference ( env, rule) ?;
165- rule. inner = RuleInner :: Disconnected ( RefCell :: new ( rules[ index] . clone ( ) ) ) ;
172+ rule. inner = RuleInner :: Disconnected ( rules[ index] . clone ( ) ) ;
166173 }
167174
168175 for rule in & rule_objects. rules [ index + 1 ..] {
@@ -200,9 +207,43 @@ fn get_reference<T: napi::bindgen_prelude::FromNapiMutRef>(
200207 }
201208}
202209
210+ enum RuleListReference {
211+ StyleSheet ( SharedReference < CSSStyleSheet , & ' static mut CssRuleList < ' static > > ) ,
212+ Rule ( SharedReference < CSSGroupingRule , & ' static mut CssRuleList < ' static > > ) ,
213+ }
214+
215+ impl RuleListReference {
216+ fn clone ( & self , env : Env ) -> Result < Self > {
217+ match self {
218+ RuleListReference :: StyleSheet ( s) => Ok ( RuleListReference :: StyleSheet ( s. clone ( env) ?) ) ,
219+ RuleListReference :: Rule ( r) => Ok ( RuleListReference :: Rule ( r. clone ( env) ?) ) ,
220+ }
221+ }
222+ }
223+
224+ impl Deref for RuleListReference {
225+ type Target = CssRuleList < ' static > ;
226+
227+ fn deref ( & self ) -> & Self :: Target {
228+ match self {
229+ RuleListReference :: StyleSheet ( s) => & * * s,
230+ RuleListReference :: Rule ( r) => & * * r,
231+ }
232+ }
233+ }
234+
235+ impl DerefMut for RuleListReference {
236+ fn deref_mut ( & mut self ) -> & mut CssRuleList < ' static > {
237+ match self {
238+ RuleListReference :: StyleSheet ( s) => & mut * * s,
239+ RuleListReference :: Rule ( r) => & mut * * r,
240+ }
241+ }
242+ }
243+
203244#[ napi( js_name = "CSSRuleList" ) ]
204245struct CSSRuleList {
205- stylesheet : Rc < RefCell < OwnedStyleSheet > > ,
246+ rule_list : RuleListReference ,
206247 rules : Vec < Option < Ref < ( ) > > > ,
207248 stylesheet_reference : Reference < CSSStyleSheet > ,
208249}
@@ -216,7 +257,7 @@ impl CSSRuleList {
216257
217258 #[ napi( getter) ]
218259 pub fn length ( & self ) -> u32 {
219- self . stylesheet . borrow ( ) . stylesheet . rules . 0 . len ( ) as u32
260+ self . rule_list . 0 . len ( ) as u32
220261 }
221262
222263 #[ napi]
@@ -226,15 +267,14 @@ impl CSSRuleList {
226267 return env. get_reference_value ( rule) ;
227268 }
228269
229- let stylesheet = self . stylesheet . borrow ( ) ;
230- let rule = match stylesheet. stylesheet . rules . 0 . get ( index) {
270+ let rule = match self . rule_list . 0 . get ( index) {
231271 Some ( rule) => rule,
232272 None => return Ok ( env. get_null ( ) ?. into_unknown ( ) ) ,
233273 } ;
234274
235275 let css_rule = CSSRule {
236276 inner : RuleInner :: Connected {
237- stylesheet : self . stylesheet . clone ( ) ,
277+ rule_list : self . rule_list . clone ( env ) ? ,
238278 index,
239279 } ,
240280 parent_stylesheet : self . stylesheet_reference . clone ( env) ?,
@@ -245,6 +285,15 @@ impl CSSRuleList {
245285 let rule = CSSStyleRule :: new ( css_rule) ;
246286 unsafe { napi:: bindgen_prelude:: ToNapiValue :: to_napi_value ( env. raw ( ) , rule) ? }
247287 }
288+ CssRule :: Media ( _) => {
289+ let rule = CSSMediaRule {
290+ rule : CSSGroupingRule {
291+ rule : css_rule,
292+ rules : None ,
293+ } ,
294+ } ;
295+ unsafe { napi:: bindgen_prelude:: ToNapiValue :: to_napi_value ( env. raw ( ) , rule) ? }
296+ }
248297 _ => unreachable ! ( ) ,
249298 } ;
250299
@@ -260,11 +309,8 @@ impl CSSRuleList {
260309}
261310
262311enum RuleInner {
263- Connected {
264- stylesheet : Rc < RefCell < OwnedStyleSheet > > ,
265- index : usize ,
266- } ,
267- Disconnected ( RefCell < CssRule < ' static > > ) ,
312+ Connected { rule_list : RuleListReference , index : usize } ,
313+ Disconnected ( CssRule < ' static > ) ,
268314}
269315
270316#[ napi( js_name = "CSSRule" ) ]
@@ -307,23 +353,20 @@ impl CSSRule {
307353 // On setting the cssText attribute must do nothing.
308354 }
309355
310- fn rule ( & self ) -> std :: cell :: Ref < CssRule < ' static > > {
356+ fn rule ( & self ) -> & CssRule < ' static > {
311357 match & self . inner {
312- RuleInner :: Connected { stylesheet , index } => {
313- let stylesheet = stylesheet. borrow ( ) ;
314- std :: cell :: Ref :: map ( stylesheet , |stylesheet| & stylesheet . stylesheet . rules . 0 [ * index] )
358+ RuleInner :: Connected { rule_list , index } => {
359+ // std::cell::Ref::map( stylesheet, |stylesheet| & stylesheet.stylesheet.rules.0[*index])
360+ & rule_list . 0 [ * index]
315361 }
316- RuleInner :: Disconnected ( rule) => rule. borrow ( ) ,
362+ RuleInner :: Disconnected ( rule) => & rule,
317363 }
318364 }
319365
320- fn rule_mut ( & mut self ) -> std:: cell:: RefMut < CssRule < ' static > > {
321- match & self . inner {
322- RuleInner :: Connected { stylesheet, index } => {
323- let stylesheet = ( * * stylesheet) . borrow_mut ( ) ;
324- std:: cell:: RefMut :: map ( stylesheet, |stylesheet| & mut stylesheet. stylesheet . rules . 0 [ * index] )
325- }
326- RuleInner :: Disconnected ( rule) => rule. borrow_mut ( ) ,
366+ fn rule_mut ( & mut self ) -> & mut CssRule < ' static > {
367+ match & mut self . inner {
368+ RuleInner :: Connected { rule_list, index } => & mut rule_list. 0 [ * index] ,
369+ RuleInner :: Disconnected ( rule) => rule,
327370 }
328371 }
329372
@@ -396,20 +439,20 @@ impl CSSStyleRule {
396439 } ;
397440 }
398441
399- fn rule ( & self ) -> std :: cell :: Ref < StyleRule < ' static > > {
442+ fn rule ( & self ) -> & StyleRule < ' static > {
400443 let rule = self . rule . rule ( ) ;
401- std :: cell :: Ref :: map ( rule , |rule| match rule {
444+ match rule {
402445 CssRule :: Style ( style) => style,
403446 _ => unreachable ! ( ) ,
404- } )
447+ }
405448 }
406449
407- fn rule_mut ( & mut self ) -> std :: cell :: RefMut < StyleRule < ' static > > {
450+ fn rule_mut ( & mut self ) -> & mut StyleRule < ' static > {
408451 let rule = self . rule . rule_mut ( ) ;
409- std :: cell :: RefMut :: map ( rule , |rule| match rule {
452+ match rule {
410453 CssRule :: Style ( style) => style,
411454 _ => unreachable ! ( ) ,
412- } )
455+ }
413456 }
414457}
415458
@@ -528,6 +571,52 @@ impl CSSStyleDeclaration {
528571 }
529572}
530573
574+ #[ napi( js_name = "CSSGroupingRule" ) ]
575+ struct CSSGroupingRule {
576+ rule : CSSRule ,
577+ rules : Option < Reference < CSSRuleList > > ,
578+ }
579+
580+ #[ napi]
581+ impl CSSGroupingRule {
582+ #[ napi( constructor) ]
583+ pub fn new ( ) {
584+ unreachable ! ( )
585+ }
586+
587+ #[ napi( getter) ]
588+ pub fn css_rules ( & mut self , env : Env , reference : Reference < CSSGroupingRule > ) -> Result < Reference < CSSRuleList > > {
589+ if let Some ( rules) = & self . rules {
590+ return rules. clone ( env) ;
591+ }
592+
593+ let rules = CSSRuleList {
594+ rule_list : RuleListReference :: Rule ( reference. share_with ( env, |rule| match rule. rule . rule_mut ( ) {
595+ CssRule :: Media ( media) => Ok ( & mut media. rules ) ,
596+ _ => unreachable ! ( ) ,
597+ } ) ?) ,
598+ rules : Vec :: new ( ) ,
599+ stylesheet_reference : self . rule . parent_stylesheet . clone ( env) ?,
600+ } ;
601+
602+ self . rules = Some ( CSSRuleList :: into_reference ( rules, env) ?) ;
603+ self . rules . as_ref ( ) . unwrap ( ) . clone ( env)
604+ }
605+ }
606+
607+ #[ napi( js_name = "CSSMediaRule" ) ]
608+ struct CSSMediaRule {
609+ rule : CSSGroupingRule ,
610+ }
611+
612+ #[ napi]
613+ impl CSSMediaRule {
614+ #[ napi( constructor) ]
615+ pub fn new ( ) {
616+ unreachable ! ( )
617+ }
618+ }
619+
531620fn leak_str ( string : String ) -> & ' static str {
532621 let res = unsafe {
533622 let slice = std:: slice:: from_raw_parts ( string. as_ptr ( ) , string. len ( ) ) ;
0 commit comments