@wsxjs/wsx-core 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -101,6 +101,7 @@ var _RenderContext = class _RenderContext {
101
101
  * @param fn The function to execute (usually the render method).
102
102
  */
103
103
  static runInContext(component, fn) {
104
+ resetCounterForNewRenderCycle(component);
104
105
  const prev = _RenderContext.current;
105
106
  _RenderContext.current = component;
106
107
  try {
@@ -126,21 +127,20 @@ _RenderContext.current = null;
126
127
  var RenderContext = _RenderContext;
127
128
 
128
129
  // src/utils/cache-key.ts
129
- var POSITION_ID_KEY = "__wsxPositionId";
130
130
  var INDEX_KEY = "__wsxIndex";
131
131
  var componentElementCounters = /* @__PURE__ */ new WeakMap();
132
132
  var componentIdCache = /* @__PURE__ */ new WeakMap();
133
133
  function generateCacheKey(tag, props, componentId, component) {
134
- const positionId = props?.[POSITION_ID_KEY];
135
134
  const userKey = props?.key;
136
135
  const index = props?.[INDEX_KEY];
136
+ const positionId = props?.__wsxPositionId;
137
137
  if (userKey !== void 0 && userKey !== null) {
138
138
  return `${componentId}:${tag}:key-${String(userKey)}`;
139
139
  }
140
140
  if (index !== void 0 && index !== null) {
141
141
  return `${componentId}:${tag}:idx-${String(index)}`;
142
142
  }
143
- if (positionId !== void 0 && positionId !== null && positionId !== "no-id") {
143
+ if (positionId !== void 0 && positionId !== null) {
144
144
  return `${componentId}:${tag}:${String(positionId)}`;
145
145
  }
146
146
  if (component) {
@@ -151,6 +151,9 @@ function generateCacheKey(tag, props, componentId, component) {
151
151
  }
152
152
  return `${componentId}:${tag}:fallback-${Date.now()}-${Math.random()}`;
153
153
  }
154
+ function resetCounterForNewRenderCycle(component) {
155
+ componentElementCounters.set(component, 0);
156
+ }
154
157
  function getComponentId() {
155
158
  const component = RenderContext.getCurrentComponent();
156
159
  if (component) {
@@ -568,7 +571,9 @@ function applySingleProp(element, key, value, tag, isSVG) {
568
571
  }
569
572
  if (key.startsWith("on") && typeof value === "function") {
570
573
  const eventName = key.slice(2).toLowerCase();
574
+ const listenerKey = `__wsxListener_${eventName}`;
571
575
  element.addEventListener(eventName, value);
576
+ element[listenerKey] = value;
572
577
  return;
573
578
  }
574
579
  if (typeof value === "boolean") {
@@ -622,10 +627,269 @@ function createElementWithPropsAndChildren(tag, props, children) {
622
627
  return element;
623
628
  }
624
629
 
630
+ // src/utils/update-children-helpers.ts
631
+ function collectPreservedElements(element) {
632
+ const preserved = [];
633
+ for (let i = 0; i < element.childNodes.length; i++) {
634
+ const child = element.childNodes[i];
635
+ if (shouldPreserveElement(child)) {
636
+ preserved.push(child);
637
+ }
638
+ }
639
+ return preserved;
640
+ }
641
+ function findDOMNodeByReference(oldChild, parent) {
642
+ if (oldChild.parentNode === parent && !shouldPreserveElement(oldChild)) {
643
+ return oldChild;
644
+ }
645
+ return null;
646
+ }
647
+ function findDOMNodeByCacheKey(cacheKey, parent) {
648
+ for (let i = 0; i < parent.childNodes.length; i++) {
649
+ const child = parent.childNodes[i];
650
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
651
+ if (shouldPreserveElement(child)) continue;
652
+ if (getElementCacheKey(child) === cacheKey) {
653
+ return child;
654
+ }
655
+ }
656
+ }
657
+ return null;
658
+ }
659
+ function findElementNode(oldChild, parent) {
660
+ const byRef = findDOMNodeByReference(oldChild, parent);
661
+ if (byRef) return byRef;
662
+ const cacheKey = getElementCacheKey(oldChild);
663
+ if (cacheKey) {
664
+ return findDOMNodeByCacheKey(cacheKey, parent);
665
+ }
666
+ return null;
667
+ }
668
+ function findTextNode(parent, domIndex) {
669
+ while (domIndex.value < parent.childNodes.length) {
670
+ const node = parent.childNodes[domIndex.value];
671
+ if (node.nodeType === Node.TEXT_NODE && node.parentNode === parent) {
672
+ const textNode = node;
673
+ domIndex.value++;
674
+ return textNode;
675
+ }
676
+ domIndex.value++;
677
+ }
678
+ return null;
679
+ }
680
+ function updateOrCreateTextNode(parent, oldNode, newText) {
681
+ if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
682
+ if (oldNode.textContent !== newText) {
683
+ oldNode.textContent = newText;
684
+ }
685
+ return oldNode;
686
+ } else {
687
+ if (!oldNode) {
688
+ for (let i = 0; i < parent.childNodes.length; i++) {
689
+ const node = parent.childNodes[i];
690
+ if (node.nodeType === Node.TEXT_NODE && node.parentNode === parent && node.textContent === newText) {
691
+ return node;
692
+ }
693
+ }
694
+ }
695
+ const newTextNode = document.createTextNode(newText);
696
+ if (oldNode && !shouldPreserveElement(oldNode)) {
697
+ parent.replaceChild(newTextNode, oldNode);
698
+ } else {
699
+ parent.insertBefore(newTextNode, oldNode || null);
700
+ }
701
+ return newTextNode;
702
+ }
703
+ }
704
+ function removeNodeIfNotPreserved(parent, node) {
705
+ if (node && !shouldPreserveElement(node) && node.parentNode === parent) {
706
+ parent.removeChild(node);
707
+ }
708
+ }
709
+ function replaceOrInsertElement(parent, newChild, oldNode) {
710
+ const targetNextSibling = oldNode && shouldPreserveElement(oldNode) ? oldNode : oldNode?.nextSibling || null;
711
+ replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling);
712
+ }
713
+ function replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling) {
714
+ if (newChild.parentNode && newChild.parentNode !== parent) {
715
+ newChild.parentNode.removeChild(newChild);
716
+ }
717
+ const isInCorrectPosition = newChild.parentNode === parent && newChild.nextSibling === targetNextSibling;
718
+ if (isInCorrectPosition) {
719
+ return;
720
+ }
721
+ if (newChild.parentNode === parent) {
722
+ parent.insertBefore(newChild, targetNextSibling);
723
+ return;
724
+ }
725
+ if (oldNode && oldNode.parentNode === parent && !shouldPreserveElement(oldNode)) {
726
+ if (oldNode !== newChild) {
727
+ parent.replaceChild(newChild, oldNode);
728
+ }
729
+ } else {
730
+ if (newChild.parentNode === parent) {
731
+ return;
732
+ }
733
+ const newChildCacheKey = getElementCacheKey(newChild);
734
+ if (!newChildCacheKey) {
735
+ const newChildContent = newChild.textContent || "";
736
+ const newChildTag = newChild.tagName.toLowerCase();
737
+ for (let i = 0; i < parent.childNodes.length; i++) {
738
+ const existingNode = parent.childNodes[i];
739
+ if (existingNode instanceof HTMLElement || existingNode instanceof SVGElement) {
740
+ const existingCacheKey = getElementCacheKey(existingNode);
741
+ if (!existingCacheKey && existingNode.tagName.toLowerCase() === newChildTag && existingNode.textContent === newChildContent && existingNode !== newChild) {
742
+ return;
743
+ }
744
+ }
745
+ }
746
+ }
747
+ parent.insertBefore(newChild, targetNextSibling);
748
+ }
749
+ }
750
+ function appendNewChild(parent, child, processedNodes) {
751
+ if (child === null || child === void 0 || child === false) {
752
+ return;
753
+ }
754
+ if (typeof child === "string" || typeof child === "number") {
755
+ const newTextNode = document.createTextNode(String(child));
756
+ parent.appendChild(newTextNode);
757
+ if (processedNodes) {
758
+ processedNodes.add(newTextNode);
759
+ }
760
+ } else if (child instanceof HTMLElement || child instanceof SVGElement) {
761
+ if (child.parentNode === parent) {
762
+ return;
763
+ }
764
+ if (child.parentNode && child.parentNode !== parent) {
765
+ child.parentNode.removeChild(child);
766
+ }
767
+ parent.appendChild(child);
768
+ if (processedNodes) {
769
+ processedNodes.add(child);
770
+ }
771
+ } else if (child instanceof DocumentFragment) {
772
+ parent.appendChild(child);
773
+ }
774
+ }
775
+ function buildNewChildrenMaps(flatNew) {
776
+ const elementSet = /* @__PURE__ */ new Set();
777
+ const cacheKeyMap = /* @__PURE__ */ new Map();
778
+ for (const child of flatNew) {
779
+ if (child instanceof HTMLElement || child instanceof SVGElement || child instanceof DocumentFragment) {
780
+ elementSet.add(child);
781
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
782
+ const cacheKey = getElementCacheKey(child);
783
+ if (cacheKey) {
784
+ cacheKeyMap.set(cacheKey, child);
785
+ }
786
+ }
787
+ }
788
+ }
789
+ return { elementSet, cacheKeyMap };
790
+ }
791
+ function shouldRemoveNode(node, elementSet, cacheKeyMap, processedNodes) {
792
+ if (shouldPreserveElement(node)) {
793
+ return false;
794
+ }
795
+ if (node.nodeType === Node.TEXT_NODE && processedNodes && processedNodes.has(node)) {
796
+ return false;
797
+ }
798
+ if (node.nodeType === Node.TEXT_NODE && processedNodes) {
799
+ let parent = node.parentNode;
800
+ while (parent) {
801
+ if (processedNodes.has(parent) && parent.parentNode) {
802
+ return false;
803
+ }
804
+ parent = parent.parentNode;
805
+ }
806
+ }
807
+ if (node instanceof HTMLElement || node instanceof SVGElement || node instanceof DocumentFragment) {
808
+ if (elementSet.has(node)) {
809
+ return false;
810
+ }
811
+ if (node instanceof HTMLElement || node instanceof SVGElement) {
812
+ const cacheKey = getElementCacheKey(node);
813
+ if (cacheKey && cacheKeyMap.has(cacheKey)) {
814
+ return false;
815
+ }
816
+ }
817
+ }
818
+ return true;
819
+ }
820
+ function deduplicateCacheKeys(parent, cacheKeyMap) {
821
+ const processedCacheKeys = /* @__PURE__ */ new Set();
822
+ for (let i = parent.childNodes.length - 1; i >= 0; i--) {
823
+ const child = parent.childNodes[i];
824
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
825
+ if (shouldPreserveElement(child)) {
826
+ continue;
827
+ }
828
+ const cacheKey = getElementCacheKey(child);
829
+ if (cacheKey && cacheKeyMap.has(cacheKey) && !processedCacheKeys.has(cacheKey)) {
830
+ processedCacheKeys.add(cacheKey);
831
+ const newChild = cacheKeyMap.get(cacheKey);
832
+ if (child !== newChild) {
833
+ parent.replaceChild(newChild, child);
834
+ }
835
+ } else if (cacheKey && cacheKeyMap.has(cacheKey) && processedCacheKeys.has(cacheKey)) {
836
+ const newChild = cacheKeyMap.get(cacheKey);
837
+ if (child !== newChild) {
838
+ parent.removeChild(child);
839
+ }
840
+ }
841
+ }
842
+ }
843
+ }
844
+ function collectNodesToRemove(parent, elementSet, cacheKeyMap, processedNodes) {
845
+ const nodesToRemove = [];
846
+ for (let i = 0; i < parent.childNodes.length; i++) {
847
+ const node = parent.childNodes[i];
848
+ if (shouldRemoveNode(node, elementSet, cacheKeyMap, processedNodes)) {
849
+ nodesToRemove.push(node);
850
+ }
851
+ }
852
+ return nodesToRemove;
853
+ }
854
+ function removeNodes(parent, nodes, cacheManager) {
855
+ for (let i = nodes.length - 1; i >= 0; i--) {
856
+ const node = nodes[i];
857
+ if (node.parentNode === parent) {
858
+ if (cacheManager && (node instanceof HTMLElement || node instanceof SVGElement)) {
859
+ const metadata = cacheManager.getMetadata(node);
860
+ const refCallback = metadata?.ref;
861
+ if (typeof refCallback === "function") {
862
+ try {
863
+ refCallback(null);
864
+ } catch {
865
+ }
866
+ }
867
+ }
868
+ parent.removeChild(node);
869
+ }
870
+ }
871
+ }
872
+ function reinsertPreservedElements(parent, preservedElements) {
873
+ for (const element of preservedElements) {
874
+ if (element.parentNode !== parent) {
875
+ parent.appendChild(element);
876
+ }
877
+ }
878
+ }
879
+ function flattenChildrenSafe(children) {
880
+ return flattenChildren(children);
881
+ }
882
+
625
883
  // src/utils/element-update.ts
626
884
  function removeProp(element, key, oldValue, tag) {
627
885
  const isSVG = shouldUseSVGNamespace(tag);
628
886
  if (key === "ref") {
887
+ if (typeof oldValue === "function") {
888
+ try {
889
+ oldValue(null);
890
+ } catch {
891
+ }
892
+ }
629
893
  return;
630
894
  }
631
895
  if (key === "className" || key === "class") {
@@ -641,6 +905,13 @@ function removeProp(element, key, oldValue, tag) {
641
905
  return;
642
906
  }
643
907
  if (key.startsWith("on") && typeof oldValue === "function") {
908
+ const eventName = key.slice(2).toLowerCase();
909
+ const listenerKey = `__wsxListener_${eventName}`;
910
+ const savedListener = element[listenerKey];
911
+ if (savedListener) {
912
+ element.removeEventListener(eventName, savedListener);
913
+ delete element[listenerKey];
914
+ }
644
915
  return;
645
916
  }
646
917
  if (key === "value") {
@@ -684,7 +955,13 @@ function applySingleProp2(element, key, value, tag, isSVG) {
684
955
  }
685
956
  if (key.startsWith("on") && typeof value === "function") {
686
957
  const eventName = key.slice(2).toLowerCase();
958
+ const listenerKey = `__wsxListener_${eventName}`;
959
+ const oldListener = element[listenerKey];
960
+ if (oldListener) {
961
+ element.removeEventListener(eventName, oldListener);
962
+ }
687
963
  element.addEventListener(eventName, value);
964
+ element[listenerKey] = value;
688
965
  return;
689
966
  }
690
967
  if (typeof value === "boolean") {
@@ -739,49 +1016,36 @@ function updateProps(element, oldProps, newProps, tag) {
739
1016
  applySingleProp2(element, key, newValue, tag, isSVG);
740
1017
  }
741
1018
  }
742
- function updateChildren(element, oldChildren, newChildren) {
743
- const flatOld = flattenChildren(oldChildren);
744
- const flatNew = flattenChildren(newChildren);
1019
+ function updateChildren(element, oldChildren, newChildren, _cacheManager) {
1020
+ const flatOld = flattenChildrenSafe(oldChildren);
1021
+ const flatNew = flattenChildrenSafe(newChildren);
1022
+ const preservedElements = collectPreservedElements(element);
745
1023
  const minLength = Math.min(flatOld.length, flatNew.length);
746
- let domIndex = 0;
1024
+ const domIndex = { value: 0 };
1025
+ const processedNodes = /* @__PURE__ */ new Set();
747
1026
  for (let i = 0; i < minLength; i++) {
748
1027
  const oldChild = flatOld[i];
749
1028
  const newChild = flatNew[i];
750
1029
  let oldNode = null;
751
1030
  if (oldChild instanceof HTMLElement || oldChild instanceof SVGElement) {
752
- if (oldChild.parentNode === element) {
753
- if (!shouldPreserveElement(oldChild)) {
754
- oldNode = oldChild;
755
- }
756
- } else {
757
- const oldCacheKey = getElementCacheKey(oldChild);
758
- if (oldCacheKey) {
759
- for (let j = 0; j < element.childNodes.length; j++) {
760
- const domChild = element.childNodes[j];
761
- if (domChild instanceof HTMLElement || domChild instanceof SVGElement) {
762
- if (shouldPreserveElement(domChild)) {
763
- continue;
764
- }
765
- const domCacheKey = getElementCacheKey(domChild);
766
- if (domCacheKey === oldCacheKey) {
767
- oldNode = domChild;
768
- break;
769
- }
770
- }
771
- }
1031
+ oldNode = findElementNode(oldChild, element);
1032
+ if (oldNode && oldNode.parentNode === element) {
1033
+ const nodeIndex = Array.from(element.childNodes).indexOf(oldNode);
1034
+ if (nodeIndex !== -1 && nodeIndex >= domIndex.value) {
1035
+ domIndex.value = nodeIndex + 1;
772
1036
  }
773
1037
  }
774
1038
  } else if (typeof oldChild === "string" || typeof oldChild === "number") {
775
- while (domIndex < element.childNodes.length) {
776
- const node = element.childNodes[domIndex];
777
- if (node.nodeType === Node.TEXT_NODE) {
778
- oldNode = node;
779
- domIndex++;
780
- break;
781
- } else if (node.nodeType === Node.ELEMENT_NODE) {
782
- domIndex++;
783
- } else {
784
- domIndex++;
1039
+ oldNode = findTextNode(element, domIndex);
1040
+ if (!oldNode && element.childNodes.length > 0) {
1041
+ const oldText = String(oldChild);
1042
+ for (let j = domIndex.value; j < element.childNodes.length; j++) {
1043
+ const node = element.childNodes[j];
1044
+ if (node.nodeType === Node.TEXT_NODE && node.parentNode === element && node.textContent === oldText) {
1045
+ oldNode = node;
1046
+ domIndex.value = j + 1;
1047
+ break;
1048
+ }
785
1049
  }
786
1050
  }
787
1051
  }
@@ -790,27 +1054,20 @@ function updateChildren(element, oldChildren, newChildren) {
790
1054
  const oldText = String(oldChild);
791
1055
  const newText = String(newChild);
792
1056
  const needsUpdate = oldText !== newText || oldNode && oldNode.nodeType === Node.TEXT_NODE && oldNode.textContent !== newText;
793
- if (!needsUpdate) {
794
- continue;
795
- }
796
- if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
797
- oldNode.textContent = newText;
1057
+ if (needsUpdate) {
1058
+ const updatedNode = updateOrCreateTextNode(element, oldNode, newText);
1059
+ if (updatedNode && !processedNodes.has(updatedNode)) {
1060
+ processedNodes.add(updatedNode);
1061
+ }
798
1062
  } else {
799
- const newTextNode = document.createTextNode(newText);
800
- if (oldNode && !shouldPreserveElement(oldNode)) {
801
- element.replaceChild(newTextNode, oldNode);
802
- } else {
803
- element.insertBefore(newTextNode, oldNode || null);
1063
+ if (oldNode && oldNode.parentNode === element) {
1064
+ processedNodes.add(oldNode);
804
1065
  }
805
1066
  }
806
1067
  } else {
807
- if (oldNode && !shouldPreserveElement(oldNode)) {
808
- element.removeChild(oldNode);
809
- }
1068
+ removeNodeIfNotPreserved(element, oldNode);
810
1069
  if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
811
- if (newChild.parentNode !== element) {
812
- element.insertBefore(newChild, oldNode || null);
813
- }
1070
+ replaceOrInsertElement(element, newChild, oldNode);
814
1071
  } else if (newChild instanceof DocumentFragment) {
815
1072
  element.insertBefore(newChild, oldNode || null);
816
1073
  }
@@ -819,54 +1076,48 @@ function updateChildren(element, oldChildren, newChildren) {
819
1076
  if (oldNode && shouldPreserveElement(oldNode)) {
820
1077
  continue;
821
1078
  }
822
- if (newChild === oldChild) {
823
- continue;
824
- } else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
825
- const oldCacheKey = oldNode && (oldNode instanceof HTMLElement || oldNode instanceof SVGElement) ? getElementCacheKey(oldNode) : null;
826
- const newCacheKey = getElementCacheKey(newChild);
827
- const hasSameCacheKey = oldCacheKey && newCacheKey && oldCacheKey === newCacheKey;
828
- if (oldNode) {
829
- if (!shouldPreserveElement(oldNode)) {
830
- if (oldNode !== newChild) {
831
- if (newChild.parentNode === element) {
832
- if (hasSameCacheKey) {
833
- if (newChild !== oldNode) {
834
- element.replaceChild(newChild, oldNode);
835
- }
836
- } else {
837
- element.removeChild(newChild);
838
- element.replaceChild(newChild, oldNode);
839
- }
840
- } else if (newChild.parentNode) {
841
- newChild.parentNode.removeChild(newChild);
842
- element.replaceChild(newChild, oldNode);
843
- } else {
844
- element.replaceChild(newChild, oldNode);
845
- }
846
- }
847
- } else {
848
- if (newChild.parentNode !== element) {
849
- if (newChild.parentNode) {
850
- newChild.parentNode.removeChild(newChild);
851
- }
852
- element.insertBefore(newChild, oldNode.nextSibling);
1079
+ if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
1080
+ let targetNextSibling = null;
1081
+ let foundPreviousElement = false;
1082
+ for (let j = i - 1; j >= 0; j--) {
1083
+ const prevChild = flatNew[j];
1084
+ if (prevChild instanceof HTMLElement || prevChild instanceof SVGElement) {
1085
+ if (prevChild.parentNode === element) {
1086
+ targetNextSibling = prevChild.nextSibling;
1087
+ foundPreviousElement = true;
1088
+ break;
853
1089
  }
854
1090
  }
855
- } else {
856
- if (newChild.parentNode !== element) {
857
- if (newChild.parentNode) {
858
- newChild.parentNode.removeChild(newChild);
859
- }
860
- element.appendChild(newChild);
861
- }
862
1091
  }
863
- } else {
864
- if (oldNode && !shouldPreserveElement(oldNode)) {
865
- element.removeChild(oldNode);
1092
+ if (!foundPreviousElement) {
1093
+ const firstChild = Array.from(element.childNodes).find(
1094
+ (node) => !shouldPreserveElement(node) && !processedNodes.has(node)
1095
+ );
1096
+ targetNextSibling = firstChild || null;
1097
+ }
1098
+ const isInCorrectPosition = newChild.parentNode === element && newChild.nextSibling === targetNextSibling;
1099
+ if (newChild === oldChild && isInCorrectPosition) {
1100
+ if (oldNode) processedNodes.add(oldNode);
1101
+ processedNodes.add(newChild);
1102
+ continue;
1103
+ }
1104
+ const referenceNode = oldNode && oldNode.parentNode === element ? oldNode : null;
1105
+ replaceOrInsertElementAtPosition(
1106
+ element,
1107
+ newChild,
1108
+ referenceNode,
1109
+ targetNextSibling
1110
+ );
1111
+ if (oldNode && oldNode !== newChild) {
1112
+ processedNodes.delete(oldNode);
866
1113
  }
1114
+ processedNodes.add(newChild);
1115
+ } else {
1116
+ removeNodeIfNotPreserved(element, oldNode);
867
1117
  if (typeof newChild === "string" || typeof newChild === "number") {
868
1118
  const newTextNode = document.createTextNode(String(newChild));
869
1119
  element.insertBefore(newTextNode, oldNode?.nextSibling || null);
1120
+ processedNodes.add(newTextNode);
870
1121
  } else if (newChild instanceof DocumentFragment) {
871
1122
  element.insertBefore(newChild, oldNode?.nextSibling || null);
872
1123
  }
@@ -874,98 +1125,13 @@ function updateChildren(element, oldChildren, newChildren) {
874
1125
  }
875
1126
  }
876
1127
  for (let i = minLength; i < flatNew.length; i++) {
877
- const newChild = flatNew[i];
878
- if (newChild === null || newChild === void 0 || newChild === false) {
879
- continue;
880
- }
881
- if (typeof newChild === "string" || typeof newChild === "number") {
882
- element.appendChild(document.createTextNode(String(newChild)));
883
- } else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
884
- if (newChild.parentNode === element) {
885
- const currentIndex = Array.from(element.childNodes).indexOf(newChild);
886
- const expectedIndex = element.childNodes.length - 1;
887
- if (currentIndex !== expectedIndex) {
888
- element.removeChild(newChild);
889
- element.appendChild(newChild);
890
- }
891
- continue;
892
- } else if (newChild.parentNode) {
893
- newChild.parentNode.removeChild(newChild);
894
- }
895
- element.appendChild(newChild);
896
- } else if (newChild instanceof DocumentFragment) {
897
- element.appendChild(newChild);
898
- }
899
- }
900
- const nodesToRemove = [];
901
- const newChildSet = /* @__PURE__ */ new Set();
902
- const newChildCacheKeyMap = /* @__PURE__ */ new Map();
903
- for (const child of flatNew) {
904
- if (child instanceof HTMLElement || child instanceof SVGElement || child instanceof DocumentFragment) {
905
- newChildSet.add(child);
906
- if (child instanceof HTMLElement || child instanceof SVGElement) {
907
- const cacheKey = getElementCacheKey(child);
908
- if (cacheKey) {
909
- newChildCacheKeyMap.set(cacheKey, child);
910
- }
911
- }
912
- }
913
- }
914
- const processedCacheKeys = /* @__PURE__ */ new Set();
915
- const newChildToIndexMap = /* @__PURE__ */ new Map();
916
- for (let i = 0; i < flatNew.length; i++) {
917
- const child = flatNew[i];
918
- if (child instanceof HTMLElement || child instanceof SVGElement) {
919
- newChildToIndexMap.set(child, i);
920
- }
921
- }
922
- for (let i = element.childNodes.length - 1; i >= 0; i--) {
923
- const child = element.childNodes[i];
924
- if (child instanceof HTMLElement || child instanceof SVGElement) {
925
- if (shouldPreserveElement(child)) {
926
- continue;
927
- }
928
- const cacheKey = getElementCacheKey(child);
929
- if (cacheKey && newChildCacheKeyMap.has(cacheKey) && !processedCacheKeys.has(cacheKey)) {
930
- processedCacheKeys.add(cacheKey);
931
- const newChild = newChildCacheKeyMap.get(cacheKey);
932
- if (child !== newChild) {
933
- if (newChild.parentNode === element) {
934
- element.replaceChild(newChild, child);
935
- } else {
936
- element.replaceChild(newChild, child);
937
- }
938
- } else {
939
- }
940
- }
941
- }
942
- }
943
- for (let i = 0; i < element.childNodes.length; i++) {
944
- const child = element.childNodes[i];
945
- if (shouldPreserveElement(child)) {
946
- continue;
947
- }
948
- if (child instanceof HTMLElement || child instanceof SVGElement) {
949
- if (newChildSet.has(child)) {
950
- continue;
951
- }
952
- const cacheKey = getElementCacheKey(child);
953
- if (cacheKey && newChildCacheKeyMap.has(cacheKey)) {
954
- continue;
955
- }
956
- } else if (child instanceof DocumentFragment) {
957
- if (newChildSet.has(child)) {
958
- continue;
959
- }
960
- }
961
- nodesToRemove.push(child);
962
- }
963
- for (let i = nodesToRemove.length - 1; i >= 0; i--) {
964
- const node = nodesToRemove[i];
965
- if (node.parentNode === element) {
966
- element.removeChild(node);
967
- }
1128
+ appendNewChild(element, flatNew[i], processedNodes);
968
1129
  }
1130
+ const { elementSet, cacheKeyMap } = buildNewChildrenMaps(flatNew);
1131
+ deduplicateCacheKeys(element, cacheKeyMap);
1132
+ const nodesToRemove = collectNodesToRemove(element, elementSet, cacheKeyMap, processedNodes);
1133
+ removeNodes(element, nodesToRemove, _cacheManager);
1134
+ reinsertPreservedElements(element, preservedElements);
969
1135
  }
970
1136
  function updateElement(element, newProps, newChildren, tag, cacheManager) {
971
1137
  const oldMetadata = cacheManager.getMetadata(element);
@@ -976,7 +1142,7 @@ function updateElement(element, newProps, newChildren, tag, cacheManager) {
976
1142
  children: newChildren
977
1143
  });
978
1144
  updateProps(element, oldProps, newProps, tag);
979
- updateChildren(element, oldChildren, newChildren);
1145
+ updateChildren(element, oldChildren, newChildren, cacheManager);
980
1146
  }
981
1147
 
982
1148
  // src/jsx-factory.ts
@@ -2,7 +2,7 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-OXFZ575O.mjs";
5
+ } from "./chunk-5Q2VEEUH.mjs";
6
6
  export {
7
7
  Fragment,
8
8
  jsx,