DOM diff problem: fix bug, tests
This commit is contained in:
parent
477bb60b14
commit
c75295d334
4 changed files with 99 additions and 71 deletions
19
diffDomTests.html
Normal file
19
diffDomTests.html
Normal 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
62
diffDomTests.nim
Normal 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()
|
||||||
86
karax.nim
86
karax.nim
|
|
@ -137,7 +137,7 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
|
||||||
# n.nodeName & " = " & oldNode.id & ")")
|
# n.nodeName & " = " & oldNode.id & ")")
|
||||||
elif newNode.kind != VNodeKind.text:
|
elif newNode.kind != VNodeKind.text:
|
||||||
let newLength = newNode.len
|
let newLength = newNode.len
|
||||||
let oldLength = oldNode.len
|
var oldLength = oldNode.len
|
||||||
let minLength = min(newLength, oldLength)
|
let minLength = min(newLength, oldLength)
|
||||||
assert oldNode.kind == newNode.kind
|
assert oldNode.kind == newNode.kind
|
||||||
when false:
|
when false:
|
||||||
|
|
@ -181,15 +181,27 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
|
||||||
#kout cstring("----------")
|
#kout cstring("----------")
|
||||||
|
|
||||||
var nextChildPos = oldPos + 1
|
var nextChildPos = oldPos + 1
|
||||||
|
# kout cstring("pos = " & $pos)
|
||||||
|
# kout cstring("nextChildPos = " & $nextChildPos)
|
||||||
while pos <= newPos:
|
while pos <= newPos:
|
||||||
if nextChildPos == oldLength:
|
if nextChildPos == oldLength:
|
||||||
current.appendChild(vnodeToDom(newNode[pos]))
|
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("pos = " & $pos)
|
||||||
#kout cstring("newLength = " & $newLength)
|
#kout cstring("newLength = " & $newLength)
|
||||||
else:
|
else:
|
||||||
kout cstring"insertBefore"
|
kout cstring"insertBefore " & newNode[pos].id
|
||||||
current.insertBefore(vnodeToDom(newNode[pos]), current.childNodes[nextChildPos])
|
current.insertBefore(vnodeToDom(newNode[pos]), current.childNodes[nextChildPos])
|
||||||
|
inc oldLength
|
||||||
inc pos
|
inc pos
|
||||||
inc nextChildPos
|
inc nextChildPos
|
||||||
|
|
||||||
|
|
@ -223,74 +235,6 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
|
||||||
# kout cstring"removeChild"
|
# kout cstring"removeChild"
|
||||||
# current.removeChild(current.lastChild)
|
# 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() =
|
proc dodraw() =
|
||||||
let newtree = dorender()
|
let newtree = dorender()
|
||||||
|
|
|
||||||
|
|
@ -119,3 +119,6 @@ proc onload(session: cstring) {.exportc.} =
|
||||||
for i in 0..1: # 0_000:
|
for i in 0..1: # 0_000:
|
||||||
entries.add((cstring"Entry " & &i, false))
|
entries.add((cstring"Entry " & &i, false))
|
||||||
init()
|
init()
|
||||||
|
|
||||||
|
for i in 0..10_000:
|
||||||
|
entries.add((cstring"Entry " & &i, false))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue