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 047e339cba3e817a5c7eb056291cb3d2776f7584..0f394e1342f6b80c192dd6966114aacfbe59fa60 100644 |
| --- a/third_party/WebKit/Source/core/dom/Element.cpp |
| +++ b/third_party/WebKit/Source/core/dom/Element.cpp |
| @@ -1860,6 +1860,7 @@ void Element::recalcStyle(StyleRecalcChange change, Text* nextTextSibling) { |
| if (parentComputedStyle()) |
| change = recalcOwnStyle(change); |
| clearNeedsStyleRecalc(); |
| + clearNeedsReattachLayoutTree(); |
| } |
| // If we reattached we don't need to recalc the style of our descendants |
| @@ -1891,13 +1892,11 @@ void Element::recalcStyle(StyleRecalcChange change, Text* nextTextSibling) { |
| childNeedsStyleRecalc() ? Force : change); |
| clearChildNeedsStyleRecalc(); |
| + clearChildNeedsReattachLayoutTree(); |
| } |
| if (hasCustomStyleCallbacks()) |
| didRecalcStyle(change); |
| - |
| - if (change == Reattach) |
| - reattachWhitespaceSiblingsIfNeeded(nextTextSibling); |
| } |
| PassRefPtr<ComputedStyle> Element::propagateInheritedProperties( |
| @@ -1946,6 +1945,7 @@ StyleRecalcChange Element::recalcOwnStyle(StyleRecalcChange change) { |
| if (localChange == Reattach) { |
| document().addNonAttachedStyle(*this, std::move(newStyle)); |
| + setNeedsReattachLayoutTree(); |
| return rebuildLayoutTree(); |
| } |
| @@ -1992,12 +1992,52 @@ StyleRecalcChange Element::rebuildLayoutTree() { |
| AttachContext reattachContext; |
| reattachContext.resolvedStyle = document().getNonAttachedStyle(*this); |
| bool layoutObjectWillChange = needsAttach() || layoutObject(); |
| - reattachLayoutTree(reattachContext); |
| - if (layoutObjectWillChange || layoutObject()) |
| + |
| + if (needsReattachLayoutTree()) { |
| + reattachLayoutTree(reattachContext); |
| + } else if (childNeedsReattachLayoutTree()) { |
| + reattachPseudoElementLayoutTree(PseudoIdBefore); |
| + |
| + for (Node* child = firstChild(); child && child->isElementNode(); |
|
esprehn
2016/10/10 21:50:42
this breaks at the first non element, ex. text or
nainar
2016/10/10 22:56:34
Added NOTREACHED() here and noted the changes need
|
| + child = child->nextSibling()) |
| + toElement(child)->rebuildLayoutTree(); |
| + |
| + reattachPseudoElementLayoutTree(PseudoIdAfter); |
| + reattachPseudoElementLayoutTree(PseudoIdBackdrop); |
| + } |
| + |
| + if (layoutObjectWillChange || layoutObject()) { |
| + // nextTextSibling is passed on to recalcStyle from recalcDescendantStyles |
| + // we can either traverse the parent's tree to get this node or store it |
| + // (like WebKit does). |
| + // The choice is between increased time and increased memory complexity |
| + Text* nextTextSibling = nullptr; |
| + for (Node* child = parentNode()->lastChild(); child; |
|
esprehn
2016/10/10 21:50:42
This is n^2, if you appendChild 500 elements, this
nainar
2016/10/10 22:56:34
Done. Starting iteration from this->nextSibling.
|
| + child = child->previousSibling()) { |
| + if (child->isTextNode()) { |
| + nextTextSibling = toText(child); |
| + } else if (child->isElementNode()) { |
| + if (toElement(child) == this) { |
| + reattachWhitespaceSiblingsIfNeeded(nextTextSibling); |
| + break; |
| + } |
| + if (toElement(child)->layoutObject()) { |
| + nextTextSibling = nullptr; |
| + } |
| + } |
| + } |
| return Reattach; |
| + } |
| return ReattachNoLayoutObject; |
| } |
| +void Element::reattachPseudoElementLayoutTree(PseudoId pseudoId) { |
| + if (PseudoElement* element = pseudoElement(pseudoId)) { |
| + if (element->needsReattachLayoutTree()) |
| + element->rebuildLayoutTree(); |
| + } |
| +} |
| + |
| void Element::updateCallbackSelectors(const ComputedStyle* oldStyle, |
| const ComputedStyle* newStyle) { |
| Vector<String> emptyVector; |