Sfoglia il codice sorgente

wip: move hooklist into scope

Jonathan Kelley 3 anni fa
parent
commit
b9fc5fc

+ 112 - 0
packages/core/src/diff.rs

@@ -90,6 +90,7 @@
 
 use crate::innerlude::*;
 use fxhash::{FxHashMap, FxHashSet};
+use smallvec::{smallvec, SmallVec};
 use DomEdit::*;
 
 /// Our DiffMachine is an iterative tree differ.
@@ -124,6 +125,117 @@ impl<'bump> DiffState<'bump> {
     }
 }
 
+/// The stack instructions we use to diff and create new nodes.
+#[derive(Debug)]
+pub(crate) enum DiffInstruction<'a> {
+    Diff {
+        old: &'a VNode<'a>,
+        new: &'a VNode<'a>,
+    },
+
+    Create {
+        node: &'a VNode<'a>,
+    },
+
+    /// pushes the node elements onto the stack for use in mount
+    PrepareMove {
+        node: &'a VNode<'a>,
+    },
+
+    Mount {
+        and: MountType<'a>,
+    },
+
+    PopScope,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum MountType<'a> {
+    Absorb,
+    Append,
+    Replace { old: &'a VNode<'a> },
+    InsertAfter { other_node: &'a VNode<'a> },
+    InsertBefore { other_node: &'a VNode<'a> },
+}
+
+pub(crate) struct DiffStack<'bump> {
+    pub(crate) instructions: Vec<DiffInstruction<'bump>>,
+    nodes_created_stack: SmallVec<[usize; 10]>,
+    pub scope_stack: SmallVec<[ScopeId; 5]>,
+}
+
+impl<'bump> DiffStack<'bump> {
+    pub fn new() -> Self {
+        Self {
+            instructions: Vec::with_capacity(1000),
+            nodes_created_stack: smallvec![],
+            scope_stack: smallvec![],
+        }
+    }
+
+    pub fn pop(&mut self) -> Option<DiffInstruction<'bump>> {
+        self.instructions.pop()
+    }
+
+    pub fn pop_off_scope(&mut self) {
+        self.scope_stack.pop();
+    }
+
+    pub fn push(&mut self, instruction: DiffInstruction<'bump>) {
+        self.instructions.push(instruction)
+    }
+
+    pub fn create_children(&mut self, children: &'bump [VNode<'bump>], and: MountType<'bump>) {
+        self.nodes_created_stack.push(0);
+        self.instructions.push(DiffInstruction::Mount { and });
+
+        for child in children.iter().rev() {
+            self.instructions
+                .push(DiffInstruction::Create { node: child });
+        }
+    }
+
+    pub fn push_subtree(&mut self) {
+        self.nodes_created_stack.push(0);
+        self.instructions.push(DiffInstruction::Mount {
+            and: MountType::Append,
+        });
+    }
+
+    pub fn push_nodes_created(&mut self, count: usize) {
+        self.nodes_created_stack.push(count);
+    }
+
+    pub fn create_node(&mut self, node: &'bump VNode<'bump>, and: MountType<'bump>) {
+        self.nodes_created_stack.push(0);
+        self.instructions.push(DiffInstruction::Mount { and });
+        self.instructions.push(DiffInstruction::Create { node });
+    }
+
+    pub fn add_child_count(&mut self, count: usize) {
+        *self.nodes_created_stack.last_mut().unwrap() += count;
+    }
+
+    pub fn pop_nodes_created(&mut self) -> usize {
+        self.nodes_created_stack.pop().unwrap()
+    }
+
+    pub fn current_scope(&self) -> Option<ScopeId> {
+        self.scope_stack.last().copied()
+    }
+
+    pub fn create_component(&mut self, idx: ScopeId, node: &'bump VNode<'bump>) {
+        // Push the new scope onto the stack
+        self.scope_stack.push(idx);
+
+        self.instructions.push(DiffInstruction::PopScope);
+
+        // Run the creation algorithm with this scope on the stack
+        // ?? I think we treat components as fragments??
+        self.instructions.push(DiffInstruction::Create { node });
+    }
+}
+
 impl<'bump> DiffState<'bump> {
     pub fn diff_scope(&mut self, id: &ScopeId) {
         let (old, new) = (self.scopes.wip_head(id), self.scopes.fin_head(id));

+ 0 - 113
packages/core/src/diff_stack.rs

@@ -1,113 +0,0 @@
-use crate::innerlude::*;
-use smallvec::{smallvec, SmallVec};
-
-/// The stack instructions we use to diff and create new nodes.
-#[derive(Debug)]
-pub(crate) enum DiffInstruction<'a> {
-    Diff {
-        old: &'a VNode<'a>,
-        new: &'a VNode<'a>,
-    },
-
-    Create {
-        node: &'a VNode<'a>,
-    },
-
-    /// pushes the node elements onto the stack for use in mount
-    PrepareMove {
-        node: &'a VNode<'a>,
-    },
-
-    Mount {
-        and: MountType<'a>,
-    },
-
-    PopScope,
-}
-
-#[derive(Debug, Clone, Copy)]
-pub enum MountType<'a> {
-    Absorb,
-    Append,
-    Replace { old: &'a VNode<'a> },
-    InsertAfter { other_node: &'a VNode<'a> },
-    InsertBefore { other_node: &'a VNode<'a> },
-}
-
-pub(crate) struct DiffStack<'bump> {
-    pub(crate) instructions: Vec<DiffInstruction<'bump>>,
-    nodes_created_stack: SmallVec<[usize; 10]>,
-    pub scope_stack: SmallVec<[ScopeId; 5]>,
-}
-
-impl<'bump> DiffStack<'bump> {
-    pub fn new() -> Self {
-        Self {
-            instructions: Vec::with_capacity(1000),
-            nodes_created_stack: smallvec![],
-            scope_stack: smallvec![],
-        }
-    }
-
-    pub fn pop(&mut self) -> Option<DiffInstruction<'bump>> {
-        self.instructions.pop()
-    }
-
-    pub fn pop_off_scope(&mut self) {
-        self.scope_stack.pop();
-    }
-
-    pub fn push(&mut self, instruction: DiffInstruction<'bump>) {
-        self.instructions.push(instruction)
-    }
-
-    pub fn create_children(&mut self, children: &'bump [VNode<'bump>], and: MountType<'bump>) {
-        self.nodes_created_stack.push(0);
-        self.instructions.push(DiffInstruction::Mount { and });
-
-        for child in children.iter().rev() {
-            self.instructions
-                .push(DiffInstruction::Create { node: child });
-        }
-    }
-
-    pub fn push_subtree(&mut self) {
-        self.nodes_created_stack.push(0);
-        self.instructions.push(DiffInstruction::Mount {
-            and: MountType::Append,
-        });
-    }
-
-    pub fn push_nodes_created(&mut self, count: usize) {
-        self.nodes_created_stack.push(count);
-    }
-
-    pub fn create_node(&mut self, node: &'bump VNode<'bump>, and: MountType<'bump>) {
-        self.nodes_created_stack.push(0);
-        self.instructions.push(DiffInstruction::Mount { and });
-        self.instructions.push(DiffInstruction::Create { node });
-    }
-
-    pub fn add_child_count(&mut self, count: usize) {
-        *self.nodes_created_stack.last_mut().unwrap() += count;
-    }
-
-    pub fn pop_nodes_created(&mut self) -> usize {
-        self.nodes_created_stack.pop().unwrap()
-    }
-
-    pub fn current_scope(&self) -> Option<ScopeId> {
-        self.scope_stack.last().copied()
-    }
-
-    pub fn create_component(&mut self, idx: ScopeId, node: &'bump VNode<'bump>) {
-        // Push the new scope onto the stack
-        self.scope_stack.push(idx);
-
-        self.instructions.push(DiffInstruction::PopScope);
-
-        // Run the creation algorithm with this scope on the stack
-        // ?? I think we treat components as fragments??
-        self.instructions.push(DiffInstruction::Create { node });
-    }
-}

+ 0 - 71
packages/core/src/hooklist.rs

@@ -1,71 +0,0 @@
-use std::{
-    any::Any,
-    cell::{Cell, RefCell},
-};
-
-use bumpalo::Bump;
-
-/// An abstraction over internally stored data using a hook-based memory layout.
-///
-/// Hooks are allocated using Boxes and then our stored references are given out.
-///
-/// It's unsafe to "reset" the hooklist, but it is safe to add hooks into it.
-///
-/// Todo: this could use its very own bump arena, but that might be a tad overkill
-#[derive(Default)]
-pub(crate) struct HookList {
-    arena: Bump,
-    vals: RefCell<Vec<*mut dyn Any>>,
-    idx: Cell<usize>,
-}
-
-impl HookList {
-    pub(crate) fn next<T: 'static>(&self) -> Option<&mut T> {
-        self.vals.borrow().get(self.idx.get()).and_then(|inn| {
-            self.idx.set(self.idx.get() + 1);
-            let raw_box = unsafe { &mut **inn };
-            raw_box.downcast_mut::<T>()
-        })
-    }
-
-    /// This resets the internal iterator count
-    /// It's okay that we've given out each hook, but now we have the opportunity to give it out again
-    /// Therefore, resetting is considered unsafe
-    ///
-    /// This should only be ran by Dioxus itself before "running scope".
-    /// Dioxus knows how to descend through the tree to prevent mutable aliasing.
-    pub(crate) unsafe fn reset(&self) {
-        self.idx.set(0);
-    }
-
-    pub(crate) fn push_hook<T: 'static>(&self, new: T) {
-        let val = self.arena.alloc(new);
-        self.vals.borrow_mut().push(val)
-    }
-
-    pub(crate) fn len(&self) -> usize {
-        self.vals.borrow().len()
-    }
-
-    pub(crate) fn cur_idx(&self) -> usize {
-        self.idx.get()
-    }
-
-    pub(crate) fn at_end(&self) -> bool {
-        self.cur_idx() >= self.len()
-    }
-
-    pub fn clear_hooks(&mut self) {
-        self.vals.borrow_mut().drain(..).for_each(|state| {
-            let as_mut = unsafe { &mut *state };
-            let boxed = unsafe { bumpalo::boxed::Box::from_raw(as_mut) };
-            drop(boxed);
-        });
-    }
-
-    /// Get the ammount of memory a hooklist uses
-    /// Used in heuristics
-    pub fn get_hook_arena_size(&self) -> usize {
-        self.arena.allocated_bytes()
-    }
-}

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

