Browse Source

Tests: add tests for hotreload and recurse into children

Jonathan Kelley 1 year ago
parent
commit
e4f65b7260

+ 25 - 7
packages/core/src/virtual_dom.rs

@@ -2,20 +2,19 @@
 //!
 //! This module provides the primary mechanics to create a hook-based, concurrent VDOM for Rust.
 
-use crate::innerlude::{DirtyTasks, ScopeOrder};
 use crate::Task;
 use crate::{
     any_props::AnyProps,
     arena::ElementId,
     innerlude::{
-        ElementRef, ErrorBoundary, NoOpMutations, SchedulerMsg, ScopeState, VNodeMount, VProps,
-        WriteMutations,
+        DirtyTasks, ElementRef, ErrorBoundary, NoOpMutations, SchedulerMsg, ScopeOrder, ScopeState,
+        VNodeMount, VProps, WriteMutations,
     },
     nodes::RenderReturn,
     nodes::{Template, TemplateId},
     runtime::{Runtime, RuntimeGuard},
     scopes::ScopeId,
-    AttributeValue, ComponentFunction, Element, Event, Mutations,
+    AttributeValue, ComponentFunction, Element, Event, Mutations, VNode,
 };
 use futures_util::StreamExt;
 use rustc_hash::FxHashMap;
@@ -538,10 +537,29 @@ impl VirtualDom {
         // iterating a slab is very inefficient, but this is a rare operation that will only happen during development so it's fine
         let mut dirty = Vec::new();
         for (id, scope) in self.scopes.iter() {
+            // Recurse into the dynamic nodes of the existing mounted node to see if the template is alive in the tree
+            fn check_node_for_templates(node: &VNode, template: Template) -> bool {
+                let this_template_name = node.template.get().name.rsplit_once(':').unwrap().0;
+
+                if this_template_name == template.name.rsplit_once(':').unwrap().0 {
+                    return true;
+                }
+
+                for dynamic in node.dynamic_nodes.iter() {
+                    if let crate::DynamicNode::Fragment(nodes) = dynamic {
+                        for node in nodes {
+                            if check_node_for_templates(node, template) {
+                                return true;
+                            }
+                        }
+                    }
+                }
+
+                false
+            }
+
             if let Some(RenderReturn::Ready(sync)) = scope.try_root_node() {
-                if sync.template.get().name.rsplit_once(':').unwrap().0
-                    == template.name.rsplit_once(':').unwrap().0
-                {
+                if check_node_for_templates(&sync, template) {
                     dirty.push(ScopeId(id));
                 }
             }

+ 12 - 20
packages/rsx/src/hot_reload/hot_reload_diff.rs

@@ -1,6 +1,6 @@
 use proc_macro2::TokenStream;
 use quote::ToTokens;
-use syn::{Expr, File, Item, Macro};
+use syn::{Expr, File, Item, Macro, Stmt, TraitItem};
 
 #[derive(Debug)]
 pub enum DiffResult {
@@ -218,7 +218,7 @@ fn find_rsx_trait(
     }
     for (new_item, old_item) in new_item.items.iter().zip(old_item.items.iter()) {
         if match (new_item, old_item) {
-            (syn::TraitItem::Const(new_item), syn::TraitItem::Const(old_item)) => {
+            (TraitItem::Const(new_item), TraitItem::Const(old_item)) => {
                 if let (Some((_, new_expr)), Some((_, old_expr))) =
                     (&new_item.default, &old_item.default)
                 {
@@ -227,7 +227,7 @@ fn find_rsx_trait(
                     true
                 }
             }
-            (syn::TraitItem::Fn(new_item), syn::TraitItem::Fn(old_item)) => {
+            (TraitItem::Fn(new_item), TraitItem::Fn(old_item)) => {
                 match (&new_item.default, &old_item.default) {
                     (Some(new_block), Some(old_block)) => {
                         find_rsx_block(new_block, old_block, rsx_calls)
@@ -236,13 +236,9 @@ fn find_rsx_trait(
                     _ => true,
                 }
             }
-            (syn::TraitItem::Type(new_item), syn::TraitItem::Type(old_item)) => {
-                old_item != new_item
-            }
-            (syn::TraitItem::Macro(new_item), syn::TraitItem::Macro(old_item)) => {
-                old_item != new_item
-            }
-            (syn::TraitItem::Verbatim(stream), syn::TraitItem::Verbatim(stream2)) => {
+            (TraitItem::Type(new_item), TraitItem::Type(old_item)) => old_item != new_item,
+            (TraitItem::Macro(new_item), TraitItem::Macro(old_item)) => old_item != new_item,
+            (TraitItem::Verbatim(stream), TraitItem::Verbatim(stream2)) => {
                 stream.to_string() != stream2.to_string()
             }
             _ => true,
@@ -280,17 +276,13 @@ fn find_rsx_block(
     new_block.brace_token != old_block.brace_token
 }
 
-fn find_rsx_stmt(
-    new_stmt: &syn::Stmt,
-    old_stmt: &syn::Stmt,
-    rsx_calls: &mut Vec<ChangedRsx>,
-) -> bool {
+fn find_rsx_stmt(new_stmt: &Stmt, old_stmt: &Stmt, rsx_calls: &mut Vec<ChangedRsx>) -> bool {
     match (new_stmt, old_stmt) {
-        (syn::Stmt::Local(new_local), syn::Stmt::Local(old_local)) => {
+        (Stmt::Local(new_local), Stmt::Local(old_local)) => {
             (match (&new_local.init, &old_local.init) {
                 (Some(new_local), Some(old_local)) => {
                     find_rsx_expr(&new_local.expr, &old_local.expr, rsx_calls)
-                        || new_local != old_local
+                        || new_local.diverge != old_local.diverge
                 }
                 (None, None) => false,
                 _ => true,
@@ -299,13 +291,13 @@ fn find_rsx_stmt(
                 || new_local.pat != old_local.pat
                 || new_local.semi_token != old_local.semi_token)
         }
-        (syn::Stmt::Item(new_item), syn::Stmt::Item(old_item)) => {
+        (Stmt::Item(new_item), Stmt::Item(old_item)) => {
             find_rsx_item(new_item, old_item, rsx_calls)
         }
-        (syn::Stmt::Expr(new_expr, _), syn::Stmt::Expr(old_expr, _)) => {
+        (Stmt::Expr(new_expr, _), Stmt::Expr(old_expr, _)) => {
             find_rsx_expr(new_expr, old_expr, rsx_calls)
         }
-        (syn::Stmt::Macro(new_macro), syn::Stmt::Macro(old_macro)) => {
+        (Stmt::Macro(new_macro), Stmt::Macro(old_macro)) => {
             find_rsx_macro(&new_macro.mac, &old_macro.mac, rsx_calls)
                 || new_macro.attrs != old_macro.attrs
                 || new_macro.semi_token != old_macro.semi_token

+ 28 - 4
packages/rsx/tests/hotreloads.rs

@@ -1,4 +1,4 @@
-use dioxus_rsx::hot_reload::diff_rsx;
+use dioxus_rsx::hot_reload::{diff_rsx, DiffResult};
 use syn::File;
 
 fn load_files(old: &str, new: &str) -> (File, File) {
@@ -10,10 +10,34 @@ fn load_files(old: &str, new: &str) -> (File, File) {
 #[test]
 fn hotreloads() {
     let (old, new) = load_files(
-        include_str!("./valid_samples/old.expr.rsx"),
-        include_str!("./valid_samples/new.expr.rsx"),
+        include_str!("./valid/expr.old.rsx"),
+        include_str!("./valid/expr.new.rsx"),
+    );
+
+    assert!(matches!(
+        diff_rsx(&new, &old),
+        DiffResult::RsxChanged { .. }
+    ));
+
+    let (old, new) = load_files(
+        include_str!("./valid/let.old.rsx"),
+        include_str!("./valid/let.new.rsx"),
+    );
+
+    assert!(matches!(
+        diff_rsx(&new, &old),
+        DiffResult::RsxChanged { .. }
+    ));
+}
+
+#[test]
+fn doesnt_hotreload() {
+    let (old, new) = load_files(
+        include_str!("./invalid/changedexpr.old.rsx"),
+        include_str!("./invalid/changedexpr.new.rsx"),
     );
 
     let res = diff_rsx(&new, &old);
-    dbg!(res);
+    dbg!(&res);
+    assert!(matches!(res, DiffResult::CodeChanged(_)));
 }

+ 9 - 0
packages/rsx/tests/invalid/changedexpr.new.rsx

@@ -0,0 +1,9 @@
+use dioxus::prelude::*;
+
+pub fn CoolChild() -> Element {
+    rsx! {
+        div {
+            {some_expr()}
+        }
+    }
+}

+ 11 - 0
packages/rsx/tests/invalid/changedexpr.old.rsx

@@ -0,0 +1,11 @@
+use dioxus::prelude::*;
+
+pub fn CoolChild() -> Element {
+    let a = 123;
+
+    rsx! {
+        div {
+            {some_expr()}
+        }
+    }
+}

+ 0 - 0
packages/rsx/tests/valid_samples/new.expr.rsx → packages/rsx/tests/valid/expr.new.rsx


+ 0 - 0
packages/rsx/tests/valid_samples/old.expr.rsx → packages/rsx/tests/valid/expr.old.rsx


+ 12 - 0
packages/rsx/tests/valid/let.new.rsx

@@ -0,0 +1,12 @@
+use dioxus::prelude::*;
+
+pub fn CoolChild() -> Element {
+    let head_ = rsx! {
+        div {
+            div { "asasddasdasd" }
+            div { "asasdd1asaassdd23asasddasd" }
+        }
+    };
+
+    head_
+}

+ 12 - 0
packages/rsx/tests/valid/let.old.rsx

@@ -0,0 +1,12 @@
+use dioxus::prelude::*;
+
+pub fn CoolChild() -> Element {
+    let head_ = rsx! {
+        div {
+            div { "asasddasdasd" }
+            div { "asasdd1asaassdd23asasddasdasd" }
+        }
+    };
+
+    head_
+}