feat: improve safety

This commit is contained in:
Jonathan Kelley committed 2021-10-25 15:05:17 -04:00
1 parent 601078f9cf
commit fda2ebc2a2
12 files changed
+113 -36

No files matched your search

+39 -19
View File
@@ -221,12 +221,12 @@ impl<'bump> DiffMachine<'bump> {
MountType::Replace { old } => {
if let Some(old_id) = old.try_mounted_id() {
self.mutations.replace_with(old_id, nodes_created as u32);
self.remove_nodes(Some(old));
self.remove_nodes(Some(old), true);
} else {
if let Some(id) = self.find_first_element_id(old) {
self.mutations.replace_with(id, nodes_created as u32);
}
self.remove_nodes(Some(old));
self.remove_nodes(Some(old), true);
}
}
@@ -369,7 +369,11 @@ impl<'bump> DiffMachine<'bump> {
let new_component = self.vdom.get_scope_mut(new_idx).unwrap();
log::debug!("initializing component {:?}", new_idx);
log::debug!(
"initializing component {:?} with height {:?}",
new_idx,
parent_scope.height + 1
);
// Run the scope for one iteration to initialize it
if new_component.run_scope(self.vdom) {
@@ -614,7 +618,7 @@ impl<'bump> DiffMachine<'bump> {
self.stack.create_children(new, MountType::Append);
}
(_, []) => {
self.remove_nodes(old);
self.remove_nodes(old, true);
}
([VNode::Anchor(old_anchor)], [VNode::Anchor(new_anchor)]) => {
old_anchor.dom_id.set(new_anchor.dom_id.get());
@@ -667,7 +671,7 @@ impl<'bump> DiffMachine<'bump> {
use std::cmp::Ordering;
match old.len().cmp(&new.len()) {
Ordering::Greater => self.remove_nodes(&old[new.len()..]),
Ordering::Greater => self.remove_nodes(&old[new.len()..], true),
Ordering::Less => {
self.stack.create_children(
&new[old.len()..],
@@ -750,7 +754,7 @@ impl<'bump> DiffMachine<'bump> {
);
if new_middle.is_empty() {
// remove the old elements
self.remove_nodes(old_middle);
self.remove_nodes(old_middle, true);
} else if old_middle.is_empty() {
// there were no old elements, so just create the new elements
// we need to find the right "foothold" though - we shouldnt use the "append" at all
@@ -825,7 +829,7 @@ impl<'bump> DiffMachine<'bump> {
// And if that was all of the new children, then remove all of the remaining
// old children and we're finished.
if left_offset == new.len() {
self.remove_nodes(&old[left_offset..]);
self.remove_nodes(&old[left_offset..], true);
return None;
}
@@ -1070,7 +1074,7 @@ impl<'bump> DiffMachine<'bump> {
new: &'bump VNode<'bump>,
) {
if let Some(first_old) = old.get(0) {
self.remove_nodes(&old[1..]);
self.remove_nodes(&old[1..], true);
self.stack
.create_node(new, MountType::Replace { old: first_old });
} else {
@@ -1080,42 +1084,58 @@ impl<'bump> DiffMachine<'bump> {
/// schedules nodes for garbage collection and pushes "remove" to the mutation stack
/// remove can happen whenever
fn remove_nodes(&mut self, nodes: impl IntoIterator<Item = &'bump VNode<'bump>>) {
fn remove_nodes(
&mut self,
nodes: impl IntoIterator<Item = &'bump VNode<'bump>>,
gen_muts: bool,
) {
// or cache the vec on the diff machine
for node in nodes {
match node {
VNode::Text(t) => {
if let Some(id) = t.dom_id.get() {
let id = t.dom_id.get().unwrap();
self.vdom.collect_garbage(id);
if gen_muts {
self.mutations.remove(id.as_u64());
self.vdom.collect_garbage(id);
}
}
VNode::Suspended(s) => {
if let Some(id) = s.dom_id.get() {
let id = s.dom_id.get().unwrap();
self.vdom.collect_garbage(id);
if gen_muts {
self.mutations.remove(id.as_u64());
self.vdom.collect_garbage(id);
}
}
VNode::Anchor(a) => {
if let Some(id) = a.dom_id.get() {
let id = a.dom_id.get().unwrap();
self.vdom.collect_garbage(id);
if gen_muts {
self.mutations.remove(id.as_u64());
self.vdom.collect_garbage(id);
}
}
VNode::Element(e) => {
if let Some(id) = e.dom_id.get() {
let id = e.dom_id.get().unwrap();
if gen_muts {
self.mutations.remove(id.as_u64());
}
self.remove_nodes(e.children, false);
}
VNode::Fragment(f) => {
self.remove_nodes(f.children);
self.remove_nodes(f.children, gen_muts);
}
VNode::Component(c) => {
let scope_id = c.associated_scope.get().unwrap();
let scope = self.vdom.get_scope_mut(scope_id).unwrap();
let root = scope.root_node();
self.remove_nodes(Some(root));
self.remove_nodes(Some(root), gen_muts);
log::debug!("Destroying scope {:?}", scope_id);
let mut s = self.vdom.try_remove(scope_id).unwrap();
s.hooks.clear_hooks();
}
@@ -1132,7 +1152,7 @@ impl<'bump> DiffMachine<'bump> {
new: &'bump [VNode<'bump>],
) {
if let Some(first_old) = old.get(0) {
self.remove_nodes(&old[1..]);
self.remove_nodes(&old[1..], true);
self.stack
.create_children(new, MountType::Replace { old: first_old })
} else {