Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Unified Diff: third_party/WebKit/Source/core/dom/ContainerNode.cpp

Issue 2889523002: MutationObserver: Correct MutationRecords for Node.replaceChild(). (Closed)
Patch Set: Add step comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/LayoutTests/fast/events/mutation-during-replace-child-expected.txt ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/dom/ContainerNode.cpp
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
index 3831b25430f942f5a9b09408216f6cd1142b852e..d151f86379fc836a645b02d36faf14bb1800b7d3 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -412,48 +412,80 @@ Node* ContainerNode::ReplaceChild(Node* new_child,
return nullptr;
}
- // Make sure replacing the old child with the new is OK.
+ // 1. If parent is not a Document, DocumentFragment, or Element node, throw a
+ // HierarchyRequestError.
+ // 2. If node is a host-including inclusive ancestor of parent, throw a
+ // HierarchyRequestError.
+ // 4. If node is not a DocumentFragment, DocumentType, Element, Text,
+ // ProcessingInstruction, or Comment node, throw a HierarchyRequestError.
+ // 5. If either node is a Text node and parent is a document, or node is a
+ // doctype and parent is not a document, throw a HierarchyRequestError.
+ // 6. If parent is a document, and any of the statements below, switched on
+ // node, are true, throw a HierarchyRequestError.
if (!CheckAcceptChild(new_child, old_child, exception_state))
return old_child;
- // NotFoundError: Raised if oldChild is not a child of this node.
+ // 3. If child’s parent is not parent, then throw a NotFoundError.
if (old_child->parentNode() != this) {
exception_state.ThrowDOMException(
kNotFoundError, "The node to be replaced is not a child of this node.");
return nullptr;
}
- ChildListMutationScope mutation(*this);
// 7. Let reference child be child’s next sibling.
Node* next = old_child->nextSibling();
// 8. If reference child is node, set it to node’s next sibling.
if (next == new_child)
next = new_child->nextSibling();
- // TODO(tkent): According to the specification, we should remove |newChild|
- // from its parent here, and create a separated mutation record for it.
- // Refer to external/wpt/dom/nodes/MutationObserver-childList.html.
+ // 10. Adopt node into parent’s node document.
+ // TODO(tkent): Actually we do only RemoveChild() as a part of 'adopt'
+ // operation.
+ // Though the following CollectChildrenAndRemoveFromOldParentWithCheck() also
+ // calls RemoveChild(), we'd like to call RemoveChild() here to make a
+ // separated MutationRecord.
+ if (ContainerNode* new_child_parent = new_child->parentNode()) {
+ new_child_parent->RemoveChild(new_child, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+ }
+
+ // 9. Let previousSibling be child’s previous sibling.
+ // 11. Let removedNodes be the empty list.
+ // 15. Queue a mutation record of "childList" for target parent with
+ // addedNodes nodes, removedNodes removedNodes, nextSibling reference child,
+ // and previousSibling previousSibling.
+ ChildListMutationScope mutation(*this);
// 12. If child’s parent is not null, run these substeps:
// 1. Set removedNodes to a list solely containing child.
// 2. Remove child from its parent with the suppress observers flag set.
- RemoveChild(old_child, exception_state);
- if (exception_state.HadException())
- return nullptr;
+ if (ContainerNode* old_child_parent = old_child->parentNode()) {
+ old_child_parent->RemoveChild(old_child, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+ }
// Does this one more time because removeChild() fires a MutationEvent.
if (!CheckAcceptChild(new_child, old_child, exception_state))
return old_child;
+ // 13. Let nodes be node’s children if node is a DocumentFragment node, and a
+ // list containing solely node otherwise.
NodeVector targets;
if (!CollectChildrenAndRemoveFromOldParentWithCheck(
next, old_child, *new_child, targets, exception_state))
return old_child;
+ // 10. Adopt node into parent’s node document.
+ // 14. Insert node into parent before reference child with the suppress
+ // observers flag set.
if (next)
InsertNodeVector(targets, next, AdoptAndInsertBefore());
else
InsertNodeVector(targets, nullptr, AdoptAndAppendChild());
+
+ // 16. Return child.
return old_child;
}
« no previous file with comments | « third_party/WebKit/LayoutTests/fast/events/mutation-during-replace-child-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698