Răsfoiți Sursa

fix: get rollover working

Jonathan Kelley 2 ani în urmă
părinte
comite
5c20e651da

+ 1 - 0
Cargo.toml

@@ -57,6 +57,7 @@ reqwest = { version = "0.11.9", features = ["json"] }
 fern = { version = "0.6.0", features = ["colored"] }
 thiserror = "1.0.30"
 env_logger = "0.9.0"
+simple_logger = "4.0.0"
 
 [profile.release]
 opt-level = 3

+ 10 - 1
packages/router/examples/simple_desktop.rs → examples/simple_desktop.rs

@@ -20,6 +20,9 @@ fn app(cx: Scope) -> Element {
                 Link { to: "/blog", li { "blog" } }
                 Link { to: "/blog/tim", li { "tims' blog" } }
                 Link { to: "/blog/bill", li { "bills' blog" } }
+                Link { to: "/blog/james",
+                        li { "james amazing' blog" }
+                }
                 Link { to: "/apples", li { "go to apples" } }
             }
             Route { to: "/", Home {} }
@@ -42,11 +45,17 @@ fn BlogList(cx: Scope) -> Element {
 }
 
 fn BlogPost(cx: Scope) -> Element {
+
     let Some(id) = use_route(cx).segment("id") else {
         return cx.render(rsx! { div { "No blog post id" } })
     };
 
     log::debug!("rendering blog post {}", id);
 
-    cx.render(rsx! { div { "{id:?}" } })
+    cx.render(rsx! {
+        div {
+            h3 { "blog post: {id:?}"  }
+            Link { to: "/blog/", "back to blog list" }
+        }
+    })
 }

+ 1 - 0
packages/core/Cargo.toml

@@ -36,6 +36,7 @@ serde = { version = "1", features = ["derive"], optional = true }
 anyhow = "1.0.66"
 
 smallbox = "0.8.1"
+log = "0.4.17"
 
 [dev-dependencies]
 tokio = { version = "*", features = ["full"] }

+ 7 - 4
packages/core/src/arena.rs

@@ -108,9 +108,10 @@ impl VirtualDom {
         });
 
         for root in node.root_ids {
-            let id = root.get().unwrap();
-            if id.0 != 0 {
-                self.try_reclaim(id);
+            if let Some(id) = root.get() {
+                if id.0 != 0 {
+                    self.try_reclaim(id);
+                }
             }
         }
     }
