diff --git a/packages/native-core/src/dioxus.rs b/packages/native-core/src/dioxus.rs index d5dc59e2b..1c688b864 100644 --- a/packages/native-core/src/dioxus.rs +++ b/packages/native-core/src/dioxus.rs @@ -3,7 +3,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue}, - prelude::{NodeImmutable, NodeMutable}, + prelude::NodeImmutable, real_dom::NodeTypeMut, NodeId, NodeMut, RealDom, }; @@ -68,7 +68,7 @@ impl DioxusState { let children = self.stack.split_off(self.stack.len() - m); let parent = self.element_to_node_id(id); for child in children { - rdom.add_child(parent, child); + rdom.get_mut(parent).unwrap().add_child(child); } } AssignId { path, id } => { @@ -114,7 +114,7 @@ impl DioxusState { let mut node = rdom.get_mut(new).unwrap(); node.insert_before(old_node_id); } - rdom.remove(old_node_id); + rdom.get_mut(old_node_id).unwrap().remove(); } ReplacePlaceholder { path, m } => { let new_nodes = self.stack.split_off(self.stack.len() - m); @@ -123,7 +123,7 @@ impl DioxusState { let mut node = rdom.get_mut(new).unwrap(); node.insert_before(old_node_id); } - rdom.remove(old_node_id); + rdom.get_mut(old_node_id).unwrap().remove(); } InsertAfter { id, m } => { let new_nodes = self.stack.split_off(self.stack.len() - m); @@ -186,7 +186,7 @@ impl DioxusState { } Remove { id } => { let node_id = self.element_to_node_id(id); - rdom.remove(node_id); + rdom.get_mut(node_id).unwrap().remove(); } PushRoot { id } => { let node_id = self.element_to_node_id(id); @@ -231,7 +231,7 @@ fn create_template_node(rdom: &mut RealDom, node: &TemplateNode) -> NodeId { let node_id = rdom.create_node(node).id(); for child in *children { let child_id = create_template_node(rdom, child); - rdom.add_child(node_id, child_id); + rdom.get_mut(node_id).unwrap().add_child(child_id); } node_id } diff --git a/packages/native-core/src/utils/persistant_iterator.rs b/packages/native-core/src/utils/persistant_iterator.rs index b922d0f56..d290caaa4 100644 --- a/packages/native-core/src/utils/persistant_iterator.rs +++ b/packages/native-core/src/utils/persistant_iterator.rs @@ -92,9 +92,20 @@ impl PersistantElementIter { stack.push(new); ElementProduced::Looped(id) } else { + let mut look_in_children = true; loop { - let last = stack.pop().unwrap(); - if let Some(current) = rdom.get(last) { + if let Some(current) = stack.last().and_then(|last| rdom.get(*last)) { + // if the current element has children, add the first child to the stack and return it + if look_in_children { + if let Some(children) = current.children() { + if let Some(first) = children.first() { + let new = first.id(); + stack.push(new); + return ElementProduced::Progressed(new); + } + } + } + stack.pop(); if let Some(new) = current.next() { // the next element exists, add it to the stack and return it let new = new.id(); @@ -109,6 +120,7 @@ impl PersistantElementIter { stack.push(new); return ElementProduced::Looped(new); } + look_in_children = false; } } } @@ -136,23 +148,27 @@ impl PersistantElementIter { let id = NodeId(0); let last = push_back(&mut stack, rdom.get(id).unwrap()); ElementProduced::Looped(last) - } else { - loop { - let last = stack.pop().unwrap(); - if let Some(current) = rdom.get(last) { - if let Some(new) = current.prev() { - // the next element exists, add it to the stack and return it - let new = push_back(&mut stack, new); - return ElementProduced::Progressed(new); - } - // otherwise, continue the loop and go to the parent - } else { - // if there is no parent, loop back to the root - let id = NodeId(0); - let last = push_back(&mut stack, rdom.get(id).unwrap()); - return ElementProduced::Looped(last); - } + } else if let Some(current) = stack.pop().and_then(|last| rdom.get(last)) { + if let Some(new) = current.prev() { + // the next element exists, add it to the stack and return it + let new = push_back(&mut stack, new); + ElementProduced::Progressed(new) } + // otherwise, yeild the parent + else if let Some(parent) = stack.last() { + // if there is a parent, return it + ElementProduced::Progressed(*parent) + } else { + // if there is no parent, loop back to the root + let id = NodeId(0); + let last = push_back(&mut stack, rdom.get(id).unwrap()); + ElementProduced::Looped(last) + } + } else { + // if there is no parent, loop back to the root + let id = NodeId(0); + let last = push_back(&mut stack, rdom.get(id).unwrap()); + ElementProduced::Looped(last) } } } @@ -160,6 +176,8 @@ impl PersistantElementIter { #[test] #[allow(unused_variables)] fn traverse() { + use crate::dioxus::DioxusState; + use crate::prelude::*; use dioxus::prelude::*; #[allow(non_snake_case)] fn Base(cx: Scope) -> Element { @@ -181,133 +199,74 @@ fn traverse() { let mut rdom: RealDom = RealDom::new(Box::new([])); - let _to_update = rdom.apply_mutations(mutations); + let mut iter = PersistantElementIter::create(&mut rdom); + let mut dioxus_state = DioxusState::create(&mut rdom); + dioxus_state.apply_mutations(&mut rdom, mutations); - let mut iter = PersistantElementIter::new(); let div_tag = "div".to_string(); assert!(matches!( - &rdom - .get(iter.next(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.next(&rdom).id()).unwrap().node_type(), NodeType::Element(ElementNode { tag: div_tag, .. }) )); assert!(matches!( - &rdom - .get(iter.next(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.next(&rdom).id()).unwrap().node_type(), NodeType::Element(ElementNode { tag: div_tag, .. }) )); let text1 = "hello".to_string(); assert!(matches!( - &rdom - .get(iter.next(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.next(&rdom).id()).unwrap().node_type(), NodeType::Text(text1) )); let p_tag = "p".to_string(); assert!(matches!( - &rdom - .get(iter.next(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.next(&rdom).id()).unwrap().node_type(), NodeType::Element(ElementNode { tag: p_tag, .. }) )); let text2 = "world".to_string(); assert!(matches!( - &rdom - .get(iter.next(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.next(&rdom).id()).unwrap().node_type(), NodeType::Text(text2) )); let text3 = "hello world".to_string(); assert!(matches!( - &rdom - .get(iter.next(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.next(&rdom).id()).unwrap().node_type(), NodeType::Text(text3) )); assert!(matches!( - &rdom - .get(iter.next(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.next(&rdom).id()).unwrap().node_type(), NodeType::Element(ElementNode { tag: div_tag, .. }) )); assert!(matches!( - &rdom - .get(iter.prev(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.prev(&rdom).id()).unwrap().node_type(), NodeType::Text(text3) )); assert!(matches!( - &rdom - .get(iter.prev(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.prev(&rdom).id()).unwrap().node_type(), NodeType::Text(text2) )); assert!(matches!( - &rdom - .get(iter.prev(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.prev(&rdom).id()).unwrap().node_type(), NodeType::Element(ElementNode { tag: p_tag, .. }) )); assert!(matches!( - &rdom - .get(iter.prev(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.prev(&rdom).id()).unwrap().node_type(), NodeType::Text(text1) )); assert!(matches!( - &rdom - .get(iter.prev(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.prev(&rdom).id()).unwrap().node_type(), NodeType::Element(ElementNode { tag: div_tag, .. }) )); assert!(matches!( - &rdom - .get(iter.prev(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.prev(&rdom).id()).unwrap().node_type(), NodeType::Element(ElementNode { tag: div_tag, .. }) )); assert!(matches!( - &rdom - .get(iter.prev(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.prev(&rdom).id()).unwrap().node_type(), NodeType::Element(ElementNode { tag: div_tag, .. }) )); assert!(matches!( - &rdom - .get(iter.prev(&rdom).id()) - .unwrap() - .node_data() - .node_type, + &rdom.get(iter.prev(&rdom).id()).unwrap().node_type(), NodeType::Text(text3) )); } @@ -315,6 +274,8 @@ fn traverse() { #[test] #[allow(unused_variables)] fn persist_removes() { + use crate::dioxus::DioxusState; + use crate::prelude::*; use dioxus::prelude::*; #[allow(non_snake_case)] fn Base(cx: Scope) -> Element { @@ -342,12 +303,13 @@ fn persist_removes() { let build = vdom.rebuild(); println!("{build:#?}"); - let _to_update = rdom.apply_mutations(build); - // this will end on the node that is removed - let mut iter1 = PersistantElementIter::new(); + let mut iter1 = PersistantElementIter::create(&mut rdom); // this will end on the after node that is removed - let mut iter2 = PersistantElementIter::new(); + let mut iter2 = PersistantElementIter::create(&mut rdom); + let mut dioxus_state = DioxusState::create(&mut rdom); + dioxus_state.apply_mutations(&mut rdom, build); + // root iter1.next(&rdom).id(); iter2.next(&rdom).id(); @@ -374,22 +336,18 @@ fn persist_removes() { vdom.mark_dirty(ScopeId(0)); let update = vdom.render_immediate(); println!("{update:#?}"); - iter1.prune(&update, &rdom); - iter2.prune(&update, &rdom); - let _to_update = rdom.apply_mutations(update); + dioxus_state.apply_mutations(&mut rdom, update); let root_tag = "Root".to_string(); let idx = iter1.next(&rdom).id(); - dbg!(&rdom.get(idx).unwrap().node_data().node_type); assert!(matches!( - &rdom.get(idx).unwrap().node_data().node_type, + &rdom.get(idx).unwrap().node_type(), NodeType::Element(ElementNode { tag: root_tag, .. }) )); let idx = iter2.next(&rdom).id(); - dbg!(&rdom.get(idx).unwrap().node_data().node_type); assert!(matches!( - &rdom.get(idx).unwrap().node_data().node_type, + &rdom.get(idx).unwrap().node_type(), NodeType::Element(ElementNode { tag: root_tag, .. }) )); } @@ -397,6 +355,8 @@ fn persist_removes() { #[test] #[allow(unused_variables)] fn persist_instertions_before() { + use crate::dioxus::DioxusState; + use crate::prelude::*; use dioxus::prelude::*; #[allow(non_snake_case)] fn Base(cx: Scope) -> Element { @@ -421,11 +381,12 @@ fn persist_instertions_before() { let mut vdom = VirtualDom::new(Base); let mut rdom: RealDom = RealDom::new(Box::new([])); + let mut dioxus_state = DioxusState::create(&mut rdom); let build = vdom.rebuild(); - let _to_update = rdom.apply_mutations(build); + dioxus_state.apply_mutations(&mut rdom, build); - let mut iter = PersistantElementIter::new(); + let mut iter = PersistantElementIter::create(&mut rdom); // div iter.next(&rdom).id(); // p @@ -439,13 +400,12 @@ fn persist_instertions_before() { vdom.mark_dirty(ScopeId(0)); let update = vdom.render_immediate(); - iter.prune(&update, &rdom); - let _to_update = rdom.apply_mutations(update); + dioxus_state.apply_mutations(&mut rdom, update); let p_tag = "div".to_string(); let idx = iter.next(&rdom).id(); assert!(matches!( - &rdom.get(idx).unwrap().node_data().node_type, + &rdom.get(idx).unwrap().node_type(), NodeType::Element(ElementNode { tag: p_tag, .. }) )); } @@ -453,6 +413,8 @@ fn persist_instertions_before() { #[test] #[allow(unused_variables)] fn persist_instertions_after() { + use crate::dioxus::DioxusState; + use crate::prelude::*; use dioxus::prelude::*; #[allow(non_snake_case)] fn Base(cx: Scope) -> Element { @@ -477,11 +439,12 @@ fn persist_instertions_after() { let mut vdom = VirtualDom::new(Base); let mut rdom: RealDom = RealDom::new(Box::new([])); + let mut iter = PersistantElementIter::create(&mut rdom); + let mut dioxus_state = DioxusState::create(&mut rdom); let build = vdom.rebuild(); - let _to_update = rdom.apply_mutations(build); + dioxus_state.apply_mutations(&mut rdom, build); - let mut iter = PersistantElementIter::new(); // div iter.next(&rdom).id(); // p @@ -494,19 +457,18 @@ fn persist_instertions_after() { iter.next(&rdom).id(); let update = vdom.rebuild(); - iter.prune(&update, &rdom); - let _to_update = rdom.apply_mutations(update); + dioxus_state.apply_mutations(&mut rdom, update); let p_tag = "p".to_string(); let idx = iter.next(&rdom).id(); assert!(matches!( - &rdom.get(idx).unwrap().node_data().node_type, + &rdom.get(idx).unwrap().node_type(), NodeType::Element(ElementNode { tag: p_tag, .. }) )); let text = "hello world".to_string(); let idx = iter.next(&rdom).id(); assert!(matches!( - &rdom.get(idx).unwrap().node_data().node_type, + &rdom.get(idx).unwrap().node_type(), NodeType::Text(text) )); }