Feat: wire up rebuild
This commit is contained in:
1 parent
4d01455729
commit
06ae4fc178
11 files changed
+210
-170
No files matched your search
+65
-67
@@ -12,6 +12,7 @@ use std::{
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
sync::atomic::AtomicUsize,
|
||||
sync::atomic::Ordering,
|
||||
todo,
|
||||
};
|
||||
|
||||
@@ -40,34 +41,23 @@ pub struct Scope {
|
||||
|
||||
// lying, cheating reference >:(
|
||||
pub props: Box<dyn std::any::Any>,
|
||||
// pub props: Box<dyn Properties>,
|
||||
|
||||
//
|
||||
// pub props_type: TypeId,
|
||||
pub caller: *const (),
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
// create a new scope from a function
|
||||
pub fn new<'a, P1, P2: 'static>(
|
||||
// pub fn new<'a, P: Properties, PFree: P + 'a, PLocked: P + 'static>(
|
||||
f: FC<P1>,
|
||||
props: P1,
|
||||
parent: Option<Index>,
|
||||
) -> Self
|
||||
// where
|
||||
// PFree: 'a,
|
||||
// PLocked: 'static,
|
||||
{
|
||||
// Capture the props type
|
||||
// let props_type = TypeId::of::<P>();
|
||||
pub fn new<'a, P1, P2: 'static>(f: FC<P1>, props: P1, parent: Option<Index>) -> Self {
|
||||
let hook_arena = typed_arena::Arena::new();
|
||||
let hooks = RefCell::new(Vec::new());
|
||||
|
||||
// Capture the caller
|
||||
let caller = f as *const ();
|
||||
|
||||
let listeners = Vec::new();
|
||||
let listeners: Vec<Box<dyn Fn()>> = vec![Box::new(|| {
|
||||
log::info!("Base listener called");
|
||||
})];
|
||||
|
||||
let old_frame = BumpFrame {
|
||||
bump: Bump::new(),
|
||||
@@ -84,16 +74,11 @@ impl Scope {
|
||||
// box the props
|
||||
let props = Box::new(props);
|
||||
|
||||
// erase the lifetime
|
||||
// we'll manage this with dom lifecycle
|
||||
|
||||
let props = unsafe { std::mem::transmute::<_, Box<P2>>(props) };
|
||||
|
||||
// todo!()
|
||||
Self {
|
||||
hook_arena,
|
||||
hooks,
|
||||
// props_type,
|
||||
caller,
|
||||
frames,
|
||||
listeners,
|
||||
@@ -102,13 +87,6 @@ impl Scope {
|
||||
}
|
||||
}
|
||||
|
||||
/// Update this component's props with a new set of props, remotely
|
||||
///
|
||||
///
|
||||
pub(crate) fn update_props<'a, P>(&self, _new_props: P) -> crate::error::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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
|
||||
///
|
||||
@@ -120,67 +98,67 @@ impl Scope {
|
||||
frame
|
||||
};
|
||||
|
||||
let node_slot = std::rc::Rc::new(RefCell::new(None));
|
||||
let ctx: Context<'bump> = Context {
|
||||
arena: &self.hook_arena,
|
||||
hooks: &self.hooks,
|
||||
bump: &frame.bump,
|
||||
idx: 0.into(),
|
||||
_p: PhantomData {},
|
||||
final_nodes: node_slot.clone(),
|
||||
};
|
||||
|
||||
unsafe {
|
||||
/*
|
||||
SAFETY ALERT
|
||||
|
||||
This particular usage of transmute is outlined in its docs https://doc.rust-lang.org/std/mem/fn.transmute.html
|
||||
We hide the generic bound on the function item by casting it to raw pointer. When the function is actually called,
|
||||
we transmute the function back using the props as reference.
|
||||
|
||||
we could do a better check to make sure that the TypeID is correct before casting
|
||||
--
|
||||
This is safe because we check that the generic type matches before casting.
|
||||
*/
|
||||
// we use plocked to be able to remove the borrowed lifetime
|
||||
// these lifetimes could be very broken, so we need to dynamically manage them
|
||||
let caller = std::mem::transmute::<*const (), FC<PLocked>>(self.caller);
|
||||
let props = self.props.downcast_ref::<PLocked>().unwrap();
|
||||
|
||||
// Note that the actual modification of the vnode head element occurs during this call
|
||||
let _nodes: DomTree = caller(ctx, props);
|
||||
todo!("absorb domtree into self")
|
||||
// let nodes: VNode<'bump> = caller(ctx, props);
|
||||
|
||||
// let unsafe_node = std::mem::transmute::<VNode<'bump>, VNode<'static>>(nodes);
|
||||
// frame.head_node = unsafe_node;
|
||||
/*
|
||||
SAFETY ALERT
|
||||
|
||||
DO NOT USE THIS VNODE WITHOUT THE APPOPRIATE ACCESSORS.
|
||||
KEEPING THIS STATIC REFERENCE CAN LEAD TO UB.
|
||||
|
||||
Some things to note:
|
||||
- The VNode itself is bound to the lifetime, but it itself is owned by scope.
|
||||
- The VNode has a private API and can only be used from accessors.
|
||||
- Public API cannot drop or destructure VNode
|
||||
*/
|
||||
// the nodes we care about have been unsafely extended to a static lifetime in context
|
||||
frame.head_node = node_slot
|
||||
.deref()
|
||||
.borrow_mut()
|
||||
.take()
|
||||
.expect("Viewing did not happen");
|
||||
}
|
||||
/*
|
||||
SAFETY ALERT
|
||||
|
||||
This particular usage of transmute is outlined in its docs https://doc.rust-lang.org/std/mem/fn.transmute.html
|
||||
We hide the generic bound on the function item by casting it to raw pointer. When the function is actually called,
|
||||
we transmute the function back using the props as reference.
|
||||
|
||||
we could do a better check to make sure that the TypeID is correct before casting
|
||||
--
|
||||
This is safe because we check that the generic type matches before casting.
|
||||
*/
|
||||
|
||||
/*
|
||||
SAFETY ALERT
|
||||
|
||||
DO NOT USE THIS VNODE WITHOUT THE APPOPRIATE ACCESSORS.
|
||||
KEEPING THIS STATIC REFERENCE CAN LEAD TO UB.
|
||||
|
||||
Some things to note:
|
||||
- The VNode itself is bound to the lifetime, but it itself is owned by scope.
|
||||
- The VNode has a private API and can only be used from accessors.
|
||||
- Public API cannot drop or destructure VNode
|
||||
*/
|
||||
}
|
||||
|
||||
/// 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 current_root_node<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
||||
pub fn new_frame<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
||||
self.frames.current_head_node()
|
||||
}
|
||||
|
||||
pub fn prev_root_node<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
||||
todo!()
|
||||
pub fn old_frame<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
||||
self.frames.prev_head_node()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BumpFrame {
|
||||
pub bump: Bump,
|
||||
pub head_node: VNode<'static>,
|
||||
}
|
||||
|
||||
// todo, do better with the active frame stuff
|
||||
// somehow build this vnode with a lifetime tied to self
|
||||
// This root node has "static" lifetime, but it's really not static.
|
||||
@@ -192,6 +170,11 @@ pub struct ActiveFrame {
|
||||
pub frames: [BumpFrame; 2],
|
||||
}
|
||||
|
||||
pub struct BumpFrame {
|
||||
pub bump: Bump,
|
||||
pub head_node: VNode<'static>,
|
||||
}
|
||||
|
||||
impl ActiveFrame {
|
||||
fn from_frames(a: BumpFrame, b: BumpFrame) -> Self {
|
||||
Self {
|
||||
@@ -201,8 +184,23 @@ impl ActiveFrame {
|
||||
}
|
||||
|
||||
fn current_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
||||
let cur_idx = self.idx.borrow().load(std::sync::atomic::Ordering::Relaxed) % 1;
|
||||
let raw_node = &self.frames[cur_idx];
|
||||
let raw_node = match self.idx.borrow().load(Ordering::Relaxed) & 1 != 0 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
};
|
||||
unsafe {
|
||||
let unsafe_head = &raw_node.head_node;
|
||||
let safe_node = std::mem::transmute::<&VNode<'static>, &VNode<'b>>(unsafe_head);
|
||||
safe_node
|
||||
}
|
||||
}
|
||||
|
||||
fn prev_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
||||
let raw_node = match self.idx.borrow().load(Ordering::Relaxed) & 1 == 0 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let unsafe_head = &raw_node.head_node;
|
||||
let safe_node = std::mem::transmute::<&VNode<'static>, &VNode<'b>>(unsafe_head);
|
||||
@@ -211,8 +209,8 @@ impl ActiveFrame {
|
||||
}
|
||||
|
||||
fn next(&mut self) -> &mut BumpFrame {
|
||||
self.idx.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
let cur = self.idx.borrow().load(std::sync::atomic::Ordering::Relaxed);
|
||||
self.idx.fetch_add(1, Ordering::Relaxed);
|
||||
let cur = self.idx.borrow().load(Ordering::Relaxed);
|
||||
match cur % 1 {
|
||||
1 => &mut self.frames[1],
|
||||
0 => &mut self.frames[0],
|
||||
@@ -276,7 +274,7 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
fn child_example(ctx: Context, props: &ExampleProps) -> DomTree {
|
||||
fn child_example<'b>(ctx: Context<'b>, props: &'b ExampleProps) -> DomTree {
|
||||
ctx.view(move |b| {
|
||||
div(b)
|
||||
.child(text(props.name))
|
||||
|
||||
Reference in new issue
Block a user