DOM diff problem: hashing

This commit is contained in:
Roman Vishnevskii 2017-04-08 18:58:08 +07:00
commit c065b8f709
3 changed files with 79 additions and 13 deletions

View file

@ -176,6 +176,3 @@ proc onload(session: cstring) {.exportc.} =
t += dtReset t += dtReset
timeout = setTimeout(test7, t) timeout = setTimeout(test7, t)
t += dtTest
timeout = setTimeout(reset, t)
t += dtReset

View file

@ -109,16 +109,65 @@ proc equals(a, b: VNode): bool =
a.class = b.class a.class = b.class
return true return true
proc getStringHash(s: string): uint64 =
result = 0
for c in s:
result = (result * 257 + uint64(c)) mod 1000000007
proc calcHash(a : VNode) =
if a.validHash:
return
var result : uint64 = 0
for i in a:
i.calcHash()
result = result + i.hash
a.validHash = true
a.hash = (getStringHash(getVNodeData(a)) * 71 + result) mod 1000000007
proc equalsTree(a, b : VNode): bool = proc equalsTree(a, b : VNode): bool =
if not equals(a, b): if not a.validHash:
return false a.calcHash()
else: if not b.validHash:
if len(a) != len(b): b.calcHash()
return false
for i in 0..len(a)-1: return a.hash == b.hash
if not equalsTree(a[i], b[i]):
return false # if not equals(a, b):
return true # return false
# else:
# if len(a) != len(b):
# return false
# for i in 0..len(a)-1:
# if not equalsTree(a[i], b[i]):
# return false
# return true
# kout cstring("a " & $int64(a.hash) & " " & "b " & $int64(b.hash))
# if not equals(a, b):
# if a.hash == b.hash:
# kout cstring("false " & getVNodeData(a) & " " & $int64(a.hash) & " " & getVNodeData(b) & " " & $int64(b.hash))
# kout cstring($int64(getStringHash(getVNodeData(a))) & " " & $int64(getStringHash(getVNodeData(b))))
# for c in getVNodeData(a):
# kout cstring($int64(uint64(c)))
# kout "-------"
# for c in getVNodeData(b):
# kout cstring($int64(uint64(c)))
# return false
# else:
# if len(a) != len(b):
# if a.hash == b.hash:
# kout cstring("false " & getVNodeData(a) & " " & $int64(a.hash) & " " & getVNodeData(b) & " " & $int64(b.hash))
# return false
# for i in 0..len(a)-1:
# if not equalsTree(a[i], b[i]):
# if a.hash == b.hash:
# kout cstring("false " & getVNodeData(a) & " " & $int64(a.hash) & " " & getVNodeData(b) & " " & $int64(b.hash))
# return false
# if a.hash != b.hash:
# kout cstring("true " & getVNodeData(a) & " " & getVNodeData(b))
# return true
proc updateElement(parent, current: Node, newNode, oldNode: VNode) = proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
if not equals(newNode, oldNode): if not equals(newNode, oldNode):
@ -137,7 +186,7 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
kout current.nodeName kout current.nodeName
kout toTag[oldNode.kind] kout toTag[oldNode.kind]
assert false assert false
var commonPrefix = 0 var commonPrefix = 0
while commonPrefix < minLength and equalsTree(newNode[commonPrefix], oldNode[commonPrefix]): while commonPrefix < minLength and equalsTree(newNode[commonPrefix], oldNode[commonPrefix]):
inc commonPrefix inc commonPrefix

View file

@ -38,6 +38,8 @@ type
# even index: key, odd index: value; done this way for memory efficiency: # even index: key, odd index: value; done this way for memory efficiency:
attrs: seq[cstring] attrs: seq[cstring]
events*: seq[(EventKind, EventHandler)] events*: seq[(EventKind, EventHandler)]
hash*: uint64
validHash*: bool
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
@ -129,6 +131,24 @@ proc toString*(n: VNode; result: var string; indent: int) =
for i in 1..indent: result.add ' ' for i in 1..indent: result.add ' '
result.add "\L</" & $n.kind & ">" result.add "\L</" & $n.kind & ">"
proc getVNodeData*(n: VNode): string =
result.add "<" & $n.kind
toStringAttr(id)
toStringAttr(class)
#for k, v in attrs(n):
# result.add " " & $k & " = " & $v
result.add ">"
if n.kind == VNodeKind.text:
result.add n.text
else:
if n.text != nil:
result.add " value = "
result.add n.text
result.add "</" & $n.kind & ">"
proc `$`*(n: VNode): cstring = proc `$`*(n: VNode): cstring =
var res = "" var res = ""
toString(n, res, 0) toString(n, res, 0)