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 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No
de& nextChild) | 287 void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No
de& nextChild) |
288 { | 288 { |
289 ASSERT(newChild); | 289 ASSERT(newChild); |
290 ASSERT(nextChild.parentNode() == this); | 290 ASSERT(nextChild.parentNode() == this); |
291 ASSERT(!newChild->isDocumentFragment()); | 291 ASSERT(!newChild->isDocumentFragment()); |
292 ASSERT(!isHTMLTemplateElement(this)); | 292 ASSERT(!isHTMLTemplateElement(this)); |
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 RefPtrWillBeRawPtr<Node> protect(this); |
| 298 |
297 if (document() != newChild->document()) | 299 if (document() != newChild->document()) |
298 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); | 300 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
299 | 301 |
300 insertBeforeCommon(nextChild, *newChild); | 302 insertBeforeCommon(nextChild, *newChild); |
301 | 303 |
302 newChild->updateAncestorConnectedSubframeCountForInsertion(); | 304 newChild->updateAncestorConnectedSubframeCountForInsertion(); |
303 | 305 |
304 ChildListMutationScope(*this).childAdded(*newChild); | 306 ChildListMutationScope(*this).childAdded(*newChild); |
305 | 307 |
306 childrenChanged(true, newChild->previousSibling(), &nextChild, 1); | 308 notifyNodeInserted(*newChild, ChildrenChangeSourceParser); |
307 | |
308 notifyNodeInserted(*newChild); | |
309 } | 309 } |
310 | 310 |
311 void ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, Node* ol
dChild, ExceptionState& exceptionState) | 311 void ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, Node* ol
dChild, ExceptionState& exceptionState) |
312 { | 312 { |
313 #if !ENABLE(OILPAN) | 313 #if !ENABLE(OILPAN) |
314 // Check that this node is not "floating". | 314 // Check that this node is not "floating". |
315 // If it is, it can be deleted as a side effect of sending mutation events. | 315 // If it is, it can be deleted as a side effect of sending mutation events. |
316 ASSERT(refCount() || parentOrShadowHostNode()); | 316 ASSERT(refCount() || parentOrShadowHostNode()); |
317 #endif | 317 #endif |
318 | 318 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 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?"); | 475 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?"); |
476 return; | 476 return; |
477 } | 477 } |
478 | 478 |
479 { | 479 { |
480 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; | 480 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; |
481 | 481 |
482 Node* prev = child->previousSibling(); | 482 Node* prev = child->previousSibling(); |
483 Node* next = child->nextSibling(); | 483 Node* next = child->nextSibling(); |
484 removeBetween(prev, next, *child); | 484 removeBetween(prev, next, *child); |
| 485 notifyNodeRemoved(*child); |
485 childrenChanged(false, prev, next, -1); | 486 childrenChanged(false, prev, next, -1); |
486 notifyNodeRemoved(*child); | |
487 } | 487 } |
488 dispatchSubtreeModifiedEvent(); | 488 dispatchSubtreeModifiedEvent(); |
489 } | 489 } |
490 | 490 |
491 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol
dChild) | 491 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol
dChild) |
492 { | 492 { |
493 NoEventDispatchAssertion assertNoEventDispatch; | 493 NoEventDispatchAssertion assertNoEventDispatch; |
494 | 494 |
495 ASSERT(oldChild.parentNode() == this); | 495 ASSERT(oldChild.parentNode() == this); |
496 | 496 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 // Exclude this node when looking for removed focusedElement since only | 557 // Exclude this node when looking for removed focusedElement since only |
558 // children will be removed. | 558 // children will be removed. |
559 // This must be later than willRemoveChildren, which might change focus | 559 // This must be later than willRemoveChildren, which might change focus |
560 // state of a child. | 560 // state of a child. |
561 document().removeFocusedElementOfSubtree(this, true); | 561 document().removeFocusedElementOfSubtree(this, true); |
562 | 562 |
563 // Removing a node from a selection can cause widget updates. | 563 // Removing a node from a selection can cause widget updates. |
564 document().nodeChildrenWillBeRemoved(*this); | 564 document().nodeChildrenWillBeRemoved(*this); |
565 } | 565 } |
566 | 566 |
567 | 567 // FIXME: Remove this NodeVector. Right now WebPluginContainerImpl::m_elemen
t is a |
| 568 // raw ptr which means the code below can drop the last ref to a plugin elem
ent and |
| 569 // then the code in UpdateSuspendScope::performDeferredWidgetTreeOperations
will |
| 570 // try to destroy the plugin which will be a use-after-free. We should use a
RefPtr |
| 571 // in the WebPluginContainerImpl instead. |
568 NodeVector removedChildren; | 572 NodeVector removedChildren; |
569 { | 573 { |
570 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; | 574 HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; |
| 575 |
571 { | 576 { |
572 NoEventDispatchAssertion assertNoEventDispatch; | 577 NoEventDispatchAssertion assertNoEventDispatch; |
| 578 ScriptForbiddenScope forbidScript; |
| 579 |
573 removedChildren.reserveInitialCapacity(countChildren()); | 580 removedChildren.reserveInitialCapacity(countChildren()); |
574 while (m_firstChild) { | 581 |
575 removedChildren.append(m_firstChild); | 582 while (RefPtrWillBeRawPtr<Node> child = m_firstChild) { |
576 removeBetween(0, m_firstChild->nextSibling(), *m_firstChild); | 583 removeBetween(0, child->nextSibling(), *child); |
| 584 removedChildren.append(child.get()); |
| 585 notifyNodeRemoved(*child); |
577 } | 586 } |
578 } | 587 } |
579 | 588 |
580 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); | 589 childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); |
581 | |
582 for (size_t i = 0; i < removedChildren.size(); ++i) | |
583 notifyNodeRemoved(*removedChildren[i]); | |
584 } | 590 } |
585 | 591 |
586 dispatchSubtreeModifiedEvent(); | 592 dispatchSubtreeModifiedEvent(); |
587 } | 593 } |
588 | 594 |
589 void ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, Exception
State& exceptionState) | 595 void ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, Exception
State& exceptionState) |
590 { | 596 { |
591 RefPtrWillBeRawPtr<ContainerNode> protect(this); | 597 RefPtrWillBeRawPtr<ContainerNode> protect(this); |
592 | 598 |
593 #if !ENABLE(OILPAN) | 599 #if !ENABLE(OILPAN) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 dispatchSubtreeModifiedEvent(); | 650 dispatchSubtreeModifiedEvent(); |
645 } | 651 } |
646 | 652 |
647 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild) | 653 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild) |
648 { | 654 { |
649 ASSERT(newChild); | 655 ASSERT(newChild); |
650 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re
parenting (and want DOM mutation events). | 656 ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle re
parenting (and want DOM mutation events). |
651 ASSERT(!newChild->isDocumentFragment()); | 657 ASSERT(!newChild->isDocumentFragment()); |
652 ASSERT(!isHTMLTemplateElement(this)); | 658 ASSERT(!isHTMLTemplateElement(this)); |
653 | 659 |
| 660 RefPtrWillBeRawPtr<Node> protect(this); |
| 661 |
654 if (document() != newChild->document()) | 662 if (document() != newChild->document()) |
655 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); | 663 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
656 | 664 |
657 Node* last = m_lastChild; | |
658 | |
659 { | 665 { |
660 NoEventDispatchAssertion assertNoEventDispatch; | 666 NoEventDispatchAssertion assertNoEventDispatch; |
661 ScriptForbiddenScope forbidScript; | 667 ScriptForbiddenScope forbidScript; |
662 | 668 |
663 treeScope().adoptIfNeeded(*newChild); | 669 treeScope().adoptIfNeeded(*newChild); |
664 appendChildCommon(*newChild); | 670 appendChildCommon(*newChild); |
665 newChild->updateAncestorConnectedSubframeCountForInsertion(); | 671 newChild->updateAncestorConnectedSubframeCountForInsertion(); |
666 ChildListMutationScope(*this).childAdded(*newChild); | 672 ChildListMutationScope(*this).childAdded(*newChild); |
667 } | 673 } |
668 | 674 |
669 childrenChanged(true, last, 0, 1); | 675 notifyNodeInserted(*newChild, ChildrenChangeSourceParser); |
670 notifyNodeInserted(*newChild); | |
671 } | 676 } |
672 | 677 |
673 void ContainerNode::notifyNodeInserted(Node& root) | 678 void ContainerNode::notifyNodeInserted(Node& root, ChildrenChangeSource source) |
674 { | 679 { |
675 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); | 680 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); |
676 | 681 |
677 InspectorInstrumentation::didInsertDOMNode(&root); | 682 InspectorInstrumentation::didInsertDOMNode(&root); |
678 | 683 |
679 RefPtrWillBeRawPtr<Node> protect(this); | 684 RefPtrWillBeRawPtr<Node> protect(this); |
680 RefPtrWillBeRawPtr<Node> protectNode(root); | 685 RefPtrWillBeRawPtr<Node> protectNode(root); |
681 | 686 |
682 NodeVector postInsertionNotificationTargets; | 687 NodeVector postInsertionNotificationTargets; |
683 notifyNodeInsertedInternal(root, postInsertionNotificationTargets); | 688 notifyNodeInsertedInternal(root, postInsertionNotificationTargets); |
684 | 689 |
| 690 // ShadowRoots are not real children, we don't need to tell host that it's |
| 691 // children changed when one is added. |
| 692 // FIXME: We should have a separate code path for ShadowRoot since it only |
| 693 // needs to call insertedInto and the rest of this logic is not needed. |
| 694 if (!root.isShadowRoot()) { |
| 695 childrenChanged(source == ChildrenChangeSourceParser, root.previousSibli
ng(), root.nextSibling(), 1); |
| 696 } |
| 697 |
685 for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) { | 698 for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) { |
686 Node* targetNode = postInsertionNotificationTargets[i].get(); | 699 Node* targetNode = postInsertionNotificationTargets[i].get(); |
687 if (targetNode->inDocument()) | 700 if (targetNode->inDocument()) |
688 targetNode->didNotifySubtreeInsertionsToDocument(); | 701 targetNode->didNotifySubtreeInsertionsToDocument(); |
689 } | 702 } |
690 } | 703 } |
691 | 704 |
692 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInser
tionNotificationTargets) | 705 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInser
tionNotificationTargets) |
693 { | 706 { |
694 NoEventDispatchAssertion assertNoEventDispatch; | 707 NoEventDispatchAssertion assertNoEventDispatch; |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 | 1099 |
1087 void ContainerNode::updateTreeAfterInsertion(Node& child) | 1100 void ContainerNode::updateTreeAfterInsertion(Node& child) |
1088 { | 1101 { |
1089 #if !ENABLE(OILPAN) | 1102 #if !ENABLE(OILPAN) |
1090 ASSERT(refCount()); | 1103 ASSERT(refCount()); |
1091 ASSERT(child.refCount()); | 1104 ASSERT(child.refCount()); |
1092 #endif | 1105 #endif |
1093 | 1106 |
1094 ChildListMutationScope(*this).childAdded(child); | 1107 ChildListMutationScope(*this).childAdded(child); |
1095 | 1108 |
1096 childrenChanged(false, child.previousSibling(), child.nextSibling(), 1); | |
1097 | |
1098 notifyNodeInserted(child); | 1109 notifyNodeInserted(child); |
1099 | 1110 |
1100 dispatchChildInsertionEvents(child); | 1111 dispatchChildInsertionEvents(child); |
1101 } | 1112 } |
1102 | 1113 |
1103 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const | 1114 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const |
1104 { | 1115 { |
1105 return rareData()->hasRestyleFlag(mask); | 1116 return rareData()->hasRestyleFlag(mask); |
1106 } | 1117 } |
1107 | 1118 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1286 return true; | 1297 return true; |
1287 | 1298 |
1288 if (node->isElementNode() && toElement(node)->shadow()) | 1299 if (node->isElementNode() && toElement(node)->shadow()) |
1289 return true; | 1300 return true; |
1290 | 1301 |
1291 return false; | 1302 return false; |
1292 } | 1303 } |
1293 #endif | 1304 #endif |
1294 | 1305 |
1295 } // namespace WebCore | 1306 } // namespace WebCore |
OLD | NEW |