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

Side by Side Diff: Source/core/dom/ContainerNode.cpp

Issue 465593003: Merge 178976 "Call insertedInto or removedFrom before childrenCh..." (Closed) Base URL: svn://svn.chromium.org/blink/branches/chromium/2062/
Patch Set: Created 6 years, 4 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 | Annotate | Revision Log
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 Apple Inc. All rights reserv ed. 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No de& nextChild) 287 void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No de& nextChild)
288 { 288 {
289 ASSERT(newChild); 289 ASSERT(newChild);
290 ASSERT(nextChild.parentNode() == this); 290 ASSERT(nextChild.parentNode() == this);
291 ASSERT(!newChild->isDocumentFragment()); 291 ASSERT(!newChild->isDocumentFragment());
292 ASSERT(!isHTMLTemplateElement(this)); 292 ASSERT(!isHTMLTemplateElement(this));
293 293
294 if (nextChild.previousSibling() == newChild || &nextChild == newChild) // no thing to do 294 if (nextChild.previousSibling() == newChild || &nextChild == newChild) // no thing to do
295 return; 295 return;
296 296
297 RefPtrWillBeRawPtr<Node> protect(this);
298
297 if (document() != newChild->document()) 299 if (document() != newChild->document())
298 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); 300 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
299 301
300 insertBeforeCommon(nextChild, *newChild); 302 insertBeforeCommon(nextChild, *newChild);
301 303
302 newChild->updateAncestorConnectedSubframeCountForInsertion(); 304 newChild->updateAncestorConnectedSubframeCountForInsertion();
303 305
304 ChildListMutationScope(*this).childAdded(*newChild); 306 ChildListMutationScope(*this).childAdded(*newChild);
305 307
306 childrenChanged(true, newChild->previousSibling(), &nextChild, 1); 308 notifyNodeInserted(*newChild, ChildrenChangeSourceParser);
307
308 notifyNodeInserted(*newChild);
309 } 309 }
310 310
311 void ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, Node* ol dChild, ExceptionState& exceptionState) 311 void ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, Node* ol dChild, ExceptionState& exceptionState)
312 { 312 {
313 #if !ENABLE(OILPAN) 313 #if !ENABLE(OILPAN)
314 // Check that this node is not "floating". 314 // Check that this node is not "floating".
315 // If it is, it can be deleted as a side effect of sending mutation events. 315 // If it is, it can be deleted as a side effect of sending mutation events.
316 ASSERT(refCount() || parentOrShadowHostNode()); 316 ASSERT(refCount() || parentOrShadowHostNode());
317 #endif 317 #endif
318 318
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 exceptionState.throwDOMException(NotFoundError, "The node to be removed is no longer a child of this node. Perhaps it was moved in response to a mutatio n?"); 475 exceptionState.throwDOMException(NotFoundError, "The node to be removed is no longer a child of this node. Perhaps it was moved in response to a mutatio n?");
476 return; 476 return;
477 } 477 }
478 478
479 { 479 {
480 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; 480 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
481 481
482 Node* prev = child->previousSibling(); 482 Node* prev = child->previousSibling();
483 Node* next = child->nextSibling(); 483 Node* next = child->nextSibling();
484 removeBetween(prev, next, *child); 484 removeBetween(prev, next, *child);
485 notifyNodeRemoved(*child);
485 childrenChanged(false, prev, next, -1); 486 childrenChanged(false, prev, next, -1);
486 notifyNodeRemoved(*child);
487 } 487 }
488 dispatchSubtreeModifiedEvent(); 488 dispatchSubtreeModifiedEvent();
489 } 489 }
490 490
491 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol dChild) 491 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol dChild)
492 { 492 {
493 NoEventDispatchAssertion assertNoEventDispatch; 493 NoEventDispatchAssertion assertNoEventDispatch;
494 494
495 ASSERT(oldChild.parentNode() == this); 495 ASSERT(oldChild.parentNode() == this);
496 496
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 // Exclude this node when looking for removed focusedElement since only 557 // Exclude this node when looking for removed focusedElement since only
558 // children will be removed. 558 // children will be removed.
559 // This must be later than willRemoveChildren, which might change focus 559 // This must be later than willRemoveChildren, which might change focus
560 // state of a child. 560 // state of a child.
561 document().removeFocusedElementOfSubtree(this, true); 561 document().removeFocusedElementOfSubtree(this, true);
562 562
563 // Removing a node from a selection can cause widget updates. 563 // Removing a node from a selection can cause widget updates.
564 document().nodeChildrenWillBeRemoved(*this); 564 document().nodeChildrenWillBeRemoved(*this);
565 } 565 }
566 566
567 567 // FIXME: Remove this NodeVector. Right now WebPluginContainerImpl::m_elemen t is a
568 // raw ptr which means the code below can drop the last ref to a plugin elem ent and
569 // then the code in UpdateSuspendScope::performDeferredWidgetTreeOperations will
570 // try to destroy the plugin which will be a use-after-free. We should use a RefPtr
571 // in the WebPluginContainerImpl instead.
568 NodeVector removedChildren; 572 NodeVector removedChildren;
569 { 573 {
570 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; 574 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
575
571 { 576 {
572 NoEventDispatchAssertion assertNoEventDispatch; 577 NoEventDispatchAssertion assertNoEventDispatch;
578 ScriptForbiddenScope forbidScript;
579
573 removedChildren.reserveInitialCapacity(countChildren()); 580 removedChildren.reserveInitialCapacity(countChildren());
574 while (m_firstChild) { 581
575 removedChildren.append(m_firstChild); 582 while (RefPtrWillBeRawPtr<Node> child = m_firstChild) {
576 removeBetween(0, m_firstChild->nextSibling(), *m_firstChild); 583 removeBetween(0, child->nextSibling(), *child);
584 removedChildren.append(child.get());
585 notifyNodeRemoved(*child);
577 } 586 }
578 } 587 }
579 588
580 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); 589 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size()));
581
582 for (size_t i = 0; i < removedChildren.size(); ++i)
583 notifyNodeRemoved(*removedChildren[i]);
584 } 590 }
585 591
586 dispatchSubtreeModifiedEvent(); 592 dispatchSubtreeModifiedEvent();
587 } 593 }
588 594
589 void ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, Exception State& exceptionState) 595 void ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, Exception State& exceptionState)
590 { 596 {
591 RefPtrWillBeRawPtr<ContainerNode> protect(this); 597 RefPtrWillBeRawPtr<ContainerNode> protect(this);
592 598
593 #if !ENABLE(OILPAN) 599 #if !ENABLE(OILPAN)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 dispatchSubtreeModifiedEvent(); 650 dispatchSubtreeModifiedEvent();
645 } 651 }
646 652
647 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild) 653 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild)
648 { 654 {
649 ASSERT(newChild); 655 ASSERT(newChild);
650 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re parenting (and want DOM mutation events). 656 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re parenting (and want DOM mutation events).
651 ASSERT(!newChild->isDocumentFragment()); 657 ASSERT(!newChild->isDocumentFragment());
652 ASSERT(!isHTMLTemplateElement(this)); 658 ASSERT(!isHTMLTemplateElement(this));
653 659
660 RefPtrWillBeRawPtr<Node> protect(this);
661
654 if (document() != newChild->document()) 662 if (document() != newChild->document())
655 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); 663 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
656 664
657 Node* last = m_lastChild;
658
659 { 665 {
660 NoEventDispatchAssertion assertNoEventDispatch; 666 NoEventDispatchAssertion assertNoEventDispatch;
661 ScriptForbiddenScope forbidScript; 667 ScriptForbiddenScope forbidScript;
662 668
663 treeScope().adoptIfNeeded(*newChild); 669 treeScope().adoptIfNeeded(*newChild);
664 appendChildCommon(*newChild); 670 appendChildCommon(*newChild);
665 newChild->updateAncestorConnectedSubframeCountForInsertion(); 671 newChild->updateAncestorConnectedSubframeCountForInsertion();
666 ChildListMutationScope(*this).childAdded(*newChild); 672 ChildListMutationScope(*this).childAdded(*newChild);
667 } 673 }
668 674
669 childrenChanged(true, last, 0, 1); 675 notifyNodeInserted(*newChild, ChildrenChangeSourceParser);
670 notifyNodeInserted(*newChild);
671 } 676 }
672 677
673 void ContainerNode::notifyNodeInserted(Node& root) 678 void ContainerNode::notifyNodeInserted(Node& root, ChildrenChangeSource source)
674 { 679 {
675 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); 680 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
676 681
677 InspectorInstrumentation::didInsertDOMNode(&root); 682 InspectorInstrumentation::didInsertDOMNode(&root);
678 683
679 RefPtrWillBeRawPtr<Node> protect(this); 684 RefPtrWillBeRawPtr<Node> protect(this);
680 RefPtrWillBeRawPtr<Node> protectNode(root); 685 RefPtrWillBeRawPtr<Node> protectNode(root);
681 686
682 NodeVector postInsertionNotificationTargets; 687 NodeVector postInsertionNotificationTargets;
683 notifyNodeInsertedInternal(root, postInsertionNotificationTargets); 688 notifyNodeInsertedInternal(root, postInsertionNotificationTargets);
684 689
690 // ShadowRoots are not real children, we don't need to tell host that it's
691 // children changed when one is added.
692 // FIXME: We should have a separate code path for ShadowRoot since it only
693 // needs to call insertedInto and the rest of this logic is not needed.
694 if (!root.isShadowRoot()) {
695 childrenChanged(source == ChildrenChangeSourceParser, root.previousSibli ng(), root.nextSibling(), 1);
696 }
697
685 for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) { 698 for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) {
686 Node* targetNode = postInsertionNotificationTargets[i].get(); 699 Node* targetNode = postInsertionNotificationTargets[i].get();
687 if (targetNode->inDocument()) 700 if (targetNode->inDocument())
688 targetNode->didNotifySubtreeInsertionsToDocument(); 701 targetNode->didNotifySubtreeInsertionsToDocument();
689 } 702 }
690 } 703 }
691 704
692 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInser tionNotificationTargets) 705 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInser tionNotificationTargets)
693 { 706 {
694 NoEventDispatchAssertion assertNoEventDispatch; 707 NoEventDispatchAssertion assertNoEventDispatch;
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 1099
1087 void ContainerNode::updateTreeAfterInsertion(Node& child) 1100 void ContainerNode::updateTreeAfterInsertion(Node& child)
1088 { 1101 {
1089 #if !ENABLE(OILPAN) 1102 #if !ENABLE(OILPAN)
1090 ASSERT(refCount()); 1103 ASSERT(refCount());
1091 ASSERT(child.refCount()); 1104 ASSERT(child.refCount());
1092 #endif 1105 #endif
1093 1106
1094 ChildListMutationScope(*this).childAdded(child); 1107 ChildListMutationScope(*this).childAdded(child);
1095 1108
1096 childrenChanged(false, child.previousSibling(), child.nextSibling(), 1);
1097
1098 notifyNodeInserted(child); 1109 notifyNodeInserted(child);
1099 1110
1100 dispatchChildInsertionEvents(child); 1111 dispatchChildInsertionEvents(child);
1101 } 1112 }
1102 1113
1103 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const 1114 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const
1104 { 1115 {
1105 return rareData()->hasRestyleFlag(mask); 1116 return rareData()->hasRestyleFlag(mask);
1106 } 1117 }
1107 1118
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 return true; 1297 return true;
1287 1298
1288 if (node->isElementNode() && toElement(node)->shadow()) 1299 if (node->isElementNode() && toElement(node)->shadow())
1289 return true; 1300 return true;
1290 1301
1291 return false; 1302 return false;
1292 } 1303 }
1293 #endif 1304 #endif
1294 1305
1295 } // namespace WebCore 1306 } // namespace WebCore
OLDNEW
« no previous file with comments | « LayoutTests/fast/dom/script-remove-child-id-map-expected.txt ('k') | Source/core/html/HTMLOptionElement.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698