Quellcode durchsuchen

wip: clean up using new children syntax

Jonathan Kelley vor 3 Jahren
Ursprung
Commit
9c13436

+ 24 - 10
packages/core/src/component.rs

@@ -5,11 +5,7 @@
 //! 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, Element, FC},
-    NodeFactory, VNode,
-};
-
+use crate::innerlude::{Context, Element, VNode};
 /// A component is a wrapper around a Context and some Props that share a lifetime
 ///
 ///
@@ -44,6 +40,27 @@ use crate::{
 ///
 pub type Scope<'a, T> = (Context<'a>, &'a T);
 
+pub struct FragmentProps<'a> {
+    childen: &'a VNode<'a>,
+}
+pub struct FragmentPropsBuilder<'a> {
+    childen: Option<&'a VNode<'a>>,
+}
+
+impl<'a> Properties for FragmentProps<'a> {
+    type Builder = FragmentPropsBuilder<'a>;
+
+    const IS_STATIC: bool = false;
+
+    fn builder() -> Self::Builder {
+        todo!()
+    }
+
+    unsafe fn memoize(&self, other: &Self) -> bool {
+        todo!()
+    }
+}
+
 /// Create inline fragments using Component syntax.
 ///
 /// Fragments capture a series of children without rendering extra nodes.
@@ -66,11 +83,8 @@ pub type Scope<'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<'a>((cx, _): Scope<'a, ()>) -> Element<'a> {
-    todo!()
-    // let p: Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_> =
-    //     Box::new(|f: NodeFactory| f.fragment_from_iter(cx.children()));
-    // cx.render(p)
+pub fn Fragment<'a>((_, props): Scope<'a, FragmentProps<'a>>) -> Element<'a> {
+    Some(props.childen.decouple())
 }
 
 /// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus

+ 0 - 4
packages/core/src/diff.rs

@@ -420,10 +420,6 @@ impl<'bump> DiffMachine<'bump> {
             ) => self
                 .stack
                 .create_node(new_node, MountType::Replace { old: old_node }),
-
-            (Placeholder, _) | (_, Placeholder) => {
-                unreachable!("placeholder should never be diffed");
-            }
         }
     }
 

+ 34 - 18
packages/core/src/lazynodes.rs

@@ -1,21 +1,18 @@
-use std::mem;
-
-/*
-Remember: calls to rsx! are lazy - they are not evaluated immediately.
-
-They also using dynamic dispatch, so we can return multiple rsx!'s from match statements and such.
-
-If we allocated every rsx! call on the heap, it would be quite wasteful. Rsx! calls are FnOnce, so they can be stored in a stack.
+//! Support for storing lazy-nodes on the stack
+//!
+//! This module provides support for a type called `LazyNodes` which is a micro-heap located on the stack to make calls
+//! to `rsx!` more efficient.
+//!
+//! To support returning rsx! from branches in match statements, we need to use dynamic dispatch on NodeFactory closures.
+//!
+//! This can be done either through boxing directly, or by using dynamic-sized-types and a custom allocator. In our case,
+//! we build a tiny alloactor in the stack and allocate the closure into that.
+//!
+//! The logic for this was borrowed from https://docs.rs/stack_dst/0.6.1/stack_dst/. Unfortunately, this crate does not
+//! support non-static closures, so we've implemented the core logic of `ValueA` in this module.
 
-Solutions like stackdst are useful, but they only support 'static closures.
-
-All our closures are bound by the bump lifetime, so stack-dst will not work for us
-
-Our solution is to try and manually allocate the closure onto the stack.
-If it fails, then we default to Box.
-
-*/
 use crate::innerlude::{NodeFactory, VNode};
+use std::mem;
 
 /// A concrete type provider for closures that build VNode structures.
 ///
