feat: pull children out of component definition
This commit is contained in:
1 parent
f438bbcfd2
commit
2cf90b6903
4 files changed
+40
-75
No files matched your search
@@ -161,12 +161,22 @@ impl ToTokens for Component {
|
|||||||
None => {
|
None => {
|
||||||
let mut toks = quote! { fc_to_builder(#name) };
|
let mut toks = quote! { fc_to_builder(#name) };
|
||||||
for field in &self.body {
|
for field in &self.body {
|
||||||
if field.name == "key" {
|
match field.name.to_string().as_str() {
|
||||||
has_key = Some(field);
|
"key" => {
|
||||||
} else {
|
//
|
||||||
toks.append_all(quote! {#field})
|
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! {
|
toks.append_all(quote! {
|
||||||
.build()
|
.build()
|
||||||
});
|
});
|
||||||
@@ -182,17 +192,13 @@ impl ToTokens for Component {
|
|||||||
None => quote! { None },
|
None => quote! { None },
|
||||||
};
|
};
|
||||||
|
|
||||||
let childs = &self.children;
|
// #children
|
||||||
let children = quote! {
|
|
||||||
[ #( #childs ),* ]
|
|
||||||
};
|
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
__cx.component(
|
__cx.component(
|
||||||
#name,
|
#name,
|
||||||
#builder,
|
#builder,
|
||||||
#key_token,
|
#key_token,
|
||||||
#children
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,15 +230,10 @@ fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let b = cx.bump();
|
|
||||||
let node: &'a VNode<'a> = b.alloc(node);
|
|
||||||
|
|
||||||
let children = Children { pthru: node };
|
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
ChildrenComp {
|
ChildrenComp {
|
||||||
children: children
|
div {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -246,46 +241,14 @@ fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> {
|
|||||||
|
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
struct ChildrenTest<'a> {
|
struct ChildrenTest<'a> {
|
||||||
children: Children<'a>,
|
children: ScopeChildren<'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,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ChildrenComp<'a>((cx, props): Scope<'a, ChildrenTest<'a>>) -> Element<'a> {
|
fn ChildrenComp<'a>((cx, props): Scope<'a, ChildrenTest<'a>>) -> Element<'a> {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
div {
|
div {
|
||||||
|
{&props.children}
|
||||||
// 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)}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+17
-20
@@ -187,11 +187,7 @@ impl Debug for VNode<'_> {
|
|||||||
|
|
||||||
VNode::Fragment(frag) => write!(s, "VFragment {{ children: {:?} }}", frag.children),
|
VNode::Fragment(frag) => write!(s, "VFragment {{ children: {:?} }}", frag.children),
|
||||||
VNode::Suspended { .. } => write!(s, "VSuspended"),
|
VNode::Suspended { .. } => write!(s, "VSuspended"),
|
||||||
VNode::Component(comp) => write!(
|
VNode::Component(comp) => write!(s, "VComponent {{ fc: {:?}}}", comp.user_fc),
|
||||||
s,
|
|
||||||
"VComponent {{ fc: {:?}, children: {:?} }}",
|
|
||||||
comp.user_fc, comp.children
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -331,8 +327,6 @@ pub struct VComponent<'src> {
|
|||||||
|
|
||||||
pub(crate) caller: &'src dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>,
|
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) comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
|
||||||
|
|
||||||
pub(crate) drop_props: RefCell<Option<BumpBox<'src, dyn FnMut()>>>,
|
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,
|
&self,
|
||||||
component: fn(Scope<'a, P>) -> Element<'a>,
|
component: fn(Scope<'a, P>) -> Element<'a>,
|
||||||
props: P,
|
props: P,
|
||||||
key: Option<Arguments>,
|
key: Option<Arguments>,
|
||||||
children: V,
|
|
||||||
) -> VNode<'a>
|
) -> VNode<'a>
|
||||||
where
|
where
|
||||||
P: Properties + 'a,
|
P: Properties + 'a,
|
||||||
V: AsRef<[VNode<'a>]> + 'a,
|
|
||||||
{
|
{
|
||||||
let bump = self.bump();
|
let bump = self.bump();
|
||||||
let children: &'a V = bump.alloc(children);
|
|
||||||
let children = children.as_ref();
|
|
||||||
let props = bump.alloc(props);
|
let props = bump.alloc(props);
|
||||||
let raw_props = props as *mut P as *mut ();
|
let raw_props = props as *mut P as *mut ();
|
||||||
let user_fc = component as *const ();
|
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
|
// 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
|
// Implementing memoize is unsafe and done automatically with the props trait
|
||||||
matches!((props_memoized, children.is_empty()), (true, true))
|
props_memoized
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -549,8 +539,6 @@ impl<'a> NodeFactory<'a> {
|
|||||||
RefCell::new(Some(drop_props))
|
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 key = key.map(|f| self.raw_text(f).0);
|
||||||
|
|
||||||
let caller: &'a mut dyn for<'b> Fn(&'b ScopeInner) -> Element<'b> =
|
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) }
|
unsafe { std::mem::transmute(res) }
|
||||||
});
|
});
|
||||||
|
|
||||||
let can_memoize = children.is_empty() && P::IS_STATIC;
|
|
||||||
|
|
||||||
VNode::Component(bump.alloc(VComponent {
|
VNode::Component(bump.alloc(VComponent {
|
||||||
user_fc,
|
user_fc,
|
||||||
comparator,
|
comparator,
|
||||||
raw_props,
|
raw_props,
|
||||||
children,
|
|
||||||
caller,
|
caller,
|
||||||
is_static,
|
is_static: P::IS_STATIC,
|
||||||
key,
|
key,
|
||||||
can_memoize,
|
can_memoize: P::IS_STATIC,
|
||||||
drop_props,
|
drop_props,
|
||||||
associated_scope: Cell::new(None),
|
associated_scope: Cell::new(None),
|
||||||
}))
|
}))
|
||||||
@@ -770,6 +755,18 @@ pub struct ScopeChildren<'a> {
|
|||||||
root: Option<VNode<'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<'_> {
|
impl IntoIterator for &ScopeChildren<'_> {
|
||||||
type Item = Self;
|
type Item = Self;
|
||||||
|
|
||||||
|
|||||||
@@ -208,12 +208,11 @@ fn create_simple() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn create_components() {
|
fn create_components() {
|
||||||
static App: FC<()> = |(cx, props)| {
|
static App: FC<()> = |(cx, props)| {
|
||||||
todo!()
|
cx.render(rsx! {
|
||||||
// cx.render(rsx! {
|
Child { "abc1" }
|
||||||
// Child { "abc1" }
|
Child { "abc2" }
|
||||||
// Child { "abc2" }
|
Child { "abc3" }
|
||||||
// Child { "abc3" }
|
})
|
||||||
// })
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
|
|||||||
Reference in new issue
Block a user