| 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& exceptionState) |
| 67 { | 67 { |
| 68 if (!node.isDocumentFragment()) { | 68 if (!node.isDocumentFragment()) { |
| 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, exceptionState); |
| 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()) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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& exceptionState) |
| 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 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute(method, "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.isEle
mentNode()) { | 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 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMes
sages::failedToExecute(method, "Node", "The new child element contains the paren
t.")); |
| 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 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessage
s::failedToExecute(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 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessage
s::failedToExecute(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 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMes
sages::failedToExecute(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 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessage
s::failedToExecute(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& exceptionState) |
| 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 exceptionState.throwDOMException(HierarchyRequestError, ExceptionMessage
s::failedToExecute(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& exceptionState) |
| 186 { | 186 { |
| 187 return checkAcceptChild(newParent, newChild, 0, method, es); | 187 return checkAcceptChild(newParent, newChild, 0, method, exceptionState); |
| 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& exceptionState) |
| 191 { | 191 { |
| 192 return checkAcceptChild(newParent, newChild, &oldChild, method, es); | 192 return checkAcceptChild(newParent, newChild, &oldChild, method, exceptionSta
te); |
| 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& exceptionState) |
| 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, exceptionState); |
| 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, exceptionS
tate)) |
| 211 return; | 211 return; |
| 212 ASSERT(newChild); | 212 ASSERT(newChild); |
| 213 | 213 |
| 214 // NotFoundError: Raised if refChild is not a child of this node | 214 // NotFoundError: Raised if refChild is not a child of this node |
| 215 if (refChild->parentNode() != this) { | 215 if (refChild->parentNode() != this) { |
| 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 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.")); |
| 217 return; | 217 return; |
| 218 } | 218 } |
| 219 | 219 |
| 220 if (refChild->previousSibling() == newChild || refChild == newChild) // noth
ing to do | 220 if (refChild->previousSibling() == newChild || refChild == newChild) // noth
ing to do |
| 221 return; | 221 return; |
| 222 | 222 |
| 223 RefPtr<Node> next = refChild; | 223 RefPtr<Node> next = refChild; |
| 224 | 224 |
| 225 NodeVector targets; | 225 NodeVector targets; |
| 226 collectChildrenAndRemoveFromOldParent(*newChild, targets, es); | 226 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); |
| 227 if (es.hadException()) | 227 if (exceptionState.hadException()) |
| 228 return; | 228 return; |
| 229 if (targets.isEmpty()) | 229 if (targets.isEmpty()) |
| 230 return; | 230 return; |
| 231 | 231 |
| 232 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 232 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
| 233 if (!checkAcceptChildGuaranteedNodeTypes(*this, *newChild, insertBeforeMetho
dName, es)) | 233 if (!checkAcceptChildGuaranteedNodeTypes(*this, *newChild, insertBeforeMetho
dName, exceptionState)) |
| 234 return; | 234 return; |
| 235 | 235 |
| 236 InspectorInstrumentation::willInsertDOMNode(this); | 236 InspectorInstrumentation::willInsertDOMNode(this); |
| 237 | 237 |
| 238 ChildListMutationScope mutation(*this); | 238 ChildListMutationScope mutation(*this); |
| 239 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { | 239 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { |
| 240 ASSERT(*it); | 240 ASSERT(*it); |
| 241 Node& child = **it; | 241 Node& child = **it; |
| 242 | 242 |
| 243 // 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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& exceptionState) |
| 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 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute(replaceChildMethodName, "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, replaceChildMethodN
ame, es)) | 328 if (!checkReplaceChild(*this, newChild.get(), *oldChild, replaceChildMethodN
ame, exceptionState)) |
| 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 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute(replaceChildMethodName, "Node", "The node to be replaced is not a chi
ld of this node.")); |
| 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, exceptionState); |
| 344 if (es.hadException()) | 344 if (exceptionState.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, replaceChildMethodN
ame, es)) | 351 if (!checkReplaceChild(*this, newChild.get(), *oldChild, replaceChildMethodN
ame, exceptionState)) |
| 352 return; | 352 return; |
| 353 | 353 |
| 354 NodeVector targets; | 354 NodeVector targets; |
| 355 collectChildrenAndRemoveFromOldParent(*newChild, targets, es); | 355 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); |
| 356 if (es.hadException()) | 356 if (exceptionState.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, replaceChildMethodN
ame, es)) | 360 if (!checkReplaceChild(*this, newChild.get(), *oldChild, replaceChildMethodN
ame, exceptionState)) |
| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 } | 420 } |
| 421 | 421 |
| 422 ChildFrameDisconnector(container).disconnect(ChildFrameDisconnector::Descend
antsOnly); | 422 ChildFrameDisconnector(container).disconnect(ChildFrameDisconnector::Descend
antsOnly); |
| 423 } | 423 } |
| 424 | 424 |
| 425 void ContainerNode::disconnectDescendantFrames() | 425 void ContainerNode::disconnectDescendantFrames() |
| 426 { | 426 { |
| 427 ChildFrameDisconnector(*this).disconnect(); | 427 ChildFrameDisconnector(*this).disconnect(); |
| 428 } | 428 } |
| 429 | 429 |
| 430 void ContainerNode::removeChild(Node* oldChild, ExceptionState& es) | 430 void ContainerNode::removeChild(Node* oldChild, ExceptionState& exceptionState) |
| 431 { | 431 { |
| 432 // Check that this node is not "floating". | 432 // Check that this node is not "floating". |
| 433 // If it is, it can be deleted as a side effect of sending mutation events. | 433 // If it is, it can be deleted as a side effect of sending mutation events. |
| 434 ASSERT(refCount() || parentOrShadowHostNode()); | 434 ASSERT(refCount() || parentOrShadowHostNode()); |
| 435 | 435 |
| 436 RefPtr<Node> protect(this); | 436 RefPtr<Node> protect(this); |
| 437 | 437 |
| 438 // NotFoundError: Raised if oldChild is not a child of this node. | 438 // NotFoundError: Raised if oldChild is not a child of this node. |
| 439 if (!oldChild || oldChild->parentNode() != this) { | 439 if (!oldChild || oldChild->parentNode() != this) { |
| 440 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute("
removeChild", "Node", "The node to be removed is not a child of this node.")); | 440 exceptionState.throwDOMException(NotFoundError, ExceptionMessages::faile
dToExecute("removeChild", "Node", "The node to be removed is not a child of this
node.")); |
| 441 return; | 441 return; |
| 442 } | 442 } |
| 443 | 443 |
| 444 RefPtr<Node> child = oldChild; | 444 RefPtr<Node> child = oldChild; |
| 445 | 445 |
| 446 document().removeFocusedElementOfSubtree(child.get()); | 446 document().removeFocusedElementOfSubtree(child.get()); |
| 447 | 447 |
| 448 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExist
s(&document())) | 448 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExist
s(&document())) |
| 449 fullscreen->removeFullScreenElementOfSubtree(child.get()); | 449 fullscreen->removeFullScreenElementOfSubtree(child.get()); |
| 450 | 450 |
| 451 // Events fired when blurring currently focused node might have moved this | 451 // Events fired when blurring currently focused node might have moved this |
| 452 // child into a different parent. | 452 // child into a different parent. |
| 453 if (child->parentNode() != this) { | 453 if (child->parentNode() != this) { |
| 454 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute("
removeChild", "Node", "The node to be removed is no longer a child of this node.
Perhaps it was moved in a 'blur' event handler?")); | 454 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?")); |
| 455 return; | 455 return; |
| 456 } | 456 } |
| 457 | 457 |
| 458 willRemoveChild(*child); | 458 willRemoveChild(*child); |
| 459 | 459 |
| 460 // Mutation events might have moved this child into a different parent. | 460 // Mutation events might have moved this child into a different parent. |
| 461 if (child->parentNode() != this) { | 461 if (child->parentNode() != this) { |
| 462 es.throwDOMException(NotFoundError, ExceptionMessages::failedToExecute("
removeChild", "Node", "The node to be removed is no longer a child of this node.
Perhaps it was moved in response to a mutation?")); | 462 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?")); |
| 463 return; | 463 return; |
| 464 } | 464 } |
| 465 | 465 |
| 466 { | 466 { |
| 467 RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates; | 467 RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates; |
| 468 | 468 |
| 469 Node* prev = child->previousSibling(); | 469 Node* prev = child->previousSibling(); |
| 470 Node* next = child->nextSibling(); | 470 Node* next = child->nextSibling(); |
| 471 removeBetween(prev, next, *child); | 471 removeBetween(prev, next, *child); |
| 472 childrenChanged(false, prev, next, -1); | 472 childrenChanged(false, prev, next, -1); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 | 566 |
| 567 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); | 567 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); |
| 568 | 568 |
| 569 for (size_t i = 0; i < removedChildren.size(); ++i) | 569 for (size_t i = 0; i < removedChildren.size(); ++i) |
| 570 ChildNodeRemovalNotifier(*this).notify(*removedChildren[i]); | 570 ChildNodeRemovalNotifier(*this).notify(*removedChildren[i]); |
| 571 } | 571 } |
| 572 | 572 |
| 573 dispatchSubtreeModifiedEvent(); | 573 dispatchSubtreeModifiedEvent(); |
| 574 } | 574 } |
| 575 | 575 |
| 576 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& es) | 576 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& excep
tionState) |
| 577 { | 577 { |
| 578 RefPtr<ContainerNode> protect(this); | 578 RefPtr<ContainerNode> protect(this); |
| 579 | 579 |
| 580 // Check that this node is not "floating". | 580 // Check that this node is not "floating". |
| 581 // If it is, it can be deleted as a side effect of sending mutation events. | 581 // If it is, it can be deleted as a side effect of sending mutation events. |
| 582 ASSERT(refCount() || parentOrShadowHostNode()); | 582 ASSERT(refCount() || parentOrShadowHostNode()); |
| 583 | 583 |
| 584 // Make sure adding the new child is ok | 584 // Make sure adding the new child is ok |
| 585 if (!checkAddChild(*this, newChild.get(), appendChildMethodName, es)) | 585 if (!checkAddChild(*this, newChild.get(), appendChildMethodName, exceptionSt
ate)) |
| 586 return; | 586 return; |
| 587 ASSERT(newChild); | 587 ASSERT(newChild); |
| 588 | 588 |
| 589 if (newChild == m_lastChild) // nothing to do | 589 if (newChild == m_lastChild) // nothing to do |
| 590 return; | 590 return; |
| 591 | 591 |
| 592 NodeVector targets; | 592 NodeVector targets; |
| 593 collectChildrenAndRemoveFromOldParent(*newChild, targets, es); | 593 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); |
| 594 if (es.hadException()) | 594 if (exceptionState.hadException()) |
| 595 return; | 595 return; |
| 596 | 596 |
| 597 if (targets.isEmpty()) | 597 if (targets.isEmpty()) |
| 598 return; | 598 return; |
| 599 | 599 |
| 600 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 600 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
| 601 if (!checkAcceptChildGuaranteedNodeTypes(*this, *newChild, appendChildMethod
Name, es)) | 601 if (!checkAcceptChildGuaranteedNodeTypes(*this, *newChild, appendChildMethod
Name, exceptionState)) |
| 602 return; | 602 return; |
| 603 | 603 |
| 604 InspectorInstrumentation::willInsertDOMNode(this); | 604 InspectorInstrumentation::willInsertDOMNode(this); |
| 605 | 605 |
| 606 // Now actually add the child(ren) | 606 // Now actually add the child(ren) |
| 607 ChildListMutationScope mutation(*this); | 607 ChildListMutationScope mutation(*this); |
| 608 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { | 608 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); +
+it) { |
| 609 ASSERT(*it); | 609 ASSERT(*it); |
| 610 Node& child = **it; | 610 Node& child = **it; |
| 611 | 611 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 document().updateRangesAfterChildrenChanged(this); | 676 document().updateRangesAfterChildrenChanged(this); |
| 677 invalidateNodeListCachesInAncestors(); | 677 invalidateNodeListCachesInAncestors(); |
| 678 if (childCountDelta > 0 && inActiveDocument()) { | 678 if (childCountDelta > 0 && inActiveDocument()) { |
| 679 setChildNeedsStyleRecalc(); | 679 setChildNeedsStyleRecalc(); |
| 680 markAncestorsWithChildNeedsStyleRecalc(); | 680 markAncestorsWithChildNeedsStyleRecalc(); |
| 681 } | 681 } |
| 682 } | 682 } |
| 683 | 683 |
| 684 void ContainerNode::cloneChildNodes(ContainerNode *clone) | 684 void ContainerNode::cloneChildNodes(ContainerNode *clone) |
| 685 { | 685 { |
| 686 TrackExceptionState es; | 686 TrackExceptionState exceptionState; |
| 687 for (Node* n = firstChild(); n && !es.hadException(); n = n->nextSibling()) | 687 for (Node* n = firstChild(); n && !exceptionState.hadException(); n = n->nex
tSibling()) |
| 688 clone->appendChild(n->cloneNode(true), es); | 688 clone->appendChild(n->cloneNode(true), exceptionState); |
| 689 } | 689 } |
| 690 | 690 |
| 691 | 691 |
| 692 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const | 692 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const |
| 693 { | 693 { |
| 694 if (!renderer()) | 694 if (!renderer()) |
| 695 return false; | 695 return false; |
| 696 // What is this code really trying to do? | 696 // What is this code really trying to do? |
| 697 RenderObject* o = renderer(); | 697 RenderObject* o = renderer(); |
| 698 RenderObject* p = o; | 698 RenderObject* p = o; |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1007 return true; | 1007 return true; |
| 1008 | 1008 |
| 1009 if (node->isElementNode() && toElement(node)->shadow()) | 1009 if (node->isElementNode() && toElement(node)->shadow()) |
| 1010 return true; | 1010 return true; |
| 1011 | 1011 |
| 1012 return false; | 1012 return false; |
| 1013 } | 1013 } |
| 1014 #endif | 1014 #endif |
| 1015 | 1015 |
| 1016 } // namespace WebCore | 1016 } // namespace WebCore |
| OLD | NEW |