Cross comparing (debug)

This commit is contained in:
Roman Vishnevskii 2017-05-10 14:38:16 +07:00
commit 1b56477e59
3 changed files with 173 additions and 59 deletions

View file

@ -130,9 +130,6 @@ proc equalsShallow(a, b: VNode): bool =
if a.text != b.text: return false if a.text != b.text: return false
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 false
if a.len != b.len: return false
for i in 0..<a.len:
if not equalsShallow(a[i], b[i]): return false
if not sameAttrs(a, b): return false if not sameAttrs(a, b): return false
if a.class != b.class: return false if a.class != b.class: return false
# XXX test event listeners here? # XXX test event listeners here?
@ -164,6 +161,26 @@ proc updateDirtyElements(parent, current: Node, newNode: VNode) =
# leave early if we know there cannot be anything left to do: # leave early if we know there cannot be anything left to do:
#if dirtyCount <= 0: return #if dirtyCount <= 0: return
proc printChildren(parent: Node): cstring =
if parent != nil and parent.hasChildNodes:
var it = parent.firstChild
result = ""
while it != nil:
if it.id == nil:
result.add(" nil")
else:
result.add(" " & $it.id)
it = it.nextSibling
proc printChildren(parent: VNode): cstring =
if parent != nil:
result = ""
for i in 0..parent.len-1:
if parent[i] == nil or parent[i].id == nil:
kout cstring("nil")
else:
result.add(" " & $(parent[i].id))
proc updateElement(parent, current: Node, newNode, oldNode: VNode) = proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
newNode.dom = oldNode.dom newNode.dom = oldNode.dom
if not equalsShallow(newNode, oldNode): if not equalsShallow(newNode, oldNode):
@ -176,6 +193,7 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
elif newNode.kind != VNodeKind.text: elif 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)
assert oldNode.kind == newNode.kind assert oldNode.kind == newNode.kind
when defined(simpleDiff): when defined(simpleDiff):
for i in 0..min(newLength, oldLength)-1: for i in 0..min(newLength, oldLength)-1:
@ -188,46 +206,143 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
detach(oldNode[i]) detach(oldNode[i])
current.removeChild(current.lastChild) current.removeChild(current.lastChild)
else: else:
var left = 0 #kout cstring("start")
var rightNew = newLength - 1 kout cstring("----------------")
var rightOld = oldLength - 1 kout cstring("----------------")
var before = printChildren(current)
# maximal common prefix
var left = 0
while left < minLength and equalsShallow(newNode[left], oldNode[left]):
updateElement(current, oldNode[left].dom, newNode[left], oldNode[left])
inc left
# maximal common suffix
var rightOld = oldLength - 1
var rightNew = newLength - 1
while rightOld >= left and rightNew >= left and equalsShallow(newNode[rightNew], oldNode[rightOld]):
updateElement(current, oldNode[rightOld].dom, newNode[rightNew], oldNode[rightOld])
dec rightOld
dec rightNew
var leftOld = left
var leftNew = left
while left <= min(rightNew, rightOld):
var minRight = min(rightOld, rightNew) var flag = false
#if rightOld >= leftOld and rightNew >= leftNew and equalsShallow(oldNode[leftOld], newNode[rightNew]):
while left <= minRight and kout cstring("current")
equalsTree(newNode[left], oldNode[left]): kout printChildren(current)
newNode[left] = oldNode[left] kout cstring("oldNode")
inc left kout printChildren(oldNode)
kout cstring("newNode")
kout printChildren(newNode)
flag = true
var step = 1
while rightOld >= leftOld and rightNew >= leftNew and equalsShallow(oldNode[leftOld], newNode[rightNew]):
kout cstring($oldNode[leftOld].id & " " & $newNode[rightNew].id)
kout cstring("pos: " & $leftOld & " " & $rightNew)
while rightOld > left and rightNew > left and var nextNode: Node = nil
equalsTree(newNode[rightNew], oldNode[rightOld]): if rightNew + 1 < newLength:
newNode[rightNew] = oldNode[rightOld] nextNode = newNode[rightNew + 1].dom
dec rightOld
dec rightNew
minRight = min(rightOld, rightNew)
if left <= minRight:
updateElement(current, oldNode[left].dom, newNode[left], oldNode[left])
inc left
if left < minRight: updateElement(current, oldNode[leftOld].dom, newNode[rightNew], oldNode[leftOld])
updateElement(current, oldNode[rightOld].dom, newNode[rightNew], oldNode[rightOld]) if nextNode == nil:
dec rightNew current.appendChild(oldNode[leftOld].dom)
dec rightOld kout cstring("append")
else:
var posNextElem = rightOld + 1 kout cstring("insertBefore")
var isPushBack = posNextElem == oldLength current.insertBefore(oldNode[leftOld].dom, nextNode)
while left <= rightNew: #kout cstring("step = " & $step & "; leftOld = " & $leftOld & "; rightNew = " & $rightNew)
if isPushBack: kout cstring($oldNode[leftOld])
current.appendChild(vnodeToDom(newNode[left])) inc step
else: inc leftOld
current.insertBefore(vnodeToDom(newNode[left]), oldNode[posNextElem].dom) dec rightNew
inc left
if flag:
kout cstring("after")
kout printChildren(current)
for i in left..rightOld: while rightOld >= leftOld and rightNew >= leftNew:
current.removeChild(oldNode[i].dom) updateElement(current, current[leftOld], newNode[leftNew], oldNode[leftOld])
detach(oldNode[i]) inc leftNew
inc leftOld
var isPushBack = (rightNew + 1 == newLength)
var nextNode: Node = nil
if not isPushBack:
nextNode = newNode[rightNew + 1].dom
while leftNew <= rightNew:
var node = vnodeToDom(newNode[leftNew])ды
if isPushBack:
current.appendChild(node)
else:
current.insertBefore(node, nextNode)
inc leftNew
for i in leftOld..rightOld:
current.removeChild(oldNode[i].dom)
detach(oldNode[i])
kout cstring("----------------")
kout cstring("before")
kout before
kout cstring("finish")
kout printChildren(current)
kout cstring("----------------")
kout cstring("----------------")
# var leftNew = left
# var leftOld = left
# while rightOld >= leftOld and rightNew >= leftNew and equalsShallow(oldNode[leftOld], newNode[rightNew]):
# var nextNode: Node = nil
# if rightNew + 1 < newLength:
# nextNode = newNode[rightNew + 1].dom
# if nextNode == nil:
# current.appendChild(oldNode[leftOld].dom)
# else:
# current.insertBefore(oldNode[leftOld].dom, nextNode)
# inc leftOld
# dec rightNew
# var lastTarget: Node = nil
# if leftOld <= rightOld:
# lastTarget = oldNode[leftOld].dom
# while rightOld >= leftOld and rightNew >= leftNew and equalsShallow(oldNode[rightOld], newNode[leftNew]):
# current.insertBefore(oldNode[rightOld].dom, lastTarget)
# lastTarget = oldNode[rightOld].dom
# inc leftNew
# dec rightOld
# if rightOld < leftOld:
# var isPushBack = leftOld < oldLength
# for i in leftNew..rightNew:
# if isPushBack:
# current.appendChild(vnodeToDom(newNode[i]))
# else:
# current.insertBefore(vnodeToDom(newNode[i]), oldNode[leftOld].dom)
# elif rightNew < leftNew:
# for i in leftOld..rightOld:
# current.removeChild(oldNode[i].dom)
# detach(oldNode[i])
# else:
# while rightOld >= leftOld and rightNew >= leftNew:
# updateElement(current, oldNode[leftOld].dom, newNode[leftNew], oldNode[leftOld])
# inc leftNew
# inc leftOld
# if rightOld < leftOld:
# while rightNew >= leftNew:
# current.appendChild(vnodeToDom(newNode[leftNew]))
# inc leftNew
# elif rightNew < leftNew:
# while rightOld >= leftOld:
# current.removeChild(oldNode[leftOld].dom)
# detach(oldNode[leftOld])
# inc leftOld
when false: when false:
var drawTimeout: Timeout var drawTimeout: Timeout

