DOM diff problem: fix bug, tests

This commit is contained in:
Roman Vishnevskii 2017-04-07 18:49:11 +07:00
commit c75295d334
4 changed files with 99 additions and 71 deletions

19
diffDomTests.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Diff dom tests</title>
<link rel="stylesheet" href="style.css">
</head>
<body id="body">
<div id="ROOT" />
<script type="text/javascript" src="nimcache/diffDomTests.js"></script>
<script type="text/javascript">
onload(window.location.pathname.split('/')[1])
</script>
</body>
</html>

62
diffDomTests.nim Normal file
View file

@ -0,0 +1,62 @@
import vdom, karax, karaxdsl, jdict, jstrutils, parseutils, sequtils
var
entries: seq[cstring]
# result: 0 1 2 3 4 7 5
proc test1(ev: Event; n: VNode) =
entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ]
entries.insert(cstring("7"), 5)
# result: 8 0 1 2 3 4 7 5
proc test2(ev: Event; n: VNode) =
entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ]
entries.insert(cstring("7"), 5)
entries.insert(cstring("8"), 0)
# result: 2 3 4 1
proc test3(ev: Event; n: VNode) =
entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ]
entries = @[cstring("2"), cstring("3"), cstring("4"), cstring("1") ]
# result: 5 6 7 8
proc test4(ev: Event; n: VNode) =
entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ]
entries = @[cstring("5"), cstring("6"), cstring("7"), cstring("8") ]
# result: 0 1 3 5 4 5
proc test5(ev: Event; n: VNode) =
entries = @[cstring("0"), cstring("1"), cstring("2"), cstring("3"), cstring("4"), cstring("5") ]
entries = @[cstring("0"), cstring("1"), cstring("3"), cstring("5"), cstring("4"), cstring("5") ]
proc createEntry(id: int): VNode =
result = buildHtml():
button(id="" & $id):
text $id
proc createDom(): VNode =
result = buildHtml(tdiv()):
button(onclick=test1):
text "Test1"
button(onclick=test2):
text "Test2"
button(onclick=test3):
text "Test3"
button(onclick=test4):
text "Test4"
button(onclick=test5):
text "Test5"
ul():
for e in entries:
li:
createEntry(parseInt(e))
setRenderer createDom
proc onload(session: cstring) {.exportc.} =
for i in 0..5: # 0_000:
entries.add(cstring($i))
init()

View file

@ -137,7 +137,7 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
# n.nodeName & " = " & oldNode.id & ")")
elif newNode.kind != VNodeKind.text:
let newLength = newNode.len
let oldLength = oldNode.len
var oldLength = oldNode.len
let minLength = min(newLength, oldLength)
assert oldNode.kind == newNode.kind
when false:
@ -181,15 +181,27 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
#kout cstring("----------")
var nextChildPos = oldPos + 1
# kout cstring("pos = " & $pos)
# kout cstring("nextChildPos = " & $nextChildPos)
while pos <= newPos:
if nextChildPos == oldLength:
current.appendChild(vnodeToDom(newNode[pos]))
kout cstring"appendChild"
# kout cstring"appendChild " & newNode[pos].id
# kout cstring("commonPrefix = " & $commonPrefix)
# kout cstring("oldPos = " & $oldPos)
# kout cstring("newPos = " & $newPos)
# kout cstring("newLength = " & $newLength)
# kout cstring("oldLength = " & $oldLength)
# kout cstring("pos = " & $pos)
# kout cstring("nextChildPos = " & $nextChildPos)
# kout cstring("-----------")
#kout cstring("pos = " & $pos)
#kout cstring("newLength = " & $newLength)
else:
kout cstring"insertBefore"
kout cstring"insertBefore " & newNode[pos].id
current.insertBefore(vnodeToDom(newNode[pos]), current.childNodes[nextChildPos])
inc oldLength
inc pos
inc nextChildPos
@ -223,74 +235,6 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
# kout cstring"removeChild"
# current.removeChild(current.lastChild)
proc updateElement1(parent, current: Node, newNode, oldNode: VNode) =
if not equals(newNode, oldNode):
let n = vnodeToDom(newNode)
if parent == nil:
replaceById("ROOT", n)
else:
parent.replaceChild(n, current)
kout cstring"ReplaceChild"
elif newNode.kind != VNodeKind.text:
let newLength = newNode.len
let oldLength = oldNode.len
let minLength = min(newLength, oldLength)
assert oldNode.kind == newNode.kind
when false:
if current.nodeName != toTag[oldNode.kind]:
kout current.nodeName
kout toTag[oldNode.kind]
assert false
# var commonPrefix = 0
# while commonPrefix < minLength and equals(newNode[commonPrefix], oldNode[commonPrefix]):
# inc commonPrefix
# var oldPos = oldLength - 1
# var newPos = newLength - 1
# while oldPos >= commonPrefix and newPos >= commonPrefix and equals(newNode[newPos], oldNode[oldPos]):
# dec oldPos
# dec newPos
# var pos = min(oldPos, newPos) + 1
# var nextChildPos = oldPos + 1
# while pos <= newPos:
# if nextChildPos == oldLength:
# current.appendChild(vnodeToDom(newNode[pos]))
# kout cstring"appendChild"
# else:
# kout cstring"insertBefore"
# current.insertBefore(vnodeToDom(newNode[pos]), current.childNodes[nextChildPos])
# inc pos
# inc nextChildPos
# for i in 0..oldPos-pos:
# kout cstring"removeChild"
# current.removeChild(current.childNodes[pos])
# # kout cstring("commonPrefix = " & $commonPrefix)
# # kout cstring("oldPos = " & $oldPos)
# # kout cstring("newPos = " & $newPos)
# # kout cstring("newLength = " & $newLength)
# # kout cstring("oldLength = " & $oldLength)
# for i in 0..newLength-1:
# updateElement(current, current.childNodes[i],
# newNode[i],
# oldNode[i])
for i in 0..min(newLength, oldLength)-1:
updateElement(current, current.childNodes[i],
newNode[i],
oldNode[i])
if newLength > oldLength:
for i in oldLength..newLength-1:
kout cstring"appendChild"
current.appendChild(vnodeToDom(newNode[i]))
elif oldLength > newLength:
for i in countdown(oldLength-1, newLength):
kout cstring"removeChild"
current.removeChild(current.lastChild)
proc dodraw() =
let newtree = dorender()

View file

@ -119,3 +119,6 @@ proc onload(session: cstring) {.exportc.} =
for i in 0..1: # 0_000:
entries.add((cstring"Entry " & &i, false))
init()
for i in 0..10_000:
entries.add((cstring"Entry " & &i, false))