@wsxjs/wsx-core 0.0.21 → 0.0.22

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.
@@ -171,6 +171,10 @@ var CACHE_KEY_PROP = "__wsxCacheKey";
171
171
  function markElement(element, cacheKey) {
172
172
  element[CACHE_KEY_PROP] = cacheKey;
173
173
  }
174
+ function getElementCacheKey(element) {
175
+ const key = element[CACHE_KEY_PROP];
176
+ return key !== void 0 ? String(key) : null;
177
+ }
174
178
  function isCreatedByH(element) {
175
179
  if (!(element instanceof HTMLElement || element instanceof SVGElement)) {
176
180
  return false;
@@ -718,9 +722,18 @@ function updateProps(element, oldProps, newProps, tag) {
718
722
  if (oldValue === newValue) {
719
723
  continue;
720
724
  }
725
+ if (oldValue === void 0) {
726
+ applySingleProp2(element, key, newValue, tag, isSVG);
727
+ continue;
728
+ }
721
729
  if (typeof oldValue === "object" && oldValue !== null && typeof newValue === "object" && newValue !== null) {
722
- if (JSON.stringify(oldValue) === JSON.stringify(newValue)) {
723
- continue;
730
+ try {
731
+ const oldJson = JSON.stringify(oldValue);
732
+ const newJson = JSON.stringify(newValue);
733
+ if (oldJson === newJson) {
734
+ continue;
735
+ }
736
+ } catch {
724
737
  }
725
738
  }
726
739
  applySingleProp2(element, key, newValue, tag, isSVG);
@@ -730,68 +743,132 @@ function updateChildren(element, oldChildren, newChildren) {
730
743
  const flatOld = flattenChildren(oldChildren);
731
744
  const flatNew = flattenChildren(newChildren);
732
745
  const minLength = Math.min(flatOld.length, flatNew.length);
746
+ let domIndex = 0;
733
747
  for (let i = 0; i < minLength; i++) {
734
748
  const oldChild = flatOld[i];
735
749
  const newChild = flatNew[i];
750
+ let oldNode = null;
751
+ 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
+ }
772
+ }
773
+ }
774
+ } 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++;
785
+ }
786
+ }
787
+ }
736
788
  if (typeof oldChild === "string" || typeof oldChild === "number") {
737
789
  if (typeof newChild === "string" || typeof newChild === "number") {
738
- const textNode = element.childNodes[i];
739
- if (textNode && textNode.nodeType === Node.TEXT_NODE) {
740
- textNode.textContent = String(newChild);
790
+ const oldText = String(oldChild);
791
+ const newText = String(newChild);
792
+ 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;
741
798
  } else {
742
- const newTextNode = document.createTextNode(String(newChild));
743
- if (textNode) {
744
- element.replaceChild(newTextNode, textNode);
799
+ const newTextNode = document.createTextNode(newText);
800
+ if (oldNode && !shouldPreserveElement(oldNode)) {
801
+ element.replaceChild(newTextNode, oldNode);
745
802
  } else {
746
- element.appendChild(newTextNode);
803
+ element.insertBefore(newTextNode, oldNode || null);
747
804
  }
748
805
  }
749
806
  } else {
750
- const textNode = element.childNodes[i];
751
- if (textNode) {
752
- if (!shouldPreserveElement(textNode)) {
753
- element.removeChild(textNode);
754
- }
807
+ if (oldNode && !shouldPreserveElement(oldNode)) {
808
+ element.removeChild(oldNode);
755
809
  }
756
- if (typeof newChild === "string" || typeof newChild === "number") {
757
- element.appendChild(document.createTextNode(String(newChild)));
758
- } else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
759
- element.appendChild(newChild);
810
+ if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
811
+ if (newChild.parentNode !== element) {
812
+ element.insertBefore(newChild, oldNode || null);
813
+ }
760
814
  } else if (newChild instanceof DocumentFragment) {
761
- element.appendChild(newChild);
815
+ element.insertBefore(newChild, oldNode || null);
762
816
  }
763
817
  }
764
818
  } else if (oldChild instanceof HTMLElement || oldChild instanceof SVGElement) {
819
+ if (oldNode && shouldPreserveElement(oldNode)) {
820
+ continue;
821
+ }
765
822
  if (newChild === oldChild) {
766
823
  continue;
767
824
  } else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
768
- const oldNode = element.childNodes[i];
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;
769
828
  if (oldNode) {
770
829
  if (!shouldPreserveElement(oldNode)) {
771
830
  if (oldNode !== newChild) {
772
- element.replaceChild(newChild, oldNode);
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
+ }
773
846
  }
774
847
  } else {
775
848
  if (newChild.parentNode !== element) {
776
- element.appendChild(newChild);
849
+ if (newChild.parentNode) {
850
+ newChild.parentNode.removeChild(newChild);
851
+ }
852
+ element.insertBefore(newChild, oldNode.nextSibling);
777
853
  }
778
854
  }
779
855
  } else {
780
856
  if (newChild.parentNode !== element) {
857
+ if (newChild.parentNode) {
858
+ newChild.parentNode.removeChild(newChild);
859
+ }
781
860
  element.appendChild(newChild);
782
861
  }
783
862
  }
784
863
  } else {
785
- const oldNode = element.childNodes[i];
786
- if (oldNode) {
787
- if (!shouldPreserveElement(oldNode)) {
788
- element.removeChild(oldNode);
789
- }
864
+ if (oldNode && !shouldPreserveElement(oldNode)) {
865
+ element.removeChild(oldNode);
790
866
  }
791
867
  if (typeof newChild === "string" || typeof newChild === "number") {
792
- element.appendChild(document.createTextNode(String(newChild)));
868
+ const newTextNode = document.createTextNode(String(newChild));
869
+ element.insertBefore(newTextNode, oldNode?.nextSibling || null);
793
870
  } else if (newChild instanceof DocumentFragment) {
794
- element.appendChild(newChild);
871
+ element.insertBefore(newChild, oldNode?.nextSibling || null);
795
872
  }
796
873
  }
797
874
  }
