Parcourir la source

feat: pull children out of component definition

Jonathan Kelley il y a 3 ans
Parent
commit
2cf90b6

+ 15 - 9
packages/core-macro/src/rsx/component.rs

@@ -161,12 +161,22 @@ impl ToTokens for Component {
             None => {
                 let mut toks = quote! { fc_to_builder(#name) };
                 for field in &self.body {
-                    if field.name == "key" {
-                        has_key = Some(field);
-                    } else {
-                        toks.append_all(quote! {#field})
+                    match field.name.to_string().as_str() {
+                        "key" => {
+                            //
+                            has_key = Some(field);
+                        }
+                        _ => toks.append_all(quote! {#field}),
                     }
                 }
+
+                if !self.children.is_empty() {
+                    let childs = &self.children;
+                    toks.append_all(quote! {
+                        .children(ScopeChildren::new(__cx.fragment_from_iter([ #( #childs ),* ])))
+                    });
+                }
+
                 toks.append_all(quote! {
                     .build()
                 });
@@ -182,17 +192,13 @@ impl ToTokens for Component {
             None => quote! { None },
         };
 
-        let childs = &self.children;
-        let children = quote! {
-            [ #( #childs ),* ]
-        };
+        // #children
 
         tokens.append_all(quote! {
             __cx.component(
                 #name,
                 #builder,
                 #key_token,
-                #children
             )
         })
     }

+ 3 - 40
packages/core/examples/syntax2.rs

@@ -230,15 +230,10 @@ fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
         })
         .unwrap();
 
-    let b = cx.bump();
-    let node: &'a VNode<'a> = b.alloc(node);
-
-    let children = Children { pthru: node };
-
     cx.render(rsx! {
         div {
             ChildrenComp {
-                children: children
+                div {}
             }
         }
     })
@@ -246,46 +241,14 @@ fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
 
 #[derive(Props)]
 struct ChildrenTest<'a> {
-    children: Children<'a>,
-}
-
-struct Children<'a> {
-    pthru: &'a VNode<'a>,
-}
-
-impl<'a> Clone for Children<'a> {
-    fn clone(&self) -> Self {
-        Self { pthru: self.pthru }
-    }
-}
-impl<'a> Copy for Children<'a> {}
-
-impl<'a> IntoVNode<'a> for Children<'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,
-            }),
-        }
-    }
+    children: ScopeChildren<'a>,
 }
 
 fn ChildrenComp<'a>((cx, props): Scope<'a, ChildrenTest<'a>>) -> Element<'a> {
     cx.render(rsx! {
         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.children)}
+                {&props.children}
             }
         }
     })

+ 17 - 20
packages/core/src/nodes.rs

@@ -187,11 +187,7 @@ impl Debug for VNode<'_> {
 
             VNode::Fragment(frag) => write!(s, "VFragment {{ children: {:?} }}", frag.children),
             VNode::Suspended { .. } => write!(s, "VSuspended"),
-            VNode::Component(comp) => write!(
-                s,
-                "VComponent {{ fc: {:?}, children: {:?} }}",
-                comp.user_fc, comp.children
-            ),
+            VNode::Component(comp) => write!(s, "VComponent {{ fc: {:?}}}", comp.user_fc),
         }
     }
 }
@@ -331,8 +327,6 @@ pub struct VComponent<'src> {
 
     pub(crate) caller: &'src dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>,
 
-    pub(crate) children: &'src [VNode<'src>],
-
     pub(crate) comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
 
     pub(crate) drop_props: RefCell<Option<BumpBox<'src, dyn FnMut()>>>,
@@ -483,20 +477,16 @@ impl<'a> NodeFactory<'a> {
         }
     }
 
-    pub fn component<P, V>(
+    pub fn component<P>(
         &self,
         component: fn(Scope<'a, P>) -> Element<'a>,
         props: P,
         key: Option<Arguments>,
-        children: V,
     ) -> VNode<'a>
     where
         P: Properties + 'a,
-        V: AsRef<[VNode<'a>]> + 'a,
     {
         let bump = self.bump();
-        let children: &'a V = bump.alloc(children);
-        let children = children.as_ref();
         let props = bump.alloc(props);
         let raw_props = props as *mut P as *mut ();
         let user_fc = component as *const ();
@@ -518,7 +508,7 @@ impl<'a> NodeFactory<'a> {
 
                     // It's only okay to memoize if there are no children and the props can be memoized
                     // Implementing memoize is unsafe and done automatically with the props trait
-                    matches!((props_memoized, children.is_empty()), (true, true))
+                    props_memoized
                 } else {
                     false
                 }
@@ -549,8 +539,6 @@ impl<'a> NodeFactory<'a> {
             RefCell::new(Some(drop_props))
         };
 
-        let is_static = children.is_empty() && P::IS_STATIC && key.is_none();
-
         let key = key.map(|f| self.raw_text(f).0);
 
         let caller: &'a mut dyn for<'b> Fn(&'b ScopeInner) -> Element<'b> =
@@ -565,17 +553,14 @@ impl<'a> NodeFactory<'a> {
                 unsafe { std::mem::transmute(res) }
             });
 
-        let can_memoize = children.is_empty() && P::IS_STATIC;
-
         VNode::Component(bump.alloc(VComponent {
             user_fc,
             comparator,
             raw_props,
-            children,
             caller,
-            is_static,
+            is_static: P::IS_STATIC,
             key,
-            can_memoize,
+            can_memoize: P::IS_STATIC,
             drop_props,
             associated_scope: Cell::new(None),
         }))
@@ -770,6 +755,18 @@ pub struct ScopeChildren<'a> {
     root: Option<VNode<'a>>,
 }
 
+impl Default for ScopeChildren<'_> {
+    fn default() -> Self {
+        Self { root: None }
+    }
+}
+
+impl<'a> ScopeChildren<'a> {
+    pub fn new(root: VNode<'a>) -> Self {
+        Self { root: Some(root) }
+    }
+}
+
 impl IntoIterator for &ScopeChildren<'_> {
     type Item = Self;
 

+ 5 - 6
packages/core/tests/create_dom.rs

@@ -208,12 +208,11 @@ fn create_simple() {
 #[test]
 fn create_components() {
     static App: FC<()> = |(cx, props)| {
-        todo!()
-        // cx.render(rsx! {
-        //     Child { "abc1" }
-        //     Child { "abc2" }
-        //     Child { "abc3" }
-        // })
+        cx.render(rsx! {
+            Child { "abc1" }
+            Child { "abc2" }
+            Child { "abc3" }
+        })
     };
 
     #[derive(Props)]