1
0
Jonathan Kelley 2 жил өмнө
parent
commit
0cfbfc88e2

+ 19 - 17
packages/core/src/create.rs

@@ -216,12 +216,10 @@ impl<'b: 'static> VirtualDom {
     ) {
         match *node {
             // Todo: create the children's template
-            TemplateNode::Dynamic(_) => {
-                let id = ElementId(0);
-                self.mutations
-                    .template_mutations
-                    .push(CreatePlaceholder { id })
-            }
+            TemplateNode::Dynamic(_) => self
+                .mutations
+                .template_mutations
+                .push(CreateStaticPlaceholder {}),
             TemplateNode::Text(value) => self
                 .mutations
                 .template_mutations
@@ -236,15 +234,20 @@ impl<'b: 'static> VirtualDom {
                 children,
                 namespace,
                 tag,
-                inner_opt,
+                ..
             } => {
-                let id = ElementId(0);
-
-                self.mutations.template_mutations.push(CreateElement {
-                    name: tag,
-                    namespace,
-                    id,
-                });
+                if let Some(namespace) = namespace {
+                    self.mutations
+                        .template_mutations
+                        .push(CreateElementNamespace {
+                            name: tag,
+                            namespace,
+                        });
+                } else {
+                    self.mutations
+                        .template_mutations
+                        .push(CreateElement { name: tag });
+                }
 
                 self.mutations
                     .template_mutations
@@ -254,16 +257,15 @@ impl<'b: 'static> VirtualDom {
                             value,
                             namespace,
                             ..
-                        } => Some(SetAttribute {
+                        } => Some(SetStaticAttribute {
                             name,
                             value,
-                            id,
                             ns: *namespace,
                         }),
                         _ => None,
                     }));
 
-                if children.is_empty() && inner_opt {
+                if children.is_empty() {
                     return;
                 }
 

+ 66 - 2
packages/core/src/diff.rs

@@ -239,8 +239,72 @@ impl<'b: 'static> VirtualDom {
         //
         // Remove the old nodes, except for one
         self.remove_nodes(&l[1..]);
-        let id = self.next_element(&l[0], &[]);
-        // self.replace(left_template, right_template, left, right)
+        let first = self.find_first_element(&l[0]);
+        self.remove_all_but_first_node(&l[0]);
+
+        let placeholder = self.next_element(&l[0], &[]);
+        r.set(placeholder);
+        self.mutations
+            .push(Mutation::CreatePlaceholder { id: placeholder });
+        self.mutations
+            .push(Mutation::ReplaceWith { id: first, m: 1 })
+    }
+
+    // Remove all the top-level nodes, returning the
+    fn remove_all_but_first_node(&mut self, node: &'b VNode<'b>) {
+        match &node.template.roots[0] {
+            TemplateNode::Text(_) | TemplateNode::Element { .. } => {}
+            TemplateNode::DynamicText(id) | TemplateNode::Dynamic(id) => {
+                match &node.dynamic_nodes[*id] {
+                    Text(_) => {}
+                    Fragment(VFragment::Empty(_)) => {}
+                    Fragment(VFragment::NonEmpty(nodes)) => {
+                        self.remove_all_but_first_node(&nodes[0]);
+                        self.remove_nodes(&nodes[1..]);
+                    }
+                    Component(comp) => {
+                        let scope = comp.scope.get().unwrap();
+                        match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
+                            RenderReturn::Sync(Ok(t)) => self.remove_all_but_first_node(t),
+                            _ => todo!("cannot handle nonstandard nodes"),
+                        };
+                    }
+                };
+            }
+        }
+
+        // Just remove the rest
+        for (idx, _) in node.template.roots.iter().enumerate().skip(1) {
+            self.remove_root_node(node, idx);
+        }
+    }
+
+    fn remove_root_node(&mut self, node: &'b VNode<'b>, idx: usize) {
+        let root = node.template.roots[idx];
+        match root {
+            TemplateNode::Element { .. } | TemplateNode::Text(_) => {
+                self.mutations.push(Mutation::Remove {
+                    id: node.root_ids[idx].get(),
+                })
+            }
+
+            TemplateNode::DynamicText(id) | TemplateNode::Dynamic(id) => {
+                match &node.dynamic_nodes[id] {
+                    Text(i) => self.mutations.push(Mutation::Remove { id: i.id.get() }),
+                    Fragment(VFragment::Empty(e)) => {
+                        self.mutations.push(Mutation::Remove { id: e.get() })
+                    }
+                    Fragment(VFragment::NonEmpty(nodes)) => self.remove_nodes(nodes),
+                    Component(comp) => {
+                        let scope = comp.scope.get().unwrap();
+                        match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
+                            RenderReturn::Sync(Ok(t)) => self.remove_node(t),
+                            _ => todo!("cannot handle nonstandard nodes"),
+                        };
+                    }
+                };
+            }
+        }
     }
 
     fn diff_non_empty_fragment(&mut self, new: &'b [VNode<'b>], old: &'b [VNode<'b>]) {

+ 1 - 1
packages/core/src/fragment.rs

@@ -96,7 +96,7 @@ impl<'a> Properties for FragmentProps<'a> {
     type Builder = FragmentBuilder<'a, false>;
     const IS_STATIC: bool = false;
     fn builder() -> Self::Builder {
-        todo!()
+        FragmentBuilder(VNode::empty())
     }
     unsafe fn memoize(&self, _other: &Self) -> bool {
         false

+ 11 - 3
packages/core/src/mutations.rs

@@ -72,13 +72,15 @@ pub enum Mutation<'a> {
 
     CreateElement {
         name: &'a str,
-        namespace: Option<&'a str>,
-        id: ElementId,
     },
-
+    CreateElementNamespace {
+        name: &'a str,
+        namespace: &'a str,
+    },
     CreatePlaceholder {
         id: ElementId,
     },
+    CreateStaticPlaceholder,
     CreateStaticText {
         value: &'a str,
     },
@@ -142,6 +144,12 @@ pub enum Mutation<'a> {
         ns: Option<&'a str>,
     },
 
+    SetStaticAttribute {
+        name: &'a str,
+        value: &'a str,
+        ns: Option<&'a str>,
+    },
+
     SetBoolAttribute {
         name: &'a str,
         value: bool,

+ 15 - 0
packages/core/tests/boolattrs.rs

@@ -0,0 +1,15 @@
+use dioxus::core::{ElementId, Mutation::*};
+use dioxus::prelude::*;
+
+#[test]
+fn bool_test() {
+    let mut app = VirtualDom::new(|cx| cx.render(rsx!(div { hidden: false })));
+    assert_eq!(
+        app.rebuild().santize().edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(1) },
+            SetBoolAttribute { name: "hidden", value: false, id: ElementId(1,) },
+            AppendChildren { m: 1 },
+        ]
+    )
+}

+ 55 - 0
packages/core/tests/borrowedstate.rs

@@ -0,0 +1,55 @@
+#![allow(non_snake_case)]
+
+use dioxus::core::{ElementId, Mutation::*};
+use dioxus::prelude::*;
+
+#[test]
+fn test_borrowed_state() {
+    let mut dom = VirtualDom::new(Parent);
+
+    assert_eq!(
+        dom.rebuild().santize().edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
+            LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
+            LoadTemplate { name: "template", index: 0, id: ElementId(3,) },
+            HydrateText { path: &[0,], value: "Hello w1!", id: ElementId(4,) },
+            ReplacePlaceholder { path: &[1,], m: 1 },
+            ReplacePlaceholder { path: &[0,], m: 1 },
+            AppendChildren { m: 1 },
+        ]
+    )
+}
+
+fn Parent(cx: Scope) -> Element {
+    let w1 = cx.use_hook(|| String::from("w1"));
+
+    cx.render(rsx! {
+        div {
+            Child { name: w1 }
+        }
+    })
+}
+
+#[derive(Props)]
+struct ChildProps<'a> {
+    name: &'a str,
+}
+
+fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element {
+    cx.render(rsx! {
+        div {
+            h1 { "it's nested" }
+            Child2 { name: cx.props.name }
+        }
+    })
+}
+
+#[derive(Props)]
+struct Grandchild<'a> {
+    name: &'a str,
+}
+
+fn Child2<'a>(cx: Scope<'a, Grandchild<'a>>) -> Element {
+    cx.render(rsx!(div { "Hello {cx.props.name}!" }))
+}

