fix 2020: return None if the root nodes are empty in rsx (#2026)
This commit is contained in:
1 parent
8eda67ecb2
commit
7461a14cb4
3 files changed
+41
-13
No files matched your search
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use rsx::RenderCallBody;
|
|
||||||
use syn::parse::Parser;
|
use syn::parse::Parser;
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::{parse_macro_input, Path, Token};
|
use syn::{parse_macro_input, Path, Token};
|
||||||
@@ -42,7 +41,7 @@ pub fn derive_typed_builder(input: TokenStream) -> TokenStream {
|
|||||||
pub fn rsx(tokens: TokenStream) -> TokenStream {
|
pub fn rsx(tokens: TokenStream) -> TokenStream {
|
||||||
match syn::parse::<rsx::CallBody>(tokens) {
|
match syn::parse::<rsx::CallBody>(tokens) {
|
||||||
Err(err) => err.to_compile_error().into(),
|
Err(err) => err.to_compile_error().into(),
|
||||||
Ok(body) => RenderCallBody(body).into_token_stream().into(),
|
Ok(body) => body.into_token_stream().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -181,3 +181,28 @@ fn attribute_diff() {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn diff_empty() {
|
||||||
|
fn app() -> Element {
|
||||||
|
match generation() % 2 {
|
||||||
|
0 => rsx! { div { "hello" } },
|
||||||
|
1 => rsx! {},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut vdom = VirtualDom::new(app);
|
||||||
|
vdom.rebuild(&mut NoOpMutations);
|
||||||
|
|
||||||
|
vdom.mark_dirty(ScopeId::ROOT);
|
||||||
|
let edits = vdom.render_immediate_to_vec().santize().edits;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
edits,
|
||||||
|
[
|
||||||
|
CreatePlaceholder { id: ElementId(2,) },
|
||||||
|
ReplaceWith { id: ElementId(1,), m: 1 },
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
+15
-11
@@ -84,10 +84,13 @@ impl CallBody {
|
|||||||
location: Some(location),
|
location: Some(location),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Empty templates just are placeholders for "none"
|
||||||
|
if self.roots.is_empty() {
|
||||||
|
return quote! { None };
|
||||||
|
}
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
Some({
|
Some({ #body })
|
||||||
#body
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,20 +113,20 @@ impl Parse for CallBody {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
impl ToTokens for CallBody {
|
||||||
pub struct RenderCallBody(pub CallBody);
|
|
||||||
|
|
||||||
impl ToTokens for RenderCallBody {
|
|
||||||
fn to_tokens(&self, out_tokens: &mut TokenStream2) {
|
fn to_tokens(&self, out_tokens: &mut TokenStream2) {
|
||||||
let body: TemplateRenderer = TemplateRenderer {
|
let body: TemplateRenderer = TemplateRenderer {
|
||||||
roots: &self.0.roots,
|
roots: &self.roots,
|
||||||
location: None,
|
location: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Empty templates just are placeholders for "none"
|
||||||
|
if self.roots.is_empty() {
|
||||||
|
return out_tokens.append_all(quote! { None });
|
||||||
|
}
|
||||||
|
|
||||||
out_tokens.append_all(quote! {
|
out_tokens.append_all(quote! {
|
||||||
Some({
|
Some({ #body })
|
||||||
#body
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,6 +148,7 @@ impl<'a> TemplateRenderer<'a> {
|
|||||||
let mut context = DynamicContext::default();
|
let mut context = DynamicContext::default();
|
||||||
|
|
||||||
let mut roots = Vec::new();
|
let mut roots = Vec::new();
|
||||||
|
|
||||||
for (idx, root) in self.roots.iter().enumerate() {
|
for (idx, root) in self.roots.iter().enumerate() {
|
||||||
context.current_path.push(idx as u8);
|
context.current_path.push(idx as u8);
|
||||||
roots.push(context.update_node::<Ctx>(root, &mut mapping)?);
|
roots.push(context.update_node::<Ctx>(root, &mut mapping)?);
|
||||||
|
|||||||
Reference in new issue
Block a user