From 5a09ec161031abaa01582435839a8077fd80b228 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Mon, 13 Sep 2021 01:14:09 -0400 Subject: [PATCH] wip: more clean up --- packages/core/src/diff.rs | 17 +++++--------- packages/core/src/nodes.rs | 2 ++ packages/core/src/scheduler.rs | 4 ---- packages/core/src/virtual_dom.rs | 39 ++++++++++++++++++++++++++++++-- packages/core/tests/lifecycle.rs | 6 ++--- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 9fe322fe3..73da2bd83 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -113,7 +113,7 @@ pub(crate) struct DiffMachine<'bump> { } pub(crate) struct DiffCfg { - force_diff: bool, + pub force_diff: bool, } impl Default for DiffCfg { fn default() -> Self { @@ -172,6 +172,7 @@ impl<'bump> DiffMachine<'bump> { if let Some(component) = self.vdom.get_scope_mut(id) { let (old, new) = (component.frames.wip_head(), component.frames.fin_head()); self.stack.push(DiffInstruction::Diff { new, old }); + self.work(|| false); } } @@ -535,17 +536,11 @@ impl<'bump> DiffMachine<'bump> { scope.update_scope_dependencies(new.caller.clone(), ScopeChildren(new.children)); // React doesn't automatically memoize, but we do. - let compare = old.comparator.unwrap(); + let props_are_the_same = old.comparator.unwrap(); - match compare(new) { - true => { - // the props are the same... do nothing - } - false => { - // the props are different... - if scope.run_scope(self.vdom) { - self.diff_node(scope.frames.wip_head(), scope.frames.fin_head()); - } + if self.cfg.force_diff || !props_are_the_same(new) { + if scope.run_scope(self.vdom) { + self.diff_node(scope.frames.wip_head(), scope.frames.fin_head()); } } diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 39a90be34..3b8b8ecf9 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -488,6 +488,8 @@ impl<'a> NodeFactory<'a> { std::mem::drop(b); has_dropped = true; + } else { + panic!("Drop props called twice - this is an internal failure of Dioxus"); } } }); diff --git a/packages/core/src/scheduler.rs b/packages/core/src/scheduler.rs index 77eafd595..e4d01800f 100644 --- a/packages/core/src/scheduler.rs +++ b/packages/core/src/scheduler.rs @@ -566,10 +566,6 @@ impl Scheduler { // EventPriority::Low => self.low_priority.dirty_scopes.insert(scope), // }; } - - fn collect_garbage(&mut self, id: ElementId) { - // - } } pub(crate) struct PriorityLane { diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index d7cc4d828..7ce8f816d 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -120,9 +120,10 @@ impl VirtualDom { /// let mutations = dom.rebuild(); /// ``` pub fn new_with_props(root: FC

, root_props: P) -> Self { - let scheduler = Scheduler::new(); + let root_fc = Box::new(root); let root_props: Pin> = Box::pin(root_props); + let props_ptr = root_props.downcast_ref::

().unwrap() as *const P; let root_caller: Box DomTree> = Box::new(move |scope: &Scope| unsafe { @@ -130,6 +131,8 @@ impl VirtualDom { std::mem::transmute(root(Context { props, scope })) }); + let scheduler = Scheduler::new(); + let base_scope = scheduler.pool.insert_scope_with_key(|myidx| { Scope::new( root_caller.as_ref(), @@ -143,7 +146,7 @@ impl VirtualDom { Self { root_caller, - root_fc: Box::new(root), + root_fc, base_scope, scheduler, root_props, @@ -253,6 +256,37 @@ impl VirtualDom { /// Compute a manual diff of the VirtualDOM between states. /// /// This can be useful when state inside the DOM is remotely changed from the outside, but not propogated as an event. + /// + /// In this case, every component will be diffed, even if their props are memoized. This method is intended to be used + /// to force an update of the DOM when the state of the app is changed outside of the app. + /// + /// + /// # Example + /// ```rust + /// #[derive(PartialEq, Props)] + /// struct AppProps { + /// value: Shared<&'static str>, + /// } + /// + /// static App: FC = |cx| { + /// let val = cx.value.borrow(); + /// cx.render(rsx! { div { "{val}" } }) + /// }; + /// + /// let value = Rc::new(RefCell::new("Hello")); + /// let mut dom = VirtualDom::new_with_props( + /// App, + /// AppProps { + /// value: value.clone(), + /// }, + /// ); + /// + /// let _ = dom.rebuild(); + /// + /// *value.borrow_mut() = "goodbye"; + /// + /// let edits = dom.diff(); + /// ``` pub fn diff<'s>(&'s mut self) -> Mutations<'s> { let cur_component = self .scheduler @@ -263,6 +297,7 @@ impl VirtualDom { if cur_component.run_scope(&self.scheduler.pool) { let mut diff_machine: DiffMachine<'s> = DiffMachine::new(Mutations::new(), &mut self.scheduler.pool); + diff_machine.cfg.force_diff = true; diff_machine.diff_scope(self.base_scope); diff_machine.mutations } else { diff --git a/packages/core/tests/lifecycle.rs b/packages/core/tests/lifecycle.rs index 5ce588e75..ad5a8b0f4 100644 --- a/packages/core/tests/lifecycle.rs +++ b/packages/core/tests/lifecycle.rs @@ -13,6 +13,8 @@ type Shared = Rc>; #[test] fn manual_diffing() { + test_logging::set_up_logging(IS_LOGGING_ENABLED); + #[derive(PartialEq, Props)] struct AppProps { value: Shared<&'static str>, @@ -23,9 +25,7 @@ fn manual_diffing() { cx.render(rsx! { div { "{val}" } }) }; - test_logging::set_up_logging(IS_LOGGING_ENABLED); - - let mut value = Rc::new(RefCell::new("Hello")); + let value = Rc::new(RefCell::new("Hello")); let mut dom = VirtualDom::new_with_props( App, AppProps {