@@ -73,13 +70,13 @@ impl<'a, 'b> LazyNodes<'a, 'b> {
             let size = mem::size_of::<F>();
 
             if info.len() * mem::size_of::<usize>() + size > mem::size_of::<StackHeapSize>() {
-                log::error!("lazy nodes was too large to fit into stack. falling back to heap");
+                log::debug!("lazy nodes was too large to fit into stack. falling back to heap");
 
                 Self {
                     inner: StackNodeStorage::Heap(Box::new(val)),
                 }
             } else {
-                log::error!("lazy nodes fits on stack!");
+                log::debug!("lazy nodes fits on stack!");
                 let mut buf: StackHeapSize = [0; 12];
 
                 assert!(info.len() + round_to_words(size) <= buf.as_ref().len());
@@ -173,3 +170,22 @@ unsafe fn make_fat_ptr<T: ?Sized>(data_ptr: usize, meta_vals: &[usize]) -> *mut
 fn round_to_words(len: usize) -> usize {
     (len + mem::size_of::<usize>() - 1) / mem::size_of::<usize>()
 }
+
+#[test]
+fn it_works() {
+    let bump = bumpalo::Bump::new();
+
+    simple_logger::init();
+
+    let factory = NodeFactory { bump: &bump };
+
+    let caller = NodeFactory::annotate_lazy(|f| {
+        //
+        f.text(format_args!("hello world!"))
+    })
+    .unwrap();
+
+    let g = caller.call(factory);
+
+    dbg!(g);
+}

+ 16 - 0
packages/core/src/nodes.rs

@@ -155,6 +155,22 @@ impl<'src> VNode<'src> {
             VNode::Component(_) => None,
         }
     }
+
+    // Create an "owned" version of the vnode.
+    pub fn decouple(&self) -> VNode<'src> {
+        match self {
+            VNode::Text(t) => VNode::Text(*t),
+            VNode::Element(e) => VNode::Element(*e),
+            VNode::Component(c) => VNode::Component(*c),
+            VNode::Suspended(s) => VNode::Suspended(*s),
+            VNode::Anchor(a) => VNode::Anchor(*a),
+            VNode::Fragment(f) => VNode::Fragment(VFragment {
+                children: f.children,
+                key: f.key,
+                is_static: f.is_static,
+            }),
+        }
+    }
 }
 
 /// A placeholder node only generated when Fragments don't have any children.

+ 15 - 15
packages/core/src/scope.rs

@@ -341,21 +341,21 @@ impl ScopeInner {
 
         // Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
         //
-        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
-        // }
+        // 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
+        }
     }
 }
 

+ 9 - 40
packages/core/src/test_dom.rs

@@ -21,27 +21,13 @@ impl TestDom {
         NodeFactory::new(&self.bump)
     }
 
-    pub fn render_direct<'a>(
-        &'a self,
-        lazy_nodes: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
-    ) -> VNode<'a>
-// where
-    //     F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
-    {
-        todo!()
-        // lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
+    pub fn render_direct<'a>(&'a self, lazy_nodes: Option<LazyNodes<'a, '_>>) -> VNode<'a> {
+        lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
     }
 
-    pub fn render<'a>(
-        &'a self,
-        lazy_nodes: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
-    ) -> &'a VNode<'a>
-// where
-    //     F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
-    {
-        todo!()
-        // self.bump
-        // .alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump)))
+    pub fn render<'a>(&'a self, lazy_nodes: Option<LazyNodes<'a, '_>>) -> &'a VNode<'a> {
+        self.bump
+            .alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump)))
     }
 
     pub fn diff<'a>(&'a self, old: &'a VNode<'a>, new: &'a VNode<'a>) -> Mutations<'a> {
@@ -51,14 +37,7 @@ impl TestDom {
         machine.mutations
     }
 
-    pub fn create<'a>(
-        &'a self,
-        left: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
-    ) -> Mutations<'a>
-// 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: Option<LazyNodes<'a, '_>>) -> Mutations<'a> {
         let old = self.bump.alloc(self.render_direct(left));
 
         let mut machine = DiffMachine::new(Mutations::new(), &self.scheduler.pool);
@@ -72,13 +51,9 @@ impl TestDom {
 
     pub fn lazy_diff<'a>(
         &'a self,
-        left: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
-        right: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
-    ) -> (Mutations<'a>, Mutations<'a>)
-// where
-    //     F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
-    //     F2: FnOnce(NodeFactory<'a>) -> VNode<'a>,
-    {
+        left: Option<LazyNodes<'a, '_>>,
+        right: Option<LazyNodes<'a, '_>>,
+    ) -> (Mutations<'a>, Mutations<'a>) {
         let (old, new) = (self.render(left), self.render(right));
 
         let mut machine = DiffMachine::new(Mutations::new(), &self.scheduler.pool);
@@ -105,9 +80,3 @@ impl Default for TestDom {
         Self::new()
     }
 }
-
-impl VirtualDom {
-    pub fn simulate(&mut self) {
-        //
-    }
-}