From 14b3fa72e46537b7783ff9b72246ab8e1325bb62 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Sun, 15 Oct 2023 17:40:56 -0700 Subject: [PATCH] Change the semantics of exprs/for loops allocations strategy This commit adjusts how exprs and for loops are handled within rsx. This is a breaking change in terms of codegen, but has slight semantic changes as well. Now, when exprs/for loops are allocated, they are given a temporary. The temporary is elided to the <'a> lifetime of the bump, to satisfy the borrow checker. This fixes issues with signals where exprs/for loops mapping vecs out of RefCells would be caught up without a temporary lifetime. --- examples/signals.rs | 11 +++++++++++ packages/rsx/src/node.rs | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/examples/signals.rs b/examples/signals.rs index bc627fa8f..09c184d47 100644 --- a/examples/signals.rs +++ b/examples/signals.rs @@ -7,6 +7,7 @@ fn main() { fn app(cx: Scope) -> Element { let mut count = dioxus_signals::use_signal(cx, || 0); + let saved_values = dioxus_signals::use_signal(cx, || vec![0]); use_future!(cx, || async move { loop { @@ -19,9 +20,19 @@ fn app(cx: Scope) -> Element { h1 { "High-Five counter: {count}" } button { onclick: move |_| count += 1, "Up high!" } button { onclick: move |_| count -= 1, "Down low!" } + button { + onclick: move |_| saved_values.push(count.value()), + "Save this value" + } + // We can do boolean operations on the current signal value if count.value() > 5 { rsx!{ h2 { "High five!" } } } + + // We can cleanly map signals with iterators + for value in saved_values.read().iter() { + h3 { "Saved value: {value}" } + } }) } diff --git a/packages/rsx/src/node.rs b/packages/rsx/src/node.rs index 1bda081d9..9c2f7b330 100644 --- a/packages/rsx/src/node.rs +++ b/packages/rsx/src/node.rs @@ -125,7 +125,11 @@ impl ToTokens for BodyNode { __cx.text_node(#txt) }), BodyNode::RawExpr(exp) => tokens.append_all(quote! { - __cx.make_node(#exp) + { + use ::dioxus::core::IntoDynNode; + let ___nodes =(#exp).into_vnode(__cx); + ___nodes + } }), BodyNode::ForLoop(exp) => { let ForLoop { @@ -137,10 +141,15 @@ impl ToTokens for BodyNode { location: None, }; + // Signals expose an issue with temporary lifetimes + // We need to directly render out the nodes first to collapse their lifetime to <'a> + // And then we can return them into the dyn loop tokens.append_all(quote! { - __cx.make_node( - (#expr).into_iter().map(|#pat| { #renderer }) - ) + { + use ::dioxus::core::IntoDynNode; + let ___nodes =(#expr).into_iter().map(|#pat| { #renderer }).into_vnode(__cx); + ___nodes + } }) } BodyNode::IfChain(chain) => {