fix: more panic resilience (#5489)

* fix: more panic resilience

* fix: panic typos
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2026-04-14 17:58:50 -07:00
1 parent cb5abb48dd
commit 51b0cd3313
1 file changed
+13 -8
+13 -8
View File
@@ -406,21 +406,25 @@ fn MyComponent() -> Element {{
name = "VirtualDom::handle_bubbling_event" name = "VirtualDom::handle_bubbling_event"
)] )]
fn handle_bubbling_event(&self, parent: ElementRef, name: &str, uievent: Event<dyn Any>) { fn handle_bubbling_event(&self, parent: ElementRef, name: &str, uievent: Event<dyn Any>) {
let mounts = self.mounts.borrow();
// If the event bubbles, we traverse through the tree until we find the target element. // If the event bubbles, we traverse through the tree until we find the target element.
// Loop through each dynamic attribute (in a depth first order) in this template before moving up to the template's parent. // Loop through each dynamic attribute (in a depth first order) in this template before moving up to the template's parent.
let mut parent = Some(parent); let mut parent = Some(parent);
while let Some(path) = parent { while let Some(path) = parent {
let mut listeners = vec![]; let mut listeners = vec![];
let mount_id;
// We do this in its own block to prevent mounts from staying open while we call user code
{
let mounts = self.mounts.borrow();
let Some(mount) = mounts.get(path.mount.0) else { let Some(mount) = mounts.get(path.mount.0) else {
// If the node is suspended and not mounted, we can just ignore the event // If the node is suspended and not mounted, we can just ignore the event
return; return;
}; };
let el_ref = &mount.node; let el_ref = &mount.node;
let node_template = el_ref.template; let node_template = el_ref.template;
let target_path = path.path; let target_path = path.path;
mount_id = el_ref.mount.get().as_usize();
// Accumulate listeners into the listener list bottom to top // Accumulate listeners into the listener list bottom to top
for (idx, this_path) in node_template.attr_paths.iter().enumerate() { for (idx, this_path) in node_template.attr_paths.iter().enumerate() {
@@ -428,8 +432,11 @@ fn MyComponent() -> Element {{
for attr in attrs.iter() { for attr in attrs.iter() {
// Remove the "on" prefix if it exists, TODO, we should remove this and settle on one // Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
if attr.name.get(2..) == Some(name) && target_path.is_descendant(this_path) { if attr.name.get(2..) == Some(name) && target_path.is_descendant(this_path)
listeners.push(&attr.value); {
if let AttributeValue::Listener(listener) = &attr.value {
listeners.push(listener.clone());
}
// Break if this is the exact target element. // Break if this is the exact target element.
// This means we won't call two listeners with the same name on the same element. This should be // This means we won't call two listeners with the same name on the same element. This should be
@@ -440,6 +447,7 @@ fn MyComponent() -> Element {{
} }
} }
} }
}
// Now that we've accumulated all the parent attributes for the target element, call them in reverse order // Now that we've accumulated all the parent attributes for the target element, call them in reverse order
// We check the bubble state between each call to see if the event has been stopped from bubbling // We check the bubble state between each call to see if the event has been stopped from bubbling
@@ -449,7 +457,6 @@ fn MyComponent() -> Element {{
listeners.len() listeners.len()
); );
for listener in listeners.into_iter().rev() { for listener in listeners.into_iter().rev() {
if let AttributeValue::Listener(listener) = listener {
listener.call(uievent.clone()); listener.call(uievent.clone());
let metadata = uievent.metadata.borrow(); let metadata = uievent.metadata.borrow();
@@ -457,10 +464,8 @@ fn MyComponent() -> Element {{
return; return;
} }
} }
}
let mount = el_ref.mount.get().as_usize(); parent = mount_id.and_then(|id| self.mounts.borrow().get(id).and_then(|el| el.parent));
parent = mount.and_then(|id| mounts.get(id).and_then(|el| el.parent));
} }
} }