optimized the new diff algorihtm

This commit is contained in:
Andreas Rumpf 2017-06-24 08:23:22 +02:00
commit 09a5e1c34e

View file

@ -205,26 +205,30 @@ type
pkReplace, pkRemove, pkAppend, pkInsertBefore pkReplace, pkRemove, pkAppend, pkInsertBefore
Patch = object Patch = object
k: PatchKind k: PatchKind
parent, current, n: Node parent, current: Node
n: VNode
proc addPatch(patches: var seq[Patch]; k: PatchKind; parent, current, n: Node) = proc addPatch(patches: var seq[Patch]; k: PatchKind; parent, current: Node;
n: VNode) =
patches.add(Patch(k: k, parent: parent, current: current, n: n)) patches.add(Patch(k: k, parent: parent, current: current, n: n))
proc apply(patches: seq[Patch]; kxi: KaraxInstance) = proc apply(patches: seq[Patch]; kxi: KaraxInstance) =
for p in patches: for p in patches:
case p.k case p.k
of pkReplace: of pkReplace:
let nn = vnodeToDom(p.n, kxi)
if p.parent == nil: if p.parent == nil:
replaceById(kxi.rootId, p.n) replaceById(kxi.rootId, nn)
else: else:
if p.n != p.current: p.parent.replaceChild(nn, p.current)
p.parent.replaceChild(p.n, p.current)
of pkRemove: of pkRemove:
p.parent.removeChild(p.current) p.parent.removeChild(p.current)
of pkAppend: of pkAppend:
p.parent.appendChild(p.n) let nn = vnodeToDom(p.n, kxi)
p.parent.appendChild(nn)
of pkInsertBefore: of pkInsertBefore:
p.parent.insertBefore(p.n, p.current) let nn = vnodeToDom(p.n, kxi)
p.parent.insertBefore(nn, p.current)
proc diff(parent, current: Node; newNode, oldNode: VNode; patches: var seq[Patch]; proc diff(parent, current: Node; newNode, oldNode: VNode; patches: var seq[Patch];
kxi: KaraxInstance): EqResult = kxi: KaraxInstance): EqResult =
@ -248,7 +252,8 @@ proc diff(parent, current: Node; newNode, oldNode: VNode; patches: var seq[Patch
assert current.childNodes[j] != nil, $info assert current.childNodes[j] != nil, $info
assert oldNode.len == current.len assert oldNode.len == current.len
let r = if oldNode.kind in {VNodeKind.component, VNodeKind.vthunk, VNodeKind.dthunk}: let r = if oldNode.kind == VNodeKind.component or oldNode.kind == VNodeKind.vthunk or
oldNode.kind == VNodeKind.dthunk:
diff(parent, current, a[i], b[j], patches, kxi) diff(parent, current, a[i], b[j], patches, kxi)
else: else:
diff(current, current.childNodes[j], a[i], b[j], patches, kxi) diff(current, current.childNodes[j], a[i], b[j], patches, kxi)
@ -287,13 +292,12 @@ proc diff(parent, current: Node; newNode, oldNode: VNode; patches: var seq[Patch
if oldPos + 1 == oldLength: if oldPos + 1 == oldLength:
for i in pos..newPos: for i in pos..newPos:
patches.addPatch(pkAppend, current, nil, vnodeToDom(newNode[i], kxi)) patches.addPatch(pkAppend, current, nil, newNode[i])
result = different result = different
else: else:
let before = current.childNodes[oldPos + 1] let before = current.childNodes[oldPos + 1]
for i in pos..newPos: for i in pos..newPos:
patches.addPatch(pkInsertBefore, current, before, patches.addPatch(pkInsertBefore, current, before, newNode[i])
vnodeToDom(newNode[i], kxi))
result = different result = different
# XXX call 'attach' here? # XXX call 'attach' here?
for i in pos..oldPos: for i in pos..oldPos:
@ -312,8 +316,7 @@ proc diff(parent, current: Node; newNode, oldNode: VNode; patches: var seq[Patch
x.updatedImpl(x) x.updatedImpl(x)
if oldExpanded == nil: if oldExpanded == nil:
detach(oldNode) detach(oldNode)
let n = vnodeToDom(x.expanded, kxi) patches.addPatch(pkReplace, parent, current, x.expanded)
patches.addPatch(pkReplace, parent, current, n)
else: else:
let res = diff(parent, current, x.expanded, oldExpanded, patches, kxi) let res = diff(parent, current, x.expanded, oldExpanded, patches, kxi)
if res != different: if res != different:
@ -323,8 +326,7 @@ proc diff(parent, current: Node; newNode, oldNode: VNode; patches: var seq[Patch
assert x.expanded.dom != nil, "expanded.dom is nil" assert x.expanded.dom != nil, "expanded.dom is nil"
of different: of different:
detach(oldNode) detach(oldNode)
let n = vnodeToDom(newNode, kxi) patches.addPatch(pkReplace, parent, current, newNode)
patches.addPatch(pkReplace, parent, current, n)
proc dodraw(kxi: KaraxInstance) = proc dodraw(kxi: KaraxInstance) =
if kxi.renderer.isNil: return if kxi.renderer.isNil: return