@wsxjs/wsx-core 0.0.22 → 0.0.23

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.
@@ -622,6 +622,185 @@ function createElementWithPropsAndChildren(tag, props, children) {
622
622
  return element;
623
623
  }
624
624
 
625
+ // src/utils/update-children-helpers.ts
626
+ function collectPreservedElements(element) {
627
+ const preserved = [];
628
+ for (let i = 0; i < element.childNodes.length; i++) {
629
+ const child = element.childNodes[i];
630
+ if (shouldPreserveElement(child)) {
631
+ preserved.push(child);
632
+ }
633
+ }
634
+ return preserved;
635
+ }
636
+ function findDOMNodeByReference(oldChild, parent) {
637
+ if (oldChild.parentNode === parent && !shouldPreserveElement(oldChild)) {
638
+ return oldChild;
639
+ }
640
+ return null;
641
+ }
642
+ function findDOMNodeByCacheKey(cacheKey, parent) {
643
+ for (let i = 0; i < parent.childNodes.length; i++) {
644
+ const child = parent.childNodes[i];
645
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
646
+ if (shouldPreserveElement(child)) continue;
647
+ if (getElementCacheKey(child) === cacheKey) {
648
+ return child;
649
+ }
650
+ }
651
+ }
652
+ return null;
653
+ }
654
+ function findElementNode(oldChild, parent) {
655
+ const byRef = findDOMNodeByReference(oldChild, parent);
656
+ if (byRef) return byRef;
657
+ const cacheKey = getElementCacheKey(oldChild);
658
+ if (cacheKey) {
659
+ return findDOMNodeByCacheKey(cacheKey, parent);
660
+ }
661
+ return null;
662
+ }
663
+ function findTextNode(parent, domIndex) {
664
+ while (domIndex.value < parent.childNodes.length) {
665
+ const node = parent.childNodes[domIndex.value];
666
+ if (node.nodeType === Node.TEXT_NODE) {
667
+ const textNode = node;
668
+ domIndex.value++;
669
+ return textNode;
670
+ }
671
+ domIndex.value++;
672
+ }
673
+ return null;
674
+ }
675
+ function updateOrCreateTextNode(parent, oldNode, newText) {
676
+ if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
677
+ if (oldNode.textContent !== newText) {
678
+ oldNode.textContent = newText;
679
+ }
680
+ } else {
681
+ const newTextNode = document.createTextNode(newText);
682
+ if (oldNode && !shouldPreserveElement(oldNode)) {
683
+ parent.replaceChild(newTextNode, oldNode);
684
+ } else {
685
+ parent.insertBefore(newTextNode, oldNode || null);
686
+ }
687
+ }
688
+ }
689
+ function removeNodeIfNotPreserved(parent, node) {
690
+ if (node && !shouldPreserveElement(node) && node.parentNode === parent) {
691
+ parent.removeChild(node);
692
+ }
693
+ }
694
+ function replaceOrInsertElement(parent, newChild, oldNode) {
695
+ if (newChild.parentNode && newChild.parentNode !== parent) {
696
+ newChild.parentNode.removeChild(newChild);
697
+ }
698
+ if (oldNode && !shouldPreserveElement(oldNode)) {
699
+ if (oldNode !== newChild) {
700
+ parent.replaceChild(newChild, oldNode);
701
+ }
702
+ } else if (newChild.parentNode !== parent) {
703
+ parent.insertBefore(newChild, oldNode || null);
704
+ }
705
+ }
706
+ function appendNewChild(parent, child) {
707
+ if (child === null || child === void 0 || child === false) {
708
+ return;
709
+ }
710
+ if (typeof child === "string" || typeof child === "number") {
711
+ parent.appendChild(document.createTextNode(String(child)));
712
+ } else if (child instanceof HTMLElement || child instanceof SVGElement) {
713
+ if (child.parentNode && child.parentNode !== parent) {
714
+ child.parentNode.removeChild(child);
715
+ }
716
+ if (child.parentNode !== parent) {
717
+ parent.appendChild(child);
718
+ }
719
+ } else if (child instanceof DocumentFragment) {
720
+ parent.appendChild(child);
721
+ }
722
+ }
723
+ function buildNewChildrenMaps(flatNew) {
724
+ const elementSet = /* @__PURE__ */ new Set();
725
+ const cacheKeyMap = /* @__PURE__ */ new Map();
726
+ for (const child of flatNew) {
727
+ if (child instanceof HTMLElement || child instanceof SVGElement || child instanceof DocumentFragment) {
728
+ elementSet.add(child);
729
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
730
+ const cacheKey = getElementCacheKey(child);
731
+ if (cacheKey) {
732
+ cacheKeyMap.set(cacheKey, child);
733
+ }
734
+ }
735
+ }
736
+ }
737
+ return { elementSet, cacheKeyMap };
738
+ }
739
+ function shouldRemoveNode(node, elementSet, cacheKeyMap) {
740
+ if (shouldPreserveElement(node)) {
741
+ return false;
742
+ }
743
+ if (node instanceof HTMLElement || node instanceof SVGElement || node instanceof DocumentFragment) {
744
+ if (elementSet.has(node)) {
745
+ return false;
746
+ }
747
+ if (node instanceof HTMLElement || node instanceof SVGElement) {
748
+ const cacheKey = getElementCacheKey(node);
749
+ if (cacheKey && cacheKeyMap.has(cacheKey)) {
750
+ return false;
751
+ }
752
+ }
753
+ }
754
+ return true;
755
+ }
756
+ function deduplicateCacheKeys(parent, cacheKeyMap) {
757
+ const processedCacheKeys = /* @__PURE__ */ new Set();
758
+ for (let i = parent.childNodes.length - 1; i >= 0; i--) {
759
+ const child = parent.childNodes[i];
760
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
761
+ if (shouldPreserveElement(child)) {
762
+ continue;
763
+ }
764
+ const cacheKey = getElementCacheKey(child);
765
+ if (cacheKey && cacheKeyMap.has(cacheKey) && !processedCacheKeys.has(cacheKey)) {
766
+ processedCacheKeys.add(cacheKey);
767
+ const newChild = cacheKeyMap.get(cacheKey);
768
+ if (child !== newChild) {
769
+ parent.replaceChild(newChild, child);
770
+ }
771
+ }
772
+ }
773
+ }
774
+ }
775
+ function collectNodesToRemove(parent, elementSet, cacheKeyMap) {
776
+ const nodesToRemove = [];
777
+ for (let i = 0; i < parent.childNodes.length; i++) {
778
+ const node = parent.childNodes[i];
779
+ if (shouldRemoveNode(node, elementSet, cacheKeyMap)) {
780
+ nodesToRemove.push(node);
781
+ }
782
+ }
783
+ return nodesToRemove;
784
+ }
785
+ function removeNodes(parent, nodes) {
786
+ for (let i = nodes.length - 1; i >= 0; i--) {
787
+ const node = nodes[i];
788
+ if (node.parentNode === parent) {
789
+ parent.removeChild(node);
790
+ }
791
+ }
792
+ }
793
+ function reinsertPreservedElements(parent, preservedElements) {
794
+ for (const element of preservedElements) {
795
+ if (element.parentNode !== parent) {
796
+ parent.appendChild(element);
797
+ }
798
+ }
799
+ }
800
+ function flattenChildrenSafe(children) {
801
+ return flattenChildren(children);
802
+ }
803
+
625
804
  // src/utils/element-update.ts
626
805
  function removeProp(element, key, oldValue, tag) {
627
806
  const isSVG = shouldUseSVGNamespace(tag);
@@ -739,49 +918,34 @@ function updateProps(element, oldProps, newProps, tag) {
739
918
  applySingleProp2(element, key, newValue, tag, isSVG);
740
919
  }
741
920
  }
742
- function updateChildren(element, oldChildren, newChildren) {
743
- const flatOld = flattenChildren(oldChildren);
744
- const flatNew = flattenChildren(newChildren);
921
+ function updateChildren(element, oldChildren, newChildren, cacheManager) {
922
+ const flatOld = flattenChildrenSafe(oldChildren);
923
+ const flatNew = flattenChildrenSafe(newChildren);
924
+ const preservedElements = collectPreservedElements(element);
745
925
  const minLength = Math.min(flatOld.length, flatNew.length);
746
- let domIndex = 0;
926
+ const domIndex = { value: 0 };
747
927
  for (let i = 0; i < minLength; i++) {
748
928
  const oldChild = flatOld[i];
749
929
  const newChild = flatNew[i];
750
930
  let oldNode = null;
751
931
  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
- }
932
+ oldNode = findElementNode(oldChild, element);
933
+ if (oldNode && oldNode.parentNode === element) {
934
+ const nodeIndex = Array.from(element.childNodes).indexOf(oldNode);
935
+ if (nodeIndex !== -1 && nodeIndex >= domIndex.value) {
936
+ domIndex.value = nodeIndex + 1;
772
937
  }
773
938
  }
774
939
  } 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++;
940
+ oldNode = findTextNode(element, domIndex);
941
+ if (!oldNode && element.childNodes.length > 0) {
942
+ for (let j = domIndex.value; j < element.childNodes.length; j++) {
943
+ const node = element.childNodes[j];
944
+ if (node.nodeType === Node.TEXT_NODE) {
945
+ oldNode = node;
946
+ domIndex.value = j + 1;
947
+ break;
948
+ }
785
949
  }
786
950
  }
787
951
  }
