diff --git a/packages/core/src/scope.rs b/packages/core/src/scope.rs index b6edbb67b..015c2480a 100644 --- a/packages/core/src/scope.rs +++ b/packages/core/src/scope.rs @@ -43,7 +43,8 @@ pub struct Scope { // - is self-refenrential and therefore needs to point into the bump // // Stores references into the listeners attached to the vnodes - pub listeners: RefCell>, + // NEEDS TO BE PRIVATE + listeners: RefCell>, // Unsafety // - is a raw ptr because we need to compare @@ -94,6 +95,37 @@ impl Scope { props, } } + + // A safe wrapper around calling listeners + // calling listeners will invalidate the list of listeners + // The listener list will be completely drained because the next frame will write over previous listeners + pub fn call_listener(&mut self, trigger: EventTrigger) { + let EventTrigger { + listener_id, + event: source, + .. + } = trigger; + + unsafe { + let listener = self + .listeners + .borrow() + .get(listener_id as usize) + .expect("Listener should exist if it was triggered") + .as_ref() + .unwrap(); + + // Run the callback with the user event + log::debug!("Running listener"); + listener(source); + log::debug!("Running listener"); + + // drain all the event listeners + // if we don't, then they'll stick around and become invalid + // big big big big safety issue + self.listeners.borrow_mut().drain(..); + } + } } pub struct RawComponent { diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 20a249d78..a98e23879 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -125,31 +125,12 @@ impl VirtualDom { /// /// ``` pub fn progress_with_event(&mut self, event: EventTrigger) -> Result> { - let EventTrigger { - component_id, - listener_id, - event: source, - } = event; - let component = self .components - .get_mut(component_id) + .get_mut(event.component_id) .expect("Component should exist if an event was triggered"); - log::debug!("list: {}", component.listeners.borrow().len()); - - let listener = unsafe { - component - .listeners - .borrow() - .get(listener_id as usize) - .expect("Listener should exist if it was triggered") - .as_ref() - } - .unwrap(); - - // Run the callback with the user event - listener(source); + component.call_listener(event); // Reset and then build a new diff machine // The previous edit list cannot be around while &mut is held diff --git a/packages/web/examples/infer.rs b/packages/web/examples/infer.rs index 4382ba75d..b1eb91ad0 100644 --- a/packages/web/examples/infer.rs +++ b/packages/web/examples/infer.rs @@ -10,16 +10,32 @@ fn main() { } static Example: FC<()> = |ctx, _props| { + let (event, set_event) = use_state(&ctx, || None); + let event = format!("{:#?}", event); + let handler = move |evt: MouseEvent| { - // Awesome! - // We get type inference with events - dbg!(evt.alt_key); + set_event(Some(evt)); }; ctx.render(rsx! { - button { - "Hello" - onclick: {handler} + div { + + class: "py-12 px-4 w-full max-w-2xl mx-auto bg-red-100" + // class: "py-12 px-4 text-center w-full max-w-2xl mx-auto bg-red-100" + span { + class: "text-sm font-semibold" + "Dioxus Example: Synthetic Events" + } + 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" + + "press me" + } + pre { + onmousemove: {handler} + id: "json" + "{event}" + } } }) };