what-core 0.5.5 → 0.5.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "what-core",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "description": "What Framework - The closest framework to vanilla JS",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/dom.js CHANGED
@@ -544,7 +544,7 @@ function reconcileUnkeyed(parent, oldNodes, newVNodes, beforeMarker) {
544
544
  const node = createDOM(newVNode, parent);
545
545
  if (node) {
546
546
  const ref = getInsertionRef(oldNodes, beforeMarker);
547
- parent.insertBefore(node, ref);
547
+ safeInsertBefore(parent, node, ref);
548
548
  newNodes.push(node);
549
549
  }
550
550
  continue;
@@ -659,14 +659,14 @@ function reconcileKeyed(parent, oldNodes, newVNodes, beforeMarker) {
659
659
 
660
660
  // Move if not in LIS
661
661
  if (!lisSet.has(i) && patched.parentNode) {
662
- parent.insertBefore(patched, lastInserted);
662
+ safeInsertBefore(parent, patched, lastInserted);
663
663
  }
664
664
  lastInserted = patched;
665
665
  } else {
666
666
  // Create new node
667
667
  const node = createDOM(vnode, parent);
668
668
  if (node) {
669
- parent.insertBefore(node, lastInserted);
669
+ safeInsertBefore(parent, node, lastInserted);
670
670
  lastInserted = node;
671
671
  }
672
672
  newNodes[i] = node;
@@ -725,6 +725,18 @@ function getInsertionRef(nodes, marker) {
725
725
  return marker ? marker.nextSibling : null;
726
726
  }
727
727
 
728
+ // Safe insertBefore: guards against stale reference nodes from nested reconciliation.
729
+ // When patchNode triggers a child component re-render (via propsSignal.set), the child's
730
+ // effect can run synchronously and mutate the DOM tree, leaving the parent's reference
731
+ // node detached. This helper falls back to appendChild when the ref is stale.
732
+ function safeInsertBefore(parent, node, ref) {
733
+ if (ref && ref.parentNode === parent) {
734
+ parent.insertBefore(node, ref);
735
+ } else {
736
+ parent.appendChild(node);
737
+ }
738
+ }
739
+
728
740
  // Helper: clean up array marker range (startMarker .. endMarker) and return a clean replacement node
729
741
  function cleanupArrayMarkers(parent, startMarker) {
730
742
  const endMarker = startMarker._arrayEnd;
package/src/render.js CHANGED
@@ -136,7 +136,10 @@ function reconcileInsert(parent, value, current, marker) {
136
136
  for (let i = newNodes.length - 1; i >= 0; i--) {
137
137
  const node = newNodes[i];
138
138
  if (node.parentNode !== parent || node.nextSibling !== ref) {
139
- parent.insertBefore(node, ref);
139
+ // Guard against stale ref from nested reconciliation
140
+ if (ref && ref.parentNode !== parent) ref = null;
141
+ if (ref) parent.insertBefore(node, ref);
142
+ else parent.appendChild(node);
140
143
  }
141
144
  ref = node;
142
145
  }
@@ -360,6 +363,8 @@ function _reconcileMiddle(parent, endMarker, oldItems, newItems, mappedNodes, di
360
363
  const mi = i - start;
361
364
  if (oldIndices[mi] === -1 || !inLIS[mi]) {
362
365
  // New item or moved item — insert
366
+ // Guard against stale nextSibling from nested reconciliation
367
+ if (nextSibling && nextSibling.parentNode !== parent) nextSibling = endMarker;
363
368
  parent.insertBefore(newMapped[i], nextSibling);
364
369
  }
365
370
  nextSibling = newMapped[i];
@@ -649,6 +654,8 @@ function reconcileKeyed(parent, endMarker, oldItems, newItems, mappedNodes, disp
649
654
  for (let i = newEnd; i >= start; i--) {
650
655
  const mi = i - start;
651
656
  if (oldIndices[mi] === -1 || !inLIS[mi]) {
657
+ // Guard against stale nextSibling from nested reconciliation
658
+ if (nextSibling && nextSibling.parentNode !== parent) nextSibling = endMarker;
652
659
  parent.insertBefore(newMapped[i], nextSibling);
653
660
  }
654
661
  nextSibling = newMapped[i];