2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "core/rendering/RenderObjectChildList.h"
30 #include "core/accessibility/AXObjectCache.h"
31 #include "core/rendering/RenderCounter.h"
32 #include "core/rendering/RenderLayer.h"
33 #include "core/rendering/RenderObject.h"
34 #include "core/rendering/RenderView.h"
35 #include "core/rendering/style/RenderStyle.h"
39 void RenderObjectChildList::trace(Visitor* visitor)
41 visitor->trace(m_firstChild);
42 visitor->trace(m_lastChild);
45 void RenderObjectChildList::destroyLeftoverChildren()
47 while (firstChild()) {
48 if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == FIRST_LETTER && !firstChild()->isText())) {
49 firstChild()->remove(); // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
51 // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
52 if (firstChild()->node())
53 firstChild()->node()->setRenderer(0);
54 firstChild()->destroy();
59 RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool notifyRenderer)
61 ASSERT(oldChild->parent() == owner);
63 if (oldChild->isFloatingOrOutOfFlowPositioned())
64 toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();
67 // FIXME: We should not be allowing paint invalidation during layout. crbug.com/336250
68 AllowPaintInvalidationScope scoper(owner->frameView());
70 // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
71 // that a positioned child got yanked). We also issue paint invalidations, so that the area exposed when the child
72 // disappears gets paint invalidated properly.
73 if (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
74 oldChild->setNeedsLayoutAndPrefWidthsRecalc();
75 invalidatePaintOnRemoval(*oldChild);
79 // If we have a line box wrapper, delete it.
80 if (oldChild->isBox())
81 toRenderBox(oldChild)->deleteLineBoxWrapper();
83 // If oldChild is the start or end of the selection, then clear the selection to
84 // avoid problems of invalid pointers.
85 // FIXME: The FrameSelection should be responsible for this when it
86 // is notified of DOM mutations.
87 if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
88 owner->view()->clearSelection();
90 if (!owner->documentBeingDestroyed() && notifyRenderer)
91 oldChild->willBeRemovedFromTree();
93 // WARNING: There should be no code running between willBeRemovedFromTree and the actual removal below.
94 // This is needed to avoid race conditions where willBeRemovedFromTree would dirty the tree's structure
95 // and the code running here would force an untimely rebuilding, leaving |oldChild| dangling.
97 if (oldChild->previousSibling())
98 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
99 if (oldChild->nextSibling())
100 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
102 if (firstChild() == oldChild)
103 setFirstChild(oldChild->nextSibling());
104 if (lastChild() == oldChild)
105 setLastChild(oldChild->previousSibling());
107 oldChild->setPreviousSibling(0);
108 oldChild->setNextSibling(0);
109 oldChild->setParent(0);
111 // rendererRemovedFromTree walks the whole subtree. We can improve performance
112 // by skipping this step when destroying the entire tree.
113 if (!owner->documentBeingDestroyed())
114 RenderCounter::rendererRemovedFromTree(oldChild);
116 if (AXObjectCache* cache = owner->document().existingAXObjectCache())
117 cache->childrenChanged(owner);
122 void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* newChild, RenderObject* beforeChild, bool notifyRenderer)
124 ASSERT(!newChild->parent());
125 ASSERT(!owner->isRenderBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
127 while (beforeChild && beforeChild->parent() && beforeChild->parent() != owner)
128 beforeChild = beforeChild->parent();
130 // This should never happen, but if it does prevent render tree corruption
131 // where child->parent() ends up being owner but child->nextSibling()->parent()
133 if (beforeChild && beforeChild->parent() != owner) {
134 ASSERT_NOT_REACHED();
138 newChild->setParent(owner);
140 if (firstChild() == beforeChild)
141 setFirstChild(newChild);
144 RenderObject* previousSibling = beforeChild->previousSibling();
146 previousSibling->setNextSibling(newChild);
147 newChild->setPreviousSibling(previousSibling);
148 newChild->setNextSibling(beforeChild);
149 beforeChild->setPreviousSibling(newChild);
152 lastChild()->setNextSibling(newChild);
153 newChild->setPreviousSibling(lastChild());
154 setLastChild(newChild);
157 if (!owner->documentBeingDestroyed() && notifyRenderer)
158 newChild->insertedIntoTree();
160 if (!owner->documentBeingDestroyed()) {
161 RenderCounter::rendererSubtreeAttached(newChild);
164 newChild->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
165 if (!owner->normalChildNeedsLayout())
166 owner->setChildNeedsLayout(); // We may supply the static position for an absolute positioned child.
168 if (AXObjectCache* cache = owner->document().axObjectCache())
169 cache->childrenChanged(owner);
172 void RenderObjectChildList::invalidatePaintOnRemoval(const RenderObject& oldChild)
174 if (!oldChild.isRooted())
176 if (oldChild.isBody()) {
177 oldChild.view()->setShouldDoFullPaintInvalidation(true);
180 if (oldChild.isText()) {
181 oldChild.parent()->setShouldDoFullPaintInvalidation(true);
184 DisableCompositingQueryAsserts disabler;
185 oldChild.invalidatePaintUsingContainer(oldChild.containerForPaintInvalidation(), oldChild.previousPaintInvalidationRect(), InvalidationRendererRemoval);