feat: pull children out of component definition

This commit is contained in:
Jonathan Kelley 2021-11-01 13:32:01 -04:00
parent f438bbcfd2
commit 2cf90b6903
4 changed files with 40 additions and 75 deletions

View file

@ -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
)
})
}

View file

@ -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}
}
}
})

View file

@ -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;

View file

@ -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)]