Răsfoiți Sursa

feat: it properly bubbles

Jonathan Kelley 3 ani în urmă
părinte
comite
9d8c5ca5ab

+ 26 - 20
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);
             }

+ 5 - 2
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();
                 }
             }

+ 9 - 10
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<ScopeId>,
 
     pub priority: EventPriority,
 

+ 4 - 4
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,
     }

+ 8 - 12
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);