Fix: memory leak on listeners for elements (#2244)
* Fix: memory leak on listeners for elements * Recycle in manuallydrop --------- Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
This commit is contained in:
1 parent
6f3c5518ca
commit
44fe2defc2
3 files changed
+27
-2
No files matched your search
Generated
+1
@@ -2453,6 +2453,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
@@ -142,6 +142,29 @@ impl Clone for VNode {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for VNode {
|
||||
fn drop(&mut self) {
|
||||
// FIXME:
|
||||
// TODO:
|
||||
//
|
||||
// We have to add this drop *here* becase we can't add a drop impl to AttributeValue and
|
||||
// keep semver compatibility. Adding a drop impl means you can't destructure the value, which
|
||||
// we need to do for enums.
|
||||
//
|
||||
// if dropping this will drop the last vnode (rc count is 1), then we need to drop the listeners
|
||||
// in this template
|
||||
if Rc::strong_count(&self.vnode) == 1 {
|
||||
for attrs in self.vnode.dynamic_attrs.iter() {
|
||||
for attr in attrs.iter() {
|
||||
if let AttributeValue::Listener(listener) = &attr.value {
|
||||
listener.callback.manually_drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for VNode {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Rc::ptr_eq(&self.vnode, &other.vnode)
|
||||
@@ -714,14 +737,14 @@ impl AttributeValue {
|
||||
///
|
||||
/// The callback must be confined to the lifetime of the ScopeState
|
||||
pub fn listener<T: 'static>(mut callback: impl FnMut(Event<T>) + 'static) -> AttributeValue {
|
||||
// TODO: maybe don't use the copy-variant of EventHandler here?
|
||||
// Maybe, create an Owned variant so we are less likely to run into leaks
|
||||
AttributeValue::Listener(EventHandler::new(move |event: Event<dyn Any>| {
|
||||
let data = event.data.downcast::<T>().unwrap();
|
||||
// if let Ok(data) = event.data.downcast::<T>() {
|
||||
callback(Event {
|
||||
propagates: event.propagates,
|
||||
data,
|
||||
});
|
||||
// }
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -189,6 +189,7 @@ impl<T, S: Storage<T>> GenerationalBox<T, S> {
|
||||
/// Drop the value out of the generational box and invalidate the generational box. This will return the value if the value was taken.
|
||||
pub fn manually_drop(&self) -> Option<T> {
|
||||
if self.validate() {
|
||||
<S as AnyStorage>::recycle(&self.raw);
|
||||
Storage::take(&self.raw.0.data)
|
||||
} else {
|
||||
None
|
||||
|
||||
Reference in new issue
Block a user