Element inserts into DOM in wrong location when replacing empty fragment
Author: xariahdailstoneCreated Dec 21, 2025Updated Dec 21, 2025
Given the following HTML:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<div id="elTestHost"></div>
<script type="module">
import { jsx, init, fragment, attributesModule, classModule, propsModule, styleModule } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
const elTestHost = document.getElementById("elTestHost");
const patch = init([ attributesModule, classModule, propsModule, styleModule ], undefined, { experimental: { fragments: true } });
const initVNode = jsx("div", { "attrs": { "id": "elTestHost" } });
let currentVNode = patch(elTestHost, initVNode);
// Point 0
let newVNode = jsx("div", { "attrs": { "id": "elTestHost" } }, [
fragment([]),
jsx("div", { "key": "k2", "attrs": { "data-key": "k2" }, "class": { "key2": true } })
]);
currentVNode = patch(currentVNode, newVNode);
// Point 1
newVNode = jsx("div", { "attrs": { "id": "elTestHost" } }, [
jsx("div", { "key": "k1", "attrs": { "data-key": "k1" }, "class": { "key1": true } }),
jsx("div", { "key": "k2", "attrs": { "data-key": "k2" }, "class": { "key2": true } }),
]);
currentVNode = patch(currentVNode, newVNode);
// Point 2
</script>
</body>
</html>The expectation is that the page DOM should look like the following at each point:
Point 0:
<div id="elTestHost">
</div>Point 1:
<div id="elTestHost">
<div data-key="k2" class="key2"></div>
</div>Point 2 (expected):
<div id="elTestHost">
<div data-key="k1" class="key1"></div>
<div data-key="k2" class="key2"></div>
</div>However, during the patching between points 1 and 2, when the k1 element is being inserted into the DOM in place of the empty fragment from the previous version of the virtual DOM, snabbdom incorrectly inserts k1 into the DOM after k2 instead of before it as the virtual DOM indicates. The actual DOM as of point 2 ends up looking like this:
Point 2 (actual):
<div id="elTestHost">
<div data-key="k2" class="key2"></div>
<div data-key="k1" class="key1"></div>
</div>Source: snabbdom/snabbdom