OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0; | 56 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0; |
57 | 57 |
58 #ifndef NDEBUG | 58 #ifndef NDEBUG |
59 unsigned NoEventDispatchAssertion::s_count = 0; | 59 unsigned NoEventDispatchAssertion::s_count = 0; |
60 #endif | 60 #endif |
61 | 61 |
62 static const char appendChildMethodName[] = "appendChild"; | 62 static const char appendChildMethodName[] = "appendChild"; |
63 static const char insertBeforeMethodName[] = "insertBefore"; | 63 static const char insertBeforeMethodName[] = "insertBefore"; |
64 static const char replaceChildMethodName[] = "replaceChild"; | 64 static const char replaceChildMethodName[] = "replaceChild"; |
65 | 65 |
66 static void collectChildrenAndRemoveFromOldParent(Node* node, NodeVector& nodes,
ExceptionState& es) | 66 static void collectChildrenAndRemoveFromOldParent(Node& node, NodeVector& nodes,
ExceptionState& es) |
67 { | 67 { |
68 if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) { | 68 if (node.nodeType() != Node::DOCUMENT_FRAGMENT_NODE) { |
69 nodes.append(node); | 69 nodes.append(&node); |
70 if (ContainerNode* oldParent = node->parentNode()) | 70 if (ContainerNode* oldParent = node.parentNode()) |
71 oldParent->removeChild(node, es); | 71 oldParent->removeChild(&node, es); |
72 return; | 72 return; |
73 } | 73 } |
74 getChildNodes(node, nodes); | 74 getChildNodes(node, nodes); |
75 toContainerNode(node)->removeChildren(); | 75 toContainerNode(node).removeChildren(); |
76 } | 76 } |
77 | 77 |
78 void ContainerNode::removeDetachedChildren() | 78 void ContainerNode::removeDetachedChildren() |
79 { | 79 { |
80 if (connectedSubframeCount()) { | 80 if (connectedSubframeCount()) { |
81 for (Node* child = firstChild(); child; child = child->nextSibling()) | 81 for (Node* child = firstChild(); child; child = child->nextSibling()) |
82 child->updateAncestorConnectedSubframeCountForRemoval(); | 82 child->updateAncestorConnectedSubframeCountForRemoval(); |
83 } | 83 } |
84 // FIXME: We should be able to ASSERT(!confusingAndOftenMisusedAttached()) h
ere: https://bugs.webkit.org/show_bug.cgi?id=107801 | 84 // FIXME: We should be able to ASSERT(!confusingAndOftenMisusedAttached()) h
ere: https://bugs.webkit.org/show_bug.cgi?id=107801 |
85 removeDetachedChildrenInContainer<Node, ContainerNode>(*this); | 85 removeDetachedChildrenInContainer<Node, ContainerNode>(*this); |
86 } | 86 } |
87 | 87 |
88 void ContainerNode::parserTakeAllChildrenFrom(ContainerNode* oldParent) | 88 void ContainerNode::parserTakeAllChildrenFrom(ContainerNode& oldParent) |
89 { | 89 { |
90 while (RefPtr<Node> child = oldParent->firstChild()) { | 90 while (RefPtr<Node> child = oldParent.firstChild()) { |
91 oldParent->parserRemoveChild(*child); | 91 oldParent.parserRemoveChild(*child); |
92 treeScope().adoptIfNeeded(*child); | 92 treeScope().adoptIfNeeded(*child); |
93 parserAppendChild(child.get()); | 93 parserAppendChild(child.get()); |
94 } | 94 } |
95 } | 95 } |
96 | 96 |
97 ContainerNode::~ContainerNode() | 97 ContainerNode::~ContainerNode() |
98 { | 98 { |
99 willBeDeletedFromDocument(); | 99 willBeDeletedFromDocument(); |
100 removeDetachedChildren(); | 100 removeDetachedChildren(); |
101 } | 101 } |
102 | 102 |
103 static inline bool isChildTypeAllowed(ContainerNode* newParent, Node* child) | 103 static inline bool isChildTypeAllowed(ContainerNode& newParent, Node& child) |
104 { | 104 { |
105 if (!child->isDocumentFragment()) | 105 if (!child.isDocumentFragment()) |
106 return newParent->childTypeAllowed(child->nodeType()); | 106 return newParent.childTypeAllowed(child.nodeType()); |
107 | 107 |
108 for (Node* node = child->firstChild(); node; node = node->nextSibling()) { | 108 for (Node* node = child.firstChild(); node; node = node->nextSibling()) { |
109 if (!newParent->childTypeAllowed(node->nodeType())) | 109 if (!newParent.childTypeAllowed(node->nodeType())) |
110 return false; | 110 return false; |
111 } | 111 } |
112 return true; | 112 return true; |
113 } | 113 } |
114 | 114 |
115 static inline bool isInTemplateContent(const Node* node) | 115 static inline bool isInTemplateContent(const Node& node) |
116 { | 116 { |
117 Document& document = node->document(); | 117 const Document& document = node.document(); |
118 return document == document.templateDocument(); | 118 return document == document.templateDocument(); |
119 } | 119 } |
120 | 120 |
121 static inline bool containsConsideringHostElements(const Node* newChild, const N
ode* newParent) | 121 static inline bool containsConsideringHostElements(const Node& newChild, const N
ode& newParent) |
122 { | 122 { |
123 return (newParent->isInShadowTree() || isInTemplateContent(newParent)) | 123 return (newParent.isInShadowTree() || isInTemplateContent(newParent)) |
124 ? newChild->containsIncludingHostElements(newParent) | 124 ? newChild.containsIncludingHostElements(newParent) |
125 : newChild->contains(newParent); | 125 : newChild.contains(&newParent); |
126 } | 126 } |
127 | 127 |
128 static inline bool checkAcceptChild(ContainerNode* newParent, Node* newChild, No
de* oldChild, const char* method, ExceptionState& es) | 128 static inline bool checkAcceptChild(ContainerNode& newParent, Node* newChild, No
de* oldChild, const char* method, ExceptionState& es) |
129 { | 129 { |
130 // Not mentioned in spec: throw NotFoundError if newChild is null | 130 // Not mentioned in spec: throw NotFoundError if newChild is null |
131 if (!newChild) { | 131 if (!newChild) { |
132 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute(m
ethod, "Node", "The new child element is null.")); | 132 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute(m
ethod, "Node", "The new child element is null.")); |
133 return false; | 133 return false; |
134 } | 134 } |
135 | 135 |
136 // Use common case fast path if possible. | 136 // Use common case fast path if possible. |
137 if ((newChild->isElementNode() || newChild->isTextNode()) && newParent->isEl
ementNode()) { | 137 if ((newChild->isElementNode() || newChild->isTextNode()) && newParent.isEle
mentNode()) { |
138 ASSERT(!newParent->isDocumentTypeNode()); | 138 ASSERT(!newParent.isDocumentTypeNode()); |
139 ASSERT(isChildTypeAllowed(newParent, newChild)); | 139 ASSERT(isChildTypeAllowed(newParent, *newChild)); |
140 if (containsConsideringHostElements(newChild, newParent)) { | 140 if (containsConsideringHostElements(*newChild, newParent)) { |
141 es.throwDOMException(HierarchyRequestError, ExceptionMessages::faile
dToExecute(method, "Node", "The new child element contains the parent.")); | 141 es.throwDOMException(HierarchyRequestError, ExceptionMessages::faile
dToExecute(method, "Node", "The new child element contains the parent.")); |
142 return false; | 142 return false; |
143 } | 143 } |
144 return true; | 144 return true; |
145 } | 145 } |
146 | 146 |
147 // This should never happen, but also protect release builds from tree corru
ption. | 147 // This should never happen, but also protect release builds from tree corru
ption. |
148 ASSERT(!newChild->isPseudoElement()); | 148 ASSERT(!newChild->isPseudoElement()); |
149 if (newChild->isPseudoElement()) { | 149 if (newChild->isPseudoElement()) { |
150 es.throwDOMException(HierarchyRequestError, ExceptionMessages::failedToE
xecute(method, "Node", "The new child element is a pseudo-element.")); | 150 es.throwDOMException(HierarchyRequestError, ExceptionMessages::failedToE
xecute(method, "Node", "The new child element is a pseudo-element.")); |
151 return false; | 151 return false; |
152 } | 152 } |
153 | 153 |
154 if (containsConsideringHostElements(newChild, newParent)) { | 154 if (containsConsideringHostElements(*newChild, newParent)) { |
155 es.throwDOMException(HierarchyRequestError, ExceptionMessages::failedToE
xecute(method, "Node", "The new child element contains the parent.")); | 155 es.throwDOMException(HierarchyRequestError, ExceptionMessages::failedToE
xecute(method, "Node", "The new child element contains the parent.")); |
156 return false; | 156 return false; |
157 } | 157 } |
158 | 158 |
159 if (oldChild && newParent->isDocumentNode()) { | 159 if (oldChild && newParent.isDocumentNode()) { |
160 if (!toDocument(newParent)->canReplaceChild(newChild, oldChild)) { | 160 if (!toDocument(newParent).canReplaceChild(*newChild, *oldChild)) { |
161 // FIXME: Adjust 'Document::canReplaceChild' to return some addition
al detail (or an error message). | 161 // FIXME: Adjust 'Document::canReplaceChild' to return some addition
al detail (or an error message). |
162 es.throwDOMException(HierarchyRequestError, ExceptionMessages::faile
dToExecute(method, "ContainerNode")); | 162 es.throwDOMException(HierarchyRequestError, ExceptionMessages::faile
dToExecute(method, "ContainerNode")); |
163 return false; | 163 return false; |
164 } | 164 } |
165 } else if (!isChildTypeAllowed(newParent, newChild)) { | 165 } else if (!isChildTypeAllowed(newParent, *newChild)) { |
166 es.throwDOMException(HierarchyRequestError, ExceptionMessages::failedToE
xecute(method, "Node", "Nodes of type '" + newChild->nodeName() + "' may not be
inserted inside nodes of type '" + newParent->nodeName() + "'.")); | 166 es.throwDOMException(HierarchyRequestError, ExceptionMessages::failedToE
xecute(method, "Node", "Nodes of type '" + newChild->nodeName() + "' may not be
inserted inside nodes of type '" + newParent.nodeName() + "'.")); |
167 return false; | 167 return false; |
168 } | 168 } |
169 | 169 |
170 return true; | 170 return true; |
171 } | 171 } |
172 | 172 |
173 static inline bool checkAcceptChildGuaranteedNodeTypes(ContainerNode* newParent,
Node* newChild, const char* method, ExceptionState& es) | 173 static inline bool checkAcceptChildGuaranteedNodeTypes(ContainerNode& newParent,
Node& newChild, const char* method, ExceptionState& es) |
174 { | 174 { |
175 ASSERT(!newParent->isDocumentTypeNode()); | 175 ASSERT(!newParent.isDocumentTypeNode()); |
176 ASSERT(isChildTypeAllowed(newParent, newChild)); | 176 ASSERT(isChildTypeAllowed(newParent, newChild)); |
177 if (newChild->contains(newParent)) { | 177 if (newChild.contains(&newParent)) { |
178 es.throwDOMException(HierarchyRequestError, ExceptionMessages::failedToE
xecute(method, "Node", "The new child element contains the parent.")); | 178 es.throwDOMException(HierarchyRequestError, ExceptionMessages::failedToE
xecute(method, "Node", "The new child element contains the parent.")); |
179 return false; | 179 return false; |
180 } | 180 } |
181 | 181 |
182 return true; | 182 return true; |
183 } | 183 } |
184 | 184 |
185 static inline bool checkAddChild(ContainerNode* newParent, Node* newChild, const
char* method, ExceptionState& es) | 185 static inline bool checkAddChild(ContainerNode& newParent, Node* newChild, const
char* method, ExceptionState& es) |
186 { | 186 { |
187 return checkAcceptChild(newParent, newChild, 0, method, es); | 187 return checkAcceptChild(newParent, newChild, 0, method, es); |
188 } | 188 } |
189 | 189 |
190 static inline bool checkReplaceChild(ContainerNode* newParent, Node* newChild, N
ode* oldChild, const char* method, ExceptionState& es) | 190 static inline bool checkReplaceChild(ContainerNode& newParent, Node* newChild, N
ode& oldChild, const char* method, ExceptionState& es) |
191 { | 191 { |
192 return checkAcceptChild(newParent, newChild, oldChild, method, es); | 192 return checkAcceptChild(newParent, newChild, &oldChild, method, es); |
193 } | 193 } |
194 | 194 |
195 void ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
ptionState& es) | 195 void ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
ptionState& es) |
196 { | 196 { |
197 // Check that this node is not "floating". | 197 // Check that this node is not "floating". |
198 // If it is, it can be deleted as a side effect of sending mutation events. | 198 // If it is, it can be deleted as a side effect of sending mutation events. |
199 ASSERT(refCount() || parentOrShadowHostNode()); | 199 ASSERT(refCount() || parentOrShadowHostNode()); |
200 | 200 |
201 RefPtr<Node> protect(this); | 201 RefPtr<Node> protect(this); |
202 | 202 |
203 // insertBefore(node, 0) is equivalent to appendChild(node) | 203 // insertBefore(node, 0) is equivalent to appendChild(node) |
204 if (!refChild) { | 204 if (!refChild) { |
205 appendChild(newChild, es); | 205 appendChild(newChild, es); |
206 return; | 206 return; |
207 } | 207 } |
208 | 208 |
209 // Make sure adding the new child is OK. | 209 // Make sure adding the new child is OK. |
210 if (!checkAddChild(this, newChild.get(), insertBeforeMethodName, es)) | 210 if (!checkAddChild(*this, newChild.get(), insertBeforeMethodName, es)) |
211 return; | 211 return; |
| 212 ASSERT(newChild); |
212 | 213 |
213 // NotFoundError: Raised if refChild is not a child of this node | 214 // NotFoundError: Raised if refChild is not a child of this node |
214 if (refChild->parentNode() != this) { | 215 if (refChild->parentNode() != this) { |
215 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute(i
nsertBeforeMethodName, "Node", "The node before which the new node is to be inse
rted is not a child of this node.")); | 216 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute(i
nsertBeforeMethodName, "Node", "The node before which the new node is to be inse
rted is not a child of this node.")); |
216 return; | 217 return; |
217 } | 218 } |
218 | 219 |
219 if (refChild->previousSibling() == newChild || refChild == newChild) // noth
ing to do | 220 if (refChild->previousSibling() == newChild || refChild == newChild) // noth
ing to do |
220 return; | 221 return; |
221 | 222 |
222 RefPtr<Node> next = refChild; | 223 RefPtr<Node> next = refChild; |
223 | 224 |
224 NodeVector targets; | 225 NodeVector targets; |
225 collectChildrenAndRemoveFromOldParent(newChild.get(), targets, es); | 226 collectChildrenAndRemoveFromOldParent(*newChild, targets, es); |
226 if (es.hadException()) | 227 if (es.hadException()) |
227 return; | 228 return; |
228 if (targets.isEmpty()) | 229 if (targets.isEmpty()) |
229 return; | 230 return; |
230 | 231 |
231 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 232 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
232 if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), insertBeforeM
ethodName, es)) | 233 if (!checkAcceptChildGuaranteedNodeTypes(*this, *newChild, insertBeforeMetho
dName, es)) |
233 return; | 234 return; |
234 | 235 |
235 InspectorInstrumentation::willInsertDOMNode(this); | 236 InspectorInstrumentation::willInsertDOMNode(this); |
236 | 237 |
237 ChildListMutationScope mutation(*this); | 238 ChildListMutationScope mutation(*this); |
238 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { | 239 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { |
239 ASSERT(*it); | 240 ASSERT(*it); |
240 Node& child = **it; | 241 Node& child = **it; |
241 | 242 |
242 // Due to arbitrary code running in response to a DOM mutation event it'
s | 243 // Due to arbitrary code running in response to a DOM mutation event it'
s |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 prev->setNextSibling(&newChild); | 277 prev->setNextSibling(&newChild); |
277 } else { | 278 } else { |
278 ASSERT(m_firstChild == nextChild); | 279 ASSERT(m_firstChild == nextChild); |
279 m_firstChild = &newChild; | 280 m_firstChild = &newChild; |
280 } | 281 } |
281 newChild.setParentOrShadowHostNode(this); | 282 newChild.setParentOrShadowHostNode(this); |
282 newChild.setPreviousSibling(prev); | 283 newChild.setPreviousSibling(prev); |
283 newChild.setNextSibling(&nextChild); | 284 newChild.setNextSibling(&nextChild); |
284 } | 285 } |
285 | 286 |
286 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChil
d) | 287 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node& nextChil
d) |
287 { | 288 { |
288 ASSERT(newChild); | 289 ASSERT(newChild); |
289 ASSERT(nextChild); | 290 ASSERT(nextChild.parentNode() == this); |
290 ASSERT(nextChild->parentNode() == this); | |
291 ASSERT(!newChild->isDocumentFragment()); | 291 ASSERT(!newChild->isDocumentFragment()); |
292 ASSERT(!hasTagName(HTMLNames::templateTag)); | 292 ASSERT(!hasTagName(HTMLNames::templateTag)); |
293 | 293 |
294 if (nextChild->previousSibling() == newChild || nextChild == newChild) // no
thing to do | 294 if (nextChild.previousSibling() == newChild || nextChild == newChild) // not
hing to do |
295 return; | 295 return; |
296 | 296 |
297 if (document() != newChild->document()) | 297 if (document() != newChild->document()) |
298 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); | 298 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
299 | 299 |
300 insertBeforeCommon(*nextChild, *newChild); | 300 insertBeforeCommon(nextChild, *newChild); |
301 | 301 |
302 newChild->updateAncestorConnectedSubframeCountForInsertion(); | 302 newChild->updateAncestorConnectedSubframeCountForInsertion(); |
303 | 303 |
304 ChildListMutationScope(*this).childAdded(*newChild); | 304 ChildListMutationScope(*this).childAdded(*newChild); |
305 | 305 |
306 childrenChanged(true, newChild->previousSibling(), nextChild, 1); | 306 childrenChanged(true, newChild->previousSibling(), &nextChild, 1); |
307 | 307 |
308 ChildNodeInsertionNotifier(*this).notify(*newChild); | 308 ChildNodeInsertionNotifier(*this).notify(*newChild); |
309 } | 309 } |
310 | 310 |
311 void ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce
ptionState& es) | 311 void ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce
ptionState& es) |
312 { | 312 { |
313 // Check that this node is not "floating". | 313 // Check that this node is not "floating". |
314 // If it is, it can be deleted as a side effect of sending mutation events. | 314 // If it is, it can be deleted as a side effect of sending mutation events. |
315 ASSERT(refCount() || parentOrShadowHostNode()); | 315 ASSERT(refCount() || parentOrShadowHostNode()); |
316 | 316 |
317 RefPtr<Node> protect(this); | 317 RefPtr<Node> protect(this); |
318 | 318 |
319 if (oldChild == newChild) // nothing to do | 319 if (oldChild == newChild) // nothing to do |
320 return; | 320 return; |
321 | 321 |
322 if (!oldChild) { | 322 if (!oldChild) { |
323 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute(r
eplaceChildMethodName, "Node", "The node to be replaced is null.")); | 323 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute(r
eplaceChildMethodName, "Node", "The node to be replaced is null.")); |
324 return; | 324 return; |
325 } | 325 } |
326 | 326 |
327 // Make sure replacing the old child with the new is ok | 327 // Make sure replacing the old child with the new is ok |
328 if (!checkReplaceChild(this, newChild.get(), oldChild, replaceChildMethodNam
e, es)) | 328 if (!checkReplaceChild(*this, newChild.get(), *oldChild, replaceChildMethodN
ame, es)) |
329 return; | 329 return; |
330 | 330 |
331 // NotFoundError: Raised if oldChild is not a child of this node. | 331 // NotFoundError: Raised if oldChild is not a child of this node. |
332 if (oldChild->parentNode() != this) { | 332 if (oldChild->parentNode() != this) { |
333 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute(r
eplaceChildMethodName, "Node", "The node to be replaced is not a child of this n
ode.")); | 333 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute(r
eplaceChildMethodName, "Node", "The node to be replaced is not a child of this n
ode.")); |
334 return; | 334 return; |
335 } | 335 } |
336 | 336 |
337 ChildListMutationScope mutation(*this); | 337 ChildListMutationScope mutation(*this); |
338 | 338 |
339 RefPtr<Node> next = oldChild->nextSibling(); | 339 RefPtr<Node> next = oldChild->nextSibling(); |
340 | 340 |
341 // Remove the node we're replacing | 341 // Remove the node we're replacing |
342 RefPtr<Node> removedChild = oldChild; | 342 RefPtr<Node> removedChild = oldChild; |
343 removeChild(oldChild, es); | 343 removeChild(oldChild, es); |
344 if (es.hadException()) | 344 if (es.hadException()) |
345 return; | 345 return; |
346 | 346 |
347 if (next && (next->previousSibling() == newChild || next == newChild)) // no
thing to do | 347 if (next && (next->previousSibling() == newChild || next == newChild)) // no
thing to do |
348 return; | 348 return; |
349 | 349 |
350 // Does this one more time because removeChild() fires a MutationEvent. | 350 // Does this one more time because removeChild() fires a MutationEvent. |
351 if (!checkReplaceChild(this, newChild.get(), oldChild, replaceChildMethodNam
e, es)) | 351 if (!checkReplaceChild(*this, newChild.get(), *oldChild, replaceChildMethodN
ame, es)) |
352 return; | 352 return; |
353 | 353 |
354 NodeVector targets; | 354 NodeVector targets; |
355 collectChildrenAndRemoveFromOldParent(newChild.get(), targets, es); | 355 collectChildrenAndRemoveFromOldParent(*newChild, targets, es); |
356 if (es.hadException()) | 356 if (es.hadException()) |
357 return; | 357 return; |
358 | 358 |
359 // Does this yet another check because collectChildrenAndRemoveFromOldParent
() fires a MutationEvent. | 359 // Does this yet another check because collectChildrenAndRemoveFromOldParent
() fires a MutationEvent. |
360 if (!checkReplaceChild(this, newChild.get(), oldChild, replaceChildMethodNam
e, es)) | 360 if (!checkReplaceChild(*this, newChild.get(), *oldChild, replaceChildMethodN
ame, es)) |
361 return; | 361 return; |
362 | 362 |
363 InspectorInstrumentation::willInsertDOMNode(this); | 363 InspectorInstrumentation::willInsertDOMNode(this); |
364 | 364 |
365 // Add the new child(ren) | 365 // Add the new child(ren) |
366 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { | 366 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { |
367 ASSERT(*it); | 367 ASSERT(*it); |
368 Node& child = **it; | 368 Node& child = **it; |
369 | 369 |
370 // Due to arbitrary code running in response to a DOM mutation event it'
s | 370 // Due to arbitrary code running in response to a DOM mutation event it'
s |
(...skipping 28 matching lines...) Expand all Loading... |
399 ChildListMutationScope(*child.parentNode()).willRemoveChild(child); | 399 ChildListMutationScope(*child.parentNode()).willRemoveChild(child); |
400 child.notifyMutationObserversNodeWillDetach(); | 400 child.notifyMutationObserversNodeWillDetach(); |
401 dispatchChildRemovalEvents(child); | 401 dispatchChildRemovalEvents(child); |
402 child.document().nodeWillBeRemoved(child); // e.g. mutation event listener c
an create a new range. | 402 child.document().nodeWillBeRemoved(child); // e.g. mutation event listener c
an create a new range. |
403 ChildFrameDisconnector(child).disconnect(); | 403 ChildFrameDisconnector(child).disconnect(); |
404 } | 404 } |
405 | 405 |
406 static void willRemoveChildren(ContainerNode& container) | 406 static void willRemoveChildren(ContainerNode& container) |
407 { | 407 { |
408 NodeVector children; | 408 NodeVector children; |
409 getChildNodes(&container, children); | 409 getChildNodes(container, children); |
410 | 410 |
411 ChildListMutationScope mutation(container); | 411 ChildListMutationScope mutation(container); |
412 for (NodeVector::const_iterator it = children.begin(); it != children.end();
it++) { | 412 for (NodeVector::const_iterator it = children.begin(); it != children.end();
it++) { |
413 ASSERT(*it); | 413 ASSERT(*it); |
414 Node& child = **it; | 414 Node& child = **it; |
415 mutation.willRemoveChild(child); | 415 mutation.willRemoveChild(child); |
416 child.notifyMutationObserversNodeWillDetach(); | 416 child.notifyMutationObserversNodeWillDetach(); |
417 | 417 |
418 // fire removed from document mutation events. | 418 // fire removed from document mutation events. |
419 dispatchChildRemovalEvents(child); | 419 dispatchChildRemovalEvents(child); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 | 576 |
577 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& es) | 577 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& es) |
578 { | 578 { |
579 RefPtr<ContainerNode> protect(this); | 579 RefPtr<ContainerNode> protect(this); |
580 | 580 |
581 // Check that this node is not "floating". | 581 // Check that this node is not "floating". |
582 // If it is, it can be deleted as a side effect of sending mutation events. | 582 // If it is, it can be deleted as a side effect of sending mutation events. |
583 ASSERT(refCount() || parentOrShadowHostNode()); | 583 ASSERT(refCount() || parentOrShadowHostNode()); |
584 | 584 |
585 // Make sure adding the new child is ok | 585 // Make sure adding the new child is ok |
586 if (!checkAddChild(this, newChild.get(), appendChildMethodName, es)) | 586 if (!checkAddChild(*this, newChild.get(), appendChildMethodName, es)) |
587 return; | 587 return; |
| 588 ASSERT(newChild); |
588 | 589 |
589 if (newChild == m_lastChild) // nothing to do | 590 if (newChild == m_lastChild) // nothing to do |
590 return; | 591 return; |
591 | 592 |
592 NodeVector targets; | 593 NodeVector targets; |
593 collectChildrenAndRemoveFromOldParent(newChild.get(), targets, es); | 594 collectChildrenAndRemoveFromOldParent(*newChild, targets, es); |
594 if (es.hadException()) | 595 if (es.hadException()) |
595 return; | 596 return; |
596 | 597 |
597 if (targets.isEmpty()) | 598 if (targets.isEmpty()) |
598 return; | 599 return; |
599 | 600 |
600 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 601 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
601 if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), appendChildMe
thodName, es)) | 602 if (!checkAcceptChildGuaranteedNodeTypes(*this, *newChild, appendChildMethod
Name, es)) |
602 return; | 603 return; |
603 | 604 |
604 InspectorInstrumentation::willInsertDOMNode(this); | 605 InspectorInstrumentation::willInsertDOMNode(this); |
605 | 606 |
606 // Now actually add the child(ren) | 607 // Now actually add the child(ren) |
607 ChildListMutationScope mutation(*this); | 608 ChildListMutationScope mutation(*this); |
608 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { | 609 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { |
609 ASSERT(*it); | 610 ASSERT(*it); |
610 Node& child = **it; | 611 Node& child = **it; |
611 | 612 |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 return true; | 992 return true; |
992 | 993 |
993 if (node->isElementNode() && toElement(node)->shadow()) | 994 if (node->isElementNode() && toElement(node)->shadow()) |
994 return true; | 995 return true; |
995 | 996 |
996 return false; | 997 return false; |
997 } | 998 } |
998 #endif | 999 #endif |
999 | 1000 |
1000 } // namespace WebCore | 1001 } // namespace WebCore |
OLD | NEW |