@@ -35,7 +35,6 @@ var udomdiff = (function (exports) {
35
35
var aStart = 0 ;
36
36
var bStart = 0 ;
37
37
var map = null ;
38
-
39
38
while ( aStart < aEnd || bStart < bEnd ) {
40
39
// append head, tail, or nodes in between: fast path
41
40
if ( aEnd === aStart ) {
@@ -44,111 +43,106 @@ var udomdiff = (function (exports) {
44
43
// the node to `insertBefore`, if the index is more than 0
45
44
// must be retrieved, otherwise it's gonna be the first item.
46
45
var node = bEnd < bLength ? bStart ? get ( b [ bStart - 1 ] , - 0 ) . nextSibling : get ( b [ bEnd - bStart ] , 0 ) : before ;
47
-
48
- while ( bStart < bEnd ) {
49
- parentNode . insertBefore ( get ( b [ bStart ++ ] , 1 ) , node ) ;
50
- }
51
- } // remove head or tail: fast path
46
+ while ( bStart < bEnd ) parentNode . insertBefore ( get ( b [ bStart ++ ] , 1 ) , node ) ;
47
+ }
48
+ // remove head or tail: fast path
52
49
else if ( bEnd === bStart ) {
53
- while ( aStart < aEnd ) {
54
- // remove the node only if it's unknown or not live
55
- if ( ! map || ! map . has ( a [ aStart ] ) ) parentNode . removeChild ( get ( a [ aStart ] , - 1 ) ) ;
56
- aStart ++ ;
50
+ while ( aStart < aEnd ) {
51
+ // remove the node only if it's unknown or not live
52
+ if ( ! map || ! map . has ( a [ aStart ] ) ) parentNode . removeChild ( get ( a [ aStart ] , - 1 ) ) ;
53
+ aStart ++ ;
54
+ }
55
+ }
56
+ // same node: fast path
57
+ else if ( a [ aStart ] === b [ bStart ] ) {
58
+ aStart ++ ;
59
+ bStart ++ ;
60
+ }
61
+ // same tail: fast path
62
+ else if ( a [ aEnd - 1 ] === b [ bEnd - 1 ] ) {
63
+ aEnd -- ;
64
+ bEnd -- ;
65
+ }
66
+ // The once here single last swap "fast path" has been removed in v1.1.0
67
+ // https://github.com/WebReflection/udomdiff/blob/single-final-swap/esm/index.js#L69-L85
68
+ // reverse swap: also fast path
69
+ else if ( a [ aStart ] === b [ bEnd - 1 ] && b [ bStart ] === a [ aEnd - 1 ] ) {
70
+ // this is a "shrink" operation that could happen in these cases:
71
+ // [1, 2, 3, 4, 5]
72
+ // [1, 4, 3, 2, 5]
73
+ // or asymmetric too
74
+ // [1, 2, 3, 4, 5]
75
+ // [1, 2, 3, 5, 6, 4]
76
+ var _node = get ( a [ -- aEnd ] , - 1 ) . nextSibling ;
77
+ parentNode . insertBefore ( get ( b [ bStart ++ ] , 1 ) , get ( a [ aStart ++ ] , - 1 ) . nextSibling ) ;
78
+ parentNode . insertBefore ( get ( b [ -- bEnd ] , 1 ) , _node ) ;
79
+ // mark the future index as identical (yeah, it's dirty, but cheap 👍)
80
+ // The main reason to do this, is that when a[aEnd] will be reached,
81
+ // the loop will likely be on the fast path, as identical to b[bEnd].
82
+ // In the best case scenario, the next loop will skip the tail,
83
+ // but in the worst one, this node will be considered as already
84
+ // processed, bailing out pretty quickly from the map index check
85
+ a [ aEnd ] = b [ bEnd ] ;
86
+ }
87
+ // map based fallback, "slow" path
88
+ else {
89
+ // the map requires an O(bEnd - bStart) operation once
90
+ // to store all future nodes indexes for later purposes.
91
+ // In the worst case scenario, this is a full O(N) cost,
92
+ // and such scenario happens at least when all nodes are different,
93
+ // but also if both first and last items of the lists are different
94
+ if ( ! map ) {
95
+ map = new Map ( ) ;
96
+ var i = bStart ;
97
+ while ( i < bEnd ) map . set ( b [ i ] , i ++ ) ;
98
+ }
99
+ // if it's a future node, hence it needs some handling
100
+ if ( map . has ( a [ aStart ] ) ) {
101
+ // grab the index of such node, 'cause it might have been processed
102
+ var index = map . get ( a [ aStart ] ) ;
103
+ // if it's not already processed, look on demand for the next LCS
104
+ if ( bStart < index && index < bEnd ) {
105
+ var _i = aStart ;
106
+ // counts the amount of nodes that are the same in the future
107
+ var sequence = 1 ;
108
+ while ( ++ _i < aEnd && _i < bEnd && map . get ( a [ _i ] ) === index + sequence ) sequence ++ ;
109
+ // effort decision here: if the sequence is longer than replaces
110
+ // needed to reach such sequence, which would brings again this loop
111
+ // to the fast path, prepend the difference before a sequence,
112
+ // and move only the future list index forward, so that aStart
113
+ // and bStart will be aligned again, hence on the fast path.
114
+ // An example considering aStart and bStart are both 0:
115
+ // a: [1, 2, 3, 4]
116
+ // b: [7, 1, 2, 3, 6]
117
+ // this would place 7 before 1 and, from that time on, 1, 2, and 3
118
+ // will be processed at zero cost
119
+ if ( sequence > index - bStart ) {
120
+ var _node2 = get ( a [ aStart ] , 0 ) ;
121
+ while ( bStart < index ) parentNode . insertBefore ( get ( b [ bStart ++ ] , 1 ) , _node2 ) ;
122
+ }
123
+ // if the effort wasn't good enough, fallback to a replace,
124
+ // moving both source and target indexes forward, hoping that some
125
+ // similar node will be found later on, to go back to the fast path
126
+ else {
127
+ parentNode . replaceChild ( get ( b [ bStart ++ ] , 1 ) , get ( a [ aStart ++ ] , - 1 ) ) ;
128
+ }
57
129
}
58
- } // same node: fast path
59
- else if ( a [ aStart ] === b [ bStart ] ) {
60
- aStart ++ ;
61
- bStart ++ ;
62
- } // same tail: fast path
63
- else if ( a [ aEnd - 1 ] === b [ bEnd - 1 ] ) {
64
- aEnd -- ;
65
- bEnd -- ;
66
- } // The once here single last swap "fast path" has been removed in v1.1.0
67
- // https://github.com/WebReflection/udomdiff/blob/single-final-swap/esm/index.js#L69-L85
68
- // reverse swap: also fast path
69
- else if ( a [ aStart ] === b [ bEnd - 1 ] && b [ bStart ] === a [ aEnd - 1 ] ) {
70
- // this is a "shrink" operation that could happen in these cases:
71
- // [1, 2, 3, 4, 5]
72
- // [1, 4, 3, 2, 5]
73
- // or asymmetric too
74
- // [1, 2, 3, 4, 5]
75
- // [1, 2, 3, 5, 6, 4]
76
- var _node = get ( a [ -- aEnd ] , - 1 ) . nextSibling ;
77
- parentNode . insertBefore ( get ( b [ bStart ++ ] , 1 ) , get ( a [ aStart ++ ] , - 1 ) . nextSibling ) ;
78
- parentNode . insertBefore ( get ( b [ -- bEnd ] , 1 ) , _node ) ; // mark the future index as identical (yeah, it's dirty, but cheap 👍)
79
- // The main reason to do this, is that when a[aEnd] will be reached,
80
- // the loop will likely be on the fast path, as identical to b[bEnd].
81
- // In the best case scenario, the next loop will skip the tail,
82
- // but in the worst one, this node will be considered as already
83
- // processed, bailing out pretty quickly from the map index check
84
-
85
- a [ aEnd ] = b [ bEnd ] ;
86
- } // map based fallback, "slow" path
87
- else {
88
- // the map requires an O(bEnd - bStart) operation once
89
- // to store all future nodes indexes for later purposes.
90
- // In the worst case scenario, this is a full O(N) cost,
91
- // and such scenario happens at least when all nodes are different,
92
- // but also if both first and last items of the lists are different
93
- if ( ! map ) {
94
- map = new Map ( ) ;
95
- var i = bStart ;
96
-
97
- while ( i < bEnd ) {
98
- map . set ( b [ i ] , i ++ ) ;
99
- }
100
- } // if it's a future node, hence it needs some handling
101
-
102
-
103
- if ( map . has ( a [ aStart ] ) ) {
104
- // grab the index of such node, 'cause it might have been processed
105
- var index = map . get ( a [ aStart ] ) ; // if it's not already processed, look on demand for the next LCS
106
-
107
- if ( bStart < index && index < bEnd ) {
108
- var _i = aStart ; // counts the amount of nodes that are the same in the future
109
-
110
- var sequence = 1 ;
111
-
112
- while ( ++ _i < aEnd && _i < bEnd && map . get ( a [ _i ] ) === index + sequence ) {
113
- sequence ++ ;
114
- } // effort decision here: if the sequence is longer than replaces
115
- // needed to reach such sequence, which would brings again this loop
116
- // to the fast path, prepend the difference before a sequence,
117
- // and move only the future list index forward, so that aStart
118
- // and bStart will be aligned again, hence on the fast path.
119
- // An example considering aStart and bStart are both 0:
120
- // a: [1, 2, 3, 4]
121
- // b: [7, 1, 2, 3, 6]
122
- // this would place 7 before 1 and, from that time on, 1, 2, and 3
123
- // will be processed at zero cost
124
-
125
-
126
- if ( sequence > index - bStart ) {
127
- var _node2 = get ( a [ aStart ] , 0 ) ;
128
-
129
- while ( bStart < index ) {
130
- parentNode . insertBefore ( get ( b [ bStart ++ ] , 1 ) , _node2 ) ;
131
- }
132
- } // if the effort wasn't good enough, fallback to a replace,
133
- // moving both source and target indexes forward, hoping that some
134
- // similar node will be found later on, to go back to the fast path
135
- else {
136
- parentNode . replaceChild ( get ( b [ bStart ++ ] , 1 ) , get ( a [ aStart ++ ] , - 1 ) ) ;
137
- }
138
- } // otherwise move the source forward, 'cause there's nothing to do
139
- else aStart ++ ;
140
- } // this node has no meaning in the future list, so it's more than safe
141
- // to remove it, and check the next live node out instead, meaning
142
- // that only the live list index should be forwarded
143
- else parentNode . removeChild ( get ( a [ aStart ++ ] , - 1 ) ) ;
144
- }
130
+ // otherwise move the source forward, 'cause there's nothing to do
131
+ else aStart ++ ;
132
+ }
133
+ // this node has no meaning in the future list, so it's more than safe
134
+ // to remove it, and check the next live node out instead, meaning
135
+ // that only the live list index should be forwarded
136
+ else parentNode . removeChild ( get ( a [ aStart ++ ] , - 1 ) ) ;
137
+ }
145
138
}
146
-
147
139
return b ;
148
140
} ) ;
149
141
150
- exports . default = index ;
142
+ exports [ "default" ] = index ;
143
+
144
+ Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
151
145
152
146
return exports ;
153
147
154
- } ( { } ) . default ) ;
148
+ } ) ( { } ) . default ;
0 commit comments