|
@@ -3,18 +3,12 @@ use crate::context::hooks::Hook;
|
|
use crate::innerlude::*;
|
|
use crate::innerlude::*;
|
|
use crate::nodes::VNode;
|
|
use crate::nodes::VNode;
|
|
use bumpalo::Bump;
|
|
use bumpalo::Bump;
|
|
-// use generational_arena::ScopeIdx;
|
|
|
|
|
|
|
|
use std::{
|
|
use std::{
|
|
- any::TypeId,
|
|
|
|
- borrow::{Borrow, BorrowMut},
|
|
|
|
- cell::{RefCell, UnsafeCell},
|
|
|
|
- future::Future,
|
|
|
|
|
|
+ any::{Any, TypeId},
|
|
|
|
+ cell::RefCell,
|
|
marker::PhantomData,
|
|
marker::PhantomData,
|
|
- ops::{Deref, DerefMut},
|
|
|
|
- sync::atomic::AtomicUsize,
|
|
|
|
- sync::atomic::Ordering,
|
|
|
|
- todo,
|
|
|
|
|
|
+ ops::Deref,
|
|
};
|
|
};
|
|
|
|
|
|
/// Every component in Dioxus is represented by a `Scope`.
|
|
/// Every component in Dioxus is represented by a `Scope`.
|
|
@@ -24,31 +18,35 @@ use std::{
|
|
/// Scopes are allocated in a generational arena. As components are mounted/unmounted, they will replace slots of dead components.
|
|
/// Scopes are allocated in a generational arena. As components are mounted/unmounted, they will replace slots of dead components.
|
|
/// The actual contents of the hooks, though, will be allocated with the standard allocator. These should not allocate as frequently.
|
|
/// The actual contents of the hooks, though, will be allocated with the standard allocator. These should not allocate as frequently.
|
|
pub struct Scope {
|
|
pub struct Scope {
|
|
- // pub(crate) struct Scope {
|
|
|
|
- // TODO @Jon
|
|
|
|
- // These hooks are actually references into the hook arena
|
|
|
|
- // These two could be combined with "OwningRef" to remove unsafe usage
|
|
|
|
- // could also use ourborous
|
|
|
|
- pub hooks: RefCell<Vec<*mut Hook>>,
|
|
|
|
- pub hook_arena: typed_arena::Arena<Hook>,
|
|
|
|
-
|
|
|
|
// Map to the parent
|
|
// Map to the parent
|
|
pub parent: Option<ScopeIdx>,
|
|
pub parent: Option<ScopeIdx>,
|
|
|
|
|
|
- pub frames: ActiveFrame,
|
|
|
|
-
|
|
|
|
- // List of listeners generated when CTX is evaluated
|
|
|
|
- pub listeners: Vec<*const dyn Fn(crate::events::VirtualEvent)>,
|
|
|
|
- // pub listeners: Vec<*const dyn Fn(crate::events::VirtualEvent)>,
|
|
|
|
- // pub listeners: Vec<Box<dyn Fn(crate::events::VirtualEvent)>>,
|
|
|
|
-
|
|
|
|
// lying, cheating reference >:(
|
|
// lying, cheating reference >:(
|
|
pub props: Box<dyn std::any::Any>,
|
|
pub props: Box<dyn std::any::Any>,
|
|
|
|
|
|
// our own index
|
|
// our own index
|
|
pub myidx: ScopeIdx,
|
|
pub myidx: ScopeIdx,
|
|
|
|
|
|
- // pub props_type: TypeId,
|
|
|
|
|
|
+ // ==========================
|
|
|
|
+ // slightly unsafe stuff
|
|
|
|
+ // ==========================
|
|
|
|
+ // an internal, highly efficient storage of vnodes
|
|
|
|
+ pub frames: ActiveFrame,
|
|
|
|
+
|
|
|
|
+ // These hooks are actually references into the hook arena
|
|
|
|
+ // These two could be combined with "OwningRef" to remove unsafe usage
|
|
|
|
+ // could also use ourborous
|
|
|
|
+ pub hooks: RefCell<Vec<*mut Hook>>,
|
|
|
|
+ pub hook_arena: typed_arena::Arena<Hook>,
|
|
|
|
+
|
|
|
|
+ // Unsafety:
|
|
|
|
+ // - is self-refenrential and therefore needs to point into the bump
|
|
|
|
+ //
|
|
|
|
+ // Stores references into the listeners attached to the vnodes
|
|
|
|
+ pub listeners: RefCell<Vec<*const dyn Fn(crate::events::VirtualEvent)>>,
|
|
|
|
+
|
|
|
|
+ // Unsafety
|
|
|
|
+ // - is a raw ptr because we need to compare
|
|
pub caller: *const (),
|
|
pub caller: *const (),
|
|
}
|
|
}
|
|
|
|
|
|
@@ -66,8 +64,7 @@ impl Scope {
|
|
// Capture the caller
|
|
// Capture the caller
|
|
let caller = f as *const ();
|
|
let caller = f as *const ();
|
|
|
|
|
|
- let listeners = vec![];
|
|
|
|
- // let listeners: Vec<Box<dyn Fn(crate::events::VirtualEvent)>> = vec![];
|
|
|
|
|
|
+ let listeners = Default::default();
|
|
|
|
|
|
let old_frame = BumpFrame {
|
|
let old_frame = BumpFrame {
|
|
bump: Bump::new(),
|
|
bump: Bump::new(),
|
|
@@ -97,7 +94,21 @@ impl Scope {
|
|
props,
|
|
props,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+pub struct RawComponent {
|
|
|
|
+ // used as a memoization strategy
|
|
|
|
+ comparator: *const Box<dyn Fn(&Box<dyn Any>) -> bool>,
|
|
|
|
+
|
|
|
|
+ // used to actually run the component
|
|
|
|
+ // encapsulates props
|
|
|
|
+ runner: *const Box<dyn Fn(Context) -> DomTree>,
|
|
|
|
|
|
|
|
+ // the actual FC<T>
|
|
|
|
+ raw: *const (),
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Scope {
|
|
/// Create a new context and run the component with references from the Virtual Dom
|
|
/// Create a new context and run the component with references from the Virtual Dom
|
|
/// This function downcasts the function pointer based on the stored props_type
|
|
/// This function downcasts the function pointer based on the stored props_type
|
|
///
|
|
///
|
|
@@ -106,11 +117,11 @@ impl Scope {
|
|
let frame = {
|
|
let frame = {
|
|
let frame = self.frames.next();
|
|
let frame = self.frames.next();
|
|
frame.bump.reset();
|
|
frame.bump.reset();
|
|
- log::debug!("Rednering into frame {:?}", frame as *const _);
|
|
|
|
frame
|
|
frame
|
|
};
|
|
};
|
|
|
|
|
|
let node_slot = std::rc::Rc::new(RefCell::new(None));
|
|
let node_slot = std::rc::Rc::new(RefCell::new(None));
|
|
|
|
+
|
|
let ctx: Context<'bump> = Context {
|
|
let ctx: Context<'bump> = Context {
|
|
arena: &self.hook_arena,
|
|
arena: &self.hook_arena,
|
|
hooks: &self.hooks,
|
|
hooks: &self.hooks,
|
|
@@ -119,6 +130,7 @@ impl Scope {
|
|
_p: PhantomData {},
|
|
_p: PhantomData {},
|
|
final_nodes: node_slot.clone(),
|
|
final_nodes: node_slot.clone(),
|
|
scope: self.myidx,
|
|
scope: self.myidx,
|
|
|
|
+ listeners: &self.listeners,
|
|
};
|
|
};
|
|
|
|
|
|
unsafe {
|
|
unsafe {
|
|
@@ -139,7 +151,7 @@ impl Scope {
|
|
let props = self.props.downcast_ref::<PLocked>().unwrap();
|
|
let props = self.props.downcast_ref::<PLocked>().unwrap();
|
|
|
|
|
|
// Note that the actual modification of the vnode head element occurs during this call
|
|
// Note that the actual modification of the vnode head element occurs during this call
|
|
- let _nodes: DomTree = caller(ctx, props);
|
|
|
|
|
|
+ let _: DomTree = caller(ctx, props);
|
|
|
|
|
|
/*
|
|
/*
|
|
SAFETY ALERT
|
|
SAFETY ALERT
|
|
@@ -158,32 +170,8 @@ impl Scope {
|
|
.borrow_mut()
|
|
.borrow_mut()
|
|
.take()
|
|
.take()
|
|
.expect("Viewing did not happen");
|
|
.expect("Viewing did not happen");
|
|
-
|
|
|
|
- // todo:
|
|
|
|
- // make this so we dont have to iterate through the vnodes to get its listener
|
|
|
|
- let mut listeners = vec![];
|
|
|
|
- retrieve_listeners(&frame.head_node, &mut listeners);
|
|
|
|
- self.listeners = listeners
|
|
|
|
- .into_iter()
|
|
|
|
- .map(|f| {
|
|
|
|
- let g = f.callback;
|
|
|
|
- g as *const _
|
|
|
|
- })
|
|
|
|
- .collect();
|
|
|
|
-
|
|
|
|
- // consume the listeners from the head_node into a list of boxed ref listeners
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- /// Accessor to get the root node and its children (safely)\
|
|
|
|
- /// Scope is self-referntial, so we are forced to use the 'static lifetime to cheat
|
|
|
|
- pub fn new_frame<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
|
|
|
- self.frames.current_head_node()
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn old_frame<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
|
|
|
- self.frames.prev_head_node()
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
fn retrieve_listeners(node: &VNode<'static>, listeners: &mut Vec<&Listener>) {
|
|
fn retrieve_listeners(node: &VNode<'static>, listeners: &mut Vec<&Listener>) {
|
|
@@ -198,6 +186,21 @@ fn retrieve_listeners(node: &VNode<'static>, listeners: &mut Vec<&Listener>) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// ==========================
|
|
|
|
+// Active-frame related code
|
|
|
|
+// ==========================
|
|
|
|
+impl Scope {
|
|
|
|
+ /// Accessor to get the root node and its children (safely)\
|
|
|
|
+ /// Scope is self-referntial, so we are forced to use the 'static lifetime to cheat
|
|
|
|
+ pub fn new_frame<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
|
|
|
+ self.frames.current_head_node()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn old_frame<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
|
|
|
+ self.frames.prev_head_node()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
// todo, do better with the active frame stuff
|
|
// todo, do better with the active frame stuff
|
|
// somehow build this vnode with a lifetime tied to self
|
|
// somehow build this vnode with a lifetime tied to self
|
|
// This root node has "static" lifetime, but it's really not static.
|
|
// This root node has "static" lifetime, but it's really not static.
|
|
@@ -205,7 +208,7 @@ fn retrieve_listeners(node: &VNode<'static>, listeners: &mut Vec<&Listener>) {
|
|
// Use this node as if it were static is unsafe, and needs to be fixed with ourborous or owning ref
|
|
// Use this node as if it were static is unsafe, and needs to be fixed with ourborous or owning ref
|
|
// ! do not copy this reference are things WILL break !
|
|
// ! do not copy this reference are things WILL break !
|
|
pub struct ActiveFrame {
|
|
pub struct ActiveFrame {
|
|
- pub idx: AtomicUsize,
|
|
|
|
|
|
+ pub idx: RefCell<usize>,
|
|
pub frames: [BumpFrame; 2],
|
|
pub frames: [BumpFrame; 2],
|
|
}
|
|
}
|
|
|
|
|
|
@@ -223,7 +226,7 @@ impl ActiveFrame {
|
|
}
|
|
}
|
|
|
|
|
|
fn current_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
|
fn current_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
|
- let raw_node = match self.idx.borrow().load(Ordering::Relaxed) & 1 == 0 {
|
|
|
|
|
|
+ let raw_node = match *self.idx.borrow() & 1 == 0 {
|
|
true => &self.frames[0],
|
|
true => &self.frames[0],
|
|
false => &self.frames[1],
|
|
false => &self.frames[1],
|
|
};
|
|
};
|
|
@@ -237,7 +240,7 @@ impl ActiveFrame {
|
|
}
|
|
}
|
|
|
|
|
|
fn prev_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
|
fn prev_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
|
- let raw_node = match self.idx.borrow().load(Ordering::Relaxed) & 1 != 0 {
|
|
|
|
|
|
+ let raw_node = match *self.idx.borrow() & 1 != 0 {
|
|
true => &self.frames[0],
|
|
true => &self.frames[0],
|
|
false => &self.frames[1],
|
|
false => &self.frames[1],
|
|
};
|
|
};
|
|
@@ -251,10 +254,9 @@ impl ActiveFrame {
|
|
}
|
|
}
|
|
|
|
|
|
fn next(&mut self) -> &mut BumpFrame {
|
|
fn next(&mut self) -> &mut BumpFrame {
|
|
- self.idx.fetch_add(1, Ordering::Relaxed);
|
|
|
|
- let cur = self.idx.borrow().load(Ordering::Relaxed);
|
|
|
|
|
|
+ *self.idx.borrow_mut() += 1;
|
|
|
|
|
|
- if cur % 2 == 0 {
|
|
|
|
|
|
+ if *self.idx.borrow() % 2 == 0 {
|
|
&mut self.frames[0]
|
|
&mut self.frames[0]
|
|
} else {
|
|
} else {
|
|
&mut self.frames[1]
|
|
&mut self.frames[1]
|
|
@@ -262,7 +264,7 @@ impl ActiveFrame {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-// #[cfg(test)]
|
|
|
|
|
|
+#[cfg(test)]
|
|
mod tests {
|
|
mod tests {
|
|
use super::*;
|
|
use super::*;
|
|
use crate::prelude::*;
|
|
use crate::prelude::*;
|