Cross comparing (debug)
This commit is contained in:
parent
78a47158a1
commit
1b56477e59
3 changed files with 173 additions and 59 deletions
193
src/karax.nim
193
src/karax.nim
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue