Index: third_party/WebKit/Source/core/dom/Text.cpp |
diff --git a/third_party/WebKit/Source/core/dom/Text.cpp b/third_party/WebKit/Source/core/dom/Text.cpp |
index a105811975803ddc44edf75f845d6386a3f5d22c..a0adf4ea2996e522aea9f0ecc9d27cf550c29788 100644 |
--- a/third_party/WebKit/Source/core/dom/Text.cpp |
+++ b/third_party/WebKit/Source/core/dom/Text.cpp |
@@ -254,6 +254,9 @@ static inline bool canHaveWhitespaceChildren(const LayoutObject& parent) { |
bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, |
const LayoutObject& parent) const { |
+ const LayoutObject* prev = nullptr; |
+ bool lookedForPrev = false; |
+ |
if (!parent.canHaveChildren()) |
return false; |
@@ -269,6 +272,26 @@ bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, |
if (!containsOnlyWhitespace()) |
return true; |
+ // We may have multiple text layout object siblings as part of a layout tree |
+ // affected by display: contents. In the case we have something like: |
+ // |
+ // <div>Foo<div style="display: contents"> </div>Bar</div> |
+ // |
+ // We can't just bail out and don't create a text layout object for the |
+ // whitespace text node inside the display: contents element. |
+ // |
+ // We can check whether our style parent or our previous light-tree sibling |
+ // has display contents to to avoid doing the previous layout object lookup |
rune
2017/01/27 13:09:23
double "to"
|
+ // more than necessary. |
+ if (style.display() == EDisplay::Contents || |
+ (previousSibling() && previousSibling()->isElementNode() && |
+ toElement(previousSibling())->hasDisplayContentsStyle())) { |
+ prev = LayoutTreeBuilderTraversal::previousSiblingLayoutObject(*this); |
+ lookedForPrev = true; |
+ if (prev && prev->node() && prev->node()->isTextNode()) |
rune
2017/01/27 13:09:23
Not strictly true if the previous sibling is also
emilio
2017/01/27 22:13:15
Right, I guess we could avoid creating it if the p
|
+ return true; |
+ } |
+ |
if (!canHaveWhitespaceChildren(parent)) |
return false; |
@@ -290,9 +313,12 @@ bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, |
// the number of siblings to visit. |
unsigned maxSiblingsToVisit = 50; |
- const LayoutObject* prev = |
- LayoutTreeBuilderTraversal::previousSiblingLayoutObject( |
- *this, maxSiblingsToVisit); |
+ if (!lookedForPrev) { |
+ lookedForPrev = true; |
+ prev = LayoutTreeBuilderTraversal::previousSiblingLayoutObject( |
+ *this, maxSiblingsToVisit); |
+ } |
+ |
if (prev && prev->isBR()) // <span><br/> <br/></span> |
return false; |
@@ -349,12 +375,17 @@ LayoutText* Text::createTextLayoutObject(const ComputedStyle& style) { |
} |
void Text::attachLayoutTree(const AttachContext& context) { |
- if (ContainerNode* layoutParent = LayoutTreeBuilderTraversal::parent(*this)) { |
- if (LayoutObject* parentLayoutObject = layoutParent->layoutObject()) { |
- if (textLayoutObjectIsNeeded(*parentLayoutObject->style(), |
- *parentLayoutObject)) |
- LayoutTreeBuilderForText(*this, parentLayoutObject) |
- .createLayoutObject(); |
+ ContainerNode* styleParent = LayoutTreeBuilderTraversal::parent(*this); |
+ LayoutObject* parentLayoutObject = |
+ LayoutTreeBuilderTraversal::parentLayoutObject(*this); |
+ |
+ if (styleParent && parentLayoutObject) { |
+ DCHECK(styleParent->computedStyle()); |
+ if (textLayoutObjectIsNeeded(*styleParent->computedStyle(), |
+ *parentLayoutObject)) { |
+ LayoutTreeBuilderForText(*this, parentLayoutObject, |
+ styleParent->mutableComputedStyle()) |
rune
2017/01/27 13:09:23
Using mutableComputedStyle() here looks worrying,
emilio
2017/01/27 22:13:15
Yes, I agree, though this was pre-existing (the pr
|
+ .createLayoutObject(); |
} |
} |
CharacterData::attachLayoutTree(context); |
@@ -362,13 +393,13 @@ void Text::attachLayoutTree(const AttachContext& context) { |
void Text::reattachLayoutTreeIfNeeded(const AttachContext& context) { |
bool layoutObjectIsNeeded = false; |
- ContainerNode* layoutParent = LayoutTreeBuilderTraversal::parent(*this); |
- if (layoutParent) { |
- if (LayoutObject* parentLayoutObject = layoutParent->layoutObject()) { |
- if (textLayoutObjectIsNeeded(*parentLayoutObject->style(), |
- *parentLayoutObject)) |
- layoutObjectIsNeeded = true; |
- } |
+ ContainerNode* styleParent = LayoutTreeBuilderTraversal::parent(*this); |
+ LayoutObject* parentLayoutObject = |
+ LayoutTreeBuilderTraversal::parentLayoutObject(*this); |
+ if (styleParent && parentLayoutObject) { |
+ DCHECK(styleParent->computedStyle()); |
+ layoutObjectIsNeeded = textLayoutObjectIsNeeded( |
+ *styleParent->computedStyle(), *parentLayoutObject); |
} |
if (layoutObjectIsNeeded == !!layoutObject()) |
@@ -382,9 +413,11 @@ void Text::reattachLayoutTreeIfNeeded(const AttachContext& context) { |
if (getStyleChangeType() < NeedsReattachStyleChange) |
detachLayoutTree(reattachContext); |
- if (layoutObjectIsNeeded) |
- LayoutTreeBuilderForText(*this, layoutParent->layoutObject()) |
+ if (layoutObjectIsNeeded) { |
+ LayoutTreeBuilderForText(*this, parentLayoutObject, |
+ styleParent->mutableComputedStyle()) |
.createLayoutObject(); |
+ } |
CharacterData::attachLayoutTree(reattachContext); |
} |