From 5b7887d76c714d11e0cea5207197ffaac856a0a7 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Mon, 15 Mar 2021 02:16:03 -0400 Subject: [PATCH] Fix: some stuff related to event listeners. POC for lifecyel --- packages/core/src/patch.rs | 12 +++++- packages/core/src/scope.rs | 11 ++++- packages/core/src/virtual_dom.rs | 9 ++-- packages/web/examples/rsxt.rs | 70 ++++++++++++++++++++++++++------ packages/web/src/interpreter.rs | 23 +++++++++-- packages/web/src/lib.rs | 2 +- 6 files changed, 103 insertions(+), 24 deletions(-) diff --git a/packages/core/src/patch.rs b/packages/core/src/patch.rs index cc89efec2..306ce8e5d 100644 --- a/packages/core/src/patch.rs +++ b/packages/core/src/patch.rs @@ -146,13 +146,17 @@ pub struct EditMachine<'lock> { pub traversal: Traversal, next_temporary: u32, forcing_new_listeners: bool, - + + // // if the current node is a "known" node + // // any actions that modify this node should update the mapping + // current_known: Option, pub emitter: EditList<'lock>, } impl<'lock> EditMachine<'lock> { pub fn new() -> Self { Self { + // current_known: None, traversal: Traversal::new(), next_temporary: 0, forcing_new_listeners: false, @@ -283,6 +287,11 @@ impl<'a> EditMachine<'a> { debug_assert!(self.traversal_is_committed()); // debug!("emit: replace_with()"); self.emitter.push(Edit::ReplaceWith {}); + // if let Some(id) = self.current_known { + // // update mapping + // self.emitter.push(Edit::MakeKnown{node: id}); + // self.current_known = None; + // } // self.emitter.replace_with(); } @@ -377,6 +386,7 @@ impl<'a> EditMachine<'a> { pub fn load_known_root(&mut self, id: u32) { log::debug!("emit: TraverseToKnown({:?})", id); + // self.current_known = Some(id); self.emitter.push(Edit::TraverseToKnown { node: id }) } diff --git a/packages/core/src/scope.rs b/packages/core/src/scope.rs index 8eed046f5..bbc5c3374 100644 --- a/packages/core/src/scope.rs +++ b/packages/core/src/scope.rs @@ -73,6 +73,12 @@ impl Scope { } } + pub fn update_caller<'creator_node>(&mut self, caller: Weak>) { + let broken_caller: Weak> = unsafe { std::mem::transmute(caller) }; + + self.caller = broken_caller; + } + /// Create a new context and run the component with references from the Virtual Dom /// This function downcasts the function pointer based on the stored props_type /// @@ -115,13 +121,14 @@ impl Scope { - Public API cannot drop or destructure VNode */ - frame.head_node = node_slot.as_ref() + frame.head_node = node_slot + .as_ref() // .deref() .borrow_mut() .take() .expect("Viewing did not happen"); - Ok(()) + Ok(()) } // A safe wrapper around calling listeners diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 7029b7bf8..1782fc6a4 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -3,7 +3,7 @@ use crate::{error::Error, innerlude::*}; use crate::{patch::Edit, scope::Scope}; use generational_arena::Arena; -use std::{any::TypeId, borrow::Borrow, rc::{Rc, Weak}}; +use std::{any::TypeId, borrow::{Borrow, BorrowMut}, rc::{Rc, Weak}}; use thiserror::private::AsDynError; // We actually allocate the properties for components in their parent's properties @@ -119,21 +119,20 @@ impl VirtualDom { diff_machine.change_list.load_known_root(id); diff_machine.diff_node(c.old_frame(), c.new_frame()); - diff_machine.change_list.save_known_root(id); + // diff_machine.change_list.save_known_root(id); } } LifeCycleEvent::PropsChanged { caller, id, scope } => { let idx = scope.upgrade().unwrap().as_ref().borrow().unwrap(); - // We're modifying the component arena while holding onto references into the assoiated bump arenas of its children - // those references are stable, even if the component arena moves around in memory, thanks to the bump arenas. - // However, there is no way to convey this to rust, so we need to use unsafe to pierce through the lifetime. unsafe { let p = &mut *(very_unsafe_components); // todo, hook up the parent/child indexes properly // let idx = p.insert_with(|f| Scope::new(caller, f, None)); let c = p.get_mut(idx).unwrap(); + c.update_caller(caller); c.run_scope()?; + // c.caller = caller; diff_machine.change_list.load_known_root(id); diff --git a/packages/web/examples/rsxt.rs b/packages/web/examples/rsxt.rs index 19e0827eb..80b2ca1fc 100644 --- a/packages/web/examples/rsxt.rs +++ b/packages/web/examples/rsxt.rs @@ -40,10 +40,56 @@ static Example: FC = |ctx, props| { } // CustomButton { name: sub, set_name: Box::new(move || set_name("jack")) } - CustomButton { name: "Jack!", set_name: Box::new(move || set_name("jack")) } - CustomButton { name: "Jill!", set_name: Box::new(move || set_name("jill")) } - CustomButton { name: "Bill!", set_name: Box::new(move || set_name("Bill")) } - CustomButton { name: "Reset!", set_name: Box::new(move || set_name(props.initial_name)) } + CustomButton { name: "Jack!", set_name: Box::new(set_name) } + CustomButton { name: "Jill!", set_name: Box::new(set_name) } + CustomButton { name: "Bob!", set_name: Box::new(set_name) } + CustomButton { name: "Bill!", set_name: Box::new(set_name) } + CustomButton { name: "Dill!", set_name: Box::new(set_name) } + CustomButton { name: "Crack!", set_name: Box::new(set_name) } + CustomButton { name: "back!", set_name: Box::new(set_name) } + CustomButton { name: "cheder!", set_name: Box::new(set_name) } + CustomButton { name: "Jack!", set_name: Box::new(set_name) } + CustomButton { name: "Jill!", set_name: Box::new(set_name) } + CustomButton { name: "Bob!", set_name: Box::new(set_name) } + CustomButton { name: "Bill!", set_name: Box::new(set_name) } + CustomButton { name: "Dill!", set_name: Box::new(set_name) } + CustomButton { name: "Crack!", set_name: Box::new(set_name) } + CustomButton { name: "back!", set_name: Box::new(set_name) } + CustomButton { name: "cheder!", set_name: Box::new(set_name) } + CustomButton { name: "Jack!", set_name: Box::new(set_name) } + CustomButton { name: "Jill!", set_name: Box::new(set_name) } + CustomButton { name: "Bob!", set_name: Box::new(set_name) } + CustomButton { name: "Bill!", set_name: Box::new(set_name) } + CustomButton { name: "Dill!", set_name: Box::new(set_name) } + CustomButton { name: "Crack!", set_name: Box::new(set_name) } + CustomButton { name: "back!", set_name: Box::new(set_name) } + CustomButton { name: "cheder!", set_name: Box::new(set_name) } + CustomButton { name: "Jack!", set_name: Box::new(set_name) } + CustomButton { name: "Jill!", set_name: Box::new(set_name) } + CustomButton { name: "Bob!", set_name: Box::new(set_name) } + CustomButton { name: "Bill!", set_name: Box::new(set_name) } + CustomButton { name: "Dill!", set_name: Box::new(set_name) } + CustomButton { name: "Crack!", set_name: Box::new(set_name) } + CustomButton { name: "back!", set_name: Box::new(set_name) } + CustomButton { name: "cheder!", set_name: Box::new(set_name) } + CustomButton { name: "Jack!", set_name: Box::new(set_name) } + CustomButton { name: "Jill!", set_name: Box::new(set_name) } + CustomButton { name: "Bob!", set_name: Box::new(set_name) } + CustomButton { name: "Bill!", set_name: Box::new(set_name) } + CustomButton { name: "Dill!", set_name: Box::new(set_name) } + CustomButton { name: "Crack!", set_name: Box::new(set_name) } + CustomButton { name: "back!", set_name: Box::new(set_name) } + CustomButton { name: "cheder!", set_name: Box::new(set_name) } + CustomButton { name: "Jack!", set_name: Box::new(set_name) } + CustomButton { name: "Jill!", set_name: Box::new(set_name) } + CustomButton { name: "Bob!", set_name: Box::new(set_name) } + CustomButton { name: "Bill!", set_name: Box::new(set_name) } + CustomButton { name: "Dill!", set_name: Box::new(set_name) } + CustomButton { name: "Crack!", set_name: Box::new(set_name) } + CustomButton { name: "back!", set_name: Box::new(set_name) } + CustomButton { name: "cheder!", set_name: Box::new(set_name) } + // CustomButton { name: "Bill!", set_name: Box::new(move || set_name("Bill")) } + // CustomButton { name: "Reset!", set_name: Box::new(move || set_name(props.initial_name)) } } }) @@ -51,9 +97,9 @@ static Example: FC = |ctx, props| { #[derive(Props)] struct ButtonProps<'src> { - name: &'src str, + name: &'static str, // name: &'src str, - set_name: Box< dyn Fn() + 'src> + set_name: Box< dyn Fn(&'static str) + 'src> } impl PartialEq for ButtonProps<'_> { fn eq(&self, other: &Self) -> bool { @@ -63,13 +109,13 @@ impl PartialEq for ButtonProps<'_> { fn CustomButton<'a>(ctx: Context<'a>, props: &'a ButtonProps<'a>) -> DomTree { ctx.render(rsx!{ - div { - button { - class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow" - onmouseover: move |_| (props.set_name)() - "{props.name}" - } + // div { + button { + class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow" + onmouseover: move |_| (props.set_name)(props.name) + "{props.name}" } + // } }) } diff --git a/packages/web/src/interpreter.rs b/packages/web/src/interpreter.rs index 2147a0a69..429a6bebe 100644 --- a/packages/web/src/interpreter.rs +++ b/packages/web/src/interpreter.rs @@ -36,6 +36,8 @@ pub(crate) struct PatchMachine { pub(crate) document: Document, pub(crate) events: EventDelegater, + + pub(crate) current_known: Option, } #[derive(Debug)] @@ -95,9 +97,13 @@ impl EventDelegater { if let (Some(gi_id), Some(gi_gen), Some(li_idx)) = (gi_id, gi_gen, li_idx) { // Call the trigger + log::debug!("decoded gi_id: {}, gi_gen: {}, li_idx: {}", gi_id,gi_gen,li_idx); + + let triggered_scope = ScopeIdx::from_raw_parts(gi_id, gi_gen); trigger.0.as_ref()(EventTrigger::new( virtual_event_from_websys_event(event), - scope, + triggered_scope, + // scope, li_idx, )); } @@ -167,6 +173,7 @@ impl PatchMachine { let events = EventDelegater::new(root.clone(), event_callback); Self { + current_known: None, known_roots: Default::default(), root, events, @@ -250,6 +257,13 @@ impl PatchMachine { panic!("Cannot replace node: {:?}", old_node); } + // poc to see if this is a valid solution + if let Some(id) = self.current_known { + // update mapping + self.known_roots.insert(id, new_node.clone()); + self.current_known = None; + } + self.stack.push(new_node); } @@ -485,9 +499,12 @@ impl PatchMachine { self.known_roots.insert(node, domnode.clone()); } Edit::TraverseToKnown { node } => { - let domnode = self.known_roots.get(&node).expect("Failed to pop know root"); + let domnode = self + .known_roots + .get(&node) + .expect("Failed to pop know root"); + self.current_known = Some(node); self.stack.push(domnode.clone()); - } Edit::RemoveKnown => {} } diff --git a/packages/web/src/lib.rs b/packages/web/src/lib.rs index 50ba8af38..3d5ff8fd3 100644 --- a/packages/web/src/lib.rs +++ b/packages/web/src/lib.rs @@ -102,7 +102,7 @@ impl WebsysRenderer { for edit in &edits { log::debug!("edit stream {:?}", edit); - log::debug!("Stream stack {:#?}", patch_machine.stack.top()); + // log::debug!("Stream stack {:#?}", patch_machine.stack.top()); patch_machine.handle_edit(edit); }