-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Changing the content of an element from an array of children to some innerHTML
content currently produces the following exception:
Uncaught DOMException: Node.removeChild: The node to be removed is not a child of this node
This bug can be reproduced as such:
var patch = snabbdom.init([
snabbdom.propsModule
]);
var el = document.createElement('div');
document.body.appendChild(el);
var vdom = patch(el, snabbdom.h('p', {}, ["Text"]));
patch(vdom, snabbdom.h('p', {props: {innerHTML: "Eh?"}}, []));
In other words:
- Snabbdom renders an element with
TextNode
children - Snabbdom reuses the element for a new vnode that has no children, but instead sets
innerHTML
- Snabbdom calls on the properties module to update the node first, causing it to set innerHTML
- Snabbdom attempts to remove the old
TextNode
from the DOM - The
TextNode
is no longer attached to the DOM; Snabbdom encounters an exception
It can happen when trying to remove elements as well:
var vdom = patch(el, snabbdom.h('p', {}, [snabbdom.h('span', {}, ['LUL'])]));
patch(vdom, snabbdom.h('p', {props: {innerHTML: "Eh?"}}, []));
This time it fails in a different place.
I could provide a PR, but I'm not sure what the preferred fix is. It seems to me that the way Snabbdom allows its modules to "do anything" to a node is somewhat at odds with its assumptions that all DOM operations are safe. My suggestion for a fix is to ensure that the node being removed in DOMAPI.removeChild
is still attached to the DOM (in the position expected by Snabbdom), before attempting to remove it:
function removeChild(node: Node, child: Node): void {
if (child.parentNode === node) {
node.removeChild(child);
}
}
I'm not intimately familiar with the implementation or guiding principles in it, so this may not be your preferred solution.