+ 217 - 0
packages/core/tests/create_dom.rs

@@ -0,0 +1,217 @@
+#![allow(unused, non_upper_case_globals, non_snake_case)]
+
+//! Prove that the dom works normally through virtualdom methods.
+//!
+//! This methods all use "rebuild" which completely bypasses the scheduler.
+//! Hard rebuilds don't consume any events from the event queue.
+
+use dioxus::core::Mutation::*;
+use dioxus::prelude::*;
+use dioxus_core::ElementId;
+
+#[test]
+fn test_original_diff() {
+    let mut dom = VirtualDom::new(|cx| {
+        cx.render(rsx! {
+            div {
+                div {
+                    "Hello, world!"
+                }
+            }
+        })
+    });
+
+    let edits = dom.rebuild().santize();
+    assert_eq!(
+        edits.template_mutations,
+        [
+            // create template
+            CreateElement { name: "div" },
+            CreateElement { name: "div" },
+            CreateStaticText { value: "Hello, world!" },
+            AppendChildren { m: 1 },
+            AppendChildren { m: 1 },
+            SaveTemplate { name: "template", m: 1 },
+        ]
+    );
+
+    assert_eq!(
+        edits.edits,
+        [
+            // add to root
+            LoadTemplate { name: "template", index: 0, id: ElementId(1) },
+            AppendChildren { m: 1 }
+        ]
+    )
+}
+
+#[test]
+fn create() {
+    let mut dom = VirtualDom::new(|cx| {
+        cx.render(rsx! {
+            div {
+                div {
+                    "Hello, world!"
+                    div {
+                        div {
+                            Fragment {
+                                "hello"
+                                "world"
+                            }
+                        }
+                    }
+                }
+            }
+        })
+    });
+
+    let edits = dom.rebuild().santize();
+    assert_eq!(
+        edits.template_mutations,
+        [
+            // create template
+            CreateElement { name: "div" },
+            CreateElement { name: "div" },
+            CreateStaticText { value: "Hello, world!" },
+            CreateElement { name: "div" },
+            CreateElement { name: "div" },
+            CreateStaticPlaceholder {},
+            AppendChildren { m: 1 },
+            AppendChildren { m: 1 },
+            AppendChildren { m: 2 },
+            AppendChildren { m: 1 },
+            SaveTemplate { name: "template", m: 1 },
+            // The fragment child template
+            CreateStaticText { value: "hello" },
+            CreateStaticText { value: "world" },
+            SaveTemplate { name: "template", m: 2 },
+        ]
+    );
+}
+
+#[test]
+fn create_list() {
+    let mut dom = VirtualDom::new(|cx| {
+        cx.render(rsx! {
+            (0..3).map(|f| rsx!( div { "hello" } ))
+        })
+    });
+
+    let edits = dom.rebuild().santize();
+    assert_eq!(
+        edits.template_mutations,
+        [
+            // create template
+            CreateElement { name: "div" },
+            CreateStaticText { value: "hello" },
+            AppendChildren { m: 1 },
+            SaveTemplate { name: "template", m: 1 }
+        ]
+    );
+}
+
+#[test]
+fn create_simple() {
+    let mut dom = VirtualDom::new(|cx| {
+        cx.render(rsx! {
+            div {}
+            div {}
+            div {}
+            div {}
+        })
+    });
+
+    let edits = dom.rebuild().santize();
+    assert_eq!(
+        edits.template_mutations,
+        [
+            // create template
+            CreateElement { name: "div" },
+            CreateElement { name: "div" },
+            CreateElement { name: "div" },
+            CreateElement { name: "div" },
+            // add to root
+            SaveTemplate { name: "template", m: 4 }
+        ]
+    );
+}
+#[test]
+fn create_components() {
+    let mut dom = VirtualDom::new(|cx| {
+        cx.render(rsx! {
+            Child { "abc1" }
+            Child { "abc2" }
+            Child { "abc3" }
+        })
+    });
+
+    #[derive(Props)]
+    struct ChildProps<'a> {
+        children: Element<'a>,
+    }
+
+    fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element {
+        cx.render(rsx! {
+            h1 {}
+            div { &cx.props.children }
+            p {}
+        })
+    }
+
+    let edits = dom.rebuild().santize();
+    assert_eq!(
+        edits.template_mutations,
+        [
+            // The "child" template
+            CreateElement { name: "h1" },
+            CreateElement { name: "div" },
+            CreateStaticPlaceholder {},
+            AppendChildren { m: 1 },
+            CreateElement { name: "p" },
+            SaveTemplate { name: "template", m: 3 },
+            // Sub template for component children
+            CreateStaticText { value: "abc1" },
+            SaveTemplate { name: "template", m: 1 },
+            CreateStaticText { value: "abc2" },
+            SaveTemplate { name: "template", m: 1 },
+            CreateStaticText { value: "abc3" },
+            SaveTemplate { name: "template", m: 1 }
+        ]
+    );
+}
+
+#[test]
+fn anchors() {
+    let mut dom = VirtualDom::new(|cx| {
+        cx.render(rsx! {
+            if true {
+                rsx!( div { "hello" } )
+            }
+            if false {
+                rsx!( div { "goodbye" } )
+            }
+        })
+    });
+
+    // note that the template under "false" doesn't show up since it's not loaded
+    let edits = dom.rebuild().santize();
+    assert_eq!(
+        edits.template_mutations,
+        [
+            // create each template
+            CreateElement { name: "div" },
+            CreateStaticText { value: "hello" },
+            AppendChildren { m: 1 },
+            SaveTemplate { m: 1, name: "template" },
+        ]
+    );
+
+    assert_eq!(
+        edits.edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(1) },
+            CreatePlaceholder { id: ElementId(2) },
+            AppendChildren { m: 2 }
+        ]
+    )
+}

