From 9d8c5ca5ab5784b3f17d7ee20a451ee68fd703d6 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 11 Nov 2021 23:55:57 -0500 Subject: [PATCH] feat: it properly bubbles --- packages/core/src/diff.rs | 46 ++++++++++++++++++-------------- packages/core/src/scopearena.rs | 7 +++-- packages/core/src/virtual_dom.rs | 19 +++++++------ packages/desktop/src/events.rs | 8 +++--- packages/desktop/src/index.js | 20 ++++++-------- 5 files changed, 52 insertions(+), 48 deletions(-) diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 07f0794e4..ba7eb30fd 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -365,6 +365,8 @@ impl<'bump> DiffState<'bump> { fn create_text_node(&mut self, vtext: &'bump VText<'bump>, node: &'bump VNode<'bump>) { let real_id = self.scopes.reserve_node(node); + let parent = self.stack.element_stack.last().unwrap(); + self.mutations.create_text_node(vtext.text, real_id); vtext.dom_id.set(Some(real_id)); self.stack.add_child_count(1); @@ -403,6 +405,7 @@ impl<'bump> DiffState<'bump> { // set the parent ID for event bubbling self.stack.instructions.push(DiffInstruction::PopElement); + let parent = self.stack.element_stack.last().unwrap(); parent_id.set(Some(*parent)); @@ -410,6 +413,7 @@ impl<'bump> DiffState<'bump> { let real_id = self.scopes.reserve_node(node); self.stack.element_stack.push(real_id); dom_id.set(Some(real_id)); + log::debug!("Parent ID for {:?} set to {:?}", real_id, parent_id.get()); self.mutations.create_element(tag_name, *namespace, real_id); @@ -458,6 +462,8 @@ impl<'bump> DiffState<'bump> { self.scopes .new_with_key(fc_ptr, caller, parent_scope, container, height, subtree); + log::debug!("container for scope {:?} is {:?}", new_idx, container); + // Actually initialize the caller's slot with the right address vcomponent.associated_scope.set(Some(new_idx)); @@ -511,7 +517,9 @@ impl<'bump> DiffState<'bump> { use VNode::*; match (old_node, new_node) { // Check the most common cases first - (Text(old), Text(new)) => self.diff_text_nodes(old, new), + (Text(old), Text(new)) => { + self.diff_text_nodes(old, new, old_node, new_node); + } (Component(old), Component(new)) => { self.diff_component_nodes(old_node, new_node, old, new) } @@ -533,11 +541,18 @@ impl<'bump> DiffState<'bump> { } } - fn diff_text_nodes(&mut self, old: &'bump VText<'bump>, new: &'bump VText<'bump>) { + fn diff_text_nodes( + &mut self, + old: &'bump VText<'bump>, + new: &'bump VText<'bump>, + old_node: &'bump VNode<'bump>, + new_node: &'bump VNode<'bump>, + ) { if let Some(root) = old.dom_id.get() { if old.text != new.text { self.mutations.set_text(new.text, root.as_u64()); } + self.scopes.update_node(new_node, root); new.dom_id.set(Some(root)); } @@ -567,8 +582,10 @@ impl<'bump> DiffState<'bump> { return; } - self.scopes.update_reservation(new_node, root); + self.scopes.update_node(new_node, root); + new.dom_id.set(Some(root)); + new.parent_id.set(old.parent_id.get()); // todo: attributes currently rely on the element on top of the stack, but in theory, we only need the id of the // element to modify its attributes. @@ -634,8 +651,12 @@ impl<'bump> DiffState<'bump> { self.mutations.edits.push(PushRoot { root: root.as_u64(), }); + self.stack.element_stack.push(root); + self.stack.instructions.push(DiffInstruction::PopElement); self.stack.create_children(new.children, MountType::Append); } else { + self.stack.element_stack.push(root); + self.stack.instructions.push(DiffInstruction::PopElement); self.diff_children(old.children, new.children); } } @@ -871,13 +892,7 @@ impl<'bump> DiffState<'bump> { Some(count) => count, None => return, }; - // log::debug!( - // "Left offset, right offset, {}, {}", - // left_offset, - // right_offset, - // ); - // log::debug!("stack before lo is {:#?}", self.stack.instructions); // Ok, we now hopefully have a smaller range of children in the middle // within which to re-order nodes with the same keys, remove old nodes with // now-unused keys, and create new nodes with fresh keys. @@ -926,8 +941,6 @@ impl<'bump> DiffState<'bump> { } else { self.diff_keyed_middle(old_middle, new_middle); } - - log::debug!("stack after km is {:#?}", self.stack.instructions); } /// Diff both ends of the children that share keys. @@ -1054,15 +1067,6 @@ impl<'bump> DiffState<'bump> { // If none of the old keys are reused by the new children, then we remove all the remaining old children and // create the new children afresh. if shared_keys.is_empty() { - log::debug!( - "no shared keys, replacing and creating many with many, {:#?}, {:#?}", - old, - new - ); - log::debug!("old_key_to_old_index, {:#?}", old_key_to_old_index); - log::debug!("new_index_to_old_index, {:#?}", new_index_to_old_index); - log::debug!("shared_keys, {:#?}", shared_keys); - if let Some(first_old) = old.get(0) { self.remove_nodes(&old[1..], true); self.stack @@ -1225,6 +1229,8 @@ impl<'bump> DiffState<'bump> { .try_mounted_id() .unwrap_or_else(|| panic!("broke on {:?}", old)); + log::debug!("element parent is {:?}", el.parent_id.get()); + self.mutations.replace_with(id, nodes_created as u32); self.remove_nodes(el.children, false); } diff --git a/packages/core/src/scopearena.rs b/packages/core/src/scopearena.rs index 0b4fca9f5..db635352a 100644 --- a/packages/core/src/scopearena.rs +++ b/packages/core/src/scopearena.rs @@ -90,6 +90,8 @@ impl ScopeArena { let new_scope_id = ScopeId(self.scope_counter.get()); self.scope_counter.set(self.scope_counter.get() + 1); + log::debug!("new scope {:?} with parent {:?}", new_scope_id, container); + if let Some(old_scope) = self.free_scopes.borrow_mut().pop() { let scope = unsafe { &mut *old_scope }; log::debug!( @@ -251,7 +253,7 @@ impl ScopeArena { id } - pub fn update_reservation(&self, node: &VNode, id: ElementId) { + pub fn update_node(&self, node: &VNode, id: ElementId) { let node = unsafe { std::mem::transmute::<*const VNode, *const VNode>(node) }; *self.nodes.borrow_mut().get_mut(id.0).unwrap() = node; } @@ -369,10 +371,10 @@ impl ScopeArena { let mut cur_el = Some(element); while let Some(id) = cur_el.take() { - log::debug!("checking element {:?} for listeners", id); if let Some(el) = nodes.get(id.0) { let real_el = unsafe { &**el }; if let VNode::Element(real_el) = real_el { + // for listener in real_el.listeners.borrow().iter() { if listener.event == event.name { let mut cb = listener.callback.borrow_mut(); @@ -381,6 +383,7 @@ impl ScopeArena { } } } + cur_el = real_el.parent_id.get(); } } diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 1232c5fa7..d014fc3c0 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -403,12 +403,12 @@ impl VirtualDom { if let Some(element) = event.mounted_dom_id { log::info!("Calling listener {:?}, {:?}", event.scope_id, element); - if let Some(scope) = self.scopes.get_scope(&event.scope_id) { - self.scopes.call_listener_with_bubbling(event, element); - while let Ok(Some(dirty_scope)) = self.receiver.try_next() { - self.pending_messages.push_front(dirty_scope); - } + // if let Some(scope) = self.scopes.get_scope(&event.scope_id) { + self.scopes.call_listener_with_bubbling(event, element); + while let Ok(Some(dirty_scope)) = self.receiver.try_next() { + self.pending_messages.push_front(dirty_scope); } + // } } else { log::debug!("User event without a targetted ElementId. Not currently supported.\nUnsure how to proceed. {:?}", event); } @@ -449,7 +449,9 @@ impl VirtualDom { diff_state.stack.push(DiffInstruction::Diff { new, old }); diff_state.stack.scope_stack.push(scopeid); let scope = scopes.get_scope(&scopeid).unwrap(); - diff_state.stack.element_stack.push(scope.container); + let container = scope.container; + log::debug!("scope {:?} container {:?}", scope.our_arena_idx, container); + diff_state.stack.element_stack.push(container); } } } @@ -467,9 +469,6 @@ impl VirtualDom { self.dirty_scopes.remove(&scope); } - // // I think the stack should be empty at the end of diffing? - // debug_assert_eq!(stack.scope_stack.len(), 1); - committed_mutations.push(mutations); } else { // leave the work in an incomplete state @@ -631,7 +630,7 @@ pub enum SchedulerMsg { #[derive(Debug)] pub struct UserEvent { /// The originator of the event trigger - pub scope_id: ScopeId, + pub scope_id: Option, pub priority: EventPriority, diff --git a/packages/desktop/src/events.rs b/packages/desktop/src/events.rs index 59ad9c28d..5b146e409 100644 --- a/packages/desktop/src/events.rs +++ b/packages/desktop/src/events.rs @@ -11,7 +11,7 @@ use dioxus_html::on::*; struct ImEvent { event: String, mounted_dom_id: u64, - scope: u64, + // scope: u64, contents: serde_json::Value, } @@ -20,11 +20,11 @@ pub fn trigger_from_serialized(val: serde_json::Value) -> UserEvent { let ImEvent { event, mounted_dom_id, - scope, + // scope, contents, } = ims.into_iter().next().unwrap(); - let scope_id = ScopeId(scope as usize); + // let scope_id = ScopeId(scope as usize); let mounted_dom_id = Some(ElementId(mounted_dom_id as usize)); let name = event_name_from_typ(&event); @@ -33,7 +33,7 @@ pub fn trigger_from_serialized(val: serde_json::Value) -> UserEvent { UserEvent { name, priority: EventPriority::Low, - scope_id, + scope_id: None, mounted_dom_id, event, } diff --git a/packages/desktop/src/index.js b/packages/desktop/src/index.js index 2caad4dc2..ced36b378 100644 --- a/packages/desktop/src/index.js +++ b/packages/desktop/src/index.js @@ -39,14 +39,9 @@ class Interpreter { } ReplaceWith(edit) { - // console.log(edit); let root = this.nodes[edit.root]; let els = this.stack.splice(this.stack.length - edit.m); - // console.log(root); - // console.log(els); - - root.replaceWith(...els); } @@ -79,6 +74,7 @@ class Interpreter { const tagName = edit.tag; const el = document.createElement(tagName); this.nodes[edit.root] = el; + el.setAttribute("dioxus-id", edit.root); this.stack.push(el); } @@ -110,14 +106,14 @@ class Interpreter { this.root.addEventListener(event_name, (event) => { // console.log("CLICKED"); const target = event.target; - const val = target.getAttribute(`dioxus-event-${event_name}`); - if (val == null) { + const real_id = target.getAttribute(`dioxus-id`); + if (real_id == null) { return; } - const fields = val.split("."); - const scope_id = parseInt(fields[0]); - const real_id = parseInt(fields[1]); + // const fields = val.split("."); + // const scope_id = parseInt(fields[0]); + // const real_id = parseInt(fields[1]); // // console.log(`parsed event with scope_id ${scope_id} and real_id ${real_id}`); @@ -125,8 +121,8 @@ class Interpreter { let contents = serialize_event(event); let evt = { event: event_name, - scope: scope_id, - mounted_dom_id: real_id, + // scope: scope_id, + mounted_dom_id: parseInt(real_id), contents: contents, }; // console.log(evt);