From c126de8c2f8b893187e00383c76814ca9dd07ab8 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Sun, 18 Oct 2020 18:00:22 +0800 Subject: [PATCH] Fix call stack exceeded bug --- yew/src/html/mod.rs | 8 ++++++++ yew/src/virtual_dom/vcomp.rs | 25 +++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/yew/src/html/mod.rs b/yew/src/html/mod.rs index 481a0c4a18a..3f2d1901cd8 100644 --- a/yew/src/html/mod.rs +++ b/yew/src/html/mod.rs @@ -456,6 +456,14 @@ impl NodeRef { this.node = None; this.link = Some(node_ref); } + + /// Reuse an existing `NodeRef` + pub(crate) fn reuse(&self, node_ref: Self) { + let mut this = self.0.borrow_mut(); + let existing = node_ref.0.borrow(); + this.node = existing.node.clone(); + this.link = existing.link.clone(); + } } /// Trait for building properties for a component diff --git a/yew/src/virtual_dom/vcomp.rs b/yew/src/virtual_dom/vcomp.rs index e9dcaa7d0a6..23b6d87854e 100644 --- a/yew/src/virtual_dom/vcomp.rs +++ b/yew/src/virtual_dom/vcomp.rs @@ -186,7 +186,7 @@ impl VDiff for VComp { if let VNode::VComp(ref mut vcomp) = &mut ancestor { // If the ancestor is the same type, reuse it and update its properties if self.type_id == vcomp.type_id && self.key == vcomp.key { - self.node_ref.link(vcomp.node_ref.clone()); + self.node_ref.reuse(vcomp.node_ref.clone()); let scope = vcomp.scope.take().expect("VComp is not mounted"); mountable.reuse(scope.borrow(), next_sibling); self.scope = Some(scope); @@ -316,7 +316,7 @@ mod tests { } fn change(&mut self, _: Self::Properties) -> ShouldRender { - unimplemented!(); + true } fn view(&self) -> Html { @@ -324,6 +324,27 @@ mod tests { } } + #[test] + fn update_loop() { + let document = crate::utils::document(); + let parent_scope: AnyScope = crate::html::Scope::::new(None).into(); + let parent_element = document.create_element("div").unwrap(); + + let mut ancestor = html! { }; + ancestor.apply(&parent_scope, &parent_element, NodeRef::default(), None); + + for _ in 0..10000 { + let mut node = html! { }; + node.apply( + &parent_scope, + &parent_element, + NodeRef::default(), + Some(ancestor), + ); + ancestor = node; + } + } + #[test] fn set_properties_to_component() { html! {