Chromium Code Reviews| Index: third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversal.cpp |
| diff --git a/third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversal.cpp b/third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversal.cpp |
| index df6ce336cd67a569ae6ee9b3a8fafd813493c799..3252605f6069636e5415ffbfa9a7b0a7855a4ad5 100644 |
| --- a/third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversal.cpp |
| +++ b/third_party/WebKit/Source/core/dom/LayoutTreeBuilderTraversal.cpp |
| @@ -35,11 +35,19 @@ namespace blink { |
| namespace LayoutTreeBuilderTraversal { |
| +inline static bool hasDisplayContentsStyle(const Node& node) { |
| + return node.isElementNode() && toElement(node).displayContentsStyle(); |
| +} |
| + |
| static bool isLayoutObjectReparented(const LayoutObject* layoutObject) { |
| if (!layoutObject->node()->isElementNode()) |
| return false; |
| if (toElement(layoutObject->node())->isInTopLayer()) |
| return true; |
| + |
| + // NB: We intentionally ignore display:contents children here, since we aim to |
| + // find them in the traversal. |
|
rune
2016/11/08 13:09:20
I think you can just remove this comment. The repa
emilio
2016/11/08 15:43:01
Oh, ok, I see, will do.
|
| + |
| return false; |
| } |
| @@ -68,6 +76,16 @@ ContainerNode* parent(const Node& node, ParentDetails* details) { |
| return FlatTreeTraversal::parent(node, details); |
| } |
| +LayoutObject* parentLayoutObject(const Node& node) { |
| + ContainerNode* parent = LayoutTreeBuilderTraversal::parent(node); |
| + |
| + while (parent && hasDisplayContentsStyle(*parent)) { |
| + parent = LayoutTreeBuilderTraversal::parent(*parent); |
| + } |
| + |
| + return parent ? parent->layoutObject() : nullptr; |
| +} |
| + |
| Node* nextSibling(const Node& node) { |
| if (node.isBeforePseudoElement()) { |
| assertPseudoElementParent(toPseudoElement(node)); |
| @@ -214,28 +232,100 @@ Node* next(const Node& node, const Node* stayWithin) { |
| return nextSkippingChildren(node, stayWithin); |
| } |
| -LayoutObject* nextSiblingLayoutObject(const Node& node, int32_t limit) { |
| - DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; |
| - for (Node* sibling = LayoutTreeBuilderTraversal::nextSibling(node); |
| - sibling && limit-- != 0; |
| +static LayoutObject* nextSiblingLayoutObjectInternal(Node* node, |
| + int32_t& limit) { |
| + for (Node* sibling = node; sibling && limit-- != 0; |
| sibling = LayoutTreeBuilderTraversal::nextSibling(*sibling)) { |
| LayoutObject* layoutObject = sibling->layoutObject(); |
| + |
| +#if DCHECK_IS_ON() |
| + if (hasDisplayContentsStyle(*sibling)) |
| + DCHECK(!layoutObject); |
| +#endif |
| + |
| + if (!layoutObject && hasDisplayContentsStyle(*sibling)) { |
| + layoutObject = nextSiblingLayoutObjectInternal( |
| + pseudoAwareFirstChild(*sibling), limit); |
| + if (layoutObject) |
| + return layoutObject; |
| + if (!limit) |
| + return nullptr; |
| + } |
| + |
| if (layoutObject && !isLayoutObjectReparented(layoutObject)) |
| return layoutObject; |
| } |
| - return 0; |
| + |
| + return nullptr; |
| } |
| -LayoutObject* previousSiblingLayoutObject(const Node& node, int32_t limit) { |
| +LayoutObject* nextSiblingLayoutObject(const Node& node, int32_t limit) { |
| DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; |
| - for (Node* sibling = LayoutTreeBuilderTraversal::previousSibling(node); |
| - sibling && limit-- != 0; |
| + if (LayoutObject* foundLayoutObject = nextSiblingLayoutObjectInternal( |
| + LayoutTreeBuilderTraversal::nextSibling(node), limit)) |
| + return foundLayoutObject; |
| + |
| + Node* maybeDisplayContentsParent = LayoutTreeBuilderTraversal::parent(node); |
| + while (limit && maybeDisplayContentsParent && |
| + hasDisplayContentsStyle(*maybeDisplayContentsParent)) { |
| + Node* displayContentsSibling = |
| + LayoutTreeBuilderTraversal::nextSibling(*maybeDisplayContentsParent); |
| + if (LayoutObject* siblingLayoutObject = |
| + nextSiblingLayoutObjectInternal(displayContentsSibling, limit)) |
| + return siblingLayoutObject; |
| + maybeDisplayContentsParent = |
| + LayoutTreeBuilderTraversal::parent(*maybeDisplayContentsParent); |
| + } |
| + |
| + return nullptr; |
| +} |
| + |
| +static LayoutObject* previousSiblingLayoutObjectInternal(Node* node, |
| + int32_t& limit) { |
| + for (Node* sibling = node; sibling && limit-- != 0; |
| sibling = LayoutTreeBuilderTraversal::previousSibling(*sibling)) { |
| LayoutObject* layoutObject = sibling->layoutObject(); |
| + |
| +#if DCHECK_IS_ON() |
| + if (hasDisplayContentsStyle(*sibling)) |
| + DCHECK(!layoutObject); |
| +#endif |
| + |
| + if (!layoutObject && hasDisplayContentsStyle(*sibling)) { |
| + layoutObject = nextSiblingLayoutObjectInternal( |
| + pseudoAwareFirstChild(*sibling), limit); |
| + if (layoutObject) |
| + return layoutObject; |
| + if (!limit) |
| + return nullptr; |
| + } |
| + |
| if (layoutObject && !isLayoutObjectReparented(layoutObject)) |
| return layoutObject; |
| } |
| - return 0; |
| + |
| + return nullptr; |
| +} |
| + |
| +LayoutObject* previousSiblingLayoutObject(const Node& node, int32_t limit) { |
| + DCHECK(limit == kTraverseAllSiblings || limit >= 0) << limit; |
| + if (LayoutObject* foundLayoutObject = previousSiblingLayoutObjectInternal( |
| + LayoutTreeBuilderTraversal::previousSibling(node), limit)) |
| + return foundLayoutObject; |
| + |
| + Node* maybeDisplayContentsParent = LayoutTreeBuilderTraversal::parent(node); |
| + while (limit && maybeDisplayContentsParent && |
| + hasDisplayContentsStyle(*maybeDisplayContentsParent)) { |
| + Node* displayContentsSibling = LayoutTreeBuilderTraversal::previousSibling( |
| + *maybeDisplayContentsParent); |
| + if (LayoutObject* siblingLayoutObject = |
| + previousSiblingLayoutObjectInternal(displayContentsSibling, limit)) |
| + return siblingLayoutObject; |
| + maybeDisplayContentsParent = |
| + LayoutTreeBuilderTraversal::parent(*maybeDisplayContentsParent); |
| + } |
| + |
| + return nullptr; |
| } |
| LayoutObject* nextInTopLayer(const Element& element) { |