mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
fix render macro
This commit is contained in:
parent
a0ce5493ea
commit
0a35b5a670
3 changed files with 53 additions and 4 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::ptr::NonNull;
|
||||
use crate::ScopeState;use std::ptr::NonNull;
|
||||
|
||||
use crate::{
|
||||
innerlude::DirtyScope, nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom,
|
||||
|
@ -174,7 +174,14 @@ impl VirtualDom {
|
|||
scope.borrowed_props.borrow_mut().clear();
|
||||
|
||||
// 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| {
|
||||
let listener = unsafe { &*listener };
|
||||
if let AttributeValue::Listener(l) = &listener.value {
|
||||
|
|
|
@ -102,6 +102,7 @@ pub struct ScopeState {
|
|||
|
||||
impl Drop for ScopeState {
|
||||
fn drop(&mut self) {
|
||||
self.drop_listeners();
|
||||
self.runtime.remove_context(self.context_id);
|
||||
}
|
||||
}
|
||||
|
@ -345,7 +346,7 @@ impl<'src> ScopeState {
|
|||
/// // Actually build the tree and allocate it
|
||||
/// cx.render(lazy_tree)
|
||||
/// }
|
||||
///```
|
||||
/// ```
|
||||
pub fn render(&'src self, rsx: LazyNodes<'src, '_>) -> Element<'src> {
|
||||
let element = rsx.call(self);
|
||||
|
||||
|
@ -387,6 +388,45 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a dynamic text node using [`Arguments`] and the [`ScopeState`]'s internal [`Bump`] allocator
|
||||
pub fn text_node(&'src self, args: Arguments) -> DynamicNode<'src> {
|
||||
DynamicNode::Text(VText {
|
||||
|
|
|
@ -139,7 +139,9 @@ impl ToTokens for RenderCallBody {
|
|||
out_tokens.append_all(quote! {
|
||||
Some({
|
||||
let __cx = cx;
|
||||
#body
|
||||
let __element = { #body };
|
||||
cx.link_node(&__element);
|
||||
__element
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue