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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights
6 * reserved. 6 * reserved.
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 Node* old_child, 405 Node* old_child,
406 ExceptionState& exception_state) { 406 ExceptionState& exception_state) {
407 // https://dom.spec.whatwg.org/#concept-node-replace 407 // https://dom.spec.whatwg.org/#concept-node-replace
408 408
409 if (!old_child) { 409 if (!old_child) {
410 exception_state.ThrowDOMException(kNotFoundError, 410 exception_state.ThrowDOMException(kNotFoundError,
411 "The node to be replaced is null."); 411 "The node to be replaced is null.");
412 return nullptr; 412 return nullptr;
413 } 413 }
414 414
415 // Make sure replacing the old child with the new is OK. 415 // 1. If parent is not a Document, DocumentFragment, or Element node, throw a
416 // HierarchyRequestError.
417 // 2. If node is a host-including inclusive ancestor of parent, throw a
418 // HierarchyRequestError.
419 // 4. If node is not a DocumentFragment, DocumentType, Element, Text,
420 // ProcessingInstruction, or Comment node, throw a HierarchyRequestError.
421 // 5. If either node is a Text node and parent is a document, or node is a
422 // doctype and parent is not a document, throw a HierarchyRequestError.
423 // 6. If parent is a document, and any of the statements below, switched on
424 // node, are true, throw a HierarchyRequestError.
416 if (!CheckAcceptChild(new_child, old_child, exception_state)) 425 if (!CheckAcceptChild(new_child, old_child, exception_state))
417 return old_child; 426 return old_child;
418 427
419 // NotFoundError: Raised if oldChild is not a child of this node. 428 // 3. If child’s parent is not parent, then throw a NotFoundError.
420 if (old_child->parentNode() != this) { 429 if (old_child->parentNode() != this) {
421 exception_state.ThrowDOMException( 430 exception_state.ThrowDOMException(
422 kNotFoundError, "The node to be replaced is not a child of this node."); 431 kNotFoundError, "The node to be replaced is not a child of this node.");
423 return nullptr; 432 return nullptr;
424 } 433 }
425 434
426 ChildListMutationScope mutation(*this);
427 // 7. Let reference child be child’s next sibling. 435 // 7. Let reference child be child’s next sibling.
428 Node* next = old_child->nextSibling(); 436 Node* next = old_child->nextSibling();
429 // 8. If reference child is node, set it to node’s next sibling. 437 // 8. If reference child is node, set it to node’s next sibling.
430 if (next == new_child) 438 if (next == new_child)
431 next = new_child->nextSibling(); 439 next = new_child->nextSibling();
432 440
433 // TODO(tkent): According to the specification, we should remove |newChild| 441 // 10. Adopt node into parent’s node document.
434 // from its parent here, and create a separated mutation record for it. 442 // TODO(tkent): Actually we do only RemoveChild() as a part of 'adopt'
435 // Refer to external/wpt/dom/nodes/MutationObserver-childList.html. 443 // operation.
444 // Though the following CollectChildrenAndRemoveFromOldParentWithCheck() also
445 // calls RemoveChild(), we'd like to call RemoveChild() here to make a
446 // separated MutationRecord.
447 if (ContainerNode* new_child_parent = new_child->parentNode()) {
448 new_child_parent->RemoveChild(new_child, exception_state);
449 if (exception_state.HadException())
450 return nullptr;
451 }
452
453 // 9. Let previousSibling be child’s previous sibling.
454 // 11. Let removedNodes be the empty list.
455 // 15. Queue a mutation record of "childList" for target parent with
456 // addedNodes nodes, removedNodes removedNodes, nextSibling reference child,
457 // and previousSibling previousSibling.
458 ChildListMutationScope mutation(*this);
436 459
437 // 12. If child’s parent is not null, run these substeps: 460 // 12. If child’s parent is not null, run these substeps:
438 // 1. Set removedNodes to a list solely containing child. 461 // 1. Set removedNodes to a list solely containing child.
439 // 2. Remove child from its parent with the suppress observers flag set. 462 // 2. Remove child from its parent with the suppress observers flag set.
440 RemoveChild(old_child, exception_state); 463 if (ContainerNode* old_child_parent = old_child->parentNode()) {
441 if (exception_state.HadException()) 464 old_child_parent->RemoveChild(old_child, exception_state);
442 return nullptr; 465 if (exception_state.HadException())
466 return nullptr;
467 }
443 468
444 // Does this one more time because removeChild() fires a MutationEvent. 469 // Does this one more time because removeChild() fires a MutationEvent.
445 if (!CheckAcceptChild(new_child, old_child, exception_state)) 470 if (!CheckAcceptChild(new_child, old_child, exception_state))
446 return old_child; 471 return old_child;
447 472
473 // 13. Let nodes be node’s children if node is a DocumentFragment node, and a
474 // list containing solely node otherwise.
448 NodeVector targets; 475 NodeVector targets;
449 if (!CollectChildrenAndRemoveFromOldParentWithCheck( 476 if (!CollectChildrenAndRemoveFromOldParentWithCheck(
450 next, old_child, *new_child, targets, exception_state)) 477 next, old_child, *new_child, targets, exception_state))
451 return old_child; 478 return old_child;
452 479
480 // 10. Adopt node into parent’s node document.
481 // 14. Insert node into parent before reference child with the suppress
482 // observers flag set.
453 if (next) 483 if (next)
454 InsertNodeVector(targets, next, AdoptAndInsertBefore()); 484 InsertNodeVector(targets, next, AdoptAndInsertBefore());
455 else 485 else
456 InsertNodeVector(targets, nullptr, AdoptAndAppendChild()); 486 InsertNodeVector(targets, nullptr, AdoptAndAppendChild());
487
488 // 16. Return child.
457 return old_child; 489 return old_child;
458 } 490 }
459 491
460 void ContainerNode::WillRemoveChild(Node& child) { 492 void ContainerNode::WillRemoveChild(Node& child) {
461 DCHECK_EQ(child.parentNode(), this); 493 DCHECK_EQ(child.parentNode(), this);
462 ChildListMutationScope(*this).WillRemoveChild(child); 494 ChildListMutationScope(*this).WillRemoveChild(child);
463 child.NotifyMutationObserversNodeWillDetach(); 495 child.NotifyMutationObserversNodeWillDetach();
464 DispatchChildRemovalEvents(child); 496 DispatchChildRemovalEvents(child);
465 ChildFrameDisconnector(child).Disconnect(); 497 ChildFrameDisconnector(child).Disconnect();
466 if (GetDocument() != child.GetDocument()) { 498 if (GetDocument() != child.GetDocument()) {
(...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 return true; 1570 return true;
1539 1571
1540 if (node->IsElementNode() && ToElement(node)->Shadow()) 1572 if (node->IsElementNode() && ToElement(node)->Shadow())
1541 return true; 1573 return true;
1542 1574
1543 return false; 1575 return false;
1544 } 1576 }
1545 #endif 1577 #endif
1546 1578
1547 } // namespace blink 1579 } // namespace blink
OLDNEW
« 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