1
0
Evan Almloff 1 жил өмнө
parent
commit
3ad16ddd37

+ 0 - 3
packages/core/Cargo.toml

@@ -10,9 +10,6 @@ homepage = "https://dioxuslabs.com"
 keywords = ["dom", "ui", "gui", "react"]
 
 [dependencies]
-# Bumpalo is used as a micro heap backing each component
-bumpalo = { version = "3.6", features = ["collections", "boxed"] }
-
 # faster hashmaps
 rustc-hash = { workspace = true }
 

+ 3 - 3
packages/core/src/any_props.rs

@@ -11,9 +11,9 @@ use std::panic::AssertUnwindSafe;
 /// # Safety
 ///
 /// This should not be implemented outside this module
-pub(crate) unsafe trait AnyProps<'a> {
+pub(crate) unsafe trait AnyProps {
     fn props_ptr(&self) -> *const ();
-    fn render(&'a self, bump: &'a ScopeState) -> RenderReturn<'a>;
+    fn render<'a>(&'a self, bump: &'a ScopeState) -> RenderReturn<'a>;
     unsafe fn memoize(&self, other: &dyn AnyProps) -> bool;
 }
 
@@ -37,7 +37,7 @@ impl<'a, P> VProps<'a, P> {
     }
 }
 
-unsafe impl<'a, P> AnyProps<'a> for VProps<'a, P> {
+unsafe impl<'a, P> AnyProps for VProps<'a, P> {
     fn props_ptr(&self) -> *const () {
         &self.props as *const _ as *const ()
     }

+ 0 - 76
packages/core/src/bump_frame.rs

@@ -1,76 +0,0 @@
-use crate::nodes::RenderReturn;
-use crate::{Attribute, AttributeValue, VComponent};
-use bumpalo::Bump;
-use std::cell::RefCell;
-use std::cell::{Cell, UnsafeCell};
-
-pub(crate) struct BumpFrame {
-    pub bump: UnsafeCell<Bump>,
-    pub node: Cell<*const RenderReturn<'static>>,
-
-    // The bump allocator will not call the destructor of the objects it allocated. Attributes and props need to have there destructor called, so we keep a list of them to drop before the bump allocator is reset.
-    pub(crate) attributes_to_drop_before_reset: RefCell<Vec<*const Attribute<'static>>>,
-    pub(crate) props_to_drop_before_reset: RefCell<Vec<*const VComponent<'static>>>,
-}
-
-impl BumpFrame {
-    pub(crate) fn new(capacity: usize) -> Self {
-        let bump = Bump::with_capacity(capacity);
-        Self {
-            bump: UnsafeCell::new(bump),
-            node: Cell::new(std::ptr::null()),
-            attributes_to_drop_before_reset: Default::default(),
-            props_to_drop_before_reset: Default::default(),
-        }
-    }
-
-    /// Creates a new lifetime out of thin air
-    pub(crate) unsafe fn try_load_node<'b>(&self) -> Option<&'b RenderReturn<'b>> {
-        let node = self.node.get();
-
-        if node.is_null() {
-            return None;
-        }
-
-        unsafe { std::mem::transmute(&*node) }
-    }
-
-    pub(crate) fn bump(&self) -> &Bump {
-        unsafe { &*self.bump.get() }
-    }
-
-    pub(crate) fn add_attribute_to_drop(&self, attribute: *const Attribute<'static>) {
-        self.attributes_to_drop_before_reset
-            .borrow_mut()
-            .push(attribute);
-    }
-
-    /// Reset the bump allocator and drop all the attributes and props that were allocated in it.
-    ///
-    /// # Safety
-    /// The caller must insure that no reference to anything allocated in the bump allocator is available after this function is called.
-    pub(crate) unsafe fn reset(&self) {
-        let mut attributes = self.attributes_to_drop_before_reset.borrow_mut();
-        attributes.drain(..).for_each(|attribute| {
-            let attribute = unsafe { &*attribute };
-            if let AttributeValue::Any(l) = &attribute.value {
-                _ = l.take();
-            }
-        });
-        let mut props = self.props_to_drop_before_reset.borrow_mut();
-        props.drain(..).for_each(|prop| {
-            let prop = unsafe { &*prop };
-            _ = prop.props.borrow_mut().take();
-        });
-        unsafe {
-            let bump = &mut *self.bump.get();
-            bump.reset();
-        }
-    }
-}
-
-impl Drop for BumpFrame {
-    fn drop(&mut self) {
-        unsafe { self.reset() }
-    }
-}

+ 9 - 9
packages/core/src/create.rs

@@ -67,7 +67,7 @@ impl<'b> VirtualDom {
     /// Create a new template [`VNode`] and write it to the [`Mutations`] buffer.
     ///
     /// This method pushes the ScopeID to the internal scopestack and returns the number of nodes created.