View file

@ -3,7 +3,6 @@
<html> <html>
<head> <head>
<title>Diff dom tests</title> <title>Diff dom tests</title>
<link rel="stylesheet" href="style.css">
</head> </head>
<body id="body"> <body id="body">

View file

@ -41,7 +41,7 @@ proc test1() =
proc check2() = proc check2() =
let result = checkOrder(@[8, 0, 1, 2, 3, 4, 7, 5]) let result = checkOrder(@[8, 0, 1, 2, 3, 4, 7, 5])
if result: if result:
results.add cstring"test1 - OK" results.add cstring"test2 - OK"
else: else:
results.add cstring"test2 - FAIL" results.add cstring"test2 - FAIL"
@ -134,7 +134,7 @@ proc createDom(): VNode =
result = buildHtml(tdiv()): result = buildHtml(tdiv()):
ul(id="ul"): ul(id="ul"):
for e in entries: for e in entries:
createEntry(parseInt(e)) createEntry(jstrutils.parseInt(e))
for r in results: for r in results:
tdiv: tdiv:
text r text r
@ -147,20 +147,20 @@ proc onload() =
var dtTest = 500 var dtTest = 500
var t = dtReset var t = dtReset
timeout = setTimeout(test1, t) # timeout = setTimeout(test1, t)
t += dtTest # t += dtTest
timeout = setTimeout(reset, t) # timeout = setTimeout(reset, t)
t += dtReset # t += dtReset
timeout = setTimeout(test2, t) # timeout = setTimeout(test2, t)
t += dtTest # t += dtTest
timeout = setTimeout(reset, t) # timeout = setTimeout(reset, t)
t += dtReset # t += dtReset
timeout = setTimeout(test3, t) # timeout = setTimeout(test3, t)
t += dtTest # t += dtTest
timeout = setTimeout(reset, t) # timeout = setTimeout(reset, t)
t += dtReset # t += dtReset
timeout = setTimeout(test4, t) timeout = setTimeout(test4, t)
t += dtTest t += dtTest
@ -172,12 +172,12 @@ proc onload() =
timeout = setTimeout(reset, t) timeout = setTimeout(reset, t)
t += dtReset t += dtReset
timeout = setTimeout(test6, t) # timeout = setTimeout(test6, t)
t += dtTest # t += dtTest
timeout = setTimeout(reset, t) # timeout = setTimeout(reset, t)
t += dtReset # t += dtReset
timeout = setTimeout(test7, t) # timeout = setTimeout(test7, t)
onload() onload()
setRenderer createDom setRenderer createDom