Fix leak in render macro
This commit is contained in:
9 files changed
+197
-114
No files matched your search
+75
-47
@@ -2,13 +2,13 @@ use crate::{
|
||||
any_props::AnyProps,
|
||||
any_props::VProps,
|
||||
bump_frame::BumpFrame,
|
||||
innerlude::{DynamicNode, EventHandler, VComponent, VNodeId, VText},
|
||||
innerlude::{DynamicNode, ElementRef, EventHandler, VComponent, VNodeId, VText},
|
||||
lazynodes::LazyNodes,
|
||||
nodes::{IntoAttributeValue, IntoDynNode, RenderReturn},
|
||||
runtime::Runtime,
|
||||
scope_context::ScopeContext,
|
||||
AnyValue, Attribute, AttributeType, AttributeValue, Element, Event, MountedAttribute,
|
||||
Properties, TaskId,
|
||||
AnyValue, Attribute, AttributeType, AttributeValue, Element, ElementId, Event,
|
||||
MountedAttribute, Properties, TaskId, Template, VNode,
|
||||
};
|
||||
use bumpalo::{boxed::Box as BumpBox, Bump};
|
||||
use std::{
|
||||
@@ -348,17 +348,76 @@ impl<'src> ScopeState {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn render(&'src self, rsx: LazyNodes<'src, '_>) -> Element<'src> {
|
||||
let element = rsx.call(self);
|
||||
// <<<<<<< HEAD
|
||||
// let element = rsx.call(self);
|
||||
|
||||
// let mut listeners = self.attributes_to_drop_before_render.borrow_mut();
|
||||
// for attr in element.dynamic_attrs {
|
||||
// attr.ty.for_each(|attr| {
|
||||
// match attr.value {
|
||||
// // We need to drop listeners before the next render because they may borrow data from the borrowed props which will be dropped
|
||||
// AttributeValue::Listener(_) => {
|
||||
// let unbounded = unsafe { std::mem::transmute(attr as *const Attribute) };
|
||||
// listeners.push(unbounded);
|
||||
// }
|
||||
// // We need to drop any values manually to make sure that their drop implementation is called before the next render
|
||||
// AttributeValue::Any(_) => {
|
||||
// let unbounded = unsafe { std::mem::transmute(attr as *const Attribute) };
|
||||
// self.previous_frame().add_attribute_to_drop(unbounded);
|
||||
// }
|
||||
|
||||
// _ => (),
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// let mut props = self.borrowed_props.borrow_mut();
|
||||
// let mut drop_props = self
|
||||
// .previous_frame()
|
||||
// .props_to_drop_before_reset
|
||||
// .borrow_mut();
|
||||
// for node in element.dynamic_nodes {
|
||||
// if let DynamicNode::Component(comp) = node {
|
||||
// let unbounded = unsafe { std::mem::transmute(comp as *const VComponent) };
|
||||
// if !comp.static_props {
|
||||
// props.push(unbounded);
|
||||
// }
|
||||
// drop_props.push(unbounded);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Some(element)
|
||||
// =======
|
||||
// Note: We can't do anything in this function related to safety because the user could always circumvent it by creating a VNode manually and return it without calling this function
|
||||
Some(rsx.call(self))
|
||||
// >>>>>>> 9fe172e9 (Fix leak in render macro)
|
||||
}
|
||||
|
||||
/// Create a [`crate::VNode`] from the component parts
|
||||
pub fn vnode(
|
||||
&'src self,
|
||||
parent: Cell<Option<ElementRef>>,
|
||||
key: Option<&'src str>,
|
||||
template: Cell<Template<'static>>,
|
||||
root_ids: RefCell<bumpalo::collections::Vec<'src, ElementId>>,
|
||||
dynamic_nodes: &'src [DynamicNode<'src>],
|
||||
dynamic_attrs: &'src [MountedAttribute<'src>],
|
||||
) -> VNode<'src> {
|
||||
let mut listeners = self.attributes_to_drop_before_render.borrow_mut();
|
||||
for attr in element.dynamic_attrs {
|
||||
attr.ty.for_each(|attr| {
|
||||
for attr in dynamic_attrs {
|
||||
let attrs = match attr.ty {
|
||||
AttributeType::Single(ref attr) => std::slice::from_ref(attr),
|
||||
AttributeType::Many(attrs) => attrs,
|
||||
};
|
||||
|
||||
for attr in attrs {
|
||||
match attr.value {
|
||||
// We need to drop listeners before the next render because they may borrow data from the borrowed props which will be dropped
|
||||
AttributeValue::Listener(_) => {
|
||||
let unbounded = unsafe { std::mem::transmute(attr as *const Attribute) };
|
||||
listeners.push(unbounded);
|
||||
}
|
||||
|
||||
// We need to drop any values manually to make sure that their drop implementation is called before the next render
|
||||
AttributeValue::Any(_) => {
|
||||
let unbounded = unsafe { std::mem::transmute(attr as *const Attribute) };
|
||||
@@ -367,7 +426,7 @@ impl<'src> ScopeState {
|
||||
|
||||
_ => (),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let mut props = self.borrowed_props.borrow_mut();
|
||||
@@ -375,7 +434,7 @@ impl<'src> ScopeState {
|
||||
.previous_frame()
|
||||
.props_to_drop_before_reset
|
||||
.borrow_mut();
|
||||
for node in element.dynamic_nodes {
|
||||
for node in dynamic_nodes {
|
||||
if let DynamicNode::Component(comp) = node {
|
||||
let unbounded = unsafe { std::mem::transmute(comp as *const VComponent) };
|
||||
if !comp.static_props {
|
||||
@@ -385,45 +444,14 @@ impl<'src> ScopeState {
|
||||
}
|
||||
}
|
||||
|
||||
Some(element)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Take a [`crate::VNode`] and link it to a [`ScopeState`]
|
||||
///
|
||||
/// This is used internally in the render macro
|
||||
pub fn link_node(&'src self, element: &crate::VNode<'src>) {
|
||||
let mut listeners = self.attributes_to_drop_before_render.borrow_mut();
|
||||
for attr in element.dynamic_attrs {
|
||||
match attr.value {
|
||||
// We need to drop listeners before the next render because they may borrow data from the borrowed props which will be dropped
|
||||
AttributeValue::Listener(_) => {
|
||||
let unbounded = unsafe { std::mem::transmute(attr as *const Attribute) };
|
||||
listeners.push(unbounded);
|
||||
}
|
||||
// We need to drop any values manually to make sure that their drop implementation is called before the next render
|
||||
AttributeValue::Any(_) => {
|
||||
let unbounded = unsafe { std::mem::transmute(attr as *const Attribute) };
|
||||
self.previous_frame().add_attribute_to_drop(unbounded);
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let mut props = self.borrowed_props.borrow_mut();
|
||||
let mut drop_props = self
|
||||
.previous_frame()
|
||||
.props_to_drop_before_reset
|
||||
.borrow_mut();
|
||||
for node in element.dynamic_nodes {
|
||||
if let DynamicNode::Component(comp) = node {
|
||||
let unbounded = unsafe { std::mem::transmute(comp as *const VComponent) };
|
||||
if !comp.static_props {
|
||||
props.push(unbounded);
|
||||
}
|
||||
drop_props.push(unbounded);
|
||||
}
|
||||
VNode {
|
||||
stable_id: Default::default(),
|
||||
key,
|
||||
parent,
|
||||
template,
|
||||
root_ids,
|
||||
dynamic_nodes,
|
||||
dynamic_attrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user