diff --git a/src/browser/tests/element/replace_with.html b/src/browser/tests/element/replace_with.html index 14940f4d..0597b9b1 100644 --- a/src/browser/tests/element/replace_with.html +++ b/src/browser/tests/element/replace_with.html @@ -332,3 +332,34 @@ testing.expectEqual(new13, document.getElementById('new13')); testing.expectEqual(l4, new13.parentElement); + + + diff --git a/src/browser/tests/node/replace_child.html b/src/browser/tests/node/replace_child.html index 51b0a173..b45a3d51 100644 --- a/src/browser/tests/node/replace_child.html +++ b/src/browser/tests/node/replace_child.html @@ -40,3 +40,34 @@ testing.expectEqual(c3, d1.replaceChild(c3, c3)); assertChildren([c3, c4], d1) + + diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index 655a4e9d..a26f1f80 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -872,7 +872,9 @@ pub fn replaceWith(self: *Element, nodes: []const Node.NodeOrText, page: *Page) ); } - if (rm_ref_node) { + // Re-check parent after insertNodeRelative since callbacks (e.g. connectedCallback) + // could have already removed ref_node from parent. + if (rm_ref_node and ref_node._parent == parent) { page.removeNode(parent, ref_node, .{ .will_be_reconnected = false }); } } diff --git a/src/browser/webapi/Node.zig b/src/browser/webapi/Node.zig index 5871abee..d6d73fee 100644 --- a/src/browser/webapi/Node.zig +++ b/src/browser/webapi/Node.zig @@ -624,7 +624,9 @@ pub fn replaceChild(self: *Node, new_child: *Node, old_child: *Node, page: *Page // Special case: if we replace a node by itself, we don't remove it. // insertBefore is an noop in this case. - if (new_child != old_child) { + // Re-check parent after insertBefore since callbacks (e.g. connectedCallback) + // could have already removed old_child from self. + if (new_child != old_child and old_child._parent == self) { page.removeNode(self, old_child, .{ .will_be_reconnected = false }); }