optimized the diff algorithm further
This commit is contained in:
parent
507094bdfd
commit
b3c83ed119
2 changed files with 48 additions and 9 deletions
|
|
@ -190,13 +190,33 @@ type
|
||||||
EqResult = enum
|
EqResult = enum
|
||||||
componentsIdentical, different, similar, identical, usenewNode
|
componentsIdentical, different, similar, identical, usenewNode
|
||||||
|
|
||||||
|
DifferEnum = enum
|
||||||
|
deKind, deId, deIndex, deText, deComponent, deClass,
|
||||||
|
deSimilar
|
||||||
|
|
||||||
|
when defined(profileKarax):
|
||||||
|
var
|
||||||
|
reasons: array[DifferEnum, int]
|
||||||
|
|
||||||
|
proc echa(a: array[DifferEnum, int]) =
|
||||||
|
for i in low(DifferEnum)..high(DifferEnum):
|
||||||
|
echo i, " value: ", a[i]
|
||||||
|
|
||||||
proc eq(a, b: VNode): EqResult =
|
proc eq(a, b: VNode): EqResult =
|
||||||
if a.kind != b.kind: return different
|
if a.kind != b.kind:
|
||||||
if a.id != b.id: return different
|
when defined(profileKarax): inc reasons[deKind]
|
||||||
|
return different
|
||||||
|
if a.id != b.id:
|
||||||
|
when defined(profileKarax): inc reasons[deId]
|
||||||
|
return different
|
||||||
result = identical
|
result = identical
|
||||||
if a.index != b.index: return different
|
if a.index != b.index:
|
||||||
|
when defined(profileKarax): inc reasons[deIndex]
|
||||||
|
return different
|
||||||
if a.kind == VNodeKind.text:
|
if a.kind == VNodeKind.text:
|
||||||
if a.text != b.text: return different
|
if a.text != b.text:
|
||||||
|
when defined(profileKarax): inc reasons[deText]
|
||||||
|
return similar
|
||||||
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 different
|
if a.text != b.text: return different
|
||||||
if a.len != b.len: return different
|
if a.len != b.len: return different
|
||||||
|
|
@ -204,11 +224,19 @@ proc eq(a, b: VNode): EqResult =
|
||||||
if eq(a[i], b[i]) == different: return different
|
if eq(a[i], b[i]) == different: return different
|
||||||
elif b.kind == VNodeKind.component:
|
elif b.kind == VNodeKind.component:
|
||||||
# different component names mean different components:
|
# different component names mean different components:
|
||||||
if a.text != b.text: return different
|
if a.text != b.text:
|
||||||
if VComponent(a).key != VComponent(b).key: return different
|
when defined(profileKarax): inc reasons[deComponent]
|
||||||
|
return different
|
||||||
|
if VComponent(a).key != VComponent(b).key:
|
||||||
|
when defined(profileKarax): inc reasons[deComponent]
|
||||||
|
return different
|
||||||
return componentsIdentical
|
return componentsIdentical
|
||||||
if a.class != b.class: return different
|
if a.class != b.class:
|
||||||
if not eq(a.style, b.style) or not sameAttrs(a, b): return similar
|
when defined(profileKarax): inc reasons[deClass]
|
||||||
|
return different
|
||||||
|
if not eq(a.style, b.style) or not sameAttrs(a, b):
|
||||||
|
when defined(profileKarax): inc reasons[deSimilar]
|
||||||
|
return similar
|
||||||
# Do not test event listeners here!
|
# Do not test event listeners here!
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
@ -328,6 +356,10 @@ proc diff(newNode, oldNode: VNode; parent, current: Node; kxi: KaraxInstance): E
|
||||||
if result == similar:
|
if result == similar:
|
||||||
updateStyles(newNode, oldNode)
|
updateStyles(newNode, oldNode)
|
||||||
updateAttributes(newNode, oldNode)
|
updateAttributes(newNode, oldNode)
|
||||||
|
if oldNode.kind == VNodeKind.text:
|
||||||
|
oldNode.text = newNode.text
|
||||||
|
oldNode.dom.nodeValue = newNode.text
|
||||||
|
|
||||||
if newNode.events.len != 0 or oldNode.events.len != 0:
|
if newNode.events.len != 0 or oldNode.events.len != 0:
|
||||||
mergeEvents(newNode, oldNode, kxi)
|
mergeEvents(newNode, oldNode, kxi)
|
||||||
if oldNode.kind == VNodeKind.input or oldNode.kind == VNodeKind.textarea:
|
if oldNode.kind == VNodeKind.input or oldNode.kind == VNodeKind.textarea:
|
||||||
|
|
@ -471,7 +503,14 @@ proc dodraw(kxi: KaraxInstance) =
|
||||||
let olddom = document.getElementById(kxi.rootId)
|
let olddom = document.getElementById(kxi.rootId)
|
||||||
discard diff(newtree, kxi.currentTree, nil, olddom, kxi)
|
discard diff(newtree, kxi.currentTree, nil, olddom, kxi)
|
||||||
#kout cstring"patch len ", patches.len
|
#kout cstring"patch len ", patches.len
|
||||||
|
when defined(profileKarax):
|
||||||
|
echo "<<<<<<<<<<<<<<"
|
||||||
|
echa reasons
|
||||||
applyComponents(kxi)
|
applyComponents(kxi)
|
||||||
|
when defined(profileKarax):
|
||||||
|
echo "--------------"
|
||||||
|
echa reasons
|
||||||
|
echo ">>>>>>>>>>>>>>"
|
||||||
applyPatch(kxi)
|
applyPatch(kxi)
|
||||||
kxi.currentTree = newtree
|
kxi.currentTree = newtree
|
||||||
doAssert same(kxi.currentTree, document.getElementById(kxi.rootId))
|
doAssert same(kxi.currentTree, document.getElementById(kxi.rootId))
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ proc getAttr*(n: VNode; key: cstring): cstring =
|
||||||
if n.attrs[i] == key: return n.attrs[i+1]
|
if n.attrs[i] == key: return n.attrs[i+1]
|
||||||
|
|
||||||
proc takeOverAttr*(newNode, oldNode: VNode) =
|
proc takeOverAttr*(newNode, oldNode: VNode) =
|
||||||
oldNode.attrs = newNode.attrs
|
shallowCopy oldNode.attrs, newNode.attrs
|
||||||
|
|
||||||
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]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue