Skip to content

Commit

Permalink
Adds a styleVersion field that tracks the rendered styles version, so…
Browse files Browse the repository at this point in the history
… the vstyle can be reused (#248)
  • Loading branch information
geotre authored Mar 9, 2023
1 parent aa1e53f commit c037346
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 3 deletions.
11 changes: 8 additions & 3 deletions karax/karax.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions karax/vdom.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions karax/vstyles.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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:
Expand Down

0 comments on commit c037346

Please sign in to comment.