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