LibWeb: Abandon Node.replaceChild() if removal rejigs the DOM

This isn't directly in the spec, but since replaceChild is implemented
in terms of remove + insert, the removal step may cause arbitrary code
to execute, and so we have to verify that the replaceChild inputs still
make sense afterwards, before doing the insertion.

This roughly matches what WebKit does, and makes a bunch of HTML parsing
tests in WPT stop asserting.
This commit is contained in:
Andreas Kling 2024-11-24 10:23:56 +01:00 committed by Andreas Kling
commit 01f4bbbba7
Notes: github-actions[bot] 2024-11-24 10:46:37 +00:00
5 changed files with 179 additions and 12 deletions

View file

@ -982,8 +982,13 @@ WebIDL::ExceptionOr<GC::Ref<Node>> Node::replace_child(GC::Ref<Node> node, GC::R
else
nodes.append(GC::make_root(*node));
// 13. Insert node into parent before referenceChild with the suppress observers flag set.
insert_before(node, reference_child, true);
// AD-HOC: Since removing the child may have executed arbitrary code, we have to verify
// the sanity of inserting `node` before `reference_child` again, as well as
// `child` not being reinserted elsewhere.
if (!reference_child || (reference_child->parent() == this && !child->parent_node())) {
// 13. Insert node into parent before referenceChild with the suppress observers flag set.
insert_before(node, reference_child, true);
}
// 14. Queue a tree mutation record for parent with nodes, removedNodes, previousSibling, and referenceChild.
queue_tree_mutation_record(move(nodes), move(removed_nodes), previous_sibling.ptr(), reference_child.ptr());