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

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

Issue 306233005: Call insertedInto or removedFrom before childrenChanged (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: enum { OjanReview } Created 6 years, 6 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
« no previous file with comments | « Source/core/dom/ContainerNode.h ('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 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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 newChild.setNextSibling(&nextChild); 271 newChild.setNextSibling(&nextChild);
272 } 272 }
273 273
274 void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No de& nextChild) 274 void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No de& nextChild)
275 { 275 {
276 ASSERT(newChild); 276 ASSERT(newChild);
277 ASSERT(nextChild.parentNode() == this); 277 ASSERT(nextChild.parentNode() == this);
278 ASSERT(!newChild->isDocumentFragment()); 278 ASSERT(!newChild->isDocumentFragment());
279 ASSERT(!isHTMLTemplateElement(this)); 279 ASSERT(!isHTMLTemplateElement(this));
280 280
281 if (nextChild.previousSibling() == newChild || &nextChild == newChild) // no thing to do 281 RefPtrWillBeRawPtr<Node> protect(this);
abarth-chromium 2014/06/07 01:17:51 Why not do this after checking for early return?
282
283 if (nextChild.previousSibling() == newChild || nextChild == newChild) // not hing to do
sof 2014/06/07 15:41:08 Oilpan compilation broke as a result of dropping t
282 return; 284 return;
283 285
284 if (document() != newChild->document()) 286 if (document() != newChild->document())
285 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); 287 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
286 288
287 insertBeforeCommon(nextChild, *newChild); 289 insertBeforeCommon(nextChild, *newChild);
288 290
289 newChild->updateAncestorConnectedSubframeCountForInsertion(); 291 newChild->updateAncestorConnectedSubframeCountForInsertion();
290 292
291 ChildListMutationScope(*this).childAdded(*newChild); 293 ChildListMutationScope(*this).childAdded(*newChild);
292 294
293 childrenChanged(true, newChild->previousSibling(), &nextChild, 1); 295 notifyNodeInserted(*newChild, InsertedByParser);
294
295 notifyNodeInserted(*newChild);
296 } 296 }
297 297
298 void ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, Node* ol dChild, ExceptionState& exceptionState) 298 void ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, Node* ol dChild, ExceptionState& exceptionState)
299 { 299 {
300 #if !ENABLE(OILPAN) 300 #if !ENABLE(OILPAN)
301 // Check that this node is not "floating". 301 // Check that this node is not "floating".
302 // If it is, it can be deleted as a side effect of sending mutation events. 302 // If it is, it can be deleted as a side effect of sending mutation events.
303 ASSERT(refCount() || parentOrShadowHostNode()); 303 ASSERT(refCount() || parentOrShadowHostNode());
304 #endif 304 #endif
305 305
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 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?"); 462 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?");
463 return; 463 return;
464 } 464 }
465 465
466 { 466 {
467 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; 467 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
468 468
469 Node* prev = child->previousSibling(); 469 Node* prev = child->previousSibling();
470 Node* next = child->nextSibling(); 470 Node* next = child->nextSibling();
471 removeBetween(prev, next, *child); 471 removeBetween(prev, next, *child);
472 notifyNodeRemoved(*child);
472 childrenChanged(false, prev, next, -1); 473 childrenChanged(false, prev, next, -1);
473 notifyNodeRemoved(*child);
474 } 474 }
475 dispatchSubtreeModifiedEvent(); 475 dispatchSubtreeModifiedEvent();
476 } 476 }
477 477
478 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol dChild) 478 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol dChild)
479 { 479 {
480 NoEventDispatchAssertion assertNoEventDispatch; 480 NoEventDispatchAssertion assertNoEventDispatch;
481 481
482 ASSERT(oldChild.parentNode() == this); 482 ASSERT(oldChild.parentNode() == this);
483 483
(...skipping 14 matching lines...) Expand all
498 oldChild.setParentOrShadowHostNode(0); 498 oldChild.setParentOrShadowHostNode(0);
499 499
500 document().adoptIfNeeded(oldChild); 500 document().adoptIfNeeded(oldChild);
501 } 501 }
502 502
503 void ContainerNode::parserRemoveChild(Node& oldChild) 503 void ContainerNode::parserRemoveChild(Node& oldChild)
504 { 504 {
505 ASSERT(oldChild.parentNode() == this); 505 ASSERT(oldChild.parentNode() == this);
506 ASSERT(!oldChild.isDocumentFragment()); 506 ASSERT(!oldChild.isDocumentFragment());
507 507
508 ScriptForbiddenScope forbidScript;
509
508 Node* prev = oldChild.previousSibling(); 510 Node* prev = oldChild.previousSibling();
509 Node* next = oldChild.nextSibling(); 511 Node* next = oldChild.nextSibling();
510 512
511 oldChild.updateAncestorConnectedSubframeCountForRemoval(); 513 oldChild.updateAncestorConnectedSubframeCountForRemoval();
512 514
513 ChildListMutationScope(*this).willRemoveChild(oldChild); 515 ChildListMutationScope(*this).willRemoveChild(oldChild);
514 oldChild.notifyMutationObserversNodeWillDetach(); 516 oldChild.notifyMutationObserversNodeWillDetach();
515 517
516 removeBetween(prev, next, oldChild); 518 removeBetween(prev, next, oldChild);
517 519 notifyNodeRemoved(oldChild);
518 childrenChanged(true, prev, next, -1); 520 childrenChanged(true, prev, next, -1);
519 notifyNodeRemoved(oldChild);
520 } 521 }
521 522
522 // this differs from other remove functions because it forcibly removes all the children, 523 // this differs from other remove functions because it forcibly removes all the children,
523 // regardless of read-only status or event exceptions, e.g. 524 // regardless of read-only status or event exceptions, e.g.
524 void ContainerNode::removeChildren() 525 void ContainerNode::removeChildren()
525 { 526 {
526 if (!m_firstChild) 527 if (!m_firstChild)
527 return; 528 return;
528 529
529 // The container node can be removed from event handlers. 530 // The container node can be removed from event handlers.
(...skipping 14 matching lines...) Expand all
544 // Exclude this node when looking for removed focusedElement since only 545 // Exclude this node when looking for removed focusedElement since only
545 // children will be removed. 546 // children will be removed.
546 // This must be later than willRemoveChildren, which might change focus 547 // This must be later than willRemoveChildren, which might change focus
547 // state of a child. 548 // state of a child.
548 document().removeFocusedElementOfSubtree(this, true); 549 document().removeFocusedElementOfSubtree(this, true);
549 550
550 // Removing a node from a selection can cause widget updates. 551 // Removing a node from a selection can cause widget updates.
551 document().nodeChildrenWillBeRemoved(*this); 552 document().nodeChildrenWillBeRemoved(*this);
552 } 553 }
553 554
554
555 NodeVector removedChildren;
556 { 555 {
557 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; 556 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
558 { 557 ScriptForbiddenScope forbidScript;
558
559 // FIXME: We can't have a top level NoEventDispatchAssertion since
560 // SVGElement::invalidateInstances() is called inside ::childrenChanged
561 // and will stamp out new <use> shadow trees which mutates the DOM and
562 // hits the event dispatching assert in ::notifyNodeInserted. We should
563 // figure out how to make ths work async.
564
565 int childCount = 0;
566 while (RefPtrWillBeRawPtr<Node> child = m_firstChild) {
559 NoEventDispatchAssertion assertNoEventDispatch; 567 NoEventDispatchAssertion assertNoEventDispatch;
560 removedChildren.reserveInitialCapacity(countChildren()); 568 ++childCount;
561 while (m_firstChild) { 569 removeBetween(0, child->nextSibling(), *child);
562 removedChildren.append(m_firstChild); 570 notifyNodeRemoved(*child);
563 removeBetween(0, m_firstChild->nextSibling(), *m_firstChild);
564 }
565 } 571 }
566 572
567 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); 573 childrenChanged(false, 0, 0, -childCount);
568
569 for (size_t i = 0; i < removedChildren.size(); ++i)
570 notifyNodeRemoved(*removedChildren[i]);
571 } 574 }
572 575
573 dispatchSubtreeModifiedEvent(); 576 dispatchSubtreeModifiedEvent();
574 } 577 }
575 578
576 void ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, Exception State& exceptionState) 579 void ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, Exception State& exceptionState)
577 { 580 {
578 RefPtrWillBeRawPtr<ContainerNode> protect(this); 581 RefPtrWillBeRawPtr<ContainerNode> protect(this);
579 582
580 #if !ENABLE(OILPAN) 583 #if !ENABLE(OILPAN)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 dispatchSubtreeModifiedEvent(); 634 dispatchSubtreeModifiedEvent();
632 } 635 }
633 636
634 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild) 637 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild)
635 { 638 {
636 ASSERT(newChild); 639 ASSERT(newChild);
637 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re parenting (and want DOM mutation events). 640 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re parenting (and want DOM mutation events).
638 ASSERT(!newChild->isDocumentFragment()); 641 ASSERT(!newChild->isDocumentFragment());
639 ASSERT(!isHTMLTemplateElement(this)); 642 ASSERT(!isHTMLTemplateElement(this));
640 643
644 RefPtrWillBeRawPtr<Node> protect(this);
645
641 if (document() != newChild->document()) 646 if (document() != newChild->document())
642 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); 647 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
643 648
644 Node* last = m_lastChild;
645
646 { 649 {
647 NoEventDispatchAssertion assertNoEventDispatch; 650 NoEventDispatchAssertion assertNoEventDispatch;
648 ScriptForbiddenScope forbidScript; 651 ScriptForbiddenScope forbidScript;
649 652
650 treeScope().adoptIfNeeded(*newChild); 653 treeScope().adoptIfNeeded(*newChild);
651 // FIXME: This method should take a PassRefPtr. 654 // FIXME: This method should take a PassRefPtr.
652 appendChildToContainer(*newChild, *this); 655 appendChildToContainer(*newChild, *this);
653 newChild->updateAncestorConnectedSubframeCountForInsertion(); 656 newChild->updateAncestorConnectedSubframeCountForInsertion();
654 ChildListMutationScope(*this).childAdded(*newChild); 657 ChildListMutationScope(*this).childAdded(*newChild);
655 } 658 }
656 659
657 childrenChanged(true, last, 0, 1); 660 notifyNodeInserted(*newChild, InsertedByParser);
658 notifyNodeInserted(*newChild);
659 } 661 }
660 662
661 void ContainerNode::notifyNodeInserted(Node& root) 663 void ContainerNode::notifyNodeInserted(Node& root, InsertionSourceType source)
662 { 664 {
663 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); 665 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
664 666
665 InspectorInstrumentation::didInsertDOMNode(&root); 667 InspectorInstrumentation::didInsertDOMNode(&root);
666 668
667 RefPtrWillBeRawPtr<Node> protect(this); 669 RefPtrWillBeRawPtr<Node> protect(this);
668 RefPtrWillBeRawPtr<Node> protectNode(root); 670 RefPtrWillBeRawPtr<Node> protectNode(root);
669 671
670 NodeVector postInsertionNotificationTargets; 672 NodeVector postInsertionNotificationTargets;
671 notifyNodeInsertedInternal(root, postInsertionNotificationTargets); 673 notifyNodeInsertedInternal(root, postInsertionNotificationTargets);
672 674
675 // ShadowRoots are not real children, we don't need to tell host that it's
676 // children changed when one is added.
677 // FIXME: We should have a separate code path for ShadowRoot since it only
678 // needs to call insertedInto and the rest of this logic is not needed.
679 if (!root.isShadowRoot())
680 childrenChanged(source == InsertedByParser, root.previousSibling(), root .nextSibling(), 1);
681
673 for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) { 682 for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) {
674 Node* targetNode = postInsertionNotificationTargets[i].get(); 683 Node* targetNode = postInsertionNotificationTargets[i].get();
675 if (targetNode->inDocument()) 684 if (targetNode->inDocument())
676 targetNode->didNotifySubtreeInsertionsToDocument(); 685 targetNode->didNotifySubtreeInsertionsToDocument();
677 } 686 }
678 } 687 }
679 688
680 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInser tionNotificationTargets) 689 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInser tionNotificationTargets)
681 { 690 {
682 NoEventDispatchAssertion assertNoEventDispatch; 691 NoEventDispatchAssertion assertNoEventDispatch;
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 1083
1075 void ContainerNode::updateTreeAfterInsertion(Node& child) 1084 void ContainerNode::updateTreeAfterInsertion(Node& child)
1076 { 1085 {
1077 #if !ENABLE(OILPAN) 1086 #if !ENABLE(OILPAN)
1078 ASSERT(refCount()); 1087 ASSERT(refCount());
1079 ASSERT(child.refCount()); 1088 ASSERT(child.refCount());
1080 #endif 1089 #endif
1081 1090
1082 ChildListMutationScope(*this).childAdded(child); 1091 ChildListMutationScope(*this).childAdded(child);
1083 1092
1084 childrenChanged(false, child.previousSibling(), child.nextSibling(), 1);
1085
1086 notifyNodeInserted(child); 1093 notifyNodeInserted(child);
1087 1094
1088 dispatchChildInsertionEvents(child); 1095 dispatchChildInsertionEvents(child);
1089 } 1096 }
1090 1097
1091 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const 1098 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const
1092 { 1099 {
1093 return rareData()->hasRestyleFlag(mask); 1100 return rareData()->hasRestyleFlag(mask);
1094 } 1101 }
1095 1102
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 return true; 1285 return true;
1279 1286
1280 if (node->isElementNode() && toElement(node)->shadow()) 1287 if (node->isElementNode() && toElement(node)->shadow())
1281 return true; 1288 return true;
1282 1289
1283 return false; 1290 return false;
1284 } 1291 }
1285 #endif 1292 #endif
1286 1293
1287 } // namespace WebCore 1294 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/dom/ContainerNode.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698