feat: more and more sophisticated diff
This commit is contained in:
1 parent
d618092e9d
commit
1749eba8eb
3 files changed
+76
-58
No files matched your search
+70
-56
@@ -334,53 +334,14 @@ impl<'real, 'bump> DiffMachine<'real, 'bump> {
|
||||
| VNodeKind::Element(_)
|
||||
| VNodeKind::Anchor(_),
|
||||
) => {
|
||||
todo!();
|
||||
// log::info!(
|
||||
// "taking the awkard diffing path {:#?}, {:#?}",
|
||||
// old_node,
|
||||
// new_node
|
||||
// );
|
||||
// // currently busted for components - need to fid
|
||||
// let root = old_node.dom_id.get().expect(&format!(
|
||||
// "Should not be diffing old nodes that were never assigned, {:#?}",
|
||||
// old_node
|
||||
// ));
|
||||
// // Choose the node to use as the placeholder for replacewith
|
||||
// let back_node_id = match old_node.kind {
|
||||
// // We special case these two types to avoid allocating the small-vecs
|
||||
// VNodeKind::Element(_) | VNodeKind::Text(_) => root,
|
||||
|
||||
// _ => {
|
||||
// let mut old_iter = RealChildIterator::new(old_node, &self.vdom);
|
||||
|
||||
// let back_node = old_iter
|
||||
// .next()
|
||||
// .expect("Empty fragments should generate a placeholder.");
|
||||
|
||||
// // remove any leftovers
|
||||
// for to_remove in old_iter {
|
||||
// self.edit_push_root(to_remove.dom_id().unwrap());
|
||||
// self.edit_remove();
|
||||
// }
|
||||
|
||||
// back_node.dom_id().unwrap()
|
||||
// }
|
||||
// };
|
||||
|
||||
// // replace the placeholder or first node with the nodes generated from the "new"
|
||||
// self.edit_push_root(back_node_id);
|
||||
// let meta = self.create_vnode(new_node);
|
||||
// self.edit_replace_with(meta.added_to_stack);
|
||||
|
||||
// // todo use the is_static metadata to update this subtree
|
||||
self.replace_many_with_many([old_node], new_node);
|
||||
}
|
||||
|
||||
// TODO
|
||||
(VNodeKind::Suspended(node), new) => todo!(),
|
||||
(old, VNodeKind::Suspended { .. }) => {
|
||||
// a node that was once real is now suspended
|
||||
//
|
||||
}
|
||||
(VNodeKind::Suspended(_), new) => todo!(),
|
||||
|
||||
// a node that was once real is now suspended
|
||||
(old, VNodeKind::Suspended(_)) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,17 +597,28 @@ impl<'real, 'bump> DiffMachine<'real, 'bump> {
|
||||
let first_new = &new[0];
|
||||
|
||||
match (&first_old.kind, &first_new.kind) {
|
||||
// Anchors can only appear in empty fragments
|
||||
(VNodeKind::Anchor(old_anchor), VNodeKind::Anchor(new_anchor)) => {
|
||||
old_anchor.dom_id.set(new_anchor.dom_id.get());
|
||||
}
|
||||
|
||||
// Replace the anchor with whatever new nodes are coming down the pipe
|
||||
(VNodeKind::Anchor(anchor), _) => {
|
||||
// replace new anchor with many
|
||||
todo!();
|
||||
self.edit_push_root(anchor.dom_id.get().unwrap());
|
||||
let mut added = 0;
|
||||
for el in new {
|
||||
let meta = self.create_vnode(el);
|
||||
added += meta.added_to_stack;
|
||||
}
|
||||
self.edit_replace_with(1, added);
|
||||
}
|
||||
|
||||
// Replace whatever nodes are sitting there with the anchor
|
||||
(_, VNodeKind::Anchor(anchor)) => {
|
||||
// replace many with new anchor
|
||||
todo!();
|
||||
self.replace_many_with_many(old, first_new);
|
||||
}
|
||||
|
||||
// Use the complex diff algorithm to diff the nodes
|
||||
_ => {
|
||||
let new_is_keyed = new[0].key.is_some();
|
||||
let old_is_keyed = old[0].key.is_some();
|
||||
@@ -1175,6 +1147,53 @@ impl<'real, 'bump> DiffMachine<'real, 'bump> {
|
||||
// self.remove_self_and_next_siblings();
|
||||
}
|
||||
|
||||
fn replace_many_with_many(
|
||||
&mut self,
|
||||
old_node: impl IntoIterator<Item = &'bump VNode<'bump>>,
|
||||
// old_node: &'bump VNode<'bump>,
|
||||
new_node: &'bump VNode<'bump>,
|
||||
) {
|
||||
let mut nodes_to_replace = Vec::new();
|
||||
let mut nodes_to_search = old_node.into_iter().collect::<Vec<_>>();
|
||||
let mut scopes_obliterated = Vec::new();
|
||||
while let Some(node) = nodes_to_search.pop() {
|
||||
match &node.kind {
|
||||
// the ones that have a direct id
|
||||
VNodeKind::Text(el) => nodes_to_replace.push(el.dom_id.get().unwrap()),
|
||||
VNodeKind::Element(el) => nodes_to_replace.push(el.dom_id.get().unwrap()),
|
||||
VNodeKind::Anchor(el) => nodes_to_replace.push(el.dom_id.get().unwrap()),
|
||||
VNodeKind::Suspended(el) => nodes_to_replace.push(el.node.get().unwrap()),
|
||||
|
||||
VNodeKind::Fragment(frag) => {
|
||||
for child in frag.children {
|
||||
nodes_to_search.push(child);
|
||||
}
|
||||
}
|
||||
VNodeKind::Component(el) => {
|
||||
let scope_id = el.ass_scope.get().unwrap();
|
||||
let scope = self.get_scope(&scope_id).unwrap();
|
||||
let root = scope.root();
|
||||
nodes_to_search.push(root);
|
||||
scopes_obliterated.push(scope_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let n = nodes_to_replace.len();
|
||||
for node in nodes_to_replace {
|
||||
self.edit_push_root(node);
|
||||
}
|
||||
|
||||
let meta = self.create_vnode(new_node);
|
||||
|
||||
self.edit_replace_with(n as u32, meta.added_to_stack);
|
||||
|
||||
// obliterate!
|
||||
for scope in scopes_obliterated {
|
||||
self.destroy_scopes(scope);
|
||||
}
|
||||
}
|
||||
|
||||
fn create_garbage(&mut self, node: &'bump VNode<'bump>) {
|
||||
let cur_scope = self.current_scope().unwrap();
|
||||
let scope = self.get_scope(&cur_scope).unwrap();
|
||||
@@ -1194,16 +1213,11 @@ impl<'real, 'bump> DiffMachine<'real, 'bump> {
|
||||
) {
|
||||
self.edit_push_root(anchor);
|
||||
let meta = self.create_vnode(new_node);
|
||||
self.edit_replace_with(meta.added_to_stack);
|
||||
self.edit_replace_with(1, meta.added_to_stack);
|
||||
self.create_garbage(old_node);
|
||||
self.edit_pop();
|
||||
}
|
||||
|
||||
// assumes
|
||||
fn remove_many_and_return_the_first_root(&mut self) -> ElementId {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn remove_vnode(&mut self, node: &'bump VNode<'bump>) {
|
||||
match &node.kind {
|
||||
VNodeKind::Text(el) => self.immediately_dispose_garabage(node.direct_id()),
|
||||
@@ -1274,8 +1288,8 @@ impl<'real, 'bump> DiffMachine<'real, 'bump> {
|
||||
|
||||
// replace the n-m node on the stack with the m nodes
|
||||
// ends with the last element of the chain on the top of the stack
|
||||
pub(crate) fn edit_replace_with(&mut self, many: u32) {
|
||||
self.edits.push(ReplaceWith { many });
|
||||
pub(crate) fn edit_replace_with(&mut self, n: u32, m: u32) {
|
||||
self.edits.push(ReplaceWith { n, m });
|
||||
}
|
||||
|
||||
// Remove Nodesfrom the dom
|
||||
|
||||
@@ -24,7 +24,11 @@ pub enum DomEdit<'bump> {
|
||||
many: u32,
|
||||
},
|
||||
ReplaceWith {
|
||||
many: u32,
|
||||
// the first n elements
|
||||
n: u32,
|
||||
|
||||
// the last m elements
|
||||
m: u32,
|
||||
},
|
||||
Remove,
|
||||
RemoveAllChildren,
|
||||
|
||||
@@ -342,7 +342,7 @@ impl VirtualDom {
|
||||
let meta = diff_machine.create_vnode(&*nodes);
|
||||
|
||||
// replace the placeholder with the new nodes we just pushed on the stack
|
||||
diff_machine.edit_replace_with(meta.added_to_stack);
|
||||
diff_machine.edit_replace_with(1, meta.added_to_stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user