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) { |