Evan Almloff 1 год назад
Родитель
Сommit
918d09b516
2 измененных файлов с 37 добавлено и 8 удалено
  1. 32 6
      packages/rsx/src/attribute.rs
  2. 5 2
      packages/rsx/src/lib.rs

+ 32 - 6
packages/rsx/src/attribute.rs

@@ -33,13 +33,39 @@ impl AttributeType {
             _ => None,
         }
     }
-}
 
-impl ToTokens for AttributeType {
-    fn to_tokens(&self, tokens: &mut TokenStream2) {
-        match self {
-            AttributeType::Named(n) => tokens.append_all(quote! { Box::new([#n]) }),
-            AttributeType::Spread(e) => tokens.append_all(quote! { #e.into_boxed_slice() }),
+    pub(crate) fn merge_quote(vec: &[&Self]) -> TokenStream2 {
+        // split into spread and single attributes
+        let mut spread = vec![];
+        let mut single = vec![];
+        for attr in vec.iter() {
+            match attr {
+                AttributeType::Named(named) => single.push(named),
+                AttributeType::Spread(expr) => spread.push(expr),
+            }
+        }
+
+        // If all of them are single attributes, create a static slice
+        if spread.is_empty() {
+            quote! {
+                Box::new([
+                    #(#single),*
+                ])
+            }
+        } else {
+            // Otherwise start with the single attributes and append the spread attributes
+            quote! {
+                {
+                    let mut __attributes = vec![
+                        #(#single),*
+                    ];
+                    #(
+                        let mut __spread = #spread;
+                        __attributes.append(&mut __spread);
+                    )*
+                    __attributes.into_boxed_slice()
+                }
+            }
         }
     }
 }

+ 5 - 2
packages/rsx/src/lib.rs

@@ -241,7 +241,10 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
         // Render and release the mutable borrow on context
         let roots = quote! { #( #root_printer ),* };
         let node_printer = &context.dynamic_nodes;
-        let dyn_attr_printer = &context.dynamic_attributes;
+        let dyn_attr_printer = context
+            .dynamic_attributes
+            .iter()
+            .map(|attrs| AttributeType::merge_quote(attrs));
         let node_paths = context.node_paths.iter().map(|it| quote!(&[#(#it),*]));
         let attr_paths = context.attr_paths.iter().map(|it| quote!(&[#(#it),*]));
 
@@ -257,7 +260,7 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
                 #key_tokens,
                 TEMPLATE,
                 Box::new([ #( #node_printer),* ]),
-                Box::new([ #( #(#dyn_attr_printer),* ),* ]),
+                Box::new([ #(#dyn_attr_printer),* ]),
             )
         });
     }