Pre-build static arrays of attrs etc to save on allocations.

This commit is contained in:
Bodil Stokke 2019-03-16 16:24:23 +00:00
parent 813121b3a7
commit c892a9f27e
2 changed files with 42 additions and 19 deletions

View File

@ -40,7 +40,7 @@ impl Render for Counter {
let count = bumpalo::format!(in bump, "{}", self.count); let count = bumpalo::format!(in bump, "{}", self.count);
dodrio!(bump, dodrio!(bump,
<div> <div id="counter">
<button onclick={|root, vdom, _event| { <button onclick={|root, vdom, _event| {
// Cast the root render component to a `Counter`, since // Cast the root render component to a `Counter`, since
// we know that's what it is. // we know that's what it is.

View File

@ -61,6 +61,7 @@ impl Node {
} }
} }
#[cfg(feature = "dodrio")]
pub fn into_dodrio_token_stream( pub fn into_dodrio_token_stream(
self, self,
bump: &Ident, bump: &Ident,
@ -279,6 +280,7 @@ impl Element {
)) ))
} }
#[cfg(feature = "dodrio")]
fn into_dodrio_token_stream( fn into_dodrio_token_stream(
mut self, mut self,
bump: &Ident, bump: &Ident,
@ -367,39 +369,59 @@ impl Element {
} }
} }
let mut builder = TokenStream::new(); let mut builder = quote!(
builder.extend(quote!(
dodrio::builder::ElementBuilder::new(#bump, #tag_name) dodrio::builder::ElementBuilder::new(#bump, #tag_name)
)); );
// Build an array of attributes.
let mut attr_array = TokenStream::new();
for (key, _) in self.attributes.iter() { for (key, _) in self.attributes.iter() {
let key_str = TokenTree::from(Literal::string(&stringify_ident(key))); let key_str = TokenTree::from(Literal::string(&stringify_ident(key)));
builder.extend(quote!( attr_array.extend(quote!(
.attr(#key_str, dodrio::bumpalo::format!(in &#bump, "{}", dodrio::builder::attr(
element.attrs.#key.unwrap()).into_bump_str()) #key_str,
dodrio::bumpalo::format!(
in &#bump, "{}", element.attrs.#key.unwrap()
).into_bump_str()
),
)); ));
} }
for (key, value) in data_attrs for (key, value) in data_attrs
.iter() .iter()
.map(|(k, v)| (TokenTree::from(Literal::string(&k)), v.clone())) .map(|(k, v)| (TokenTree::from(Literal::string(&k)), v.clone()))
{ {
builder.extend(quote!( attr_array.extend(quote!(
.attr(#key, #value.into()) dodrio::builder::attr(
#key,
dodrio::bumpalo::format!(
in &#bump, "{}", #value
).into_bump_str()
)
)); ));
} }
builder.extend(quote!(
.attributes([#attr_array])
));
// Build an array of event listeners.
let mut event_array = TokenStream::new();
for (key, value) in events.iter() { for (key, value) in events.iter() {
let key = TokenTree::from(Literal::string(&stringify_ident(key))); let key = TokenTree::from(Literal::string(&stringify_ident(key)));
let value = process_value(value); let value = process_value(value);
builder.extend(quote!( event_array.extend(quote!(
.on(#key, #value) dodrio::builder::on(&#bump, #key, #value),
)); ));
} }
builder.extend(quote!(
.listeners([#event_array])
));
// And finally an array of children.
let mut child_array = TokenStream::new();
// Walk through required children and build them inline.
let mut make_req_children = TokenStream::new(); let mut make_req_children = TokenStream::new();
let mut arg_list = Vec::new(); let mut arg_list = Vec::new();
let mut req_nodes = Vec::new();
for (index, child) in req_children.into_iter().enumerate() { for (index, child) in req_children.into_iter().enumerate() {
let req_child = TokenTree::from(Ident::new( let req_child = TokenTree::from(Ident::new(
&format!("req_child_{}", index), &format!("req_child_{}", index),
@ -412,20 +434,20 @@ impl Element {
make_req_children.extend(quote!( make_req_children.extend(quote!(
let (#req_child, #child_node) = #child; let (#req_child, #child_node) = #child;
)); ));
builder.extend(quote!( child_array.extend(quote!(
.child(#child_node) #child_node,
)); ));
arg_list.push(req_child); arg_list.push(req_child);
req_nodes.push(child_node);
} }
for child in opt_children { for child in opt_children {
builder.extend(quote!( child_array.extend(quote!(
.child(#child) #child,
)); ));
} }
builder.extend(quote!( builder.extend(quote!(
.children([#child_array])
.finish() .finish()
)); ));
@ -443,7 +465,8 @@ impl Element {
Ok(quote!( Ok(quote!(
{ {
#make_req_children #make_req_children
let mut element: typed_html::elements::#typename<typed_html::output::dodrio::Dodrio> = typed_html::elements::#typename::new(#args); let mut element: typed_html::elements::#typename<typed_html::output::dodrio::Dodrio> =
typed_html::elements::#typename::new(#args);
#set_attrs #set_attrs
#builder #builder
} }