@@ -16,8 +16,8 @@ use crate::virtual_dom::{Key, VList, VNode};
1616/// This struct represents a mounted [VList]
1717#[ derive( Debug ) ]
1818pub ( super ) struct BList {
19- /// The reverse (render order) list of child [BNode]s
20- rev_children : Vec < BNode > ,
19+ /// Child [BNode]s in render order
20+ children : Vec < BNode > ,
2121 /// All [BNode]s in the BList have keys
2222 fully_keyed : bool ,
2323 key : Option < Key > ,
@@ -41,7 +41,7 @@ impl Deref for BList {
4141 type Target = Vec < BNode > ;
4242
4343 fn deref ( & self ) -> & Self :: Target {
44- & self . rev_children
44+ & self . children
4545 }
4646}
4747
@@ -119,7 +119,7 @@ impl BNode {
119119 _ => unreachable ! ( "just been set to the variant" ) ,
120120 } ;
121121 let key = b. key ( ) . cloned ( ) ;
122- self_list. rev_children . push ( b) ;
122+ self_list. children . push ( b) ;
123123 self_list. fully_keyed = key. is_some ( ) ;
124124 self_list. key = key;
125125 self_list
@@ -132,7 +132,7 @@ impl BList {
132132 /// Create a new empty [BList]
133133 pub const fn new ( ) -> BList {
134134 BList {
135- rev_children : vec ! [ ] ,
135+ children : vec ! [ ] ,
136136 fully_keyed : true ,
137137 key : None ,
138138 }
@@ -145,7 +145,7 @@ impl BList {
145145
146146 /// Diff and patch unkeyed child lists
147147 ///
148- /// Pairs children by render-order position from the front, so that leading
148+ /// Pairs children front-to-front by render-order position so that leading
149149 /// nodes are always reconciled with themselves when the list grows or
150150 /// shrinks at the tail.
151151 fn apply_unkeyed (
@@ -163,26 +163,20 @@ impl BList {
163163 slot,
164164 } ;
165165
166- // `rights` is stored in reverse render order. Flip to render order so
167- // that simple index-based pairing matches children front-to-front.
168- rights. reverse ( ) ;
169-
170- let left_len = lefts. len ( ) ;
171-
172- // Remove excess old nodes from the END of render order (now the tail).
173- if left_len < rights. len ( ) {
174- for r in rights. drain ( left_len..) {
166+ // Remove excess old nodes from the end of render order.
167+ if lefts. len ( ) < rights. len ( ) {
168+ for r in rights. drain ( lefts. len ( ) ..) {
175169 test_log ! ( "removing: {:?}" , r) ;
176170 r. detach ( root, parent, false ) ;
177171 }
178172 }
179173
180174 let paired_count = rights. len ( ) ; // min(left_len, old_len)
181-
182- // The NodeWriter must process children right-to-left in render order.
175+ let left_len = lefts. len ( ) ;
183176 let mut lefts_rev = lefts. into_iter ( ) . rev ( ) ;
184177
185- // 1. Add excess new nodes at the tail of render order (rightmost first).
178+ // Add excess new nodes at the tail of render order (rightmost first
179+ // for the NodeWriter).
186180 let excess_start = rights. len ( ) ;
187181 for l in lefts_rev
188182 . by_ref ( )
@@ -192,18 +186,14 @@ impl BList {
192186 rights. push ( el) ;
193187 writer = next_writer;
194188 }
195- // Items were pushed right-to-left; flip them to render order.
189+ // Items were pushed right-to-left; flip to render order.
196190 rights[ excess_start..] . reverse ( ) ;
197191
198- // 2. Patch paired nodes right-to-left. lefts_rev now yields positions [paired_count-1 ..
199- // 0]. rights[..paired_count] is in render order, .rev() walks right-to-left.
192+ // Patch paired nodes right-to-left.
200193 for ( l, r) in lefts_rev. zip ( rights[ ..paired_count] . iter_mut ( ) . rev ( ) ) {
201194 writer = writer. patch ( l, r) ;
202195 }
203196
204- // Flip back to reverse render order.
205- rights. reverse ( ) ;
206-
207197 writer. slot
208198 }
209199
@@ -217,7 +207,7 @@ impl BList {
217207 parent : & Element ,
218208 slot : DomSlot ,
219209 left_vdoms : Vec < VNode > ,
220- rev_bundles : & mut Vec < BNode > ,
210+ bundles : & mut Vec < BNode > ,
221211 ) -> DomSlot {
222212 macro_rules! key {
223213 ( $v: expr) => {
@@ -232,10 +222,10 @@ impl BList {
232222 a. zip ( b) . take_while ( |( a, b) | a == b) . count ( )
233223 }
234224
235- // Find first key mismatch from the back
225+ // Find first key mismatch from the back of render order
236226 let matching_len_end = matching_len (
237227 left_vdoms. iter ( ) . map ( |v| key ! ( v) ) . rev ( ) ,
238- rev_bundles . iter ( ) . map ( |v| key ! ( v) ) ,
228+ bundles . iter ( ) . map ( |v| key ! ( v) ) . rev ( ) ,
239229 ) ;
240230
241231 if cfg ! ( debug_assertions) {
@@ -252,9 +242,9 @@ impl BList {
252242
253243 // If there is no key mismatch, apply the unkeyed approach
254244 // Corresponds to adding or removing items from the back of the list
255- if matching_len_end == std:: cmp:: min ( left_vdoms. len ( ) , rev_bundles . len ( ) ) {
245+ if matching_len_end == std:: cmp:: min ( left_vdoms. len ( ) , bundles . len ( ) ) {
256246 // No key changes
257- return Self :: apply_unkeyed ( root, parent_scope, parent, slot, left_vdoms, rev_bundles ) ;
247+ return Self :: apply_unkeyed ( root, parent_scope, parent, slot, left_vdoms, bundles ) ;
258248 }
259249
260250 // We partially drain the new vnodes in several steps.
@@ -265,35 +255,36 @@ impl BList {
265255 parent,
266256 slot,
267257 } ;
268- // Step 1. Diff matching children at the end
258+ // Step 1. Diff matching children at the end of render order
269259 let lefts_to = lefts. len ( ) - matching_len_end;
260+ let bundles_from = bundles. len ( ) - matching_len_end;
270261 for ( l, r) in lefts
271262 . drain ( lefts_to..)
272263 . rev ( )
273- . zip ( rev_bundles [ ..matching_len_end ] . iter_mut ( ) )
264+ . zip ( bundles [ bundles_from.. ] . iter_mut ( ) . rev ( ) )
274265 {
275266 writer = writer. patch ( l, r) ;
276267 }
277268
278269 // Step 2. Diff matching children in the middle, that is between the first and last key
279- // mismatch Find first key mismatch from the front
270+ // mismatch. Find first key mismatch from the front.
280271 let mut matching_len_start = matching_len (
281272 lefts. iter ( ) . map ( |v| key ! ( v) ) ,
282- rev_bundles . iter ( ) . map ( |v| key ! ( v) ) . rev ( ) ,
273+ bundles . iter ( ) . map ( |v| key ! ( v) ) ,
283274 ) ;
284275
285276 // Step 2.1. Splice out the existing middle part and build a lookup by key
286- let rights_to = rev_bundles. len ( ) - matching_len_start;
287- let mut bundle_middle = matching_len_end..rights_to;
277+ let mut bundle_middle = matching_len_start..bundles_from;
288278 if bundle_middle. start > bundle_middle. end {
289279 // If this range is "inverted", this implies that the incoming nodes in lefts contain a
290280 // duplicate key!
291281 // Pictogram:
292282 // v lefts_to
293- // lefts: | SSSSSSSS | ------ | EEEEEEEE |
294- // ↕ matching_len_start
295- // rev_bundles.rev(): | SSS | ?? | EEE |
296- // ^ rights_to
283+ // lefts: | SSSSSSSS | ------ | EEEEEEEE |
284+ // ↕ matching_len_start
285+ // bundles: | SSS | ?? | EEE |
286+ // ^ matching_len_start
287+ // ^ bundles_from
297288 // Both a key from the (S)tarting portion and (E)nding portion of lefts has matched a
298289 // key in the ? portion of bundles. Since the former can't overlap, a key
299290 // must be duplicate. Duplicates might lead to us forgetting about some
@@ -304,15 +295,21 @@ impl BList {
304295 // by pretending. We still need to adjust some things so splicing doesn't
305296 // panic:
306297 matching_len_start = 0 ;
307- bundle_middle = matching_len_end..rev_bundles . len ( ) ;
298+ bundle_middle = 0 ..bundles_from ;
308299 }
309300 let ( matching_len_start, bundle_middle) = ( matching_len_start, bundle_middle) ;
310301
302+ let middle_count = bundle_middle. len ( ) ;
303+
311304 // BNode contains js objects that look suspicious to clippy but are harmless
312305 #[ allow( clippy:: mutable_key_type) ]
313- let mut spare_bundles: HashSet < KeyedEntry > = HashSet :: with_capacity ( bundle_middle. len ( ) ) ;
314- let mut spliced_middle = rev_bundles. splice ( bundle_middle, std:: iter:: empty ( ) ) ;
315- for ( idx, r) in ( & mut spliced_middle) . enumerate ( ) {
306+ let mut spare_bundles: HashSet < KeyedEntry > = HashSet :: with_capacity ( middle_count) ;
307+ let mut spliced_middle = bundles. splice ( bundle_middle, std:: iter:: empty ( ) ) ;
308+ for ( fwd_idx, r) in ( & mut spliced_middle) . enumerate ( ) {
309+ // Assign indices measuring distance from the right (rightmost = 0).
310+ // The run algorithm below processes right-to-left and expects
311+ // increasing indices in that direction.
312+ let idx = middle_count - 1 - fwd_idx;
316313 #[ cold]
317314 fn duplicate_in_bundle ( root : & BSubtree , parent : & Element , r : BNode ) {
318315 test_log ! ( "removing: {:?}" , r) ;
@@ -413,7 +410,9 @@ impl BList {
413410 }
414411 // drop the splice iterator and immediately replace the range with the reordered elements
415412 drop ( spliced_middle) ;
416- rev_bundles. splice ( matching_len_end..matching_len_end, replacements) ;
413+ // replacements was built right-to-left; reverse to render order
414+ replacements. reverse ( ) ;
415+ bundles. splice ( matching_len_start..matching_len_start, replacements) ;
417416
418417 // Step 2.3. Remove any extra rights
419418 for KeyedEntry ( _, r) in spare_bundles. drain ( ) {
@@ -422,11 +421,10 @@ impl BList {
422421 }
423422
424423 // Step 3. Diff matching children at the start
425- let rights_to = rev_bundles. len ( ) - matching_len_start;
426424 for ( l, r) in lefts
427425 . drain ( ..) // matching_len_start.. has been drained already
428426 . rev ( )
429- . zip ( rev_bundles [ rights_to.. ] . iter_mut ( ) )
427+ . zip ( bundles [ ..matching_len_start ] . iter_mut ( ) . rev ( ) )
430428 {
431429 writer = writer. patch ( l, r) ;
432430 }
@@ -437,13 +435,13 @@ impl BList {
437435
438436impl ReconcileTarget for BList {
439437 fn detach ( self , root : & BSubtree , parent : & Element , parent_to_detach : bool ) {
440- for child in self . rev_children . into_iter ( ) {
438+ for child in self . children . into_iter ( ) {
441439 child. detach ( root, parent, parent_to_detach) ;
442440 }
443441 }
444442
445443 fn shift ( & self , next_parent : & Element , mut slot : DomSlot ) -> DomSlot {
446- for node in self . rev_children . iter ( ) {
444+ for node in self . children . iter ( ) . rev ( ) {
447445 slot = node. shift ( next_parent, slot) ;
448446 }
449447
@@ -498,7 +496,7 @@ impl Reconcilable for VList {
498496 // i.e. the current DOM list element that we want to replace with self.
499497 let ( key, fully_keyed, lefts) = self . split_for_blist ( ) ;
500498
501- let rights = & mut blist. rev_children ;
499+ let rights = & mut blist. children ;
502500 test_log ! ( "lefts: {:?}" , lefts) ;
503501 test_log ! ( "rights: {:?}" , rights) ;
504502
@@ -541,10 +539,8 @@ mod feat_hydration {
541539 children. push ( child) ;
542540 }
543541
544- children. reverse ( ) ;
545-
546542 BList {
547- rev_children : children,
543+ children,
548544 fully_keyed,
549545 key,
550546 }
0 commit comments