From cbd471fa46d80fb3ea4d5e484be4bf62a31f770f Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Mon, 31 Jan 2022 01:24:11 -0500 Subject: [PATCH] debugging: add some more debug tooling --- packages/core/src/diff.rs | 24 ++++++++++++++++++++---- packages/core/src/nodes.rs | 16 +++++++--------- packages/core/src/scopes.rs | 8 ++++---- packages/core/src/virtual_dom.rs | 13 +++++++++++++ 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index d790292c8..6f7f12fa4 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -406,10 +406,14 @@ impl<'b> AsyncDiffState<'b> { fn diff_fragment_nodes(&mut self, old: &'b VFragment<'b>, new: &'b VFragment<'b>) { // This is the case where options or direct vnodes might be used. // In this case, it's faster to just skip ahead to their diff - if old.children.len() == 1 && new.children.len() == 1 { - self.diff_node(&old.children[0], &new.children[0]); - return; - } + // if old.children.len() == 1 && new.children.len() == 1 { + // if std::ptr::eq(old, new) { + // log::debug!("skipping fragment diff - fragment is the same"); + // return; + // } + // self.diff_node(&old.children[0], &new.children[0]); + // return; + // } debug_assert!(!old.children.is_empty()); debug_assert!(!new.children.is_empty()); @@ -437,6 +441,11 @@ impl<'b> AsyncDiffState<'b> { // Fragment nodes cannot generate empty children lists, so we can assume that when a list is empty, it belongs only // to an element, and appending makes sense. fn diff_children(&mut self, old: &'b [VNode<'b>], new: &'b [VNode<'b>]) { + if std::ptr::eq(old, new) { + log::debug!("skipping fragment diff - fragment is the same"); + return; + } + // Remember, fragments can never be empty (they always have a single child) match (old, new) { ([], []) => {} @@ -484,7 +493,13 @@ impl<'b> AsyncDiffState<'b> { Ordering::Equal => {} } + // panic!( + // "diff_children: new_is_keyed: {:#?}, old_is_keyed: {:#?}. stack: {:#?}, oldptr: {:#?}, newptr: {:#?}", + // old, new, self.scope_stack, old as *const _, new as *const _ + // ); + for (new, old) in new.iter().zip(old.iter()) { + log::debug!("diffing nonkeyed {:#?} {:#?}", old, new); self.diff_node(old, new); } } @@ -893,6 +908,7 @@ impl<'b> AsyncDiffState<'b> { // we can only remove this node if the originator is actively if self.scope_stack.contains(&c.originator) { + log::debug!("I am allowed to remove component because scope stack contains originator. Scope stack: {:#?} {:#?} {:#?}", self.scope_stack, c.originator, c.scope); self.scopes.try_remove(scope_id).unwrap(); } } diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 74234a84c..2f1453e1d 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -182,15 +182,13 @@ impl Debug for VNode<'_> { VNode::Fragment(frag) => { write!(s, "VNode::VFragment {{ children: {:?} }}", frag.children) } - VNode::Component(comp) => { - s.debug_struct("VNode::VComponent") - .field("fnptr", &comp.user_fc) - .field("key", &comp.key) - .field("scope", &comp.scope) - .field("originator", &comp.originator) - .finish() - //write!(s, "VNode::VComponent {{ fc: {:?}}}", comp.user_fc) - } + VNode::Component(comp) => s + .debug_struct("VNode::VComponent") + .field("fnptr", &comp.user_fc) + .field("key", &comp.key) + .field("scope", &comp.scope) + .field("originator", &comp.originator) + .finish(), } } } diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs index 0ebbea9b9..93a0c94a7 100644 --- a/packages/core/src/scopes.rs +++ b/packages/core/src/scopes.rs @@ -98,7 +98,8 @@ impl ScopeArena { let height = parent_scope .map(|id| self.get_scope(id).map(|scope| scope.height)) .flatten() - .unwrap_or_default(); + .unwrap_or_default() + + 1; let parent_scope = parent_scope.map(|f| self.get_scope_raw(f)).flatten(); @@ -203,9 +204,8 @@ impl ScopeArena { } pub fn collect_garbage(&self, id: ElementId) { - // println!("collecting garbage for {:?}", id); - // log::debug!("collecting garbage for {:?}", id); - self.nodes.borrow_mut().remove(id.0); + let node = self.nodes.borrow_mut().remove(id.0); + log::debug!("collecting garbage for {:?}, {:?}", id, unsafe { &*node }); } /// This method cleans up any references to data held within our hook list. This prevents mutable aliasing from diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 032aa6198..613ea9292 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -462,14 +462,27 @@ impl VirtualDom { self.dirty_scopes .retain(|id| scopes.get_scope(*id).is_some()); + log::debug!("dirty_scopes: {:?}", self.dirty_scopes); + + for id in &self.dirty_scopes { + let scope = scopes.get_scope(*id).unwrap(); + + log::debug!("dirty scope: {:?} with height {:?}", id, scope.height); + } + self.dirty_scopes.sort_by(|a, b| { let h1 = scopes.get_scope(*a).unwrap().height; let h2 = scopes.get_scope(*b).unwrap().height; h1.cmp(&h2).reverse() }); + log::debug!("dirty_scopes: {:?}", self.dirty_scopes); + if let Some(scopeid) = self.dirty_scopes.pop() { + log::debug!("diffing scope {:?}", scopeid); if !ran_scopes.contains(&scopeid) { + log::debug!("running scope scope {:?}", scopeid); + ran_scopes.insert(scopeid); self.scopes.run_scope(scopeid);