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 |