wip: remove cx.children. start to move towards a "children" field
This commit is contained in:
1 parent
6b2645fd80
commit
7b97e009ec
14 files changed
+114
-276
No files matched your search
@@ -138,6 +138,6 @@ impl EmptyBuilder {
|
||||
|
||||
/// This utility function launches the builder method so rsx! and html! macros can use the typed-builder pattern
|
||||
/// to initialize a component's props.
|
||||
pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
|
||||
pub fn fc_to_builder<'a, T: Properties + 'a>(_: fn(Scope<'a, T>) -> Element<'a>) -> T::Builder {
|
||||
T::builder()
|
||||
}
|
||||
@@ -54,49 +54,6 @@ impl<'a> Deref for Context<'a> {
|
||||
}
|
||||
|
||||
impl<'src> Context<'src> {
|
||||
/// Access the children elements passed into the component
|
||||
///
|
||||
/// This enables patterns where a component is passed children from its parent.
|
||||
///
|
||||
/// ## Details
|
||||
///
|
||||
/// Unlike React, Dioxus allows *only* lists of children to be passed from parent to child - not arbitrary functions
|
||||
/// or classes. If you want to generate nodes instead of accepting them as a list, consider declaring a closure
|
||||
/// on the props that takes Context.
|
||||
///
|
||||
/// If a parent passes children into a component, the child will always re-render when the parent re-renders. In other
|
||||
/// words, a component cannot be automatically memoized if it borrows nodes from its parent, even if the component's
|
||||
/// props are valid for the static lifetime.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// const App: FC<()> = |(cx, props)|{
|
||||
/// cx.render(rsx!{
|
||||
/// CustomCard {
|
||||
/// h1 {}
|
||||
/// p {}
|
||||
/// }
|
||||
/// })
|
||||
/// }
|
||||
///
|
||||
/// const CustomCard: FC<()> = |(cx, props)|{
|
||||
/// cx.render(rsx!{
|
||||
/// div {
|
||||
/// h1 {"Title card"}
|
||||
/// {cx.children()}
|
||||
/// }
|
||||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Notes:
|
||||
///
|
||||
/// This method returns a "ScopeChildren" object. This object is copy-able and preserve the correct lifetime.
|
||||
pub fn children(&self) -> ScopeChildren<'src> {
|
||||
self.scope.child_nodes()
|
||||
}
|
||||
|
||||
/// Create a subscription that schedules a future render for the reference component
|
||||
///
|
||||
/// ## Notice: you should prefer using prepare_update and get_scope_id
|
||||
@@ -147,28 +104,10 @@ impl<'src> Context<'src> {
|
||||
pub fn render(
|
||||
self,
|
||||
lazy_nodes: Option<Box<dyn FnOnce(NodeFactory<'src>) -> VNode<'src> + '_>>,
|
||||
// lazy_nodes: Option<Box<dyn FnOnce(NodeFactory) -> VNode + '_>>,
|
||||
// lazy_nodes: Box<dyn FnOnce(NodeFactory<'src>) -> VNode<'src> + '_>,
|
||||
) -> Option<VNode<'src>> {
|
||||
// pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
|
||||
// self,
|
||||
// lazy_nodes: LazyNodes<'src, F>,
|
||||
// ) -> Option<VNode<'src>> {
|
||||
let bump = &self.scope.frames.wip_frame().bump;
|
||||
// Some(lazy_nodes.into_vnode(NodeFactory { bump }))
|
||||
|
||||
let factory = NodeFactory { bump };
|
||||
// let vnode = lazy_nodes(factory);
|
||||
|
||||
match lazy_nodes {
|
||||
Some(f) => Some(f(factory)),
|
||||
None => None,
|
||||
}
|
||||
|
||||
// match lazy_nodes {
|
||||
// None => todo!(),
|
||||
// }
|
||||
// Some(lazy_nodes)
|
||||
lazy_nodes.map(|f| f(factory))
|
||||
}
|
||||
|
||||
/// `submit_task` will submit the future to be polled.
|
||||
|
||||
@@ -348,7 +348,6 @@ impl<'bump> DiffMachine<'bump> {
|
||||
Some(parent_idx),
|
||||
parent_scope.height + 1,
|
||||
parent_scope.subtree(),
|
||||
ScopeChildren(vcomponent.children),
|
||||
shared,
|
||||
)
|
||||
});
|
||||
@@ -555,7 +554,7 @@ impl<'bump> DiffMachine<'bump> {
|
||||
|
||||
// make sure the component's caller function is up to date
|
||||
let scope = self.vdom.get_scope_mut(scope_addr).unwrap();
|
||||
scope.update_scope_dependencies(new.caller, ScopeChildren(new.children));
|
||||
scope.update_scope_dependencies(new.caller);
|
||||
|
||||
// React doesn't automatically memoize, but we do.
|
||||
let props_are_the_same = old.comparator.unwrap();
|
||||
|
||||
+23
-79
@@ -638,47 +638,6 @@ pub trait IntoVNode<'a> {
|
||||
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a>;
|
||||
}
|
||||
|
||||
/// Child nodes of the parent component.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let children = cx.children();
|
||||
/// let first_node = &children[0];
|
||||
/// rsx!{
|
||||
/// h1 { {first_node} }
|
||||
/// p { {&children[1..]} }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
pub struct ScopeChildren<'a>(pub &'a [VNode<'a>]);
|
||||
|
||||
impl Copy for ScopeChildren<'_> {}
|
||||
|
||||
impl<'a> Clone for ScopeChildren<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
ScopeChildren(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ScopeChildren<'_> {
|
||||
// dangerous method - used to fix the associated lifetime
|
||||
pub(crate) unsafe fn extend_lifetime(self) -> ScopeChildren<'static> {
|
||||
std::mem::transmute(self)
|
||||
}
|
||||
|
||||
// dangerous method - used to fix the associated lifetime
|
||||
pub(crate) unsafe fn shorten_lifetime<'a>(self) -> ScopeChildren<'a> {
|
||||
std::mem::transmute(self)
|
||||
}
|
||||
}
|
||||
|
||||
// impl IntoVNodeList for ScopeChildren<'_> {
|
||||
// fn into_vnode_list<'a>(self, _: NodeFactory<'a>) -> &'a [VNode<'a>] {
|
||||
// self.0
|
||||
// }
|
||||
// }
|
||||
|
||||
// For the case where a rendered VNode is passed into the rsx! macro through curly braces
|
||||
impl<'a> IntoIterator for VNode<'a> {
|
||||
type Item = VNode<'a>;
|
||||
@@ -690,34 +649,31 @@ impl<'a> IntoIterator for VNode<'a> {
|
||||
|
||||
// TODO: do we even need this? It almost seems better not to
|
||||
// // For the case where a rendered VNode is passed into the rsx! macro through curly braces
|
||||
// impl IntoVNode for VNode<'_> {
|
||||
// fn into_vnode<'a>(self, _: NodeFactory<'a>) -> VNode<'a> {
|
||||
// self
|
||||
// }
|
||||
// }
|
||||
impl<'a> IntoVNode<'a> for VNode<'a> {
|
||||
fn into_vnode(self, _: NodeFactory<'a>) -> VNode<'a> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// Conveniently, we also support "null" (nothing) passed in
|
||||
// impl IntoVNode for () {
|
||||
// fn into_vnode(self, cx: NodeFactory) -> VNode {
|
||||
// cx.fragment_from_iter(None as Option<VNode>)
|
||||
// }
|
||||
// }
|
||||
impl IntoVNode<'_> for () {
|
||||
fn into_vnode(self, cx: NodeFactory) -> VNode {
|
||||
cx.fragment_from_iter(None as Option<VNode>)
|
||||
}
|
||||
}
|
||||
|
||||
// // Conveniently, we also support "None"
|
||||
// impl IntoVNode for Option<()> {
|
||||
// fn into_vnode(self, cx: NodeFactory) -> VNode {
|
||||
// cx.fragment_from_iter(None as Option<VNode>)
|
||||
// }
|
||||
// }
|
||||
// Conveniently, we also support "None"
|
||||
impl IntoVNode<'_> for Option<()> {
|
||||
fn into_vnode(self, cx: NodeFactory) -> VNode {
|
||||
cx.fragment_from_iter(None as Option<VNode>)
|
||||
}
|
||||
}
|
||||
|
||||
// impl IntoVNode for Option<VNode<'_>> {
|
||||
// fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
// match self {
|
||||
// Some(n) => n,
|
||||
// None => cx.fragment_from_iter(None as Option<VNode>),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl<'a> IntoVNode<'a> for Option<VNode<'a>> {
|
||||
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
self.unwrap_or_else(|| cx.fragment_from_iter(None as Option<VNode>))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn annotate_lazy<'a, 'b, F>(f: F) -> Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b>>
|
||||
where
|
||||
@@ -729,11 +685,7 @@ where
|
||||
impl<'a> IntoVNode<'a> for Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>> {
|
||||
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
match self {
|
||||
Some(n) => {
|
||||
//
|
||||
// n.into_vnode(cx)
|
||||
n(cx)
|
||||
}
|
||||
Some(lazy) => lazy(cx),
|
||||
None => VNode::Fragment(VFragment {
|
||||
children: &[],
|
||||
is_static: false,
|
||||
@@ -749,20 +701,12 @@ impl<'a> IntoVNode<'a> for Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_> {
|
||||
}
|
||||
}
|
||||
|
||||
// impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> IntoVNode<'a> for Option<LazyNodes<'a, F>> {
|
||||
// fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
// match self {
|
||||
// Some(n) => n.into_vnode(cx),
|
||||
// None => cx.fragment_from_iter(None as Option<VNode>),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl IntoVNode<'_> for &'static str {
|
||||
fn into_vnode(self, cx: NodeFactory) -> VNode {
|
||||
cx.static_text(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoVNode<'_> for Arguments<'_> {
|
||||
fn into_vnode(self, cx: NodeFactory) -> VNode {
|
||||
cx.text(self)
|
||||
|
||||
@@ -29,7 +29,6 @@ pub struct ScopeInner {
|
||||
// Nodes
|
||||
pub(crate) frames: ActiveFrame,
|
||||
pub(crate) caller: *const dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>,
|
||||
pub(crate) child_nodes: ScopeChildren<'static>,
|
||||
|
||||
/*
|
||||
we care about:
|
||||
@@ -181,11 +180,8 @@ impl ScopeInner {
|
||||
parent_idx: Option<ScopeId>,
|
||||
height: u32,
|
||||
subtree: u32,
|
||||
child_nodes: ScopeChildren,
|
||||
shared: EventChannel,
|
||||
) -> Self {
|
||||
let child_nodes = unsafe { child_nodes.extend_lifetime() };
|
||||
|
||||
let schedule_any_update = shared.schedule_any_immediate.clone();
|
||||
|
||||
let memoized_updater = Rc::new(move || schedule_any_update(our_arena_idx));
|
||||
@@ -198,7 +194,6 @@ impl ScopeInner {
|
||||
Self {
|
||||
memoized_updater,
|
||||
shared,
|
||||
child_nodes,
|
||||
caller,
|
||||
parent_idx,
|
||||
our_arena_idx,
|
||||
@@ -218,18 +213,10 @@ impl ScopeInner {
|
||||
pub(crate) fn update_scope_dependencies<'creator_node>(
|
||||
&mut self,
|
||||
caller: &'creator_node dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>,
|
||||
child_nodes: ScopeChildren,
|
||||
) {
|
||||
log::debug!("Updating scope dependencies {:?}", self.our_arena_idx);
|
||||
let caller = caller as *const _;
|
||||
self.caller = unsafe { std::mem::transmute(caller) };
|
||||
|
||||
let child_nodes = unsafe { child_nodes.extend_lifetime() };
|
||||
self.child_nodes = child_nodes;
|
||||
}
|
||||
|
||||
pub(crate) fn child_nodes(&self) -> ScopeChildren {
|
||||
unsafe { self.child_nodes.shorten_lifetime() }
|
||||
}
|
||||
|
||||
/// This method cleans up any references to data held within our hook list. This prevents mutable aliasing from
|
||||
|
||||
@@ -21,7 +21,10 @@ impl TestDom {
|
||||
NodeFactory::new(&self.bump)
|
||||
}
|
||||
|
||||
pub fn render_direct<'a>(&'a self, lazy_nodes: Element<'a>) -> VNode<'a>
|
||||
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>,
|
||||
{
|
||||
@@ -29,7 +32,10 @@ impl TestDom {
|
||||
// lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
|
||||
}
|
||||
|
||||
pub fn render<'a>(&'a self, lazy_nodes: Element<'a>) -> &'a VNode<'a>
|
||||
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>,
|
||||
{
|
||||
@@ -45,7 +51,10 @@ impl TestDom {
|
||||
machine.mutations
|
||||
}
|
||||
|
||||
pub fn create<'a>(&'a self, left: Element<'a>) -> Mutations<'a>
|
||||
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>,
|
||||
@@ -63,10 +72,8 @@ impl TestDom {
|
||||
|
||||
pub fn lazy_diff<'a>(
|
||||
&'a self,
|
||||
left: Element<'a>,
|
||||
right: Element<'a>,
|
||||
// left: LazyNodes<'a, F1>,
|
||||
// right: LazyNodes<'a, F2>,
|
||||
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>,
|
||||
|
||||
@@ -158,7 +158,6 @@ impl VirtualDom {
|
||||
None,
|
||||
0,
|
||||
0,
|
||||
ScopeChildren(&[]),
|
||||
scheduler.pool.channel.clone(),
|
||||
)
|
||||
});
|
||||
@@ -226,7 +225,7 @@ impl VirtualDom {
|
||||
std::mem::transmute(root((Context { scope }, props)))
|
||||
});
|
||||
|
||||
root_scope.update_scope_dependencies(&root_caller, ScopeChildren(&[]));
|
||||
root_scope.update_scope_dependencies(&root_caller);
|
||||
|
||||
drop(root_props);
|
||||
|
||||
|
||||
Reference in new issue
Block a user