Feat: remove old macro

This commit is contained in:
Jonathan Kelley committed 2021-03-13 19:11:06 -05:00
1 parent e66827ec92
commit 9d0727edab
43 files changed
+208 -2306

No files matched your search

+5 -1
View File
@@ -3,7 +3,7 @@
//!
//! Renderers don't actually need to own the virtual dom (it's up to the implementer).
use crate::virtual_dom::VirtualDom;
use crate::{events::EventTrigger, virtual_dom::VirtualDom};
use crate::{innerlude::Result, prelude::*};
pub struct DebugRenderer {
@@ -33,6 +33,10 @@ impl DebugRenderer {
Self { internal_dom: dom }
}
pub fn handle_event(&mut self, trigger: EventTrigger) -> Result<()> {
Ok(())
}
pub fn step(&mut self, machine: &mut DiffMachine) -> Result<()> {
Ok(())
}
+50 -49
View File
@@ -36,13 +36,13 @@ use crate::{innerlude::*, scope::Scope};
use bumpalo::Bump;
use fxhash::{FxHashMap, FxHashSet};
use generational_arena::Arena;
use uuid::Uuid;
use std::{
cell::{RefCell, RefMut},
cmp::Ordering,
collections::VecDeque,
rc::{Rc, Weak},
sync::atomic::AtomicU32,
};
/// The DiffState is a cursor internal to the VirtualDOM's diffing algorithm that allows persistence of state while
@@ -66,13 +66,33 @@ pub struct DiffMachine<'a> {
pub enum LifeCycleEvent<'a> {
Mount {
caller: Weak<dyn for<'r> Fn(Context<'r>) -> DomTree + 'a>,
id: Uuid,
scope: Weak<VCompAssociatedScope>,
id: u32,
},
PropsChanged {
caller: Weak<dyn for<'r> Fn(Context<'r>) -> DomTree + 'a>,
scope: Weak<VCompAssociatedScope>,
id: u32,
},
SameProps {
caller: Weak<dyn for<'r> Fn(Context<'r>) -> DomTree + 'a>,
scope: Weak<VCompAssociatedScope>,
id: u32,
},
Replace {
caller: Weak<dyn for<'r> Fn(Context<'r>) -> DomTree + 'a>,
old_scope: Weak<VCompAssociatedScope>,
new_scope: Weak<VCompAssociatedScope>,
id: u32,
},
PropsChanged,
SameProps,
Remove,
}
static COUNTER: AtomicU32 = AtomicU32::new(1);
fn get_id() -> u32 {
COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
}
impl<'a> DiffMachine<'a> {
pub fn new() -> Self {
Self {
@@ -128,12 +148,27 @@ impl<'a> DiffMachine<'a> {
}
(VNode::Component(cold), VNode::Component(cnew)) => {
todo!("should not happen")
// if cold.caller_ref != cnew.caller_ref {
// // todo: create a stable addr
// self.lifecycle_events.push_back(LifeCycleEvent::Mount);
// return;
// }
// todo!("should not happen")
if cold.user_fc == cnew.user_fc {
// todo: create a stable addr
let caller = Rc::downgrade(&cnew.caller);
let id = cold.stable_addr.borrow().unwrap();
let scope = Rc::downgrade(&cold.ass_scope);
self.lifecycle_events
.push_back(LifeCycleEvent::PropsChanged { caller, id, scope });
} else {
let caller = Rc::downgrade(&cnew.caller);
let id = cold.stable_addr.borrow().unwrap();
let old_scope = Rc::downgrade(&cold.ass_scope);
let new_scope = Rc::downgrade(&cnew.ass_scope);
self.lifecycle_events.push_back(LifeCycleEvent::Replace {
caller,
id,
old_scope,
new_scope,
});
}
// let comparator = &cnew.comparator.0;
// let old_props = cold.raw_props.as_ref();
@@ -151,23 +186,7 @@ impl<'a> DiffMachine<'a> {
// todo: knock out any listeners
(_, VNode::Component(_new)) => {
// self.lifecycle_events.push_back(LifeCycleEvent::Mount);
// we have no stable reference to work from
// push the lifecycle event onto the queue
// self.lifecycle_events
// .borrow_mut()
// .push_back(LifecycleEvent {
// event_type: LifecycleType::Mount {
// props: new.props,
// to: self.cur_idx,
// },
// });
// we need to associaote this new component with a scope...
// self.change_list.save_known_root(id)
self.change_list.commit_traversal();
// push the current
}
(VNode::Component(_old), _) => {
@@ -242,36 +261,18 @@ impl<'a> DiffMachine<'a> {
/*
todo: integrate re-entrace
*/
// NodeKind::Cached(ref c) => {
// cached_roots.insert(c.id);
// let (node, template) = cached_set.get(c.id);
// if let Some(template) = template {
// create_with_template(
// cached_set,
// self.change_list,
// registry,
// template,
// node,
// cached_roots,
// );
// } else {
// create(cached_set, change_list, registry, node, cached_roots);
// }
// }
VNode::Component(component) => {
self.change_list
.create_text_node("placeholder for vcomponent");
let id = uuid::Uuid::new_v4();
let id = get_id();
*component.stable_addr.as_ref().borrow_mut() = Some(id);
self.change_list.save_known_root(id);
let caller = Rc::downgrade(&component.caller);
// let broken_caller: Weak<dyn Fn(Context) -> DomTree + 'static> =
// unsafe { std::mem::transmute(caller) };
let scope = Rc::downgrade(&component.ass_scope);
self.lifecycle_events.push_back(LifeCycleEvent::Mount {
caller,
// caller: broken_caller,
caller: Rc::downgrade(&component.caller),
id,
scope
});
}
VNode::Suspended => {
+1 -1
View File
@@ -3,7 +3,7 @@
//! 3rd party renderers are responsible for forming this virtual events from events.
//! The goal here is to provide a consistent event interface across all renderer types.
//!
//! also... websys is kinda bad for rust-analyzer so we coerce for you automatically :)
//! also... websys integerates poorly with rust analyzer, so we handle that for you automatically.
use crate::innerlude::ScopeIdx;
+14 -42
View File
@@ -88,8 +88,8 @@ impl<'a> VNode<'a> {
VNode::Suspended => {
todo!()
}
VNode::Component(_) => {
todo!()
VNode::Component(c) => {
c.key
}
}
}
@@ -107,27 +107,6 @@ pub struct VElement<'a> {
pub attributes: &'a [Attribute<'a>],
pub children: &'a [VNode<'a>],
pub namespace: Option<&'a str>,
// The HTML tag, such as "div"
// pub tag: &'a str,
// pub tag_name: &'a str,
// pub attributes: &'a [Attribute<'a>],
// todo: hook up listeners
// pub listeners: &'a [Listener<'a>],
// / HTML attributes such as id, class, style, etc
// pub attrs: HashMap<String, String>,
// TODO: @JON Get this to not heap allocate, but rather borrow
// pub attrs: HashMap<&'static str, &'static str>,
// TODO @Jon, re-enable "events"
//
// /// Events that will get added to your real DOM element via `.addEventListener`
// pub events: Events,
// pub events: HashMap<String, ()>,
// /// The children of this `VNode`. So a <div> <em></em> </div> structure would
// /// have a parent div and one child, em.
// pub children: Vec<VNode>,
}
impl<'a> VElement<'a> {
@@ -264,10 +243,14 @@ impl<'a> VText<'a> {
/// Virtual Components for custom user-defined components
/// Only supports the functional syntax
pub type StableScopeAddres = Rc<RefCell<Option<uuid::Uuid>>>;
pub type StableScopeAddres = RefCell<Option<u32>>;
pub type VCompAssociatedScope = RefCell<Option<ScopeIdx>>;
pub struct VComponent<'src> {
pub stable_addr: StableScopeAddres,
pub key: NodeKey,
pub stable_addr: Rc<StableScopeAddres>,
pub ass_scope: Rc<VCompAssociatedScope>,
pub comparator: Rc<dyn Fn(&VComponent) -> bool + 'src>,
pub caller: Rc<dyn for<'r> Fn(Context<'r>) -> DomTree + 'src>,
@@ -276,28 +259,15 @@ pub struct VComponent<'src> {
raw_props: *const (),
// a pointer to the raw fn typ
caller_ref: *const (),
pub user_fc: *const (),
_p: PhantomData<&'src ()>,
}
impl std::fmt::Debug for VComponent<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
Ok(())
}
}
// pub struct Comparator(pub Rc<dyn Fn(&VComponent) -> bool>);
// impl std::fmt::Debug for Comparator {
// fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Ok(())
// }
// }
// pub struct Caller(pub Rc<dyn Fn(Context) -> DomTree>);
// impl std::fmt::Debug for Caller {
// fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Ok(())
// }
// }
impl<'a> VComponent<'a> {
// use the type parameter on props creation and move it into a portable context
@@ -318,7 +288,7 @@ impl<'a> VComponent<'a> {
// Therefore, if the render functions are identical (by address), then so will be
// props type paramter (because it is the same render function). Therefore, we can be
// sure
if caller_ref == other.caller_ref {
if caller_ref == other.user_fc {
let real_other = unsafe { &*(other.raw_props as *const _ as *const P) };
real_other == props
} else {
@@ -333,7 +303,9 @@ impl<'a> VComponent<'a> {
};
Self {
caller_ref,
key: NodeKey::NONE,
ass_scope: Rc::new(RefCell::new(None)),
user_fc: caller_ref,
raw_props: props as *const P as *const _,
_p: PhantomData,
caller: Rc::new(caller),
+4 -20
View File
@@ -94,12 +94,12 @@ pub enum Edit<'src_bump> {
// ========================================================
// push a known node on to the stack
TraverseToKnown {
node: uuid::Uuid,
node: u32,
// node: ScopeIdx,
},
// Add the current top of the stack to the known nodes
MakeKnown {
node: uuid::Uuid,
node: u32,
// node: ScopeIdx,
},
// Remove the current top of the stack from the known nodes
@@ -383,32 +383,16 @@ impl<'a> EditMachine<'a> {
// debug!("emit: remove_event_listener({:?})", event);
}
pub fn save_known_root(&mut self, id: uuid::Uuid) {
// pub fn save_known_root(&mut self, id: ScopeIdx) {
// pub fn save_known_root(&mut self, id: ScopeIdx) {
pub fn save_known_root(&mut self, id: u32) {
log::debug!("emit: save_known_root({:?})", id);
self.emitter.push(Edit::MakeKnown { node: id })
}
pub fn load_known_root(&mut self, id: uuid::Uuid) {
pub fn load_known_root(&mut self, id: u32) {
log::debug!("emit: TraverseToKnown({:?})", id);
self.emitter.push(Edit::TraverseToKnown { node: id })
}
// pub fn save_template(&mut self, id: CacheId) {
// debug_assert!(self.traversal_is_committed());
// debug_assert!(!self.has_template(id));
// // debug!("emit: save_template({:?})", id);
// self.templates.insert(id);
// self.emitter.save_template(id.into());
// }
// pub fn push_template(&mut self, id: CacheId) {
// debug_assert!(self.traversal_is_committed());
// debug_assert!(self.has_template(id));
// // debug!("emit: push_template({:?})", id);
// self.emitter.push_template(id.into());
// }
}
// Keeps track of where we are moving in a DOM tree, and shortens traversal
+10 -7
View File
@@ -96,10 +96,11 @@ impl Scope {
scope: self.myidx,
listeners: &self.listeners,
};
let caller = self.caller.upgrade().expect("Failed to get caller");
todo!()
// todo!()
// Note that the actual modification of the vnode head element occurs during this call
// let _: DomTree = (self.caller.0.as_ref())(ctx);
let _: DomTree = (caller.as_ref())(ctx);
// let _: DomTree = (self.raw_caller)(ctx, &self.props);
/*
@@ -114,11 +115,13 @@ impl Scope {
- Public API cannot drop or destructure VNode
*/
// frame.head_node = node_slot
// .deref()
// .borrow_mut()
// .take()
// .expect("Viewing did not happen");
frame.head_node = node_slot.as_ref()
// .deref()
.borrow_mut()
.take()
.expect("Viewing did not happen");
Ok(())
}
// A safe wrapper around calling listeners
+46 -30
View File
@@ -3,10 +3,7 @@
use crate::{error::Error, innerlude::*};
use crate::{patch::Edit, scope::Scope};
use generational_arena::Arena;
use std::{
any::TypeId,
rc::{Rc, Weak},
};
use std::{any::TypeId, borrow::Borrow, rc::{Rc, Weak}};
use thiserror::private::AsDynError;
// We actually allocate the properties for components in their parent's properties
@@ -82,19 +79,19 @@ impl VirtualDom {
.ok_or_else(|| Error::FatalInternal("Acquring base component should never fail"))?;
component.run_scope()?;
let component = &*component;
// let component = &*component;
// // get raw pointer to the arena
// let very_unsafe_components = &mut self.components as *mut generational_arena::Arena<Scope>;
// get raw pointer to the arena
let very_unsafe_components = &mut self.components as *mut generational_arena::Arena<Scope>;
// {
// let component = self
// .components
// .get(self.base_scope)
// .ok_or_else(|| Error::FatalInternal("Acquring base component should never fail"))?
{
let component = self
.components
.get(self.base_scope)
.ok_or_else(|| Error::FatalInternal("Acquring base component should never fail"))?;
// diff_machine.diff_node(component.old_frame(), component.new_frame());
// }
diff_machine.diff_node(component.old_frame(), component.new_frame());
}
// let p = &mut self.components;
// chew down the the lifecycle events until all dirty nodes are computed
while let Some(event) = diff_machine.lifecycle_events.pop_front() {
@@ -102,31 +99,48 @@ impl VirtualDom {
// A new component has been computed from the diffing algorithm
// create a new component in the arena, run it, move the diffing machine to this new spot, and then diff it
// this will flood the lifecycle queue with new updates
LifeCycleEvent::Mount { caller, id } => {
LifeCycleEvent::Mount { caller, id, scope } => {
log::debug!("Mounting a new component");
diff_machine.change_list.load_known_root(id);
// We're modifying the component arena while holding onto references into the assoiated bump arenas of its children
// those references are stable, even if the component arena moves around in memory, thanks to the bump arenas.
// However, there is no way to convey this to rust, so we need to use unsafe to pierce through the lifetime.
unsafe {
// let p = &mut *(very_unsafe_components);
// let p = &mut self.components;
let p = &mut *(very_unsafe_components);
// todo, hook up the parent/child indexes properly
let idx = self.components.insert_with(|f| Scope::new(caller, f, None));
let c = self.components.get_mut(idx).unwrap();
// let idx = p.insert_with(|f| Scope::new(caller, f, None));
// let c = p.get_mut(idx).unwrap();
c.run_scope();
// diff_machine.diff_node(c.old_frame(), c.new_frame());
let idx = p.insert_with(|f| Scope::new(caller, f, None));
let c = p.get_mut(idx).unwrap();
let real_scope = scope.upgrade().unwrap();
*real_scope.as_ref().borrow_mut() = Some(idx);
c.run_scope()?;
diff_machine.change_list.load_known_root(id);
diff_machine.diff_node(c.old_frame(), c.new_frame());
}
}
LifeCycleEvent::PropsChanged => {
//
LifeCycleEvent::PropsChanged { caller, id, scope } => {
let idx = scope.upgrade().unwrap().as_ref().borrow().unwrap();
// We're modifying the component arena while holding onto references into the assoiated bump arenas of its children
// those references are stable, even if the component arena moves around in memory, thanks to the bump arenas.
// However, there is no way to convey this to rust, so we need to use unsafe to pierce through the lifetime.
unsafe {
let p = &mut *(very_unsafe_components);
// todo, hook up the parent/child indexes properly
// let idx = p.insert_with(|f| Scope::new(caller, f, None));
let c = p.get_mut(idx).unwrap();
c.run_scope()?;
diff_machine.change_list.load_known_root(id);
diff_machine.diff_node(c.old_frame(), c.new_frame());
}
// break 'render;
}
LifeCycleEvent::SameProps => {
LifeCycleEvent::SameProps { caller, id, scope } => {
//
// break 'render;
}
@@ -134,6 +148,7 @@ impl VirtualDom {
//
// break 'render;
}
LifeCycleEvent::Replace { caller, id, .. } => {}
}
// } else {
@@ -176,13 +191,14 @@ impl VirtualDom {
.expect("Borrowing should not fail");
component.call_listener(event);
component.run_scope();
component.run_scope()?;
let mut diff_machine = DiffMachine::new();
// let mut diff_machine = DiffMachine::new(&self.diff_bump);
diff_machine.diff_node(component.old_frame(), component.new_frame());
// diff_machine.diff_node(component.old_frame(), component.new_frame());
Ok(diff_machine.consume())
// Ok(diff_machine.consume())
self.rebuild()
}
}