| 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 |