1
0
Эх сурвалжийг харах

use boxed slices instead of vecs where possible

Evan Almloff 1 жил өмнө
parent
commit
aefa8a2431

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

@@ -76,7 +76,7 @@ impl VirtualDom {
 
     /// Create this template and write its mutations
     pub(crate) fn create(&mut self, node: &VNode, to: &mut impl WriteMutations) -> usize {
-        // check for a overriden template
+        // check for a overridden template
         #[cfg(debug_assertions)]
         {
             let (path, byte_index) = node.template.get().name.rsplit_once(':').unwrap();
@@ -86,14 +86,14 @@ impl VirtualDom {
                 .and_then(|map| map.get(&byte_index.parse().unwrap()))
             {
                 node.template.set(*template);
-            }
-        }
 
-        // Initialize the root nodes slice
-        {
-            let mut nodes_mut = node.root_ids.borrow_mut();
-            let len = node.template.get().roots.len();
-            nodes_mut.resize(len, ElementId::default());
+                // Initialize the root nodes slice if it was changed
+                let mut nodes_mut = node.root_ids.borrow_mut();
+                let len = node.template.get().roots.len();
+                if nodes_mut.len() != len {
+                    *nodes_mut = vec![ElementId::default(); len].into_boxed_slice();
+                };
+            }
         };
 
         // The best renderers will have templates prehydrated and registered

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

@@ -149,9 +149,9 @@ impl VirtualDom {
         // Make sure the roots get transferred over while we're here
         {
             let mut right = right_template.root_ids.borrow_mut();
-            right.clear();
-            for &element in left_template.root_ids.borrow().iter() {
-                right.push(element);
+            let left = left_template.root_ids.borrow();
+            for (from, into) in left.iter().zip(right.iter_mut()) {
+                *into = *from;
             }
         }
     }

+ 13 - 1
packages/core/src/dirty_scope.rs

@@ -2,12 +2,24 @@ use std::hash::Hash;
 
 use crate::ScopeId;
 
-#[derive(Debug, Clone, Eq, PartialOrd, Ord)]
+#[derive(Debug, Clone, Eq)]
 pub struct DirtyScope {
     pub height: u32,
     pub id: ScopeId,
 }
 
+impl PartialOrd for DirtyScope {
+    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for DirtyScope {
+    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+        self.height.cmp(&other.height).then(self.id.cmp(&other.id))
+    }
+}
+
 impl PartialEq for DirtyScope {
     fn eq(&self, other: &Self) -> bool {
         self.id == other.id

+ 4 - 4
packages/core/src/error_boundary.rs

@@ -287,8 +287,8 @@ fn default_handler(error: CapturedError) -> Element {
     Some(VNode::new(
         None,
         TEMPLATE,
-        Vec::with_capacity(1usize),
-        vec![error.to_string().into_dyn_node()],
+        Box::new([Default::default(); 1]),
+        Box::new([error.to_string().into_dyn_node()]),
         Default::default(),
     ))
 }
@@ -460,8 +460,8 @@ pub fn ErrorBoundary(props: ErrorBoundaryProps) -> Element {
             VNode::new(
                 None,
                 TEMPLATE,
-                Vec::with_capacity(1usize),
-                vec![(props.children).into_dyn_node()],
+                Box::new([Default::default(); 1]),
+                Box::new([(props.children).into_dyn_node()]),
                 Default::default(),
             )
         }),

+ 4 - 3
packages/core/src/lib.rs

@@ -77,8 +77,8 @@ pub use crate::innerlude::{
     fc_to_builder, generation, once, schedule_update, schedule_update_any, vdom_is_rendering,
     AnyValue, Attribute, AttributeValue, CapturedError, Component, DynamicNode, Element, ElementId,
     Event, Fragment, IntoDynNode, Mutation, MutationsVec, Properties, RenderReturn, ScopeId, Task,
-    Template, TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, VirtualDom,
-    WriteMutations,
+    Template, TemplateAttribute, TemplateNode, VComponent, VNode, VNodeInner, VPlaceholder, VText,
+    VirtualDom, WriteMutations,
 };
 
 /// The purpose of this module is to alleviate imports of many common types
@@ -91,6 +91,7 @@ pub mod prelude {
         push_future, remove_future, schedule_update, schedule_update_any, spawn, spawn_forever,
         suspend, use_error_boundary, AnyValue, Component, Element, ErrorBoundary, Event,
         EventHandler, Fragment, IntoAttributeValue, IntoDynNode, Properties, Runtime, RuntimeGuard,
-        ScopeId, Task, Template, TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom,
+        ScopeId, Task, Template, TemplateAttribute, TemplateNode, Throw, VNode, VNodeInner,
+        VirtualDom,
     };
 }

+ 9 - 8
packages/core/src/nodes.rs

@@ -4,6 +4,7 @@ use crate::Properties;
 use crate::{arena::ElementId, Element, Event, ScopeId};
 use std::ops::Deref;
 use std::rc::Rc;
+use std::vec;
 use std::{
     any::{Any, TypeId},
     cell::{Cell, RefCell},
@@ -53,16 +54,16 @@ pub struct VNodeInner {
 
     /// The IDs for the roots of this template - to be used when moving the template around and removing it from
     /// the actual Dom
-    pub root_ids: RefCell<Vec<ElementId>>,
+    pub root_ids: RefCell<Box<[ElementId]>>,
 
     /// The static nodes and static descriptor of the template
     pub template: Cell<Template>,
 
     /// The dynamic parts of the template
-    pub dynamic_nodes: Vec<DynamicNode>,
+    pub dynamic_nodes: Box<[DynamicNode]>,
 
     /// The dynamic parts of the template
-    pub dynamic_attrs: Vec<Attribute>,
+    pub dynamic_attrs: Box<[Attribute]>,
 }
 
 /// A reference to a template along with any context needed to hydrate it
@@ -93,8 +94,8 @@ impl VNode {
             key: None,
             parent: Default::default(),
             root_ids: Default::default(),
-            dynamic_nodes: Vec::new(),
-            dynamic_attrs: Vec::new(),
+            dynamic_nodes: Box::new([]),
+            dynamic_attrs: Box::new([]),
             template: Cell::new(Template {
                 name: "dioxus-empty",
                 roots: &[],
@@ -108,9 +109,9 @@ impl VNode {
     pub fn new(
         key: Option<String>,
         template: Template,
-        root_ids: Vec<ElementId>,
-        dynamic_nodes: Vec<DynamicNode>,
-        dynamic_attrs: Vec<Attribute>,
+        root_ids: Box<[ElementId]>,
+        dynamic_nodes: Box<[DynamicNode]>,
+        dynamic_attrs: Box<[Attribute]>,
     ) -> Self {
         Self(Rc::new(VNodeInner {
             key,

+ 5 - 12
packages/core/src/virtual_dom.rs

@@ -317,9 +317,9 @@ impl VirtualDom {
     ///
     /// Whenever the Runtime "works", it will re-render this scope
     pub fn mark_dirty(&mut self, id: ScopeId) {
-        if let Some(scope) = self.get_scope(id) {
-            let height = scope.context().height();
-            tracing::trace!("Marking scope {:?} ({}) as dirty", id, scope.context().name);
+        if let Some(context) = self.runtime.get_context(id) {
+            let height = context.height();
+            tracing::trace!("Marking scope {:?} ({}) as dirty", id, context.name);
             self.dirty_scopes.insert(DirtyScope { height, id });
         }
     }
@@ -504,7 +504,7 @@ impl VirtualDom {
     /// Replace a template at runtime. This will re-render all components that use this template.
     /// This is the primitive that enables hot-reloading.
     ///
-    /// The caller must ensure that the template refrences the same dynamic attributes and nodes as the original template.
+    /// The caller must ensure that the template references the same dynamic attributes and nodes as the original template.
     ///
     /// This will only replace the the parent template, not any nested templates.
     pub fn replace_template(&mut self, template: Template) {
@@ -619,9 +619,7 @@ impl VirtualDom {
         loop {
             // Next, diff any dirty scopes
             // We choose not to poll the deadline since we complete pretty quickly anyways
-            if let Some(dirty) = self.dirty_scopes.iter().next().cloned() {
-                self.dirty_scopes.remove(&dirty);
-
+            while let Some(dirty) = self.dirty_scopes.pop_first() {
                 // If the scope doesn't exist for whatever reason, then we should skip it
                 if !self.scopes.contains(dirty.id.0) {
                     continue;
@@ -635,11 +633,6 @@ impl VirtualDom {
                 }
             }
 
-            // If there's more work, then just continue, plenty of work to do
-            if !self.dirty_scopes.is_empty() {
-                continue;
-            }
-
             // Poll the suspense leaves in the meantime
             let mut work = self.wait_for_work();
 

+ 4 - 4
packages/rsx/src/hot_reload/hot_reloading_file_map.rs

@@ -15,7 +15,7 @@ use syn::spanned::Spanned;
 use super::hot_reload_diff::{find_rsx, DiffResult};
 
 pub enum UpdateResult {
-    UpdatedRsx(Vec<Template<'static>>),
+    UpdatedRsx(Vec<Template>),
     NeedsRebuild,
 }
 
@@ -28,7 +28,7 @@ pub struct FileMapBuildResult<Ctx: HotReloadingContext> {
 }
 
 pub struct FileMap<Ctx: HotReloadingContext> {
-    pub map: HashMap<PathBuf, (String, Option<Template<'static>>)>,
+    pub map: HashMap<PathBuf, (String, Option<Template>)>,
     in_workspace: HashMap<PathBuf, Option<PathBuf>>,
     phantom: std::marker::PhantomData<Ctx>,
 }
@@ -45,7 +45,7 @@ impl<Ctx: HotReloadingContext> FileMap<Ctx> {
         mut filter: impl FnMut(&Path) -> bool,
     ) -> io::Result<FileMapBuildResult<Ctx>> {
         struct FileMapSearchResult {
-            map: HashMap<PathBuf, (String, Option<Template<'static>>)>,
+            map: HashMap<PathBuf, (String, Option<Template>)>,
             errors: Vec<io::Error>,
         }
         fn find_rs_files(
@@ -115,7 +115,7 @@ impl<Ctx: HotReloadingContext> FileMap<Ctx> {
                             self.map.insert(file_path.to_path_buf(), (src, None));
                         }
                         DiffResult::RsxChanged(changed) => {
-                            let mut messages: Vec<Template<'static>> = Vec::new();
+                            let mut messages: Vec<Template> = Vec::new();
                             for (old, new) in changed.into_iter() {
                                 let old_start = old.span().start();
 

+ 3 - 3
packages/rsx/src/lib.rs

@@ -256,9 +256,9 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
             ::dioxus::core::VNode::new(
                 #key_tokens,
                 TEMPLATE,
-                Vec::with_capacity(#root_count),
-                vec![ #( #node_printer ),* ],
-                vec![ #( #dyn_attr_printer ),* ],
+                Box::new([Default::default();#root_count]),
+                Box::new([ #( #node_printer ),* ]),
+                Box::new([ #( #dyn_attr_printer ),* ]),
             )
         });
     }