+ 4 - 4
packages/core/tests/create_lists.rs

@@ -31,18 +31,18 @@ fn list_renders() {
         edits.template_mutations,
         [
             // Create the outer div
-            CreateElement { name: "div", namespace: None, id: ElementId(0) },
+            CreateElement { name: "div" },
             // todo: since this is the only child, we should just use
             // append when modify the values (IE no need for a placeholder)
             CreatePlaceholder { id: ElementId(0) },
             AppendChildren { m: 1 },
             SaveTemplate { name: "template", m: 1 },
             // Create the inner template div
-            CreateElement { name: "div", namespace: None, id: ElementId(0) },
-            CreateElement { name: "h1", namespace: None, id: ElementId(0) },
+            CreateElement { name: "div" },
+            CreateElement { name: "h1" },
             CreateStaticText { value: "hello world! " },
             AppendChildren { m: 1 },
-            CreateElement { name: "p", namespace: None, id: ElementId(0) },
+            CreateElement { name: "p" },
             CreateStaticText { value: "d" },
             AppendChildren { m: 1 },
             AppendChildren { m: 2 },

+ 149 - 10
packages/core/tests/diff_unkeyed_list.rs

@@ -73,10 +73,7 @@ fn list_creates_one_by_one() {
 #[test]
 fn removes_one_by_one() {
     let mut dom = VirtualDom::new(|cx| {
-        let gen = 3 - cx.generation();
-
-        println!("gen: {:?}", gen);
-        println!("range: {:?}", 0..gen);
+        let gen = 3 - cx.generation() % 4;
 
         cx.render(rsx! {
             div {
@@ -123,12 +120,154 @@ fn removes_one_by_one() {
     );
 
     // Remove div(1) and replace with a placeholder
+    // todo: this should just be a remove with no placeholder
+    dom.mark_dirty_scope(ScopeId(0));
+    assert_eq!(
+        dom.render_immediate().santize().edits,
+        [
+            CreatePlaceholder { id: ElementId(8) },
+            ReplaceWith { id: ElementId(2), m: 1 }
+        ]
+    );
+
+    // load the 3 and replace the placeholder
+    // todo: this should actually be append to, but replace placeholder is fine for now
+    dom.mark_dirty_scope(ScopeId(0));
+    assert_eq!(
+        dom.render_immediate().santize().edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(9) },
+            HydrateText { path: &[0], value: "0", id: ElementId(10) },
+            LoadTemplate { name: "template", index: 0, id: ElementId(11) },
+            HydrateText { path: &[0], value: "1", id: ElementId(12) },
+            LoadTemplate { name: "template", index: 0, id: ElementId(13) },
+            HydrateText { path: &[0], value: "2", id: ElementId(14) },
+            ReplaceWith { id: ElementId(8), m: 3 }
+        ]
+    );
+}
+
+#[test]
+fn list_shrink_multiroot() {
+    let mut dom = VirtualDom::new(|cx| {
+        let gen = cx.generation();
+        cx.render(rsx! {
+            div {
+                (0..gen).map(|i| rsx! {
+                    div { "{i}" }
+                    div { "{i}" }
+                })
+            }
+        })
+    });
+
+    assert_eq!(
+        dom.rebuild().santize().edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
+            AssignId { path: &[0,], id: ElementId(2,) },
+            AppendChildren { m: 1 }
+        ]
+    );
+
+    dom.mark_dirty_scope(ScopeId(0));
+    assert_eq!(
+        dom.render_immediate().santize().edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(3) },
+            HydrateText { path: &[0], value: "0", id: ElementId(4) },
+            LoadTemplate { name: "template", index: 1, id: ElementId(5) },
+            HydrateText { path: &[0], value: "0", id: ElementId(6) },
+            ReplaceWith { id: ElementId(2), m: 2 }
+        ]
+    );
+
+    dom.mark_dirty_scope(ScopeId(0));
+    assert_eq!(
+        dom.render_immediate().santize().edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(7) },
+            HydrateText { path: &[0], value: "1", id: ElementId(8) },
+            LoadTemplate { name: "template", index: 1, id: ElementId(9) },
+            HydrateText { path: &[0], value: "1", id: ElementId(10) },
+            InsertAfter { id: ElementId(5), m: 2 }
+        ]
+    );
+
     dom.mark_dirty_scope(ScopeId(0));
-    assert_eq!(dom.render_immediate().santize().edits, []);
+    assert_eq!(
+        dom.render_immediate().santize().edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(11) },
+            HydrateText { path: &[0], value: "2", id: ElementId(12) },
+            LoadTemplate { name: "template", index: 1, id: ElementId(13) },
+            HydrateText { path: &[0], value: "2", id: ElementId(14) },
+            InsertAfter { id: ElementId(9), m: 2 }
+        ]
+    );
+}
+
+#[test]
+fn removes_one_by_one_multiroot() {
+    let mut dom = VirtualDom::new(|cx| {
+        let gen = 3 - cx.generation() % 4;
 
-    // dom.mark_dirty_scope(ScopeId(0));
-    // assert_eq!(
-    //     dom.render_immediate().santize().edits,
-    //     [Remove { id: ElementId(4) }]
-    // );
+        cx.render(rsx! {
+            div {
+                (0..gen).map(|i| rsx! {
+                    div { "{i}" }
+                    div { "{i}" }
+                })
+            }
+        })
+    });
+
+    // load the div and then assign the empty fragment as a placeholder
+    assert_eq!(
+        dom.rebuild().santize().edits,
+        [
+            LoadTemplate { name: "template", index: 0, id: ElementId(1) },
+            //
+            LoadTemplate { name: "template", index: 0, id: ElementId(2) },
+            HydrateText { path: &[0], value: "0", id: ElementId(3) },
+            LoadTemplate { name: "template", index: 1, id: ElementId(4) },
+            HydrateText { path: &[0], value: "0", id: ElementId(5) },
+            //
+            LoadTemplate { name: "template", index: 0, id: ElementId(6) },
+            HydrateText { path: &[0], value: "1", id: ElementId(7) },
+            LoadTemplate { name: "template", index: 1, id: ElementId(8) },
+            HydrateText { path: &[0], value: "1", id: ElementId(9) },
+            //
+            LoadTemplate { name: "template", index: 0, id: ElementId(10) },
+            HydrateText { path: &[0], value: "2", id: ElementId(11) },
+            LoadTemplate { name: "template", index: 1, id: ElementId(12) },
+            HydrateText { path: &[0], value: "2", id: ElementId(13) },
+            //
+            ReplacePlaceholder { path: &[0], m: 6 },
+            //
+            AppendChildren { m: 1 }
+        ]
+    );
+
+    dom.mark_dirty_scope(ScopeId(0));
+    assert_eq!(
+        dom.render_immediate().santize().edits,
+        [Remove { id: ElementId(10) }, Remove { id: ElementId(12) }]
+    );
+
+    dom.mark_dirty_scope(ScopeId(0));
+    assert_eq!(
+        dom.render_immediate().santize().edits,
+        [Remove { id: ElementId(6) }, Remove { id: ElementId(8) }]
+    );
+
+    dom.mark_dirty_scope(ScopeId(0));
+    assert_eq!(
+        dom.render_immediate().santize().edits,
+        [
+            Remove { id: ElementId(4) },
+            CreatePlaceholder { id: ElementId(14) },
+            ReplaceWith { id: ElementId(2), m: 1 }
+        ]
+    );
 }

