diff --git a/third_party/blink/renderer/core/dom/container_node.cc b/third_party/blink/renderer/core/dom/container_node.cc index bb8769ce97f61..3105fa6ba8c03 100644 --- a/third_party/blink/renderer/core/dom/container_node.cc +++ b/third_party/blink/renderer/core/dom/container_node.cc @@ -279,6 +279,19 @@ bool ContainerNode::EnsurePreInsertionValidity( // Step 3: if (!CheckReferenceChildParent(*this, next, old_child, exception_state)) return false; + // When called with a node vector (multi-argument append/prepend/etc.), + // ConvertNodeUnionsIntoNodes() already removed each node from its old + // parent, which may have run synchronous event handlers (blur, iframe + // unload). Re-validate that none of the nodes were reparented during + // those handlers; otherwise InsertNodeVector() would link a node into a + // second child list without unlinking it from the first. + if (new_children && new_children->size() != 1u && + RuntimeEnabledFeatures:: + RecheckParentDuringNodeVectorInsertionEnabled() && + !RecheckNodeInsertionStructuralPrereq(*new_children, next, + exception_state)) { + return false; + } // Step 4-6. return document->CanAcceptChild(new_child, new_children, next, old_child, exception_state);