From c037346f084ef5249e407552059756e1f3416a4f Mon Sep 17 00:00:00 2001 From: geotre Date: Thu, 9 Mar 2023 16:17:56 +0000 Subject: [PATCH] Adds a styleVersion field that tracks the rendered styles version, so the vstyle can be reused (#248) --- karax/karax.nim | 11 ++++++++--- karax/vdom.nim | 2 ++ karax/vstyles.nim | 11 +++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/karax/karax.nim b/karax/karax.nim index a09830b..5697cfa 100644 --- a/karax/karax.nim +++ b/karax/karax.nim @@ -209,7 +209,9 @@ proc toDom*(n: VNode; useAttachedNode: bool; kxi: KaraxInstance = nil): Node = applyEvents(n) if kxi != nil and n == kxi.toFocusV and kxi.toFocus.isNil: kxi.toFocus = result - if not n.style.isNil: applyStyle(result, n.style) + if not n.style.isNil: + applyStyle(result, n.style) + n.styleVersion = n.style.version proc same(n: VNode, e: Node; nesting = 0): bool = if kxi.orphans.contains(n.id): return true @@ -299,7 +301,8 @@ proc eq(a, b: VNode; recursive: bool): EqResult = #if: # when defined(profileKarax): inc reasons[deClass] # return different - if a.class != b.class or not eq(a.style, b.style) or not sameAttrs(a, b): + + if a.class != b.class or not (eq(a.style, b.style) and versionMatch(a.style, b.styleVersion)) or not sameAttrs(a, b): when defined(profileKarax): inc reasons[deSimilar] return similar @@ -316,7 +319,9 @@ proc eq(a, b: VNode; recursive: bool): EqResult = proc updateStyles(newNode, oldNode: VNode) = # we keep the oldNode, but take over the style from the new node: if oldNode.dom != nil: - if newNode.style != nil: applyStyle(oldNode.dom, newNode.style) + if newNode.style != nil: + applyStyle(oldNode.dom, newNode.style) + newNode.styleVersion = newNode.style.version else: oldNode.dom.style = Style() oldNode.dom.class = newNode.class oldNode.style = newNode.style diff --git a/karax/vdom.nim b/karax/vdom.nim index fb3e158..c8b69b1 100644 --- a/karax/vdom.nim +++ b/karax/vdom.nim @@ -162,6 +162,7 @@ type hash*: Hash validHash*: bool style*: VStyle ## the style that should be applied to the virtual node. + styleVersion*: int dom*: Node ## the attached real DOM node. Can be 'nil' if the virtual node ## is not part of the virtual DOM anymore. @@ -277,6 +278,7 @@ proc takeOverFields*(newNode, oldNode: VNode) = take attrs take events take style + take styleVersion take dom proc len*(x: VNode): int = x.kids.len diff --git a/karax/vstyles.nim b/karax/vstyles.nim index 7097aee..b07bc8d 100644 --- a/karax/vstyles.nim +++ b/karax/vstyles.nim @@ -222,6 +222,9 @@ buildLookupTables() when defined(js): type VStyle* = JSeq[cstring] + + proc version*(s: VStyle): int {.importcpp: "(#.__version || 0)".} + proc `version=`*(s: VStyle, v: int) {.importcpp: "#.__version = #;".} else: type VStyle* = ref seq[string] @@ -238,10 +241,18 @@ proc eq*(a, b: VStyle): bool = if a[i] != b[i]: return false return true +proc versionMatch*(s: VStyle, version: int): bool = + when defined(js): + s.isNil or s.version == version + else: + true + proc setAttr*(s: VStyle; a, value: kstring) {.noSideEffect.} = ## inserts (a, value) in sorted order of key `a` # worst case quadratic complexity (if given styles in reverse order), hopefully # not a concern assuming small cardinal + when defined(js): + s.version = s.version + 1 var i = 0 while i < s.len: if s[i] == a: