forked from Matt-Esch/virtual-dom
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdiff.js
79 lines (63 loc) · 1.97 KB
/
diff.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// NOT WORKING, just the general outline
var deepEqual = require("deep-equal")
var isVDOMNode = require("./lib/is-virtual-dom")
var isVTextNode = require("./lib/is-virtual-text")
module.exports = diff
function diff(a, b) {
var patch = {}
// index a and b so we can implicitly reference
indexTree(a)
walk(a, b, patch)
return patch
}
// Index the tree in-order (we should be able to avoid this)
function indexTree(tree, index) {
index = index || 0
tree.index = index
if (tree.children) {
for (var i = 0; i < tree.children.length; i++) {
index = indexTree(tree.children[i], index + 1)
}
}
return tree.index
}
var remove = { type: "remove" }
function walk(a, b, patch) {
var apply
if (isVDOMNode(a) && isVDOMNode(b)) {
if (a.tagName === b.tagName) {
if (!deepEqual(a.properties, b.properties)) {
apply = [{ type: "update", b: b }]
}
var aChildren = a.children
var bChildren = b.children
var aLen = aChildren.length
var bLen = bChildren.length
var len = aLen < bLen ? aLen : bLen
for (var i = 0; i < len; i++) {
walk(aChildren[i], bChildren[i], patch)
}
// Excess nodes in a need to be removed
for (; i < aLen; i++) {
patch[aChildren[i].index] = [remove]
}
// Excess nodes in b need to be added
for (; i < bLen; i++) {
apply = apply || []
apply.push({
type: "insert",
b: bChildren[i]
})
}
} else {
apply = [{ type: "replace", b: b }]
}
} else if (isVTextNode(a) && isVTextNode(b) && a.text !== b.text) {
apply = [{ type: "update", b: b }]
} else if (a !== b) {
apply = [{ type: "replace", b: b }]
}
if (apply) {
patch[a.index] = apply
}
}