Index: third_party/WebKit/Source/core/dom/Element.cpp |
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp |
index 4b146314627f4c71e8e39040cffaf7eb002c7094..6790cf7791ffe71b191459ede23b223a946b97e8 100644 |
--- a/third_party/WebKit/Source/core/dom/Element.cpp |
+++ b/third_party/WebKit/Source/core/dom/Element.cpp |
@@ -1574,7 +1574,8 @@ const AtomicString Element::imageSourceURL() const { |
} |
bool Element::layoutObjectIsNeeded(const ComputedStyle& style) { |
- return style.display() != EDisplay::None; |
+ return style.display() != EDisplay::None && |
+ style.display() != EDisplay::Contents; |
} |
LayoutObject* Element::createLayoutObject(const ComputedStyle& style) { |
@@ -1715,9 +1716,15 @@ void Element::attachLayoutTree(const AttachContext& context) { |
data->clearComputedStyle(); |
} |
- if (!isActiveSlotOrActiveInsertionPoint()) |
- LayoutTreeBuilderForElement(*this, context.resolvedStyle) |
- .createLayoutObjectIfNeeded(); |
+ if (!isActiveSlotOrActiveInsertionPoint()) { |
+ LayoutTreeBuilderForElement builder(*this, context.resolvedStyle); |
+ builder.createLayoutObjectIfNeeded(); |
+ |
+ if (ComputedStyle* style = builder.resolvedStyle()) { |
+ if (!layoutObject() && shouldStoreNonLayoutObjectComputedStyle(*style)) |
+ storeNonLayoutObjectComputedStyle(style); |
+ } |
+ } |
addCallbackSelectors(); |
@@ -1893,8 +1900,28 @@ void Element::recalcStyle(StyleRecalcChange change, Text* nextTextSibling) { |
if (change >= IndependentInherit || needsStyleRecalc()) { |
if (hasRareData()) { |
ElementRareData* data = elementRareData(); |
- if (change != IndependentInherit) |
- data->clearComputedStyle(); |
+ if (change != IndependentInherit) { |
+ // We keep the old computed style around for display: contents, option |
+ // and optgroup. This way we can call stylePropagationDiff accurately. |
+ // |
+ // We could clear it always, but we'd have more expensive restyles for |
+ // children. |
+ // |
+ // Note that we can't just keep stored other kind of non-layout object |
+ // computed style (like the one that gets set when getComputedStyle is |
+ // called on a display: none element), because that is a sizable memory |
+ // hit. |
+ // |
+ // Also, we don't want to leave a stale computed style, which may happen |
+ // if we don't end up calling recalcOwnStyle because there's no parent |
+ // style. |
+ const ComputedStyle* nonLayoutStyle = nonLayoutObjectComputedStyle(); |
+ if (!nonLayoutStyle || |
+ !shouldStoreNonLayoutObjectComputedStyle(*nonLayoutStyle) || |
+ !parentComputedStyle()) { |
+ data->clearComputedStyle(); |
+ } |
+ } |
if (change >= IndependentInherit) { |
if (ElementAnimations* elementAnimations = data->elementAnimations()) |
@@ -2016,6 +2043,9 @@ StyleRecalcChange Element::recalcOwnStyle(StyleRecalcChange change, |
// https://codereview.chromium.org/30453002/ |
layoutObject->setStyleInternal(newStyle.get()); |
} |
+ } else if (localChange != NoChange && |
+ shouldStoreNonLayoutObjectComputedStyle(*newStyle)) { |
+ storeNonLayoutObjectComputedStyle(newStyle); |
} |
if (getStyleChangeType() >= SubtreeStyleChange) |
@@ -3173,15 +3203,49 @@ const ComputedStyle* Element::ensureComputedStyle( |
elementStyle->getCachedPseudoStyle(pseudoElementSpecifier)) |
return pseudoElementStyle; |
+ // TODO(ecobos): Passing two times elementStyle may be wrong, though we don't |
+ // support display: contents elements' pseudo-elements yet, so this is not a |
+ // problem for now. |
RefPtr<ComputedStyle> result = |
document().ensureStyleResolver().pseudoStyleForElement( |
this, PseudoStyleRequest(pseudoElementSpecifier, |
PseudoStyleRequest::ForComputedStyle), |
- elementStyle); |
+ elementStyle, elementStyle); |
DCHECK(result); |
return elementStyle->addCachedPseudoStyle(result.release()); |
} |
+const ComputedStyle* Element::nonLayoutObjectComputedStyle() const { |
+ if (layoutObject() || !hasRareData()) |
+ return nullptr; |
+ |
+ return elementRareData()->computedStyle(); |
+} |
+ |
+bool Element::hasDisplayContentsStyle() const { |
+ if (const ComputedStyle* style = nonLayoutObjectComputedStyle()) |
+ return style->display() == EDisplay::Contents; |
+ return false; |
+} |
+ |
+bool Element::shouldStoreNonLayoutObjectComputedStyle( |
+ const ComputedStyle& style) const { |
+#if DCHECK_IS_ON() |
+ if (style.display() == EDisplay::Contents) |
+ DCHECK(!layoutObject()); |
+#endif |
+ |
+ return style.display() == EDisplay::Contents || |
+ isHTMLOptGroupElement(*this) || isHTMLOptionElement(*this); |
+} |
+ |
+void Element::storeNonLayoutObjectComputedStyle( |
+ PassRefPtr<ComputedStyle> style) { |
+ DCHECK(style); |
+ DCHECK(shouldStoreNonLayoutObjectComputedStyle(*style)); |
+ ensureElementRareData().setComputedStyle(std::move(style)); |
+} |
+ |
AtomicString Element::computeInheritedLanguage() const { |
const Node* n = this; |
AtomicString value; |