From 31702dbf878dd0207d101f7869ebefd2bb9f6860 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 27 Aug 2021 09:53:26 -0400 Subject: [PATCH] feat: wire up resource pool --- packages/core/src/childiter.rs | 3 +- packages/core/src/diff.rs | 16 +++---- packages/core/src/nodes.rs | 73 ++++++++++++++------------------ packages/core/src/scope.rs | 56 ++++++++++++------------ packages/core/src/virtual_dom.rs | 4 +- packages/ssr/src/lib.rs | 2 +- 6 files changed, 73 insertions(+), 81 deletions(-) diff --git a/packages/core/src/childiter.rs b/packages/core/src/childiter.rs index 3b762c547..2f5ffde96 100644 --- a/packages/core/src/childiter.rs +++ b/packages/core/src/childiter.rs @@ -74,7 +74,8 @@ impl<'a> Iterator for RealChildIterator<'a> { // For components, we load their root and push them onto the stack VNode::Component(sc) => { let scope = - unsafe { self.scopes.get_scope(sc.ass_scope.get().unwrap()) }.unwrap(); + unsafe { self.scopes.get_scope(sc.associated_scope.get().unwrap()) } + .unwrap(); // let scope = self.scopes.get(sc.ass_scope.get().unwrap()).unwrap(); // Simply swap the current node on the stack with the root of the component diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 3c8b3ebb9..59011301e 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -341,7 +341,7 @@ impl<'bump> DiffMachine<'bump> { }); // Actually initialize the caller's slot with the right address - vcomponent.ass_scope.set(Some(new_idx)); + vcomponent.associated_scope.set(Some(new_idx)); if !vcomponent.can_memoize { let cur_scope = self.vdom.get_scope_mut(parent_idx).unwrap(); @@ -357,7 +357,7 @@ impl<'bump> DiffMachine<'bump> { let new_component = self.vdom.get_scope_mut(new_idx).unwrap(); // Run the scope for one iteration to initialize it - if new_component.run_scope() { + if new_component.run_scope(self.vdom) { // Take the node that was just generated from running the component let nextnode = new_component.frames.fin_head(); self.stack.create_component(new_idx, nextnode); @@ -505,7 +505,7 @@ impl<'bump> DiffMachine<'bump> { old: &'bump VComponent<'bump>, new: &'bump VComponent<'bump>, ) { - let scope_addr = old.ass_scope.get().unwrap(); + let scope_addr = old.associated_scope.get().unwrap(); // Make sure we're dealing with the same component (by function pointer) if old.user_fc == new.user_fc { @@ -513,7 +513,7 @@ impl<'bump> DiffMachine<'bump> { self.stack.scope_stack.push(scope_addr); // Make sure the new component vnode is referencing the right scope id - new.ass_scope.set(Some(scope_addr)); + new.associated_scope.set(Some(scope_addr)); // make sure the component's caller function is up to date let scope = self.vdom.get_scope_mut(scope_addr).unwrap(); @@ -529,7 +529,7 @@ impl<'bump> DiffMachine<'bump> { } false => { // the props are different... - if scope.run_scope() { + if scope.run_scope(self.vdom) { self.diff_node(scope.frames.wip_head(), scope.frames.fin_head()); } } @@ -967,7 +967,7 @@ impl<'bump> DiffMachine<'bump> { search_node = frag.children.last(); } VNode::Component(el) => { - let scope_id = el.ass_scope.get().unwrap(); + let scope_id = el.associated_scope.get().unwrap(); let scope = self.vdom.get_scope(scope_id).unwrap(); search_node = Some(scope.root()); } @@ -985,7 +985,7 @@ impl<'bump> DiffMachine<'bump> { search_node = Some(&frag.children[0]); } VNode::Component(el) => { - let scope_id = el.ass_scope.get().unwrap(); + let scope_id = el.associated_scope.get().unwrap(); let scope = self.vdom.get_scope(scope_id).unwrap(); search_node = Some(scope.root()); } @@ -1043,7 +1043,7 @@ impl<'bump> DiffMachine<'bump> { } VNode::Component(c) => { - let scope_id = c.ass_scope.get().unwrap(); + let scope_id = c.associated_scope.get().unwrap(); let scope = self.vdom.get_scope(scope_id).unwrap(); let root = scope.root(); self.remove_nodes(Some(root)); diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 5e2db6ef8..a66e96727 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -13,7 +13,6 @@ use std::{ cell::{Cell, RefCell}, fmt::{Arguments, Debug, Formatter}, marker::PhantomData, - mem::ManuallyDrop, rc::Rc, }; @@ -43,8 +42,8 @@ impl<'src> VNode<'src> { VNode::Component(c) => c.key, VNode::Fragment(f) => f.key, VNode::Text(_t) => None, - VNode::Suspended(s) => None, - VNode::Anchor(f) => None, + VNode::Suspended(_s) => None, + VNode::Anchor(_f) => None, } } pub fn direct_id(&self) -> ElementId { @@ -68,16 +67,36 @@ pub struct VAnchor { pub struct VText<'src> { pub text: &'src str, + pub dom_id: Cell>, + pub is_static: bool, } pub struct VFragment<'src> { - pub children: &'src [VNode<'src>], pub key: Option<&'src str>, + + pub children: &'src [VNode<'src>], + pub is_static: bool, } +pub struct VElement<'a> { + pub tag_name: &'static str, + + pub namespace: Option<&'static str>, + + pub key: Option<&'a str>, + + pub dom_id: Cell>, + + pub listeners: &'a [Listener<'a>], + + pub attributes: &'a [Attribute<'a>], + + pub children: &'a [VNode<'a>], +} + pub trait DioxusElement { const TAG_NAME: &'static str; const NAME_SPACE: Option<&'static str>; @@ -91,19 +110,6 @@ pub trait DioxusElement { } } -pub struct VElement<'a> { - pub key: Option<&'a str>, - - // tag is always static - pub tag_name: &'static str, - pub namespace: Option<&'static str>, - pub dom_id: Cell>, - - pub listeners: &'a [Listener<'a>], - pub attributes: &'a [Attribute<'a>], - pub children: &'a [VNode<'a>], -} - /// An attribute on a DOM node, such as `id="my-thing"` or /// `href="https://example.com"`. #[derive(Clone, Debug)] @@ -131,22 +137,12 @@ pub struct Listener<'bump> { pub(crate) callback: RefCell>>, } -impl Listener<'_> { - // serialize the listener event stuff to a string - pub fn serialize(&self) { - // - } - pub fn deserialize() { - // - } -} - /// Virtual Components for custom user-defined components /// Only supports the functional syntax pub struct VComponent<'src> { pub key: Option<&'src str>, - pub ass_scope: Cell>, + pub associated_scope: Cell>, pub(crate) caller: Rc DomTree>, @@ -158,21 +154,19 @@ pub struct VComponent<'src> { pub is_static: bool, - pub can_memoize: bool, + pub(crate) can_memoize: bool, - pub name: &'static str, - - // a pointer into the bump arena (given by the 'src lifetime) + // Raw pointer into the bump arena for the props of the component pub(crate) raw_props: *const (), - // a pointer to the raw fn typ + // Function pointer to the FC that was used to generate this component pub(crate) user_fc: *const (), } pub struct VSuspended<'a> { - pub dom_id: Cell>, pub task_id: u64, - pub callback: RefCell) -> DomTree<'a>>>, + pub dom_id: Cell>, + pub(crate) callback: RefCell) -> DomTree<'a>>>, } /// This struct provides an ergonomic API to quickly build VNodes. @@ -350,10 +344,8 @@ impl<'a> NodeFactory<'a> { { let bump = self.bump(); - let name = crate::util::type_name_of(component); - // We don't want the fat part of the fat pointer - // This function does static dispatch so we don't need any VTable stuff + // THe "Fat" part is provided on next-render let children: &'a V = bump.alloc(children); let children = children.as_ref(); @@ -415,9 +407,8 @@ impl<'a> NodeFactory<'a> { is_static, drop_props: RefCell::new(Some(drop_props)), can_memoize: P::IS_STATIC, - ass_scope: Cell::new(None), + associated_scope: Cell::new(None), key, - name, })) } @@ -663,7 +654,7 @@ impl Debug for VNode<'_> { VNode::Component(comp) => write!( s, "VComponent {{ fc: {:?}, children: {:?} }}", - comp.name, comp.children + comp.user_fc, comp.children ), } } diff --git a/packages/core/src/scope.rs b/packages/core/src/scope.rs index 081b1bd8f..c9350b6de 100644 --- a/packages/core/src/scope.rs +++ b/packages/core/src/scope.rs @@ -115,12 +115,12 @@ impl Scope { /// Returns true if the scope completed successfully /// - pub(crate) fn run_scope<'sel>(&'sel mut self) -> bool { + pub(crate) fn run_scope<'sel>(&'sel mut self, pool: &ResourcePool) -> bool { // Cycle to the next frame and then reset it // This breaks any latent references, invalidating every pointer referencing into it. // Remove all the outdated listeners - self.ensure_drop_safety(); + self.ensure_drop_safety(pool); // Safety: // - We dropped the listeners, so no more &mut T can be used while these are held @@ -154,7 +154,7 @@ impl Scope { /// /// Refrences to hook data can only be stored in listeners and component props. During diffing, we make sure to log /// all listeners and borrowed props so we can clear them here. - fn ensure_drop_safety(&mut self) { + fn ensure_drop_safety(&mut self, pool: &ResourcePool) { // make sure all garabge is collected before trying to proceed with anything else debug_assert!( self.pending_garbage.borrow().is_empty(), @@ -163,33 +163,33 @@ impl Scope { // todo!("arch changes"); - // // make sure we drop all borrowed props manually to guarantee that their drop implementation is called before we - // // run the hooks (which hold an &mut Referrence) - // // right now, we don't drop - // // let vdom = &self.vdom; - // self.borrowed_props - // .get_mut() - // .drain(..) - // .map(|li| unsafe { &*li }) - // .for_each(|comp| { - // // First drop the component's undropped references - // let scope_id = comp.ass_scope.get().unwrap(); - // let scope = unsafe { vdom.get_scope_mut(scope_id) }.unwrap(); - // scope.ensure_drop_safety(); + // make sure we drop all borrowed props manually to guarantee that their drop implementation is called before we + // run the hooks (which hold an &mut Referrence) + // right now, we don't drop + // let vdom = &self.vdom; + self.borrowed_props + .get_mut() + .drain(..) + .map(|li| unsafe { &*li }) + .for_each(|comp| { + // First drop the component's undropped references + let scope_id = comp.associated_scope.get().unwrap(); + let scope = pool.get_scope_mut(scope_id).unwrap(); + scope.ensure_drop_safety(pool); - // // Now, drop our own reference - // let mut dropper = comp.drop_props.borrow_mut().take().unwrap(); - // dropper(); - // }); + // Now, drop our own reference + let mut dropper = comp.drop_props.borrow_mut().take().unwrap(); + dropper(); + }); - // // Now that all the references are gone, we can safely drop our own references in our listeners. - // self.listeners - // .get_mut() - // .drain(..) - // .map(|li| unsafe { &*li }) - // .for_each(|listener| { - // listener.callback.borrow_mut().take(); - // }); + // Now that all the references are gone, we can safely drop our own references in our listeners. + self.listeners + .get_mut() + .drain(..) + .map(|li| unsafe { &*li }) + .for_each(|listener| { + listener.callback.borrow_mut().take(); + }); } // A safe wrapper around calling listeners diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 6b152b77b..f8d3ebb61 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -168,7 +168,7 @@ impl VirtualDom { .expect("The base scope should never be moved"); // // We run the component. If it succeeds, then we can diff it and add the changes to the dom. - if cur_component.run_scope() { + if cur_component.run_scope(&self.scheduler.pool) { diff_machine .stack .create_node(cur_component.frames.fin_head(), MountType::Append); @@ -204,7 +204,7 @@ impl VirtualDom { .get_scope_mut(self.base_scope) .expect("The base scope should never be moved"); - if cur_component.run_scope() { + if cur_component.run_scope(&self.scheduler.pool) { diff_machine.diff_scope(self.base_scope).await; } diff --git a/packages/ssr/src/lib.rs b/packages/ssr/src/lib.rs index 00c028cd1..e8cc94689 100644 --- a/packages/ssr/src/lib.rs +++ b/packages/ssr/src/lib.rs @@ -169,7 +169,7 @@ impl<'a> TextRenderer<'a> { } } VNode::Component(vcomp) => { - let idx = vcomp.ass_scope.get().unwrap(); + let idx = vcomp.associated_scope.get().unwrap(); match (self.vdom, self.cfg.skip_components) { (Some(vdom), false) => { let new_node = vdom.get_scope(idx).unwrap().root();