diff algorithm special cases diffing of virtual styles

This commit is contained in:
Andreas Rumpf 2017-06-05 10:21:38 +02:00
commit a9b5216a42

View file

@ -123,22 +123,26 @@ proc replaceById(id: cstring; newTree: Node) =
x.parentNode.replaceChild(newTree, x) x.parentNode.replaceChild(newTree, x)
#newTree.id = id #newTree.id = id
proc equalsShallow(a, b: VNode): bool = type
if a.kind != b.kind: return false EqResult = enum
if a.id != b.id: return false different, similar, identical
if a.key != b.key: return false
proc equalsShallow(a, b: VNode): EqResult =
if a.kind != b.kind: return different
if a.id != b.id: return different
if a.key != b.key: return different
if a.kind == VNodeKind.text: if a.kind == VNodeKind.text:
if a.text != b.text: return false if a.text != b.text: return different
elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk: elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk:
if a.text != b.text: return false if a.text != b.text: return different
if a.len != b.len: return false if a.len != b.len: return different
for i in 0..<a.len: for i in 0..<a.len:
if not equalsShallow(a[i], b[i]): return false if equalsShallow(a[i], b[i]) == different: return different
if not sameAttrs(a, b): return false if not sameAttrs(a, b): return different
if a.class != b.class: return false if a.class != b.class: return different
if a.style != b.style: return false if a.style != b.style: return similar
# XXX test event listeners here? # Do not test event listeners here!
return true return identical
proc equalsTree(a, b: VNode): bool = proc equalsTree(a, b: VNode): bool =
when false: when false:
@ -167,14 +171,23 @@ proc updateDirtyElements(parent, current: Node, newNode: VNode) =
#if dirtyCount <= 0: return #if dirtyCount <= 0: return
proc updateElement(parent, current: Node, newNode, oldNode: VNode) = proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
if not equalsShallow(newNode, oldNode): let res = equalsShallow(newNode, oldNode)
if res == different:
detach(oldNode) detach(oldNode)
let n = vnodeToDom(newNode) let n = vnodeToDom(newNode)
if parent == nil: if parent == nil:
replaceById("ROOT", n) replaceById("ROOT", n)
else: else:
parent.replaceChild(n, current) parent.replaceChild(n, current)
elif newNode.kind != VNodeKind.text: else:
if res == similar:
# we keep the oldNode, but take over the style from the new node:
if oldNode.dom != nil:
if newNode.style != nil: applyStyle(oldNode.dom, newNode.style)
else: oldNode.dom.style = Style()
oldNode.style = newNode.style
if newNode.kind != VNodeKind.text:
let newLength = newNode.len let newLength = newNode.len
var oldLength = oldNode.len var oldLength = oldNode.len
let minLength = min(newLength, oldLength) let minLength = min(newLength, oldLength)