1 /*
2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22 #ifndef ContainerNodeAlgorithms_h
23 #define ContainerNodeAlgorithms_h
24
25 #include "core/dom/Document.h"
26 #include "wtf/Assertions.h"
27
28 namespace WebCore {
29
30 namespace Private {
31
32 template<class GenericNode, class GenericNodeContainer>
33 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
34
35 }
36
37 #if !ENABLE(OILPAN)
38 // Helper functions for TreeShared-derived classes, which have a 'Node' style interface
39 // This applies to 'ContainerNode' and 'SVGElementInstance'
40 template<class GenericNode, class GenericNodeContainer>
removeDetachedChildrenInContainer(GenericNodeContainer & container)41 inline void removeDetachedChildrenInContainer(GenericNodeContainer& container)
42 {
43 // List of nodes to be deleted.
44 GenericNode* head = 0;
45 GenericNode* tail = 0;
46
47 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(head, tail, container);
48
49 GenericNode* n;
50 GenericNode* next;
51 while ((n = head) != 0) {
52 ASSERT_WITH_SECURITY_IMPLICATION(n->m_deletionHasBegun);
53
54 next = n->nextSibling();
55 n->setNextSibling(0);
56
57 head = next;
58 if (next == 0)
59 tail = 0;
60
61 if (n->hasChildren())
62 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(head, tail, static_cast<GenericNodeContainer&>(*n));
63
64 delete n;
65 }
66 }
67 #endif
68
69 // Helper methods for removeDetachedChildrenInContainer, hidden from WebCore namespace
70 namespace Private {
71
72 template<class GenericNode, class GenericNodeContainer>
addChildNodesToDeletionQueue(GenericNode * & head,GenericNode * & tail,GenericNodeContainer & container)73 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer& container)
74 {
75 // We have to tell all children that their parent has died.
76 GenericNode* next = 0;
77 for (GenericNode* n = container.firstChild(); n; n = next) {
78 ASSERT_WITH_SECURITY_IMPLICATION(!n->m_deletionHasBegun);
79
80 next = n->nextSibling();
81 n->setNextSibling(0);
82 n->setParentOrShadowHostNode(0);
83 container.setFirstChild(next);
84 if (next)
85 next->setPreviousSibling(0);
86
87 if (!n->refCount()) {
88 #if SECURITY_ASSERT_ENABLED
89 n->m_deletionHasBegun = true;
90 #endif
91 // Add the node to the list of nodes to be deleted.
92 // Reuse the nextSibling pointer for this purpose.
93 if (tail)
94 tail->setNextSibling(n);
95 else
96 head = n;
97
98 tail = n;
99 } else {
100 RefPtrWillBeRawPtr<GenericNode> protect(n); // removedFromDocument may remove all references to this node.
101 container.document().adoptIfNeeded(*n);
102 if (n->inDocument())
103 container.notifyNodeRemoved(*n);
104 }
105 }
106
107 container.setLastChild(0);
108 }
109
110 } // namespace Private
111
112 } // namespace WebCore
113
114 #endif // ContainerNodeAlgorithms_h
115