@@ -14,8 +14,6 @@ Some utilities
 */
 pub(crate) mod component;
 pub(crate) mod diff;
-pub(crate) mod diff_stack;
-pub(crate) mod hooklist;
 pub(crate) mod lazynodes;
 pub(crate) mod mutations;
 pub(crate) mod nodes;
@@ -25,9 +23,7 @@ pub(crate) mod virtual_dom;
 
 pub(crate) mod innerlude {
     pub use crate::component::*;
-    pub(crate) use crate::diff::*;
-    pub use crate::diff_stack::*;
-    pub(crate) use crate::hooklist::*;
+    pub use crate::diff::*;
     pub use crate::lazynodes::*;
     pub use crate::mutations::*;
     pub use crate::nodes::*;

+ 65 - 0
packages/core/src/scope.rs

@@ -528,6 +528,71 @@ impl BumpFrame {
     }
 }
 
+/// An abstraction over internally stored data using a hook-based memory layout.
+///
+/// Hooks are allocated using Boxes and then our stored references are given out.
+///
+/// It's unsafe to "reset" the hooklist, but it is safe to add hooks into it.
+///
+/// Todo: this could use its very own bump arena, but that might be a tad overkill
+#[derive(Default)]
+pub(crate) struct HookList {
+    arena: Bump,
+    vals: RefCell<Vec<*mut dyn Any>>,
+    idx: Cell<usize>,
+}
+
+impl HookList {
+    pub(crate) fn next<T: 'static>(&self) -> Option<&mut T> {
+        self.vals.borrow().get(self.idx.get()).and_then(|inn| {
+            self.idx.set(self.idx.get() + 1);
+            let raw_box = unsafe { &mut **inn };
+            raw_box.downcast_mut::<T>()
+        })
+    }
+
+    /// This resets the internal iterator count
+    /// It's okay that we've given out each hook, but now we have the opportunity to give it out again
+    /// Therefore, resetting is considered unsafe
+    ///
+    /// This should only be ran by Dioxus itself before "running scope".
+    /// Dioxus knows how to descend through the tree to prevent mutable aliasing.
+    pub(crate) unsafe fn reset(&self) {
+        self.idx.set(0);
+    }
+
+    pub(crate) fn push_hook<T: 'static>(&self, new: T) {
+        let val = self.arena.alloc(new);
+        self.vals.borrow_mut().push(val)
+    }
+
+    pub(crate) fn len(&self) -> usize {
+        self.vals.borrow().len()
+    }
+
+    pub(crate) fn cur_idx(&self) -> usize {
+        self.idx.get()
+    }
+
+    pub(crate) fn at_end(&self) -> bool {
+        self.cur_idx() >= self.len()
+    }
+
+    pub fn clear_hooks(&mut self) {
+        self.vals.borrow_mut().drain(..).for_each(|state| {
+            let as_mut = unsafe { &mut *state };
+            let boxed = unsafe { bumpalo::boxed::Box::from_raw(as_mut) };
+            drop(boxed);
+        });
+    }
+
+    /// Get the ammount of memory a hooklist uses
+    /// Used in heuristics
+    pub fn get_hook_arena_size(&self) -> usize {
+        self.arena.allocated_bytes()
+    }
+}
+
 #[test]
 fn sizeof() {
     dbg!(std::mem::size_of::<Scope>());