about summary refs log tree commit diff stats
path: root/src/html
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-07-01 23:52:52 +0200
committerbptato <nincsnevem662@gmail.com>2023-07-01 23:52:52 +0200
commit249b3e71d9656e41c08dd3b83809c520d34104c8 (patch)
treef1745631a61112a879d9cc992c469c2497775957 /src/html
parentd98de70324e3ef03cde158ce916382ef3092fd9f (diff)
downloadchawan-249b3e71d9656e41c08dd3b83809c520d34104c8.tar.gz
Cache Node.children, Node.childNodes
To avoid unexpected behavior (e.g. node.children != node.children)
Diffstat (limited to 'src/html')
-rw-r--r--src/html/dom.nim27
1 files changed, 23 insertions, 4 deletions
diff --git a/src/html/dom.nim b/src/html/dom.nim
index ee4d5620..40e627eb 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -162,6 +162,8 @@ type
     # (We can't just store pointers, because those may be invalidated by
     # the JavaScript finalizers.)
     liveCollections: HashSet[int]
+    children_cached: HTMLCollection
+    childNodes_cached: NodeList
 
   Attr* = ref object of Node
     namespaceURI* {.jsget.}: string
@@ -995,7 +997,10 @@ func len(collection: Collection): int =
   collection.refreshCollection()
   return collection.snapshot.len
 
-func newCollection[T: Collection](root: Node, match: proc(node: Node): bool {.noSideEffect.}, islive, childonly: bool): T =
+type CollectionMatchFun = proc(node: Node): bool {.noSideEffect.}
+
+func newCollection[T: Collection](root: Node, match: CollectionMatchFun,
+    islive, childonly: bool): T =
   result = T(
     islive: islive,
     childonly: childonly,
@@ -1012,11 +1017,25 @@ func nodeType(node: Node): uint16 {.jsfget.} =
 func isElement(node: Node): bool =
   return node.nodeType == ELEMENT_NODE
 
-func children*(node: Node): HTMLCollection {.jsfget.} =
-  return newCollection[HTMLCollection](node, isElement, true, true)
+func children(node: Node): HTMLCollection {.jsfget.} =
+  if node.children_cached == nil:
+    node.children_cached = newCollection[HTMLCollection](
+      root = node,
+      match = isElement,
+      islive = true,
+      childonly = true
+    )
+  return node.children_cached
 
 func childNodes(node: Node): NodeList {.jsfget.} =
-  return newCollection[NodeList](node, nil, true, true)
+  if node.childNodes_cached == nil:
+    node.childNodes_cached = newCollection[NodeList](
+      root = node,
+      match = nil,
+      islive = true,
+      childonly = true
+    )
+  return node.childNodes_cached
 
 # DOMTokenList
 func length(tokenList: DOMTokenList): int {.jsfget.} =