|
@@ -19,13 +19,19 @@ impl VNode {
|
|
mut to: Option<&mut impl WriteMutations>,
|
|
mut to: Option<&mut impl WriteMutations>,
|
|
) {
|
|
) {
|
|
// The node we are diffing from should always be mounted
|
|
// The node we are diffing from should always be mounted
|
|
- debug_assert!(dom.mounts.get(self.mount.get().0).is_some() || to.is_none());
|
|
|
|
|
|
+ debug_assert!(
|
|
|
|
+ dom.runtime
|
|
|
|
+ .mounts
|
|
|
|
+ .borrow()
|
|
|
|
+ .get(self.mount.get().0)
|
|
|
|
+ .is_some()
|
|
|
|
+ || to.is_none()
|
|
|
|
+ );
|
|
|
|
|
|
// If the templates are different, we need to replace the entire template
|
|
// If the templates are different, we need to replace the entire template
|
|
if self.template != new.template {
|
|
if self.template != new.template {
|
|
let mount_id = self.mount.get();
|
|
let mount_id = self.mount.get();
|
|
- let mount = &dom.mounts[mount_id.0];
|
|
|
|
- let parent = mount.parent;
|
|
|
|
|
|
+ let parent = dom.get_mounted_parent(mount_id);
|
|
return self.replace(std::slice::from_ref(new), parent, dom, to);
|
|
return self.replace(std::slice::from_ref(new), parent, dom, to);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -62,7 +68,8 @@ impl VNode {
|
|
new.mount.set(mount_id);
|
|
new.mount.set(mount_id);
|
|
|
|
|
|
if mount_id.mounted() {
|
|
if mount_id.mounted() {
|
|
- let mount = &mut dom.mounts[mount_id.0];
|
|
|
|
|
|
+ let mut mounts = dom.runtime.mounts.borrow_mut();
|
|
|
|
+ let mount = &mut mounts[mount_id.0];
|
|
|
|
|
|
// Update the reference to the node for bubbling events
|
|
// Update the reference to the node for bubbling events
|
|
mount.node = new.clone_mounted();
|
|
mount.node = new.clone_mounted();
|
|
@@ -83,8 +90,8 @@ impl VNode {
|
|
(Text(old), Text(new)) => {
|
|
(Text(old), Text(new)) => {
|
|
// Diffing text is just a side effect, if we are diffing suspended nodes and are not outputting mutations, we can skip it
|
|
// Diffing text is just a side effect, if we are diffing suspended nodes and are not outputting mutations, we can skip it
|
|
if let Some(to) = to {
|
|
if let Some(to) = to {
|
|
- let mount = &dom.mounts[mount.0];
|
|
|
|
- self.diff_vtext(to, mount, idx, old, new)
|
|
|
|
|
|
+ let id = ElementId(dom.get_mounted_dyn_node(mount, idx));
|
|
|
|
+ self.diff_vtext(to, id, old, new)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
(Placeholder(_), Placeholder(_)) => {}
|
|
(Placeholder(_), Placeholder(_)) => {}
|
|
@@ -95,7 +102,7 @@ impl VNode {
|
|
Some(self.reference_to_dynamic_node(mount, idx)),
|
|
Some(self.reference_to_dynamic_node(mount, idx)),
|
|
),
|
|
),
|
|
(Component(old), Component(new)) => {
|
|
(Component(old), Component(new)) => {
|
|
- let scope_id = ScopeId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
|
|
|
|
|
|
+ let scope_id = ScopeId(dom.get_mounted_dyn_node(mount, idx));
|
|
self.diff_vcomponent(
|
|
self.diff_vcomponent(
|
|
mount,
|
|
mount,
|
|
idx,
|
|
idx,
|
|
@@ -114,20 +121,20 @@ impl VNode {
|
|
// Mark the mount as unused. When a scope is created, it reads the mount and
|
|
// Mark the mount as unused. When a scope is created, it reads the mount and
|
|
// if it is the placeholder value, it will create the scope, otherwise it will
|
|
// if it is the placeholder value, it will create the scope, otherwise it will
|
|
// reuse the scope
|
|
// reuse the scope
|
|
- let old_mount = dom.mounts[mount.0].mounted_dynamic_nodes[idx];
|
|
|
|
- dom.mounts[mount.0].mounted_dynamic_nodes[idx] = usize::MAX;
|
|
|
|
|
|
+ let old_mount = dom.get_mounted_dyn_node(mount, idx);
|
|
|
|
+ dom.set_mounted_dyn_node(mount, idx, usize::MAX);
|
|
|
|
|
|
let new_nodes_on_stack =
|
|
let new_nodes_on_stack =
|
|
self.create_dynamic_node(new, mount, idx, dom, to.as_deref_mut());
|
|
self.create_dynamic_node(new, mount, idx, dom, to.as_deref_mut());
|
|
|
|
|
|
// Restore the mount for the scope we are removing
|
|
// Restore the mount for the scope we are removing
|
|
- let new_mount = dom.mounts[mount.0].mounted_dynamic_nodes[idx];
|
|
|
|
- dom.mounts[mount.0].mounted_dynamic_nodes[idx] = old_mount;
|
|
|
|
|
|
+ let new_mount = dom.get_mounted_dyn_node(mount, idx);
|
|
|
|
+ dom.set_mounted_dyn_node(mount, idx, old_mount);
|
|
|
|
|
|
self.remove_dynamic_node(mount, dom, to, true, idx, old, Some(new_nodes_on_stack));
|
|
self.remove_dynamic_node(mount, dom, to, true, idx, old, Some(new_nodes_on_stack));
|
|
|
|
|
|
// Restore the mount for the node we created
|
|
// Restore the mount for the node we created
|
|
- dom.mounts[mount.0].mounted_dynamic_nodes[idx] = new_mount;
|
|
|
|
|
|
+ dom.set_mounted_dyn_node(mount, idx, new_mount);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
}
|
|
}
|
|
@@ -143,12 +150,14 @@ impl VNode {
|
|
}
|
|
}
|
|
|
|
|
|
pub(crate) fn find_first_element(&self, dom: &VirtualDom) -> ElementId {
|
|
pub(crate) fn find_first_element(&self, dom: &VirtualDom) -> ElementId {
|
|
- let mount = &dom.mounts[self.mount.get().0];
|
|
|
|
|
|
+ let mount_id = self.mount.get();
|
|
let first = match self.get_dynamic_root_node_and_id(0) {
|
|
let first = match self.get_dynamic_root_node_and_id(0) {
|
|
// This node is static, just get the root id
|
|
// This node is static, just get the root id
|
|
- None => mount.root_ids[0],
|
|
|
|
|
|
+ None => dom.get_mounted_root_node(mount_id, 0),
|
|
// If it is dynamic and shallow, grab the id from the mounted dynamic nodes
|
|
// If it is dynamic and shallow, grab the id from the mounted dynamic nodes
|
|
- Some((idx, Placeholder(_) | Text(_))) => ElementId(mount.mounted_dynamic_nodes[idx]),
|
|
|
|
|
|
+ Some((idx, Placeholder(_) | Text(_))) => {
|
|
|
|
+ ElementId(dom.get_mounted_dyn_node(mount_id, idx))
|
|
|
|
+ }
|
|
// The node is a fragment, so we need to find the first element in the fragment
|
|
// The node is a fragment, so we need to find the first element in the fragment
|
|
Some((_, Fragment(children))) => {
|
|
Some((_, Fragment(children))) => {
|
|
let child = children.first().unwrap();
|
|
let child = children.first().unwrap();
|
|
@@ -156,7 +165,7 @@ impl VNode {
|
|
}
|
|
}
|
|
// The node is a component, so we need to find the first element in the component
|
|
// The node is a component, so we need to find the first element in the component
|
|
Some((id, Component(_))) => {
|
|
Some((id, Component(_))) => {
|
|
- let scope = ScopeId(mount.mounted_dynamic_nodes[id]);
|
|
|
|
|
|
+ let scope = ScopeId(dom.get_mounted_dyn_node(mount_id, id));
|
|
dom.get_scope(scope)
|
|
dom.get_scope(scope)
|
|
.unwrap()
|
|
.unwrap()
|
|
.root_node()
|
|
.root_node()
|
|
@@ -171,13 +180,15 @@ impl VNode {
|
|
}
|
|
}
|
|
|
|
|
|
pub(crate) fn find_last_element(&self, dom: &VirtualDom) -> ElementId {
|
|
pub(crate) fn find_last_element(&self, dom: &VirtualDom) -> ElementId {
|
|
- let mount = &dom.mounts[self.mount.get().0];
|
|
|
|
|
|
+ let mount_id = self.mount.get();
|
|
let last_root_index = self.template.roots.len() - 1;
|
|
let last_root_index = self.template.roots.len() - 1;
|
|
let last = match self.get_dynamic_root_node_and_id(last_root_index) {
|
|
let last = match self.get_dynamic_root_node_and_id(last_root_index) {
|
|
// This node is static, just get the root id
|
|
// This node is static, just get the root id
|
|
- None => mount.root_ids[last_root_index],
|
|
|
|
|
|
+ None => dom.get_mounted_root_node(mount_id, last_root_index),
|
|
// If it is dynamic and shallow, grab the id from the mounted dynamic nodes
|
|
// If it is dynamic and shallow, grab the id from the mounted dynamic nodes
|
|
- Some((idx, Placeholder(_) | Text(_))) => ElementId(mount.mounted_dynamic_nodes[idx]),
|
|
|
|
|
|
+ Some((idx, Placeholder(_) | Text(_))) => {
|
|
|
|
+ ElementId(dom.get_mounted_dyn_node(mount_id, idx))
|
|
|
|
+ }
|
|
// The node is a fragment, so we need to find the first element in the fragment
|
|
// The node is a fragment, so we need to find the first element in the fragment
|
|
Some((_, Fragment(children))) => {
|
|
Some((_, Fragment(children))) => {
|
|
let child = children.first().unwrap();
|
|
let child = children.first().unwrap();
|
|
@@ -185,7 +196,7 @@ impl VNode {
|
|
}
|
|
}
|
|
// The node is a component, so we need to find the first element in the component
|
|
// The node is a component, so we need to find the first element in the component
|
|
Some((id, Component(_))) => {
|
|
Some((id, Component(_))) => {
|
|
- let scope = ScopeId(mount.mounted_dynamic_nodes[id]);
|
|
|
|
|
|
+ let scope = ScopeId(dom.get_mounted_dyn_node(mount_id, id));
|
|
dom.get_scope(scope)
|
|
dom.get_scope(scope)
|
|
.unwrap()
|
|
.unwrap()
|
|
.root_node()
|
|
.root_node()
|
|
@@ -202,16 +213,8 @@ impl VNode {
|
|
/// Diff the two text nodes
|
|
/// Diff the two text nodes
|
|
///
|
|
///
|
|
/// This just sets the text of the node if it's different.
|
|
/// This just sets the text of the node if it's different.
|
|
- fn diff_vtext(
|
|
|
|
- &self,
|
|
|
|
- to: &mut impl WriteMutations,
|
|
|
|
- mount: &VNodeMount,
|
|
|
|
- idx: usize,
|
|
|
|
- left: &VText,
|
|
|
|
- right: &VText,
|
|
|
|
- ) {
|
|
|
|
|
|
+ fn diff_vtext(&self, to: &mut impl WriteMutations, id: ElementId, left: &VText, right: &VText) {
|
|
if left.value != right.value {
|
|
if left.value != right.value {
|
|
- let id = ElementId(mount.mounted_dynamic_nodes[idx]);
|
|
|
|
to.set_node_text(&right.value, id);
|
|
to.set_node_text(&right.value, id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -291,7 +294,7 @@ impl VNode {
|
|
|
|
|
|
if destroy_component_state {
|
|
if destroy_component_state {
|
|
// Remove the mount information
|
|
// Remove the mount information
|
|
- dom.mounts.remove(mount.0);
|
|
|
|
|
|
+ dom.runtime.mounts.borrow_mut().remove(mount.0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -318,8 +321,7 @@ impl VNode {
|
|
replace_with.filter(|_| last_node),
|
|
replace_with.filter(|_| last_node),
|
|
);
|
|
);
|
|
} else if let Some(to) = to.as_deref_mut() {
|
|
} else if let Some(to) = to.as_deref_mut() {
|
|
- let mount = &dom.mounts[mount.0];
|
|
|
|
- let id = mount.root_ids[idx];
|
|
|
|
|
|
+ let id = dom.get_mounted_root_node(mount, idx);
|
|
if let (true, Some(replace_with)) = (last_node, replace_with) {
|
|
if let (true, Some(replace_with)) = (last_node, replace_with) {
|
|
to.replace_node_with(id, replace_with);
|
|
to.replace_node_with(id, replace_with);
|
|
} else {
|
|
} else {
|
|
@@ -366,11 +368,11 @@ impl VNode {
|
|
) {
|
|
) {
|
|
match node {
|
|
match node {
|
|
Component(_comp) => {
|
|
Component(_comp) => {
|
|
- let scope_id = ScopeId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
|
|
|
|
|
|
+ let scope_id = ScopeId(dom.get_mounted_dyn_node(mount, idx));
|
|
dom.remove_component_node(to, destroy_component_state, scope_id, replace_with);
|
|
dom.remove_component_node(to, destroy_component_state, scope_id, replace_with);
|
|
}
|
|
}
|
|
Text(_) | Placeholder(_) => {
|
|
Text(_) | Placeholder(_) => {
|
|
- let id = ElementId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
|
|
|
|
|
|
+ let id = ElementId(dom.get_mounted_dyn_node(mount, idx));
|
|
if let Some(to) = to {
|
|
if let Some(to) = to {
|
|
if let Some(replace_with) = replace_with {
|
|
if let Some(replace_with) = replace_with {
|
|
to.replace_node_with(id, replace_with);
|
|
to.replace_node_with(id, replace_with);
|
|
@@ -400,7 +402,7 @@ impl VNode {
|
|
}
|
|
}
|
|
|
|
|
|
// only reclaim the new element if it's different from the previous one
|
|
// only reclaim the new element if it's different from the previous one
|
|
- let new_id = dom.mounts[mount.0].mounted_attributes[idx];
|
|
|
|
|
|
+ let new_id = dom.get_mounted_dyn_attr(mount, idx);
|
|
if Some(new_id) != next_id {
|
|
if Some(new_id) != next_id {
|
|
dom.reclaim(new_id);
|
|
dom.reclaim(new_id);
|
|
next_id = Some(new_id);
|
|
next_id = Some(new_id);
|
|
@@ -423,7 +425,7 @@ impl VNode {
|
|
{
|
|
{
|
|
let mut old_attributes_iter = old_attrs.iter().peekable();
|
|
let mut old_attributes_iter = old_attrs.iter().peekable();
|
|
let mut new_attributes_iter = new_attrs.iter().peekable();
|
|
let mut new_attributes_iter = new_attrs.iter().peekable();
|
|
- let attribute_id = dom.mounts[mount_id.0].mounted_attributes[idx];
|
|
|
|
|
|
+ let attribute_id = dom.get_mounted_dyn_attr(mount_id, idx);
|
|
let path = self.template.attr_paths[idx];
|
|
let path = self.template.attr_paths[idx];
|
|
|
|
|
|
loop {
|
|
loop {
|
|
@@ -505,7 +507,8 @@ impl VNode {
|
|
path: ElementPath { path },
|
|
path: ElementPath { path },
|
|
mount,
|
|
mount,
|
|
};
|
|
};
|
|
- dom.elements[id.0] = Some(element_ref);
|
|
|
|
|
|
+ let mut elements = dom.runtime.elements.borrow_mut();
|
|
|
|
+ elements[id.0] = Some(element_ref);
|
|
to.create_event_listener(&attribute.name[2..], id);
|
|
to.create_event_listener(&attribute.name[2..], id);
|
|
}
|
|
}
|
|
_ => {
|
|
_ => {
|
|
@@ -526,7 +529,8 @@ impl VNode {
|
|
|
|
|
|
// Initialize the mount information for this vnode if it isn't already mounted
|
|
// Initialize the mount information for this vnode if it isn't already mounted
|
|
if !self.mount.get().mounted() {
|
|
if !self.mount.get().mounted() {
|
|
- let entry = dom.mounts.vacant_entry();
|
|
|
|
|
|
+ let mut mounts = dom.runtime.mounts.borrow_mut();
|
|
|
|
+ let entry = mounts.vacant_entry();
|
|
let mount = MountId(entry.key());
|
|
let mount = MountId(entry.key());
|
|
self.mount.set(mount);
|
|
self.mount.set(mount);
|
|
tracing::trace!(?self, ?mount, "creating template");
|
|
tracing::trace!(?self, ?mount, "creating template");
|
|
@@ -549,7 +553,7 @@ impl VNode {
|
|
// Get the mounted id of this block
|
|
// Get the mounted id of this block
|
|
// At this point, we should have already mounted the block
|
|
// At this point, we should have already mounted the block
|
|
debug_assert!(
|
|
debug_assert!(
|
|
- dom.mounts.contains(
|
|
|
|
|
|
+ dom.runtime.mounts.borrow().contains(
|
|
self.mount
|
|
self.mount
|
|
.get()
|
|
.get()
|
|
.as_usize()
|
|
.as_usize()
|
|
@@ -752,7 +756,7 @@ impl VNode {
|
|
|
|
|
|
for attr in &**attribute {
|
|
for attr in &**attribute {
|
|
self.write_attribute(attribute_path, attr, id, mount, dom, to);
|
|
self.write_attribute(attribute_path, attr, id, mount, dom, to);
|
|
- dom.mounts[mount.0].mounted_attributes[attribute_idx] = id;
|
|
|
|
|
|
+ dom.set_mounted_dyn_attr(mount, attribute_idx, id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -766,7 +770,7 @@ impl VNode {
|
|
) -> ElementId {
|
|
) -> ElementId {
|
|
// Get an ID for this root since it's a real root
|
|
// Get an ID for this root since it's a real root
|
|
let this_id = dom.next_element();
|
|
let this_id = dom.next_element();
|
|
- dom.mounts[mount.0].root_ids[root_idx] = this_id;
|
|
|
|
|
|
+ dom.set_mounted_root_node(mount, root_idx, this_id);
|
|
|
|
|
|
to.load_template(self.template, root_idx, this_id);
|
|
to.load_template(self.template, root_idx, this_id);
|
|
|
|
|
|
@@ -789,7 +793,7 @@ impl VNode {
|
|
) -> ElementId {
|
|
) -> ElementId {
|
|
// This is just the root node. We already know it's id
|
|
// This is just the root node. We already know it's id
|
|
if let [root_idx] = path {
|
|
if let [root_idx] = path {
|
|
- return dom.mounts[mount.0].root_ids[*root_idx as usize];
|
|
|
|
|
|
+ return dom.get_mounted_root_node(mount, *root_idx as usize);
|
|
}
|
|
}
|
|
|
|
|
|
// The node is deeper in the template and we should create a new id for it
|
|
// The node is deeper in the template and we should create a new id for it
|
|
@@ -835,7 +839,7 @@ impl VNode {
|
|
impl MountId {
|
|
impl MountId {
|
|
fn mount_node(self, node_index: usize, dom: &mut VirtualDom) -> ElementId {
|
|
fn mount_node(self, node_index: usize, dom: &mut VirtualDom) -> ElementId {
|
|
let id = dom.next_element();
|
|
let id = dom.next_element();
|
|
- dom.mounts[self.0].mounted_dynamic_nodes[node_index] = id.0;
|
|
|
|
|
|
+ dom.set_mounted_dyn_node(self, node_index, id.0);
|
|
id
|
|
id
|
|
}
|
|
}
|
|
}
|
|
}
|