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. |
11 * | 11 * |
12 * This library is distributed in the hope that it will be useful, | 12 * This library is distributed in the hope that it will be useful, |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Library General Public License for more details. | 15 * Library General Public License for more details. |
16 * | 16 * |
17 * You should have received a copy of the GNU Library General Public License | 17 * You should have received a copy of the GNU Library General Public License |
18 * along with this library; see the file COPYING.LIB. If not, write to | 18 * along with this library; see the file COPYING.LIB. If not, write to |
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 * Boston, MA 02110-1301, USA. | 20 * Boston, MA 02110-1301, USA. |
21 */ | 21 */ |
22 | 22 |
23 #include "config.h" | 23 #include "config.h" |
24 #include "core/dom/ContainerNode.h" | 24 #include "core/dom/ContainerNode.h" |
25 | 25 |
26 #include "bindings/v8/ExceptionMessages.h" | |
27 #include "bindings/v8/ExceptionState.h" | 26 #include "bindings/v8/ExceptionState.h" |
28 #include "core/dom/ChildListMutationScope.h" | 27 #include "core/dom/ChildListMutationScope.h" |
29 #include "core/dom/ContainerNodeAlgorithms.h" | 28 #include "core/dom/ContainerNodeAlgorithms.h" |
30 #include "core/dom/ElementTraversal.h" | 29 #include "core/dom/ElementTraversal.h" |
31 #include "core/dom/ExceptionCode.h" | 30 #include "core/dom/ExceptionCode.h" |
32 #include "core/dom/FullscreenElementStack.h" | 31 #include "core/dom/FullscreenElementStack.h" |
33 #include "core/dom/NodeChildRemovalTracker.h" | 32 #include "core/dom/NodeChildRemovalTracker.h" |
34 #include "core/dom/NodeRareData.h" | 33 #include "core/dom/NodeRareData.h" |
35 #include "core/dom/NodeRenderStyle.h" | 34 #include "core/dom/NodeRenderStyle.h" |
36 #include "core/dom/NodeTraversal.h" | 35 #include "core/dom/NodeTraversal.h" |
(...skipping 12 matching lines...) Expand all Loading... |
49 | 48 |
50 static void dispatchChildInsertionEvents(Node&); | 49 static void dispatchChildInsertionEvents(Node&); |
51 static void dispatchChildRemovalEvents(Node&); | 50 static void dispatchChildRemovalEvents(Node&); |
52 | 51 |
53 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0; | 52 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0; |
54 | 53 |
55 #ifndef NDEBUG | 54 #ifndef NDEBUG |
56 unsigned NoEventDispatchAssertion::s_count = 0; | 55 unsigned NoEventDispatchAssertion::s_count = 0; |
57 #endif | 56 #endif |
58 | 57 |
59 static const char appendChildMethodName[] = "appendChild"; | |
60 static const char insertBeforeMethodName[] = "insertBefore"; | |
61 static const char replaceChildMethodName[] = "replaceChild"; | |
62 | |
63 static void collectChildrenAndRemoveFromOldParent(Node& node, NodeVector& nodes,
ExceptionState& exceptionState) | 58 static void collectChildrenAndRemoveFromOldParent(Node& node, NodeVector& nodes,
ExceptionState& exceptionState) |
64 { | 59 { |
65 if (!node.isDocumentFragment()) { | 60 if (!node.isDocumentFragment()) { |
66 nodes.append(&node); | 61 nodes.append(&node); |
67 if (ContainerNode* oldParent = node.parentNode()) | 62 if (ContainerNode* oldParent = node.parentNode()) |
68 oldParent->removeChild(&node, exceptionState); | 63 oldParent->removeChild(&node, exceptionState); |
69 return; | 64 return; |
70 } | 65 } |
71 getChildNodes(node, nodes); | 66 getChildNodes(node, nodes); |
72 toContainerNode(node).removeChildren(); | 67 toContainerNode(node).removeChildren(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 return true; | 104 return true; |
110 } | 105 } |
111 | 106 |
112 bool ContainerNode::containsConsideringHostElements(const Node& newChild) const | 107 bool ContainerNode::containsConsideringHostElements(const Node& newChild) const |
113 { | 108 { |
114 if (isInShadowTree() || document() == document().templateDocument()) | 109 if (isInShadowTree() || document() == document().templateDocument()) |
115 return newChild.containsIncludingHostElements(*this); | 110 return newChild.containsIncludingHostElements(*this); |
116 return newChild.contains(this); | 111 return newChild.contains(this); |
117 } | 112 } |
118 | 113 |
119 bool ContainerNode::checkAcceptChild(const Node* newChild, const Node* oldChild,
const char* method, ExceptionState& exceptionState) const | 114 bool ContainerNode::checkAcceptChild(const Node* newChild, const Node* oldChild,
ExceptionState& exceptionState) const |
120 { | 115 { |
121 // Not mentioned in spec: throw NotFoundError if newChild is null | 116 // Not mentioned in spec: throw NotFoundError if newChild is null |
122 if (!newChild) { | 117 if (!newChild) { |
123 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute(method, "Node", "The new child element is null.")); | 118 exceptionState.throwDOMException(NotFoundError, "The new child element i
s null."); |
124 return false; | 119 return false; |
125 } | 120 } |
126 | 121 |
127 // Use common case fast path if possible. | 122 // Use common case fast path if possible. |
128 if ((newChild->isElementNode() || newChild->isTextNode()) && isElementNode()
) { | 123 if ((newChild->isElementNode() || newChild->isTextNode()) && isElementNode()
) { |
129 ASSERT(isChildTypeAllowed(*newChild)); | 124 ASSERT(isChildTypeAllowed(*newChild)); |
130 if (containsConsideringHostElements(*newChild)) { | 125 if (containsConsideringHostElements(*newChild)) { |
131 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMes
sages::failedToExecute(method, "Node", "The new child element contains the paren
t.")); | 126 exceptionState.throwDOMException(HierarchyRequestError, "The new chi
ld element contains the parent."); |
132 return false; | 127 return false; |
133 } | 128 } |
134 return true; | 129 return true; |
135 } | 130 } |
136 | 131 |
137 // This should never happen, but also protect release builds from tree corru
ption. | 132 // This should never happen, but also protect release builds from tree corru
ption. |
138 ASSERT(!newChild->isPseudoElement()); | 133 ASSERT(!newChild->isPseudoElement()); |
139 if (newChild->isPseudoElement()) { | 134 if (newChild->isPseudoElement()) { |
140 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessage
s::failedToExecute(method, "Node", "The new child element is a pseudo-element.")
); | 135 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement is a pseudo-element."); |
141 return false; | 136 return false; |
142 } | 137 } |
143 | 138 |
144 if (containsConsideringHostElements(*newChild)) { | 139 if (containsConsideringHostElements(*newChild)) { |
145 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessage
s::failedToExecute(method, "Node", "The new child element contains the parent.")
); | 140 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement contains the parent."); |
146 return false; | 141 return false; |
147 } | 142 } |
148 | 143 |
149 if (oldChild && isDocumentNode()) { | 144 if (oldChild && isDocumentNode()) { |
150 if (!toDocument(this)->canReplaceChild(*newChild, *oldChild)) { | 145 if (!toDocument(this)->canReplaceChild(*newChild, *oldChild)) { |
151 // FIXME: Adjust 'Document::canReplaceChild' to return some addition
al detail (or an error message). | 146 // FIXME: Adjust 'Document::canReplaceChild' to return some addition
al detail (or an error message). |
152 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMes
sages::failedToExecute(method, "ContainerNode")); | 147 exceptionState.throwDOMException(HierarchyRequestError, "Failed to r
eplace child."); |
153 return false; | 148 return false; |
154 } | 149 } |
155 } else if (!isChildTypeAllowed(*newChild)) { | 150 } else if (!isChildTypeAllowed(*newChild)) { |
156 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessage
s::failedToExecute(method, "Node", "Nodes of type '" + newChild->nodeName() + "'
may not be inserted inside nodes of type '" + nodeName() + "'.")); | 151 exceptionState.throwDOMException(HierarchyRequestError, "Nodes of type '
" + newChild->nodeName() + "' may not be inserted inside nodes of type '" + node
Name() + "'."); |
157 return false; | 152 return false; |
158 } | 153 } |
159 | 154 |
160 return true; | 155 return true; |
161 } | 156 } |
162 | 157 |
163 bool ContainerNode::checkAcceptChildGuaranteedNodeTypes(const Node& newChild, co
nst char* method, ExceptionState& exceptionState) const | 158 bool ContainerNode::checkAcceptChildGuaranteedNodeTypes(const Node& newChild, Ex
ceptionState& exceptionState) const |
164 { | 159 { |
165 ASSERT(isChildTypeAllowed(newChild)); | 160 ASSERT(isChildTypeAllowed(newChild)); |
166 if (newChild.contains(this)) { | 161 if (newChild.contains(this)) { |
167 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessage
s::failedToExecute(method, "Node", "The new child element contains the parent.")
); | 162 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement contains the parent."); |
168 return false; | 163 return false; |
169 } | 164 } |
170 return true; | 165 return true; |
171 } | 166 } |
172 | 167 |
173 void ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
ptionState& exceptionState) | 168 void ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
ptionState& exceptionState) |
174 { | 169 { |
175 // Check that this node is not "floating". | 170 // Check that this node is not "floating". |
176 // If it is, it can be deleted as a side effect of sending mutation events. | 171 // If it is, it can be deleted as a side effect of sending mutation events. |
177 ASSERT(refCount() || parentOrShadowHostNode()); | 172 ASSERT(refCount() || parentOrShadowHostNode()); |
178 | 173 |
179 RefPtr<Node> protect(this); | 174 RefPtr<Node> protect(this); |
180 | 175 |
181 // insertBefore(node, 0) is equivalent to appendChild(node) | 176 // insertBefore(node, 0) is equivalent to appendChild(node) |
182 if (!refChild) { | 177 if (!refChild) { |
183 appendChild(newChild, exceptionState); | 178 appendChild(newChild, exceptionState); |
184 return; | 179 return; |
185 } | 180 } |
186 | 181 |
187 // Make sure adding the new child is OK. | 182 // Make sure adding the new child is OK. |
188 if (!checkAcceptChild(newChild.get(), 0, insertBeforeMethodName, exceptionSt
ate)) | 183 if (!checkAcceptChild(newChild.get(), 0, exceptionState)) |
189 return; | 184 return; |
190 ASSERT(newChild); | 185 ASSERT(newChild); |
191 | 186 |
192 // NotFoundError: Raised if refChild is not a child of this node | 187 // NotFoundError: Raised if refChild is not a child of this node |
193 if (refChild->parentNode() != this) { | 188 if (refChild->parentNode() != this) { |
194 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute(insertBeforeMethodName, "Node", "The node before which the new node i
s to be inserted is not a child of this node.")); | 189 exceptionState.throwDOMException(NotFoundError, "The node before which t
he new node is to be inserted is not a child of this node."); |
195 return; | 190 return; |
196 } | 191 } |
197 | 192 |
198 if (refChild->previousSibling() == newChild || refChild == newChild) // noth
ing to do | 193 if (refChild->previousSibling() == newChild || refChild == newChild) // noth
ing to do |
199 return; | 194 return; |
200 | 195 |
201 RefPtr<Node> next = refChild; | 196 RefPtr<Node> next = refChild; |
202 | 197 |
203 NodeVector targets; | 198 NodeVector targets; |
204 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); | 199 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); |
205 if (exceptionState.hadException()) | 200 if (exceptionState.hadException()) |
206 return; | 201 return; |
207 if (targets.isEmpty()) | 202 if (targets.isEmpty()) |
208 return; | 203 return; |
209 | 204 |
210 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 205 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
211 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, insertBeforeMethodName,
exceptionState)) | 206 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, exceptionState)) |
212 return; | 207 return; |
213 | 208 |
214 InspectorInstrumentation::willInsertDOMNode(this); | 209 InspectorInstrumentation::willInsertDOMNode(this); |
215 | 210 |
216 ChildListMutationScope mutation(*this); | 211 ChildListMutationScope mutation(*this); |
217 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { | 212 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { |
218 ASSERT(*it); | 213 ASSERT(*it); |
219 Node& child = **it; | 214 Node& child = **it; |
220 | 215 |
221 // Due to arbitrary code running in response to a DOM mutation event it'
s | 216 // Due to arbitrary code running in response to a DOM mutation event it'
s |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 // Check that this node is not "floating". | 286 // Check that this node is not "floating". |
292 // If it is, it can be deleted as a side effect of sending mutation events. | 287 // If it is, it can be deleted as a side effect of sending mutation events. |
293 ASSERT(refCount() || parentOrShadowHostNode()); | 288 ASSERT(refCount() || parentOrShadowHostNode()); |
294 | 289 |
295 RefPtr<Node> protect(this); | 290 RefPtr<Node> protect(this); |
296 | 291 |
297 if (oldChild == newChild) // nothing to do | 292 if (oldChild == newChild) // nothing to do |
298 return; | 293 return; |
299 | 294 |
300 if (!oldChild) { | 295 if (!oldChild) { |
301 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute(replaceChildMethodName, "Node", "The node to be replaced is null.")); | 296 exceptionState.throwDOMException(NotFoundError, "The node to be replaced
is null."); |
302 return; | 297 return; |
303 } | 298 } |
304 | 299 |
305 // Make sure replacing the old child with the new is ok | 300 // Make sure replacing the old child with the new is ok |
306 if (!checkAcceptChild(newChild.get(), oldChild, replaceChildMethodName, exce
ptionState)) | 301 if (!checkAcceptChild(newChild.get(), oldChild, exceptionState)) |
307 return; | 302 return; |
308 | 303 |
309 // NotFoundError: Raised if oldChild is not a child of this node. | 304 // NotFoundError: Raised if oldChild is not a child of this node. |
310 if (oldChild->parentNode() != this) { | 305 if (oldChild->parentNode() != this) { |
311 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute(replaceChildMethodName, "Node", "The node to be replaced is not a chi
ld of this node.")); | 306 exceptionState.throwDOMException(NotFoundError, "The node to be replaced
is not a child of this node."); |
312 return; | 307 return; |
313 } | 308 } |
314 | 309 |
315 ChildListMutationScope mutation(*this); | 310 ChildListMutationScope mutation(*this); |
316 | 311 |
317 RefPtr<Node> next = oldChild->nextSibling(); | 312 RefPtr<Node> next = oldChild->nextSibling(); |
318 | 313 |
319 // Remove the node we're replacing | 314 // Remove the node we're replacing |
320 RefPtr<Node> removedChild = oldChild; | 315 RefPtr<Node> removedChild = oldChild; |
321 removeChild(oldChild, exceptionState); | 316 removeChild(oldChild, exceptionState); |
322 if (exceptionState.hadException()) | 317 if (exceptionState.hadException()) |
323 return; | 318 return; |
324 | 319 |
325 if (next && (next->previousSibling() == newChild || next == newChild)) // no
thing to do | 320 if (next && (next->previousSibling() == newChild || next == newChild)) // no
thing to do |
326 return; | 321 return; |
327 | 322 |
328 // Does this one more time because removeChild() fires a MutationEvent. | 323 // Does this one more time because removeChild() fires a MutationEvent. |
329 if (!checkAcceptChild(newChild.get(), oldChild, replaceChildMethodName, exce
ptionState)) | 324 if (!checkAcceptChild(newChild.get(), oldChild, exceptionState)) |
330 return; | 325 return; |
331 | 326 |
332 NodeVector targets; | 327 NodeVector targets; |
333 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); | 328 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); |
334 if (exceptionState.hadException()) | 329 if (exceptionState.hadException()) |
335 return; | 330 return; |
336 | 331 |
337 // Does this yet another check because collectChildrenAndRemoveFromOldParent
() fires a MutationEvent. | 332 // Does this yet another check because collectChildrenAndRemoveFromOldParent
() fires a MutationEvent. |
338 if (!checkAcceptChild(newChild.get(), oldChild, replaceChildMethodName, exce
ptionState)) | 333 if (!checkAcceptChild(newChild.get(), oldChild, exceptionState)) |
339 return; | 334 return; |
340 | 335 |
341 InspectorInstrumentation::willInsertDOMNode(this); | 336 InspectorInstrumentation::willInsertDOMNode(this); |
342 | 337 |
343 // Add the new child(ren) | 338 // Add the new child(ren) |
344 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { | 339 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { |
345 ASSERT(*it); | 340 ASSERT(*it); |
346 Node& child = **it; | 341 Node& child = **it; |
347 | 342 |
348 // Due to arbitrary code running in response to a DOM mutation event it'
s | 343 // Due to arbitrary code running in response to a DOM mutation event it'
s |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 void ContainerNode::removeChild(Node* oldChild, ExceptionState& exceptionState) | 401 void ContainerNode::removeChild(Node* oldChild, ExceptionState& exceptionState) |
407 { | 402 { |
408 // Check that this node is not "floating". | 403 // Check that this node is not "floating". |
409 // If it is, it can be deleted as a side effect of sending mutation events. | 404 // If it is, it can be deleted as a side effect of sending mutation events. |
410 ASSERT(refCount() || parentOrShadowHostNode()); | 405 ASSERT(refCount() || parentOrShadowHostNode()); |
411 | 406 |
412 RefPtr<Node> protect(this); | 407 RefPtr<Node> protect(this); |
413 | 408 |
414 // NotFoundError: Raised if oldChild is not a child of this node. | 409 // NotFoundError: Raised if oldChild is not a child of this node. |
415 if (!oldChild || oldChild->parentNode() != this) { | 410 if (!oldChild || oldChild->parentNode() != this) { |
416 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute("removeChild", "Node", "The node to be removed is not a child of this
node.")); | 411 exceptionState.throwDOMException(NotFoundError, "The node to be removed
is not a child of this node."); |
417 return; | 412 return; |
418 } | 413 } |
419 | 414 |
420 RefPtr<Node> child = oldChild; | 415 RefPtr<Node> child = oldChild; |
421 | 416 |
422 document().removeFocusedElementOfSubtree(child.get()); | 417 document().removeFocusedElementOfSubtree(child.get()); |
423 | 418 |
424 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExist
s(&document())) | 419 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExist
s(&document())) |
425 fullscreen->removeFullScreenElementOfSubtree(child.get()); | 420 fullscreen->removeFullScreenElementOfSubtree(child.get()); |
426 | 421 |
427 // Events fired when blurring currently focused node might have moved this | 422 // Events fired when blurring currently focused node might have moved this |
428 // child into a different parent. | 423 // child into a different parent. |
429 if (child->parentNode() != this) { | 424 if (child->parentNode() != this) { |
430 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute("removeChild", "Node", "The node to be removed is no longer a child o
f this node. Perhaps it was moved in a 'blur' event handler?")); | 425 exceptionState.throwDOMException(NotFoundError, "The node to be removed
is no longer a child of this node. Perhaps it was moved in a 'blur' event handle
r?"); |
431 return; | 426 return; |
432 } | 427 } |
433 | 428 |
434 willRemoveChild(*child); | 429 willRemoveChild(*child); |
435 | 430 |
436 // Mutation events might have moved this child into a different parent. | 431 // Mutation events might have moved this child into a different parent. |
437 if (child->parentNode() != this) { | 432 if (child->parentNode() != this) { |
438 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute("removeChild", "Node", "The node to be removed is no longer a child o
f this node. Perhaps it was moved in response to a mutation?")); | 433 exceptionState.throwDOMException(NotFoundError, "The node to be removed
is no longer a child of this node. Perhaps it was moved in response to a mutatio
n?"); |
439 return; | 434 return; |
440 } | 435 } |
441 | 436 |
442 { | 437 { |
443 RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates; | 438 RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates; |
444 | 439 |
445 Node* prev = child->previousSibling(); | 440 Node* prev = child->previousSibling(); |
446 Node* next = child->nextSibling(); | 441 Node* next = child->nextSibling(); |
447 removeBetween(prev, next, *child); | 442 removeBetween(prev, next, *child); |
448 childrenChanged(false, prev, next, -1); | 443 childrenChanged(false, prev, next, -1); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 | 546 |
552 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& excep
tionState) | 547 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& excep
tionState) |
553 { | 548 { |
554 RefPtr<ContainerNode> protect(this); | 549 RefPtr<ContainerNode> protect(this); |
555 | 550 |
556 // Check that this node is not "floating". | 551 // Check that this node is not "floating". |
557 // If it is, it can be deleted as a side effect of sending mutation events. | 552 // If it is, it can be deleted as a side effect of sending mutation events. |
558 ASSERT(refCount() || parentOrShadowHostNode()); | 553 ASSERT(refCount() || parentOrShadowHostNode()); |
559 | 554 |
560 // Make sure adding the new child is ok | 555 // Make sure adding the new child is ok |
561 if (!checkAcceptChild(newChild.get(), 0, appendChildMethodName, exceptionSta
te)) | 556 if (!checkAcceptChild(newChild.get(), 0, exceptionState)) |
562 return; | 557 return; |
563 ASSERT(newChild); | 558 ASSERT(newChild); |
564 | 559 |
565 if (newChild == m_lastChild) // nothing to do | 560 if (newChild == m_lastChild) // nothing to do |
566 return; | 561 return; |
567 | 562 |
568 NodeVector targets; | 563 NodeVector targets; |
569 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); | 564 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); |
570 if (exceptionState.hadException()) | 565 if (exceptionState.hadException()) |
571 return; | 566 return; |
572 | 567 |
573 if (targets.isEmpty()) | 568 if (targets.isEmpty()) |
574 return; | 569 return; |
575 | 570 |
576 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 571 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
577 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, appendChildMethodName, e
xceptionState)) | 572 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, exceptionState)) |
578 return; | 573 return; |
579 | 574 |
580 InspectorInstrumentation::willInsertDOMNode(this); | 575 InspectorInstrumentation::willInsertDOMNode(this); |
581 | 576 |
582 // Now actually add the child(ren) | 577 // Now actually add the child(ren) |
583 ChildListMutationScope mutation(*this); | 578 ChildListMutationScope mutation(*this); |
584 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { | 579 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { |
585 ASSERT(*it); | 580 ASSERT(*it); |
586 Node& child = **it; | 581 Node& child = **it; |
587 | 582 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 return true; | 982 return true; |
988 | 983 |
989 if (node->isElementNode() && toElement(node)->shadow()) | 984 if (node->isElementNode() && toElement(node)->shadow()) |
990 return true; | 985 return true; |
991 | 986 |
992 return false; | 987 return false; |
993 } | 988 } |
994 #endif | 989 #endif |
995 | 990 |
996 } // namespace WebCore | 991 } // namespace WebCore |
OLD | NEW |