+ 1 - 1
packages/core/tests/suspend.rs

@@ -14,7 +14,7 @@ async fn it_works() {
     assert_eq!(
         mutations.template_mutations,
         [
-            CreateElement { name: "div", namespace: None, id: ElementId(0) },
+            CreateElement { name: "div" },
             CreateStaticText { value: "Waiting for child..." },
             CreatePlaceholder { id: ElementId(0) },
             AppendChildren { m: 2 },

+ 5 - 5
packages/desktop/src/hot_reload.rs

@@ -17,11 +17,11 @@ pub(crate) fn init(dom: &VirtualDom) {
 
     // connect to processes for incoming data
     std::thread::spawn(move || {
-        if let Ok(listener) = LocalSocketListener::bind("@dioxusin") {
-            for conn in listener.incoming().filter_map(handle_error) {
-                *latest_in_connection_handle.lock().unwrap() = Some(BufReader::new(conn));
-            }
-        }
+        // if let Ok(listener) = LocalSocketListener::bind("@dioxusin") {
+        //     for conn in listener.incoming().filter_map(handle_error) {
+        //         *latest_in_connection_handle.lock().unwrap() = Some(BufReader::new(conn));
+        //     }
+        // }
     });
 
     std::thread::spawn(move || {

+ 0 - 24
packages/dioxus/tests/boolattrs.rs

@@ -1,24 +0,0 @@
-fn component(cx: Scope) -> Element {
-    cx.render(rsx! {
-        div { hidden: false }
-    })
-}
-
-use dioxus::prelude::*;
-
-#[test]
-fn bool_test() {
-    let mut app = VirtualDom::new(component);
-    let edits = app.rebuild();
-
-    use dioxus_core::{ElementId, Mutation::*};
-    assert_eq!(
-        edits.edits,
-        vec![
-            LoadTemplate { name: "packages/dioxus/tests/boolattrs.rs:2:15:66", index: 0 },
-            AssignId { path: &[], id: ElementId(2,) },
-            SetBoolAttribute { name: "hidden", value: false, id: ElementId(2,) },
-            AppendChildren { m: 1 },
-        ]
-    )
-}

+ 0 - 46
packages/dioxus/tests/borrowedstate.rs

@@ -1,46 +0,0 @@
-#![allow(non_snake_case)]
-
-use dioxus::prelude::*;
-
-#[test]
-fn test_borrowed_state() {
-    let _ = VirtualDom::new(Parent);
-}
-
-fn Parent(cx: Scope) -> Element {
-    let value = cx.use_hook(String::new);
-
-    cx.render(rsx! {
-        div {
-            Child { name: value }
-            Child { name: value }
-            Child { name: value }
-            Child { name: value }
-        }
-    })
-}
-
-#[derive(Props)]
-struct ChildProps<'a> {
-    name: &'a str,
-}
-
-fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element {
-    cx.render(rsx! {
-        div {
-            h1 { "it's nested" }
-            Child2 { name: cx.props.name }
-        }
-    })
-}
-
-#[derive(Props)]
-struct Grandchild<'a> {
-    name: &'a str,
-}
-
-fn Child2<'a>(cx: Scope<'a, Grandchild<'a>>) -> Element {
-    cx.render(rsx! {
-        div { "Hello {cx.props.name}!" }
-    })
-}

+ 0 - 100
packages/dioxus/tests/passthru.rs

@@ -1,100 +0,0 @@
-#![allow(unused, non_upper_case_globals)]
-#![allow(non_snake_case)]
-
-//! Diffing Tests
-//!
-//! These tests only verify that the diffing algorithm works properly for single components.
-//!
-//! It does not validated that component lifecycles work properly. This is done in another test file.
-
-use dioxus::prelude::*;
-
-fn new_dom() -> VirtualDom {
-    VirtualDom::new(|cx| render!("hi"))
-}
-
-use dioxus_core::DomEdit::*;
-
-/// Should push the text node onto the stack and modify it
-#[test]
-fn nested_passthru_creates() {
-    fn app(cx: Scope) -> Element {
-        cx.render(rsx! {
-            Child {
-                Child {
-                    Child {
-                        div {
-                            "hi"
-                        }
-                    }
-                }
-            }
-        })
-    };
-
-    #[inline_props]
-    fn Child<'a>(cx: Scope, children: Element<'a>) -> Element {
-        cx.render(rsx! { children })
-    };
-
-    let mut dom = VirtualDom::new(app);
-    let mut channel = dom.get_scheduler_channel();
-    assert!(dom.has_work());
-
-    let edits = dom.rebuild();
-    assert_eq!(
-        edits.edits,
-        [
-            CreateElement { tag: "div", root: Some(1), children: 0 },
-            CreateTextNode { text: "hi", root: Some(2) },
-            AppendChildren { root: Some(1), children: vec![2] },
-            AppendChildren { root: Some(0), children: vec![1] },
-        ]
-    )
-}
-
-/// Should push the text node onto the stack and modify it
-#[test]
-fn nested_passthru_creates_add() {
-    fn app(cx: Scope) -> Element {
-        cx.render(rsx! {
-            Child {
-                "1"
-                Child {
-                    "2"
-                    Child {
-                        "3"
-                        div {
-                            "hi"
-                        }
-                    }
-                }
-            }
-        })
-    };
-
-    #[inline_props]
-    fn Child<'a>(cx: Scope, children: Element<'a>) -> Element {
-        cx.render(rsx! {
-                children
-        })
-    };
-
-    let mut dom = VirtualDom::new(app);
-    let mut channel = dom.get_scheduler_channel();
-    assert!(dom.has_work());
-
-    let edits = dom.rebuild();
-    assert_eq!(
-        edits.edits,
-        [
-            CreateTextNode { text: "1", root: Some(1) },
-            CreateTextNode { text: "2", root: Some(2) },
-            CreateTextNode { text: "3", root: Some(3) },
-            CreateElement { tag: "div", root: Some(4), children: 0 },
-            CreateTextNode { text: "hi", root: Some(5) },
-            AppendChildren { root: Some(4), children: vec![5] },
-            AppendChildren { root: Some(0), children: vec![1, 2, 3, 4] },
-        ]
-    )
-}

+ 0 - 6
packages/dioxus/tests/scheduler.rs

@@ -1,6 +0,0 @@
-//! Tests for the scheduler.
-//!
-//! TODO
-//! - priority lanes
-//! - periodic checking
-//!

+ 25 - 29
packages/dioxus/tests/suspense.rs

@@ -1,18 +1,37 @@
-use std::future::IntoFuture;
+use std::{future::IntoFuture, rc::Rc};
 
 use dioxus::prelude::*;
 use dioxus_core::SuspenseBoundary;
 
+#[tokio::test]
+async fn basic_prints() {
+    let mut dom = VirtualDom::new(|cx| {
+        cx.render(rsx! {
+            div {
+                h1 { "var" }
+                suspense_boundary {
+                    basic_child { }
+                    async_child { }
+                }
+            }
+        })
+    });
+
+    dbg!(dom.rebuild());
+
+    dom.wait_for_work().await;
+
+    dbg!(dom.rebuild());
+}
+
 #[inline_props]
 fn suspense_boundary<'a>(cx: Scope<'a>, children: Element<'a>) -> Element {
-    cx.use_hook(|| cx.provide_context(SuspenseBoundary::new(cx.scope_id())));
+    cx.use_hook(|| cx.provide_context(Rc::new(SuspenseBoundary::new(cx.scope_id()))));
     cx.render(rsx! { children })
 }
 
 fn basic_child(cx: Scope) -> Element {
-    cx.render(rsx! {
-        div { "basic child 1" }
-    })
+    cx.render(rsx!( div { "basic child 1" } ))
 }
 
 async fn async_child(cx: Scope<'_>) -> Element {
@@ -38,28 +57,5 @@ async fn async_child(cx: Scope<'_>) -> Element {
 
     let (username, age) = tokio::join!(username.into_future(), age.into_future());
 
-    cx.render(rsx!(
-        div { "Hello! {username}, you are {age}, {_user} {_age}" }
-    ))
-}
-
-#[tokio::test]
-async fn basic_prints() {
-    let mut dom = VirtualDom::new(|cx| {
-        cx.render(rsx! {
-            div {
-                h1 { "var" }
-                suspense_boundary {
-                    basic_child { }
-                    async_child { }
-                }
-            }
-        })
-    });
-
-    dbg!(dom.rebuild());
-
-    dom.wait_for_work().await;
-
-    dbg!(dom.rebuild());
+    cx.render(rsx!( div { "Hello! {username}, you are {age}, {_user} {_age}" } ))
 }