浏览代码

debugging: add some more debug tooling

Jonathan Kelley 3 年之前
父节点
当前提交
cbd471fa46
共有 4 个文件被更改,包括 44 次插入17 次删除
  1. 20 4
      packages/core/src/diff.rs
  2. 7 9
      packages/core/src/nodes.rs
  3. 4 4
      packages/core/src/scopes.rs
  4. 13 0
      packages/core/src/virtual_dom.rs

+ 20 - 4
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();
                     }
                 }

+ 7 - 9
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(),
         }
     }
 }

+ 4 - 4
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

+ 13 - 0
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);