From 672af7b3ede1c435857aefbe7138b628e1c8f386 Mon Sep 17 00:00:00 2001 From: Pauan Date: Thu, 29 Apr 2021 19:44:21 +0200 Subject: [PATCH] Fixing bug where children_signal_vec wouldn't trigger after_removed --- src/operations.rs | 55 +++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/operations.rs b/src/operations.rs index 149dc83..a03508f 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -144,13 +144,15 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb where A: SignalVec + 'static { struct State { + element: Node, is_inserted: bool, children: Vec, } impl State { - fn new() -> Rc> { + fn new(element: Node) -> Rc> { Rc::new(RefCell::new(State { + element, is_inserted: false, children: vec![], })) @@ -170,41 +172,47 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb }); } - fn clear(&mut self, element: &Node) { + fn clear(&mut self) { for dom in self.children.drain(..) { - bindings::remove_child(element, &dom.element); + bindings::remove_child(&self.element, &dom.element); dom.callbacks.discard(); } } - fn insert_at(&self, element: &Node, new_index: usize, child: &Node) { + fn on_remove(&mut self) { + for dom in self.children.drain(..) { + dom.callbacks.discard(); + } + } + + fn insert_at(&self, new_index: usize, child: &Node) { if let Some(dom) = self.children.get(new_index) { - bindings::insert_child_before(element, child, &dom.element); + bindings::insert_child_before(&self.element, child, &dom.element); } else { - bindings::append_child(element, child); + bindings::append_child(&self.element, child); } } // TODO verify that this will drop `children` - fn process_change(&mut self, element: &Node, change: VecDiff) { + fn process_change(&mut self, change: VecDiff) { match change { VecDiff::Replace { values } => { - self.clear(element); + self.clear(); self.children = values; let is_inserted = self.is_inserted; for dom in self.children.iter_mut() { - bindings::append_child(element, &dom.element); + bindings::append_child(&self.element, &dom.element); after_insert(is_inserted, &mut dom.callbacks); } }, VecDiff::InsertAt { index, mut value } => { - self.insert_at(element, index, &value.element); + self.insert_at(index, &value.element); after_insert(self.is_inserted, &mut value.callbacks); @@ -213,7 +221,7 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb }, VecDiff::Push { mut value } => { - bindings::append_child(element, &value.element); + bindings::append_child(&self.element, &value.element); after_insert(self.is_inserted, &mut value.callbacks); @@ -224,7 +232,7 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb VecDiff::UpdateAt { index, mut value } => { let dom = &mut self.children[index]; - bindings::replace_child(element, &value.element, &dom.element); + bindings::replace_child(&self.element, &value.element, &dom.element); after_insert(self.is_inserted, &mut value.callbacks); @@ -238,7 +246,7 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb VecDiff::Move { old_index, new_index } => { let value = self.children.remove(old_index); - self.insert_at(element, new_index, &value.element); + self.insert_at(new_index, &value.element); self.children.insert(new_index, value); }, @@ -246,7 +254,7 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb VecDiff::RemoveAt { index } => { let dom = self.children.remove(index); - bindings::remove_child(element, &dom.element); + bindings::remove_child(&self.element, &dom.element); dom.callbacks.discard(); }, @@ -254,24 +262,35 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb VecDiff::Pop {} => { let dom = self.children.pop().unwrap_throw(); - bindings::remove_child(element, &dom.element); + bindings::remove_child(&self.element, &dom.element); dom.callbacks.discard(); }, VecDiff::Clear {} => { - self.clear(element); + self.clear(); }, } } } - let state = State::new(); + struct OnRemove(Rc>); + + impl Discard for OnRemove { + #[inline] + fn discard(self) { + self.0.borrow_mut().on_remove(); + } + } + + let state = State::new(element); State::after_insert(state.clone(), callbacks); + callbacks.after_remove(OnRemove(state.clone())); + callbacks.after_remove(for_each_vec(signal, move |change| { let mut state = state.borrow_mut(); - state.process_change(&element, change); + state.process_change(change); })); }