@@ -804,20 +881,85 @@ function updateChildren(element, oldChildren, newChildren) {
804
881
  if (typeof newChild === "string" || typeof newChild === "number") {
805
882
  element.appendChild(document.createTextNode(String(newChild)));
806
883
  } else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
807
- if (newChild.parentNode !== element) {
808
- element.appendChild(newChild);
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);
809
894
  }
895
+ element.appendChild(newChild);
810
896
  } else if (newChild instanceof DocumentFragment) {
811
897
  element.appendChild(newChild);
812
898
  }
813
899
  }
814
900
  const nodesToRemove = [];
815
- for (let i = flatNew.length; i < element.childNodes.length; i++) {
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--) {
816
923
  const child = element.childNodes[i];
817
- if (!shouldPreserveElement(child)) {
818
- nodesToRemove.push(child);
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
+ }
819
941
  }
820
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
+ }
821
963
  for (let i = nodesToRemove.length - 1; i >= 0; i--) {
822
964
  const node = nodesToRemove[i];
823
965
  if (node.parentNode === element) {
@@ -829,12 +971,12 @@ function updateElement(element, newProps, newChildren, tag, cacheManager) {
829
971
  const oldMetadata = cacheManager.getMetadata(element);
830
972
  const oldProps = oldMetadata?.props || null;
831
973
  const oldChildren = oldMetadata?.children || [];
832
- updateProps(element, oldProps, newProps, tag);
833
- updateChildren(element, oldChildren, newChildren);
834
974
  cacheManager.setMetadata(element, {
835
975
  props: newProps || {},
836
976
  children: newChildren
837
977
  });
978
+ updateProps(element, oldProps, newProps, tag);
979
+ updateChildren(element, oldChildren, newChildren);
838
980
  }
839
981
 
840
982
  // src/jsx-factory.ts
@@ -848,7 +990,36 @@ function h(tag, props = {}, ...children) {
848
990
  if (context && cacheManager) {
849
991
  return tryUseCacheOrCreate(tag, props, children, context, cacheManager);
850
992
  }
851
- return createElementWithPropsAndChildren(tag, props, children);
993
+ try {
994
+ const nodeEnv = typeof globalThis.process !== "undefined" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
995
+ globalThis.process.env?.NODE_ENV;
996
+ if (nodeEnv === "development") {
997
+ if (!context) {
998
+ logger3.debug(
999
+ `h() called without render context. Tag: "${tag}", ComponentId: "${getComponentId()}"`,
1000
+ {
1001
+ tag,
1002
+ props: props ? Object.keys(props) : [],
1003
+ hasCacheManager: !!cacheManager
1004
+ }
1005
+ );
1006
+ } else if (!cacheManager) {
1007
+ logger3.debug(
1008
+ `h() called with context but no cache manager. Tag: "${tag}", Component: "${context.constructor.name}"`,
1009
+ {
1010
+ tag,
1011
+ component: context.constructor.name
1012
+ }
1013
+ );
1014
+ }
1015
+ }
1016
+ } catch {
1017
+ }
1018
+ const element = createElementWithPropsAndChildren(tag, props, children);
1019
+ const componentId = getComponentId();
1020
+ const cacheKey = generateCacheKey(tag, props, componentId, context || void 0);
1021
+ markElement(element, cacheKey);
1022
+ return element;
852
1023
  }
853
1024
  function tryUseCacheOrCreate(tag, props, children, context, cacheManager) {
854
1025
  try {
@@ -858,6 +1029,14 @@ function tryUseCacheOrCreate(tag, props, children, context, cacheManager) {
858
1029
  if (cachedElement) {
859
1030
  const element2 = cachedElement;
860
1031
  updateElement(element2, props, children, tag, cacheManager);
1032
+ const isCustomElement = tag.includes("-") && customElements.get(tag);
1033
+ if (isCustomElement && element2.isConnected) {
1034
+ const parent = element2.parentNode;
1035
+ if (parent) {
1036
+ parent.removeChild(element2);
1037
+ parent.appendChild(element2);
1038
+ }
1039
+ }
861
1040
  return element2;
862
1041
  }
863
1042
  const element = createElementWithPropsAndChildren(tag, props, children);
@@ -881,7 +1060,12 @@ function handleCacheError(error, tag, props, children) {
881
1060
  }
882
1061
  } catch {
883
1062
  }
884
- return createElementWithPropsAndChildren(tag, props, children);
1063
+ const element = createElementWithPropsAndChildren(tag, props, children);
1064
+ const context = RenderContext.getCurrentComponent();
1065
+ const componentId = getComponentId();
1066
+ const cacheKey = generateCacheKey(tag, props, componentId, context || void 0);
1067
+ markElement(element, cacheKey);
1068
+ return element;
885
1069
  }
886
1070
  function Fragment(_props, children) {
887
1071
  const fragment = document.createDocumentFragment();
@@ -2,7 +2,7 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-AR3DIDLV.mjs";
5
+ } from "./chunk-OXFZ575O.mjs";
6
6
  export {
7
7
  Fragment,
8
8
  jsx,