| 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 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 #include "core/dom/Document.h" | 25 #include "core/dom/Document.h" |
| 26 #include "core/html/HTMLFrameOwnerElement.h" | 26 #include "core/html/HTMLFrameOwnerElement.h" |
| 27 #include "core/inspector/InspectorInstrumentation.h" | 27 #include "core/inspector/InspectorInstrumentation.h" |
| 28 #include "wtf/Assertions.h" | 28 #include "wtf/Assertions.h" |
| 29 | 29 |
| 30 namespace WebCore { | 30 namespace WebCore { |
| 31 | 31 |
| 32 class ChildNodeInsertionNotifier { | 32 class ChildNodeInsertionNotifier { |
| 33 public: | 33 public: |
| 34 explicit ChildNodeInsertionNotifier(ContainerNode* insertionPoint) | 34 explicit ChildNodeInsertionNotifier(ContainerNode& insertionPoint) |
| 35 : m_insertionPoint(insertionPoint) | 35 : m_insertionPoint(insertionPoint) |
| 36 { | 36 { |
| 37 } | 37 } |
| 38 | 38 |
| 39 void notify(Node*); | 39 void notify(Node&); |
| 40 | 40 |
| 41 private: | 41 private: |
| 42 void notifyDescendantInsertedIntoDocument(ContainerNode*); | 42 void notifyDescendantInsertedIntoDocument(ContainerNode&); |
| 43 void notifyDescendantInsertedIntoTree(ContainerNode*); | 43 void notifyDescendantInsertedIntoTree(ContainerNode&); |
| 44 void notifyNodeInsertedIntoDocument(Node*); | 44 void notifyNodeInsertedIntoDocument(Node&); |
| 45 void notifyNodeInsertedIntoTree(ContainerNode*); | 45 void notifyNodeInsertedIntoTree(ContainerNode&); |
| 46 | 46 |
| 47 ContainerNode* m_insertionPoint; | 47 ContainerNode& m_insertionPoint; |
| 48 Vector< RefPtr<Node> > m_postInsertionNotificationTargets; | 48 Vector< RefPtr<Node> > m_postInsertionNotificationTargets; |
| 49 }; | 49 }; |
| 50 | 50 |
| 51 class ChildNodeRemovalNotifier { | 51 class ChildNodeRemovalNotifier { |
| 52 public: | 52 public: |
| 53 explicit ChildNodeRemovalNotifier(ContainerNode* insertionPoint) | 53 explicit ChildNodeRemovalNotifier(ContainerNode& insertionPoint) |
| 54 : m_insertionPoint(insertionPoint) | 54 : m_insertionPoint(insertionPoint) |
| 55 { | 55 { |
| 56 } | 56 } |
| 57 | 57 |
| 58 void notify(Node*); | 58 void notify(Node&); |
| 59 | 59 |
| 60 private: | 60 private: |
| 61 void notifyDescendantRemovedFromDocument(ContainerNode*); | 61 void notifyDescendantRemovedFromDocument(ContainerNode&); |
| 62 void notifyDescendantRemovedFromTree(ContainerNode*); | 62 void notifyDescendantRemovedFromTree(ContainerNode&); |
| 63 void notifyNodeRemovedFromDocument(Node*); | 63 void notifyNodeRemovedFromDocument(Node&); |
| 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 } |
| 75 | 75 |
| 76 // Helper functions for TreeShared-derived classes, which have a 'Node' style in
terface | 76 // Helper functions for TreeShared-derived classes, which have a 'Node' style in
terface |
| 77 // This applies to 'ContainerNode' and 'SVGElementInstance' | 77 // This applies to 'ContainerNode' and 'SVGElementInstance' |
| 78 template<class GenericNode, class GenericNodeContainer> | 78 template<class GenericNode, class GenericNodeContainer> |
| 79 inline void removeDetachedChildrenInContainer(GenericNodeContainer* container) | 79 inline void removeDetachedChildrenInContainer(GenericNodeContainer& container) |
| 80 { | 80 { |
| 81 // List of nodes to be deleted. | 81 // List of nodes to be deleted. |
| 82 GenericNode* head = 0; | 82 GenericNode* head = 0; |
| 83 GenericNode* tail = 0; | 83 GenericNode* tail = 0; |
| 84 | 84 |
| 85 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(hea
d, tail, container); | 85 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(hea
d, tail, container); |
| 86 | 86 |
| 87 GenericNode* n; | 87 GenericNode* n; |
| 88 GenericNode* next; | 88 GenericNode* next; |
| 89 while ((n = head) != 0) { | 89 while ((n = head) != 0) { |
| 90 ASSERT_WITH_SECURITY_IMPLICATION(n->m_deletionHasBegun); | 90 ASSERT_WITH_SECURITY_IMPLICATION(n->m_deletionHasBegun); |
| 91 | 91 |
| 92 next = n->nextSibling(); | 92 next = n->nextSibling(); |
| 93 n->setNextSibling(0); | 93 n->setNextSibling(0); |
| 94 | 94 |
| 95 head = next; | 95 head = next; |
| 96 if (next == 0) | 96 if (next == 0) |
| 97 tail = 0; | 97 tail = 0; |
| 98 | 98 |
| 99 if (n->hasChildNodes()) | 99 if (n->hasChildNodes()) |
| 100 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContai
ner>(head, tail, static_cast<GenericNodeContainer*>(n)); | 100 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContai
ner>(head, tail, static_cast<GenericNodeContainer&>(*n)); |
| 101 | 101 |
| 102 delete n; | 102 delete n; |
| 103 } | 103 } |
| 104 } | 104 } |
| 105 | 105 |
| 106 template<class GenericNode, class GenericNodeContainer> | 106 template<class GenericNode, class GenericNodeContainer> |
| 107 inline void appendChildToContainer(GenericNode* child, GenericNodeContainer* con
tainer) | 107 inline void appendChildToContainer(GenericNode& child, GenericNodeContainer& con
tainer) |
| 108 { | 108 { |
| 109 child->setParentOrShadowHostNode(container); | 109 child.setParentOrShadowHostNode(&container); |
| 110 | 110 |
| 111 GenericNode* lastChild = container->lastChild(); | 111 GenericNode* lastChild = container.lastChild(); |
| 112 if (lastChild) { | 112 if (lastChild) { |
| 113 child->setPreviousSibling(lastChild); | 113 child.setPreviousSibling(lastChild); |
| 114 lastChild->setNextSibling(child); | 114 lastChild->setNextSibling(&child); |
| 115 } else | 115 } else { |
| 116 container->setFirstChild(child); | 116 container.setFirstChild(&child); |
| 117 } |
| 117 | 118 |
| 118 container->setLastChild(child); | 119 container.setLastChild(&child); |
| 119 } | 120 } |
| 120 | 121 |
| 121 // Helper methods for removeDetachedChildrenInContainer, hidden from WebCore nam
espace | 122 // Helper methods for removeDetachedChildrenInContainer, hidden from WebCore nam
espace |
| 122 namespace Private { | 123 namespace Private { |
| 123 | 124 |
| 124 template<class GenericNode, class GenericNodeContainer, bool dispatchRemoval
Notification> | 125 template<class GenericNode, class GenericNodeContainer, bool dispatchRemoval
Notification> |
| 125 struct NodeRemovalDispatcher { | 126 struct NodeRemovalDispatcher { |
| 126 static void dispatch(GenericNode*, GenericNodeContainer*) | 127 static void dispatch(GenericNode&, GenericNodeContainer&) |
| 127 { | 128 { |
| 128 // no-op, by default | 129 // no-op, by default |
| 129 } | 130 } |
| 130 }; | 131 }; |
| 131 | 132 |
| 132 template<class GenericNode, class GenericNodeContainer> | 133 template<class GenericNode, class GenericNodeContainer> |
| 133 struct NodeRemovalDispatcher<GenericNode, GenericNodeContainer, true> { | 134 struct NodeRemovalDispatcher<GenericNode, GenericNodeContainer, true> { |
| 134 static void dispatch(GenericNode* node, GenericNodeContainer* container) | 135 static void dispatch(GenericNode& node, GenericNodeContainer& container) |
| 135 { | 136 { |
| 136 // Clean up any TreeScope to a removed tree. | 137 // Clean up any TreeScope to a removed tree. |
| 137 if (Document* containerDocument = container->ownerDocument()) | 138 if (Document* containerDocument = container.ownerDocument()) |
| 138 containerDocument->adoptIfNeeded(node); | 139 containerDocument->adoptIfNeeded(&node); |
| 139 if (node->inDocument()) | 140 if (node.inDocument()) |
| 140 ChildNodeRemovalNotifier(container).notify(node); | 141 ChildNodeRemovalNotifier(container).notify(node); |
| 141 } | 142 } |
| 142 }; | 143 }; |
| 143 | 144 |
| 144 template<class GenericNode> | 145 template<class GenericNode> |
| 145 struct ShouldDispatchRemovalNotification { | 146 struct ShouldDispatchRemovalNotification { |
| 146 static const bool value = false; | 147 static const bool value = false; |
| 147 }; | 148 }; |
| 148 | 149 |
| 149 template<> | 150 template<> |
| 150 struct ShouldDispatchRemovalNotification<Node> { | 151 struct ShouldDispatchRemovalNotification<Node> { |
| 151 static const bool value = true; | 152 static const bool value = true; |
| 152 }; | 153 }; |
| 153 | 154 |
| 154 template<class GenericNode, class GenericNodeContainer> | 155 template<class GenericNode, class GenericNodeContainer> |
| 155 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, Ge
nericNodeContainer* container) | 156 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, Ge
nericNodeContainer& container) |
| 156 { | 157 { |
| 157 // We have to tell all children that their parent has died. | 158 // We have to tell all children that their parent has died. |
| 158 GenericNode* next = 0; | 159 GenericNode* next = 0; |
| 159 for (GenericNode* n = container->firstChild(); n != 0; n = next) { | 160 for (GenericNode* n = container.firstChild(); n; n = next) { |
| 160 ASSERT_WITH_SECURITY_IMPLICATION(!n->m_deletionHasBegun); | 161 ASSERT_WITH_SECURITY_IMPLICATION(!n->m_deletionHasBegun); |
| 161 | 162 |
| 162 next = n->nextSibling(); | 163 next = n->nextSibling(); |
| 163 n->setNextSibling(0); | 164 n->setNextSibling(0); |
| 164 n->setParentOrShadowHostNode(0); | 165 n->setParentOrShadowHostNode(0); |
| 165 container->setFirstChild(next); | 166 container.setFirstChild(next); |
| 166 if (next) | 167 if (next) |
| 167 next->setPreviousSibling(0); | 168 next->setPreviousSibling(0); |
| 168 | 169 |
| 169 if (!n->refCount()) { | 170 if (!n->refCount()) { |
| 170 #if SECURITY_ASSERT_ENABLED | 171 #if SECURITY_ASSERT_ENABLED |
| 171 n->m_deletionHasBegun = true; | 172 n->m_deletionHasBegun = true; |
| 172 #endif | 173 #endif |
| 173 // Add the node to the list of nodes to be deleted. | 174 // Add the node to the list of nodes to be deleted. |
| 174 // Reuse the nextSibling pointer for this purpose. | 175 // Reuse the nextSibling pointer for this purpose. |
| 175 if (tail) | 176 if (tail) |
| 176 tail->setNextSibling(n); | 177 tail->setNextSibling(n); |
| 177 else | 178 else |
| 178 head = n; | 179 head = n; |
| 179 | 180 |
| 180 tail = n; | 181 tail = n; |
| 181 } else { | 182 } else { |
| 182 RefPtr<GenericNode> protect(n); // removedFromDocument may remov
e remove all references to this node. | 183 RefPtr<GenericNode> protect(n); // removedFromDocument may remov
e remove all references to this node. |
| 183 NodeRemovalDispatcher<GenericNode, GenericNodeContainer, ShouldD
ispatchRemovalNotification<GenericNode>::value>::dispatch(n, container); | 184 NodeRemovalDispatcher<GenericNode, GenericNodeContainer, ShouldD
ispatchRemovalNotification<GenericNode>::value>::dispatch(*n, container); |
| 184 } | 185 } |
| 185 } | 186 } |
| 186 | 187 |
| 187 container->setLastChild(0); | 188 container.setLastChild(0); |
| 188 } | 189 } |
| 189 | 190 |
| 190 } // namespace Private | 191 } // namespace Private |
| 191 | 192 |
| 192 inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument(Node* nod
e) | 193 inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument(Node& nod
e) |
| 193 { | 194 { |
| 194 ASSERT(m_insertionPoint->inDocument()); | 195 ASSERT(m_insertionPoint.inDocument()); |
| 195 RefPtr<Node> protect(node); | 196 RefPtr<Node> protect(node); |
| 196 if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node->insertedInt
o(m_insertionPoint)) | 197 if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node.insertedInto
(&m_insertionPoint)) |
| 197 m_postInsertionNotificationTargets.append(node); | 198 m_postInsertionNotificationTargets.append(&node); |
| 198 if (node->isContainerNode()) | 199 if (node.isContainerNode()) |
| 199 notifyDescendantInsertedIntoDocument(toContainerNode(node)); | 200 notifyDescendantInsertedIntoDocument(toContainerNode(node)); |
| 200 } | 201 } |
| 201 | 202 |
| 202 inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoTree(ContainerNode
* node) | 203 inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoTree(ContainerNode
& node) |
| 203 { | 204 { |
| 204 NoEventDispatchAssertion assertNoEventDispatch; | 205 NoEventDispatchAssertion assertNoEventDispatch; |
| 205 ASSERT(!m_insertionPoint->inDocument()); | 206 ASSERT(!m_insertionPoint.inDocument()); |
| 206 | 207 |
| 207 if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node->insertedInt
o(m_insertionPoint)) | 208 if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node.insertedInto
(&m_insertionPoint)) |
| 208 m_postInsertionNotificationTargets.append(node); | 209 m_postInsertionNotificationTargets.append(&node); |
| 209 notifyDescendantInsertedIntoTree(node); | 210 notifyDescendantInsertedIntoTree(node); |
| 210 } | 211 } |
| 211 | 212 |
| 212 inline void ChildNodeInsertionNotifier::notify(Node* node) | 213 inline void ChildNodeInsertionNotifier::notify(Node& node) |
| 213 { | 214 { |
| 214 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); | 215 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); |
| 215 | 216 |
| 216 InspectorInstrumentation::didInsertDOMNode(node); | 217 InspectorInstrumentation::didInsertDOMNode(&node); |
| 217 | 218 |
| 218 RefPtr<Document> protectDocument(node->document()); | 219 RefPtr<Document> protectDocument(node.document()); |
| 219 RefPtr<Node> protectNode(node); | 220 RefPtr<Node> protectNode(node); |
| 220 | 221 |
| 221 if (m_insertionPoint->inDocument()) | 222 if (m_insertionPoint.inDocument()) |
| 222 notifyNodeInsertedIntoDocument(node); | 223 notifyNodeInsertedIntoDocument(node); |
| 223 else if (node->isContainerNode()) | 224 else if (node.isContainerNode()) |
| 224 notifyNodeInsertedIntoTree(toContainerNode(node)); | 225 notifyNodeInsertedIntoTree(toContainerNode(node)); |
| 225 | 226 |
| 226 // Script runs in didNotifySubtreeInsertions so we should lazy attach before | 227 // Script runs in didNotifySubtreeInsertions so we should lazy attach before |
| 227 // to ensure that triggering a style recalc in script attaches all nodes tha
t | 228 // to ensure that triggering a style recalc in script attaches all nodes tha
t |
| 228 // were inserted. | 229 // were inserted. |
| 229 // FIXME: We should merge the lazy attach logic into the tree traversal in | 230 // FIXME: We should merge the lazy attach logic into the tree traversal in |
| 230 // notifyNodeInsertedIntoDocument. | 231 // notifyNodeInsertedIntoDocument. |
| 231 if (!node->confusingAndOftenMisusedAttached() && node->parentNode() && node-
>parentNode()->confusingAndOftenMisusedAttached()) | 232 if (!node.confusingAndOftenMisusedAttached() && node.parentNode() && node.pa
rentNode()->confusingAndOftenMisusedAttached()) |
| 232 node->lazyAttach(); | 233 node.lazyAttach(); |
| 233 | 234 |
| 234 for (size_t i = 0; i < m_postInsertionNotificationTargets.size(); ++i) { | 235 for (size_t i = 0; i < m_postInsertionNotificationTargets.size(); ++i) { |
| 235 Node* node = m_postInsertionNotificationTargets[i].get(); | 236 Node* targetNode = m_postInsertionNotificationTargets[i].get(); |
| 236 if (node->inDocument()) | 237 if (targetNode->inDocument()) |
| 237 node->didNotifySubtreeInsertionsToDocument(); | 238 targetNode->didNotifySubtreeInsertionsToDocument(); |
| 238 } | 239 } |
| 239 } | 240 } |
| 240 | 241 |
| 241 inline void ChildNodeRemovalNotifier::notifyNodeRemovedFromDocument(Node* node) | 242 inline void ChildNodeRemovalNotifier::notifyNodeRemovedFromDocument(Node& node) |
| 242 { | 243 { |
| 243 ASSERT(m_insertionPoint->inDocument()); | 244 ASSERT(m_insertionPoint.inDocument()); |
| 244 node->removedFrom(m_insertionPoint); | 245 node.removedFrom(&m_insertionPoint); |
| 245 | 246 |
| 246 if (node->isContainerNode()) | 247 if (node.isContainerNode()) |
| 247 notifyDescendantRemovedFromDocument(toContainerNode(node)); | 248 notifyDescendantRemovedFromDocument(toContainerNode(node)); |
| 248 } | 249 } |
| 249 | 250 |
| 250 inline void ChildNodeRemovalNotifier::notifyNodeRemovedFromTree(ContainerNode* n
ode) | 251 inline void ChildNodeRemovalNotifier::notifyNodeRemovedFromTree(ContainerNode& n
ode) |
| 251 { | 252 { |
| 252 NoEventDispatchAssertion assertNoEventDispatch; | 253 NoEventDispatchAssertion assertNoEventDispatch; |
| 253 ASSERT(!m_insertionPoint->inDocument()); | 254 ASSERT(!m_insertionPoint.inDocument()); |
| 254 | 255 |
| 255 node->removedFrom(m_insertionPoint); | 256 node.removedFrom(&m_insertionPoint); |
| 256 notifyDescendantRemovedFromTree(node); | 257 notifyDescendantRemovedFromTree(node); |
| 257 } | 258 } |
| 258 | 259 |
| 259 inline void ChildNodeRemovalNotifier::notify(Node* node) | 260 inline void ChildNodeRemovalNotifier::notify(Node& node) |
| 260 { | 261 { |
| 261 if (node->inDocument()) { | 262 if (node.inDocument()) { |
| 262 notifyNodeRemovedFromDocument(node); | 263 notifyNodeRemovedFromDocument(node); |
| 263 node->document().notifyRemovePendingSheetIfNeeded(); | 264 node.document().notifyRemovePendingSheetIfNeeded(); |
| 264 } else if (node->isContainerNode()) | 265 } else if (node.isContainerNode()) |
| 265 notifyNodeRemovedFromTree(toContainerNode(node)); | 266 notifyNodeRemovedFromTree(toContainerNode(node)); |
| 266 } | 267 } |
| 267 | 268 |
| 268 class ChildFrameDisconnector { | 269 class ChildFrameDisconnector { |
| 269 public: | 270 public: |
| 270 enum DisconnectPolicy { | 271 enum DisconnectPolicy { |
| 271 RootAndDescendants, | 272 RootAndDescendants, |
| 272 DescendantsOnly | 273 DescendantsOnly |
| 273 }; | 274 }; |
| 274 | 275 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 for (Node* child = m_root->firstChild(); child; child = child->nextSibli
ng()) | 339 for (Node* child = m_root->firstChild(); child; child = child->nextSibli
ng()) |
| 339 collectFrameOwners(child); | 340 collectFrameOwners(child); |
| 340 } | 341 } |
| 341 | 342 |
| 342 disconnectCollectedFrameOwners(); | 343 disconnectCollectedFrameOwners(); |
| 343 } | 344 } |
| 344 | 345 |
| 345 } // namespace WebCore | 346 } // namespace WebCore |
| 346 | 347 |
| 347 #endif // ContainerNodeAlgorithms_h | 348 #endif // ContainerNodeAlgorithms_h |
| OLD | NEW |