From 918d09b516674bea11f8082eca97c571c43581e0 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 16 Jan 2024 14:20:51 -0600 Subject: [PATCH] fix merging attributes --- packages/rsx/src/attribute.rs | 38 +++++++++++++++++++++++++++++------ packages/rsx/src/lib.rs | 7 +++++-- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/packages/rsx/src/attribute.rs b/packages/rsx/src/attribute.rs index 84d92cf8d..34429495d 100644 --- a/packages/rsx/src/attribute.rs +++ b/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() + } + } } } } diff --git a/packages/rsx/src/lib.rs b/packages/rsx/src/lib.rs index 59d52892c..dd67a9dba 100644 --- a/packages/rsx/src/lib.rs +++ b/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),* ]), ) }); }