wip: a few things left, slme cleanup

This commit is contained in:
Jonathan Kelley 2021-11-07 09:58:19 -05:00
parent f33510b13f
commit 289d2f2518
5 changed files with 30 additions and 66 deletions

View file

@ -124,7 +124,7 @@ impl<'bump> DiffState<'bump> {
impl<'bump> ScopeArena { impl<'bump> ScopeArena {
pub fn diff_scope(&'bump self, state: &mut DiffState<'bump>, id: &ScopeId) { pub fn diff_scope(&'bump self, state: &mut DiffState<'bump>, id: &ScopeId) {
if let Some(component) = self.get_scope(&id) { if let Some(component) = self.get_scope(id) {
let (old, new) = (component.wip_head(), component.fin_head()); let (old, new) = (component.wip_head(), component.fin_head());
state.stack.push(DiffInstruction::Diff { new, old }); state.stack.push(DiffInstruction::Diff { new, old });
self.work(state, || false); self.work(state, || false);
@ -221,7 +221,7 @@ impl<'bump> ScopeArena {
state.mutations.replace_with(old_id, nodes_created as u32); state.mutations.replace_with(old_id, nodes_created as u32);
self.remove_nodes(state, Some(old), true); self.remove_nodes(state, Some(old), true);
} else { } else {
if let Some(id) = self.find_first_element_id(state, old) { if let Some(id) = self.find_first_element_id(old) {
state.mutations.replace_with(id, nodes_created as u32); state.mutations.replace_with(id, nodes_created as u32);
} }
self.remove_nodes(state, Some(old), true); self.remove_nodes(state, Some(old), true);
@ -235,12 +235,12 @@ impl<'bump> ScopeArena {
} }
MountType::InsertAfter { other_node } => { MountType::InsertAfter { other_node } => {
let root = self.find_last_element(state, other_node).unwrap(); let root = self.find_last_element(other_node).unwrap();
state.mutations.insert_after(root, nodes_created as u32); state.mutations.insert_after(root, nodes_created as u32);
} }
MountType::InsertBefore { other_node } => { MountType::InsertBefore { other_node } => {
let root = self.find_first_element_id(state, other_node).unwrap(); let root = self.find_first_element_id(other_node).unwrap();
state.mutations.insert_before(root, nodes_created as u32); state.mutations.insert_before(root, nodes_created as u32);
} }
} }
@ -331,7 +331,7 @@ impl<'bump> ScopeArena {
let scope = self.get_scope(&cur_scope_id).unwrap(); let scope = self.get_scope(&cur_scope_id).unwrap();
for listener in *listeners { for listener in *listeners {
self.attach_listener_to_scope(state, listener, scope); self.attach_listener_to_scope(listener, scope);
listener.mounted_node.set(Some(real_id)); listener.mounted_node.set(Some(real_id));
state.mutations.new_event_listener(listener, cur_scope_id); state.mutations.new_event_listener(listener, cur_scope_id);
} }
@ -561,7 +561,7 @@ impl<'bump> ScopeArena {
state.mutations.new_event_listener(new_l, cur_scope_id); state.mutations.new_event_listener(new_l, cur_scope_id);
} }
new_l.mounted_node.set(old_l.mounted_node.get()); new_l.mounted_node.set(old_l.mounted_node.get());
self.attach_listener_to_scope(state, new_l, scope); self.attach_listener_to_scope(new_l, scope);
} }
} else { } else {
for listener in old.listeners { for listener in old.listeners {
@ -572,7 +572,7 @@ impl<'bump> ScopeArena {
for listener in new.listeners { for listener in new.listeners {
listener.mounted_node.set(Some(root)); listener.mounted_node.set(Some(root));
state.mutations.new_event_listener(listener, cur_scope_id); state.mutations.new_event_listener(listener, cur_scope_id);
self.attach_listener_to_scope(state, listener, scope); self.attach_listener_to_scope(listener, scope);
} }
} }
} }
@ -1128,11 +1128,7 @@ impl<'bump> ScopeArena {
// Utilities // Utilities
// ===================== // =====================
fn find_last_element( fn find_last_element(&'bump self, vnode: &'bump VNode<'bump>) -> Option<ElementId> {
&'bump self,
state: &mut DiffState<'bump>,
vnode: &'bump VNode<'bump>,
) -> Option<ElementId> {
let mut search_node = Some(vnode); let mut search_node = Some(vnode);
loop { loop {
@ -1156,11 +1152,7 @@ impl<'bump> ScopeArena {
} }
} }
fn find_first_element_id( fn find_first_element_id(&'bump self, vnode: &'bump VNode<'bump>) -> Option<ElementId> {
&'bump self,
state: &mut DiffState<'bump>,
vnode: &'bump VNode<'bump>,
) -> Option<ElementId> {
let mut search_node = Some(vnode); let mut search_node = Some(vnode);
loop { loop {
@ -1288,12 +1280,7 @@ impl<'bump> ScopeArena {
} }
/// Adds a listener closure to a scope during diff. /// Adds a listener closure to a scope during diff.
fn attach_listener_to_scope( fn attach_listener_to_scope(&'bump self, listener: &'bump Listener<'bump>, scope: &ScopeState) {
&'bump self,
state: &mut DiffState<'bump>,
listener: &'bump Listener<'bump>,
scope: &ScopeState,
) {
let long_listener = unsafe { std::mem::transmute(listener) }; let long_listener = unsafe { std::mem::transmute(listener) };
scope.items.borrow_mut().listeners.push(long_listener) scope.items.borrow_mut().listeners.push(long_listener)
} }

View file

@ -39,14 +39,12 @@ impl<'a, 'b> LazyNodes<'a, 'b> {
where where
F: FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b, F: FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b,
{ {
// there's no way to call FnOnce without a box, so we need to store it in a slot and use static dispatch
let mut slot = Some(_val); let mut slot = Some(_val);
let val = move |f| { let val = move |fac: Option<NodeFactory<'a>>| {
let inn = slot.take().unwrap(); let inner = slot.take().unwrap();
match f { fac.map(inner)
Some(f) => Some(inn(f)),
None => None,
}
}; };
unsafe { LazyNodes::new_inner(val) } unsafe { LazyNodes::new_inner(val) }
@ -125,7 +123,6 @@ impl<'a, 'b> LazyNodes<'a, 'b> {
*dataptr.add(i) = *src_ptr.add(i); *dataptr.add(i) = *src_ptr.add(i);
} }
log::debug!("I am forgetting the contents of the stuff");
std::mem::forget(val); std::mem::forget(val);
Self { Self {
@ -143,7 +140,6 @@ impl<'a, 'b> LazyNodes<'a, 'b> {
StackNodeStorage::Heap(mut lazy) => lazy(Some(f)).unwrap(), StackNodeStorage::Heap(mut lazy) => lazy(Some(f)).unwrap(),
StackNodeStorage::Stack(mut stack) => stack.call(f), StackNodeStorage::Stack(mut stack) => stack.call(f),
} }
// todo drop?
} }
} }
@ -154,25 +150,12 @@ struct LazyStack {
} }
impl LazyStack { impl LazyStack {
unsafe fn as_raw<'a>(&mut self) -> *mut dyn FnOnce(NodeFactory<'a>) -> VNode<'a> {
let LazyStack { buf, .. } = self;
let data = buf.as_ref();
let info_size = mem::size_of::<*mut dyn FnOnce(NodeFactory<'a>) -> VNode<'a>>()
/ mem::size_of::<usize>()
- 1;
let info_ofs = data.len() - info_size;
make_fat_ptr(data[..].as_ptr() as usize, &data[info_ofs..])
}
fn call<'a>(&mut self, f: NodeFactory<'a>) -> VNode<'a> { fn call<'a>(&mut self, f: NodeFactory<'a>) -> VNode<'a> {
let LazyStack { buf, .. } = self; let LazyStack { buf, .. } = self;
let data = buf.as_ref(); let data = buf.as_ref();
let info_size = let info_size =
mem::size_of::<*mut dyn FnOnce(Option<NodeFactory<'a>>) -> Option<VNode<'a>>>() mem::size_of::<*mut dyn FnMut(Option<NodeFactory<'a>>) -> Option<VNode<'a>>>()
/ mem::size_of::<usize>() / mem::size_of::<usize>()
- 1; - 1;
@ -190,13 +173,11 @@ impl LazyStack {
impl Drop for LazyStack { impl Drop for LazyStack {
fn drop(&mut self) { fn drop(&mut self) {
if !self.dropped { if !self.dropped {
log::debug!("manually dropping lazy nodes");
let LazyStack { buf, .. } = self; let LazyStack { buf, .. } = self;
let data = buf.as_ref(); let data = buf.as_ref();
let info_size = mem::size_of::< let info_size = mem::size_of::<
*mut dyn FnOnce(Option<NodeFactory<'_>>) -> Option<VNode<'_>>, *mut dyn FnMut(Option<NodeFactory<'_>>) -> Option<VNode<'_>>,
>() / mem::size_of::<usize>() >() / mem::size_of::<usize>()
- 1; - 1;

View file

@ -177,7 +177,7 @@ impl<'src> VNode<'src> {
pub fn children(&self) -> &[VNode<'src>] { pub fn children(&self) -> &[VNode<'src>] {
match &self { match &self {
VNode::Fragment(f) => &f.children, VNode::Fragment(f) => f.children,
VNode::Component(c) => todo!("children are not accessible through this"), VNode::Component(c) => todo!("children are not accessible through this"),
_ => &[], _ => &[],
} }

View file

@ -45,7 +45,6 @@ impl ScopeArena {
parent_scope: Option<*mut ScopeState>, parent_scope: Option<*mut ScopeState>,
height: u32, height: u32,
subtree: u32, subtree: u32,
sender: UnboundedSender<SchedulerMsg>,
) -> ScopeId { ) -> ScopeId {
if let Some(id) = self.free_scopes.pop() { if let Some(id) = self.free_scopes.pop() {
// have already called drop on it - the slot is still chillin tho // have already called drop on it - the slot is still chillin tho
@ -59,7 +58,7 @@ impl ScopeArena {
let vcomp = unsafe { std::mem::transmute(vcomp as *const VComponent) }; let vcomp = unsafe { std::mem::transmute(vcomp as *const VComponent) };
let new_scope = ScopeState { let new_scope = ScopeState {
sender, sender: self.sender.clone(),
parent_scope, parent_scope,
our_arena_idx: id, our_arena_idx: id,
height, height,

View file

@ -69,7 +69,7 @@ use std::{
pub struct VirtualDom { pub struct VirtualDom {
base_scope: ScopeId, base_scope: ScopeId,
root_props: Rc<dyn Any>, _root_props: Rc<dyn Any>,
// we need to keep the allocation around, but we don't necessarily use it // we need to keep the allocation around, but we don't necessarily use it
_root_caller: Box<dyn Any>, _root_caller: Box<dyn Any>,
@ -156,7 +156,7 @@ impl VirtualDom {
sender: UnboundedSender<SchedulerMsg>, sender: UnboundedSender<SchedulerMsg>,
receiver: UnboundedReceiver<SchedulerMsg>, receiver: UnboundedReceiver<SchedulerMsg>,
) -> Self { ) -> Self {
let mut scopes = ScopeArena::new(sender.clone()); let mut scopes = ScopeArena::new(sender);
let base_scope = scopes.new_with_key( let base_scope = scopes.new_with_key(
// //
@ -166,7 +166,6 @@ impl VirtualDom {
None, None,
0, 0,
0, 0,
sender.clone(),
); );
Self { Self {
@ -175,7 +174,7 @@ impl VirtualDom {
receiver, receiver,
sender, sender,
root_props: todo!(), _root_props: todo!(),
_root_caller: todo!(), _root_caller: todo!(),
pending_messages: VecDeque::new(), pending_messages: VecDeque::new(),
@ -201,7 +200,7 @@ impl VirtualDom {
/// ///
/// ///
pub fn get_scope<'a>(&'a self, id: &ScopeId) -> Option<&'a ScopeState> { pub fn get_scope<'a>(&'a self, id: &ScopeId) -> Option<&'a ScopeState> {
self.scopes.get_scope(&id) self.scopes.get_scope(id)
} }
/// Get an [`UnboundedSender`] handle to the channel used by the scheduler. /// Get an [`UnboundedSender`] handle to the channel used by the scheduler.
@ -265,7 +264,7 @@ impl VirtualDom {
// right now, they're bump allocated so this shouldn't matter anyway - they're not going to move // right now, they're bump allocated so this shouldn't matter anyway - they're not going to move
let unpinned = unsafe { Pin::new_unchecked(task) }; let unpinned = unsafe { Pin::new_unchecked(task) };
if let Poll::Ready(_) = unpinned.poll(cx) { if unpinned.poll(cx).is_ready() {
all_pending = false all_pending = false
} }
} }
@ -331,7 +330,7 @@ impl VirtualDom {
/// ///
/// loop { /// loop {
/// let mut timeout = TimeoutFuture::from_ms(16); /// let mut timeout = TimeoutFuture::from_ms(16);
/// let deadline = move || timeout.now_or_never(); /// let deadline = move || (&mut timeout).now_or_never();
/// ///
/// let mutations = dom.run_with_deadline(deadline).await; /// let mutations = dom.run_with_deadline(deadline).await;
/// ///
@ -346,11 +345,8 @@ impl VirtualDom {
/// applied the edits. /// applied the edits.
/// ///
/// Mutations are the only link between the RealDOM and the VirtualDOM. /// Mutations are the only link between the RealDOM and the VirtualDOM.
pub fn work_with_deadline<'a>( pub fn work_with_deadline(&mut self, mut deadline: impl FnMut() -> bool) -> Vec<Mutations> {
&'a mut self, let mut committed_mutations = vec![];
mut deadline: impl FnMut() -> bool,
) -> Vec<Mutations<'a>> {
let mut committed_mutations = Vec::<Mutations>::new();
while self.has_any_work() { while self.has_any_work() {
while let Ok(Some(msg)) = self.receiver.try_next() { while let Ok(Some(msg)) = self.receiver.try_next() {
@ -375,7 +371,7 @@ impl VirtualDom {
self.pending_messages.push_front(dirty_scope); self.pending_messages.push_front(dirty_scope);
} }
} else { } else {
log::debug!("User event without a targetted ElementId. Unsure how to proceed. {:?}", event); log::debug!("User event without a targetted ElementId. Not currently supported.\nUnsure how to proceed. {:?}", event);
} }
} }
} }
@ -434,7 +430,8 @@ impl VirtualDom {
committed_mutations.push(mutations); committed_mutations.push(mutations);
} else { } else {
todo!("don't have a mechanism to pause work (yet)"); // leave the work in an incomplete state
log::debug!("don't have a mechanism to pause work (yet)");
return committed_mutations; return committed_mutations;
} }
} }
@ -506,7 +503,7 @@ impl VirtualDom {
pub fn hard_diff<'a>(&'a mut self, scope_id: &ScopeId) -> Option<Mutations<'a>> { pub fn hard_diff<'a>(&'a mut self, scope_id: &ScopeId) -> Option<Mutations<'a>> {
log::debug!("hard diff {:?}", scope_id); log::debug!("hard diff {:?}", scope_id);
if self.run_scope(&scope_id) { if self.run_scope(scope_id) {
let mut diff_machine = DiffState::new(Mutations::new()); let mut diff_machine = DiffState::new(Mutations::new());
diff_machine.force_diff = true; diff_machine.force_diff = true;