1
0
Эх сурвалжийг харах

wip: move everything over to a stack dst

Jonathan Kelley 3 жил өмнө
parent
commit
0e9d5fc530
36 өөрчлөгдсөн 226 нэмэгдсэн , 187 устгасан
  1. 4 4
      examples/borrowed.rs
  2. 1 1
      examples/calculator.rs
  3. 2 2
      examples/framework_benchmark.rs
  4. 1 1
      examples/hello_world.rs
  5. 1 1
      examples/pattern_model.rs
  6. 2 2
      examples/rsx_usage.rs
  7. 1 1
      examples/ssr.rs
  8. 1 1
      examples/todomvc.rs
  9. 1 1
      examples/web_tick.rs
  10. 2 2
      packages/core-macro/src/rsx/body.rs
  11. 5 1
      packages/core/Cargo.toml
  12. 5 5
      packages/core/benches/jsframework.rs
  13. 1 1
      packages/core/examples/alternative.rs
  14. 4 4
      packages/core/examples/borrowed.rs
  15. 2 2
      packages/core/examples/fragment_from_iter.rs
  16. 6 6
      packages/core/examples/jsframework.rs
  17. 5 0
      packages/core/examples/syntax.rs
  18. 1 1
      packages/core/examples/vdom_usage.rs
  19. 6 3
      packages/core/src/component.rs
  20. 1 4
      packages/core/src/context.rs
  21. 10 8
      packages/core/src/hooks.rs
  22. 5 4
      packages/core/src/lib.rs
  23. 47 30
      packages/core/src/nodes.rs
  24. 21 16
      packages/core/src/scope.rs
  25. 18 15
      packages/core/src/test_dom.rs
  26. 21 19
      packages/core/src/virtual_dom.rs
  27. 9 9
      packages/core/tests/borrowedstate.rs
  28. 16 16
      packages/core/tests/create_dom.rs
  29. 2 2
      packages/core/tests/diffing.rs
  30. 4 4
      packages/core/tests/display_vdom.rs
  31. 1 1
      packages/core/tests/lifecycle.rs
  32. 2 2
      packages/core/tests/sharedstate.rs
  33. 13 13
      packages/core/tests/vdom_rebuild.rs
  34. 1 1
      packages/desktop/examples/todomvc.rs
  35. 2 2
      packages/desktop/src/desktop_context.rs
  36. 2 2
      packages/web/examples/basic.rs

+ 4 - 4
examples/borrowed.rs

@@ -20,7 +20,7 @@ fn main() {
     dioxus::desktop::launch(App, |c| c);
 }
 
-fn App((cx, props): Component<()>) -> DomTree {
+fn App((cx, props): Component<()>) -> Element {
     let text: &mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f, |_| {});
 
     let first = text.get_mut(0).unwrap();
@@ -43,7 +43,7 @@ impl<'a> Drop for C1Props<'a> {
     fn drop(&mut self) {}
 }
 
-fn Child1<'a>((cx, props): Component<'a, C1Props>) -> DomTree<'a> {
+fn Child1<'a>((cx, props): Component<'a, C1Props>) -> Element<'a> {
     let (left, right) = props.text.split_once("=").unwrap();
 
     cx.render(rsx! {
@@ -59,7 +59,7 @@ struct C2Props<'a> {
     text: &'a str,
 }
 
-fn Child2<'a>((cx, props): Component<'a, C2Props>) -> DomTree<'a> {
+fn Child2<'a>((cx, props): Component<'a, C2Props>) -> Element<'a> {
     cx.render(rsx! {
         Child3 {
             text: props.text
@@ -72,7 +72,7 @@ struct C3Props<'a> {
     text: &'a str,
 }
 
-fn Child3<'a>((cx, props): Component<'a, C3Props>) -> DomTree<'a> {
+fn Child3<'a>((cx, props): Component<'a, C3Props>) -> Element<'a> {
     cx.render(rsx! {
         div { "{props.text}"}
     })

+ 1 - 1
examples/calculator.rs

@@ -116,7 +116,7 @@ struct CalculatorKeyProps<'a> {
     onclick: &'a dyn Fn(MouseEvent),
 }
 
-fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> DomTree<'a> {
+fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> Element<'a> {
     rsx!(cx, button {
         class: "calculator-key {props.name}"
         onclick: {props.onclick}

+ 2 - 2
examples/framework_benchmark.rs

@@ -80,7 +80,7 @@ struct ActionButtonProps<'a> {
     onclick: &'a dyn Fn(MouseEvent),
 }
 
-fn ActionButton<'a>((cx, props): Component<'a, ActionButtonProps>) -> DomTree<'a> {
+fn ActionButton<'a>((cx, props): Component<'a, ActionButtonProps>) -> Element<'a> {
     rsx!(cx, div { class: "col-sm-6 smallpad"
         button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}",  onclick: {props.onclick},
             "{props.name}"
@@ -93,7 +93,7 @@ struct RowProps {
     row_id: usize,
     label: Rc<str>,
 }
-fn Row((cx, props): Component<RowProps>) -> DomTree {
+fn Row((cx, props): Component<RowProps>) -> Element {
     rsx!(cx, tr {
         td { class:"col-md-1", "{props.row_id}" }
         td { class:"col-md-1", onclick: move |_| { /* run onselect */ }

+ 1 - 1
examples/hello_world.rs

@@ -4,7 +4,7 @@ fn main() {
     dioxus::desktop::launch(App, |c| c);
 }
 
-fn App((cx, props): Component<()>) -> DomTree {
+fn App((cx, props): Component<()>) -> Element {
     cx.render(rsx! (
         div { "Hello, world!" }
     ))

+ 1 - 1
examples/pattern_model.rs

@@ -76,7 +76,7 @@ struct CalculatorKeyProps<'a> {
     onclick: &'a dyn Fn(MouseEvent),
 }
 
-fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> DomTree<'a> {
+fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> Element<'a> {
     cx.render(rsx! {
         button {
             class: "calculator-key {props.name}"

+ 2 - 2
examples/rsx_usage.rs

@@ -184,7 +184,7 @@ mod baller {
     pub struct BallerProps {}
 
     /// This component totally balls
-    pub fn Baller(_: Component<BallerProps>) -> DomTree {
+    pub fn Baller(_: Component<BallerProps>) -> Element {
         todo!()
     }
 }
@@ -195,7 +195,7 @@ pub struct TallerProps {
 }
 
 /// This component is taller than most :)
-pub fn Taller(_: Component<TallerProps>) -> DomTree {
+pub fn Taller(_: Component<TallerProps>) -> Element {
     let b = true;
     todo!()
 }

+ 1 - 1
examples/ssr.rs

@@ -21,6 +21,6 @@ static App: FC<()> = |(cx, props)| {
 struct MyProps<'a> {
     text: &'a str,
 }
-fn App2<'a>(cx: Context<'a>, props: &'a MyProps) -> DomTree<'a> {
+fn App2<'a>(cx: Context<'a>, props: &'a MyProps) -> Element<'a> {
     None
 }

+ 1 - 1
examples/todomvc.rs

@@ -85,7 +85,7 @@ pub struct TodoEntryProps {
     todo: Rc<TodoItem>,
 }
 
-pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> DomTree {
+pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> Element {
     let is_editing = use_state(cx, || false);
     let contents = use_state(cx, || String::from(""));
     let todo = &props.todo;

+ 1 - 1
examples/web_tick.rs

@@ -45,7 +45,7 @@ struct RowProps {
     row_id: usize,
     label: Label,
 }
-fn Row((cx, props): Component<RowProps>) -> DomTree {
+fn Row((cx, props): Component<RowProps>) -> Element {
     let [adj, col, noun] = props.label.0;
     cx.render(rsx! {
         tr {

+ 2 - 2
packages/core-macro/src/rsx/body.rs

@@ -57,11 +57,11 @@ impl ToTokens for CallBody {
             }),
             // Otherwise we just build the LazyNode wrapper
             None => out_tokens.append_all(quote! {
-                dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory|{
+                Some(dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory|{
                     use dioxus_elements::{GlobalAttributes, SvgAttributes};
 
                     #inner
-                 })
+                 }))
             }),
         };
     }

+ 5 - 1
packages/core/Cargo.toml

@@ -22,7 +22,9 @@ longest-increasing-subsequence = "0.1.0"
 # internall used
 log = { version = "0.4", features = ["release_max_level_off"] }
 
-futures-util = { version = "0.3.15", no_default_features = true }
+futures-util = { version = "0.3.15", default-features = false, features = [
+    "std",
+] }
 
 smallvec = "1.6.1"
 
@@ -40,6 +42,8 @@ serde = { version = "1", features = ["derive"], optional = true }
 
 serde_repr = { version = "0.1.7", optional = true }
 
+stack_dst = "0.6.1"
+
 [dev-dependencies]
 anyhow = "1.0.42"
 dioxus-html = { path = "../html" }

+ 5 - 5
packages/core/benches/jsframework.rs

@@ -34,13 +34,13 @@ fn create_rows(c: &mut Criterion) {
                 }
             }
         });
-        cx.render(rsx! {
+        rsx! {
             table {
                 tbody {
                     {rows}
                 }
             }
-        })
+        }
     };
 
     c.bench_function("create rows", |b| {
@@ -57,9 +57,9 @@ struct RowProps {
     row_id: usize,
     label: Label,
 }
-fn Row((cx, props): Component<RowProps>) -> DomTree {
+fn Row((cx, props): Component<RowProps>) -> Element {
     let [adj, col, noun] = props.label.0;
-    cx.render(rsx! {
+    rsx! {
         tr {
             td { class:"col-md-1", "{props.row_id}" }
             td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
@@ -72,7 +72,7 @@ fn Row((cx, props): Component<RowProps>) -> DomTree {
             }
             td { class: "col-md-6" }
         }
-    })
+    }
 }
 
 #[derive(PartialEq)]

+ 1 - 1
packages/core/examples/alternative.rs

@@ -9,7 +9,7 @@ fn main() {
 pub static EXAMPLE: FC<()> = |(cx, _)| {
     let list = (0..10).map(|_f| LazyNodes::new(move |_f| todo!()));
 
-    cx.render(LazyNodes::new(move |cx| {
+    Some(LazyNodes::new(move |cx| {
         cx.raw_element(
             "div",
             None,

+ 4 - 4
packages/core/examples/borrowed.rs

@@ -20,10 +20,10 @@ struct ListItem {
     age: u32,
 }
 
-fn app<'a>(cx: Context<'a>, props: &AppProps) -> DomTree<'a> {
+fn app<'a>(cx: Context<'a>, props: &AppProps) -> Element<'a> {
     // let (val, set_val) = use_state_classic(cx, || 0);
 
-    cx.render(LazyNodes::new(move |_nodecx| {
+    Some(LazyNodes::new(move |_nodecx| {
         todo!()
         // builder::ElementBuilder::new(_nodecx, "div")
         //     .iter_child({
@@ -56,8 +56,8 @@ struct ChildProps {
     item_handler: Rc<dyn Fn(i32)>,
 }
 
-fn ChildItem<'a>(cx: Context<'a>, props: &'a ChildProps) -> DomTree<'a> {
-    cx.render(LazyNodes::new(move |__cx| todo!()))
+fn ChildItem<'a>(cx: Context<'a>, props: &'a ChildProps) -> Element<'a> {
+    Some(LazyNodes::new(move |__cx| todo!()))
 }
 
 impl PartialEq for ChildProps {

+ 2 - 2
packages/core/examples/fragment_from_iter.rs

@@ -2,7 +2,7 @@ use dioxus_core::prelude::*;
 
 fn main() {}
 
-fn app<'a>(cx: Context<'a>, props: &()) -> DomTree<'a> {
+fn app<'a>(cx: Context<'a>, props: &()) -> Element<'a> {
     let vak = use_suspense(
         cx,
         || async {},
@@ -26,7 +26,7 @@ fn app<'a>(cx: Context<'a>, props: &()) -> DomTree<'a> {
         )
     }));
 
-    cx.render(LazyNodes::new(move |f| {
+    Some(LazyNodes::new(move |f| {
         f.raw_element(
             "div",
             None,

+ 6 - 6
packages/core/examples/jsframework.rs

@@ -15,7 +15,7 @@ fn main() {
     assert!(g.edits.len() > 1);
 }
 
-fn App((cx, props): Component<()>) -> DomTree {
+fn App((cx, props): Component<()>) -> Element {
     let mut rng = SmallRng::from_entropy();
     let rows = (0..10_000_usize).map(|f| {
         let label = Label::new(&mut rng);
@@ -26,13 +26,13 @@ fn App((cx, props): Component<()>) -> DomTree {
             }
         }
     });
-    cx.render(rsx! {
+    rsx! {
         table {
             tbody {
                 {rows}
             }
         }
-    })
+    }
 }
 
 #[derive(PartialEq, Props)]
@@ -41,11 +41,11 @@ struct RowProps {
     label: Label,
 }
 
-fn Row((cx, props): Component<RowProps>) -> DomTree {
+fn Row((cx, props): Component<RowProps>) -> Element {
     let handler = move |evt: MouseEvent| {
         let g = evt.button;
     };
-    cx.render(rsx! {
+    rsx! {
         tr {
             td { class:"col-md-1", "{props.row_id}" }
             td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
@@ -58,7 +58,7 @@ fn Row((cx, props): Component<RowProps>) -> DomTree {
             }
             td { class: "col-md-6" }
         }
-    })
+    }
 }
 
 #[derive(PartialEq)]

+ 5 - 0
packages/core/examples/syntax.rs

@@ -32,3 +32,8 @@ fn html_usage() {
         }
     };
 }
+
+static App: FC<()> = |(cx, props)| {
+    //
+    rsx!(div {})
+};

+ 1 - 1
packages/core/examples/vdom_usage.rs

@@ -4,7 +4,7 @@ use dioxus_core::prelude::*;
 
 #[async_std::main]
 async fn main() {
-    static App: FC<()> = |(cx, props)| cx.render(LazyNodes::new(|f| f.text(format_args!("hello"))));
+    static App: FC<()> = |(cx, props)| Some(LazyNodes::new(|f| f.text(format_args!("hello"))));
 
     let mut dom = VirtualDom::new(App);
 

+ 6 - 3
packages/core/src/component.rs

@@ -5,7 +5,10 @@
 //! if the type supports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
 //! that ensures compile-time required and optional fields on cx.
 
-use crate::innerlude::{Context, DomTree, LazyNodes, FC};
+use crate::{
+    innerlude::{Context, Element, LazyNodes, FC},
+    VNode,
+};
 
 /// A component is a wrapper around a Context and some Props that share a lifetime
 ///
@@ -63,8 +66,8 @@ pub type Component<'a, T> = (Context<'a>, &'a T);
 /// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
 ///
 #[allow(non_upper_case_globals, non_snake_case)]
-pub fn Fragment((cx, _): Component<()>) -> DomTree {
-    cx.render(LazyNodes::new(|f| f.fragment_from_iter(cx.children())))
+pub fn Fragment((cx, _): Component<()>) -> Element {
+    Some(LazyNodes::new(|f| f.fragment_from_iter(cx.children())))
 }
 
 /// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus

+ 1 - 4
packages/core/src/context.rs

@@ -137,10 +137,7 @@ impl<'src> Context<'src> {
     ///     cx.render(lazy_tree)
     /// }
     ///```
-    pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
-        self,
-        lazy_nodes: LazyNodes<'src, F>,
-    ) -> DomTree<'src> {
+    pub fn render(self, lazy_nodes: LazyNodes<'src>) -> Option<VNode<'src>> {
         let bump = &self.scope.frames.wip_frame().bump;
         Some(lazy_nodes.into_vnode(NodeFactory { bump }))
     }

+ 10 - 8
packages/core/src/hooks.rs

@@ -93,11 +93,11 @@ pub fn use_suspense<'src, Out, Fut, Cb>(
     cx: Context<'src>,
     task_initializer: impl FnOnce() -> Fut,
     user_callback: Cb,
-) -> DomTree<'src>
+) -> Element<'src>
 where
     Fut: Future<Output = Out> + 'static,
     Out: 'static,
-    Cb: for<'a> Fn(SuspendedContext<'a>, &Out) -> DomTree<'a> + 'static,
+    Cb: for<'a> Fn(SuspendedContext<'a>, &Out) -> Element<'a> + 'static,
 {
     /*
     General strategy:
@@ -135,12 +135,12 @@ where
             None => {
                 let value = hook.value.clone();
 
-                cx.render(LazyNodes::new(|f| {
+                Some(LazyNodes::new(|f| {
                     let bump = f.bump();
 
                     use bumpalo::boxed::Box as BumpBox;
 
-                    let f: &mut dyn FnMut(SuspendedContext<'src>) -> DomTree<'src> =
+                    let f: &mut dyn FnMut(SuspendedContext<'src>) -> Element<'src> =
                         bump.alloc(move |sus| {
                             let val = value.borrow();
 
@@ -177,12 +177,14 @@ pub struct SuspendedContext<'a> {
 }
 
 impl<'src> SuspendedContext<'src> {
-    pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
+    pub fn render(
+        // pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
         self,
-        lazy_nodes: LazyNodes<'src, F>,
-    ) -> DomTree<'src> {
+        lazy_nodes: LazyNodes<'src>,
+    ) -> Element<'src> {
         let bump = &self.inner.scope.frames.wip_frame().bump;
-        Some(lazy_nodes.into_vnode(NodeFactory { bump }))
+        todo!("suspense")
+        // Some(lazy_nodes.into_vnode(NodeFactory { bump }))
     }
 }
 

+ 5 - 4
packages/core/src/lib.rs

@@ -56,12 +56,13 @@ pub(crate) mod innerlude {
     pub use crate::util::*;
     pub use crate::virtual_dom::*;
 
-    pub type DomTree<'a> = Option<VNode<'a>>;
-    pub type FC<P> = for<'a> fn(Component<'a, P>) -> DomTree<'a>;
+    // pub type Element<'a> = Option<VNode<'a>>;
+    pub type Element<'a> = Option<LazyNodes<'a>>;
+    pub type FC<P> = for<'a> fn(Component<'a, P>) -> Element<'a>;
 }
 
 pub use crate::innerlude::{
-    Context, DioxusElement, DomEdit, DomTree, ElementId, EventPriority, LazyNodes, MountType,
+    Context, DioxusElement, DomEdit, Element, ElementId, EventPriority, LazyNodes, MountType,
     Mutations, NodeFactory, Properties, SchedulerMsg, ScopeId, SuspendedContext, TaskHandle,
     TestDom, ThreadsafeVirtualDom, UserEvent, VNode, VirtualDom, FC,
 };
@@ -70,7 +71,7 @@ pub mod prelude {
     pub use crate::component::{fc_to_builder, Component, Fragment, Properties};
     pub use crate::context::Context;
     pub use crate::hooks::*;
-    pub use crate::innerlude::{DioxusElement, DomTree, LazyNodes, Mutations, NodeFactory, FC};
+    pub use crate::innerlude::{DioxusElement, Element, LazyNodes, Mutations, NodeFactory, FC};
     pub use crate::nodes::VNode;
     pub use crate::VirtualDom;
 }

+ 47 - 30
packages/core/src/nodes.rs

@@ -4,7 +4,7 @@
 //! cheap and *very* fast to construct - building a full tree should be quick.
 
 use crate::innerlude::{
-    empty_cell, Context, DomTree, ElementId, Properties, Scope, ScopeId, SuspendedContext, FC,
+    empty_cell, Context, Element, ElementId, Properties, Scope, ScopeId, SuspendedContext, FC,
 };
 use bumpalo::{boxed::Box as BumpBox, Bump};
 use std::{
@@ -13,6 +13,10 @@ use std::{
     marker::PhantomData,
 };
 
+use stack_dst::Value as StackDST;
+
+pub type LazyNodeFactory<'a> = StackDST<dyn FnOnce(NodeFactory<'a>) -> VNode<'a>>;
+
 /// A composable "VirtualNode" to declare a User Interface in the Dioxus VirtualDOM.
 ///
 /// VNodes are designed to be lightweight and used with with a bump allocator. To create a VNode, you can use either of:
@@ -287,7 +291,7 @@ pub struct VComponent<'src> {
     // Function pointer to the FC that was used to generate this component
     pub user_fc: *const (),
 
-    pub(crate) caller: &'src dyn for<'b> Fn(&'b Scope) -> DomTree<'b>,
+    pub(crate) caller: &'src dyn for<'b> Fn(&'b Scope) -> Element<'b>,
 
     pub(crate) children: &'src [VNode<'src>],
 
@@ -306,7 +310,7 @@ pub struct VSuspended<'a> {
     pub dom_id: Cell<Option<ElementId>>,
 
     #[allow(clippy::type_complexity)]
-    pub callback: RefCell<Option<BumpBox<'a, dyn FnMut(SuspendedContext<'a>) -> DomTree<'a>>>>,
+    pub callback: RefCell<Option<BumpBox<'a, dyn FnMut(SuspendedContext<'a>) -> Element<'a>>>>,
 }
 
 /// This struct provides an ergonomic API to quickly build VNodes.
@@ -328,9 +332,10 @@ impl<'a> NodeFactory<'a> {
         self.bump
     }
 
-    pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a, F>) -> DomTree<'a>
-    where
-        F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+    pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a>) -> Option<VNode<'a>>
+// pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a, F>) -> Element<'a>
+    // where
+    //     F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
     {
         Some(lazy_nodes.into_vnode(NodeFactory { bump: self.bump }))
     }
@@ -526,11 +531,11 @@ impl<'a> NodeFactory<'a> {
 
         let key = key.map(|f| self.raw_text(f).0);
 
-        let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> DomTree<'b> =
-            bump.alloc(move |scope: &Scope| -> DomTree {
+        let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> Element<'b> =
+            bump.alloc(move |scope: &Scope| -> Element {
                 log::debug!("calling component renderr {:?}", scope.our_arena_idx);
                 let props: &'_ P = unsafe { &*(raw_props as *const P) };
-                let res = component((Context { scope }, props));
+                let res: Element = component((Context { scope }, props));
                 unsafe { std::mem::transmute(res) }
             });
 
@@ -691,40 +696,43 @@ impl<'a> IntoVNode<'a> for VNode<'a> {
 /// ```rust
 /// LazyNodes::new(|f| f.element("div", [], [], [] None))
 /// ```
-pub struct LazyNodes<'a, G>
-where
-    G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
-{
-    inner: G,
-    _p: PhantomData<&'a ()>,
+pub struct LazyNodes<'a> {
+    inner: LazyNodeFactory<'a>,
 }
+// where
+//     G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
 
-impl<'a, G> LazyNodes<'a, G>
-where
-    G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+impl<'a> LazyNodes<'a>
+// where
+//     G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
 {
-    pub fn new(f: G) -> Self {
-        Self {
-            inner: f,
-            _p: PhantomData {},
-        }
+    pub fn new(f: impl FnOnce(NodeFactory<'a>) -> VNode<'a>) -> Self {
+        todo!()
+        // pub fn new<G: FnOnce(NodeFactory<'a>) -> VNode<'a>>(f: G) -> Self {
+        // let inner = LazyNodeFactory::new(f);
+        // Self { inner: f }
     }
 }
 
 // Our blanket impl
-impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G>
-where
-    G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+impl<'a> IntoVNode<'a> for LazyNodes<'a>
+// where
+//     G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
 {
     fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
-        (self.inner)(cx)
+        // let f = self.inner;
+        todo!("manually drop here")
+        // (self.inner)(cx)
     }
 }
 
 // Our blanket impl
-impl<'a, G> IntoIterator for LazyNodes<'a, G>
-where
-    G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+impl<'a> IntoIterator for LazyNodes<'a>
+// where
+//     G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+// impl<'a, G> IntoIterator for LazyNodes<'a, G>
+// where
+//     G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
 {
     type Item = Self;
     type IntoIter = std::iter::Once<Self::Item>;
@@ -756,6 +764,15 @@ impl<'a> IntoVNode<'a> for Option<VNode<'a>> {
     }
 }
 
+impl<'a> IntoVNode<'a> for Option<LazyNodes<'a>> {
+    fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
+        match self {
+            Some(n) => n.into_vnode(cx),
+            None => cx.fragment_from_iter(None as Option<VNode>),
+        }
+    }
+}
+
 impl IntoVNode<'_> for &'static str {
     fn into_vnode(self, cx: NodeFactory) -> VNode {
         cx.static_text(self)

+ 21 - 16
packages/core/src/scope.rs

@@ -28,7 +28,7 @@ pub struct Scope {
 
     // Nodes
     pub(crate) frames: ActiveFrame,
-    pub(crate) caller: *const dyn for<'b> Fn(&'b Scope) -> DomTree<'b>,
+    pub(crate) caller: *const dyn for<'b> Fn(&'b Scope) -> Element<'b>,
     pub(crate) child_nodes: ScopeChildren<'static>,
 
     /*
@@ -176,7 +176,7 @@ impl Scope {
     // Scopes cannot be made anywhere else except for this file
     // Therefore, their lifetimes are connected exclusively to the virtual dom
     pub(crate) fn new(
-        caller: &dyn for<'b> Fn(&'b Scope) -> DomTree<'b>,
+        caller: &dyn for<'b> Fn(&'b Scope) -> Element<'b>,
         our_arena_idx: ScopeId,
         parent_idx: Option<ScopeId>,
         height: u32,
@@ -217,7 +217,7 @@ impl Scope {
 
     pub(crate) fn update_scope_dependencies<'creator_node>(
         &mut self,
-        caller: &'creator_node dyn for<'b> Fn(&'b Scope) -> DomTree<'b>,
+        caller: &'creator_node dyn for<'b> Fn(&'b Scope) -> Element<'b>,
         child_nodes: ScopeChildren,
     ) {
         log::debug!("Updating scope dependencies {:?}", self.our_arena_idx);
@@ -317,7 +317,7 @@ impl Scope {
 
             let mut cb = sus.callback.borrow_mut().take().unwrap();
 
-            let new_node: DomTree<'a> = (cb)(cx);
+            let new_node: Element<'a> = (cb)(cx);
         }
     }
 
@@ -350,20 +350,25 @@ impl Scope {
         log::debug!("Borrowed stuff is successfully cleared");
 
         // Cast the caller ptr from static to one with our own reference
-        let render: &dyn for<'b> Fn(&'b Scope) -> DomTree<'b> = unsafe { &*self.caller };
+        let render: &dyn for<'b> Fn(&'b Scope) -> Element<'b> = unsafe { &*self.caller };
 
         // Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
-        if let Some(new_head) = render(self) {
-            log::debug!("Render is successful");
-
-            // the user's component succeeded. We can safely cycle to the next frame
-            self.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) };
-            self.frames.cycle_frame();
-
-            true
-        } else {
-            false
-        }
+        //
+        todo!()
+        // if let Some(builder) = render(self) {
+        //     let new_head = builder.into_vnode(NodeFactory {
+        //         bump: &self.frames.wip_frame().bump,
+        //     });
+        //     log::debug!("Render is successful");
+
+        //     // the user's component succeeded. We can safely cycle to the next frame
+        //     self.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) };
+        //     self.frames.cycle_frame();
+
+        //     true
+        // } else {
+        //     false
+        // }
     }
 }
 

+ 18 - 15
packages/core/src/test_dom.rs

@@ -21,16 +21,16 @@ impl TestDom {
         NodeFactory::new(&self.bump)
     }
 
-    pub fn render_direct<'a, F>(&'a self, lazy_nodes: LazyNodes<'a, F>) -> VNode<'a>
-    where
-        F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+    pub fn render_direct<'a>(&'a self, lazy_nodes: Element<'a>) -> VNode<'a>
+// where
+    //     F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
     {
         lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
     }
 
-    pub fn render<'a, F>(&'a self, lazy_nodes: LazyNodes<'a, F>) -> &'a VNode<'a>
-    where
-        F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+    pub fn render<'a>(&'a self, lazy_nodes: Element<'a>) -> &'a VNode<'a>
+// where
+    //     F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
     {
         self.bump
             .alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump)))
@@ -43,9 +43,10 @@ impl TestDom {
         machine.mutations
     }
 
-    pub fn create<'a, F1>(&'a self, left: LazyNodes<'a, F1>) -> Mutations<'a>
-    where
-        F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+    pub fn create<'a>(&'a self, left: Element<'a>) -> Mutations<'a>
+// pub fn create<'a, F1>(&'a self, left: LazyNodes<'a, F1>) -> Mutations<'a>
+    // where
+    //     F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
     {
         let old = self.bump.alloc(self.render_direct(left));
 
@@ -58,14 +59,16 @@ impl TestDom {
         machine.mutations
     }
 
-    pub fn lazy_diff<'a, F1, F2>(
+    pub fn lazy_diff<'a>(
         &'a self,
-        left: LazyNodes<'a, F1>,
-        right: LazyNodes<'a, F2>,
+        left: Element<'a>,
+        right: Element<'a>,
+        // left: LazyNodes<'a, F1>,
+        // right: LazyNodes<'a, F2>,
     ) -> (Mutations<'a>, Mutations<'a>)
-    where
-        F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
-        F2: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+// where
+    //     F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
+    //     F2: FnOnce(NodeFactory<'a>) -> VNode<'a>,
     {
         let (old, new) = (self.render(left), self.render(right));
 

+ 21 - 19
packages/core/src/virtual_dom.rs

@@ -143,7 +143,7 @@ impl VirtualDom {
 
         let _p = root_props.clone();
         // Safety: this callback is only valid for the lifetime of the root props
-        let root_caller: Rc<dyn Fn(&Scope) -> DomTree> = Rc::new(move |scope: &Scope| unsafe {
+        let root_caller: Rc<dyn Fn(&Scope) -> Element> = Rc::new(move |scope: &Scope| unsafe {
             let props = _p.downcast_ref::<P>().unwrap();
             std::mem::transmute(root((Context { scope }, props)))
         });
@@ -219,7 +219,7 @@ impl VirtualDom {
 
             let root = *self.root_fc.downcast_ref::<FC<P>>().unwrap();
 
-            let root_caller: Box<dyn Fn(&Scope) -> DomTree> =
+            let root_caller: Box<dyn Fn(&Scope) -> Element> =
                 Box::new(move |scope: &Scope| unsafe {
                     let props: &'_ P = &*(props_ptr as *const P);
                     std::mem::transmute(root((Context { scope }, props)))
@@ -368,22 +368,24 @@ impl VirtualDom {
         use futures_util::StreamExt;
 
         // Wait for any new events if we have nothing to do
-        futures_util::select! {
-            _ = self.scheduler.async_tasks.next() => {}
-            msg = self.scheduler.receiver.next() => {
-                match msg.unwrap() {
-                    SchedulerMsg::Task(t) => {
-                        self.scheduler.handle_task(t);
-                    },
-                    SchedulerMsg::Immediate(im) => {
-                        self.scheduler.dirty_scopes.insert(im);
-                    }
-                    SchedulerMsg::UiEvent(evt) => {
-                        self.scheduler.ui_events.push_back(evt);
-                    }
-                }
-            },
-        }
+        todo!("wait for work without select macro")
+
+        // futures_util::select! {
+        //     _ = self.scheduler.async_tasks.next() => {}
+        //     msg = self.scheduler.receiver.next() => {
+        //         match msg.unwrap() {
+        //             SchedulerMsg::Task(t) => {
+        //                 self.scheduler.handle_task(t);
+        //             },
+        //             SchedulerMsg::Immediate(im) => {
+        //                 self.scheduler.dirty_scopes.insert(im);
+        //             }
+        //             SchedulerMsg::UiEvent(evt) => {
+        //                 self.scheduler.ui_events.push_back(evt);
+        //             }
+        //         }
+        //     },
+        // }
     }
 }
 
@@ -408,4 +410,4 @@ impl std::fmt::Display for VirtualDom {
 }
 
 // we never actually use the contents of this root caller
-struct RootCaller(Rc<dyn for<'b> Fn(&'b Scope) -> DomTree<'b> + 'static>);
+struct RootCaller(Rc<dyn for<'b> Fn(&'b Scope) -> Element<'b> + 'static>);

+ 9 - 9
packages/core/tests/borrowedstate.rs

@@ -10,17 +10,17 @@ fn test_borrowed_state() {
     let _ = VirtualDom::new(Parent);
 }
 
-fn Parent((cx, _): Component<()>) -> DomTree {
+fn Parent((cx, _): Component<()>) -> Element {
     let value = cx.use_hook(|_| String::new(), |f| &*f, |_| {});
 
-    cx.render(rsx! {
+    rsx! {
         div {
             Child { name: value }
             Child { name: value }
             Child { name: value }
             Child { name: value }
         }
-    })
+    }
 }
 
 #[derive(Props)]
@@ -28,13 +28,13 @@ struct ChildProps<'a> {
     name: &'a str,
 }
 
-fn Child<'a>((cx, props): Component<'a, ChildProps>) -> DomTree<'a> {
-    cx.render(rsx! {
+fn Child<'a>((cx, props): Component<'a, ChildProps>) -> Element<'a> {
+    rsx! {
         div {
             h1 { "it's nested" }
             Child2 { name: props.name }
         }
-    })
+    }
 }
 
 #[derive(Props)]
@@ -42,8 +42,8 @@ struct Grandchild<'a> {
     name: &'a str,
 }
 
-fn Child2<'a>((cx, props): Component<'a, Grandchild>) -> DomTree<'a> {
-    cx.render(rsx! {
+fn Child2<'a>((cx, props): Component<'a, Grandchild>) -> Element<'a> {
+    rsx! {
         div { "Hello {props.name}!" }
-    })
+    }
 }

+ 16 - 16
packages/core/tests/create_dom.rs

@@ -22,13 +22,13 @@ fn new_dom<P: 'static + Send>(app: FC<P>, props: P) -> VirtualDom {
 #[test]
 fn test_original_diff() {
     static APP: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             div {
                 div {
                     "Hello, world!"
                 }
             }
-        })
+        }
     };
 
     let mut dom = new_dom(APP, ());
@@ -58,7 +58,7 @@ fn test_original_diff() {
 #[test]
 fn create() {
     static APP: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             div {
                 div {
                     "Hello, world!"
@@ -72,7 +72,7 @@ fn create() {
                     }
                 }
             }
-        })
+        }
     };
 
     let mut dom = new_dom(APP, ());
@@ -121,11 +121,11 @@ fn create() {
 #[test]
 fn create_list() {
     static APP: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             {(0..3).map(|f| rsx!{ div {
                 "hello"
             }})}
-        })
+        }
     };
 
     let mut dom = new_dom(APP, ());
@@ -170,12 +170,12 @@ fn create_list() {
 #[test]
 fn create_simple() {
     static APP: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             div {}
             div {}
             div {}
             div {}
-        })
+        }
     };
 
     let mut dom = new_dom(APP, ());
@@ -208,19 +208,19 @@ fn create_simple() {
 #[test]
 fn create_components() {
     static App: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             Child { "abc1" }
             Child { "abc2" }
             Child { "abc3" }
-        })
+        }
     };
 
     static Child: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             h1 {}
             div { {cx.children()} }
             p {}
-        })
+        }
     };
 
     let mut dom = new_dom(App, ());
@@ -269,10 +269,10 @@ fn create_components() {
 #[test]
 fn anchors() {
     static App: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             {true.then(|| rsx!{ div { "hello" } })}
             {false.then(|| rsx!{ div { "goodbye" } })}
-        })
+        }
     };
 
     let mut dom = new_dom(App, ());
@@ -303,9 +303,9 @@ fn suspended() {
             || async {
                 //
             },
-            |cx, p| cx.render(rsx! { "hi "}),
+            |cx, p| rsx! { "hi "},
         );
-        cx.render(rsx! { {val} })
+        rsx! { {val} }
     };
 
     let mut dom = new_dom(App, ());

+ 2 - 2
packages/core/tests/diffing.rs

@@ -807,14 +807,14 @@ fn controlled_keyed_diffing_out_of_order_max_test() {
 fn suspense() {
     let dom = new_dom();
 
-    let edits = dom.create(LazyNodes::new(|f| {
+    let edits = dom.create(Some(LazyNodes::new(|f| {
         use std::cell::{Cell, RefCell};
         VNode::Suspended(f.bump().alloc(VSuspended {
             task_id: 0,
             callback: RefCell::new(None),
             dom_id: Cell::new(None),
         }))
-    }));
+    })));
     assert_eq!(
         edits.edits,
         [CreatePlaceholder { root: 0 }, AppendChildren { many: 1 }]

+ 4 - 4
packages/core/tests/display_vdom.rs

@@ -14,7 +14,7 @@ mod test_logging;
 #[test]
 fn please_work() {
     static App: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             div {
                 hidden: "true"
                 "hello"
@@ -24,13 +24,13 @@ fn please_work() {
                 Child {}
             }
             div { "hello" }
-        })
+        }
     };
 
     static Child: FC<()> = |(cx, props)| {
-        cx.render(rsx! {
+        rsx! {
             div { "child" }
-        })
+        }
     };
 
     let mut dom = VirtualDom::new(App);

+ 1 - 1
packages/core/tests/lifecycle.rs

@@ -22,7 +22,7 @@ fn manual_diffing() {
 
     static App: FC<AppProps> = |(cx, props)| {
         let val = props.value.lock().unwrap();
-        cx.render(rsx! { div { "{val}" } })
+        rsx! { div { "{val}" } }
     };
 
     let value = Arc::new(Mutex::new("Hello"));

+ 2 - 2
packages/core/tests/sharedstate.rs

@@ -15,12 +15,12 @@ fn shared_state_test() {
 
     static App: FC<()> = |(cx, props)| {
         cx.provide_state(MySharedState("world!"));
-        rsx!(cx, Child {})
+        rsx!(Child {})
     };
 
     static Child: FC<()> = |(cx, props)| {
         let shared = cx.consume_state::<MySharedState>()?;
-        rsx!(cx, "Hello, {shared.0}")
+        rsx!("Hello, {shared.0}")
     };
 
     let mut dom = VirtualDom::new(App);

+ 13 - 13
packages/core/tests/vdom_rebuild.rs

@@ -19,7 +19,7 @@ use dioxus_html as dioxus_elements;
 fn app_runs() {
     static App: FC<()> = |(cx, props)| {
         //
-        cx.render(rsx!( div{"hello"} ))
+        rsx!( div{"hello"} )
     };
     let mut vdom = VirtualDom::new(App);
     let edits = vdom.rebuild();
@@ -29,10 +29,10 @@ fn app_runs() {
 #[test]
 fn fragments_work() {
     static App: FC<()> = |(cx, props)| {
-        cx.render(rsx!(
+        rsx!(
             div{"hello"}
             div{"goodbye"}
-        ))
+        )
     };
     let mut vdom = VirtualDom::new(App);
     let edits = vdom.rebuild();
@@ -43,10 +43,10 @@ fn fragments_work() {
 #[test]
 fn lists_work() {
     static App: FC<()> = |(cx, props)| {
-        cx.render(rsx!(
+        rsx!(
             h1 {"hello"}
             {(0..6).map(|f| rsx!(span{ "{f}" }))}
-        ))
+        )
     };
     let mut vdom = VirtualDom::new(App);
     let edits = vdom.rebuild();
@@ -56,11 +56,11 @@ fn lists_work() {
 #[test]
 fn conditional_rendering() {
     static App: FC<()> = |(cx, props)| {
-        cx.render(rsx!(
+        rsx!(
             h1 {"hello"}
             {true.then(|| rsx!(span{ "a" }))}
             {false.then(|| rsx!(span{ "b" }))}
-        ))
+        )
     };
     let mut vdom = VirtualDom::new(App);
 
@@ -73,16 +73,16 @@ fn conditional_rendering() {
 #[test]
 fn child_components() {
     static App: FC<()> = |(cx, props)| {
-        cx.render(rsx!(
+        rsx!(
             {true.then(|| rsx!(Child { }))}
             {false.then(|| rsx!(Child { }))}
-        ))
+        )
     };
     static Child: FC<()> = |(cx, props)| {
-        cx.render(rsx!(
+        rsx!(
             h1 {"hello"}
             h1 {"goodbye"}
-        ))
+        )
     };
     let mut vdom = VirtualDom::new(App);
     let edits = vdom.rebuild();
@@ -92,8 +92,8 @@ fn child_components() {
 #[test]
 fn suspended_works() {
     static App: FC<()> = |(cx, props)| {
-        let title = use_suspense(cx, || async { "bob" }, |cx, f| cx.render(rsx! { "{f}"}));
-        cx.render(rsx!("hello" { title }))
+        let title = use_suspense(cx, || async { "bob" }, |cx, f| rsx! { "{f}"});
+        rsx!("hello" { title })
     };
 
     let mut vdom = VirtualDom::new(App);

+ 1 - 1
packages/desktop/examples/todomvc.rs

@@ -136,7 +136,7 @@ pub struct TodoEntryProps {
     id: u32,
 }
 
-pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> DomTree {
+pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> Element {
     let todos = use_shared_state::<Todos>(cx)?;
 
     let _todos = todos.read();

+ 2 - 2
packages/desktop/src/desktop_context.rs

@@ -2,7 +2,7 @@ use std::cell::RefCell;
 
 use dioxus::prelude::Component;
 use dioxus_core as dioxus;
-use dioxus_core::{Context, DomTree, LazyNodes, NodeFactory, Properties};
+use dioxus_core::{Context, Element, LazyNodes, NodeFactory, Properties};
 use dioxus_core_macro::Props;
 
 /*
@@ -54,7 +54,7 @@ pub struct WebviewWindowProps<'a> {
 ///
 ///
 ///
-pub fn WebviewWindow<'a>((cx, props): Component<'a, WebviewWindowProps>) -> DomTree<'a> {
+pub fn WebviewWindow<'a>((cx, props): Component<'a, WebviewWindowProps>) -> Element<'a> {
     let dtcx = cx.consume_state::<RefCell<DesktopContext>>()?;
 
     cx.use_hook(

+ 2 - 2
packages/web/examples/basic.rs

@@ -68,13 +68,13 @@ static APP: FC<()> = |(cx, _)| {
     })
 };
 
-fn render_bullets(cx: Context) -> DomTree {
+fn render_bullets(cx: Context) -> Element {
     rsx!(cx, div {
         "bite me"
     })
 }
 
-fn render_list(cx: Context, count: usize) -> DomTree {
+fn render_list(cx: Context, count: usize) -> Element {
     let items = (0..count).map(|f| {
         rsx! {
             li { "a - {f}" }