Ver código fonte

wip: implement lazy nodes properly

Jonathan Kelley 3 anos atrás
pai
commit
3e07214

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

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

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

@@ -4,7 +4,7 @@ use std::marker::PhantomData;
 
 use dioxus::component::Scope;
 use dioxus::events::on::MouseEvent;
-use dioxus::nodes::{annotate_lazy, IntoVNode, VComponent, VFragment, VText};
+use dioxus::nodes::{IntoVNode, VComponent, VFragment, VText};
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
 use dioxus_core_macro::*;

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

@@ -1,11 +1,11 @@
 use std::time::Duration;
 
-use dioxus_core::prelude::*;
+use dioxus_core::{lazynodes::LazyNodes, prelude::*};
 
 // #[async_std::main]
 fn main() {
     static App: FC<()> =
-        |(cx, props)| cx.render(Some(Box::new(move |f| f.text(format_args!("hello")))));
+        |(cx, props)| cx.render(Some(LazyNodes::new(move |f| f.text(format_args!("hello")))));
 
     let mut dom = VirtualDom::new(App);
 

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

@@ -6,7 +6,7 @@
 
 use bumpalo::Bump;
 
-use crate::innerlude::*;
+use crate::{innerlude::*, lazynodes::LazyNodes};
 use std::{any::TypeId, ops::Deref, rc::Rc};
 
 /// Components in Dioxus use the "Context" object to interact with their lifecycle.
@@ -103,11 +103,12 @@ impl<'src> Context<'src> {
     ///```
     pub fn render(
         self,
-        lazy_nodes: Option<Box<dyn FnOnce(NodeFactory<'src>) -> VNode<'src> + '_>>,
+        lazy_nodes: Option<LazyNodes<'src, '_>>,
+        // lazy_nodes: Option<Box<dyn FnOnce(NodeFactory<'src>) -> VNode<'src> + '_>>,
     ) -> Option<VNode<'src>> {
         let bump = &self.scope.frames.wip_frame().bump;
         let factory = NodeFactory { bump };
-        lazy_nodes.map(|f| f(factory))
+        lazy_nodes.map(|f| f.call(factory))
     }
 
     /// `submit_task` will submit the future to be polled.

+ 22 - 14
packages/core/src/lazynodes.rs

@@ -26,29 +26,37 @@ use crate::innerlude::{IntoVNode, NodeFactory, VNode};
 /// ```rust
 /// LazyNodes::new(|f| f.element("div", [], [], [] None))
 /// ```
-// pub struct LazyNodes<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> {
-//     inner: Box<F>,
-//     _p: PhantomData<&'a ()>,
-//     // inner: StackNodeStorage<'a>,
-//     // inner: StackNodeStorage<'a>,
-// }
-// pub type LazyNodes<'b> = Box<dyn for<'a> FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b>;
+pub struct LazyNodes<'a, 'b> {
+    inner: StackNodeStorage<'a, 'b>,
+}
 
-// pub fn to_lazy_nodes<'b>(
-//     f: impl for<'a> FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b,
-// ) -> Option<LazyNodes<'b>> {
-//     Some(Box::new(f))
-// }
+impl<'a, 'b> LazyNodes<'a, 'b> {
+    pub fn new<F>(f: F) -> Self
+    where
+        F: FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b,
+    {
+        Self {
+            inner: StackNodeStorage::Heap(Box::new(f)),
+        }
+    }
+
+    pub fn call(self, f: NodeFactory<'a>) -> VNode<'a> {
+        match self.inner {
+            StackNodeStorage::Heap(lazy) => lazy(f),
+            _ => todo!(),
+        }
+    }
+}
 
 type StackHeapSize = [usize; 12];
 
-enum StackNodeStorage<'a> {
+enum StackNodeStorage<'a, 'b> {
     Stack {
         next_ofs: usize,
         buf: StackHeapSize,
         width: usize,
     },
-    Heap(Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a>>),
+    Heap(Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b>),
 }
 
 // impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> LazyNodes<'a, F> {

+ 3 - 3
packages/core/src/lib.rs

@@ -19,7 +19,6 @@ pub mod context;
 pub mod diff;
 pub mod diff_stack;
 pub mod events;
-// pub mod events2;
 pub mod heuristics;
 pub mod hooklist;
 pub mod hooks;
@@ -46,6 +45,7 @@ pub(crate) mod innerlude {
     pub use crate::heuristics::*;
     pub(crate) use crate::hooklist::*;
     pub use crate::hooks::*;
+    pub use crate::lazynodes::*;
     pub use crate::mutations::*;
     pub use crate::nodes::*;
     pub(crate) use crate::resources::*;
@@ -56,7 +56,7 @@ pub(crate) mod innerlude {
     pub use crate::threadsafe::*;
     pub use crate::util::*;
     pub use crate::virtual_dom::*;
-    // pub type Element<'a> = Option<VNode<'a>>;
+
     pub type Element<'a> = Option<VNode<'a>>;
     pub type FC<P> = for<'a> fn(Scope<'a, P>) -> Element<'a>;
 }
@@ -71,7 +71,7 @@ pub mod prelude {
     pub use crate::component::{fc_to_builder, Fragment, Properties, Scope};
     pub use crate::context::Context;
     pub use crate::hooks::*;
-    pub use crate::innerlude::{DioxusElement, Element, Mutations, NodeFactory, FC};
+    pub use crate::innerlude::{DioxusElement, Element, LazyNodes, NodeFactory, FC};
     pub use crate::nodes::VNode;
     pub use crate::VirtualDom;
 }

+ 14 - 43
packages/core/src/nodes.rs

@@ -3,9 +3,12 @@
 //! VNodes represent lazily-constructed VDom trees that support diffing and event handlers. These VNodes should be *very*
 //! cheap and *very* fast to construct - building a full tree should be quick.
 
-use crate::innerlude::{
-    empty_cell, Context, Element, ElementId, Properties, Scope, ScopeId, ScopeInner,
-    SuspendedContext, FC,
+use crate::{
+    innerlude::{
+        empty_cell, Context, Element, ElementId, Properties, Scope, ScopeId, ScopeInner,
+        SuspendedContext,
+    },
+    lazynodes::LazyNodes,
 };
 use bumpalo::{boxed::Box as BumpBox, Bump};
 use std::{
@@ -328,14 +331,6 @@ impl<'a> NodeFactory<'a> {
         self.bump
     }
 
-    pub(crate) fn unstable_place_holder(&self) -> VNode {
-        VNode::Text(self.bump.alloc(VText {
-            text: "",
-            dom_id: empty_cell(),
-            is_static: true,
-        }))
-    }
-
     /// Directly pass in text blocks without the need to use the format_args macro.
     pub fn static_text(&self, text: &'static str) -> VNode<'a> {
         VNode::Text(self.bump.alloc(VText {
@@ -449,23 +444,6 @@ impl<'a> NodeFactory<'a> {
         }
     }
 
-    pub fn component_v2_borrowed<P: 'a>(
-        self,
-        f: impl Fn(Context<'a>) -> Option<VNode<'a>> + 'a,
-        fc: fn(Scope<'a, P>) -> Element<'a>,
-        p: &'a P,
-    ) -> VNode<'a> {
-        //
-        todo!()
-    }
-    // pub fn component_v2_memoized(
-    //     self,
-    //     f: impl for<'b> Fn(Context<'b>) -> Option<VNode<'b>> + 'static,
-    // ) -> VNode<'a> {
-    //     //
-    //     todo!()
-    // }
-
     pub fn component<P, V>(
         &self,
         component: fn(Scope<'a, P>) -> Element<'a>,
@@ -609,13 +587,11 @@ impl<'a> NodeFactory<'a> {
         })
     }
 
-    pub fn annotate_lazy<'z, 'b, F>(
-        f: F,
-    ) -> Option<Box<dyn FnOnce(NodeFactory<'z>) -> VNode<'z> + 'b>>
+    pub fn annotate_lazy<'z, 'b, F>(f: F) -> Option<LazyNodes<'z, 'b>>
     where
         F: FnOnce(NodeFactory<'z>) -> VNode<'z> + 'b,
     {
-        Some(Box::new(f))
+        Some(LazyNodes::new(f))
     }
 }
 
@@ -675,17 +651,11 @@ impl<'a> IntoVNode<'a> for Option<VNode<'a>> {
     }
 }
 
-pub fn annotate_lazy<'a, 'b, F>(f: F) -> Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b>>
-where
-    F: FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b,
-{
-    Some(Box::new(f))
-}
-
-impl<'a> IntoVNode<'a> for Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>> {
+impl<'a> IntoVNode<'a> for Option<LazyNodes<'a, '_>> {
+    // impl<'a> IntoVNode<'a> for Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>> {
     fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
         match self {
-            Some(lazy) => lazy(cx),
+            Some(lazy) => lazy.call(cx),
             None => VNode::Fragment(VFragment {
                 children: &[],
                 is_static: false,
@@ -695,9 +665,10 @@ impl<'a> IntoVNode<'a> for Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> +
     }
 }
 
-impl<'a> IntoVNode<'a> for Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_> {
+impl<'a> IntoVNode<'a> for LazyNodes<'a, '_> {
+    // impl<'a> IntoVNode<'a> for Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_> {
     fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
-        self(cx)
+        self.call(cx)
     }
 }