| 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, 2013 Apple Inc. All rights
reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights
reserved. |
| 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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement contains the parent."); | 143 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement contains the parent."); |
| 144 return false; | 144 return false; |
| 145 } | 145 } |
| 146 if (!isChildTypeAllowed(newChild)) { | 146 if (!isChildTypeAllowed(newChild)) { |
| 147 exceptionState.throwDOMException(HierarchyRequestError, "Nodes of type '
" + newChild.nodeName() + "' may not be inserted inside nodes of type '" + nodeN
ame() + "'."); | 147 exceptionState.throwDOMException(HierarchyRequestError, "Nodes of type '
" + newChild.nodeName() + "' may not be inserted inside nodes of type '" + nodeN
ame() + "'."); |
| 148 return false; | 148 return false; |
| 149 } | 149 } |
| 150 return true; | 150 return true; |
| 151 } | 151 } |
| 152 | 152 |
| 153 template <typename Functor> |
| 154 void ContainerNode::insertNodeVector(const NodeVector& targets, Node* next, cons
t Functor& mutator) |
| 155 { |
| 156 InspectorInstrumentation::willInsertDOMNode(this); |
| 157 for (const auto& targetNode : targets) { |
| 158 DCHECK(targetNode); |
| 159 { |
| 160 EventDispatchForbiddenScope assertNoEventDispatch; |
| 161 ScriptForbiddenScope forbidScript; |
| 162 |
| 163 if (!mutator(*this, *targetNode, next)) |
| 164 break; |
| 165 } |
| 166 updateTreeAfterInsertion(*targetNode); |
| 167 } |
| 168 dispatchSubtreeModifiedEvent(); |
| 169 } |
| 170 |
| 171 class ContainerNode::AdoptAndInsertBefore { |
| 172 public: |
| 173 bool operator()(ContainerNode& container, Node& child, Node* next) const |
| 174 { |
| 175 DCHECK(next); |
| 176 // Due to arbitrary code running in response to a DOM mutation event |
| 177 // it's possible that "next" is no longer a child of "container". |
| 178 // It's also possible that "child" has been inserted elsewhere. In |
| 179 // either of those cases, we'll just stop. |
| 180 if (next->parentNode() != &container) |
| 181 return false; |
| 182 if (child.parentNode()) |
| 183 return false; |
| 184 |
| 185 container.treeScope().adoptIfNeeded(child); |
| 186 container.insertBeforeCommon(*next, child); |
| 187 return true; |
| 188 } |
| 189 }; |
| 190 |
| 191 class ContainerNode::AdoptAndAppendChild { |
| 192 public: |
| 193 bool operator()(ContainerNode& container, Node& child, Node* next) const |
| 194 { |
| 195 // If the child has a parent again, just stop what we're doing, because |
| 196 // that means someone is doing something with DOM mutation -- can't |
| 197 // re-parent a child that already has a parent. |
| 198 if (child.parentNode()) |
| 199 return false; |
| 200 container.treeScope().adoptIfNeeded(child); |
| 201 container.appendChildCommon(child); |
| 202 return true; |
| 203 } |
| 204 }; |
| 205 |
| 153 Node* ContainerNode::insertBefore(Node* newChild, Node* refChild, ExceptionState
& exceptionState) | 206 Node* ContainerNode::insertBefore(Node* newChild, Node* refChild, ExceptionState
& exceptionState) |
| 154 { | 207 { |
| 155 // insertBefore(node, 0) is equivalent to appendChild(node) | 208 // insertBefore(node, 0) is equivalent to appendChild(node) |
| 156 if (!refChild) { | 209 if (!refChild) { |
| 157 return appendChild(newChild, exceptionState); | 210 return appendChild(newChild, exceptionState); |
| 158 } | 211 } |
| 159 | 212 |
| 160 // Make sure adding the new child is OK. | 213 // Make sure adding the new child is OK. |
| 161 if (!checkAcceptChild(newChild, 0, exceptionState)) { | 214 if (!checkAcceptChild(newChild, 0, exceptionState)) { |
| 162 if (exceptionState.hadException()) | 215 if (exceptionState.hadException()) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 184 if (targets.isEmpty()) | 237 if (targets.isEmpty()) |
| 185 return newChild; | 238 return newChild; |
| 186 | 239 |
| 187 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 240 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
| 188 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, nullptr, exceptionState)
) { | 241 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, nullptr, exceptionState)
) { |
| 189 if (exceptionState.hadException()) | 242 if (exceptionState.hadException()) |
| 190 return nullptr; | 243 return nullptr; |
| 191 return newChild; | 244 return newChild; |
| 192 } | 245 } |
| 193 | 246 |
| 194 InspectorInstrumentation::willInsertDOMNode(this); | |
| 195 | |
| 196 ChildListMutationScope mutation(*this); | 247 ChildListMutationScope mutation(*this); |
| 197 for (const auto& targetNode : targets) { | 248 insertNodeVector(targets, next, AdoptAndInsertBefore()); |
| 198 DCHECK(targetNode); | |
| 199 Node& child = *targetNode; | |
| 200 | |
| 201 // Due to arbitrary code running in response to a DOM mutation event it'
s | |
| 202 // possible that "next" is no longer a child of "this". | |
| 203 // It's also possible that "child" has been inserted elsewhere. | |
| 204 // In either of those cases, we'll just stop. | |
| 205 if (next->parentNode() != this) | |
| 206 break; | |
| 207 if (child.parentNode()) | |
| 208 break; | |
| 209 | |
| 210 { | |
| 211 EventDispatchForbiddenScope assertNoEventDispatch; | |
| 212 ScriptForbiddenScope forbidScript; | |
| 213 | |
| 214 treeScope().adoptIfNeeded(child); | |
| 215 insertBeforeCommon(*next, child); | |
| 216 } | |
| 217 | |
| 218 updateTreeAfterInsertion(child); | |
| 219 } | |
| 220 | |
| 221 dispatchSubtreeModifiedEvent(); | |
| 222 | |
| 223 return newChild; | 249 return newChild; |
| 224 } | 250 } |
| 225 | 251 |
| 226 void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild) | 252 void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild) |
| 227 { | 253 { |
| 228 EventDispatchForbiddenScope assertNoEventDispatch; | 254 EventDispatchForbiddenScope assertNoEventDispatch; |
| 229 ScriptForbiddenScope forbidScript; | 255 ScriptForbiddenScope forbidScript; |
| 230 | 256 |
| 231 DCHECK(!newChild.parentNode()); // Use insertBefore if you need to handle re
parenting (and want DOM mutation events). | 257 DCHECK(!newChild.parentNode()); // Use insertBefore if you need to handle re
parenting (and want DOM mutation events). |
| 232 DCHECK(!newChild.nextSibling()); | 258 DCHECK(!newChild.nextSibling()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 if (exceptionState.hadException()) | 385 if (exceptionState.hadException()) |
| 360 return nullptr; | 386 return nullptr; |
| 361 | 387 |
| 362 // Does this yet another check because collectChildrenAndRemoveFromOldParent
() fires a MutationEvent. | 388 // Does this yet another check because collectChildrenAndRemoveFromOldParent
() fires a MutationEvent. |
| 363 if (!checkAcceptChild(newChild, child, exceptionState)) { | 389 if (!checkAcceptChild(newChild, child, exceptionState)) { |
| 364 if (exceptionState.hadException()) | 390 if (exceptionState.hadException()) |
| 365 return nullptr; | 391 return nullptr; |
| 366 return child; | 392 return child; |
| 367 } | 393 } |
| 368 | 394 |
| 369 InspectorInstrumentation::willInsertDOMNode(this); | 395 if (next) |
| 370 | 396 insertNodeVector(targets, next, AdoptAndInsertBefore()); |
| 371 // Add the new child(ren). | 397 else |
| 372 for (const auto& targetNode : targets) { | 398 insertNodeVector(targets, nullptr, AdoptAndAppendChild()); |
| 373 DCHECK(targetNode); | |
| 374 Node& child = *targetNode; | |
| 375 | |
| 376 // Due to arbitrary code running in response to a DOM mutation event it'
s | |
| 377 // possible that "next" is no longer a child of "this". | |
| 378 // It's also possible that "child" has been inserted elsewhere. | |
| 379 // In either of those cases, we'll just stop. | |
| 380 if (next && next->parentNode() != this) | |
| 381 break; | |
| 382 if (child.parentNode()) | |
| 383 break; | |
| 384 | |
| 385 treeScope().adoptIfNeeded(child); | |
| 386 | |
| 387 // Add child before "next". | |
| 388 { | |
| 389 EventDispatchForbiddenScope assertNoEventDispatch; | |
| 390 if (next) | |
| 391 insertBeforeCommon(*next, child); | |
| 392 else | |
| 393 appendChildCommon(child); | |
| 394 } | |
| 395 | |
| 396 updateTreeAfterInsertion(child); | |
| 397 } | |
| 398 | |
| 399 dispatchSubtreeModifiedEvent(); | |
| 400 return child; | 399 return child; |
| 401 } | 400 } |
| 402 | 401 |
| 403 void ContainerNode::willRemoveChild(Node& child) | 402 void ContainerNode::willRemoveChild(Node& child) |
| 404 { | 403 { |
| 405 DCHECK_EQ(child.parentNode(), this); | 404 DCHECK_EQ(child.parentNode(), this); |
| 406 ChildListMutationScope(*this).willRemoveChild(child); | 405 ChildListMutationScope(*this).willRemoveChild(child); |
| 407 child.notifyMutationObserversNodeWillDetach(); | 406 child.notifyMutationObserversNodeWillDetach(); |
| 408 dispatchChildRemovalEvents(child); | 407 dispatchChildRemovalEvents(child); |
| 409 ChildFrameDisconnector(child).disconnect(); | 408 ChildFrameDisconnector(child).disconnect(); |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 if (targets.isEmpty()) | 617 if (targets.isEmpty()) |
| 619 return newChild; | 618 return newChild; |
| 620 | 619 |
| 621 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 620 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
| 622 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, nullptr, exceptionState)
) { | 621 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, nullptr, exceptionState)
) { |
| 623 if (exceptionState.hadException()) | 622 if (exceptionState.hadException()) |
| 624 return nullptr; | 623 return nullptr; |
| 625 return newChild; | 624 return newChild; |
| 626 } | 625 } |
| 627 | 626 |
| 628 InspectorInstrumentation::willInsertDOMNode(this); | |
| 629 | |
| 630 // Now actually add the child(ren). | |
| 631 ChildListMutationScope mutation(*this); | 627 ChildListMutationScope mutation(*this); |
| 632 for (const auto& targetNode : targets) { | 628 insertNodeVector(targets, nullptr, AdoptAndAppendChild()); |
| 633 DCHECK(targetNode); | |
| 634 Node& child = *targetNode; | |
| 635 | |
| 636 // If the child has a parent again, just stop what we're doing, because | |
| 637 // that means someone is doing something with DOM mutation -- can't re-p
arent | |
| 638 // a child that already has a parent. | |
| 639 if (child.parentNode()) | |
| 640 break; | |
| 641 | |
| 642 { | |
| 643 EventDispatchForbiddenScope assertNoEventDispatch; | |
| 644 ScriptForbiddenScope forbidScript; | |
| 645 | |
| 646 treeScope().adoptIfNeeded(child); | |
| 647 appendChildCommon(child); | |
| 648 } | |
| 649 | |
| 650 updateTreeAfterInsertion(child); | |
| 651 } | |
| 652 | |
| 653 dispatchSubtreeModifiedEvent(); | |
| 654 return newChild; | 629 return newChild; |
| 655 } | 630 } |
| 656 | 631 |
| 657 void ContainerNode::parserAppendChild(Node* newChild) | 632 void ContainerNode::parserAppendChild(Node* newChild) |
| 658 { | 633 { |
| 659 DCHECK(newChild); | 634 DCHECK(newChild); |
| 660 DCHECK(!newChild->isDocumentFragment()); | 635 DCHECK(!newChild->isDocumentFragment()); |
| 661 DCHECK(!isHTMLTemplateElement(this)); | 636 DCHECK(!isHTMLTemplateElement(this)); |
| 662 | 637 |
| 663 if (!checkParserAcceptChild(*newChild)) | 638 if (!checkParserAcceptChild(*newChild)) |
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1398 return true; | 1373 return true; |
| 1399 | 1374 |
| 1400 if (node->isElementNode() && toElement(node)->shadow()) | 1375 if (node->isElementNode() && toElement(node)->shadow()) |
| 1401 return true; | 1376 return true; |
| 1402 | 1377 |
| 1403 return false; | 1378 return false; |
| 1404 } | 1379 } |
| 1405 #endif | 1380 #endif |
| 1406 | 1381 |
| 1407 } // namespace blink | 1382 } // namespace blink |
| OLD | NEW |