-    pub(crate) fn create_scope(&mut self, scope: ScopeId, template: &'b VNode<'b>) -> usize {
+    pub(crate) fn create_scope(&mut self, scope: ScopeId, template: &'b VNode) -> usize {
         self.runtime.scope_stack.borrow_mut().push(scope);
         let nodes = self.create(template);
         self.runtime.scope_stack.borrow_mut().pop();
@@ -75,7 +75,7 @@ impl<'b> VirtualDom {
     }
 
     /// Create this template and write its mutations
-    pub(crate) fn create(&mut self, node: &'b VNode<'b>) -> usize {
+    pub(crate) fn create(&mut self, node: &'b VNode) -> usize {
         // check for a overriden template
         #[cfg(debug_assertions)]
         {
@@ -182,7 +182,7 @@ impl<'b> VirtualDom {
         1
     }
 
-    fn write_dynamic_root(&mut self, template: &'b VNode<'b>, idx: usize) -> usize {
+    fn write_dynamic_root(&mut self, template: &'b VNode, idx: usize) -> usize {
         use DynamicNode::*;
         match &template.dynamic_nodes[idx] {
             node @ Component { .. } | node @ Fragment(_) => {
@@ -232,7 +232,7 @@ impl<'b> VirtualDom {
     /// We want to make sure we write these nodes while on top of the root
     fn write_element_root(
         &mut self,
-        template: &'b VNode<'b>,
+        template: &'b VNode,
         root_idx: usize,
         dynamic_attrs: &mut Peekable<impl Iterator<Item = (usize, &'static [u8])>>,
         dynamic_nodes_iter: &mut Peekable<impl Iterator<Item = ((usize, usize), &'static [u8])>>,
@@ -269,7 +269,7 @@ impl<'b> VirtualDom {
         dynamic_nodes_iter: &mut Peekable<impl Iterator<Item = ((usize, usize), &'static [u8])>>,
         dynamic_nodes: &[(usize, &'static [u8])],
         root_idx: u8,
-        template: &'b VNode<'b>,
+        template: &'b VNode,
     ) {
         let (start, end) = match collect_dyn_node_range(dynamic_nodes_iter, root_idx) {
             Some((a, b)) => (a, b),
@@ -306,7 +306,7 @@ impl<'b> VirtualDom {
         attrs: &mut Peekable<impl Iterator<Item = (usize, &'static [u8])>>,
         root_idx: u8,
         root: ElementId,
-        node: &'b VNode<'b>,
+        node: &'b VNode,
     ) {
         while let Some((mut attr_id, path)) =
             attrs.next_if(|(_, p)| p.first().copied() == Some(root_idx))
@@ -327,7 +327,7 @@ impl<'b> VirtualDom {
 
     fn write_attribute(
         &mut self,
-        template: &'b VNode<'b>,
+        template: &'b VNode,
         idx: usize,
         attribute: &'b crate::Attribute<'b>,
         id: ElementId,
@@ -490,7 +490,7 @@ impl<'b> VirtualDom {
         }
     }
 
-    fn create_dynamic_text(&mut self, parent: ElementRef, text: &'b VText<'b>) -> usize {
+    fn create_dynamic_text(&mut self, parent: ElementRef, text: &'b VText) -> usize {
         // Allocate a dynamic element reference for this text node
         let new_id = self.next_element();
 
@@ -538,7 +538,7 @@ impl<'b> VirtualDom {
     pub(super) fn create_component_node(
         &mut self,
         parent: Option<ElementRef>,
-        component: &'b VComponent<'b>,
+        component: &'b VComponent,
     ) -> usize {
         use RenderReturn::*;
 

+ 34 - 59
packages/core/src/diff.rs

@@ -59,7 +59,7 @@ impl<'b> VirtualDom {
         self.runtime.scope_stack.borrow_mut().pop();
     }
 
-    fn diff_ok_to_err(&mut self, l: &'b VNode<'b>, p: &'b VPlaceholder) {
+    fn diff_ok_to_err(&mut self, l: &'b VNode, p: &'b VPlaceholder) {
         let id = self.next_element();
         p.id.set(Some(id));
         p.parent.set(l.parent.get());
@@ -82,7 +82,7 @@ impl<'b> VirtualDom {
         };
     }
 
-    fn diff_node(&mut self, left_template: &'b VNode<'b>, right_template: &'b VNode<'b>) {
+    fn diff_node(&mut self, left_template: &'b VNode, right_template: &'b VNode) {
         // If hot reloading is enabled, we need to make sure we're using the latest template
         #[cfg(debug_assertions)]
         {
@@ -198,8 +198,8 @@ impl<'b> VirtualDom {
 
     fn diff_vcomponent(
         &mut self,
-        left: &'b VComponent<'b>,
-        right: &'b VComponent<'b>,
+        left: &'b VComponent,
+        right: &'b VComponent,
         parent: Option<ElementRef>,
     ) {
         if std::ptr::eq(left, right) {
@@ -249,8 +249,8 @@ impl<'b> VirtualDom {
 
     fn replace_vcomponent(
         &mut self,
-        right: &'b VComponent<'b>,
-        left: &'b VComponent<'b>,
+        right: &'b VComponent,
+        left: &'b VComponent,
         parent: Option<ElementRef>,
     ) {
         let m = self.create_component_node(parent, right);
@@ -307,7 +307,7 @@ impl<'b> VirtualDom {
     ///     Component { ..props }
     /// }
     /// ```
-    fn light_diff_templates(&mut self, left: &'b VNode<'b>, right: &'b VNode<'b>) {
+    fn light_diff_templates(&mut self, left: &'b VNode, right: &'b VNode) {
         let parent = left.parent.take();
         match matching_components(left, right) {
             None => self.replace(left, [right], parent),
@@ -321,7 +321,7 @@ impl<'b> VirtualDom {
     ///
     /// This just moves the ID of the old node over to the new node, and then sets the text of the new node if it's
     /// different.
-    fn diff_vtext(&mut self, left: &'b VText<'b>, right: &'b VText<'b>) {
+    fn diff_vtext(&mut self, left: &'b VText, right: &'b VText) {
         let id = left.id.get().unwrap_or_else(|| self.next_element());
 
         right.id.set(Some(id));
@@ -331,12 +331,7 @@ impl<'b> VirtualDom {
         }
     }
 
-    fn diff_non_empty_fragment(
-        &mut self,
-        old: &'b [VNode<'b>],
-        new: &'b [VNode<'b>],
-        parent: ElementRef,
-    ) {
+    fn diff_non_empty_fragment(&mut self, old: &'b [VNode], new: &'b [VNode], parent: ElementRef) {
         let new_is_keyed = new[0].key.is_some();
         let old_is_keyed = old[0].key.is_some();
         debug_assert!(
@@ -363,12 +358,7 @@ impl<'b> VirtualDom {
     //     [... parent]
     //
     // the change list stack is in the same state when this function returns.
-    fn diff_non_keyed_children(
-        &mut self,
-        old: &'b [VNode<'b>],
-        new: &'b [VNode<'b>],
-        parent: ElementRef,
-    ) {
+    fn diff_non_keyed_children(&mut self, old: &'b [VNode], new: &'b [VNode], parent: ElementRef) {
         use std::cmp::Ordering;
 
         // Handled these cases in `diff_children` before calling this function.
@@ -404,15 +394,10 @@ impl<'b> VirtualDom {
     // https://github.com/infernojs/inferno/blob/36fd96/packages/inferno/src/DOM/patching.ts#L530-L739
     //
     // The stack is empty upon entry.
-    fn diff_keyed_children(
-        &mut self,
-        old: &'b [VNode<'b>],
-        new: &'b [VNode<'b>],
-        parent: ElementRef,
-    ) {
+    fn diff_keyed_children(&mut self, old: &'b [VNode], new: &'b [VNode], parent: ElementRef) {
         if cfg!(debug_assertions) {
             let mut keys = rustc_hash::FxHashSet::default();
-            let mut assert_unique_keys = |children: &'b [VNode<'b>]| {
+            let mut assert_unique_keys = |children: &'b [VNode]| {
                 keys.clear();
                 for child in children {
                     let key = child.key;
@@ -485,8 +470,8 @@ impl<'b> VirtualDom {
     /// If there is no offset, then this function returns None and the diffing is complete.
     fn diff_keyed_ends(
         &mut self,
-        old: &'b [VNode<'b>],
-        new: &'b [VNode<'b>],
+        old: &'b [VNode],
+        new: &'b [VNode],
         parent: ElementRef,
     ) -> Option<(usize, usize)> {
         let mut left_offset = 0;
@@ -542,12 +527,7 @@ impl<'b> VirtualDom {
     //
     // Upon exit from this function, it will be restored to that same self.
     #[allow(clippy::too_many_lines)]
-    fn diff_keyed_middle(
-        &mut self,
-        old: &'b [VNode<'b>],
-        new: &'b [VNode<'b>],
-        parent: ElementRef,
-    ) {
+    fn diff_keyed_middle(&mut self, old: &'b [VNode], new: &'b [VNode], parent: ElementRef) {
         /*
         1. Map the old keys into a numerical ordering based on indices.
         2. Create a map of old key to its index
@@ -729,7 +709,7 @@ impl<'b> VirtualDom {
     }
 
     /// Push all the real nodes on the stack
-    fn push_all_real_nodes(&mut self, node: &'b VNode<'b>) -> usize {
+    fn push_all_real_nodes(&mut self, node: &'b VNode) -> usize {
         node.template
             .get()
             .roots
@@ -783,7 +763,7 @@ impl<'b> VirtualDom {
 
     pub(crate) fn create_children(
         &mut self,
-        nodes: impl IntoIterator<Item = &'b VNode<'b>>,
+        nodes: impl IntoIterator<Item = &'b VNode>,
         parent: Option<ElementRef>,
     ) -> usize {
         nodes
@@ -797,8 +777,8 @@ impl<'b> VirtualDom {
 
     fn create_and_insert_before(
         &mut self,
-        new: &'b [VNode<'b>],
-        before: &'b VNode<'b>,
+        new: &'b [VNode],
+        before: &'b VNode,
         parent: ElementRef,
     ) {
         let m = self.create_children(new, Some(parent));
@@ -806,12 +786,7 @@ impl<'b> VirtualDom {
         self.mutations.push(Mutation::InsertBefore { id, m })
     }
 
-    fn create_and_insert_after(
-        &mut self,
-        new: &'b [VNode<'b>],
-        after: &'b VNode<'b>,
-        parent: ElementRef,
-    ) {
+    fn create_and_insert_after(&mut self, new: &'b [VNode], after: &'b VNode, parent: ElementRef) {
         let m = self.create_children(new, Some(parent));
         let id = self.find_last_element(after);
         self.mutations.push(Mutation::InsertAfter { id, m })
@@ -821,7 +796,7 @@ impl<'b> VirtualDom {
     fn replace_placeholder(
         &mut self,
         l: &'b VPlaceholder,
-        r: impl IntoIterator<Item = &'b VNode<'b>>,
+        r: impl IntoIterator<Item = &'b VNode>,
         parent: ElementRef,
     ) {
         let m = self.create_children(r, Some(parent));
@@ -832,8 +807,8 @@ impl<'b> VirtualDom {
 
     fn replace(
         &mut self,
-        left: &'b VNode<'b>,
-        right: impl IntoIterator<Item = &'b VNode<'b>>,
+        left: &'b VNode,
+        right: impl IntoIterator<Item = &'b VNode>,
         parent: Option<ElementRef>,
     ) {
         let m = self.create_children(right, parent);
@@ -855,7 +830,7 @@ impl<'b> VirtualDom {
         };
     }
 
-    fn node_to_placeholder(&mut self, l: &'b [VNode<'b>], r: &'b VPlaceholder, parent: ElementRef) {
+    fn node_to_placeholder(&mut self, l: &'b [VNode], r: &'b VPlaceholder, parent: ElementRef) {
         // Create the placeholder first, ensuring we get a dedicated ID for the placeholder
         let placeholder = self.next_element();
 
@@ -878,14 +853,14 @@ impl<'b> VirtualDom {
 
     /// Remove these nodes from the dom
     /// Wont generate mutations for the inner nodes
-    fn remove_nodes(&mut self, nodes: &'b [VNode<'b>]) {
+    fn remove_nodes(&mut self, nodes: &'b [VNode]) {
         nodes
             .iter()
             .rev()
             .for_each(|node| self.remove_node(node, true));
     }
 
-    fn remove_node(&mut self, node: &'b VNode<'b>, gen_muts: bool) {
+    fn remove_node(&mut self, node: &'b VNode, gen_muts: bool) {
         // Clean up any attributes that have claimed a static node as dynamic for mount/unmounta
         // Will not generate mutations!
         self.reclaim_attributes(node);
@@ -903,7 +878,7 @@ impl<'b> VirtualDom {
         self.reclaim_vnode_id(node);
     }
 
-    fn reclaim_vnode_id(&mut self, node: &'b VNode<'b>) {
+    fn reclaim_vnode_id(&mut self, node: &'b VNode) {
         // Clean up the vnode id
         if let Some(id) = node.stable_id() {
             self.element_refs.remove(id.0);
@@ -1025,7 +1000,7 @@ impl<'b> VirtualDom {
         self.drop_scope(scope, false);
     }
 
-    fn find_first_element(&self, node: &'b VNode<'b>) -> ElementId {
+    fn find_first_element(&self, node: &'b VNode) -> ElementId {
         match node.dynamic_root(0) {
             None => node.root_ids.borrow()[0],
             Some(Text(t)) => t.id.get().unwrap(),
@@ -1046,7 +1021,7 @@ impl<'b> VirtualDom {
         }
     }
 
-    fn find_last_element(&self, node: &'b VNode<'b>) -> ElementId {
+    fn find_last_element(&self, node: &'b VNode) -> ElementId {
         match node.dynamic_root(node.template.get().roots.len() - 1) {
             None => *node.root_ids.borrow().last().unwrap(),
             Some(Text(t)) => t.id.get().unwrap(),
@@ -1067,7 +1042,7 @@ impl<'b> VirtualDom {
         }
     }
 
-    pub(crate) fn assign_boundary_ref(&mut self, parent: Option<ElementRef>, child: &'b VNode<'b>) {
+    pub(crate) fn assign_boundary_ref(&mut self, parent: Option<ElementRef>, child: &'b VNode) {
         if let Some(parent) = parent {
             // assign the parent of the child
             child.parent.set(Some(parent));
@@ -1080,7 +1055,7 @@ impl<'b> VirtualDom {
 /// We need to check for the obvious case, and the non-obvious case where the template as cloned
 ///
 /// We use the pointer of the dynamic_node list in this case
-fn templates_are_the_same<'b>(left_template: &'b VNode<'b>, right_template: &'b VNode<'b>) -> bool {
+fn templates_are_the_same<'b>(left_template: &'b VNode, right_template: &'b VNode) -> bool {
     std::ptr::eq(left_template, right_template)
 }
 
@@ -1092,9 +1067,9 @@ fn templates_are_different(left_template: &VNode, right_template: &VNode) -> boo
 }
 
 fn matching_components<'a>(
-    left: &'a VNode<'a>,
-    right: &'a VNode<'a>,
-) -> Option<Vec<(&'a VComponent<'a>, &'a VComponent<'a>)>> {
+    left: &'a VNode,
+    right: &'a VNode,
+) -> Option<Vec<(&'a VComponent, &'a VComponent)>> {
     let left_template = left.template.get();
     let right_template = right.template.get();
     if left_template.roots.len() != right_template.roots.len() {

+ 12 - 18
packages/core/src/error_boundary.rs

@@ -262,7 +262,7 @@ impl<T> Throw for Option<T> {
     }
 }
 
-pub struct ErrorHandler<'a>(Box<dyn Fn(CapturedError) -> LazyNodes<'a, 'a> + 'a>);
+pub struct ErrorHandler(Box<dyn Fn(CapturedError) -> LazyNodes<'a, 'a>>);
 impl<'a, F: Fn(CapturedError) -> LazyNodes<'a, 'a> + 'a> From<F> for ErrorHandler<'a> {
     fn from(value: F) -> Self {
         Self(Box::new(value))
@@ -290,7 +290,7 @@ fn default_handler<'a>(error: CapturedError) -> LazyNodes<'a, 'a> {
             stable_id: Default::default(),
             key: None,
             template: std::cell::Cell::new(TEMPLATE),
-            root_ids: bumpalo::collections::Vec::with_capacity_in(1usize, __cx.bump()).into(),
+            root_ids: Vec::with_capacity(1usize).into(),
             dynamic_nodes: __cx
                 .bump()
                 .alloc([__cx.text_node(format_args!("{0}", error))]),
@@ -298,45 +298,39 @@ fn default_handler<'a>(error: CapturedError) -> LazyNodes<'a, 'a> {
         }
     })
 }
-pub struct ErrorBoundaryProps<'a> {
-    children: Element<'a>,
-    handle_error: ErrorHandler<'a>,
+pub struct ErrorBoundaryProps {
+    children: Element,
+    handle_error: ErrorHandler,
 }
-impl<'a> ErrorBoundaryProps<'a> {
+impl ErrorBoundaryProps {
     /**
     Create a builder for building `ErrorBoundaryProps`.
     On the builder, call `.children(...)`(optional), `.handle_error(...)`(optional) to set the values of the fields.
     Finally, call `.build()` to create the instance of `ErrorBoundaryProps`.
                         */
     #[allow(dead_code)]
-    pub fn builder() -> ErrorBoundaryPropsBuilder<'a, ((), ())> {
-        ErrorBoundaryPropsBuilder {
-            fields: ((), ()),
-            _phantom: ::core::default::Default::default(),
-        }
+    pub fn builder() -> ErrorBoundaryPropsBuilder<((), ())> {
+        ErrorBoundaryPropsBuilder { fields: ((), ()) }
     }
 }
 #[must_use]
 #[doc(hidden)]
 #[allow(dead_code, non_camel_case_types, non_snake_case)]
-pub struct ErrorBoundaryPropsBuilder<'a, TypedBuilderFields> {
+pub struct ErrorBoundaryPropsBuilder<TypedBuilderFields> {
     fields: TypedBuilderFields,
-    _phantom: ::core::marker::PhantomData<&'a ()>,
 }
-impl<'a, TypedBuilderFields> Clone for ErrorBoundaryPropsBuilder<'a, TypedBuilderFields>
+impl<TypedBuilderFields> Clone for ErrorBoundaryPropsBuilder<TypedBuilderFields>
 where
     TypedBuilderFields: Clone,
 {
     fn clone(&self) -> Self {
         Self {
             fields: self.fields.clone(),
-            _phantom: ::core::default::Default::default(),
         }
     }
 }
-impl<'a> Properties for ErrorBoundaryProps<'a> {
-    type Builder = ErrorBoundaryPropsBuilder<'a, ((), ())>;
-    const IS_STATIC: bool = false;
+impl Properties for ErrorBoundaryProps {
+    type Builder = ErrorBoundaryPropsBuilder<((), ())>;
     fn builder() -> Self::Builder {
         ErrorBoundaryProps::builder()
     }

+ 1 - 1
packages/core/src/events.rs

@@ -147,7 +147,7 @@ impl<T> Default for EventHandler<'_, T> {
     }
 }
 
-type ExternalListenerCallback<'bump, T> = bumpalo::boxed::Box<'bump, dyn FnMut(T) + 'bump>;
+type ExternalListenerCallback<'bump, T> = Box<dyn FnMut(T)>;
 
 impl<T> EventHandler<'_, T> {
     /// Call this event handler with the appropriate event type

+ 3 - 3
packages/core/src/fragment.rs

@@ -26,7 +26,7 @@ use crate::innerlude::*;
 ///
 /// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
 #[allow(non_upper_case_globals, non_snake_case)]
-pub fn Fragment<'a>(cx: Scope<'a, FragmentProps<'a>>) -> Element {
+pub fn Fragment<'a>(cx: Scope<'a, FragmentProps>) -> Element {
     let children = cx.props.0.as_ref()?;
     Some(VNode {
         key: children.key,
@@ -92,8 +92,8 @@ impl<const A: bool> FragmentBuilder<A> {
 ///     })
 /// }
 /// ```
-impl<'a> Properties for FragmentProps<'a> {
-    type Builder = FragmentBuilder<'a, false>;
+impl<'a> Properties for FragmentProps {
+    type Builder = FragmentBuilder<false>;
     fn builder() -> Self::Builder {
         FragmentBuilder(None)
     }

+ 0 - 101
packages/core/src/lazynodes.rs

@@ -1,101 +0,0 @@
-//! Support for storing lazy-nodes on the stack
-//!
-//! This module provides support for a type called `LazyNodes` which is a micro-heap located on the stack to make calls
-//! to `rsx!` more efficient.
-//!
-//! To support returning rsx! from branches in match statements, we need to use dynamic dispatch on [`ScopeState`] closures.
-//!
-//! This can be done either through boxing directly, or by using dynamic-sized-types and a custom allocator. In our case,
-//! we build a tiny alloactor in the stack and allocate the closure into that.
-//!
-//! The logic for this was borrowed from <https://docs.rs/stack_dst/0.6.1/stack_dst/>. Unfortunately, this crate does not
-//! support non-static closures, so we've implemented the core logic of `ValueA` in this module.
-
-#[allow(unused_imports)]
-use smallbox::{smallbox, space::S16, SmallBox};
-
-use crate::{innerlude::VNode, ScopeState};
-
-/// A concrete type provider for closures that build [`VNode`] structures.
-///
-/// This struct wraps lazy structs that build [`VNode`] trees. Normally, we cannot perform a blanket implementation over
-/// closures, but if we wrap the closure in a concrete type, we can use it for different branches in matching.
-///
-///
-/// ```rust, ignore
-/// LazyNodes::new(|f| {
-///        static TEMPLATE: dioxus::core::Template = dioxus::core::Template {
-///         name: "main.rs:5:5:20", // Source location of the template for hot reloading
-///         roots: &[
-///             dioxus::core::TemplateNode::Element {
-///                 tag: dioxus_elements::div::TAG_NAME,
-///                 namespace: dioxus_elements::div::NAME_SPACE,
-///                 attrs: &[],
-///                 children: &[],
-///             },
-///         ],
-///         node_paths: &[],
-///         attr_paths: &[],
-///     };
-///     dioxus::core::VNode {
-///         parent: None,
-///         key: None,
-///         template: std::cell::Cell::new(TEMPLATE),
-///         root_ids: dioxus::core::exports::bumpalo::collections::Vec::with_capacity_in(
-///                 1usize,
-///                 f.bump(),
-///             )
-///             .into(),
-///         dynamic_nodes: f.bump().alloc([]),
-///         dynamic_attrs: f.bump().alloc([]),
-///     })
-/// }
-/// ```
-///
-/// Find more information about how to construct [`VNode`] at <https://dioxuslabs.com/learn/0.4/contributing/walkthrough_readme#the-rsx-macro>
-
-pub struct LazyNodes<'a, 'b> {
-    #[cfg(not(miri))]
-    inner: SmallBox<dyn FnMut(&'a ScopeState) -> VNode<'a> + 'b, S16>,
-
-    #[cfg(miri)]
-    inner: Box<dyn FnMut(&'a ScopeState) -> VNode<'a> + 'b>,
-}
-
-impl<'a, 'b> LazyNodes<'a, 'b> {
-    /// Create a new [`LazyNodes`] closure, optimistically placing it onto the stack.
-    ///
-    /// If the closure cannot fit into the stack allocation (16 bytes), then it
-    /// is placed on the heap. Most closures will fit into the stack, and is
-    /// the most optimal way to use the creation function.
-    pub fn new(val: impl FnOnce(&'a ScopeState) -> VNode<'a> + 'b) -> Self {
-        // there's no way to call FnOnce without a box, so we need to store it in a slot and use static dispatch
-        let mut slot = Some(val);
-
-        Self {
-            #[cfg(not(miri))]
-            inner: smallbox!(move |f| {
-                let val = slot.take().expect("cannot call LazyNodes twice");
-                val(f)
-            }),
-
-            #[cfg(miri)]
-            inner: Box::new(move |f| {
-                let val = slot.take().expect("cannot call LazyNodes twice");
-                val(f)
-            }),
-        }
-    }
-
-    /// Call the closure with the given factory to produce real [`VNode`].
-    ///
-    /// ```rust, ignore
-    /// let f = LazyNodes::new(/* Closure for creating VNodes */);
-    ///
-    /// let node = f.call(cac);
-    /// ```
-    #[must_use]
-    pub fn call(mut self, f: &'a ScopeState) -> VNode<'a> {
-        (self.inner)(f)
-    }
-}

+ 1 - 8
packages/core/src/lib.rs

@@ -5,7 +5,6 @@
 
 mod any_props;
 mod arena;
-mod bump_frame;
 mod create;
 mod diff;
 mod dirty_scope;
@@ -43,7 +42,7 @@ pub(crate) mod innerlude {
     /// An [`Element`] is a possibly-none [`VNode`] created by calling `render` on [`Scope`] or [`ScopeState`].
     ///
     /// An Errored [`Element`] will propagate the error to the nearest error boundary.
-    pub type Element<'a> = Option<VNode<'a>>;
+    pub type Element = Option<VNode>;
 
     /// A [`Component`] is a function that takes a [`Scope`] and returns an [`Element`].
     ///
@@ -97,9 +96,3 @@ pub mod prelude {
         VNode, VirtualDom,
     };
 }
-
-pub mod exports {
-    //! Important dependencies that are used by the rest of the library
-    //! Feel free to just add the dependencies in your own Crates.toml
-    pub use bumpalo;
-}

+ 72 - 88
packages/core/src/nodes.rs

@@ -19,9 +19,9 @@ pub type TemplateId = &'static str;
 ///
 /// Dioxus will do its best to immediately resolve any async components into a regular Element, but as an implementor
 /// you might need to handle the case where there's no node immediately ready.
-pub enum RenderReturn<'a> {
+pub enum RenderReturn {
     /// A currently-available element
-    Ready(VNode<'a>),
+    Ready(VNode),
 
     /// The component aborted rendering early. It might've thrown an error.
     ///
@@ -30,7 +30,7 @@ pub enum RenderReturn<'a> {
     Aborted(VPlaceholder),
 }
 
-impl<'a> Default for RenderReturn<'a> {
+impl Default for RenderReturn {
     fn default() -> Self {
         RenderReturn::Aborted(VPlaceholder::default())
     }
@@ -88,11 +88,11 @@ impl VNode {
 
     /// Create a new VNode
     pub fn new(
-        key: Option<&'a str>,
+        key: Option<String>,
         template: Template<'static>,
-        root_ids: bumpalo::collections::Vec<'a, ElementId>,
-        dynamic_nodes: &'a [DynamicNode<'a>],
-        dynamic_attrs: &'a [Attribute<'a>],
+        root_ids: Vec<ElementId>,
+        dynamic_nodes: &'a [DynamicNode],
+        dynamic_attrs: &'a [Attribute],
     ) -> Self {
         Self {
             key,
@@ -113,7 +113,7 @@ impl VNode {
     /// Load a dynamic root at the given index
     ///
     /// Returns [`None`] if the root is actually a static node (Element/Text)
-    pub fn dynamic_root(&self, idx: usize) -> Option<&'a DynamicNode<'a>> {
+    pub fn dynamic_root(&self, idx: usize) -> Option<&'a DynamicNode> {
         match &self.template.get().roots[idx] {
             TemplateNode::Element { .. } | TemplateNode::Text { text: _ } => None,
             TemplateNode::Dynamic { id } | TemplateNode::DynamicText { id } => {
@@ -147,7 +147,7 @@ pub struct Template<'a> {
     ///
     /// Unlike react, calls to `rsx!` can have multiple roots. This list supports that paradigm.
     #[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
-    pub roots: &'a [TemplateNode<'a>],
+    pub roots: &'a [TemplateNode],
 
     /// The paths of each node relative to the root of the template.
     ///
@@ -242,7 +242,7 @@ impl<'a> Template<'a> {
     derive(serde::Serialize, serde::Deserialize),
     serde(tag = "type")
 )]
-pub enum TemplateNode<'a> {
+pub enum TemplateNode {
     /// An statically known element in the dom.
     ///
     /// In HTML this would be something like `<div id="123"> </div>`
@@ -250,7 +250,7 @@ pub enum TemplateNode<'a> {
         /// The name of the element
         ///
         /// IE for a div, it would be the string "div"
-        tag: &'a str,
+        tag: &'static str,
 
         /// The namespace of the element
         ///
@@ -260,23 +260,23 @@ pub enum TemplateNode<'a> {
             feature = "serialize",
             serde(deserialize_with = "deserialize_option_leaky")
         )]
-        namespace: Option<&'a str>,
+        namespace: Option<&'static str>,
 
         /// A list of possibly dynamic attribues for this element
         ///
         /// An attribute on a DOM node, such as `id="my-thing"` or `href="https://example.com"`.
         #[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
-        attrs: &'a [TemplateAttribute<'a>],
+        attrs: &'static [TemplateAttribute],
 
         /// A list of template nodes that define another set of template nodes
         #[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
-        children: &'a [TemplateNode<'a>],
+        children: &'static [TemplateNode],
     },
 
     /// This template node is just a piece of static text
     Text {
         /// The actual text
-        text: &'a str,
+        text: &'static str,
     },
 
     /// This template node is unknown, and needs to be created at runtime.
@@ -298,7 +298,7 @@ pub enum TemplateNode<'a> {
 ///
 /// This node's index in the DynamicNode list on VNode should match its repsective `Dynamic` index
 #[derive(Debug)]
-pub enum DynamicNode<'a> {
+pub enum DynamicNode {
     /// A component node
     ///
     /// Most of the time, Dioxus will actually know which component this is as compile time, but the props and
@@ -306,10 +306,10 @@ pub enum DynamicNode<'a> {
     ///
     /// The actual VComponent can be dynamic between two VNodes, though, allowing implementations to swap
     /// the render function at runtime
-    Component(VComponent<'a>),
+    Component(VComponent),
 
     /// A text node
-    Text(VText<'a>),
+    Text(VText),
 
     /// A placeholder
     ///
@@ -322,27 +322,20 @@ pub enum DynamicNode<'a> {
     ///
     /// Note that this is not a list of dynamic nodes. These must be VNodes and created through conditional rendering
     /// or iterators.
-    Fragment(&'a [VNode<'a>]),
+    Fragment(&'static [VNode]),
 }
 
-impl Default for DynamicNode<'_> {
+impl Default for DynamicNode {
     fn default() -> Self {
         Self::Placeholder(Default::default())
     }
 }
 
 /// An instance of a child component
-pub struct VComponent<'a> {
+pub struct VComponent {
     /// The name of this component
     pub name: &'static str,
 
-    /// Are the props valid for the 'static lifetime?
-    ///
-    /// Internally, this is used as a guarantee. Externally, this might be incorrect, so don't count on it.
-    ///
-    /// This flag is assumed by the [`crate::Properties`] trait which is unsafe to implement
-    pub(crate) static_props: bool,
-
     /// The assigned Scope for this component
     pub(crate) scope: Cell<Option<ScopeId>>,
 
@@ -351,17 +344,17 @@ pub struct VComponent<'a> {
     /// It is possible that components get folded at compile time, so these shouldn't be really used as a key
     pub(crate) render_fn: *const (),
 
-    pub(crate) props: RefCell<Option<Box<dyn AnyProps<'a> + 'a>>>,
+    pub(crate) props: RefCell<Option<Box<dyn AnyProps>>>,
 }
 
-impl<'a> VComponent<'a> {
+impl<'a> VComponent {
     /// Get the scope that this component is mounted to
     pub fn mounted_scope(&self) -> Option<ScopeId> {
         self.scope.get()
     }
 }
 
-impl<'a> std::fmt::Debug for VComponent<'a> {
+impl<'a> std::fmt::Debug for VComponent {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("VComponent")
             .field("name", &self.name)
@@ -373,17 +366,17 @@ impl<'a> std::fmt::Debug for VComponent<'a> {
 
 /// An instance of some text, mounted to the DOM
 #[derive(Debug)]
-pub struct VText<'a> {
+pub struct VText {
     /// The actual text itself
-    pub value: &'a str,
+    pub value: String,
 
     /// The ID of this node in the real DOM
     pub(crate) id: Cell<Option<ElementId>>,
 }
 
-impl<'a> VText<'a> {
+impl<'a> VText {
     /// Create a new VText
-    pub fn new(value: &'a str) -> Self {
+    pub fn new(value: String) -> Self {
         Self {
             value,
             id: Default::default(),
@@ -419,21 +412,21 @@ impl VPlaceholder {
     derive(serde::Serialize, serde::Deserialize),
     serde(tag = "type")
 )]
-pub enum TemplateAttribute<'a> {
+pub enum TemplateAttribute {
     /// This attribute is entirely known at compile time, enabling
     Static {
         /// The name of this attribute.
         ///
         /// For example, the `href` attribute in `href="https://example.com"`, would have the name "href"
-        name: &'a str,
+        name: &'static str,
 
         /// The value of this attribute, known at compile time
         ///
         /// Currently this only accepts &str, so values, even if they're known at compile time, are not known
-        value: &'a str,
+        value: &'static str,
 
         /// The namespace of this attribute. Does not exist in the HTML spec
-        namespace: Option<&'a str>,
+        namespace: Option<&'static str>,
     },
 
     /// The attribute in this position is actually determined dynamically at runtime
@@ -447,12 +440,12 @@ pub enum TemplateAttribute<'a> {
 
 /// An attribute on a DOM node, such as `id="my-thing"` or `href="https://example.com"`
 #[derive(Debug)]
-pub struct Attribute<'a> {
+pub struct Attribute {
     /// The name of the attribute.
-    pub name: &'a str,
+    pub name: &'static str,
 
     /// The value of the attribute
-    pub value: AttributeValue<'a>,
+    pub value: AttributeValue,
 
     /// The namespace of the attribute.
     ///
@@ -466,11 +459,11 @@ pub struct Attribute<'a> {
     pub(crate) mounted_element: Cell<ElementId>,
 }
 
-impl<'a> Attribute<'a> {
+impl Attribute {
     /// Create a new attribute
     pub fn new(
-        name: &'a str,
-        value: AttributeValue<'a>,
+        name: &'static str,
+        value: AttributeValue,
         namespace: Option<&'static str>,
         volatile: bool,
     ) -> Self {
@@ -493,9 +486,9 @@ impl<'a> Attribute<'a> {
 ///
 /// These are built-in to be faster during the diffing process. To use a custom value, use the [`AttributeValue::Any`]
 /// variant.
-pub enum AttributeValue<'a> {
+pub enum AttributeValue {
     /// Text attribute
-    Text(&'a str),
+    Text(String),
 
     /// A float
     Float(f64),
@@ -507,16 +500,16 @@ pub enum AttributeValue<'a> {
     Bool(bool),
 
     /// A listener, like "onclick"
-    Listener(RefCell<Option<ListenerCb<'a>>>),
+    Listener(RefCell<Option<ListenerCb>>),
 
     /// An arbitrary value that implements PartialEq and is static
-    Any(RefCell<Option<BumpBox<'a, dyn AnyValue>>>),
+    Any(RefCell<Option<Box<dyn AnyValue>>>),
 
     /// A "none" value, resulting in the removal of an attribute from the dom
     None,
 }
 
-pub type ListenerCb<'a> = BumpBox<'a, dyn FnMut(Event<dyn Any>) + 'a>;
+pub type ListenerCb = Box<dyn FnMut(Event<dyn Any>)>;
 
 /// Any of the built-in values that the Dioxus VirtualDom supports as dynamic attributes on elements that are borrowed
 ///
@@ -550,8 +543,8 @@ pub enum BorrowedAttributeValue<'a> {
     None,
 }
 
-impl<'a> From<&'a AttributeValue<'a>> for BorrowedAttributeValue<'a> {
-    fn from(value: &'a AttributeValue<'a>) -> Self {
+impl<'a> From<&'a AttributeValue> for BorrowedAttributeValue<'a> {
+    fn from(value: &'a AttributeValue) -> Self {
         match value {
             AttributeValue::Text(value) => BorrowedAttributeValue::Text(value),
             AttributeValue::Float(value) => BorrowedAttributeValue::Float(*value),
@@ -613,7 +606,7 @@ where
     panic!("Any cannot be deserialized")
 }
 
-impl<'a> std::fmt::Debug for AttributeValue<'a> {
+impl std::fmt::Debug for AttributeValue {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
             Self::Text(arg0) => f.debug_tuple("Text").field(arg0).finish(),
@@ -627,7 +620,7 @@ impl<'a> std::fmt::Debug for AttributeValue<'a> {
     }
 }
 
-impl<'a> PartialEq for AttributeValue<'a> {
+impl PartialEq for AttributeValue {
     fn eq(&self, other: &Self) -> bool {
         match (self, other) {
             (Self::Text(l0), Self::Text(r0)) => l0 == r0,
@@ -668,42 +661,33 @@ impl<T: Any + PartialEq + 'static> AnyValue for T {
     }
 }
 
-impl<'a> RenderReturn<'a> {
-    pub(crate) unsafe fn extend_lifetime_ref<'c>(&self) -> &'c RenderReturn<'c> {
-        unsafe { std::mem::transmute(self) }
-    }
-    pub(crate) unsafe fn extend_lifetime<'c>(self) -> RenderReturn<'c> {
-        unsafe { std::mem::transmute(self) }
-    }
-}
-
 /// A trait that allows various items to be converted into a dynamic node for the rsx macro
 pub trait IntoDynNode<'a, A = ()> {
     /// Consume this item along with a scopestate and produce a DynamicNode
     ///
     /// You can use the bump alloactor of the scopestate to creat the dynamic node
-    fn into_dyn_node(self, cx: &'a ScopeState) -> DynamicNode<'a>;
+    fn into_dyn_node(self, cx: &'a ScopeState) -> DynamicNode;
 }
 
 impl<'a> IntoDynNode<'a> for () {
-    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode {
         DynamicNode::default()
     }
 }
-impl<'a> IntoDynNode<'a> for VNode<'a> {
-    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+impl<'a> IntoDynNode<'a> for VNode {
+    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode {
         DynamicNode::Fragment(_cx.bump().alloc([self]))
     }
 }
 
-impl<'a> IntoDynNode<'a> for DynamicNode<'a> {
-    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+impl<'a> IntoDynNode<'a> for DynamicNode {
+    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode {
         self
     }
 }
 
 impl<'a, T: IntoDynNode<'a>> IntoDynNode<'a> for Option<T> {
-    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode {
         match self {
             Some(val) => val.into_dyn_node(_cx),
             None => DynamicNode::default(),
@@ -711,8 +695,8 @@ impl<'a, T: IntoDynNode<'a>> IntoDynNode<'a> for Option<T> {
     }
 }
 
-impl<'a> IntoDynNode<'a> for &Element<'a> {
-    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+impl<'a> IntoDynNode<'a> for &Element {
+    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode {
         match self.as_ref() {
             Some(val) => val.clone().into_dyn_node(_cx),
             _ => DynamicNode::default(),
@@ -721,13 +705,13 @@ impl<'a> IntoDynNode<'a> for &Element<'a> {
 }
 
 impl<'a, 'b> IntoDynNode<'a> for LazyNodes<'a, 'b> {
-    fn into_dyn_node(self, cx: &'a ScopeState) -> DynamicNode<'a> {
+    fn into_dyn_node(self, cx: &'a ScopeState) -> DynamicNode {
         DynamicNode::Fragment(cx.bump().alloc([cx.render(self).unwrap()]))
     }
 }
 
 impl<'a, 'b> IntoDynNode<'b> for &'a str {
-    fn into_dyn_node(self, cx: &'b ScopeState) -> DynamicNode<'b> {
+    fn into_dyn_node(self, cx: &'b ScopeState) -> DynamicNode {
         DynamicNode::Text(VText {
             value: cx.bump().alloc_str(self),
             id: Default::default(),
@@ -745,13 +729,13 @@ impl IntoDynNode<'_> for String {
 }
 
 impl<'b> IntoDynNode<'b> for Arguments<'_> {
-    fn into_dyn_node(self, cx: &'b ScopeState) -> DynamicNode<'b> {
+    fn into_dyn_node(self, cx: &'b ScopeState) -> DynamicNode {
         cx.text_node(self)
     }
 }
 
-impl<'a> IntoDynNode<'a> for &'a VNode<'a> {
-    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
+impl<'a> IntoDynNode<'a> for &'a VNode {
+    fn into_dyn_node(self, _cx: &'a ScopeState) -> DynamicNode {
         DynamicNode::Fragment(_cx.bump().alloc([VNode {
             parent: self.parent.clone(),
             stable_id: self.stable_id.clone(),
@@ -764,24 +748,24 @@ impl<'a> IntoDynNode<'a> for &'a VNode<'a> {
     }
 }
 
-pub trait IntoVNode<'a> {
-    fn into_vnode(self, _cx: &'a ScopeState) -> VNode<'a>;
+pub trait IntoVNode {
+    fn into_vnode(self) -> VNode;
 }
-impl<'a> IntoVNode<'a> for VNode<'a> {
-    fn into_vnode(self, _cx: &'a ScopeState) -> VNode<'a> {
+impl<'a> IntoVNode for VNode {
+    fn into_vnode(self) -> VNode {
         self
     }
 }
-impl<'a> IntoVNode<'a> for Element<'a> {
-    fn into_vnode(self, cx: &'a ScopeState) -> VNode<'a> {
+impl<'a> IntoVNode for Element {
+    fn into_vnode(self) -> VNode {
         match self {
             Some(val) => val.into_vnode(cx),
-            _ => VNode::empty(cx).unwrap(),
+            _ => VNode::empty().unwrap(),
         }
     }
 }
-impl<'a, 'b> IntoVNode<'a> for LazyNodes<'a, 'b> {
-    fn into_vnode(self, cx: &'a ScopeState) -> VNode<'a> {
+impl<'a, 'b> IntoVNode for LazyNodes<'a, 'b> {
+    fn into_vnode(self) -> VNode {
         cx.render(self).unwrap()
     }
 }
@@ -791,9 +775,9 @@ pub struct FromNodeIterator;
 impl<'a, T, I> IntoDynNode<'a, FromNodeIterator> for T
 where
     T: Iterator<Item = I>,
-    I: IntoVNode<'a>,
+    I: IntoVNode,
 {
-    fn into_dyn_node(self, cx: &'a ScopeState) -> DynamicNode<'a> {
+    fn into_dyn_node(self, cx: &'a ScopeState) -> DynamicNode {
         let mut nodes = bumpalo::collections::Vec::new_in(cx.bump());
 
         nodes.extend(self.into_iter().map(|node| node.into_vnode(cx)));

+ 2 - 2
packages/core/src/properties.rs

@@ -32,7 +32,7 @@ use crate::innerlude::*;
 ///     data: &'a str
 /// }
 /// ```
-pub trait Properties: Sized + 'static {
+pub trait Properties: Clone + Sized + 'static {
     /// The type of the builder for this component.
     /// Used to create "in-progress" versions of the props.
     type Builder;
@@ -66,7 +66,7 @@ impl EmptyBuilder {
 
 /// This utility function launches the builder method so rsx! and html! macros can use the typed-builder pattern
 /// to initialize a component's props.
-pub fn fc_to_builder<'a, T: Properties + 'a>(_: fn(Scope<'a, T>) -> Element<'a>) -> T::Builder {
+pub fn fc_to_builder<'a, T: Properties + 'a>(_: fn(Scope<'a, T>) -> Element) -> T::Builder {
     T::builder()
 }
 

+ 1 - 5
packages/core/src/scope_arena.rs

@@ -1,6 +1,5 @@
 use crate::{
     any_props::AnyProps,
-    bump_frame::BumpFrame,
     innerlude::DirtyScope,
     nodes::RenderReturn,
     scope_context::ScopeContext,
@@ -11,7 +10,7 @@ use crate::{
 impl VirtualDom {
     pub(super) fn new_scope(
         &mut self,
-        props: Box<dyn AnyProps<'static>>,
+        props: Box<dyn AnyProps>,
         name: &'static str,
     ) -> &ScopeState {
         let parent_id = self.runtime.current_scope_id();
@@ -27,9 +26,6 @@ impl VirtualDom {
 
             props: Some(props),
 
-            node_arena_1: BumpFrame::new(0),
-            node_arena_2: BumpFrame::new(0),
-
             render_cnt: Default::default(),
             hooks: Default::default(),
             hook_idx: Default::default(),

+ 1 - 1
packages/core/src/scope_context.rs

@@ -301,7 +301,7 @@ pub fn provide_root_context<T: 'static + Clone>(value: T) -> Option<T> {
 }
 
 /// Suspends the current component
-pub fn suspend() -> Option<Element<'static>> {
+pub fn suspend() -> Option<Element> {
     with_current_scope(|cx| {
         cx.suspend();
     });

+ 20 - 75
packages/core/src/scopes.rs

@@ -1,16 +1,13 @@
 use crate::{
     any_props::AnyProps,
     any_props::VProps,
-    bump_frame::BumpFrame,
     innerlude::ErrorBoundary,
     innerlude::{DynamicNode, EventHandler, VComponent, VNodeId, VText},
-    lazynodes::LazyNodes,
     nodes::{IntoAttributeValue, IntoDynNode, RenderReturn},
     runtime::Runtime,
     scope_context::ScopeContext,
     AnyValue, Attribute, AttributeValue, Element, Event, Properties, TaskId,
 };
-use bumpalo::{boxed::Box as BumpBox, Bump};
 use std::{
     any::Any,
     cell::{Cell, Ref, RefCell, UnsafeCell},
@@ -90,11 +87,11 @@ pub struct ScopeState {
     pub(crate) hooks: RefCell<Vec<Box<UnsafeCell<dyn Any>>>>,
     pub(crate) hook_idx: Cell<usize>,
 
-    pub(crate) borrowed_props: RefCell<Vec<*const VComponent<'static>>>,
+    pub(crate) borrowed_props: RefCell<Vec<*const VComponent>>,
     pub(crate) element_refs_to_drop: RefCell<Vec<VNodeId>>,
-    pub(crate) attributes_to_drop_before_render: RefCell<Vec<*const Attribute<'static>>>,
+    pub(crate) attributes_to_drop_before_render: RefCell<Vec<*const Attribute>>,
 
-    pub(crate) props: Option<Box<dyn AnyProps<'static>>>,
+    pub(crate) props: Option<Box<dyn AnyProps>>,
 }
 
 impl Drop for ScopeState {
@@ -108,22 +105,6 @@ impl<'src> ScopeState {
         self.runtime.get_context(self.context_id).unwrap()
     }
 
-    pub(crate) fn current_frame(&self) -> &BumpFrame {
-        match self.render_cnt.get() % 2 {
-            0 => &self.node_arena_1,
-            1 => &self.node_arena_2,
-            _ => unreachable!(),
-        }
-    }
-
-    pub(crate) fn previous_frame(&self) -> &BumpFrame {
-        match self.render_cnt.get() % 2 {
-            1 => &self.node_arena_1,
-            0 => &self.node_arena_2,
-            _ => unreachable!(),
-        }
-    }
-
     /// Get the name of this component
     pub fn name(&self) -> &str {
         self.context().name
@@ -136,17 +117,6 @@ impl<'src> ScopeState {
         self.render_cnt.get()
     }
 
-    /// Get a handle to the currently active bump arena for this Scope
-    ///
-    /// This is a bump memory allocator. Be careful using this directly since the contents will be wiped on the next render.
-    /// It's easy to leak memory here since the drop implementation will not be called for any objects allocated in this arena.
-    ///
-    /// If you need to allocate items that need to be dropped, use bumpalo's box.
-    pub fn bump(&self) -> &Bump {
-        // note that this is actually the previous frame since we use that as scratch space while the component is rendering
-        self.previous_frame().bump()
-    }
-
     /// Get a handle to the currently active head node arena for this Scope
     ///
     /// This is useful for traversing the tree outside of the VirtualDom, such as in a custom renderer or in SSR.
@@ -343,7 +313,7 @@ impl<'src> ScopeState {
     ///     cx.render(lazy_tree)
     /// }
     ///```
-    pub fn render(&'src self, rsx: LazyNodes<'src, '_>) -> Element<'src> {
+    pub fn render(&'src self, rsx: LazyNodes<'src, '_>) -> Element {
         let element = rsx.call(self);
 
         let mut listeners = self.attributes_to_drop_before_render.borrow_mut();
@@ -383,25 +353,13 @@ impl<'src> ScopeState {
     }
 
     /// 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 {
         DynamicNode::Text(VText {
             value: self.raw_text(args),
             id: Default::default(),
         })
     }
 
-    /// Allocate some text inside the [`ScopeState`] from [`Arguments`]
-    ///
-    /// Uses the currently active [`Bump`] allocator
-    pub fn raw_text(&'src self, args: Arguments) -> &'src str {
-        args.as_str().unwrap_or_else(|| {
-            use bumpalo::core_alloc::fmt::Write;
-            let mut str_buf = bumpalo::collections::String::new_in(self.bump());
-            str_buf.write_fmt(args).unwrap();
-            str_buf.into_bump_str()
-        })
-    }
-
     /// Convert any item that implements [`IntoDynNode`] into a [`DynamicNode`] using the internal [`Bump`] allocator
     pub fn make_node<'c, I>(&'src self, into: impl IntoDynNode<'src, I> + 'c) -> DynamicNode {
         into.into_dyn_node(self)
@@ -417,7 +375,7 @@ impl<'src> ScopeState {
         value: impl IntoAttributeValue<'src>,
         namespace: Option<&'static str>,
         volatile: bool,
-    ) -> Attribute<'src> {
+    ) -> Attribute {
         Attribute {
             name,
             namespace,
@@ -443,10 +401,10 @@ impl<'src> ScopeState {
     /// ```
     pub fn component<'child, P>(
         &'src self,
-        component: fn(Scope<'child, P>) -> Element<'child>,
+        component: fn(Scope<'child, P>) -> Element,
         props: P,
         fn_name: &'static str,
-    ) -> DynamicNode<'src>
+    ) -> DynamicNode
     where
         // The properties must be valid until the next bump frame
         P: Properties + 'src,
@@ -456,13 +414,12 @@ impl<'src> ScopeState {
         let vcomp = VProps::new(component, P::memoize, props);
 
         // cast off the lifetime of the render return
-        let as_dyn: Box<dyn AnyProps<'child> + '_> = Box::new(vcomp);
-        let extended: Box<dyn AnyProps<'src> + 'src> = unsafe { std::mem::transmute(as_dyn) };
+        let as_dyn: Box<dyn AnyProps + '_> = Box::new(vcomp);
+        let extended: Box<dyn AnyProps + 'src> = unsafe { std::mem::transmute(as_dyn) };
 
         DynamicNode::Component(VComponent {
             name: fn_name,
             render_fn: component as *const (),
-            static_props: P::IS_STATIC,
             props: RefCell::new(Some(extended)),
             scope: Default::default(),
         })
@@ -470,9 +427,9 @@ impl<'src> ScopeState {
 
     /// Create a new [`EventHandler`] from an [`FnMut`]
     pub fn event_handler<T>(&'src self, f: impl FnMut(T) + 'src) -> EventHandler<'src, T> {
-        let handler: &mut dyn FnMut(T) = self.bump().alloc(f);
-        let caller = unsafe { BumpBox::from_raw(handler as *mut dyn FnMut(T)) };
-        let callback = RefCell::new(Some(caller));
+        let callback = RefCell::new(Some(Box::new(move |event: Event<T>| {
+            f(event.data);
+        })));
         EventHandler {
             callback,
             origin: self.context().id,
@@ -485,34 +442,22 @@ impl<'src> ScopeState {
     pub fn listener<T: 'static>(
         &'src self,
         mut callback: impl FnMut(Event<T>) + 'src,
-    ) -> AttributeValue<'src> {
-        // safety: there's no other way to create a dynamicly-dispatched bump box other than alloc + from-raw
-        // This is the suggested way to build a bumpbox
-        //
-        // In theory, we could just use regular boxes
-        let boxed: BumpBox<'src, dyn FnMut(_) + 'src> = unsafe {
-            BumpBox::from_raw(self.bump().alloc(move |event: Event<dyn Any>| {
+    ) -> AttributeValue {
+        AttributeValue::Listener(RefCell::new(Some(Box::new(
+            move |event: Event<dyn Any>| {
                 if let Ok(data) = event.data.downcast::<T>() {
                     callback(Event {
                         propagates: event.propagates,
                         data,
                     });
                 }
-            }))
-        };
-
-        AttributeValue::Listener(RefCell::new(Some(boxed)))
+            },
+        ))))
     }
 
     /// Create a new [`AttributeValue`] with a value that implements [`AnyValue`]
-    pub fn any_value<T: AnyValue>(&'src self, value: T) -> AttributeValue<'src> {
-        // safety: there's no other way to create a dynamicly-dispatched bump box other than alloc + from-raw
-        // This is the suggested way to build a bumpbox
-        //
-        // In theory, we could just use regular boxes
-        let boxed: BumpBox<'src, dyn AnyValue> =
-            unsafe { BumpBox::from_raw(self.bump().alloc(value)) };
-        AttributeValue::Any(RefCell::new(Some(boxed)))
+    pub fn any_value<T: AnyValue>(&'src self, value: T) -> AttributeValue {
+        AttributeValue::Any(RefCell::new(Some(Box::new(value))))
     }
 
     /// Mark this component as suspended and then return None

+ 4 - 2
packages/core/src/virtual_dom.rs

@@ -16,7 +16,9 @@ use crate::{
 use futures_util::{pin_mut, StreamExt};
 use rustc_hash::{FxHashMap, FxHashSet};
 use slab::Slab;
-use std::{any::Any, cell::Cell, collections::BTreeSet, future::Future, ptr::NonNull, rc::Rc, sync::Arc};
+use std::{
+    any::Any, cell::Cell, collections::BTreeSet, future::Future, ptr::NonNull, rc::Rc, sync::Arc,
+};
 
 /// A virtual node system that progresses user events and diffs UI trees.
 ///
@@ -186,7 +188,7 @@ pub struct VirtualDom {
     pub(crate) templates: FxHashMap<TemplateId, FxHashMap<usize, Template<'static>>>,
 
     // Every element is actually a dual reference - one to the template and the other to the dynamic node in that template
-    pub(crate) element_refs: Slab<Option<NonNull<VNode<'static>>>>,
+    pub(crate) element_refs: Slab<Option<NonNull<VNode>>>,
 
     // The element ids that are used in the renderer
     pub(crate) elements: Slab<Option<ElementRef>>,

+ 1 - 1
packages/html/src/events.rs

@@ -9,7 +9,7 @@ macro_rules! impl_event {
         $(
             $( #[$attr] )*
             #[inline]
-            pub fn $name<'a, E: crate::EventReturn<T>, T>(_cx: &'a ::dioxus_core::ScopeState, mut _f: impl FnMut(::dioxus_core::Event<$data>) -> E + 'a) -> ::dioxus_core::Attribute<'a> {
+            pub fn $name<'a, E: crate::EventReturn<T>, T>(_cx: &'a ::dioxus_core::ScopeState, mut _f: impl FnMut(::dioxus_core::Event<$data>) -> E + 'a) -> ::dioxus_core::Attribute {
                 ::dioxus_core::Attribute::new(
                     stringify!($name),
                     _cx.listener(move |e: ::dioxus_core::Event<$data>| {

+ 1 - 1
packages/html/src/events/mouse.rs

@@ -151,7 +151,7 @@ impl_event! {
 pub fn ondoubleclick<'a, E: crate::EventReturn<T>, T>(
     _cx: &'a ::dioxus_core::ScopeState,
     mut _f: impl FnMut(::dioxus_core::Event<MouseData>) -> E + 'a,
-) -> ::dioxus_core::Attribute<'a> {
+) -> ::dioxus_core::Attribute {
     ::dioxus_core::Attribute::new(
         "ondblclick",
         _cx.listener(move |e: ::dioxus_core::Event<MouseData>| {