Skip to content

Commit 89e10a9

Browse files
committed
cache subtree maps for 100 runs, check long-list.html
1 parent 5c2a937 commit 89e10a9

File tree

2 files changed

+134
-25
lines changed

2 files changed

+134
-25
lines changed

diffDOM.js

Lines changed: 131 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,7 @@
4040
}
4141
};
4242

43-
var SubsetMapping = function SubsetMapping(a, b) {
44-
this.oldValue = a;
45-
this.newValue = b;
46-
};
4743

48-
SubsetMapping.prototype = {
49-
contains: function contains(subset) {
50-
if (subset.length < this.length) {
51-
return subset.newValue >= this.newValue && subset.newValue < this.newValue + this.length;
52-
}
53-
return false;
54-
},
55-
toString: function toString() {
56-
return this.length + " element subset, first mapping: old " + this.oldValue + " → new " + this.newValue;
57-
}
58-
};
5944

6045
var elementDescriptors = function(el) {
6146
var output = [];
@@ -318,11 +303,12 @@
318303
if (lcsSize === 0) {
319304
return false;
320305
}
321-
origin = [index[0] - lcsSize, index[1] - lcsSize];
322-
ret = new SubsetMapping(origin[0], origin[1]);
323-
ret.length = lcsSize;
324306

325-
return ret;
307+
return {
308+
oldValue: index[0] - lcsSize,
309+
newValue: index[1] - lcsSize,
310+
length: lcsSize
311+
};
326312
};
327313