@@ -131,7 +132,9 @@ impl VirtualDom {
         node.dynamic_nodes.iter().for_each(|child| match child {
             // Only descend if the props are borrowed
             DynamicNode::Component(c) if !c.static_props => {
-                self.ensure_drop_safety(c.scope.get().unwrap());
+                if let Some(scope) = c.scope.get() {
+                    self.ensure_drop_safety(scope);
+                }
                 c.props.take();
             }
 

+ 35 - 16
packages/core/src/diff.rs

@@ -113,7 +113,7 @@ impl<'b> VirtualDom {
         idx: usize,
     ) {
         match (left_node, right_node) {
-            (Text(left), Text(right)) => self.diff_vtext(left, right),
+            (Text(left), Text(right)) => self.diff_vtext(left, right, node),
             (Fragment(left), Fragment(right)) => self.diff_non_empty_fragment(left, right),
             (Placeholder(left), Placeholder(right)) => right.id.set(left.id.get()),
             (Component(left), Component(right)) => self.diff_vcomponent(left, right, node, idx),
@@ -174,6 +174,10 @@ impl<'b> VirtualDom {
         right_template: &'b VNode<'b>,
         idx: usize,
     ) {
+        if std::ptr::eq(left, right) {
+            return;
+        }
+
         // Replace components that have different render fns
         if left.render_fn != right.render_fn {
             let created = self.create_component_node(right_template, right, idx);
@@ -193,7 +197,16 @@ impl<'b> VirtualDom {
         }
 
         // Make sure the new vcomponent has the right scopeid associated to it
-        let scope_id = left.scope.get().unwrap();
+        let Some(scope_id) = left.scope.get() else {
+            return;
+        };
+        // let scope_id = left.scope.get().unwrap_or_else(|| {
+        //     panic!(
+        //         "A component should always have a scope associated to it. {:?}\n {:#?}",
+        //         right.name,
+        //         std::backtrace::Backtrace::force_capture()
+        //     )
+        // });
 
         right.scope.set(Some(scope_id));
 
@@ -260,21 +273,26 @@ impl<'b> VirtualDom {
     /// }
     /// ```
     fn light_diff_templates(&mut self, left: &'b VNode<'b>, right: &'b VNode<'b>) {
-        match matching_components(left, right) {
-            None => self.replace(left, right),
-            Some(components) => components
-                .into_iter()
-                .enumerate()
-                .for_each(|(idx, (l, r))| self.diff_vcomponent(l, r, right, idx)),
-        }
+        self.replace(left, right)
+        // match matching_components(left, right) {
+        //     None => self.replace(left, right),
+        //     Some(components) => components
+        //         .into_iter()
+        //         .enumerate()
+        //         .for_each(|(idx, (l, r))| self.diff_vcomponent(l, r, right, idx)),
+        // }
     }
 
     /// Diff the two text nodes
     ///
     /// This just moves the ID of the old node over to the new node, and then sets the text of the new node if it's
     /// different.
-    fn diff_vtext(&mut self, left: &'b VText<'b>, right: &'b VText<'b>) {
-        let id = left.id.get().unwrap();
+    fn diff_vtext(&mut self, left: &'b VText<'b>, right: &'b VText<'b>, node: &'b VNode<'b>) {
+        let id = left
+            .id
+            .get()
+            .unwrap_or_else(|| self.next_element(node, &[0]));
+
         right.id.set(Some(id));
         if left.value != right.value {
             let value = unsafe { std::mem::transmute(right.value) };
@@ -327,11 +345,12 @@ impl<'b> VirtualDom {
 
             match dyn_node {
                 Component(comp) => {
-                    let scope = comp.scope.take().unwrap();
-                    match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
-                        RenderReturn::Sync(Ok(t)) => self.clean_up_node(t),
-                        _ => todo!("cannot handle nonstandard nodes"),
-                    };
+                    if let Some(scope) = comp.scope.take() {
+                        match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
+                            RenderReturn::Sync(Ok(t)) => self.clean_up_node(t),
+                            _ => todo!("cannot handle nonstandard nodes"),
+                        };
+                    }
                 }
                 Text(t) => {
                     if let Some(id) = t.id.take() {

+ 0 - 3
packages/core/src/virtual_dom.rs

@@ -520,7 +520,6 @@ impl VirtualDom {
         pin_mut!(deadline);
 
         self.process_events();
-        println!("rendering with dirty scopes {:#?}", self.dirty_scopes);
 
         loop {
             // first, unload any complete suspense trees
@@ -548,8 +547,6 @@ impl VirtualDom {
             if let Some(dirty) = self.dirty_scopes.iter().next().cloned() {
                 self.dirty_scopes.remove(&dirty);
 
-                println!("diffing scope {:?}", dirty);
-
                 // if the scope is currently suspended, then we should skip it, ignoring any tasks calling for an update
                 if self.is_scope_suspended(dirty.id) {
                     continue;

+ 7 - 1
packages/router/examples/simple.rs

@@ -16,6 +16,7 @@ fn app(cx: Scope) -> Element {
                 Link { to: "/blog", li { "blog" } }
                 Link { to: "/blog/tim", li { "tims' blog" } }
                 Link { to: "/blog/bill", li { "bills' blog" } }
+                Link { to: "/blog/james", li { "james amazing' blog" } }
                 Link { to: "/apples", li { "go to apples" } }
             }
             Route { to: "/", Home {} }
@@ -42,5 +43,10 @@ fn BlogPost(cx: Scope) -> Element {
 
     log::trace!("rendering blog post {}", id);
 
-    cx.render(rsx! { div { "{id:?}" } })
+    cx.render(rsx! {
+        div {
+            h3 { "blog post: {id:?}"  }
+            Link { to: "/blog/", "back to blog list" }
+        }
+    })
 }