@@ -252,7 +252,10 @@ fn css_rule_to_js_unknown(rule: &CssRule<'static>, env: Env, css_rule: CSSRule)
252252}
253253
254254fn keyframe_to_js_unknown ( env : Env , css_rule : CSSRule ) -> Result < JsUnknown > {
255- let rule = CSSKeyframeRule { rule : css_rule } ;
255+ let rule = CSSKeyframeRule {
256+ rule : css_rule,
257+ style : None ,
258+ } ;
256259 let napi_value = unsafe { napi:: bindgen_prelude:: ToNapiValue :: to_napi_value ( env. raw ( ) , rule) ? } ;
257260 unsafe { napi:: JsUnknown :: from_napi_value ( env. raw ( ) , napi_value) }
258261}
@@ -552,19 +555,31 @@ impl CSSStyleRule {
552555 return rules. clone ( env) ;
553556 }
554557
555- let style = CSSStyleDeclaration :: into_reference ( CSSStyleDeclaration { rule : reference } , env) ?;
558+ let declarations = reference
559+ . clone ( env) ?
560+ . share_with ( env, |reference| Ok ( & mut reference. rule_mut ( ) . declarations ) ) ?;
561+ let declarations = unsafe {
562+ std:: mem:: transmute :: <
563+ SharedReference < CSSStyleRule , & mut DeclarationBlock < ' static > > ,
564+ SharedReference < CSSRule , & mut DeclarationBlock < ' static > > ,
565+ > ( declarations)
566+ } ;
567+ let parent_rule = unsafe { std:: mem:: transmute :: < Reference < CSSStyleRule > , Reference < CSSRule > > ( reference) } ;
568+ let style = CSSStyleDeclaration :: into_reference (
569+ CSSStyleDeclaration {
570+ parent_rule,
571+ declarations,
572+ } ,
573+ env,
574+ ) ?;
556575 self . style = Some ( style. clone ( env) ?) ;
557576 Ok ( style)
558577 }
559578
560579 #[ napi( setter) ]
561580 pub fn set_style ( & mut self , text : String ) {
562- match & mut * self . rule . rule_mut ( ) {
563- CssRule :: Style ( style) => {
564- style. declarations = DeclarationBlock :: parse_string ( leak_str ( text) , ParserOptions :: default ( ) ) . unwrap ( ) ;
565- }
566- _ => unreachable ! ( ) ,
567- } ;
581+ self . rule_mut ( ) . declarations =
582+ DeclarationBlock :: parse_string ( leak_str ( text) , ParserOptions :: default ( ) ) . unwrap ( ) ;
568583 }
569584
570585 fn rule ( & self ) -> & StyleRule < ' static > {
@@ -586,7 +601,8 @@ impl CSSStyleRule {
586601
587602#[ napi( js_name = "CSSStyleDeclaration" ) ]
588603struct CSSStyleDeclaration {
589- rule : Reference < CSSStyleRule > ,
604+ parent_rule : Reference < CSSRule > ,
605+ declarations : SharedReference < CSSRule , & ' static mut DeclarationBlock < ' static > > ,
590606}
591607
592608#[ napi]
@@ -597,24 +613,23 @@ impl CSSStyleDeclaration {
597613 }
598614
599615 #[ napi( getter) ]
600- pub fn parent_rule ( & self , env : Env ) -> Result < Reference < CSSStyleRule > > {
601- self . rule . clone ( env)
616+ pub fn parent_rule ( & self , env : Env ) -> Result < Reference < CSSRule > > {
617+ self . parent_rule . clone ( env)
602618 }
603619
604620 #[ napi( getter) ]
605621 pub fn css_text ( & self ) -> String {
606- self . rule . rule ( ) . declarations . to_css_string ( PrinterOptions :: default ( ) ) . unwrap ( )
622+ self . declarations . to_css_string ( PrinterOptions :: default ( ) ) . unwrap ( )
607623 }
608624
609625 #[ napi( setter) ]
610626 pub fn set_css_text ( & mut self , text : String ) {
611- self . rule . set_style ( text)
627+ * * self . declarations = DeclarationBlock :: parse_string ( leak_str ( text) , ParserOptions :: default ( ) ) . unwrap ( ) ;
612628 }
613629
614630 fn get_longhands ( & self ) -> Vec < String > {
615- let rule = self . rule . rule ( ) ;
616631 let mut longhands = Vec :: new ( ) ;
617- for ( property, _important) in rule . declarations . iter ( ) {
632+ for ( property, _important) in self . declarations . iter ( ) {
618633 let property_id = property. property_id ( ) ;
619634 if let Some ( properties) = property_id. longhands ( ) {
620635 longhands. extend ( properties. iter ( ) . map ( |property_id| property_id. name ( ) . to_owned ( ) ) )
@@ -646,7 +661,7 @@ impl CSSStyleDeclaration {
646661 let property_id = PropertyId :: parse_string ( & property) . unwrap ( ) ;
647662 let opts = PrinterOptions :: default ( ) ;
648663
649- if let Some ( ( value, _important) ) = self . rule . rule ( ) . declarations . get ( & property_id) {
664+ if let Some ( ( value, _important) ) = self . declarations . get ( & property_id) {
650665 return value. value_to_css_string ( opts) . unwrap ( ) ;
651666 }
652667
@@ -656,7 +671,7 @@ impl CSSStyleDeclaration {
656671 #[ napi]
657672 pub fn get_property_priority ( & mut self , property : String ) -> & str {
658673 let property_id = PropertyId :: parse_string ( & property) . unwrap ( ) ;
659- let important = if let Some ( ( _value, important) ) = self . rule . rule ( ) . declarations . get ( & property_id) {
674+ let important = if let Some ( ( _value, important) ) = self . declarations . get ( & property_id) {
660675 important
661676 } else {
662677 false
@@ -678,7 +693,7 @@ impl CSSStyleDeclaration {
678693
679694 let property =
680695 Property :: parse_string ( leak_str ( property) . into ( ) , leak_str ( value) , ParserOptions :: default ( ) ) . unwrap ( ) ;
681- self . rule . rule_mut ( ) . declarations . set (
696+ self . declarations . set (
682697 property,
683698 if let Some ( priority) = priority {
684699 priority. eq_ignore_ascii_case ( "important" )
@@ -693,7 +708,7 @@ impl CSSStyleDeclaration {
693708 let value = self . get_property_value ( property. clone ( ) ) ;
694709
695710 let property_id = PropertyId :: parse_string ( & property) . unwrap ( ) ;
696- self . rule . rule_mut ( ) . declarations . remove ( & property_id) ;
711+ self . declarations . remove ( & property_id) ;
697712
698713 value
699714 }
@@ -1118,6 +1133,7 @@ impl CSSKeyframesRule {
11181133#[ napi( js_name = "CSSKeyframeRule" ) ]
11191134struct CSSKeyframeRule {
11201135 rule : CSSRule ,
1136+ style : Option < Reference < CSSStyleDeclaration > > ,
11211137}
11221138
11231139#[ napi]
@@ -1150,6 +1166,52 @@ impl CSSKeyframeRule {
11501166 // Spec says to throw a SyntaxError, but no browser does?
11511167 }
11521168 }
1169+
1170+ #[ napi( getter) ]
1171+ pub fn style (
1172+ & mut self ,
1173+ env : Env ,
1174+ reference : Reference < CSSKeyframeRule > ,
1175+ ) -> Result < Reference < CSSStyleDeclaration > > {
1176+ if let Some ( rules) = & self . style {
1177+ return rules. clone ( env) ;
1178+ }
1179+
1180+ let declarations =
1181+ reference
1182+ . clone ( env) ?
1183+ . share_with ( env, |reference| match reference. rule . inner . rule_mut ( ) {
1184+ RuleOrKeyframeRefMut :: Keyframe ( keyframe) => Ok ( & mut keyframe. declarations ) ,
1185+ _ => unreachable ! ( ) ,
1186+ } ) ?;
1187+ let declarations = unsafe {
1188+ std:: mem:: transmute :: <
1189+ SharedReference < CSSKeyframeRule , & mut DeclarationBlock < ' static > > ,
1190+ SharedReference < CSSRule , & mut DeclarationBlock < ' static > > ,
1191+ > ( declarations)
1192+ } ;
1193+ let parent_rule = unsafe { std:: mem:: transmute :: < Reference < CSSKeyframeRule > , Reference < CSSRule > > ( reference) } ;
1194+
1195+ let style = CSSStyleDeclaration :: into_reference (
1196+ CSSStyleDeclaration {
1197+ parent_rule,
1198+ declarations,
1199+ } ,
1200+ env,
1201+ ) ?;
1202+ self . style = Some ( style. clone ( env) ?) ;
1203+ Ok ( style)
1204+ }
1205+
1206+ #[ napi( setter) ]
1207+ pub fn set_style ( & mut self , text : String ) {
1208+ match self . rule . inner . rule_mut ( ) {
1209+ RuleOrKeyframeRefMut :: Keyframe ( keyframe) => {
1210+ keyframe. declarations = DeclarationBlock :: parse_string ( leak_str ( text) , ParserOptions :: default ( ) ) . unwrap ( ) ;
1211+ }
1212+ _ => unreachable ! ( ) ,
1213+ } ;
1214+ }
11531215}
11541216
11551217fn leak_str ( string : String ) -> & ' static str {
0 commit comments