fix render macro
This commit is contained in:
1 parent
a0ce5493ea
commit
0a35b5a670
3 files changed
+53
-4
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
use std::ptr::NonNull;
|
use crate::ScopeState;use std::ptr::NonNull;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
innerlude::DirtyScope, nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom,
|
innerlude::DirtyScope, nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom,
|
||||||
@@ -174,7 +174,14 @@ impl VirtualDom {
|
|||||||
scope.borrowed_props.borrow_mut().clear();
|
scope.borrowed_props.borrow_mut().clear();
|
||||||
|
|
||||||
// Now that all the references are gone, we can safely drop our own references in our listeners.
|
// Now that all the references are gone, we can safely drop our own references in our listeners.
|
||||||
let mut listeners = scope.attributes_to_drop_before_render.borrow_mut();
|
scope.drop_listeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScopeState {
|
||||||
|
/// Drop all listeners that were allocated in the bump allocator.
|
||||||
|
pub(crate) fn drop_listeners(&self) {
|
||||||
|
let mut listeners = self.attributes_to_drop_before_render.borrow_mut();
|
||||||
listeners.drain(..).for_each(|listener| {
|
listeners.drain(..).for_each(|listener| {
|
||||||
let listener = unsafe { &*listener };
|
let listener = unsafe { &*listener };
|
||||||
if let AttributeValue::Listener(l) = &listener.value {
|
if let AttributeValue::Listener(l) = &listener.value {
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ pub struct ScopeState {
|
|||||||
|
|
||||||
impl Drop for ScopeState {
|
impl Drop for ScopeState {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
self.drop_listeners();
|
||||||
self.runtime.remove_context(self.context_id);
|
self.runtime.remove_context(self.context_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,7 +346,7 @@ impl<'src> ScopeState {
|
|||||||
/// // Actually build the tree and allocate it
|
/// // Actually build the tree and allocate it
|
||||||
/// cx.render(lazy_tree)
|
/// cx.render(lazy_tree)
|
||||||
/// }
|
/// }
|
||||||
///```
|
/// ```
|
||||||
pub fn render(&'src self, rsx: LazyNodes<'src, '_>) -> Element<'src> {
|
pub fn render(&'src self, rsx: LazyNodes<'src, '_>) -> Element<'src> {
|
||||||
let element = rsx.call(self);
|
let element = rsx.call(self);
|
||||||
|
|
||||||
@@ -387,6 +388,45 @@ impl<'src> ScopeState {
|
|||||||
Some(element)
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a dynamic text node using [`Arguments`] and the [`ScopeState`]'s internal [`Bump`] allocator
|
/// Create a dynamic text node using [`Arguments`] and the [`ScopeState`]'s internal [`Bump`] allocator
|
||||||
pub fn text_node(&'src self, args: Arguments) -> DynamicNode<'src> {
|
pub fn text_node(&'src self, args: Arguments) -> DynamicNode<'src> {
|
||||||
DynamicNode::Text(VText {
|
DynamicNode::Text(VText {
|
||||||
|
|||||||
@@ -139,7 +139,9 @@ impl ToTokens for RenderCallBody {
|
|||||||
out_tokens.append_all(quote! {
|
out_tokens.append_all(quote! {
|
||||||
Some({
|
Some({
|
||||||
let __cx = cx;
|
let __cx = cx;
|
||||||
#body
|
let __element = { #body };
|
||||||
|
cx.link_node(&__element);
|
||||||
|
__element
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user