@@ -790,27 +954,13 @@ function updateChildren(element, oldChildren, newChildren) {
790
954
  const oldText = String(oldChild);
791
955
  const newText = String(newChild);
792
956
  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;
798
- } 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);
804
- }
957
+ if (needsUpdate) {
958
+ updateOrCreateTextNode(element, oldNode, newText);
805
959
  }
806
960
  } else {
807
- if (oldNode && !shouldPreserveElement(oldNode)) {
808
- element.removeChild(oldNode);
809
- }
961
+ removeNodeIfNotPreserved(element, oldNode);
810
962
  if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
811
- if (newChild.parentNode !== element) {
812
- element.insertBefore(newChild, oldNode || null);
813
- }
963
+ replaceOrInsertElement(element, newChild, oldNode);
814
964
  } else if (newChild instanceof DocumentFragment) {
815
965
  element.insertBefore(newChild, oldNode || null);
816
966
  }
@@ -819,51 +969,27 @@ function updateChildren(element, oldChildren, newChildren) {
819
969
  if (oldNode && shouldPreserveElement(oldNode)) {
820
970
  continue;
821
971
  }
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);
972
+ if (newChild === oldChild && (newChild instanceof HTMLElement || newChild instanceof SVGElement)) {
973
+ if (cacheManager) {
974
+ const childMetadata = cacheManager.getMetadata(newChild);
975
+ if (childMetadata) {
976
+ if (oldNode === newChild && newChild.parentNode === element) {
977
+ continue;
853
978
  }
854
979
  }
855
980
  } else {
856
- if (newChild.parentNode !== element) {
857
- if (newChild.parentNode) {
858
- newChild.parentNode.removeChild(newChild);
859
- }
860
- element.appendChild(newChild);
981
+ if (oldNode === newChild && newChild.parentNode === element) {
982
+ continue;
861
983
  }
862
984
  }
863
- } else {
864
- if (oldNode && !shouldPreserveElement(oldNode)) {
865
- element.removeChild(oldNode);
985
+ }
986
+ if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
987
+ if (newChild.parentNode === element && oldNode === newChild) {
988
+ continue;
866
989
  }
990
+ replaceOrInsertElement(element, newChild, oldNode);
991
+ } else {
992
+ removeNodeIfNotPreserved(element, oldNode);
867
993
  if (typeof newChild === "string" || typeof newChild === "number") {
868
994
  const newTextNode = document.createTextNode(String(newChild));
869
995
  element.insertBefore(newTextNode, oldNode?.nextSibling || null);
@@ -874,98 +1000,13 @@ function updateChildren(element, oldChildren, newChildren) {
874
1000
  }
875
1001
  }
876
1002
  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
- }
1003
+ appendNewChild(element, flatNew[i]);
968
1004
  }
1005
+ const { elementSet, cacheKeyMap } = buildNewChildrenMaps(flatNew);
1006
+ deduplicateCacheKeys(element, cacheKeyMap);
1007
+ const nodesToRemove = collectNodesToRemove(element, elementSet, cacheKeyMap);
1008
+ removeNodes(element, nodesToRemove);
1009
+ reinsertPreservedElements(element, preservedElements);
969
1010
  }
970
1011
  function updateElement(element, newProps, newChildren, tag, cacheManager) {
971
1012
  const oldMetadata = cacheManager.getMetadata(element);
@@ -976,7 +1017,7 @@ function updateElement(element, newProps, newChildren, tag, cacheManager) {
976
1017
  children: newChildren
977
1018
  });
978
1019
  updateProps(element, oldProps, newProps, tag);
979
- updateChildren(element, oldChildren, newChildren);
1020
+ updateChildren(element, oldChildren, newChildren, cacheManager);
980
1021
  }
981
1022
 
982
1023
  // 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-ESZYREJK.mjs";
6
6
  export {
7
7
  Fragment,
8
8
  jsx,