Avoid using node.childNodes

This commit is contained in:
Roman Vishnevskii 2017-05-02 19:46:20 +07:00
commit 4c582d7c06
2 changed files with 48 additions and 28 deletions

View file

@ -164,7 +164,13 @@ 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 setDomField(a, b: VNode) =
a.dom = b.dom
for i in 0..<len(a):
setDomField(a[i], b[i])
proc updateElement(parent, current: Node, newNode, oldNode: VNode) = proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
newNode.dom = oldNode.dom
if not equalsShallow(newNode, oldNode): if not equalsShallow(newNode, oldNode):
detach(oldNode) detach(oldNode)
let n = vnodeToDom(newNode) let n = vnodeToDom(newNode)
@ -175,7 +181,6 @@ 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,36 +193,50 @@ 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 commonPrefix = 0 var left = 0
while commonPrefix < minLength and var rightNew = newLength - 1
equalsTree(newNode[commonPrefix], oldNode[commonPrefix]): var rightOld = oldLength - 1
inc commonPrefix
var oldPos = oldLength - 1 while left <= min(rightNew, rightOld):
var newPos = newLength - 1 var minRight = min(rightOld, rightNew)
while oldPos >= commonPrefix and newPos >= commonPrefix and
equalsTree(newNode[newPos], oldNode[oldPos]):
dec oldPos
dec newPos
var pos = min(oldPos, newPos) + 1 while left <= minRight and
for i in commonPrefix..pos-1: equalsTree(newNode[left], oldNode[left]):
updateElement(current, current.childNodes[i], newNode[i], oldNode[i]) #newNode[left] = oldNode[left]
setDomField(newNode[left], oldNode[left])
inc left
var nextChildPos = oldPos + 1 while rightOld > left and rightNew > left and
while pos <= newPos: equalsTree(newNode[rightNew], oldNode[rightOld]):
#newNode[rightNew].dom = oldNode[rightOld].dom
setDomField(newNode[rightNew], oldNode[rightOld])
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[rightOld].dom, newNode[rightNew], oldNode[rightOld])
dec rightNew
dec rightOld
var nextChildPos = rightOld + 1
while left <= rightNew:
if nextChildPos == oldLength: if nextChildPos == oldLength:
current.appendChild(vnodeToDom(newNode[pos])) current.appendChild(vnodeToDom(newNode[left]))
else: else:
current.insertBefore(vnodeToDom(newNode[pos]), current.childNodes[nextChildPos]) current.insertBefore(vnodeToDom(newNode[left]), oldNode[rightOld + 1].dom)
# added new Node, so old state of VDOM have one more Node # added new Node, so old state of VDOM have one more Node
inc oldLength inc oldLength
inc pos inc left
inc nextChildPos inc nextChildPos
for i in pos..oldPos: for i in left..rightOld:
current.removeChild(oldNode[i].dom)
detach(oldNode[i]) detach(oldNode[i])
current.removeChild(current.childNodes[pos])
when false: when false:
var drawTimeout: Timeout var drawTimeout: Timeout

View file

@ -166,6 +166,7 @@ proc getAttr*(n: VNode; key: cstring): cstring =
proc len*(x: VNode): int = x.kids.len proc len*(x: VNode): int = x.kids.len
proc `[]`*(x: VNode; idx: int): VNode = x.kids[idx] proc `[]`*(x: VNode; idx: int): VNode = x.kids[idx]
proc `[]=`*(x: VNode; idx: int, y: VNode) = x.kids[idx] = y
proc add*(parent, kid: VNode) = parent.kids.add kid proc add*(parent, kid: VNode) = parent.kids.add kid
proc newVNode*(kind: VNodeKind): VNode = VNode(kind: kind, key: -1) proc newVNode*(kind: VNodeKind): VNode = VNode(kind: kind, key: -1)