Bläddra i källkod

wip: try to get lifetimes passed in properly

Jonathan Kelley 3 år sedan
förälder
incheckning
f70b5b4

+ 2 - 2
packages/core/Cargo.toml

@@ -49,8 +49,8 @@ fern = { version = "0.6.0", features = ["colored"] }
 rand = { version = "0.8.4", features = ["small_rng"] }
 simple_logger = "1.13.0"
 dioxus-core-macro = { path = "../core-macro", version = "0.1.2" }
-async-std = { version = "1.9.0", features = ["attributes"] }
-criterion = "0.3.5"
+# async-std = { version = "1.9.0", features = ["attributes"] }
+# criterion = "0.3.5"
 
 [features]
 default = []

+ 279 - 173
packages/core/examples/syntax2.rs

@@ -1,8 +1,10 @@
+use std::borrow::BorrowMut;
+use std::cell::{Cell, RefCell};
 use std::marker::PhantomData;
 
 use dioxus::component::Scope;
 use dioxus::events::on::MouseEvent;
-use dioxus::nodes::{annotate_lazy, IntoVNode};
+use dioxus::nodes::{annotate_lazy, IntoVNode, VComponent, VFragment, VText};
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
 use dioxus_core_macro::*;
@@ -29,201 +31,305 @@ fn t() {
     };
 }
 
-#[derive(PartialEq, Props)]
-struct OurProps {
-    foo: String,
-}
+// #[derive(PartialEq, Props)]
+// struct OurProps {
+//     foo: String,
+// }
 
-fn App<'a>((cx, props): Scope<'a, OurProps>) -> Element<'a> {
-    let a = rsx! {
-        div {
-            "asd"
-            "{props.foo}"
-        }
-    };
+// fn App<'a>((cx, props): Scope<'a, OurProps>) -> Element<'a> {
+//     let a = rsx! {
+//         div {
+//             "asd"
+//             "{props.foo}"
+//         }
+//     };
+
+//     let p = (0..10).map(|f| {
+//         rsx! {
+//             div {
+
+//             }
+//         }
+//     });
+
+//     let g = match "text" {
+//         "a" => {
+//             rsx!("asd")
+//         }
+//         _ => {
+//             rsx!("asd")
+//         }
+//     };
+
+//     let items = ["bob", "bill", "jack"];
+
+//     let f = items
+//         .iter()
+//         .filter(|f| f.starts_with('b'))
+//         .map(|f| rsx!("hello {f}"));
+
+//     // use dioxus_hooks;
+//     // let g = use_state(|| "hello".to_string());
+
+//     let s: &'a mut String = cx.use_hook(|_| String::new(), |f| f, |_| {});
+
+//     /*
+//     the final closure is allowed to borrow anything provided it
+//     */
+//     // cx.render({
+//     //     let p: Option<Box<dyn FnOnce(_) -> _>> = Some(Box::new(move |__cx: NodeFactory| {
+//     //         use dioxus_elements::{GlobalAttributes, SvgAttributes};
+
+//     //         let props = Child2Props { foo: s };
+//     //         let ch: VNode = __cx.component(Child2, props, None, []);
+//     //         __cx.element(
+//     //             dioxus_elements::div,
+//     //             [],
+//     //             [],
+//     //             [ch],
+//     //             // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])],
+//     //             None,
+//     //         )
+//     //     }));
+//     //     p
+//     //     // let ___p: Box<dyn FnOnce(NodeFactory) -> VNode> = Box::new(move |__cx| {
+//     //     //     use dioxus_elements::{GlobalAttributes, SvgAttributes};
+
+//     //     //     let props = Child2Props { foo: s };
+//     //     //     let ch: VNode = __cx.component(Child2, props, None, []);
+//     //     //     __cx.element(
+//     //     //         dioxus_elements::div,
+//     //     //         [],
+//     //     //         [],
+//     //     //         [ch],
+//     //     //         // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])],
+//     //     //         None,
+//     //     //     )
+//     //     // });
+//     //     // Some(___p)
+//     // })
+
+//     let a = annotate_lazy(move |f| {
+//         //
+//         todo!()
+//     });
+//     let b = annotate_lazy(move |f| {
+//         //
+//         f.text(format_args!("{}", props.foo))
+//     });
 
-    let p = (0..10).map(|f| {
-        rsx! {
+//     let c = annotate_lazy(move |f| {
+//         //
+//         f.component(
+//             Child,
+//             OurProps {
+//                 //
+//                 foo: "hello".to_string(),
+//             },
+//             None,
+//             [],
+//         )
+//     });
+
+//     let st: &'a String = cx.use_hook(|_| "hello".to_string(), |f| f, |_| {});
+
+//     let d = annotate_lazy(move |f| {
+//         //
+//         f.component(
+//             Child2,
+//             Child2Props {
+//                 //
+//                 foo: st,
+//             },
+//             None,
+//             [],
+//         )
+//     });
+
+//     let e = match "asd" {
+//         b => {
+//             //
+
+//             annotate_lazy(move |f| {
+//                 //
+//                 f.text(format_args!("{}", props.foo))
+//             })
+//         }
+//         a => {
+//             //
+
+//             annotate_lazy(move |f| {
+//                 //
+//                 f.text(format_args!("{}", props.foo))
+//             })
+//         }
+//     };
+
+//     cx.render(annotate_lazy(move |f| {
+//         //
+
+//         f.raw_element(
+//             "div",
+//             None,
+//             [],
+//             [],
+//             [
+//                 //
+//                 f.fragment_from_iter(a),
+//                 f.fragment_from_iter(b),
+//                 f.fragment_from_iter(c),
+//                 f.fragment_from_iter(e),
+//             ],
+//             None,
+//         )
+//         // todo!()
+//     }))
+//     // cx.render(rsx! {
+//     //     div {
+//     //         div {
+//     //             {a}
+//     //             // {p}
+//     //             // {g}
+//     //             // {f}
+//     //         }
+//     //         // div {
+//     //         //     "asd"
+//     //         //     div {
+//     //         //         "asd"
+//     //         //     }
+//     //         // }
+//     //         // Child {
+//     //         //     foo: "asd".to_string(),
+//     //         // }
+//     //         Child2 {
+//     //             foo: s,
+//     //         }
+//     //     }
+//     // })
+// }
+
+// fn Child((cx, props): Scope<OurProps>) -> Element {
+//     cx.render(rsx! {
+//         div {
+//             div {}
+//         }
+//     })
+// }
+
+#[derive(Props)]
+struct Child2Props<'a> {
+    foo: &'a String,
+}
+
+fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
+    let node = cx
+        .render(rsx! {
             div {
 
             }
-        }
-    });
+        })
+        .unwrap();
 
-    let g = match "text" {
-        "a" => {
-            rsx!("asd")
-        }
-        _ => {
-            rsx!("asd")
-        }
-    };
+    let b = cx.bump();
+    let node: &'a VNode<'a> = b.alloc(node);
 
-    let items = ["bob", "bill", "jack"];
-
-    let f = items
-        .iter()
-        .filter(|f| f.starts_with('b'))
-        .map(|f| rsx!("hello {f}"));
-
-    // use dioxus_hooks;
-    // let g = use_state(|| "hello".to_string());
-
-    let s: &'a mut String = cx.use_hook(|_| String::new(), |f| f, |_| {});
-
-    /*
-    the final closure is allowed to borrow anything provided it
-    */
-
-    // cx.render({
-    //     let p: Option<Box<dyn FnOnce(_) -> _>> = Some(Box::new(move |__cx: NodeFactory| {
-    //         use dioxus_elements::{GlobalAttributes, SvgAttributes};
-
-    //         let props = Child2Props { foo: s };
-    //         let ch: VNode = __cx.component(Child2, props, None, []);
-    //         __cx.element(
-    //             dioxus_elements::div,
-    //             [],
-    //             [],
-    //             [ch],
-    //             // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])],
-    //             None,
-    //         )
-    //     }));
-    //     p
-    //     // let ___p: Box<dyn FnOnce(NodeFactory) -> VNode> = Box::new(move |__cx| {
-    //     //     use dioxus_elements::{GlobalAttributes, SvgAttributes};
-
-    //     //     let props = Child2Props { foo: s };
-    //     //     let ch: VNode = __cx.component(Child2, props, None, []);
-    //     //     __cx.element(
-    //     //         dioxus_elements::div,
-    //     //         [],
-    //     //         [],
-    //     //         [ch],
-    //     //         // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])],
-    //     //         None,
-    //     //     )
-    //     // });
-    //     // Some(___p)
-    // })
+    let children = ChildList { pthru: node };
 
-    let a = annotate_lazy(move |f| {
-        //
-        todo!()
-    });
-    let b = annotate_lazy(move |f| {
-        //
-        f.text(format_args!("{}", props.foo))
-    });
-
-    let c = annotate_lazy(move |f| {
-        //
-        f.component(
-            Child,
-            OurProps {
-                //
-                foo: "hello".to_string(),
-            },
-            None,
-            [],
-        )
-    });
-
-    let st: &'a String = cx.use_hook(|_| "hello".to_string(), |f| f, |_| {});
-
-    let d = annotate_lazy(move |f| {
-        //
-        f.component(
-            Child2,
-            Child2Props {
-                //
-                foo: st,
-            },
-            None,
-            [],
-        )
-    });
-
-    let e = match "asd" {
-        b => {
-            //
-
-            annotate_lazy(move |f| {
-                //
-                f.text(format_args!("{}", props.foo))
-            })
-        }
-        a => {
-            //
+    // let c = VComponent {
+    //     key: todo!(),
+    //     associated_scope: todo!(),
+    //     is_static: todo!(),
+    //     user_fc: todo!(),
+    //     caller: todo!(),
+    //     children: todo!(),
+    //     comparator: todo!(),
+    //     drop_props: todo!(),
+    //     can_memoize: todo!(),
+    //     raw_props: todo!(),
+    // };
 
-            annotate_lazy(move |f| {
-                //
-                f.text(format_args!("{}", props.foo))
-            })
-        }
-    };
+    // Vcomp
+    // - borrowed
+    // - memoized
 
-    cx.render(annotate_lazy(move |f| {
-        //
-
-        f.raw_element(
-            "div",
-            None,
-            [],
-            [],
-            [
-                //
-                f.fragment_from_iter(a),
-                f.fragment_from_iter(b),
-                f.fragment_from_iter(c),
-                f.fragment_from_iter(e),
-            ],
-            None,
-        )
-        // todo!()
-    }))
+    cx.render({
+        NodeFactory::annotate_lazy(move |__cx: NodeFactory| -> VNode {
+            use dioxus_elements::{GlobalAttributes, SvgAttributes};
+            __cx.element(
+                dioxus_elements::div,
+                [],
+                [],
+                [],
+                // [__cx.component(
+                //     ChildrenComp,
+                //     {
+                //         let mut __manual_props = ChildrenTest { node: children };
+                //         __manual_props
+                //     },
+                //     None,
+                //     [],
+                // )],
+                None,
+            )
+        })
+    })
     // cx.render(rsx! {
     //     div {
-    //         div {
-    //             {a}
-    //             // {p}
-    //             // {g}
-    //             // {f}
-    //         }
-    //         // div {
-    //         //     "asd"
-    //         //     div {
-    //         //         "asd"
-    //         //     }
-    //         // }
-    //         // Child {
-    //         //     foo: "asd".to_string(),
-    //         // }
-    //         Child2 {
-    //             foo: s,
+    //         // div {}
+
+    //         ChildrenComp {
+    //             // node: children
+    //             ..ChildrenTest {
+    //                 node: children,
+    //             }
     //         }
     //     }
     // })
 }
 
-fn Child((cx, props): Scope<OurProps>) -> Element {
-    cx.render(rsx! {
-        div {
-            div {}
-        }
-    })
+#[derive(Props)]
+struct ChildrenTest<'a> {
+    node: ChildList<'a>,
 }
 
-#[derive(Props)]
-struct Child2Props<'a> {
-    foo: &'a String,
+struct ChildList<'a> {
+    pthru: &'a VNode<'a>,
 }
 
-fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
+impl<'a> Clone for ChildList<'a> {
+    fn clone(&self) -> Self {
+        Self { pthru: self.pthru }
+    }
+}
+impl<'a> Copy for ChildList<'a> {}
+
+impl<'a> IntoVNode<'a> for ChildList<'a> {
+    fn into_vnode(self, _: NodeFactory<'a>) -> VNode<'a> {
+        match self.pthru {
+            VNode::Text(f) => VNode::Text(*f),
+            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,
+                is_static: f.is_static,
+                key: f.key,
+            }),
+        }
+    }
+}
+
+fn ChildrenComp<'a>((cx, props): Scope<'a, ChildrenTest<'a>>) -> Element<'a> {
     cx.render(rsx! {
         div {
-            // div {}
+            div {
+
+                // if the node's id is already assigned, then it's being passed in as a child
+                // in these instances, we don't worry about re-checking the node?
+
+                {Some(props.node)}
+            }
         }
     })
 }

+ 15 - 4
packages/core/src/bumpframe.rs

