virtual_node/event/
virtual_events.rs

1use crate::event::event_name::EventName;
2use crate::event::EventHandler;
3use js_sys::Reflect;
4use std::cell::{Ref, RefCell, RefMut};
5use std::collections::HashMap;
6use std::rc::Rc;
7use wasm_bindgen::JsValue;
8
9// Every real DOM element that we create gets a property set on it that can be used to look up
10// its events in [`crate::VirtualEvents`].
11#[doc(hidden)]
12pub const ELEMENT_EVENTS_ID_PROP: &'static str = "__events_id__";
13
14/// Uniquely identifies an element so that we can store it's events in [`VirtualEvents`].
15#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
16pub struct ElementEventsId(u32);
17
18impl ElementEventsId {
19    /// Create a new ElementEventsId.
20    pub fn new(id: u32) -> Self {
21        Self(id)
22    }
23
24    /// Get the inner u32 id.
25    pub fn get(&self) -> u32 {
26        self.0
27    }
28}
29
30// Really only needs to be boxed.. but using an Rc let's us implement the
31//  removes_old_non_delegated_event_listeners test.
32// A future optimization could be using a feature flag to determine whether to Rc or Box this.
33// i.e. #[cfg(feature = "__test-utils")]
34pub(crate) type EventWrapper = Rc<dyn AsRef<JsValue>>;
35
36/// When we create a DOM node, we store all of it's closures and all of it's children's closures
37/// in VirtualEvents.
38///
39/// When an element gets interacted with in the DOM it's event handlers get looked up in
40/// VirtualEvents.
41///
42/// This helps power event delegation, where for many events kinds of events such as onclick we use
43/// a single event listener on the element that the application was mounted on and then as events
44/// occur we look up the event handlers in VirtualEvents.
45///
46/// This is faster since instead of needing to add and remove event listeners from the DOM after
47/// when applying patches we can simply overwrite the old closures in VirtualEvents with new ones.
48///
49/// ## Cloning
50///
51/// VirtualEvents can be cloned cheaply. Clones share the same inner data.
52#[derive(Clone)]
53pub struct VirtualEvents {
54    inner: Rc<RefCell<VirtualEventsInner>>,
55    // Never changes after creation.
56    events_id_props_prefix: f64,
57}
58struct VirtualEventsInner {
59    root: Rc<RefCell<VirtualEventNode>>,
60    events: HashMap<ElementEventsId, Rc<RefCell<HashMap<EventName, EventHandler>>>>,
61    /// For non delegated events an event listener is attached to the DOM element using
62    /// .add_event_listener();
63    /// That event listener is an `EventWrapper`, which in turn will find and call the
64    /// `EventHandler`.
65    /// This setup allows us to replace the `EventHandler` after every render without needing
66    /// to re-attach event listeners.
67    non_delegated_event_wrappers: HashMap<ElementEventsId, HashMap<EventName, EventWrapper>>,
68    next_events_id: u32,
69}
70
71/// A tree where each entry holds the events for the corresponding entry in a
72/// [`crate::VirtualNode`] tree.
73#[derive(Debug)]
74pub struct VirtualEventNode {
75    variant: VirtualEventNodeVariant,
76    previous_sibling: Option<Rc<RefCell<VirtualEventNode>>>,
77    next_sibling: Option<Rc<RefCell<VirtualEventNode>>>,
78}
79
80#[derive(Debug)]
81enum VirtualEventNodeVariant {
82    Element(VirtualEventElement),
83    Text,
84}
85
86/// A virtual event element node.
87#[derive(Debug)]
88pub struct VirtualEventElement {
89    events_id: ElementEventsId,
90    children: Option<VirtualEventElementChildren>,
91}
92#[derive(Debug)]
93struct VirtualEventElementChildren {
94    first_child: Rc<RefCell<VirtualEventNode>>,
95    last_child: Rc<RefCell<VirtualEventNode>>,
96}
97
98impl VirtualEvents {
99    /// Create a new EventsByNodeIdx.
100    pub fn new() -> Self {
101        VirtualEvents {
102            inner: Rc::new(RefCell::new(VirtualEventsInner::new())),
103            events_id_props_prefix: js_sys::Math::random(),
104        }
105    }
106
107    #[cfg(test)]
108    pub fn new_with_prefix(prefix: f64) -> Self {
109        VirtualEvents {
110            inner: Rc::new(RefCell::new(VirtualEventsInner::new())),
111            events_id_props_prefix: prefix,
112        }
113    }
114
115    /// Unique for every PercyDom so that if multiple instances of PercyDom are nested their
116    /// event delegation handlers don't collide.
117    pub fn events_id_props_prefix(&self) -> f64 {
118        self.events_id_props_prefix
119    }
120
121    /// Get the root event node.
122    pub fn root(&self) -> Rc<RefCell<VirtualEventNode>> {
123        self.borrow().root.clone()
124    }
125
126    /// Set the root event node.
127    pub fn set_root(&self, root: VirtualEventNode) {
128        *self.borrow_mut().root.borrow_mut() = root;
129    }
130
131    /// Insert a newly tracked event.
132    ///
133    /// # Panics
134    ///
135    /// Panics if the event_name is delegated and the event is not, or vice versa.
136    pub fn insert_event(
137        &self,
138        events_id: ElementEventsId,
139        event_name: EventName,
140        event: EventHandler,
141        wrapper: Option<EventWrapper>,
142    ) {
143        assert_eq!(event_name.is_delegated(), wrapper.is_none());
144
145        let mut borrow = self.borrow_mut();
146
147        borrow
148            .events
149            .entry(events_id)
150            .or_default()
151            .borrow_mut()
152            .insert(event_name.clone(), event);
153
154        if let Some(wrapper) = wrapper {
155            borrow
156                .non_delegated_event_wrappers
157                .entry(events_id)
158                .or_default()
159                .insert(event_name, wrapper);
160        }
161    }
162
163    /// Overwrite an event handler.
164    ///
165    /// # Panics
166    ///
167    /// Panics if there isn't an event attrib fn to overwrite.
168    pub fn overwrite_event_attrib_fn(
169        &self,
170        events_id: &ElementEventsId,
171        event_name: &EventName,
172        event: EventHandler,
173    ) {
174        let mut borrow = self.borrow_mut();
175
176        let borrow = borrow.events.get_mut(events_id).unwrap();
177        let mut borrow = borrow.borrow_mut();
178        let func = borrow.get_mut(event_name).unwrap();
179
180        *func = event;
181    }
182
183    /// Remove a managed event.
184    pub fn remove_non_delegated_event_wrapper(
185        &mut self,
186        events_id: &ElementEventsId,
187        event_name: &EventName,
188    ) -> EventWrapper {
189        let mut borrow = self.borrow_mut();
190        borrow
191            .non_delegated_event_wrappers
192            .get_mut(events_id)
193            .unwrap()
194            .remove(event_name)
195            .unwrap()
196    }
197
198    /// Get the event handler for a node.
199    pub fn get_event_handler(
200        &self,
201        events_id: &ElementEventsId,
202        event_name: &EventName,
203    ) -> Option<EventHandler> {
204        let borrow = self.borrow();
205        let borrow = borrow.events.get(events_id)?;
206        let borrow = borrow.borrow();
207        borrow.get(event_name).cloned()
208    }
209
210    /// Remove an event handler.
211    pub fn remove_event_handler(
212        &self,
213        events_id: &ElementEventsId,
214        event_name: &EventName,
215    ) -> Option<EventHandler> {
216        let mut borrow = self.borrow_mut();
217
218        let borrow = borrow.events.get_mut(events_id)?;
219        let mut borrow = borrow.borrow_mut();
220        borrow.remove(event_name)
221    }
222
223    /// Remove all event handlers for a node.
224    pub fn remove_node(&self, events_id: &ElementEventsId) {
225        let mut borrow = self.borrow_mut();
226        borrow.events.remove(events_id);
227        borrow.non_delegated_event_wrappers.remove(events_id);
228    }
229
230    /// Create a new element node.
231    pub fn create_element_node(&self) -> VirtualEventNode {
232        VirtualEventNode {
233            variant: VirtualEventNodeVariant::Element(VirtualEventElement::new(
234                self.unique_events_id(),
235            )),
236            previous_sibling: None,
237            next_sibling: None,
238        }
239    }
240
241    /// Create a new element node.
242    pub fn create_text_node(&self) -> VirtualEventNode {
243        VirtualEventNode {
244            variant: VirtualEventNodeVariant::Text,
245            previous_sibling: None,
246            next_sibling: None,
247        }
248    }
249
250    // Create an ElementEventsId that is unique to this VirtualEvents instance.
251    fn unique_events_id(&self) -> ElementEventsId {
252        let mut borrow = self.borrow_mut();
253        let counter = borrow.next_events_id;
254
255        borrow.next_events_id += 1;
256
257        ElementEventsId(counter)
258    }
259
260    fn borrow(&self) -> Ref<'_, VirtualEventsInner> {
261        self.inner.borrow()
262    }
263    fn borrow_mut(&self) -> RefMut<'_, VirtualEventsInner> {
264        self.inner.borrow_mut()
265    }
266}
267
268impl VirtualEventsInner {
269    fn new() -> Self {
270        let root = VirtualEventNode {
271            // ::Text will get replaced with an element shortly after creating VirtualEvents.
272            variant: VirtualEventNodeVariant::Text,
273            previous_sibling: None,
274            next_sibling: None,
275        };
276
277        Self {
278            root: Rc::new(RefCell::new(root)),
279            events: HashMap::new(),
280            non_delegated_event_wrappers: HashMap::new(),
281            next_events_id: 0,
282        }
283    }
284}
285
286impl VirtualEventNode {
287    /// Get the [`VirtualEventNode::VirtualEventElement`] variant.
288    pub fn as_element(&self) -> Option<&VirtualEventElement> {
289        match &self.variant {
290            VirtualEventNodeVariant::Element(e) => Some(e),
291            _ => None,
292        }
293    }
294
295    /// Get a mutable reference to the [`VirtualEventNode::VirtualEventElement`] variant.
296    pub fn as_element_mut(&mut self) -> Option<&mut VirtualEventElement> {
297        match &mut self.variant {
298            VirtualEventNodeVariant::Element(e) => Some(e),
299            _ => None,
300        }
301    }
302
303    /// Get the previous sibling.
304    pub fn previous_sibling(&self) -> Option<&Rc<RefCell<VirtualEventNode>>> {
305        self.previous_sibling.as_ref()
306    }
307
308    /// Get the next sibling.
309    pub fn next_sibling(&self) -> Option<&Rc<RefCell<VirtualEventNode>>> {
310        self.next_sibling.as_ref()
311    }
312
313    /// Replace a node with another.
314    ///
315    /// The new node is given the same siblings as the old node.
316    pub fn replace_with_node(&mut self, mut new: VirtualEventNode) {
317        new.previous_sibling = self.previous_sibling.take();
318        new.next_sibling = self.next_sibling.take();
319
320        *self = new;
321    }
322
323    /// Remove a child node from it's siblings.
324    pub fn remove_node_from_siblings(&mut self, child: &Rc<RefCell<VirtualEventNode>>) {
325        let mut child = child.borrow_mut();
326        let is_first_sibling = child.previous_sibling.is_none();
327        let is_last_sibling = child.next_sibling.is_none();
328
329        let parent = self.as_element_mut().unwrap();
330        if is_first_sibling && is_last_sibling {
331            parent.children = None;
332        } else if is_first_sibling {
333            parent.children.as_mut().unwrap().first_child = child.next_sibling.clone().unwrap();
334        } else if is_last_sibling {
335            parent.children.as_mut().unwrap().last_child = child.previous_sibling.clone().unwrap();
336        }
337
338        match (
339            child.previous_sibling.clone().as_mut(),
340            child.next_sibling.as_mut(),
341        ) {
342            (Some(previous), Some(next)) => {
343                previous.borrow_mut().next_sibling = Some(next.clone());
344                next.borrow_mut().previous_sibling = Some(previous.clone());
345            }
346            (Some(previous), None) => {
347                previous.borrow_mut().next_sibling = None;
348            }
349            (None, Some(next)) => {
350                next.borrow_mut().previous_sibling = None;
351            }
352            (None, None) => {}
353        };
354
355        child.previous_sibling = None;
356        child.next_sibling = None;
357    }
358
359    /// Insert a node before another node.
360    pub fn insert_before(
361        &mut self,
362        new: Rc<RefCell<VirtualEventNode>>,
363        existing: Rc<RefCell<VirtualEventNode>>,
364    ) {
365        let parent = self.as_element_mut().unwrap();
366
367        {
368            let mut new_borrow = new.borrow_mut();
369            let mut existing_borrow = existing.borrow_mut();
370            match existing_borrow.previous_sibling.take() {
371                Some(previous) => {
372                    previous.borrow_mut().next_sibling = Some(new.clone());
373                    new_borrow.previous_sibling = Some(previous);
374                }
375                None => {
376                    parent.children.as_mut().unwrap().first_child = new.clone();
377                }
378            };
379        }
380
381        new.borrow_mut().next_sibling = Some(existing.clone());
382        existing.borrow_mut().previous_sibling = Some(new);
383    }
384}
385
386impl VirtualEventElement {
387    /// Create a new VirtualEventNode for the given events id.
388    fn new(events_id: ElementEventsId) -> Self {
389        VirtualEventElement {
390            events_id,
391            children: None,
392        }
393    }
394
395    /// Get this node's unique id for its events.
396    pub fn events_id(&self) -> ElementEventsId {
397        self.events_id
398    }
399
400    /// Get the element's first child.
401    pub fn first_child(&self) -> Option<Rc<RefCell<VirtualEventNode>>> {
402        self.children.as_ref().map(|c| c.first_child.clone())
403    }
404
405    /// Append a child to the end of the list of children.
406    pub fn append_child(&mut self, new_child: Rc<RefCell<VirtualEventNode>>) {
407        match self.children.as_mut() {
408            Some(children) => {
409                {
410                    children.last_child.borrow_mut().next_sibling = Some(new_child.clone());
411                    let mut new_child_borrow = new_child.borrow_mut();
412
413                    new_child_borrow.previous_sibling = Some(children.last_child.clone());
414                    new_child_borrow.next_sibling = None;
415                }
416
417                children.last_child = new_child;
418            }
419            None => {
420                self.set_first_and_last_child(new_child);
421            }
422        };
423    }
424
425    // Set this element's first and last child.
426    fn set_first_and_last_child(&mut self, child: Rc<RefCell<VirtualEventNode>>) {
427        self.children = Some(VirtualEventElementChildren {
428            first_child: child.clone(),
429            last_child: child.clone(),
430        })
431    }
432}
433
434pub(crate) fn set_events_id(node: &JsValue, events: &VirtualEvents, events_id: ElementEventsId) {
435    Reflect::set(
436        &node.into(),
437        &ELEMENT_EVENTS_ID_PROP.into(),
438        &format!("{}{}", events.events_id_props_prefix(), events_id.get()).into(),
439    )
440    .unwrap();
441}
442
443#[cfg(test)]
444mod tests {
445    use super::*;
446
447    /// Verify that we can append children to a virtual event node.
448    #[test]
449    fn append_children() {
450        let events = VirtualEvents::new_with_prefix(1.);
451
452        let mut node = events.create_element_node();
453        let elem = node.as_element_mut().unwrap();
454
455        let children = create_element_nodes(&events, 3);
456        for child in &children {
457            elem.append_child(child.clone());
458        }
459
460        assert_elem_children_equal(elem, &children);
461    }
462
463    /// Verify that we can insert nodes before another node in the virtual event nodes.
464    #[test]
465    fn insert_before() {
466        let events = VirtualEvents::new_with_prefix(1.);
467
468        let children = create_element_nodes(&events, 3);
469
470        let mut node = events.create_element_node();
471
472        {
473            let elem = node.as_element_mut().unwrap();
474            elem.append_child(children[0].clone());
475        }
476
477        node.insert_before(children[1].clone(), children[0].clone());
478        node.insert_before(children[2].clone(), children[0].clone());
479
480        let expected_order = [
481            children[1].clone(),
482            children[2].clone(),
483            children[0].clone(),
484        ];
485        assert_elem_children_equal(node.as_element().unwrap(), &expected_order);
486    }
487
488    /// Verify that we can remove a node from its siblings.
489    #[test]
490    fn remove_node_from_siblings() {
491        let events = VirtualEvents::new_with_prefix(1.);
492
493        let children = create_element_nodes(&events, 3);
494
495        let mut node = events.create_element_node();
496
497        {
498            let elem = node.as_element_mut().unwrap();
499            for child in &children {
500                elem.append_child(child.clone());
501            }
502        }
503
504        node.remove_node_from_siblings(&children[1]);
505        assert_elem_children_equal(
506            node.as_element().unwrap(),
507            &[children[0].clone(), children[2].clone()],
508        );
509
510        node.remove_node_from_siblings(&children[0]);
511        assert_elem_children_equal(node.as_element().unwrap(), &[children[2].clone()]);
512
513        node.remove_node_from_siblings(&children[2]);
514        assert_elem_children_equal(node.as_element().unwrap(), &[]);
515    }
516
517    /// Verify that we can replace a node with another node.
518    #[test]
519    fn replace_node() {
520        let events = VirtualEvents::new_with_prefix(1.);
521
522        let children = create_element_nodes(&events, 3);
523
524        let mut node = events.create_element_node();
525
526        {
527            let elem = node.as_element_mut().unwrap();
528            for child in &children {
529                elem.append_child(child.clone());
530            }
531        }
532
533        let new_node = events.create_element_node();
534        let new_node_events_id = new_node.as_element().unwrap().events_id;
535
536        assert_eq!(node_events_id(&children[1]) == new_node_events_id, false);
537        children[1].borrow_mut().replace_with_node(new_node);
538        assert_eq!(node_events_id(&children[1]) == new_node_events_id, true);
539
540        assert_elem_children_equal(
541            node.as_element().unwrap(),
542            &[
543                children[0].clone(),
544                children[1].clone(),
545                children[2].clone(),
546            ],
547        );
548    }
549
550    fn create_element_nodes(
551        events: &VirtualEvents,
552        count: usize,
553    ) -> Vec<Rc<RefCell<VirtualEventNode>>> {
554        (0..count)
555            .into_iter()
556            .map(|_| {
557                let child = events.create_element_node();
558                let child = Rc::new(RefCell::new(child));
559                child
560            })
561            .collect()
562    }
563
564    fn assert_elem_children_equal(
565        elem: &VirtualEventElement,
566        expected: &[Rc<RefCell<VirtualEventNode>>],
567    ) {
568        let mut idx = 0;
569
570        let mut next_child = elem.first_child().clone();
571
572        while let Some(child) = next_child {
573            let child = child.borrow();
574
575            if idx == 0 {
576                assert_eq!(child.previous_sibling.is_none(), true);
577            }
578
579            assert_eq!(
580                child.as_element().unwrap().events_id(),
581                expected[idx].borrow().as_element().unwrap().events_id,
582            );
583
584            next_child = child.next_sibling.clone();
585            idx += 1;
586
587            if idx == expected.len() {
588                assert_eq!(child.next_sibling.is_none(), true);
589            }
590        }
591
592        assert_eq!(idx, expected.len());
593
594        assert_elem_first_and_last_child(elem, expected);
595    }
596
597    fn assert_elem_first_and_last_child(
598        elem: &VirtualEventElement,
599        expected_children: &[Rc<RefCell<VirtualEventNode>>],
600    ) {
601        if expected_children.len() == 0 {
602            assert!(elem.children.is_none());
603            return;
604        }
605
606        let elem_children = elem.children.as_ref().unwrap();
607
608        assert_eq!(
609            node_events_id(&elem_children.first_child),
610            node_events_id(expected_children.first().unwrap()),
611        );
612
613        assert_eq!(
614            node_events_id(&elem_children.last_child),
615            node_events_id(expected_children.last().unwrap()),
616        );
617    }
618
619    fn node_events_id(node: &Rc<RefCell<VirtualEventNode>>) -> ElementEventsId {
620        node.borrow().as_element().unwrap().events_id
621    }
622}