chinedufn / percy

Build frontend browser apps with Rust + WebAssembly. Supports server side rendering.
https://chinedufn.github.io/percy/
Apache License 2.0
2.25k stars 84 forks source link

Fix event handling #186

Closed chinedufn closed 1 year ago

chinedufn commented 1 year ago

This commit fixes an issue where a node's event handlers would stop working if you added or removed DOM elements before that node in certain ways.

We've added test cases and changed our event handling implementation to handle these scenarios.


The problem was that when we created new real DOM elements we gave them a property .__events_id__ = NodeIdx where NodeIdx was its index in the virtual-dom at the time of creation.

Then when you triggered an event on that element we would look up its events using that node idx.

The problem with that is that once you add/remove virtual nodes before it in the virtual tree, the node idx is no longer correct.

The new implementation added in this commit uses unique identifiers to look up the events. So, on the real DOM element we now set .__events_id__ = SomeUniqueId and we maintain a map of (pseudocode) HashMap<SomeUniqueId, Rc<RefCell<SomeEvents>>.

Alongside this we maintain a tree of SomeUniqueId's that we add/remove to during the same function that add/remove's to the real DOM tree.

This lets us know whifh SomeUniqueId corresponds to the NodeIdx so that at the end of patching we can update the Rc<RefCell<SomeEvents>> for the correct dom element.