Modified: releases/WebKitGTK/webkit-2.12/Source/WebCore/style/StyleTreeResolver.cpp (197077 => 197078)
--- releases/WebKitGTK/webkit-2.12/Source/WebCore/style/StyleTreeResolver.cpp 2016-02-25 10:00:13 UTC (rev 197077)
+++ releases/WebKitGTK/webkit-2.12/Source/WebCore/style/StyleTreeResolver.cpp 2016-02-25 10:00:32 UTC (rev 197078)
@@ -112,8 +112,6 @@
: m_document(document)
{
ensurePlaceholderStyle(document);
-
- m_scopeStack.append(adoptRef(*new Scope(document)));
}
TreeResolver::Scope::Scope(Document& document)
@@ -130,6 +128,22 @@
{
}
+TreeResolver::Parent::Parent(Document& document, Change change)
+ : element(nullptr)
+ , style(*document.renderStyle())
+ , renderTreePosition(*document.renderView())
+ , change(change)
+{
+}
+
+TreeResolver::Parent::Parent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change)
+ : element(&element)
+ , style(style)
+ , renderTreePosition(renderTreePosition)
+ , change(change)
+{
+}
+
void TreeResolver::pushScope(ShadowRoot& shadowRoot)
{
m_scopeStack.append(adoptRef(*new Scope(shadowRoot, scope())));
@@ -425,20 +439,18 @@
static void resetStyleForNonRenderedDescendants(Element& current)
{
+ // FIXME: This is not correct with shadow trees. This should be done with ComposedTreeIterator.
ASSERT(!current.renderer());
bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
for (auto& child : childrenOfType<Element>(current)) {
ASSERT(!child.renderer());
- if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) {
- if (child.styleIsAffectedByPreviousSibling())
- child.setNeedsStyleRecalc();
+ bool affectedByPreviousSibling = child.styleIsAffectedByPreviousSibling() && elementNeedingStyleRecalcAffectsNextSiblingElementStyle;
+ if (child.needsStyleRecalc() || elementNeedingStyleRecalcAffectsNextSiblingElementStyle)
elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle();
- }
- if (child.needsStyleRecalc()) {
+ if (child.needsStyleRecalc() || affectedByPreviousSibling) {
child.resetComputedStyle();
child.clearNeedsStyleRecalc();
- elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle();
}
if (child.childNeedsStyleRecalc()) {
@@ -652,28 +664,32 @@
return false;
}
-Change TreeResolver::resolveLocally(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Change inheritedChange)
+Change TreeResolver::resolveElement(Element& current)
{
Change localChange = Detach;
RefPtr<RenderStyle> newStyle;
RefPtr<RenderStyle> currentStyle = current.renderStyle();
if (currentStyle && current.styleChangeType() != ReconstructRenderTree) {
- Ref<RenderStyle> style(styleForElement(current, inheritedStyle));
+ Ref<RenderStyle> style(styleForElement(current, parent().style));
newStyle = style.ptr();
localChange = determineChange(*currentStyle, style);
}
if (localChange == Detach) {
if (current.renderer() || current.isNamedFlowContentNode())
detachRenderTree(current, ReattachDetach);
- createRenderTreeRecursively(current, inheritedStyle, renderTreePosition, newStyle.release());
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ else if (is<HTMLSlotElement>(current))
+ detachRenderTree(current, ReattachDetach);
+#endif
+ createRenderTreeRecursively(current, parent().style, parent().renderTreePosition, newStyle.release());
invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(current);
return Detach;
}
if (RenderElement* renderer = current.renderer()) {
- if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (inheritedChange == Force && renderer->requiresForcedStyleRecalcPropagation()) || current.styleChangeType() == SyntheticStyleChange)
+ if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (parent().change == Force && renderer->requiresForcedStyleRecalcPropagation()) || current.styleChangeType() == SyntheticStyleChange)
renderer->setAnimatableStyle(*newStyle, current.styleChangeType() == SyntheticStyleChange ? StyleDifferenceRecompositeLayer : StyleDifferenceEqual);
else if (current.needsStyleRecalc()) {
// Although no change occurred, we use the new style so that the cousin style sharing code won't get
@@ -689,10 +705,8 @@
scope().styleResolver.invalidateMatchedPropertiesCache();
return Force;
}
- if (inheritedChange == Force)
+ if (parent().change == Force || current.styleChangeType() >= FullStyleChange)
return Force;
- if (current.styleChangeType() >= FullStyleChange)
- return Force;
return localChange;
}
@@ -716,48 +730,28 @@
invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text);
}
-void TreeResolver::resolveChildAtShadowBoundary(Node& child, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Style::Change change)
+void TreeResolver::resolveBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId, RenderTreePosition& renderTreePosition)
{
- if (auto* renderer = child.renderer())
- renderTreePosition.invalidateNextSibling(*renderer);
-
- if (is<Text>(child) && child.needsStyleRecalc()) {
- resolveTextNode(downcast<Text>(child), renderTreePosition);
+ if (!current.renderer())
return;
+ PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId);
+ if (!existingPseudoElement) {
+ createRenderTreeForBeforeOrAfterPseudoElement(current, pseudoId, renderTreePosition);
+ return;
}
- if (is<Element>(child))
- resolveRecursively(downcast<Element>(child), inheritedStyle, renderTreePosition, change);
-}
-void TreeResolver::resolveShadowTree(Style::Change change, RenderStyle& inheritedStyle)
-{
- ASSERT(scope().shadowRoot);
- auto& host = *scope().shadowRoot->host();
- ASSERT(host.renderer());
- if (scope().shadowRoot->styleChangeType() >= FullStyleChange)
- change = Force;
- RenderTreePosition renderTreePosition(*host.renderer());
- for (auto* child = scope().shadowRoot->firstChild(); child; child = child->nextSibling())
- resolveChildAtShadowBoundary(*child, inheritedStyle, renderTreePosition, change);
+ if (existingPseudoElement->renderer())
+ renderTreePosition.invalidateNextSibling(*existingPseudoElement->renderer());
- scope().shadowRoot->clearNeedsStyleRecalc();
- scope().shadowRoot->clearChildNeedsStyleRecalc();
-}
+ if (change == NoChange && !existingPseudoElement->needsStyleRecalc())
+ return;
-void TreeResolver::resolveBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId, RenderTreePosition& renderTreePosition)
-{
- ASSERT(current.renderer());
- if (PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId)) {
- if (existingPseudoElement->renderer())
- renderTreePosition.invalidateNextSibling(*existingPseudoElement->renderer());
-
- if (needsPseudoElement(current, pseudoId))
- resolveRecursively(*existingPseudoElement, current.renderer()->style(), renderTreePosition, current.needsStyleRecalc() ? Force : change);
- else
- clearBeforeOrAfterPseudoElement(current, pseudoId);
- return;
- }
- createRenderTreeForBeforeOrAfterPseudoElement(current, pseudoId, renderTreePosition);
+ if (needsPseudoElement(current, pseudoId)) {
+ auto change = resolveElement(*existingPseudoElement);
+ existingPseudoElement->didRecalcStyle(change);
+ existingPseudoElement->clearNeedsStyleRecalc();
+ } else
+ clearBeforeOrAfterPseudoElement(current, pseudoId);
}
#if PLATFORM(IOS)
@@ -814,112 +808,155 @@
};
#endif // PLATFORM(IOS)
-void TreeResolver::resolveChildren(Element& current, RenderStyle& inheritedStyle, Change change, RenderTreePosition& childRenderTreePosition)
+void TreeResolver::pushParent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change)
{
- SelectorFilterPusher selectorFilterPusher(scope().selectorFilter, current, SelectorFilterPusher::NoPush);
+ scope().selectorFilter.pushParent(&element);
- bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
- for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
- if (RenderObject* childRenderer = child->renderer())
- childRenderTreePosition.invalidateNextSibling(*childRenderer);
- if (is<Text>(*child) && child->needsStyleRecalc()) {
- resolveTextNode(downcast<Text>(*child), childRenderTreePosition);
- continue;
- }
- if (!is<Element>(*child))
- continue;
+ Parent parent(element, style, renderTreePosition, change);
- Element& childElement = downcast<Element>(*child);
- if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) {
- if (childElement.styleIsAffectedByPreviousSibling())
- childElement.setNeedsStyleRecalc();
- elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
- } else if (childElement.needsStyleRecalc())
- elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
- if (change >= Inherit || childElement.childNeedsStyleRecalc() || childElement.needsStyleRecalc()) {
- selectorFilterPusher.push();
- resolveRecursively(childElement, inheritedStyle, childRenderTreePosition, change);
- }
+ if (auto* shadowRoot = element.shadowRoot()) {
+ pushScope(*shadowRoot);
+ parent.didPushScope = true;
}
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ else if (is<HTMLSlotElement>(element) && downcast<HTMLSlotElement>(element).assignedNodes()) {
+ pushEnclosingScope();
+ parent.didPushScope = true;
+ }
+#endif
+
+ m_parentStack.append(WTFMove(parent));
+
+ resolveBeforeOrAfterPseudoElement(element, change, BEFORE, renderTreePosition);
}
-#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
-void TreeResolver::resolveSlotAssignees(HTMLSlotElement& slot, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Change change)
+void TreeResolver::popParent()
{
- if (auto* assignedNodes = slot.assignedNodes()) {
- pushEnclosingScope();
- for (auto* child : *assignedNodes)
- resolveChildAtShadowBoundary(*child, inheritedStyle, renderTreePosition, change);
+ auto& parentElement = *parent().element;
+
+ resolveBeforeOrAfterPseudoElement(parentElement, parent().change, AFTER, parent().renderTreePosition);
+
+ parentElement.clearNeedsStyleRecalc();
+ parentElement.clearChildNeedsStyleRecalc();
+
+ if (parent().didPushScope)
popScope();
- } else
- resolveChildren(slot, inheritedStyle, change, renderTreePosition);
- slot.clearNeedsStyleRecalc();
- slot.clearChildNeedsStyleRecalc();
+ scope().selectorFilter.popParent();
+
+ m_parentStack.removeLast();
}
-#endif
-void TreeResolver::resolveRecursively(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Change change)
+void TreeResolver::popParentsToDepth(unsigned depth)
{
- ASSERT(change != Detach);
+ ASSERT(depth);
+ ASSERT(m_parentStack.size() >= depth);
-#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
- if (is<HTMLSlotElement>(current)) {
- resolveSlotAssignees(downcast<HTMLSlotElement>(current), inheritedStyle, renderTreePosition, change);
- return;
- }
-#endif
+ while (m_parentStack.size() > depth)
+ popParent();
+}
- if (current.hasCustomStyleResolveCallbacks()) {
- if (!current.willRecalcStyle(change))
- return;
- }
+void TreeResolver::resolveComposedTree()
+{
+ ASSERT(m_parentStack.size() == 1);
+ ASSERT(m_scopeStack.size() == 1);
+ auto descendants = composedTreeDescendants(m_document);
+ auto it = descendants.begin();
+ auto end = descendants.end();
+
+ // FIXME: SVG <use> element may cause tree mutations during style recalc.
+ it.dropAssertions();
+
+ while (it != end) {
+ popParentsToDepth(it.depth());
+
+ auto& node = *it;
+ auto& parent = this->parent();
+
+ ASSERT(node.containingShadowRoot() == scope().shadowRoot);
+ ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot());
+
+ if (auto* existingRenderer = node.renderer())
+ parent.renderTreePosition.invalidateNextSibling(*existingRenderer);
+
+ if (is<Text>(node)) {
+ if (node.needsStyleRecalc())
+ resolveTextNode(downcast<Text>(node), parent.renderTreePosition);
+ it.traverseNextSkippingChildren();
+ continue;
+ }
+
+ auto& element = downcast<Element>(node);
+
+ // FIXME: We should deal with this during style invalidation.
+ bool affectedByPreviousSibling = element.styleIsAffectedByPreviousSibling() && parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle;
+ if (element.needsStyleRecalc() || parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle)
+ parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle();
+
+ Change change = NoChange;
+
+ bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || affectedByPreviousSibling;
+ if (shouldResolve) {
#if PLATFORM(IOS)
- CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(¤t, current.renderStyle());
+ CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&element, element.renderStyle());
#endif
+ element.resetComputedStyle();
- if (change > NoChange || current.needsStyleRecalc())
- current.resetComputedStyle();
+ if (element.hasCustomStyleResolveCallbacks()) {
+ if (!element.willRecalcStyle(parent.change)) {
+ it.traverseNextSkippingChildren();
+ continue;
+ }
+ }
+ change = resolveElement(element);
- if (change >= Inherit || current.needsStyleRecalc())
- change = resolveLocally(current, inheritedStyle, renderTreePosition, change);
+ element.clearNeedsStyleRecalc();
- auto* renderer = current.renderer();
+ if (element.hasCustomStyleResolveCallbacks())
+ element.didRecalcStyle(change);
- if (change != Detach && renderer) {
- auto* shadowRoot = current.shadowRoot();
- if (shadowRoot && (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc())) {
- SelectorFilterPusher selectorFilterPusher(scope().selectorFilter, current);
+ if (change == Detach) {
+ it.traverseNextSkippingChildren();
+ continue;
+ }
- pushScope(*shadowRoot);
- resolveShadowTree(change, renderer->style());
- popScope();
+ if (affectedByPreviousSibling)
+ change = Force;
}
- RenderTreePosition childRenderTreePosition(*renderer);
- resolveBeforeOrAfterPseudoElement(current, change, BEFORE, childRenderTreePosition);
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ if (is<HTMLSlotElement>(element)) {
+ // FIXME: We should compute style for the slot and use it as parent style.
+ // FIXME: This should be display:contents check.
+ // Duplicate the style and render tree position from the current context.
+ pushParent(element, parent.style.get(), parent.renderTreePosition, change);
+ it.traverseNext();
+ continue;
+ }
+#endif
+ auto* renderer = element.renderer();
+ if (!renderer) {
+ resetStyleForNonRenderedDescendants(element);
+ element.clearChildNeedsStyleRecalc();
+ }
- bool skipChildren = shadowRoot;
- if (!skipChildren)
- resolveChildren(current, renderer->style(), change, childRenderTreePosition);
+ bool shouldIterateChildren = renderer && (element.childNeedsStyleRecalc() || change != NoChange);
+ if (!shouldIterateChildren) {
+ it.traverseNextSkippingChildren();
+ continue;
+ }
- resolveBeforeOrAfterPseudoElement(current, change, AFTER, childRenderTreePosition);
+ pushParent(element, renderer->style(), RenderTreePosition(*renderer), change);
+
+ it.traverseNext();
}
- if (change != Detach && !renderer)
- resetStyleForNonRenderedDescendants(current);
- current.clearNeedsStyleRecalc();
- current.clearChildNeedsStyleRecalc();
-
- if (current.hasCustomStyleResolveCallbacks())
- current.didRecalcStyle(change);
+ popParentsToDepth(1);
}
void TreeResolver::resolve(Change change)
{
- ASSERT(!scope().shadowRoot);
-
auto& renderView = *m_document.renderView();
Element* documentElement = m_document.documentElement();
@@ -928,15 +965,21 @@
if (change != Force && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
return;
+ m_scopeStack.append(adoptRef(*new Scope(m_document)));
+
// Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
renderView.setUsesFirstLineRules(renderView.usesFirstLineRules() || scope().styleResolver.usesFirstLineRules());
renderView.setUsesFirstLetterRules(renderView.usesFirstLetterRules() || scope().styleResolver.usesFirstLetterRules());
- RenderTreePosition renderTreePosition(renderView);
- resolveRecursively(*documentElement, *m_document.renderStyle(), renderTreePosition, change);
+ m_parentStack.append(Parent(m_document, change));
+ resolveComposedTree();
+
renderView.setUsesFirstLineRules(scope().styleResolver.usesFirstLineRules());
renderView.setUsesFirstLetterRules(scope().styleResolver.usesFirstLetterRules());
+
+ m_parentStack.clear();
+ m_scopeStack.clear();
}
void detachRenderTree(Element& element)
Modified: releases/WebKitGTK/webkit-2.12/Source/WebCore/style/StyleTreeResolver.h (197077 => 197078)
--- releases/WebKitGTK/webkit-2.12/Source/WebCore/style/StyleTreeResolver.h 2016-02-25 10:00:13 UTC (rev 197077)
+++ releases/WebKitGTK/webkit-2.12/Source/WebCore/style/StyleTreeResolver.h 2016-02-25 10:00:32 UTC (rev 197078)
@@ -27,6 +27,7 @@
#define StyleTreeResolver_h
#include "RenderStyleConstants.h"
+#include "RenderTreePosition.h"
#include "SelectorFilter.h"
#include "StyleChange.h"
#include "StyleSharingResolver.h"
@@ -41,7 +42,6 @@
class HTMLSlotElement;
class Node;
class RenderStyle;
-class RenderTreePosition;
class Settings;
class ShadowRoot;
class StyleResolver;
@@ -56,14 +56,10 @@
void resolve(Change);
private:
- void resolveShadowTree(Change, RenderStyle& inheritedStyle);
-
Ref<RenderStyle> styleForElement(Element&, RenderStyle& inheritedStyle);
- void resolveRecursively(Element&, RenderStyle& inheritedStyle, RenderTreePosition&, Change);
- Change resolveLocally(Element&, RenderStyle& inheritedStyle, RenderTreePosition&, Change inheritedChange);
- void resolveChildren(Element&, RenderStyle&, Change, RenderTreePosition&);
- void resolveChildAtShadowBoundary(Node&, RenderStyle& inheritedStyle, RenderTreePosition&, Change);
+ void resolveComposedTree();
+ Change resolveElement(Element&);
void resolveBeforeOrAfterPseudoElement(Element&, Change, PseudoId, RenderTreePosition&);
void createRenderTreeRecursively(Element&, RenderStyle&, RenderTreePosition&, RefPtr<RenderStyle>&& resolvedStyle);
@@ -73,7 +69,6 @@
void createRenderTreeForShadowRoot(ShadowRoot&);
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
- void resolveSlotAssignees(HTMLSlotElement&, RenderStyle& inheritedStyle, RenderTreePosition&, Change);
void createRenderTreeForSlotAssignees(HTMLSlotElement&, RenderStyle& inheritedStyle, RenderTreePosition&);
#endif
@@ -87,13 +82,33 @@
Scope(Document&);
Scope(ShadowRoot&, Scope& enclosingScope);
};
+
+ struct Parent {
+ Element* element;
+ Ref<RenderStyle> style;
+ RenderTreePosition renderTreePosition;
+ Change change;
+ bool didPushScope { false };
+ bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle { false };
+
+ Parent(Document&, Change);
+ Parent(Element&, RenderStyle&, RenderTreePosition, Change);
+ };
+
Scope& scope() { return m_scopeStack.last(); }
+ Parent& parent() { return m_parentStack.last(); }
+
void pushScope(ShadowRoot&);
void pushEnclosingScope();
void popScope();
+ void pushParent(Element&, RenderStyle&, RenderTreePosition, Change);
+ void popParent();
+ void popParentsToDepth(unsigned depth);
+
Document& m_document;
Vector<Ref<Scope>, 4> m_scopeStack;
+ Vector<Parent, 32> m_parentStack;
};
void detachRenderTree(Element&);