@@ -21,16 +21,27 @@ pub(crate) struct BumpFrame {
 
 impl ActiveFrame {
     pub fn new() -> Self {
+        let b1 = Bump::new();
+        let b2 = Bump::new();
+
         let frame_a = BumpFrame {
-            bump: Bump::new(),
-            head_node: NodeFactory::unstable_place_holder(),
+            head_node: VNode::Fragment(VFragment {
+                key: None,
+                children: &[],
+                is_static: false,
+            }),
+            bump: b1,
 
             #[cfg(test)]
             _name: "wip",
         };
         let frame_b = BumpFrame {
-            bump: Bump::new(),
-            head_node: NodeFactory::unstable_place_holder(),
+            head_node: VNode::Fragment(VFragment {
+                key: None,
+                children: &[],
+                is_static: false,
+            }),
+            bump: b2,
 
             #[cfg(test)]
             _name: "fin",

+ 7 - 0
packages/core/src/context.rs

@@ -4,6 +4,8 @@
 //!
 //! We unsafely implement `send` for the VirtualDom, but those guarantees can only be
 
+use bumpalo::Bump;
+
 use crate::innerlude::*;
 use std::{any::TypeId, ops::Deref, rc::Rc};
 
@@ -122,6 +124,11 @@ impl<'src> Context<'src> {
         self.scope.our_arena_idx
     }
 
+    pub fn bump(&self) -> &'src Bump {
+        let bump = &self.scope.frames.wip_frame().bump;
+        bump
+    }
+
     /// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
     ///
     /// This function consumes the context and absorb the lifetime, so these VNodes *must* be returned.

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

@@ -421,6 +421,10 @@ impl<'bump> DiffMachine<'bump> {
             ) => self
                 .stack
                 .create_node(new_node, MountType::Replace { old: old_node }),
+
+            (Placeholder, _) | (_, Placeholder) => {
+                unreachable!("placeholder should never be diffed");
+            }
         }
     }
 
@@ -1125,6 +1129,7 @@ impl<'bump> DiffMachine<'bump> {
 
                     self.remove_nodes(e.children, false);
                 }
+
                 VNode::Fragment(f) => {
                     self.remove_nodes(f.children, gen_muts);
                 }

+ 11 - 12
packages/core/src/nodes.rs

@@ -10,7 +10,6 @@ use bumpalo::{boxed::Box as BumpBox, Bump};
 use std::{
     cell::{Cell, RefCell},
     fmt::{Arguments, Debug, Formatter},
-    marker::PhantomData,
 };
 
 /// A composable "VirtualNode" to declare a User Interface in the Dioxus VirtualDOM.
@@ -33,7 +32,7 @@ pub enum VNode<'src> {
     ///     assert_eq!(vtext.is_static, true);
     /// }
     /// ```
-    Text(VText<'src>),
+    Text(&'src VText<'src>),
 
     /// Element VNodes are VNodes that may contain attributes, listeners, a key, a tag, and children.
     ///
@@ -116,7 +115,7 @@ pub enum VNode<'src> {
     ///     assert_eq!(root, VNode::Anchor);
     /// }
     /// ```
-    Anchor(VAnchor),
+    Anchor(&'src VAnchor),
 }
 
 impl<'src> VNode<'src> {
@@ -328,21 +327,21 @@ impl<'a> NodeFactory<'a> {
         self.bump
     }
 
-    pub fn unstable_place_holder() -> VNode<'static> {
-        VNode::Text(VText {
+    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(VText {
+        VNode::Text(self.bump.alloc(VText {
             dom_id: empty_cell(),
             text,
             is_static: true,
-        })
+        }))
     }
 
     /// Parses a lazy text Arguments and returns a string and a flag indicating if the text is 'static
@@ -365,11 +364,11 @@ impl<'a> NodeFactory<'a> {
     pub fn text(&self, args: Arguments) -> VNode<'a> {
         let (text, is_static) = self.raw_text(args);
 
-        VNode::Text(VText {
+        VNode::Text(self.bump.alloc(VText {
             text,
             is_static,
             dom_id: empty_cell(),
-        })
+        }))
     }
 
     pub fn element<L, A, V>(
@@ -556,9 +555,9 @@ impl<'a> NodeFactory<'a> {
         }
 
         if nodes.is_empty() {
-            nodes.push(VNode::Anchor(VAnchor {
+            nodes.push(VNode::Anchor(bump.alloc(VAnchor {
                 dom_id: empty_cell(),
-            }));
+            })));
         }
 
         let children = nodes.into_bump_slice();