328314
/**
@@ -413,6 +399,9 @@
413399
}
414400
}
415401
}
402+
403+
oldTree.subsets = subsets;
404+
oldTree.subsetsAge = 100;
416405
return subsets;
417406
};
418407

@@ -809,12 +798,13 @@
809798
return node;
810799
},
811800
findInnerDiff: function(t1, t2, route) {
812-
var t = this;
813-
var subtrees = (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [],
801+
var oldSubsets = t1.subsets;
802+
//var subtrees = (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [],
803+
var subtrees = t1.subsets && t1.subsetsAge-- ? t1.subsets : (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [],
814804
t1ChildNodes = t1.childNodes ? t1.childNodes : [],
815805
t2ChildNodes = t2.childNodes ? t2.childNodes : [],
816806
childNodesLengthDifference, diffs = [],
817-
index = 0,
807+
index = 0, t = this,
818808
last, e1, e2, i;
819809

820810
if (subtrees.length > 0) {
@@ -1087,6 +1077,7 @@
10871077
node = routeInfo.node,
10881078
parentNode = routeInfo.parentNode,
10891079
nodeIndex = routeInfo.nodeIndex,
1080+
newSubsets = [], splitLength,
10901081
newNode, movedNode, nodeArray, route, length, c, i;
10911082

10921083
var t = this;
@@ -1169,9 +1160,71 @@
11691160
movedNode = nodeArray[i];
11701161
node.childNodes.splice(diff[t._const.to], 0, movedNode);
11711162
}
1163+
if (node.subsets) {
1164+
1165+
node.subsets.forEach(function(map) {
1166+
if (diff[t._const.from] < diff[t._const.to] && map.oldValue <= diff[t._const.to] && map.oldValue > diff[t._const.from]) {
1167+
map.oldValue -= diff.groupLength;
1168+
splitLength = map.oldValue + map.length - diff[t._const.to];
1169+
if (splitLength > 0) {
1170+
// new insertion splits map.
1171+
newSubsets.push({
1172+
oldValue: diff[t._const.to] + diff.groupLength,
1173+
newValue: map.newValue + map.length - splitLength,
1174+
length: splitLength
1175+
})
1176+
map.length -= splitLength;
1177+
}
1178+
} else if (diff[t._const.from] > diff[t._const.to] && map.oldValue > diff[t._const.to] && map.oldValue < diff[t._const.from]) {
1179+
map.oldValue += diff.groupLength;
1180+
splitLength = map.oldValue + map.length - diff[t._const.to];
1181+
if (splitLength > 0) {
1182+
// new insertion splits map.
1183+
newSubsets.push({
1184+
oldValue: diff[t._const.to] + diff.groupLength,
1185+
newValue: map.newValue + map.length - splitLength,
1186+
length: splitLength
1187+
})
1188+
map.length -= splitLength;
1189+
}
1190+
} else if (map.oldValue === diff[t._const.from]) {
1191+
map.oldValue = diff[t._const.to];
1192+
}
1193+
});
1194+
if (node.subsets && newSubsets.length) {
1195+
node.subsets = node.subsets.concat(newSubsets);
1196+
}
1197+
}
1198+
11721199
break;
11731200
case this._const.removeElement:
11741201
parentNode.childNodes.splice(nodeIndex, 1);
1202+
if (parentNode.subsets) {
1203+
parentNode.subsets.forEach(function(map) {
1204+
if (map.oldValue > nodeIndex) {
1205+
map.oldValue -= 1;
1206+
} else if (map.oldValue === nodeIndex) {
1207+
map.delete = true;
1208+
} else if (map.oldValue < nodeIndex && (map.oldValue + map.length) > nodeIndex) {
1209+
if (map.oldValue + map.length - 1 === nodeIndex) {
1210+
map.length--;
1211+
} else {
1212+
newSubsets.push({
1213+
newValue: map.newValue + nodeIndex - map.oldValue,
1214+
oldValue: nodeIndex,
1215+
length: map.length - nodeIndex + map.oldValue - 1
1216+
})
1217+
map.length = nodeIndex - map.oldValue
1218+
}
1219+
}
1220+
});
1221+
parentNode.subsets = parentNode.subsets.filter(function(map) {
1222+
return !map.delete;
1223+
});
1224+
if (newSubsets.length) {
1225+
parentNode.subsets = parentNode.subsets.concat(newSubsets);
1226+
}
1227+
}
11751228
break;
11761229
case this._const.addElement:
11771230
route = diff[this._const.route].slice();
@@ -1191,12 +1244,53 @@
11911244
} else {
11921245
node.childNodes.splice(c, 0, newNode);
11931246
}
1247+
if (node.subsets) {
1248+
node.subsets.forEach(function(map) {
1249+
if (map.oldValue >= c) {
1250+
map.oldValue += 1;
1251+
} if (map.oldValue < c && (map.oldValue + map.length) > c) {
1252+
splitLength = map.oldValue + map.length - c
1253+
newSubsets.push({
1254+
newValue: map.newValue + map.length - splitLength,
1255+
oldValue: c + 1,
1256+
length: splitLength
1257+
})
1258+
map.length -= splitLength
1259+
}
1260+
});
1261+
}
11941262
break;
11951263
case this._const.removeTextElement:
11961264
parentNode.childNodes.splice(nodeIndex, 1);
11971265
if (parentNode.nodeName === 'TEXTAREA') {
11981266
delete parentNode.value;
11991267
}
1268+
if (parentNode.subsets) {
1269+
parentNode.subsets.forEach(function(map) {
1270+
if (map.oldValue > nodeIndex) {
1271+
map.oldValue -= 1;
1272+
} else if (map.oldValue === nodeIndex) {
1273+
map.delete = true;
1274+
} else if (map.oldValue < nodeIndex && (map.oldValue + map.length) > nodeIndex) {
1275+
if (map.oldValue + map.length - 1 === nodeIndex) {
1276+
map.length--;
1277+
} else {
1278+
newSubsets.push({
1279+
newValue: map.newValue + nodeIndex - map.oldValue,
1280+
oldValue: nodeIndex,
1281+
length: map.length - nodeIndex + map.oldValue - 1
1282+
})
1283+
map.length = nodeIndex - map.oldValue
1284+
}
1285+
}
1286+
});
1287+
parentNode.subsets = parentNode.subsets.filter(function(map) {
1288+
return !map.delete;
1289+
});
1290+
if (newSubsets.length) {
1291+
parentNode.subsets = parentNode.subsets.concat(newSubsets);
1292+
}
1293+
}
12001294
break;
12011295
case this._const.addTextElement:
12021296
route = diff[this._const.route].slice();
@@ -1217,6 +1311,21 @@
12171311
if (node.nodeName === 'TEXTAREA') {
12181312
node.value = diff[this._const.newValue];
12191313
}
1314+
if (node.subsets) {
1315+
node.subsets.forEach(function(map) {
1316+
if (map.oldValue >= c) {
1317+
map.oldValue += 1;
1318+
} if (map.oldValue < c && (map.oldValue + map.length) > c) {
1319+
splitLength = map.oldValue + map.length - c
1320+
newSubsets.push({
1321+
newValue: map.newValue + map.length - splitLength,
1322+
oldValue: c + 1,
1323+
length: splitLength
1324+
})
1325+
map.length -= splitLength
1326+
}
1327+
});
1328+
}
12201329
break;
12211330
default:
12221331
console.log('unknown action');

tests/long-list.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,18 @@
3333
<script>
3434
var dd = new diffDOM({
3535
debug: true,
36-
diffcap: 100,
36+
diffcap: 1000,
3737
valueDiffing: false,
38-
maxChildCount: 50
38+
maxChildCount: false
3939
}),
4040
tl = new TraceLogger(dd), elements, first, second, third, fourth, theDiff;
4141

4242
let divs = [].slice.call(document.querySelectorAll('div'))
4343

4444

4545
let diffs = dd.diff(divs[0], divs[1])
46-
console.log(diffs)
4746
dd.apply(divs[0], diffs)
47+
console.log(diffs)
4848
</script>
4949

5050
</body>

0 commit comments

Comments
 (0)