Chromium Code Reviews| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 #include "core/rendering/RenderView.h" | 44 #include "core/rendering/RenderView.h" |
| 45 #include "core/rendering/RenderWidget.h" | 45 #include "core/rendering/RenderWidget.h" |
| 46 #include "wtf/Vector.h" | 46 #include "wtf/Vector.h" |
| 47 | 47 |
| 48 using namespace std; | 48 using namespace std; |
| 49 | 49 |
| 50 namespace WebCore { | 50 namespace WebCore { |
| 51 | 51 |
| 52 static void dispatchChildInsertionEvents(Node*); | 52 static void dispatchChildInsertionEvents(Node*); |
| 53 static void dispatchChildRemovalEvents(Node*); | 53 static void dispatchChildRemovalEvents(Node*); |
| 54 static void updateTreeAfterInsertion(ContainerNode*, Node*); | 54 static void updateTreeAfterInsertion(ContainerNode&, Node&); |
| 55 | 55 |
| 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"; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 75 toContainerNode(node)->removeChildren(); | 75 toContainerNode(node)->removeChildren(); |
| 76 } | 76 } |
| 77 | 77 |
| 78 void ContainerNode::removeDetachedChildren() | 78 void ContainerNode::removeDetachedChildren() |
| 79 { | 79 { |
| 80 if (connectedSubframeCount()) { | 80 if (connectedSubframeCount()) { |
| 81 for (Node* child = firstChild(); child; child = child->nextSibling()) | 81 for (Node* child = firstChild(); child; child = child->nextSibling()) |
| 82 child->updateAncestorConnectedSubframeCountForRemoval(); | 82 child->updateAncestorConnectedSubframeCountForRemoval(); |
| 83 } | 83 } |
| 84 // FIXME: We should be able to ASSERT(!confusingAndOftenMisusedAttached()) h ere: https://bugs.webkit.org/show_bug.cgi?id=107801 | 84 // FIXME: We should be able to ASSERT(!confusingAndOftenMisusedAttached()) h ere: https://bugs.webkit.org/show_bug.cgi?id=107801 |
| 85 removeDetachedChildrenInContainer<Node, ContainerNode>(this); | 85 removeDetachedChildrenInContainer<Node, ContainerNode>(*this); |
| 86 } | 86 } |
| 87 | 87 |
| 88 void ContainerNode::parserTakeAllChildrenFrom(ContainerNode* oldParent) | 88 void ContainerNode::parserTakeAllChildrenFrom(ContainerNode* oldParent) |
| 89 { | 89 { |
| 90 while (RefPtr<Node> child = oldParent->firstChild()) { | 90 while (RefPtr<Node> child = oldParent->firstChild()) { |
| 91 oldParent->parserRemoveChild(child.get()); | 91 oldParent->parserRemoveChild(*child); |
| 92 treeScope().adoptIfNeeded(child.get()); | 92 treeScope().adoptIfNeeded(child.get()); |
| 93 parserAppendChild(child.get()); | 93 parserAppendChild(child.get()); |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 ContainerNode::~ContainerNode() | 97 ContainerNode::~ContainerNode() |
| 98 { | 98 { |
| 99 willBeDeletedFromDocument(); | 99 willBeDeletedFromDocument(); |
| 100 removeDetachedChildren(); | 100 removeDetachedChildren(); |
| 101 } | 101 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 return; | 229 return; |
| 230 | 230 |
| 231 // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. | 231 // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. |
| 232 if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), insertBeforeM ethodName, es)) | 232 if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), insertBeforeM ethodName, es)) |
| 233 return; | 233 return; |
| 234 | 234 |
| 235 InspectorInstrumentation::willInsertDOMNode(this); | 235 InspectorInstrumentation::willInsertDOMNode(this); |
| 236 | 236 |
| 237 ChildListMutationScope mutation(this); | 237 ChildListMutationScope mutation(this); |
| 238 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { | 238 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { |
| 239 Node* child = it->get(); | 239 ASSERT(*it); |
| 240 Node& child = **it; | |
| 240 | 241 |
| 241 // Due to arbitrary code running in response to a DOM mutation event it' s | 242 // Due to arbitrary code running in response to a DOM mutation event it' s |
| 242 // possible that "next" is no longer a child of "this". | 243 // possible that "next" is no longer a child of "this". |
| 243 // It's also possible that "child" has been inserted elsewhere. | 244 // It's also possible that "child" has been inserted elsewhere. |
| 244 // In either of those cases, we'll just stop. | 245 // In either of those cases, we'll just stop. |
| 245 if (next->parentNode() != this) | 246 if (next->parentNode() != this) |
| 246 break; | 247 break; |
| 247 if (child->parentNode()) | 248 if (child.parentNode()) |
| 248 break; | 249 break; |
| 249 | 250 |
| 250 treeScope().adoptIfNeeded(child); | 251 treeScope().adoptIfNeeded(&child); |
| 251 | 252 |
| 252 insertBeforeCommon(next.get(), child); | 253 insertBeforeCommon(*next, child); |
| 253 | 254 |
| 254 updateTreeAfterInsertion(this, child); | 255 updateTreeAfterInsertion(*this, child); |
| 255 } | 256 } |
| 256 | 257 |
| 257 dispatchSubtreeModifiedEvent(); | 258 dispatchSubtreeModifiedEvent(); |
| 258 } | 259 } |
| 259 | 260 |
| 260 void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild) | 261 void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild) |
| 261 { | 262 { |
| 262 NoEventDispatchAssertion assertNoEventDispatch; | 263 NoEventDispatchAssertion assertNoEventDispatch; |
| 263 | 264 |
| 264 ASSERT(newChild); | 265 ASSERT(!newChild.parentNode()); // Use insertBefore if you need to handle re parenting (and want DOM mutation events). |
| 265 ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle r eparenting (and want DOM mutation events). | 266 ASSERT(!newChild.nextSibling()); |
| 266 ASSERT(!newChild->nextSibling()); | 267 ASSERT(!newChild.previousSibling()); |
| 267 ASSERT(!newChild->previousSibling()); | 268 ASSERT(!newChild.isShadowRoot()); |
| 268 ASSERT(!newChild->isShadowRoot()); | |
| 269 | 269 |
| 270 Node* prev = nextChild->previousSibling(); | 270 Node* prev = nextChild.previousSibling(); |
| 271 ASSERT(m_lastChild != prev); | 271 ASSERT(m_lastChild != prev); |
| 272 nextChild->setPreviousSibling(newChild); | 272 nextChild.setPreviousSibling(&newChild); |
| 273 if (prev) { | 273 if (prev) { |
| 274 ASSERT(m_firstChild != nextChild); | 274 ASSERT(m_firstChild != nextChild); |
| 275 ASSERT(prev->nextSibling() == nextChild); | 275 ASSERT(prev->nextSibling() == nextChild); |
| 276 prev->setNextSibling(newChild); | 276 prev->setNextSibling(&newChild); |
| 277 } else { | 277 } else { |
| 278 ASSERT(m_firstChild == nextChild); | 278 ASSERT(m_firstChild == nextChild); |
| 279 m_firstChild = newChild; | 279 m_firstChild = &newChild; |
| 280 } | 280 } |
| 281 newChild->setParentOrShadowHostNode(this); | 281 newChild.setParentOrShadowHostNode(this); |
| 282 newChild->setPreviousSibling(prev); | 282 newChild.setPreviousSibling(prev); |
| 283 newChild->setNextSibling(nextChild); | 283 newChild.setNextSibling(&nextChild); |
| 284 } | 284 } |
| 285 | 285 |
| 286 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChil d) | 286 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChil d) |
| 287 { | 287 { |
| 288 ASSERT(newChild); | 288 ASSERT(newChild); |
| 289 ASSERT(nextChild); | 289 ASSERT(nextChild); |
| 290 ASSERT(nextChild->parentNode() == this); | 290 ASSERT(nextChild->parentNode() == this); |
| 291 ASSERT(!newChild->isDocumentFragment()); | 291 ASSERT(!newChild->isDocumentFragment()); |
| 292 ASSERT(!hasTagName(HTMLNames::templateTag)); | 292 ASSERT(!hasTagName(HTMLNames::templateTag)); |
| 293 | 293 |
| 294 if (nextChild->previousSibling() == newChild || nextChild == newChild) // no thing to do | 294 if (nextChild->previousSibling() == newChild || nextChild == newChild) // no thing to do |
| 295 return; | 295 return; |
| 296 | 296 |
| 297 if (document() != newChild->document()) | 297 if (document() != newChild->document()) |
| 298 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); | 298 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
| 299 | 299 |
| 300 insertBeforeCommon(nextChild, newChild.get()); | 300 insertBeforeCommon(*nextChild, *newChild); |
| 301 | 301 |
| 302 newChild->updateAncestorConnectedSubframeCountForInsertion(); | 302 newChild->updateAncestorConnectedSubframeCountForInsertion(); |
| 303 | 303 |
| 304 ChildListMutationScope(this).childAdded(newChild.get()); | 304 ChildListMutationScope(this).childAdded(newChild.get()); |
| 305 | 305 |
| 306 childrenChanged(true, newChild->previousSibling(), nextChild, 1); | 306 childrenChanged(true, newChild->previousSibling(), nextChild, 1); |
| 307 | 307 |
| 308 ChildNodeInsertionNotifier(this).notify(newChild.get()); | 308 ChildNodeInsertionNotifier(*this).notify(*newChild); |
| 309 } | 309 } |
| 310 | 310 |
| 311 void ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce ptionState& es) | 311 void ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce ptionState& es) |
| 312 { | 312 { |
| 313 // Check that this node is not "floating". | 313 // Check that this node is not "floating". |
| 314 // If it is, it can be deleted as a side effect of sending mutation events. | 314 // If it is, it can be deleted as a side effect of sending mutation events. |
| 315 ASSERT(refCount() || parentOrShadowHostNode()); | 315 ASSERT(refCount() || parentOrShadowHostNode()); |
| 316 | 316 |
| 317 RefPtr<Node> protect(this); | 317 RefPtr<Node> protect(this); |
| 318 | 318 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 return; | 357 return; |
| 358 | 358 |
| 359 // Does this yet another check because collectChildrenAndRemoveFromOldParent () fires a MutationEvent. | 359 // Does this yet another check because collectChildrenAndRemoveFromOldParent () fires a MutationEvent. |
| 360 if (!checkReplaceChild(this, newChild.get(), oldChild, replaceChildMethodNam e, es)) | 360 if (!checkReplaceChild(this, newChild.get(), oldChild, replaceChildMethodNam e, es)) |
| 361 return; | 361 return; |
| 362 | 362 |
| 363 InspectorInstrumentation::willInsertDOMNode(this); | 363 InspectorInstrumentation::willInsertDOMNode(this); |
| 364 | 364 |
| 365 // Add the new child(ren) | 365 // Add the new child(ren) |
| 366 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { | 366 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { |
| 367 Node* child = it->get(); | 367 ASSERT(*it); |
| 368 Node& child = **it; | |
| 368 | 369 |
| 369 // 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 |
| 370 // possible that "next" is no longer a child of "this". | 371 // possible that "next" is no longer a child of "this". |
| 371 // It's also possible that "child" has been inserted elsewhere. | 372 // It's also possible that "child" has been inserted elsewhere. |
| 372 // In either of those cases, we'll just stop. | 373 // In either of those cases, we'll just stop. |
| 373 if (next && next->parentNode() != this) | 374 if (next && next->parentNode() != this) |
| 374 break; | 375 break; |
| 375 if (child->parentNode()) | 376 if (child.parentNode()) |
| 376 break; | 377 break; |
| 377 | 378 |
| 378 treeScope().adoptIfNeeded(child); | 379 treeScope().adoptIfNeeded(&child); |
| 379 | 380 |
| 380 // Add child before "next". | 381 // Add child before "next". |
| 381 { | 382 { |
| 382 NoEventDispatchAssertion assertNoEventDispatch; | 383 NoEventDispatchAssertion assertNoEventDispatch; |
| 383 if (next) | 384 if (next) |
| 384 insertBeforeCommon(next.get(), child); | 385 insertBeforeCommon(*next, child); |
| 385 else | 386 else |
| 386 appendChildToContainer(child, this); | 387 appendChildToContainer(child, *this); |
| 387 } | 388 } |
| 388 | 389 |
| 389 updateTreeAfterInsertion(this, child); | 390 updateTreeAfterInsertion(*this, child); |
| 390 } | 391 } |
| 391 | 392 |
| 392 dispatchSubtreeModifiedEvent(); | 393 dispatchSubtreeModifiedEvent(); |
| 393 } | 394 } |
| 394 | 395 |
| 395 static void willRemoveChild(Node* child) | 396 static void willRemoveChild(Node* child) |
| 396 { | 397 { |
| 397 ASSERT(child->parentNode()); | 398 ASSERT(child->parentNode()); |
| 398 ChildListMutationScope(child->parentNode()).willRemoveChild(child); | 399 ChildListMutationScope(child->parentNode()).willRemoveChild(child); |
| 399 child->notifyMutationObserversNodeWillDetach(); | 400 child->notifyMutationObserversNodeWillDetach(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 if (child->parentNode() != this) { | 460 if (child->parentNode() != this) { |
| 460 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?")); | 461 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?")); |
| 461 return; | 462 return; |
| 462 } | 463 } |
| 463 | 464 |
| 464 { | 465 { |
| 465 RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates; | 466 RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates; |
| 466 | 467 |
| 467 Node* prev = child->previousSibling(); | 468 Node* prev = child->previousSibling(); |
| 468 Node* next = child->nextSibling(); | 469 Node* next = child->nextSibling(); |
| 469 removeBetween(prev, next, child.get()); | 470 removeBetween(prev, next, *child); |
| 470 childrenChanged(false, prev, next, -1); | 471 childrenChanged(false, prev, next, -1); |
| 471 ChildNodeRemovalNotifier(this).notify(child.get()); | 472 ChildNodeRemovalNotifier(*this).notify(*child); |
| 472 } | 473 } |
| 473 dispatchSubtreeModifiedEvent(); | 474 dispatchSubtreeModifiedEvent(); |
| 474 } | 475 } |
| 475 | 476 |
| 476 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* ol dChild) | 477 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol dChild) |
| 477 { | 478 { |
| 478 NoEventDispatchAssertion assertNoEventDispatch; | 479 NoEventDispatchAssertion assertNoEventDispatch; |
| 479 | 480 |
| 480 ASSERT(oldChild); | 481 ASSERT(oldChild.parentNode() == this); |
| 481 ASSERT(oldChild->parentNode() == this); | |
| 482 | 482 |
| 483 // Remove from rendering tree | 483 // Remove from rendering tree |
| 484 if (oldChild->confusingAndOftenMisusedAttached()) | 484 if (oldChild.confusingAndOftenMisusedAttached()) |
| 485 oldChild->detach(); | 485 oldChild.detach(); |
| 486 | 486 |
| 487 if (nextChild) | 487 if (nextChild) |
| 488 nextChild->setPreviousSibling(previousChild); | 488 nextChild->setPreviousSibling(previousChild); |
| 489 if (previousChild) | 489 if (previousChild) |
| 490 previousChild->setNextSibling(nextChild); | 490 previousChild->setNextSibling(nextChild); |
| 491 if (m_firstChild == oldChild) | 491 if (m_firstChild == oldChild) |
| 492 m_firstChild = nextChild; | 492 m_firstChild = nextChild; |
| 493 if (m_lastChild == oldChild) | 493 if (m_lastChild == oldChild) |
| 494 m_lastChild = previousChild; | 494 m_lastChild = previousChild; |
| 495 | 495 |
| 496 oldChild->setPreviousSibling(0); | 496 oldChild.setPreviousSibling(0); |
| 497 oldChild->setNextSibling(0); | 497 oldChild.setNextSibling(0); |
| 498 oldChild->setParentOrShadowHostNode(0); | 498 oldChild.setParentOrShadowHostNode(0); |
| 499 | 499 |
| 500 document().adoptIfNeeded(oldChild); | 500 document().adoptIfNeeded(&oldChild); |
| 501 } | 501 } |
| 502 | 502 |
| 503 void ContainerNode::parserRemoveChild(Node* oldChild) | 503 void ContainerNode::parserRemoveChild(Node& oldChild) |
| 504 { | 504 { |
| 505 ASSERT(oldChild); | 505 ASSERT(oldChild.parentNode() == this); |
| 506 ASSERT(oldChild->parentNode() == this); | 506 ASSERT(!oldChild.isDocumentFragment()); |
| 507 ASSERT(!oldChild->isDocumentFragment()); | |
| 508 | 507 |
| 509 Node* prev = oldChild->previousSibling(); | 508 Node* prev = oldChild.previousSibling(); |
| 510 Node* next = oldChild->nextSibling(); | 509 Node* next = oldChild.nextSibling(); |
| 511 | 510 |
| 512 oldChild->updateAncestorConnectedSubframeCountForRemoval(); | 511 oldChild.updateAncestorConnectedSubframeCountForRemoval(); |
| 513 | 512 |
| 514 ChildListMutationScope(this).willRemoveChild(oldChild); | 513 ChildListMutationScope(this).willRemoveChild(&oldChild); |
| 515 oldChild->notifyMutationObserversNodeWillDetach(); | 514 oldChild.notifyMutationObserversNodeWillDetach(); |
| 516 | 515 |
| 517 removeBetween(prev, next, oldChild); | 516 removeBetween(prev, next, oldChild); |
| 518 | 517 |
| 519 childrenChanged(true, prev, next, -1); | 518 childrenChanged(true, prev, next, -1); |
| 520 ChildNodeRemovalNotifier(this).notify(oldChild); | 519 ChildNodeRemovalNotifier(*this).notify(oldChild); |
| 521 } | 520 } |
| 522 | 521 |
| 523 // this differs from other remove functions because it forcibly removes all the children, | 522 // this differs from other remove functions because it forcibly removes all the children, |
| 524 // regardless of read-only status or event exceptions, e.g. | 523 // regardless of read-only status or event exceptions, e.g. |
| 525 void ContainerNode::removeChildren() | 524 void ContainerNode::removeChildren() |
| 526 { | 525 { |
| 527 if (!m_firstChild) | 526 if (!m_firstChild) |
| 528 return; | 527 return; |
| 529 | 528 |
| 530 // The container node can be removed from event handlers. | 529 // The container node can be removed from event handlers. |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 552 document().nodeChildrenWillBeRemoved(this); | 551 document().nodeChildrenWillBeRemoved(this); |
| 553 | 552 |
| 554 NodeVector removedChildren; | 553 NodeVector removedChildren; |
| 555 { | 554 { |
| 556 RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates; | 555 RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates; |
| 557 { | 556 { |
| 558 NoEventDispatchAssertion assertNoEventDispatch; | 557 NoEventDispatchAssertion assertNoEventDispatch; |
| 559 removedChildren.reserveInitialCapacity(childNodeCount()); | 558 removedChildren.reserveInitialCapacity(childNodeCount()); |
| 560 while (m_firstChild) { | 559 while (m_firstChild) { |
| 561 removedChildren.append(m_firstChild); | 560 removedChildren.append(m_firstChild); |
| 562 removeBetween(0, m_firstChild->nextSibling(), m_firstChild); | 561 removeBetween(0, m_firstChild->nextSibling(), *m_firstChild); |
| 563 } | 562 } |
| 564 } | 563 } |
| 565 | 564 |
| 566 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); | 565 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); |
| 567 | 566 |
| 568 for (size_t i = 0; i < removedChildren.size(); ++i) | 567 for (size_t i = 0; i < removedChildren.size(); ++i) |
| 569 ChildNodeRemovalNotifier(this).notify(removedChildren[i].get()); | 568 ChildNodeRemovalNotifier(*this).notify(*removedChildren[i]); |
| 570 } | 569 } |
| 571 | 570 |
| 572 dispatchSubtreeModifiedEvent(); | 571 dispatchSubtreeModifiedEvent(); |
| 573 } | 572 } |
| 574 | 573 |
| 575 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& es) | 574 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& es) |
| 576 { | 575 { |
| 577 RefPtr<ContainerNode> protect(this); | 576 RefPtr<ContainerNode> protect(this); |
| 578 | 577 |
| 579 // Check that this node is not "floating". | 578 // Check that this node is not "floating". |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 597 | 596 |
| 598 // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. | 597 // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. |
| 599 if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), appendChildMe thodName, es)) | 598 if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), appendChildMe thodName, es)) |
| 600 return; | 599 return; |
| 601 | 600 |
| 602 InspectorInstrumentation::willInsertDOMNode(this); | 601 InspectorInstrumentation::willInsertDOMNode(this); |
| 603 | 602 |
| 604 // Now actually add the child(ren) | 603 // Now actually add the child(ren) |
| 605 ChildListMutationScope mutation(this); | 604 ChildListMutationScope mutation(this); |
| 606 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { | 605 for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); + +it) { |
| 607 Node* child = it->get(); | 606 ASSERT(*it); |
|
adamk
2013/10/28 21:41:12
All these ASSERT(*it) calls make me wonder if we n
| |
| 607 Node& child = **it; | |
| 608 | 608 |
| 609 // If the child has a parent again, just stop what we're doing, because | 609 // If the child has a parent again, just stop what we're doing, because |
| 610 // that means someone is doing something with DOM mutation -- can't re-p arent | 610 // that means someone is doing something with DOM mutation -- can't re-p arent |
| 611 // a child that already has a parent. | 611 // a child that already has a parent. |
| 612 if (child->parentNode()) | 612 if (child.parentNode()) |
| 613 break; | 613 break; |
| 614 | 614 |
| 615 treeScope().adoptIfNeeded(child); | 615 treeScope().adoptIfNeeded(&child); |
| 616 | 616 |
| 617 // Append child to the end of the list | 617 // Append child to the end of the list |
| 618 { | 618 { |
| 619 NoEventDispatchAssertion assertNoEventDispatch; | 619 NoEventDispatchAssertion assertNoEventDispatch; |
| 620 appendChildToContainer(child, this); | 620 appendChildToContainer(child, *this); |
| 621 } | 621 } |
| 622 | 622 |
| 623 updateTreeAfterInsertion(this, child); | 623 updateTreeAfterInsertion(*this, child); |
| 624 } | 624 } |
| 625 | 625 |
| 626 dispatchSubtreeModifiedEvent(); | 626 dispatchSubtreeModifiedEvent(); |
| 627 } | 627 } |
| 628 | 628 |
| 629 void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild) | 629 void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild) |
| 630 { | 630 { |
| 631 ASSERT(newChild); | 631 ASSERT(newChild); |
| 632 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re parenting (and want DOM mutation events). | 632 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re parenting (and want DOM mutation events). |
| 633 ASSERT(!newChild->isDocumentFragment()); | 633 ASSERT(!newChild->isDocumentFragment()); |
| 634 ASSERT(!hasTagName(HTMLNames::templateTag)); | 634 ASSERT(!hasTagName(HTMLNames::templateTag)); |
| 635 | 635 |
| 636 if (document() != newChild->document()) | 636 if (document() != newChild->document()) |
| 637 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); | 637 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
| 638 | 638 |
| 639 Node* last = m_lastChild; | 639 Node* last = m_lastChild; |
| 640 { | 640 { |
| 641 NoEventDispatchAssertion assertNoEventDispatch; | 641 NoEventDispatchAssertion assertNoEventDispatch; |
| 642 // FIXME: This method should take a PassRefPtr. | 642 // FIXME: This method should take a PassRefPtr. |
| 643 appendChildToContainer(newChild.get(), this); | 643 appendChildToContainer(*newChild, *this); |
| 644 treeScope().adoptIfNeeded(newChild.get()); | 644 treeScope().adoptIfNeeded(newChild.get()); |
| 645 } | 645 } |
| 646 | 646 |
| 647 newChild->updateAncestorConnectedSubframeCountForInsertion(); | 647 newChild->updateAncestorConnectedSubframeCountForInsertion(); |
| 648 | 648 |
| 649 ChildListMutationScope(this).childAdded(newChild.get()); | 649 ChildListMutationScope(this).childAdded(newChild.get()); |
| 650 | 650 |
| 651 childrenChanged(true, last, 0, 1); | 651 childrenChanged(true, last, 0, 1); |
| 652 ChildNodeInsertionNotifier(this).notify(newChild.get()); | 652 ChildNodeInsertionNotifier(*this).notify(*newChild); |
| 653 } | 653 } |
| 654 | 654 |
| 655 void ContainerNode::attach(const AttachContext& context) | 655 void ContainerNode::attach(const AttachContext& context) |
| 656 { | 656 { |
| 657 attachChildren(context); | 657 attachChildren(context); |
| 658 clearChildNeedsStyleRecalc(); | 658 clearChildNeedsStyleRecalc(); |
| 659 Node::attach(context); | 659 Node::attach(context); |
| 660 } | 660 } |
| 661 | 661 |
| 662 void ContainerNode::detach(const AttachContext& context) | 662 void ContainerNode::detach(const AttachContext& context) |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 957 } | 957 } |
| 958 | 958 |
| 959 // dispatch the DOMNodeRemovedFromDocument event to all descendants | 959 // dispatch the DOMNodeRemovedFromDocument event to all descendants |
| 960 if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFRO MDOCUMENT_LISTENER)) { | 960 if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFRO MDOCUMENT_LISTENER)) { |
| 961 NodeChildRemovalTracker scope(child); | 961 NodeChildRemovalTracker scope(child); |
| 962 for (; c; c = NodeTraversal::next(c.get(), child)) | 962 for (; c; c = NodeTraversal::next(c.get(), child)) |
| 963 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNode RemovedFromDocument, false)); | 963 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNode RemovedFromDocument, false)); |
| 964 } | 964 } |
| 965 } | 965 } |
| 966 | 966 |
| 967 static void updateTreeAfterInsertion(ContainerNode* parent, Node* child) | 967 static void updateTreeAfterInsertion(ContainerNode& parent, Node& child) |
| 968 { | 968 { |
| 969 ASSERT(parent->refCount()); | 969 ASSERT(parent.refCount()); |
| 970 ASSERT(child->refCount()); | 970 ASSERT(child.refCount()); |
| 971 | 971 |
| 972 ChildListMutationScope(parent).childAdded(child); | 972 ChildListMutationScope(&parent).childAdded(&child); |
| 973 | 973 |
| 974 parent->childrenChanged(false, child->previousSibling(), child->nextSibling( ), 1); | 974 parent.childrenChanged(false, child.previousSibling(), child.nextSibling(), 1); |
| 975 | 975 |
| 976 ChildNodeInsertionNotifier(parent).notify(child); | 976 ChildNodeInsertionNotifier(parent).notify(child); |
| 977 | 977 |
| 978 dispatchChildInsertionEvents(child); | 978 dispatchChildInsertionEvents(&child); |
| 979 } | 979 } |
| 980 | 980 |
| 981 #ifndef NDEBUG | 981 #ifndef NDEBUG |
| 982 bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node) | 982 bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node) |
| 983 { | 983 { |
| 984 if (node->isShadowRoot()) | 984 if (node->isShadowRoot()) |
| 985 return true; | 985 return true; |
| 986 | 986 |
| 987 if (node->isInsertionPoint()) | 987 if (node->isInsertionPoint()) |
| 988 return true; | 988 return true; |
| 989 | 989 |
| 990 if (node->isElementNode() && toElement(node)->shadow()) | 990 if (node->isElementNode() && toElement(node)->shadow()) |
| 991 return true; | 991 return true; |
| 992 | 992 |
| 993 return false; | 993 return false; |
| 994 } | 994 } |
| 995 #endif | 995 #endif |
| 996 | 996 |
| 997 } // namespace WebCore | 997 } // namespace WebCore |
| OLD | NEW |