@@ -36,8 +36,10 @@ function init_hydrate(target: NodeEx) {
36
36
if ( target . hydrate_init ) return ;
37
37
target . hydrate_init = true ;
38
38
39
+ type NodeEx2 = NodeEx & { claim_order : number } ;
40
+
39
41
// We know that all children have claim_order values since the unclaimed have been detached
40
- const children = target . childNodes as NodeListOf < NodeEx & { claim_order : number } > ;
42
+ const children = target . childNodes as NodeListOf < NodeEx2 > ;
41
43
42
44
/*
43
45
* Reorder claimed children optimally.
@@ -57,7 +59,7 @@ function init_hydrate(target: NodeEx) {
57
59
*/
58
60
59
61
// Compute longest increasing subsequence
60
- // m: subsequence length j => index k of smallest value that ends an incresing subsequence of length j
62
+ // m: subsequence length j => index k of smallest value that ends an increasing subsequence of length j
61
63
const m = new Int32Array ( children . length + 1 ) ;
62
64
// Predecessor indices + 1
63
65
const p = new Int32Array ( children . length ) ;
@@ -82,28 +84,34 @@ function init_hydrate(target: NodeEx) {
82
84
}
83
85
84
86
// The longest increasing subsequence of nodes (initially reversed)
85
- const lis = [ ] ;
87
+ const lis : NodeEx2 [ ] = [ ] ;
86
88
for ( let cur = m [ longest ] + 1 ; cur != 0 ; cur = p [ cur - 1 ] ) {
87
89
const node = children [ cur - 1 ] ;
88
90
lis . push ( node ) ;
89
91
node . is_in_lis = true ;
90
92
}
91
- lis . reverse ( ) ;
93
+ lis . reverse ( ) ;
92
94
93
95
// Move all nodes that aren't in the longest increasing subsequence
94
- const toMove : NodeEx [ ] = [ ] ;
96
+ const toMove = lis . map ( ( ) => [ ] as NodeEx2 [ ] ) ;
97
+ // For the nodes at the end
98
+ toMove . push ( [ ] ) ;
95
99
for ( let i = 0 ; i < children . length ; i ++ ) {
96
- if ( ! children [ i ] . is_in_lis ) {
97
- toMove . push ( children [ i ] ) ;
100
+ const node = children [ i ] ;
101
+ if ( ! node . is_in_lis ) {
102
+ const idx = upper_bound ( 0 , lis . length , idx => lis [ idx ] . claim_order , node . claim_order ) ;
103
+ toMove [ idx ] . push ( node ) ;
98
104
}
99
105
}
100
106
101
- toMove . forEach ( ( node ) => {
102
- const idx = upper_bound ( 0 , lis . length , idx => lis [ idx ] . claim_order , node . claim_order ) ;
103
- if ( ( idx == 0 ) || ( lis [ idx - 1 ] . claim_order != node . claim_order ) ) {
104
- const nxt = idx == lis . length ? null : lis [ idx ] ;
105
- target . insertBefore ( node , nxt ) ;
106
- }
107
+ toMove . forEach ( ( lst , idx ) => {
108
+ // We sort the nodes being moved to guarantee that their insertion order matches the claim order
109
+ lst . sort ( ( a , b ) => a . claim_order - b . claim_order ) ;
110
+
111
+ const anchor = idx < lis . length ? lis [ idx ] : null ;
112
+ lst . forEach ( n => {
113
+ target . insertBefore ( n , anchor ) ;
114
+ } ) ;
107
115
} ) ;
108
116
}
109
117
@@ -330,7 +338,6 @@ function claim_node<R extends ChildNodeEx>(nodes: ChildNodeArray, predicate: (no
330
338
// Since we spliced before the last_index, we decrease it
331
339
nodes . claim_info . last_index -- ;
332
340
}
333
- detach ( node ) ;
334
341
return node ;
335
342
}
336
343
}
0 commit comments