Skip to content

Commit ecb0bc7

Browse files
committed
less root specific logic
1 parent 0fe2a76 commit ecb0bc7

15 files changed

Lines changed: 343 additions & 375 deletions

File tree

packages/core/src/diff/attributes.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -97,21 +97,25 @@ impl VNode {
9797
to_iter: &mut Peekable<impl Iterator<Item = &'a Attribute>>,
9898
) -> Option<(AttributeKey, Option<&'a Attribute>, Option<&'a Attribute>)> {
9999
match (from_iter.peek().copied(), to_iter.peek().copied()) {
100-
(Some(from), Some(to_attr)) => match Self::compare_attribute_keys(from, to_attr) {
101-
Ordering::Less => {
102-
from_iter.next();
103-
Some((Self::attribute_key(from), Some(from), None))
100+
(Some(from), Some(to_attr)) => {
101+
let from_key = Self::attribute_key(from);
102+
let to_key = Self::attribute_key(to_attr);
103+
match from_key.cmp(&to_key) {
104+
Ordering::Less => {
105+
from_iter.next();
106+
Some((from_key, Some(from), None))
107+
}
108+
Ordering::Greater => {
109+
to_iter.next();
110+
Some((to_key, None, Some(to_attr)))
111+
}
112+
Ordering::Equal => {
113+
from_iter.next();
114+
to_iter.next();
115+
Some((to_key, Some(from), Some(to_attr)))
116+
}
104117
}
105-
Ordering::Greater => {
106-
to_iter.next();
107-
Some((Self::attribute_key(to_attr), None, Some(to_attr)))
108-
}
109-
Ordering::Equal => {
110-
from_iter.next();
111-
to_iter.next();
112-
Some((Self::attribute_key(to_attr), Some(from), Some(to_attr)))
113-
}
114-
},
118+
}
115119
(Some(from), None) => {
116120
from_iter.next();
117121
Some((Self::attribute_key(from), Some(from), None))

packages/core/src/diff/iterator.rs

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,6 @@ impl DiffState<'_, '_, '_, '_> {
380380
lis_sequence.remove(0);
381381
}
382382

383-
let mut mounted_new = Vec::new();
384-
385383
// Every shared child not in the stable LIS will move, so its committed
386384
// position is stale for the rest of this reorder. Mark them all up front
387385
// (O(1) each) so placement scans never anchor on a node that is mid-move,
@@ -416,7 +414,6 @@ impl DiffState<'_, '_, '_, '_> {
416414
new_mounts[*idx] = Some(mount);
417415
self.dom
418416
.set_mounted_fragment_child(new_children, new_offset + *idx, mount);
419-
mounted_new.push(MountedSibling { index: *idx, mount });
420417
}
421418

422419
let last = *lis_sequence.first().unwrap();
@@ -433,7 +430,6 @@ impl DiffState<'_, '_, '_, '_> {
433430
&mut *new_mounts,
434431
new_children,
435432
new_offset,
436-
&mut mounted_new,
437433
);
438434
}
439435

@@ -452,7 +448,6 @@ impl DiffState<'_, '_, '_, '_> {
452448
new_mounts,
453449
new_children,
454450
new_offset,
455-
&mut mounted_new,
456451
);
457452
}
458453
}
@@ -471,7 +466,6 @@ impl DiffState<'_, '_, '_, '_> {
471466
&mut *new_mounts,
472467
new_children,
473468
new_offset,
474-
&mut mounted_new,
475469
);
476470
}
477471

