| 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' |
| 146 template<class GenericNode, class GenericNodeContainer> |
| 147 inline void removeDetachedChildrenInContainer(GenericNodeContainer& container) |
| 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 the ducument and their removedFrom method has |
| 153 // been called, or the nodes die with the document. |
| 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 |