From 5a21493fb7162287989bd7c0cd1c496cc3143605 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Mon, 1 Nov 2021 14:03:14 -0400 Subject: [PATCH] wip: remove send requirement on root props --- README.md | 7 +++++-- packages/core/src/scope.rs | 21 +++++++++++++++++++-- packages/core/src/virtual_dom.rs | 32 +++++++++++++++----------------- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index cdad238d0..f27f8236f 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Dioxus is a portable, performant, and ergonomic framework for building cross-platform user experiences in Rust. ```rust -fn App((cx, props): Component<()>) -> Element { +fn App((cx, props): Scope<()>) -> Element { let mut count = use_state(cx, || 0); cx.render(rsx!( @@ -147,8 +147,11 @@ Dioxus is heavily inspired by React, but we want your transition to feel like an | Subtree Memoization | ✅ | ❓ | skip diffing static element subtrees | | Compile-time correct | ✅ | ❓ | Throw errors on invalid template layouts | | Heuristic Engine | ✅ | ❓ | track component memory usage to minimize future allocations | -| Fine-grained reactivity | 🛠 | ❓ | Skip diffing for fine-grain updates | | Effects | 🛠 | ✅ | Run effects after a component has been committed to render | +| Server Components | 🛠 | ✅ | Hybrid components for SPA and Server | +| Bundle Splitting | 👀 | ✅ | Hybrid components for SPA and Server | +| Lazy Components | 👀 | ✅ | Dynamically load the new components as the page is loaded | +| Fine-grained reactivity | 👀 | ❓ | Skip diffing for fine-grain updates | - ✅ = implemented and working - 🛠 = actively being worked on diff --git a/packages/core/src/scope.rs b/packages/core/src/scope.rs index a2ce1d87c..ec5f5ad33 100644 --- a/packages/core/src/scope.rs +++ b/packages/core/src/scope.rs @@ -210,9 +210,9 @@ impl ScopeInner { } } - pub(crate) fn update_scope_dependencies<'creator_node>( + pub(crate) fn update_scope_dependencies( &mut self, - caller: &'creator_node dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>, + caller: &dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>, ) { log::debug!("Updating scope dependencies {:?}", self.our_arena_idx); let caller = caller as *const _; @@ -308,6 +308,23 @@ impl ScopeInner { } } + // run the list of effects + pub(crate) fn run_effects(&mut self, pool: &ResourcePool) { + todo!() + // let mut effects = self.frames.effects.borrow_mut(); + // let mut effects = effects.drain(..).collect::>(); + + // for effect in effects { + // let effect = unsafe { &*effect }; + // let effect = effect.as_ref(); + + // let mut effect = effect.borrow_mut(); + // let mut effect = effect.as_mut(); + + // effect.run(pool); + // } + } + /// Render this component. /// /// Returns true if the scope completed successfully and false if running failed (IE a None error was propagated). diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 412d9c2a0..7f2765c6f 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -61,10 +61,10 @@ pub struct VirtualDom { root_fc: Box, - root_props: Rc, + root_props: Rc, // we need to keep the allocation around, but we don't necessarily use it - _root_caller: RootCaller, + _root_caller: Rc, } impl VirtualDom { @@ -131,7 +131,7 @@ impl VirtualDom { /// /// This is useful when the VirtualDom must be driven from outside a thread and it doesn't make sense to wait for the /// VirtualDom to be created just to retrieve its channel receiver. - pub fn new_with_props_and_scheduler( + pub fn new_with_props_and_scheduler( root: FC

, root_props: P, sender: UnboundedSender, @@ -139,15 +139,16 @@ impl VirtualDom { ) -> Self { let root_fc = Box::new(root); - let root_props: Rc = Rc::new(root_props); + let root_props: Rc = Rc::new(root_props); - let _p = root_props.clone(); - // Safety: this callback is only valid for the lifetime of the root props - let root_caller: Rc Element> = - Rc::new(move |scope: &ScopeInner| unsafe { - let props = _p.downcast_ref::

().unwrap(); - std::mem::transmute(root((Context { scope }, props))) - }); + let props = root_props.clone(); + + let root_caller: Rc Element> = Rc::new(move |scope: &ScopeInner| { + let props = props.downcast_ref::

().unwrap(); + let node = root((Context { scope }, props)); + // cast into the right lifetime + unsafe { std::mem::transmute(node) } + }); let scheduler = Scheduler::new(sender, receiver); @@ -163,7 +164,7 @@ impl VirtualDom { }); Self { - _root_caller: RootCaller(root_caller), + _root_caller: Rc::new(root_caller), root_fc, base_scope, scheduler, @@ -204,14 +205,14 @@ impl VirtualDom { /// ``` pub fn update_root_props

(&mut self, root_props: P) -> Option where - P: 'static + Send, + P: 'static, { let root_scope = self.scheduler.pool.get_scope_mut(self.base_scope).unwrap(); // Pre-emptively drop any downstream references of the old props root_scope.ensure_drop_safety(&self.scheduler.pool); - let mut root_props: Rc = Rc::new(root_props); + let mut root_props: Rc = Rc::new(root_props); if let Some(props_ptr) = root_props.downcast_ref::

().map(|p| p as *const P) { // Swap the old props and new props @@ -394,6 +395,3 @@ impl VirtualDom { } } } - -// we never actually use the contents of this root caller -struct RootCaller(Rc Fn(&'b ScopeInner) -> Element<'b> + 'static>);