@@ -534,7 +528,6 @@ impl DiffState<'_, '_, '_, '_> {
534528
new_mounts: &mut [Option<MountId>],
535529
new_children: FragmentMountWriter,
536530
new_offset: usize,
537-
mounted_new: &mut Vec<MountedSibling>,
538531
) {
539532
let context = self.context();
540533
let sibling_mount = new_mounts[sibling_idx].expect("sibling");
@@ -549,7 +542,7 @@ impl DiffState<'_, '_, '_, '_> {
549542
crate::MountedVNode::new(&new[sibling_idx], sibling_mount),
550543
self.dom,
551544
)
552-
.or_else(|| insertion_site_in_new_order(edge, new, mounted_new, sibling_idx, self.dom))
545+
.or_else(|| insertion_site_in_new_order(edge, new, new_mounts, sibling_idx, self.dom))
553546
.unwrap_or_else(|| {
554547
insertion_site_at(
555548
edge,
@@ -577,7 +570,6 @@ impl DiffState<'_, '_, '_, '_> {
577570
new_mounts,
578571
new_children,
579572
new_offset,
580-
mounted_new,
581573
&mut replaced_nodes,
582574
)
583575
});
@@ -593,7 +585,6 @@ impl DiffState<'_, '_, '_, '_> {
593585
new_mounts,
594586
new_children,
595587
new_offset,
596-
mounted_new,
597588
&mut replaced_nodes,
598589
);
599590
}
@@ -617,7 +608,6 @@ impl DiffState<'_, '_, '_, '_> {
617608
new_mounts: &mut [Option<MountId>],
618609
new_children: FragmentMountWriter,
619610
new_offset: usize,
620-
mounted_new: &mut Vec<MountedSibling>,
621611
replaced_nodes: &mut Vec<(&'a VNode, MountId)>,
622612
) -> usize {
623613
let range_start = range.start;
@@ -658,10 +648,6 @@ impl DiffState<'_, '_, '_, '_> {
658648
new_mounts[new_index] = Some(mount);
659649
self.dom
660650
.set_mounted_fragment_child(new_children, new_offset + new_index, mount);
661-
mounted_new.push(MountedSibling {
662-
index: new_index,
663-
mount,
664-
});
665651
nodes += created_nodes;
666652
}
667653
nodes
@@ -732,44 +718,30 @@ impl DiffState<'_, '_, '_, '_> {
732718
}
733719
}
734720

735-
#[derive(Clone, Copy)]
736-
struct MountedSibling {
737-
index: usize,
738-
mount: MountId,
739-
}
740-
741721
/// Prefer anchors already materialized in the new sibling order.
742722
///
743-
/// Invariant: every entry in `mounted_new` owns a live mount in `new` order. Pending new siblings are
744-
/// not representable in this slice and therefore cannot be used as anchors.
723+
/// Invariant: every `Some` entry in `new_mounts` owns a materialized sibling in new order. Pending
724+
/// new siblings are `None` and therefore cannot be used as anchors.
745725
fn insertion_site_in_new_order(
746726
edge: ElementEdge,
747727
new: &[VNode],
748-
mounted_new: &[MountedSibling],
728+
new_mounts: &[Option<MountId>],
749729
sibling_idx: usize,
750730
dom: &VirtualDom,
751731
) -> Option<InsertionSite> {
752732
match edge {
753-
ElementEdge::First => mounted_new
754-
.iter()
755-
.filter(|sibling| sibling.index >= sibling_idx)
756-
.filter_map(|sibling| {
757-
new[sibling.index]
758-
.find_first_element(sibling.mount, dom)
759-
.map(|id| (sibling.index, id))
760-
})
761-
.min_by_key(|(index, _)| *index)
762-
.map(|(_, id)| InsertionSite::before(id)),
763-
ElementEdge::Last => mounted_new
764-
.iter()
765-
.filter(|sibling| sibling.index <= sibling_idx)
766-
.filter_map(|sibling| {
767-
new[sibling.index]
768-
.find_last_element(sibling.mount, dom)
769-
.map(|id| (sibling.index, id))
770-
})
771-
.max_by_key(|(index, _)| *index)
772-
.map(|(_, id)| InsertionSite::after(id)),
733+
ElementEdge::First => (sibling_idx..new.len()).find_map(|index| {
734+
let mount = new_mounts[index]?;
735+
new[index]
736+
.find_first_element(mount, dom)
737+
.map(InsertionSite::before)
738+
}),
739+
ElementEdge::Last => (0..=sibling_idx).rev().find_map(|index| {
740+
let mount = new_mounts[index]?;
741+
new[index]
742+
.find_last_element(mount, dom)
743+
.map(InsertionSite::after)
744+
}),
773745
}
774746
}
775747

packages/core/src/diff/node.rs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::{
88
context::{DiffFrame, DiffState},
99
placement::{
1010
ElementEdge, InsertionSite, at_site, create_at_site_with_mounts, insertion_site_at,
11-
insertion_site_for_mounted_anchor, insertion_site_for_mounted_child,
12-
insertion_site_for_slot,
11+
insertion_site_for_mounted_child, insertion_site_for_slot,
1312
},
1413
template::{DynamicAnchor, DynamicNodeSlot},
1514
},
@@ -746,7 +745,7 @@ impl VNode {
746745
"background mounts must be created without renderer writes"
747746
);
748747

749-
let nodes_created = self.materialize_template_roots(mount, state, reuse_existing_mounts);
748+
let nodes_created = self.materialize_static_roots(mount, state);
750749
self.fill_dynamic_slots(mount, state, reuse_existing_mounts);
751750

752751
state.dom.commit_mount(mount, self);
@@ -758,26 +757,16 @@ impl VNode {
758757
}
759758

760759
impl VNode {
761-
fn materialize_template_roots(
760+
fn materialize_static_roots(
762761
&self,
763762
mount: MountId,
764763
state: &mut DiffState<'_, '_, '_, '_>,
765-
reuse_existing_mounts: bool,
766764
) -> usize {
767765
let mut nodes_created = 0;
768766

769767
for child in self.children() {
770768
match child {
771-
VNodeChild::Dynamic(anchor) => {
772-
for slot in anchor.nodes() {
773-
nodes_created += self.create_dynamic_node_inner(
774-
mount,
775-
slot.index(),
776-
state,
777-
reuse_existing_mounts,
778-
);
779-
}
780-
}
769+
VNodeChild::Dynamic(_) => {}
781770
VNodeChild::Element(element) => {
782771
if let Some(to) = state.to.as_deref_mut() {
783772
let root_anchor_idx = element.anchor_index().expect("root element");
@@ -813,7 +802,7 @@ impl VNode {
813802
self.write_attr_anchor(mount, anchor, state.dom, to);
814803
}
815804

816-
if anchor.nodes().len() > 0 && anchor.parent_element_op_index().is_some() {
805+
if anchor.nodes().len() > 0 {
817806
self.load_dynamic_anchor(mount, anchor, state, reuse_existing_mounts);
818807
}
819808
}
@@ -907,8 +896,9 @@ impl VNode {
907896
return;
908897
}
909898

899+
let first_slot = anchor.nodes().next().expect("dynamic anchor has nodes");
910900
let context = state.context();
911-
let site = insertion_site_for_mounted_anchor(mount, anchor, state.dom);
901+
let site = insertion_site_for_slot(mount, first_slot, state.dom, context);
912902
let runtime = state.dom.runtime.clone();
913903
let dom = &mut *state.dom;
914904
let to = state.to.as_deref_mut().expect("writer checked");
@@ -982,16 +972,11 @@ impl VNode {
982972
dom: &mut VirtualDom,
983973
to: &mut dyn WriteMutations,
984974
) {
985-
let root_path = self.template.anchors()[root_anchor_idx].static_path();
986975
let mut assigned_paths = Vec::new();
987976

988-
for (anchor_idx, anchor) in self.template.anchors().iter().enumerate() {
989-
let Some(path) = anchor_static_target(anchor) else {
990-
continue;
991-
};
992-
if !path.starts_with(root_path) {
993-
continue;
994-
}
977+
for target in self.static_anchor_targets_under(root_anchor_idx) {
978+
let anchor_idx = target.anchor_index;
979+
let path = target.path;
995980

996981
if let Some((_, id)) = assigned_paths
997982
.iter()

0 commit comments

Comments
 (0)