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