OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007 Apple Inc. All rights reserved. |
3 * (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> | 3 * (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
64 void notifyNodeRemovedFromTree(ContainerNode&); | 64 void notifyNodeRemovedFromTree(ContainerNode&); |
65 | 65 |
66 ContainerNode& m_insertionPoint; | 66 ContainerNode& m_insertionPoint; |
67 }; | 67 }; |
68 | 68 |
69 namespace Private { | 69 namespace Private { |
70 | 70 |
71 template<class GenericNode, class GenericNodeContainer> | 71 template<class GenericNode, class GenericNodeContainer> |
72 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, Ge nericNodeContainer&); | 72 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, Ge nericNodeContainer&); |
73 | 73 |
74 } | 74 // Helper methods for removeDetachedChildrenInContainer, hidden from WebCore namespace |
75 | |
76 // Helper functions for TreeShared-derived classes, which have a 'Node' style in terface | |
77 // This applies to 'ContainerNode' and 'SVGElementInstance' | |
78 template<class GenericNode, class GenericNodeContainer> | |
79 inline void removeDetachedChildrenInContainer(GenericNodeContainer& container) | |
80 { | |
81 // List of nodes to be deleted. | |
82 GenericNode* head = 0; | |
83 GenericNode* tail = 0; | |
84 | |
85 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(hea d, tail, container); | |
86 | |
87 GenericNode* n; | |
88 GenericNode* next; | |
89 while ((n = head) != 0) { | |
90 #if !ENABLE(OILPAN) | |
91 ASSERT_WITH_SECURITY_IMPLICATION(n->m_deletionHasBegun); | |
92 #endif | |
93 | |
94 next = n->nextSibling(); | |
95 n->setNextSibling(0); | |
96 | |
97 head = next; | |
98 if (next == 0) | |
99 tail = 0; | |
100 | |
101 if (n->hasChildren()) | |
102 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContai ner>(head, tail, static_cast<GenericNodeContainer&>(*n)); | |
103 | |
104 #if !ENABLE(OILPAN) | |
105 delete n; | |
106 #endif | |
107 } | |
108 } | |
109 | |
110 template<class GenericNode, class GenericNodeContainer> | |
111 inline void appendChildToContainer(GenericNode& child, GenericNodeContainer& con tainer) | |
112 { | |
113 child.setParentOrShadowHostNode(&container); | |
114 | |
115 GenericNode* lastChild = container.lastChild(); | |
116 if (lastChild) { | |
117 child.setPreviousSibling(lastChild); | |
118 lastChild->setNextSibling(&child); | |
119 } else { | |
120 container.setFirstChild(&child); | |
121 } | |
122 | |
123 container.setLastChild(&child); | |
124 } | |
125 | |
126 // Helper methods for removeDetachedChildrenInContainer, hidden from WebCore nam espace | |
127 namespace Private { | |
128 | 75 |
129 template<class GenericNode, class GenericNodeContainer, bool dispatchRemoval Notification> | 76 template<class GenericNode, class GenericNodeContainer, bool dispatchRemoval Notification> |
130 struct NodeRemovalDispatcher { | 77 struct NodeRemovalDispatcher { |
131 static void dispatch(GenericNode&, GenericNodeContainer&) | 78 static void dispatch(GenericNode&, GenericNodeContainer&) |
132 { | 79 { |
133 // no-op, by default | 80 // no-op, by default |
134 } | 81 } |
135 }; | 82 }; |
136 | 83 |
137 template<class GenericNode, class GenericNodeContainer> | 84 template<class GenericNode, class GenericNodeContainer> |
(...skipping 26 matching lines...) Expand all Loading... | |
164 for (GenericNode* n = container.firstChild(); n; n = next) { | 111 for (GenericNode* n = container.firstChild(); n; n = next) { |
165 ASSERT_WITH_SECURITY_IMPLICATION(!n->m_deletionHasBegun); | 112 ASSERT_WITH_SECURITY_IMPLICATION(!n->m_deletionHasBegun); |
166 | 113 |
167 next = n->nextSibling(); | 114 next = n->nextSibling(); |
168 n->setNextSibling(0); | 115 n->setNextSibling(0); |
169 n->setParentOrShadowHostNode(0); | 116 n->setParentOrShadowHostNode(0); |
170 container.setFirstChild(next); | 117 container.setFirstChild(next); |
171 if (next) | 118 if (next) |
172 next->setPreviousSibling(0); | 119 next->setPreviousSibling(0); |
173 | 120 |
174 #if ENABLE(OILPAN) | |
175 { | |
176 // Always notify nodes of removal from the document even if they | |
177 // are going to die. Nodes do not immediately die when their | |
178 // refcounts reach zero with Oilpan. They die at the next garbag e | |
179 // collection. The notifications when removed from document | |
180 // allows us to perform cleanup on the nodes when they are remov ed | |
181 // instead of when their destructors are called. | |
182 RefPtr<GenericNode> protect(n); // removedFromDocument may remov e all references to this node. | |
183 NodeRemovalDispatcher<GenericNode, GenericNodeContainer, ShouldD ispatchRemovalNotification<GenericNode>::value>::dispatch(*n, container); | |
184 } | |
185 if (!n->refCount()) { | |
186 // Add the node to the list of nodes to be deleted. | |
187 // Reuse the nextSibling pointer for this purpose. | |
188 if (tail) | |
189 tail->setNextSibling(n); | |
190 else | |
191 head = n; | |
192 | |
193 tail = n; | |
194 } | |
195 #else | |
196 if (!n->refCount()) { | 121 if (!n->refCount()) { |
197 #if SECURITY_ASSERT_ENABLED | 122 #if SECURITY_ASSERT_ENABLED |
198 n->m_deletionHasBegun = true; | 123 n->m_deletionHasBegun = true; |
199 #endif | 124 #endif |
200 // Add the node to the list of nodes to be deleted. | 125 // Add the node to the list of nodes to be deleted. |
201 // Reuse the nextSibling pointer for this purpose. | 126 // Reuse the nextSibling pointer for this purpose. |
202 if (tail) | 127 if (tail) |
203 tail->setNextSibling(n); | 128 tail->setNextSibling(n); |
204 else | 129 else |
205 head = n; | 130 head = n; |
206 | 131 |
207 tail = n; | 132 tail = n; |
208 } else { | 133 } else { |
209 RefPtr<GenericNode> protect(n); // removedFromDocument may remov e all references to this node. | 134 RefPtr<GenericNode> protect(n); // removedFromDocument may remov e all references to this node. |
210 NodeRemovalDispatcher<GenericNode, GenericNodeContainer, ShouldD ispatchRemovalNotification<GenericNode>::value>::dispatch(*n, container); | 135 NodeRemovalDispatcher<GenericNode, GenericNodeContainer, ShouldD ispatchRemovalNotification<GenericNode>::value>::dispatch(*n, container); |
211 } | 136 } |
212 #endif // ENABLE(OILPAN) | |
213 } | 137 } |
214 | 138 |
215 container.setLastChild(0); | 139 container.setLastChild(0); |
216 } | 140 } |
217 | 141 |
218 } // namespace Private | 142 } // namespace Private |
219 | 143 |
144 // Helper functions for TreeShared-derived classes, which have a 'Node' style in terface | |
145 // This applies to 'ContainerNode' and 'SVGElementInstance' | |
haraken
2014/05/06 04:20:16
FYI, SVGElementInstance is going to be removed soo
Mads Ager (chromium)
2014/05/06 08:26:00
That is great! Right now this code is only used fo
| |
146 template<class GenericNode, class GenericNodeContainer> | |
147 inline void removeDetachedChildrenInContainer(GenericNodeContainer& container) | |
haraken
2014/05/06 04:20:16
Just help me understand (very fundamental question
Mads Ager (chromium)
2014/05/06 08:26:00
Yes, it is very confusing. This is still called by
| |
148 { | |
149 #if ENABLE(OILPAN) | |
150 // Always dispatch node removal notifications when nodes are | |
151 // removed. This maintains the invariant that either nodes have | |
152 // been removed from their container and their removedFrom method has | |
153 // been called, or the nodes die with the their container. | |
haraken
2014/05/06 04:20:16
the their container => their container
Just to co
Mads Ager (chromium)
2014/05/06 08:26:00
That is correct. This is only called from SVGEleme
| |
154 GenericNode* next = 0; | |
155 for (GenericNode* n = container.firstChild(); n; n = next) { | |
156 next = n->nextSibling(); | |
157 n->setNextSibling(0); | |
158 n->setParentOrShadowHostNode(0); | |
159 if (next) | |
160 next->setPreviousSibling(0); | |
161 Private::NodeRemovalDispatcher<GenericNode, GenericNodeContainer, Privat e::ShouldDispatchRemovalNotification<GenericNode>::value>::dispatch(*n, containe r); | |
162 } | |
163 container.setFirstChild(0); | |
164 container.setLastChild(0); | |
165 #else | |
166 // List of nodes to be deleted. | |
167 GenericNode* head = 0; | |
168 GenericNode* tail = 0; | |
169 | |
170 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(hea d, tail, container); | |
171 | |
172 GenericNode* n; | |
173 GenericNode* next; | |
174 while ((n = head) != 0) { | |
175 ASSERT_WITH_SECURITY_IMPLICATION(n->m_deletionHasBegun); | |
176 | |
177 next = n->nextSibling(); | |
178 n->setNextSibling(0); | |
179 | |
180 head = next; | |
181 if (next == 0) | |
182 tail = 0; | |
183 | |
184 if (n->hasChildren()) | |
185 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContai ner>(head, tail, static_cast<GenericNodeContainer&>(*n)); | |
186 | |
187 delete n; | |
188 } | |
189 #endif | |
190 } | |
191 | |
192 template<class GenericNode, class GenericNodeContainer> | |
193 inline void appendChildToContainer(GenericNode& child, GenericNodeContainer& con tainer) | |
194 { | |
195 child.setParentOrShadowHostNode(&container); | |
196 | |
197 GenericNode* lastChild = container.lastChild(); | |
198 if (lastChild) { | |
199 child.setPreviousSibling(lastChild); | |
200 lastChild->setNextSibling(&child); | |
201 } else { | |
202 container.setFirstChild(&child); | |
203 } | |
204 | |
205 container.setLastChild(&child); | |
206 } | |
207 | |
220 inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument(Node& nod e) | 208 inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument(Node& nod e) |
221 { | 209 { |
222 ASSERT(m_insertionPoint.inDocument()); | 210 ASSERT(m_insertionPoint.inDocument()); |
223 RefPtr<Node> protect(node); | 211 RefPtr<Node> protect(node); |
224 if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node.insertedInto (&m_insertionPoint)) | 212 if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node.insertedInto (&m_insertionPoint)) |
225 m_postInsertionNotificationTargets.append(&node); | 213 m_postInsertionNotificationTargets.append(&node); |
226 if (node.isContainerNode()) | 214 if (node.isContainerNode()) |
227 notifyDescendantInsertedIntoDocument(toContainerNode(node)); | 215 notifyDescendantInsertedIntoDocument(toContainerNode(node)); |
228 } | 216 } |
229 | 217 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 for (Node* child = m_root.firstChild(); child; child = child->nextSiblin g()) | 346 for (Node* child = m_root.firstChild(); child; child = child->nextSiblin g()) |
359 collectFrameOwners(*child); | 347 collectFrameOwners(*child); |
360 } | 348 } |
361 | 349 |
362 disconnectCollectedFrameOwners(); | 350 disconnectCollectedFrameOwners(); |
363 } | 351 } |
364 | 352 |
365 } // namespace WebCore | 353 } // namespace WebCore |
366 | 354 |
367 #endif // ContainerNodeAlgorithms_h | 355 #endif // ContainerNodeAlgorithms_h |
OLD | NEW |