diff --git a/packages/dom-expressions/src/client.js b/packages/dom-expressions/src/client.js index e4e6460a1..47dc6a5a2 100644 --- a/packages/dom-expressions/src/client.js +++ b/packages/dom-expressions/src/client.js @@ -460,7 +460,6 @@ function insertExpression(parent, value, current, marker, unwrapArray) { if (value === current) return current; const t = typeof value, multi = marker !== undefined; - parent = (multi && current[0] && current[0].parentNode) || parent; if (t === "string" || t === "number") { if (hydrating) return current; @@ -570,7 +569,17 @@ function appendNodes(parent, array, marker = null) { for (let i = 0, len = array.length; i < len; i++) parent.insertBefore(array[i], marker); } +const moved = new Set(); +let scheduled = false; + function cleanChildren(parent, current, marker, replacement) { + if (!scheduled && moved.size) { + queueMicrotask(() => { + moved.clear(); + scheduled = false; + }) + scheduled = true; + } if (marker === undefined) return (parent.textContent = ""); const node = replacement || document.createTextNode(""); if (current.length) { @@ -579,9 +588,12 @@ function cleanChildren(parent, current, marker, replacement) { const el = current[i]; if (node !== el) { const isParent = el.parentNode === parent; - if (!inserted && !i) - isParent ? parent.replaceChild(node, el) : parent.insertBefore(node, marker); - else isParent && el.remove(); + if (!inserted && !i) { + node.parentNode && moved.add(node); + isParent && !moved.has(el) + ? parent.replaceChild(node, el) + : parent.insertBefore(node, marker); + } else isParent && el.remove(); } else inserted = true; } } else parent.insertBefore(node, marker); diff --git a/packages/dom-expressions/test/dom/insert.spec.js b/packages/dom-expressions/test/dom/insert.spec.js index b4d4b2cf9..60be20a6c 100644 --- a/packages/dom-expressions/test/dom/insert.spec.js +++ b/packages/dom-expressions/test/dom/insert.spec.js @@ -2,7 +2,7 @@ * @jest-environment jsdom */ import * as r from '../../src/client'; -import * as S from "s-js"; +import S from "s-js"; describe("r.insert", () => { //
@@ -355,6 +355,54 @@ describe("r.insert with Markers", () => { expect(parent.innerHTML).toBe('hello '); }); + it("can move a node within a parent with marker", () => { + //