1 /* 2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. 3 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 13 * 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. 25 */ 26 27 #include "config.h" 28 #include "core/rendering/RenderObjectChildList.h" 29 30 #include "core/accessibility/AXObjectCache.h" 31 #include "core/rendering/RenderCounter.h" 32 #include "core/rendering/RenderObject.h" 33 #include "core/rendering/RenderView.h" 34 #include "core/rendering/style/RenderStyle.h" 35 36 namespace WebCore { 37 38 void RenderObjectChildList::destroyLeftoverChildren() 39 { 40 while (firstChild()) { 41 if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == FIRST_LETTER && !firstChild()->isText())) 42 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. 43 else if (firstChild()->isRunIn() && firstChild()->node()) { 44 firstChild()->node()->setRenderer(0); 45 firstChild()->node()->setNeedsStyleRecalc(); 46 firstChild()->destroy(); 47 } else { 48 // 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. 49 if (firstChild()->node()) 50 firstChild()->node()->setRenderer(0); 51 firstChild()->destroy(); 52 } 53 } 54 } 55 56 RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool notifyRenderer) 57 { 58 ASSERT(oldChild->parent() == owner); 59 60 if (oldChild->isFloatingOrOutOfFlowPositioned()) 61 toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists(); 62 63 // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or 64 // that a positioned child got yanked). We also repaint, so that the area exposed when the child 65 // disappears gets repainted properly. 66 if (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) { 67 oldChild->setNeedsLayoutAndPrefWidthsRecalc(); 68 // We only repaint |oldChild| if we have a RenderLayer as its visual overflow may not be tracked by its parent. 69 if (oldChild->isBody()) 70 owner->view()->repaint(); 71 else 72 oldChild->repaint(); 73 } 74 75 // If we have a line box wrapper, delete it. 76 if (oldChild->isBox()) 77 toRenderBox(oldChild)->deleteLineBoxWrapper(); 78 79 // If oldChild is the start or end of the selection, then clear the selection to 80 // avoid problems of invalid pointers. 81 // FIXME: The FrameSelection should be responsible for this when it 82 // is notified of DOM mutations. 83 if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder()) 84 owner->view()->clearSelection(); 85 86 if (!owner->documentBeingDestroyed() && notifyRenderer) 87 oldChild->willBeRemovedFromTree(); 88 89 // WARNING: There should be no code running between willBeRemovedFromTree and the actual removal below. 90 // This is needed to avoid race conditions where willBeRemovedFromTree would dirty the tree's structure 91 // and the code running here would force an untimely rebuilding, leaving |oldChild| dangling. 92 93 if (oldChild->previousSibling()) 94 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling()); 95 if (oldChild->nextSibling()) 96 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling()); 97 98 if (firstChild() == oldChild) 99 setFirstChild(oldChild->nextSibling()); 100 if (lastChild() == oldChild) 101 setLastChild(oldChild->previousSibling()); 102 103 oldChild->setPreviousSibling(0); 104 oldChild->setNextSibling(0); 105 oldChild->setParent(0); 106 107 // rendererRemovedFromTree walks the whole subtree. We can improve performance 108 // by skipping this step when destroying the entire tree. 109 if (!owner->documentBeingDestroyed()) 110 RenderCounter::rendererRemovedFromTree(oldChild); 111 112 if (AXObjectCache* cache = owner->document()->existingAXObjectCache()) 113 cache->childrenChanged(owner); 114 115 return oldChild; 116 } 117 118 void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* newChild, RenderObject* beforeChild, bool notifyRenderer) 119 { 120 ASSERT(!newChild->parent()); 121 ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell())); 122 123 while (beforeChild && beforeChild->parent() && beforeChild->parent() != owner) 124 beforeChild = beforeChild->parent(); 125 126 // This should never happen, but if it does prevent render tree corruption 127 // where child->parent() ends up being owner but child->nextSibling()->parent() 128 // is not owner. 129 if (beforeChild && beforeChild->parent() != owner) { 130 ASSERT_NOT_REACHED(); 131 return; 132 } 133 134 newChild->setParent(owner); 135 136 if (firstChild() == beforeChild) 137 setFirstChild(newChild); 138 139 if (beforeChild) { 140 RenderObject* previousSibling = beforeChild->previousSibling(); 141 if (previousSibling) 142 previousSibling->setNextSibling(newChild); 143 newChild->setPreviousSibling(previousSibling); 144 newChild->setNextSibling(beforeChild); 145 beforeChild->setPreviousSibling(newChild); 146 } else { 147 if (lastChild()) 148 lastChild()->setNextSibling(newChild); 149 newChild->setPreviousSibling(lastChild()); 150 setLastChild(newChild); 151 } 152 153 if (!owner->documentBeingDestroyed() && notifyRenderer) 154 newChild->insertedIntoTree(); 155 156 if (!owner->documentBeingDestroyed()) { 157 RenderCounter::rendererSubtreeAttached(newChild); 158 } 159 160 newChild->setNeedsLayoutAndPrefWidthsRecalc(); 161 if (!owner->normalChildNeedsLayout()) 162 owner->setChildNeedsLayout(); // We may supply the static position for an absolute positioned child. 163 164 if (AXObjectCache* cache = owner->document()->axObjectCache()) 165 cache->childrenChanged(owner); 166 } 167 168 } // namespace WebCore 169