@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/{chunk-OXFZ575O.mjs → chunk-5Q2VEEUH.mjs} +352 -186
- package/dist/index.js +418 -215
- package/dist/index.mjs +67 -30
- package/dist/jsx-runtime.js +352 -186
- package/dist/jsx-runtime.mjs +1 -1
- package/dist/jsx.js +352 -186
- package/dist/jsx.mjs +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +2 -2
- package/src/base-component.ts +27 -0
- package/src/light-component.ts +20 -8
- package/src/render-context.ts +4 -0
- package/src/utils/cache-key.ts +27 -21
- package/src/utils/element-creation.ts +5 -0
- package/src/utils/element-update.ts +192 -309
- package/src/utils/update-children-helpers.ts +508 -0
- package/src/web-component.ts +72 -41
package/dist/jsx-runtime.js
CHANGED
|
@@ -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
|
|
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 =
|
|
744
|
-
const flatNew =
|
|
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
|
-
|
|
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
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
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
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
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 (
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
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
|
-
|
|
800
|
-
|
|
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
|
-
|
|
808
|
-
element.removeChild(oldNode);
|
|
809
|
-
}
|
|
1068
|
+
removeNodeIfNotPreserved(element, oldNode);
|
|
810
1069
|
if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
|
|
811
|
-
|
|
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
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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
|
-
|
|
864
|
-
|
|
865
|
-
|
|
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
|
-
|
|
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
|