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

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

Issue 23243003: [oilpan] Wrap NodeVector into CollectionRoot for ensure that contained nodes stay alive. (Closed) Base URL: svn://svn.chromium.org/blink/branches/oilpan
Patch Set: Fix infinite looping Created 7 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
« no previous file with comments | « Source/core/dom/ContainerNode.h ('k') | Source/core/editing/ApplyStyleCommand.cpp » ('j') | 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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 69
70 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0; 70 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0;
71 71
72 #ifndef NDEBUG 72 #ifndef NDEBUG
73 unsigned NoEventDispatchAssertion::s_count = 0; 73 unsigned NoEventDispatchAssertion::s_count = 0;
74 #endif 74 #endif
75 75
76 static void collectChildrenAndRemoveFromOldParent(Node* node, NodeVector& nodes, ExceptionCode& ec) 76 static void collectChildrenAndRemoveFromOldParent(Node* node, NodeVector& nodes, ExceptionCode& ec)
77 { 77 {
78 if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) { 78 if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
79 nodes.append(adoptRawResult(node)); 79 nodes->append(adoptRawResult(node));
80 if (Handle<ContainerNode> oldParent = node->parentNode()) 80 if (Handle<ContainerNode> oldParent = node->parentNode())
81 oldParent->removeChild(adoptRawResult(node), ec); 81 oldParent->removeChild(adoptRawResult(node), ec);
82 return; 82 return;
83 } 83 }
84 getChildNodes(node, nodes); 84 getChildNodes(node, nodes);
85 toContainerNode(node)->removeChildren(); 85 toContainerNode(node)->removeChildren();
86 } 86 }
87 87
88 void ContainerNode::removeDetachedChildren() 88 void ContainerNode::removeDetachedChildren()
89 { 89 {
90 if (connectedSubframeCount()) { 90 if (connectedSubframeCount()) {
91 for (Handle<Node> child = firstChild(); child; child = child->nextSiblin g()) { 91 for (Handle<Node> child = firstChild(); child; child = child->nextSiblin g()) {
92 HandleScope scope; 92 HandleScope scope;
93 child->updateAncestorConnectedSubframeCountForRemoval(); 93 child->updateAncestorConnectedSubframeCountForRemoval();
94 } 94 }
95 } 95 }
96 // FIXME: We should be able to ASSERT(!attached()) here: https://bugs.webkit .org/show_bug.cgi?id=107801 96 // FIXME: We should be able to ASSERT(!attached()) here: https://bugs.webkit .org/show_bug.cgi?id=107801
97 removeDetachedChildrenInContainer<Node, ContainerNode>(this); 97 removeDetachedChildrenInContainer<Node, ContainerNode>(this);
98 } 98 }
99 99
100 void ContainerNode::takeAllChildrenFrom(const Handle<ContainerNode>& oldParent) 100 void ContainerNode::takeAllChildrenFrom(const Handle<ContainerNode>& oldParent)
101 { 101 {
102 NodeVector children; 102 NodeVector children;
103 getChildNodes(oldParent.raw(), children); 103 getChildNodes(oldParent.raw(), children);
104 104
105 if (oldParent->document()->hasMutationObserversOfType(MutationObserver::Chil dList)) { 105 if (oldParent->document()->hasMutationObserversOfType(MutationObserver::Chil dList)) {
106 ChildListMutationScope mutation(oldParent.raw()); 106 ChildListMutationScope mutation(oldParent.raw());
107 for (unsigned i = 0; i < children.size(); ++i) { 107 for (unsigned i = 0; i < children->size(); ++i) {
108 HandleScope scope; 108 HandleScope scope;
109 mutation.willRemoveChild(children[i].handle().raw()); 109 mutation.willRemoveChild(children[i].handle().raw());
110 } 110 }
111 } 111 }
112 112
113 // FIXME: We need to do notifyMutationObserversNodeWillDetach() for each chi ld, 113 // FIXME: We need to do notifyMutationObserversNodeWillDetach() for each chi ld,
114 // probably inside removeDetachedChildrenInContainer. 114 // probably inside removeDetachedChildrenInContainer.
115 115
116 oldParent->removeDetachedChildren(); 116 oldParent->removeDetachedChildren();
117 117
118 for (unsigned i = 0; i < children.size(); ++i) { 118 for (unsigned i = 0; i < children->size(); ++i) {
119 HandleScope scope; 119 HandleScope scope;
120 if (children[i]->attached()) 120 if (children[i]->attached())
121 children[i]->detach(); 121 children[i]->detach();
122 // FIXME: We need a no mutation event version of adoptNode. 122 // FIXME: We need a no mutation event version of adoptNode.
123 RefPtr<Node> child = document()->adoptNode(children[i].handle().raw(), A SSERT_NO_EXCEPTION); 123 RefPtr<Node> child = document()->adoptNode(children[i].handle().raw(), A SSERT_NO_EXCEPTION);
124 parserAppendChild(child.get()); 124 parserAppendChild(child.get());
125 // FIXME: Together with adoptNode above, the tree scope might get update d recursively twice 125 // FIXME: Together with adoptNode above, the tree scope might get update d recursively twice
126 // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree). 126 // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
127 // Can we do better? 127 // Can we do better?
128 treeScope()->adoptIfNeeded(child.get()); 128 treeScope()->adoptIfNeeded(child.get());
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 253
254 if (refChild->previousSibling() == newChild || refChild == newChild) // noth ing to do 254 if (refChild->previousSibling() == newChild || refChild == newChild) // noth ing to do
255 return true; 255 return true;
256 256
257 Handle<Node> next = refChild; 257 Handle<Node> next = refChild;
258 258
259 NodeVector targets; 259 NodeVector targets;
260 collectChildrenAndRemoveFromOldParent(newChild.raw(), targets, ec); 260 collectChildrenAndRemoveFromOldParent(newChild.raw(), targets, ec);
261 if (ec) 261 if (ec)
262 return false; 262 return false;
263 if (targets.isEmpty()) 263 if (targets->isEmpty())
264 return true; 264 return true;
265 265
266 // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. 266 // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
267 if (!checkAcceptChildGuaranteedNodeTypes(selfHandle(), newChild.raw(), ec)) 267 if (!checkAcceptChildGuaranteedNodeTypes(selfHandle(), newChild.raw(), ec))
268 return false; 268 return false;
269 269
270 InspectorInstrumentation::willInsertDOMNode(document(), this); 270 InspectorInstrumentation::willInsertDOMNode(document(), this);
271 271
272 ChildListMutationScope mutation(this); 272 ChildListMutationScope mutation(this);
273 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { 273 for (NodeVector::const_iterator it = targets->begin(); it != targets->end(); ++it) {
274 HandleScope scope; 274 HandleScope scope;
275 Handle<Node> child = *it; 275 Handle<Node> child = *it;
276 276
277 // Due to arbitrary code running in response to a DOM mutation event it' s 277 // Due to arbitrary code running in response to a DOM mutation event it' s
278 // possible that "next" is no longer a child of "this". 278 // possible that "next" is no longer a child of "this".
279 // It's also possible that "child" has been inserted elsewhere. 279 // It's also possible that "child" has been inserted elsewhere.
280 // In either of those cases, we'll just stop. 280 // In either of those cases, we'll just stop.
281 if (next->parentNode() != this) 281 if (next->parentNode() != this)
282 break; 282 break;
283 if (child->parentNode()) 283 if (child->parentNode())
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 if (ec) 393 if (ec)
394 return false; 394 return false;
395 395
396 // Does this yet another check because collectChildrenAndRemoveFromOldParent () fires a MutationEvent. 396 // Does this yet another check because collectChildrenAndRemoveFromOldParent () fires a MutationEvent.
397 if (!checkReplaceChild(selfHandle(), newChild.raw(), oldChild.raw(), ec)) 397 if (!checkReplaceChild(selfHandle(), newChild.raw(), oldChild.raw(), ec))
398 return false; 398 return false;
399 399
400 InspectorInstrumentation::willInsertDOMNode(document(), this); 400 InspectorInstrumentation::willInsertDOMNode(document(), this);
401 401
402 // Add the new child(ren) 402 // Add the new child(ren)
403 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { 403 for (NodeVector::const_iterator it = targets->begin(); it != targets->end(); ++it) {
404 HandleScope scope; 404 HandleScope scope;
405 Handle<Node> child = *it; 405 Handle<Node> child = *it;
406 406
407 // Due to arbitrary code running in response to a DOM mutation event it' s 407 // Due to arbitrary code running in response to a DOM mutation event it' s
408 // possible that "next" is no longer a child of "this". 408 // possible that "next" is no longer a child of "this".
409 // It's also possible that "child" has been inserted elsewhere. 409 // It's also possible that "child" has been inserted elsewhere.
410 // In either of those cases, we'll just stop. 410 // In either of those cases, we'll just stop.
411 if (next && next->parentNode() != this) 411 if (next && next->parentNode() != this)
412 break; 412 break;
413 if (child->parentNode()) 413 if (child->parentNode())
(...skipping 30 matching lines...) Expand all
444 444
445 static void willRemoveChildren(const Handle<ContainerNode>& container) 445 static void willRemoveChildren(const Handle<ContainerNode>& container)
446 { 446 {
447 HandleScope scope; 447 HandleScope scope;
448 NodeVector children; 448 NodeVector children;
449 getChildNodes(container.raw(), children); 449 getChildNodes(container.raw(), children);
450 450
451 container->document()->nodeChildrenWillBeRemoved(container); 451 container->document()->nodeChildrenWillBeRemoved(container);
452 452
453 ChildListMutationScope mutation(container.raw()); 453 ChildListMutationScope mutation(container.raw());
454 for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) { 454 for (NodeVector::const_iterator it = children->begin(); it != children->end( ); it++) {
455 HandleScope scope; 455 HandleScope scope;
456 Node* child = it->handle().raw(); 456 Node* child = it->handle().raw();
457 mutation.willRemoveChild(child); 457 mutation.willRemoveChild(child);
458 child->notifyMutationObserversNodeWillDetach(); 458 child->notifyMutationObserversNodeWillDetach();
459 459
460 // fire removed from document mutation events. 460 // fire removed from document mutation events.
461 dispatchChildRemovalEvents(child); 461 dispatchChildRemovalEvents(child);
462 } 462 }
463 463
464 ChildFrameDisconnector(container).disconnect(ChildFrameDisconnector::Descend antsOnly); 464 ChildFrameDisconnector(container).disconnect(ChildFrameDisconnector::Descend antsOnly);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 592
593 // Do any prep work needed before actually starting to detach 593 // Do any prep work needed before actually starting to detach
594 // and remove... e.g. stop loading frames, fire unload events. 594 // and remove... e.g. stop loading frames, fire unload events.
595 willRemoveChildren(protect); 595 willRemoveChildren(protect);
596 596
597 NodeVector removedChildren; 597 NodeVector removedChildren;
598 { 598 {
599 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; 599 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
600 { 600 {
601 NoEventDispatchAssertion assertNoEventDispatch; 601 NoEventDispatchAssertion assertNoEventDispatch;
602 removedChildren.reserveInitialCapacity(childNodeCount()); 602 removedChildren->reserveInitialCapacity(childNodeCount());
603 while (m_firstChild) { 603 while (m_firstChild) {
604 HandleScope scope; 604 HandleScope scope;
605 removedChildren.append(m_firstChild); 605 removedChildren->append(m_firstChild);
606 removeBetween(nullptr, m_firstChild->nextSibling(), m_firstChild ); 606 removeBetween(nullptr, m_firstChild->nextSibling(), m_firstChild );
607 } 607 }
608 } 608 }
609 609
610 childrenChanged(false, nullptr, nullptr, -static_cast<int>(removedChildr en.size())); 610 childrenChanged(false, nullptr, nullptr, -static_cast<int>(removedChildr en->size()));
611 611
612 for (size_t i = 0; i < removedChildren.size(); ++i) { 612 for (size_t i = 0; i < removedChildren->size(); ++i) {
613 HandleScope scope; 613 HandleScope scope;
614 ChildNodeRemovalNotifier(selfHandle()).notify(removedChildren[i].han dle().raw()); 614 ChildNodeRemovalNotifier(selfHandle()).notify(removedChildren[i].han dle().raw());
615 } 615 }
616 } 616 }
617 617
618 dispatchSubtreeModifiedEvent(); 618 dispatchSubtreeModifiedEvent();
619 } 619 }
620 620
621 bool ContainerNode::appendChild(const Handle<Node>& newChild, ExceptionCode& ec, AttachBehavior attachBehavior) 621 bool ContainerNode::appendChild(const Handle<Node>& newChild, ExceptionCode& ec, AttachBehavior attachBehavior)
622 { 622 {
623 HandleScope scope; 623 HandleScope scope;
624 // FIXME(oilpan): not needed when all Node pointers are handlified. 624 // FIXME(oilpan): not needed when all Node pointers are handlified.
625 Handle<ContainerNode> protect(this); 625 Handle<ContainerNode> protect(this);
626 626
627 ec = 0; 627 ec = 0;
628 628
629 // Make sure adding the new child is ok 629 // Make sure adding the new child is ok
630 if (!checkAddChild(selfHandle(), newChild.raw(), ec)) 630 if (!checkAddChild(selfHandle(), newChild.raw(), ec))
631 return false; 631 return false;
632 632
633 if (newChild == m_lastChild) // nothing to do 633 if (newChild == m_lastChild) // nothing to do
634 return newChild; 634 return newChild;
635 635
636 NodeVector targets; 636 NodeVector targets;
637 collectChildrenAndRemoveFromOldParent(newChild.raw(), targets, ec); 637 collectChildrenAndRemoveFromOldParent(newChild.raw(), targets, ec);
638 if (ec) 638 if (ec)
639 return false; 639 return false;
640 640
641 if (targets.isEmpty()) 641 if (targets->isEmpty())
642 return true; 642 return true;
643 643
644 // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. 644 // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
645 if (!checkAcceptChildGuaranteedNodeTypes(selfHandle(), newChild.raw(), ec)) 645 if (!checkAcceptChildGuaranteedNodeTypes(selfHandle(), newChild.raw(), ec))
646 return false; 646 return false;
647 647
648 InspectorInstrumentation::willInsertDOMNode(document(), this); 648 InspectorInstrumentation::willInsertDOMNode(document(), this);
649 649
650 // Now actually add the child(ren) 650 // Now actually add the child(ren)
651 ChildListMutationScope mutation(this); 651 ChildListMutationScope mutation(this);
652 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { 652 for (NodeVector::const_iterator it = targets->begin(); it != targets->end(); ++it) {
653 HandleScope scope; 653 HandleScope scope;
654 Handle<Node> child = *it; 654 Handle<Node> child = *it;
655 655
656 // If the child has a parent again, just stop what we're doing, because 656 // If the child has a parent again, just stop what we're doing, because
657 // that means someone is doing something with DOM mutation -- can't re-p arent 657 // that means someone is doing something with DOM mutation -- can't re-p arent
658 // a child that already has a parent. 658 // a child that already has a parent.
659 if (child->parentNode()) 659 if (child->parentNode())
660 break; 660 break;
661 661
662 treeScope()->adoptIfNeeded(child.raw()); 662 treeScope()->adoptIfNeeded(child.raw());
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 void ContainerNode::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 874 void ContainerNode::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
875 { 875 {
876 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); 876 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
877 Node::reportMemoryUsage(memoryObjectInfo); 877 Node::reportMemoryUsage(memoryObjectInfo);
878 info.ignoreMember(m_firstChild); 878 info.ignoreMember(m_firstChild);
879 info.ignoreMember(m_lastChild); 879 info.ignoreMember(m_lastChild);
880 880
881 // Report child nodes as direct members to make them look like a tree in the snapshot. 881 // Report child nodes as direct members to make them look like a tree in the snapshot.
882 NodeVector children; 882 NodeVector children;
883 getChildNodes(const_cast<ContainerNode*>(this), children); 883 getChildNodes(const_cast<ContainerNode*>(this), children);
884 for (size_t i = 0; i < children.size(); ++i) 884 for (size_t i = 0; i < children->size(); ++i)
885 info.addMember(children[i], "child"); 885 info.addMember(children[i], "child");
886 } 886 }
887 887
888 static void dispatchChildInsertionEvents(Node* child) 888 static void dispatchChildInsertionEvents(Node* child)
889 { 889 {
890 if (child->isInShadowTree()) 890 if (child->isInShadowTree())
891 return; 891 return;
892 892
893 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); 893 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
894 894
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 #endif 971 #endif
972 972
973 void ContainerNode::accept(Visitor* visitor) const 973 void ContainerNode::accept(Visitor* visitor) const
974 { 974 {
975 Node::accept(visitor); 975 Node::accept(visitor);
976 visitor->visit(m_firstChild); 976 visitor->visit(m_firstChild);
977 visitor->visit(m_lastChild); 977 visitor->visit(m_lastChild);
978 } 978 }
979 979
980 } // namespace WebCore 980 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/dom/ContainerNode.h ('k') | Source/core/editing/ApplyStyleCommand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698