diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt index 245ab49fc36c..b7afb5368705 100644 --- a/Source/WebCore/CMakeLists.txt +++ b/Source/WebCore/CMakeLists.txt @@ -2796,6 +2796,7 @@ set(WebCore_SOURCES style/RenderTreePosition.cpp style/RenderTreeUpdater.cpp style/RenderTreeUpdaterFirstLetter.cpp + style/RenderTreeUpdaterListItem.cpp style/StyleChange.cpp style/StyleFontSizeFunctions.cpp style/StyleInvalidator.cpp diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index 52d4eb79c7c4..75cbbf26d8d7 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,45 @@ +2017-08-18 Antti Koivisto + + Factor render tree mutation code from RenderListItem to RenderTreeUpdater + https://bugs.webkit.org/show_bug.cgi?id=175718 + + Reviewed by Andreas Kling. + + We already stopped doing layout time mutations. We can now move the code out too. + + * WebCore.xcodeproj/project.pbxproj: + * rendering/RenderListItem.cpp: + (WebCore::isHTMLListElement): + (WebCore::getParentOfFirstLineBox): Deleted. + (WebCore::firstNonMarkerChild): Deleted. + (WebCore::RenderListItem::updateMarkerRenderer): Deleted. + + Moved to RenderTreeUpdater::ListItem. + + * rendering/RenderListItem.h: + * rendering/RenderListMarker.cpp: + (WebCore::RenderListMarker::willBeDestroyed): + * rendering/TextAutoSizing.cpp: + (WebCore::TextAutoSizingValue::adjustTextNodeSizes): + * style/RenderTreeUpdater.cpp: + (WebCore::RenderTreeUpdater::pushParent): + (WebCore::RenderTreeUpdater::popParent): + (WebCore::RenderTreeUpdater::updateBeforeDescendants): + (WebCore::RenderTreeUpdater::updateAfterDescendants): + + Factor pre/post update into functions. + + (WebCore::RenderTreeUpdater::updateBeforeOrAfterPseudoElement): + * style/RenderTreeUpdater.h: + * style/RenderTreeUpdaterListItem.cpp: Added. + + Mutation functions move here. + + (WebCore::getParentOfFirstLineBox): + (WebCore::firstNonMarkerChild): + (WebCore::RenderTreeUpdater::ListItem::updateMarker): + * style/RenderTreeUpdaterListItem.h: Added. + 2017-08-18 Ms2ger [GTK] Show controls if a video element isn't allowed to play inline. diff --git a/Source/WebCore/rendering/RenderListItem.cpp b/Source/WebCore/rendering/RenderListItem.cpp index 5a39c3f4df3f..7ecf2538abf9 100644 --- a/Source/WebCore/rendering/RenderListItem.cpp +++ b/Source/WebCore/rendering/RenderListItem.cpp @@ -34,9 +34,6 @@ #include "RenderChildIterator.h" #include "RenderInline.h" #include "RenderListMarker.h" -#include "RenderMultiColumnFlowThread.h" -#include "RenderRuby.h" -#include "RenderTable.h" #include "RenderView.h" #include "StyleInheritedData.h" #if !ASSERT_DISABLED @@ -110,7 +107,7 @@ void RenderListItem::willBeRemovedFromTree() updateListMarkerNumbers(); } -static inline bool isHTMLListElement(const Node& node) +bool isHTMLListElement(const Node& node) { return is(node) || is(node); } @@ -226,35 +223,6 @@ void RenderListItem::updateValueNow() const m_isValueUpToDate = true; } -static RenderBlock* getParentOfFirstLineBox(RenderBlock& current, RenderObject& marker) -{ - bool inQuirksMode = current.document().inQuirksMode(); - for (auto& child : childrenOfType(current)) { - if (&child == &marker) - continue; - - if (child.isInline() && (!is(child) || current.generatesLineBoxesForInlineChild(&child))) - return ¤t; - - if (child.isFloating() || child.isOutOfFlowPositioned()) - continue; - - if (!is(child) || is(child) || is(child)) - break; - - if (is(child) && downcast(child).isWritingModeRoot()) - break; - - if (is(current) && inQuirksMode && child.node() && isHTMLListElement(*child.node())) - break; - - if (RenderBlock* lineBox = getParentOfFirstLineBox(downcast(child), marker)) - return lineBox; - } - - return nullptr; -} - void RenderListItem::updateValue() { if (!m_hasExplicitValue) { @@ -264,58 +232,6 @@ void RenderListItem::updateValue() } } -static RenderObject* firstNonMarkerChild(RenderBlock& parent) -{ - RenderObject* child = parent.firstChild(); - while (is(child)) - child = child->nextSibling(); - return child; -} - -void RenderListItem::updateMarkerRenderer() -{ - ASSERT_WITH_SECURITY_IMPLICATION(!view().layoutState()); - - if (style().listStyleType() == NoneListStyle && (!style().listStyleImage() || style().listStyleImage()->errorOccurred())) { - if (m_marker) { - m_marker->destroy(); - ASSERT(!m_marker); - } - return; - } - - auto newStyle = computeMarkerStyle(); - if (m_marker) - m_marker->setStyle(WTFMove(newStyle)); - else { - m_marker = createRenderer(*this, WTFMove(newStyle)).leakPtr(); - m_marker->initializeStyle(); - } - - RenderElement* currentParent = m_marker->parent(); - RenderBlock* newParent = getParentOfFirstLineBox(*this, *m_marker); - if (!newParent) { - // If the marker is currently contained inside an anonymous box, - // then we are the only item in that anonymous box (since no line box - // parent was found). It's ok to just leave the marker where it is - // in this case. - if (currentParent && currentParent->isAnonymousBlock()) - return; - if (multiColumnFlowThread()) - newParent = multiColumnFlowThread(); - else - newParent = this; - } - - if (newParent != currentParent) { - m_marker->removeFromParent(); - newParent->addChild(m_marker, firstNonMarkerChild(*newParent)); - // If current parent is an anonymous block that has lost all its children, destroy it. - if (currentParent && currentParent->isAnonymousBlock() && !currentParent->firstChild() && !downcast(*currentParent).continuation()) - currentParent->destroy(); - } -} - void RenderListItem::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; diff --git a/Source/WebCore/rendering/RenderListItem.h b/Source/WebCore/rendering/RenderListItem.h index ea552cde1af2..d4ba3fa68622 100644 --- a/Source/WebCore/rendering/RenderListItem.h +++ b/Source/WebCore/rendering/RenderListItem.h @@ -54,9 +54,10 @@ class RenderListItem final : public RenderBlockFlow { static void updateItemValuesForOrderedList(const HTMLOListElement&); static unsigned itemCountForOrderedList(const HTMLOListElement&); - void didDestroyListMarker() { m_marker = nullptr; } + RenderStyle computeMarkerStyle() const; - void updateMarkerRenderer(); + RenderListMarker* markerRenderer() { return m_marker; } + void setMarkerRenderer(RenderListMarker* marker) { m_marker = marker; } #if !ASSERT_DISABLED bool inLayout() const { return m_inLayout; } @@ -85,7 +86,6 @@ class RenderListItem final : public RenderBlockFlow { void updateValueNow() const; void explicitValueChanged(); - RenderStyle computeMarkerStyle() const; int m_explicitValue; RenderListMarker* m_marker; @@ -98,6 +98,8 @@ class RenderListItem final : public RenderBlockFlow { bool m_notInList : 1; }; +bool isHTMLListElement(const Node&); + } // namespace WebCore SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderListItem, isListItem()) diff --git a/Source/WebCore/rendering/RenderListMarker.cpp b/Source/WebCore/rendering/RenderListMarker.cpp index 150314dd63b7..5bb17b4034f6 100644 --- a/Source/WebCore/rendering/RenderListMarker.cpp +++ b/Source/WebCore/rendering/RenderListMarker.cpp @@ -1133,7 +1133,7 @@ RenderListMarker::~RenderListMarker() void RenderListMarker::willBeDestroyed() { - m_listItem.didDestroyListMarker(); + m_listItem.setMarkerRenderer(nullptr); if (m_image) m_image->removeClient(this); diff --git a/Source/WebCore/rendering/TextAutoSizing.cpp b/Source/WebCore/rendering/TextAutoSizing.cpp index b9d9b35dc00d..db44f41ba773 100644 --- a/Source/WebCore/rendering/TextAutoSizing.cpp +++ b/Source/WebCore/rendering/TextAutoSizing.cpp @@ -33,11 +33,11 @@ #include "FontCascade.h" #include "Logging.h" #include "RenderBlock.h" -#include "RenderListItem.h" #include "RenderListMarker.h" #include "RenderText.h" #include "RenderTextFragment.h" #include "RenderTreeUpdaterFirstLetter.h" +#include "RenderTreeUpdaterListItem.h" #include "StyleResolver.h" namespace WebCore { @@ -159,7 +159,7 @@ auto TextAutoSizingValue::adjustTextNodeSizes() -> StillHasNodes parentRenderer->setStyle(WTFMove(newParentStyle)); if (is(*parentRenderer)) - downcast(*parentRenderer).updateMarkerRenderer(); + RenderTreeUpdater::ListItem::updateMarker(downcast(*parentRenderer)); } for (auto& node : m_autoSizedNodes) { diff --git a/Source/WebCore/style/RenderTreeUpdater.cpp b/Source/WebCore/style/RenderTreeUpdater.cpp index 792937a2c4ef..7aace60c31d2 100644 --- a/Source/WebCore/style/RenderTreeUpdater.cpp +++ b/Source/WebCore/style/RenderTreeUpdater.cpp @@ -43,6 +43,7 @@ #include "RenderNamedFlowThread.h" #include "RenderQuote.h" #include "RenderTreeUpdaterFirstLetter.h" +#include "RenderTreeUpdaterListItem.h" #include "StyleResolver.h" #include "StyleTreeResolver.h" #include @@ -224,26 +225,15 @@ void RenderTreeUpdater::pushParent(Element& element, Style::Change changeType) { m_parentStack.append(Parent(element, changeType)); - updateBeforeOrAfterPseudoElement(element, BEFORE); + updateBeforeDescendants(element); } void RenderTreeUpdater::popParent() { auto& parent = m_parentStack.last(); + if (parent.element) + updateAfterDescendants(*parent.element, parent.styleChange); - if (parent.element) { - updateBeforeOrAfterPseudoElement(*parent.element, AFTER); - - if (auto* renderer = parent.element->renderer()) { - if (is(*renderer)) - FirstLetter::update(downcast(*renderer)); - if (is(*renderer)) - downcast(*renderer).updateMarkerRenderer(); - - if (parent.element->hasCustomStyleResolveCallbacks() && parent.styleChange == Style::Detach) - parent.element->didAttachRenderers(); - } - } m_parentStack.removeLast(); } @@ -255,6 +245,29 @@ void RenderTreeUpdater::popParentsToDepth(unsigned depth) popParent(); } +void RenderTreeUpdater::updateBeforeDescendants(Element& element) +{ + updateBeforeOrAfterPseudoElement(element, BEFORE); +} + +void RenderTreeUpdater::updateAfterDescendants(Element& element, Style::Change styleChange) +{ + updateBeforeOrAfterPseudoElement(element, AFTER); + + auto* renderer = element.renderer(); + if (!renderer) + return; + + // These functions do render tree mutations that require descendant renderers. + if (is(*renderer)) + FirstLetter::update(downcast(*renderer)); + if (is(*renderer)) + ListItem::updateMarker(downcast(*renderer)); + + if (element.hasCustomStyleResolveCallbacks() && styleChange == Style::Detach) + element.didAttachRenderers(); +} + static bool pseudoStyleCacheIsInvalid(RenderElement* renderer, RenderStyle* newStyle) { const RenderStyle& currentStyle = renderer->style(); @@ -571,7 +584,7 @@ void RenderTreeUpdater::updateBeforeOrAfterPseudoElement(Element& current, Pseud updateQuotesUpTo(&child); } if (is(*pseudoRenderer)) - downcast(*pseudoRenderer).updateMarkerRenderer(); + ListItem::updateMarker(downcast(*pseudoRenderer)); } void RenderTreeUpdater::tearDownRenderers(Element& root, TeardownType teardownType) diff --git a/Source/WebCore/style/RenderTreeUpdater.h b/Source/WebCore/style/RenderTreeUpdater.h index f808f0f4a0fd..2dd4cba1d02c 100644 --- a/Source/WebCore/style/RenderTreeUpdater.h +++ b/Source/WebCore/style/RenderTreeUpdater.h @@ -52,6 +52,7 @@ class RenderTreeUpdater { static void tearDownRenderer(Text&); class FirstLetter; + class ListItem; private: void updateRenderTree(ContainerNode& root); @@ -59,6 +60,8 @@ class RenderTreeUpdater { void updateElementRenderer(Element&, const Style::ElementUpdate&); void createRenderer(Element&, RenderStyle&&); void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node&); + void updateBeforeDescendants(Element&); + void updateAfterDescendants(Element&, Style::Change); void updateBeforeOrAfterPseudoElement(Element&, PseudoId); struct Parent { diff --git a/Source/WebCore/style/RenderTreeUpdaterListItem.cpp b/Source/WebCore/style/RenderTreeUpdaterListItem.cpp new file mode 100644 index 000000000000..5a4fcdbd801e --- /dev/null +++ b/Source/WebCore/style/RenderTreeUpdaterListItem.cpp @@ -0,0 +1,120 @@ +/** + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * Copyright (C) 2003-2006, 2010, 2017 Apple Inc. All rights reserved. + * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderTreeUpdaterListItem.h" + +#include "RenderChildIterator.h" +#include "RenderListMarker.h" +#include "RenderMultiColumnFlowThread.h" +#include "RenderRuby.h" +#include "RenderTable.h" + +namespace WebCore { + +static RenderBlock* getParentOfFirstLineBox(RenderBlock& current, RenderObject& marker) +{ + bool inQuirksMode = current.document().inQuirksMode(); + for (auto& child : childrenOfType(current)) { + if (&child == &marker) + continue; + + if (child.isInline() && (!is(child) || current.generatesLineBoxesForInlineChild(&child))) + return ¤t; + + if (child.isFloating() || child.isOutOfFlowPositioned()) + continue; + + if (!is(child) || is(child) || is(child)) + break; + + if (is(child) && downcast(child).isWritingModeRoot()) + break; + + if (is(current) && inQuirksMode && child.node() && isHTMLListElement(*child.node())) + break; + + if (RenderBlock* lineBox = getParentOfFirstLineBox(downcast(child), marker)) + return lineBox; + } + + return nullptr; +} + +static RenderObject* firstNonMarkerChild(RenderBlock& parent) +{ + RenderObject* child = parent.firstChild(); + while (is(child)) + child = child->nextSibling(); + return child; +} + +void RenderTreeUpdater::ListItem::updateMarker(RenderListItem& listItemRenderer) +{ + ASSERT_WITH_SECURITY_IMPLICATION(!listItemRenderer.view().layoutState()); + + auto& style = listItemRenderer.style(); + + if (style.listStyleType() == NoneListStyle && (!style.listStyleImage() || style.listStyleImage()->errorOccurred())) { + if (listItemRenderer.markerRenderer()) { + listItemRenderer.markerRenderer()->destroy(); + ASSERT(!listItemRenderer.markerRenderer()); + } + return; + } + + auto newStyle = listItemRenderer.computeMarkerStyle(); + auto* markerRenderer = listItemRenderer.markerRenderer(); + if (markerRenderer) + markerRenderer->setStyle(WTFMove(newStyle)); + else { + markerRenderer = WebCore::createRenderer(listItemRenderer, WTFMove(newStyle)).leakPtr(); + markerRenderer->initializeStyle(); + listItemRenderer.setMarkerRenderer(markerRenderer); + } + + RenderElement* currentParent = markerRenderer->parent(); + RenderBlock* newParent = getParentOfFirstLineBox(listItemRenderer, *markerRenderer); + if (!newParent) { + // If the marker is currently contained inside an anonymous box, + // then we are the only item in that anonymous box (since no line box + // parent was found). It's ok to just leave the marker where it is + // in this case. + if (currentParent && currentParent->isAnonymousBlock()) + return; + if (auto* multiColumnFlowThread = listItemRenderer.multiColumnFlowThread()) + newParent = multiColumnFlowThread; + else + newParent = &listItemRenderer; + } + + if (newParent != currentParent) { + markerRenderer->removeFromParent(); + newParent->addChild(markerRenderer, firstNonMarkerChild(*newParent)); + // If current parent is an anonymous block that has lost all its children, destroy it. + if (currentParent && currentParent->isAnonymousBlock() && !currentParent->firstChild() && !downcast(*currentParent).continuation()) + currentParent->destroy(); + } +} + +} diff --git a/Source/WebCore/style/RenderTreeUpdaterListItem.h b/Source/WebCore/style/RenderTreeUpdaterListItem.h new file mode 100644 index 000000000000..40b406398a4a --- /dev/null +++ b/Source/WebCore/style/RenderTreeUpdaterListItem.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "RenderListItem.h" +#include "RenderTreeUpdater.h" + +namespace WebCore { + +class RenderTreeUpdater::ListItem { +public: + static void updateMarker(RenderListItem&); +}; + +}