Chromium Code Reviews| 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 741ab09deb5911caef748d874430ff864557ec97..913df166d94bd8bcf94ec2d50f10d93f3ea13abb 100644 |
| --- a/third_party/WebKit/Source/core/dom/Element.cpp |
| +++ b/third_party/WebKit/Source/core/dom/Element.cpp |
| @@ -1529,7 +1529,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) { |
| @@ -1667,9 +1668,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(); |
| @@ -1692,6 +1699,25 @@ void Element::attachLayoutTree(const AttachContext& context) { |
| ContainerNode::attachLayoutTree(context); |
| + // Quite unfortunately, if we're a display: contents node reattaching our |
| + // subtree we need to reattach the parent's *after* attaching all our |
| + // children. We might be able to be more granular here, but otherwise we don't |
| + // always properly rebuild the layout tree due to anonymous boxes, for |
| + // example. See css-display-3/display-contents-reattachment.html, which fails |
| + // without this, for example, due to misplaced flex anonymous blocks. |
| + // |
| + // Also, don't do it if we're a pseudo-element, because it's pointless and |
| + // causes infinite recursion if the parent doesn't have display: contents. |
| + // |
| + // Finally, don't do it also if our parent is the document, since it's also |
| + // pointless, and it asserts when detached. |
| + if (hasDisplayContentsStyle() && !isPseudoElement() && parentNode() && |
| + parentNode() != &document() && !parentNode()->needsAttach()) { |
| + parentNode()->reattachLayoutTree(); |
|
rune
2016/11/18 10:35:40
This is not good. So if you have N display:content
emilio
2016/11/18 10:54:35
Yes, this is the single most nasty thing I've had
emilio
2016/11/18 11:04:43
Also note that this is not as bad as you said (sor
|
| + DCHECK(!needsAttach()); |
| + return; |
| + } |
| + |
| createPseudoElementIfNeeded(PseudoIdAfter); |
| createPseudoElementIfNeeded(PseudoIdBackdrop); |
| @@ -1964,6 +1990,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) |
| @@ -3126,6 +3155,37 @@ const ComputedStyle* Element::ensureComputedStyle( |
| 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; |
| @@ -3859,6 +3919,7 @@ void Element::inlineStyleChanged() { |
| StyleChangeReason::Inline)); |
| DCHECK(elementData()); |
| elementData()->m_styleAttributeIsDirty = true; |
| + |
| InspectorInstrumentation::didInvalidateStyleAttr(this); |
| if (MutationObserverInterestGroup* recipients = |