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

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

Issue 318263002: Revert "Call insertedInto or removedFrom before childrenChanged" (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: 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 RefPtrWillBeRawPtr<Node> protect(this);
282
283 if (nextChild.previousSibling() == newChild || &nextChild == newChild) // no thing to do 281 if (nextChild.previousSibling() == newChild || &nextChild == newChild) // no thing to do
284 return; 282 return;
285 283
286 if (document() != newChild->document()) 284 if (document() != newChild->document())
287 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); 285 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
288 286
289 insertBeforeCommon(nextChild, *newChild); 287 insertBeforeCommon(nextChild, *newChild);
290 288
291 newChild->updateAncestorConnectedSubframeCountForInsertion(); 289 newChild->updateAncestorConnectedSubframeCountForInsertion();
292 290
293 ChildListMutationScope(*this).childAdded(*newChild); 291 ChildListMutationScope(*this).childAdded(*newChild);
294 292
295 notifyNodeInserted(*newChild, InsertedByParser); 293 childrenChanged(true, newChild->previousSibling(), &nextChild, 1);
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 childrenChanged(false, prev, next, -1);
472 notifyNodeRemoved(*child); 473 notifyNodeRemoved(*child);
473 childrenChanged(false, prev, next, -1);
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
510 Node* prev = oldChild.previousSibling(); 508 Node* prev = oldChild.previousSibling();
511 Node* next = oldChild.nextSibling(); 509 Node* next = oldChild.nextSibling();
512 510
513 oldChild.updateAncestorConnectedSubframeCountForRemoval(); 511 oldChild.updateAncestorConnectedSubframeCountForRemoval();
514 512
515 ChildListMutationScope(*this).willRemoveChild(oldChild); 513 ChildListMutationScope(*this).willRemoveChild(oldChild);
516 oldChild.notifyMutationObserversNodeWillDetach(); 514 oldChild.notifyMutationObserversNodeWillDetach();
517 515
518 removeBetween(prev, next, oldChild); 516 removeBetween(prev, next, oldChild);
517
518 childrenChanged(true, prev, next, -1);
519 notifyNodeRemoved(oldChild); 519 notifyNodeRemoved(oldChild);
520 childrenChanged(true, prev, next, -1);
521 } 520 }
522 521
523 // this differs from other remove functions because it forcibly removes all the children, 522 // this differs from other remove functions because it forcibly removes all the children,
524 // regardless of read-only status or event exceptions, e.g. 523 // regardless of read-only status or event exceptions, e.g.
525 void ContainerNode::removeChildren() 524 void ContainerNode::removeChildren()
526 { 525 {
527 if (!m_firstChild) 526 if (!m_firstChild)
528 return; 527 return;
529 528
530 // The container node can be removed from event handlers. 529 // The container node can be removed from event handlers.
(...skipping 14 matching lines...) Expand all
545 // Exclude this node when looking for removed focusedElement since only 544 // Exclude this node when looking for removed focusedElement since only
546 // children will be removed. 545 // children will be removed.
547 // This must be later than willRemoveChildren, which might change focus 546 // This must be later than willRemoveChildren, which might change focus
548 // state of a child. 547 // state of a child.
549 document().removeFocusedElementOfSubtree(this, true); 548 document().removeFocusedElementOfSubtree(this, true);
550 549
551 // Removing a node from a selection can cause widget updates. 550 // Removing a node from a selection can cause widget updates.
552 document().nodeChildrenWillBeRemoved(*this); 551 document().nodeChildrenWillBeRemoved(*this);
553 } 552 }
554 553
554
555 NodeVector removedChildren;
555 { 556 {
556 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; 557 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
557 ScriptForbiddenScope forbidScript; 558 {
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) {
567 NoEventDispatchAssertion assertNoEventDispatch; 559 NoEventDispatchAssertion assertNoEventDispatch;
568 ++childCount; 560 removedChildren.reserveInitialCapacity(countChildren());
569 removeBetween(0, child->nextSibling(), *child); 561 while (m_firstChild) {
570 notifyNodeRemoved(*child); 562 removedChildren.append(m_firstChild);
563 removeBetween(0, m_firstChild->nextSibling(), *m_firstChild);
564 }
571 } 565 }
572 566
573 childrenChanged(false, 0, 0, -childCount); 567 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size()));
568
569 for (size_t i = 0; i < removedChildren.size(); ++i)
570 notifyNodeRemoved(*removedChildren[i]);
574 } 571 }
575 572
576 dispatchSubtreeModifiedEvent(); 573 dispatchSubtreeModifiedEvent();
577 } 574 }
578 575
579 void ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, Exception State& exceptionState) 576 void ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, Exception State& exceptionState)
580 { 577 {
581 RefPtrWillBeRawPtr<ContainerNode> protect(this); 578 RefPtrWillBeRawPtr<ContainerNode> protect(this);
582 579
583 #if !ENABLE(OILPAN) 580 #if !ENABLE(OILPAN)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 dispatchSubtreeModifiedEvent(); 631 dispatchSubtreeModifiedEvent();
635 } 632 }
636 633
637 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild) 634 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild)
638 { 635 {
639 ASSERT(newChild); 636 ASSERT(newChild);
640 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re parenting (and want DOM mutation events). 637 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re parenting (and want DOM mutation events).
641 ASSERT(!newChild->isDocumentFragment()); 638 ASSERT(!newChild->isDocumentFragment());
642 ASSERT(!isHTMLTemplateElement(this)); 639 ASSERT(!isHTMLTemplateElement(this));
643 640
644 RefPtrWillBeRawPtr<Node> protect(this);
645
646 if (document() != newChild->document()) 641 if (document() != newChild->document())
647 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); 642 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
648 643
644 Node* last = m_lastChild;
645
649 { 646 {
650 NoEventDispatchAssertion assertNoEventDispatch; 647 NoEventDispatchAssertion assertNoEventDispatch;
651 ScriptForbiddenScope forbidScript; 648 ScriptForbiddenScope forbidScript;
652 649
653 treeScope().adoptIfNeeded(*newChild); 650 treeScope().adoptIfNeeded(*newChild);
654 // FIXME: This method should take a PassRefPtr. 651 // FIXME: This method should take a PassRefPtr.
655 appendChildToContainer(*newChild, *this); 652 appendChildToContainer(*newChild, *this);
656 newChild->updateAncestorConnectedSubframeCountForInsertion(); 653 newChild->updateAncestorConnectedSubframeCountForInsertion();
657 ChildListMutationScope(*this).childAdded(*newChild); 654 ChildListMutationScope(*this).childAdded(*newChild);
658 } 655 }
659 656
660 notifyNodeInserted(*newChild, InsertedByParser); 657 childrenChanged(true, last, 0, 1);
658 notifyNodeInserted(*newChild);
661 } 659 }
662 660
663 void ContainerNode::notifyNodeInserted(Node& root, InsertionSourceType source) 661 void ContainerNode::notifyNodeInserted(Node& root)
664 { 662 {
665 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); 663 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
666 664
667 InspectorInstrumentation::didInsertDOMNode(&root); 665 InspectorInstrumentation::didInsertDOMNode(&root);
668 666
669 RefPtrWillBeRawPtr<Node> protect(this); 667 RefPtrWillBeRawPtr<Node> protect(this);
670 RefPtrWillBeRawPtr<Node> protectNode(root); 668 RefPtrWillBeRawPtr<Node> protectNode(root);
671 669
672 NodeVector postInsertionNotificationTargets; 670 NodeVector postInsertionNotificationTargets;
673 notifyNodeInsertedInternal(root, postInsertionNotificationTargets); 671 notifyNodeInsertedInternal(root, postInsertionNotificationTargets);
674 672
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
682 for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) { 673 for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) {
683 Node* targetNode = postInsertionNotificationTargets[i].get(); 674 Node* targetNode = postInsertionNotificationTargets[i].get();
684 if (targetNode->inDocument()) 675 if (targetNode->inDocument())
685 targetNode->didNotifySubtreeInsertionsToDocument(); 676 targetNode->didNotifySubtreeInsertionsToDocument();
686 } 677 }
687 } 678 }
688 679
689 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInser tionNotificationTargets) 680 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInser tionNotificationTargets)
690 { 681 {
691 NoEventDispatchAssertion assertNoEventDispatch; 682 NoEventDispatchAssertion assertNoEventDispatch;
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 1074
1084 void ContainerNode::updateTreeAfterInsertion(Node& child) 1075 void ContainerNode::updateTreeAfterInsertion(Node& child)
1085 { 1076 {
1086 #if !ENABLE(OILPAN) 1077 #if !ENABLE(OILPAN)
1087 ASSERT(refCount()); 1078 ASSERT(refCount());
1088 ASSERT(child.refCount()); 1079 ASSERT(child.refCount());
1089 #endif 1080 #endif
1090 1081
1091 ChildListMutationScope(*this).childAdded(child); 1082 ChildListMutationScope(*this).childAdded(child);
1092 1083
1084 childrenChanged(false, child.previousSibling(), child.nextSibling(), 1);
1085
1093 notifyNodeInserted(child); 1086 notifyNodeInserted(child);
1094 1087
1095 dispatchChildInsertionEvents(child); 1088 dispatchChildInsertionEvents(child);
1096 } 1089 }
1097 1090
1098 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const 1091 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const
1099 { 1092 {
1100 return rareData()->hasRestyleFlag(mask); 1093 return rareData()->hasRestyleFlag(mask);
1101 } 1094 }
1102 1095
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1281 return true; 1274 return true;
1282 1275
1283 if (node->isElementNode() && toElement(node)->shadow()) 1276 if (node->isElementNode() && toElement(node)->shadow())
1284 return true; 1277 return true;
1285 1278
1286 return false; 1279 return false;
1287 } 1280 }
1288 #endif 1281 #endif
1289 1282
1290 } // namespace WebCore 1283 } // 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