diff algorithm also diffs components' expansions

This commit is contained in:
Andreas Rumpf 2017-06-22 09:17:19 +02:00
commit c8030bc185
2 changed files with 22 additions and 7 deletions

View file

@ -177,8 +177,7 @@ proc eq(a, b: VNode; deep: bool): EqResult =
result = similar result = similar
if not sameAttrs(a, b): return different if not sameAttrs(a, b): return different
if a.class != b.class: return different if a.class != b.class: return different
# XXX Fixme: smart diffing still is broken for complex apps: if a.style != b.style: return similar
if a.style != b.style: return different # similar
# Do not test event listeners here! # Do not test event listeners here!
return result return result
@ -206,7 +205,10 @@ proc updateStyles(newNode, oldNode: VNode; deep: bool) =
else: oldNode.dom.style = Style() else: oldNode.dom.style = Style()
oldNode.style = newNode.style oldNode.style = newNode.style
if deep: if deep:
assert newNode.len == oldNode.len if newNode.len != oldNode.len:
kout cstring"argh ", newNode.len, " ", oldNode.len
kout newNode, oldNode
doAssert newNode.len == oldNode.len
for i in 0 ..< newNode.len: for i in 0 ..< newNode.len:
updateStyles(newNode[i], oldNode[i], deep) updateStyles(newNode[i], oldNode[i], deep)
@ -224,8 +226,18 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode;
if res == changed: if res == changed:
assert oldNode.kind == VNodeKind.component assert oldNode.kind == VNodeKind.component
let x = VComponent(oldNode) let x = VComponent(oldNode)
n = vnodeToDom(x.renderImpl(x), kxi) let oldExpanded = x.expanded
x.expanded = x.renderImpl(x)
x.updatedImpl(x) x.updatedImpl(x)
if oldExpanded == nil:
n = vnodeToDom(x.expanded, kxi)
else:
if updateElement(parent, current, x.expanded, oldExpanded, kxi):
n = x.expanded.dom
doAssert n != nil, "expanded.dom is nil"
else:
n = oldExpanded.dom
doAssert n != nil, "old expanded.dom is nil"
result = true result = true
else: else:
detach(oldNode) detach(oldNode)
@ -234,10 +246,10 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode;
replaceById(kxi.rootId, n) replaceById(kxi.rootId, n)
else: else:
parent.replaceChild(n, current) parent.replaceChild(n, current)
elif res == similar:
updateStyles(newNode, oldNode, false)
else: else:
if res == similar: updateStyles(newNode, oldNode, false)
newNode.dom = oldNode.dom newNode.dom = oldNode.dom
if newNode.kind != VNodeKind.text: if newNode.kind != VNodeKind.text:
let newLength = newNode.len let newLength = newNode.len
var oldLength = oldNode.len var oldLength = oldNode.len
@ -266,8 +278,8 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode;
of different, changed: break of different, changed: break
of similar: of similar:
#updateDom(a, b) #updateDom(a, b)
updateStyles(a[i], b, true)
a[i] = b a[i] = b
#updateStyles(a, b, true)
action action
while commonPrefix < minLength: while commonPrefix < minLength:
@ -299,6 +311,7 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode;
for i in pos..oldPos: for i in pos..oldPos:
detach(oldNode[i]) detach(oldNode[i])
doAssert pos < current.childNodes.len
current.removeChild(current.childNodes[pos]) current.removeChild(current.childNodes[pos])
when false: when false:

View file

@ -129,6 +129,8 @@ type
## should call 'markDirty' instead which is an alias for ## should call 'markDirty' instead which is an alias for
## 'inc version'. ## 'inc version'.
renderedVersion*: int ## Do not touch. Used by karax. renderedVersion*: int ## Do not touch. Used by karax.
expanded*: VNode ## Do not touch. Used by karax. The VDOM the component
## expanded to.
proc value*(n: VNode): cstring = n.text proc value*(n: VNode): cstring = n.text
proc `value=`*(n: VNode; v: cstring) = n.text = v proc `value=`*(n: VNode; v: cstring) = n.text = v