Skip to content

Commit 5fccd17

Browse files
committed
using external utility
1 parent 4c616f7 commit 5fccd17

File tree

6 files changed

+288
-298
lines changed

6 files changed

+288
-298
lines changed

index.js

Lines changed: 94 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ var udomdiff = (function (exports) {
3535
var aStart = 0;
3636
var bStart = 0;
3737
var map = null;
38-
3938
while (aStart < aEnd || bStart < bEnd) {
4039
// append head, tail, or nodes in between: fast path
4140
if (aEnd === aStart) {
@@ -44,111 +43,106 @@ var udomdiff = (function (exports) {
4443
// the node to `insertBefore`, if the index is more than 0
4544
// must be retrieved, otherwise it's gonna be the first item.
4645
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
5249
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+
}
57129
}
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+
}
145138
}
146-
147139
return b;
148140
});
149141

150-
exports.default = index;
142+
exports["default"] = index;
143+
144+
Object.defineProperty(exports, '__esModule', { value: true });
151145

152146
return exports;
153147

154-
}({}).default);
148+
})({}).default;

min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

new.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"cjs": "ascjs --no-default esm cjs",
99
"rollup:new": "rollup --config rollup/new.config.js",
1010
"rollup:babel": "rollup --config rollup/babel.config.js",
11-
"min": "uglifyjs index.js --support-ie8 --comments=/^!/ -c -m -o min.js",
11+
"min": "uglifyjs index.js -c -m -o min.js",
1212
"fix:default": "sed -i 's/({})/({}).default/' index.js && sed -i 's/({})/({}).default/' new.js && sed -i 's/({})/({}).default/' min.js",
1313
"coveralls": "nyc report --reporter=text-lcov | coveralls",
1414
"test": "nyc node test/index.js",

0 commit comments

Comments
 (0)