diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index adaf35920e..6d092a53d0 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -2442,6 +2442,16 @@ nsContentUtils::GetCommonAncestor(nsINode* aNode1, nsINode* aNode2) }); } +/* static */ +nsIContent* +nsContentUtils::GetCommonFlattenedTreeAncestor(nsIContent* aContent1, + nsIContent* aContent2) +{ + return GetCommonAncestorInternal(aContent1, aContent2, [](nsIContent* aContent) { + return aContent->GetFlattenedTreeParent(); + }); +} + // static nsINode* nsContentUtils::GetCommonAncestorUnderInteractiveContent(nsINode* aNode1, diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index c6e8070576..9c22fa491e 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -338,6 +338,13 @@ public: */ static nsINode* GetCommonAncestor(nsINode* aNode1, nsINode* aNode2); + /** + * Returns the common flattened tree ancestor, if any, for two given content + * nodes. + */ + static nsIContent* GetCommonFlattenedTreeAncestor(nsIContent* aContent1, + nsIContent* aContent2); + /** * Returns the common ancestor under interactive content, if any. * If neither one has interactive content as ancestor, common ancestor will be diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index dd753a97f0..371f66af42 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -4849,48 +4849,13 @@ GetLabelTarget(nsIContent* aPossibleLabel) return label->GetLabeledElement(); } -static nsIContent* FindCommonAncestor(nsIContent *aNode1, nsIContent *aNode2) +static nsIContent* +FindCommonAncestor(nsIContent *aNode1, nsIContent *aNode2) { - // Find closest common ancestor - if (aNode1 && aNode2) { - // Find the nearest common ancestor by counting the distance to the - // root and then walking up again, in pairs. - int32_t offset = 0; - nsIContent *anc1 = aNode1; - for (;;) { - ++offset; - nsIContent* parent = anc1->GetFlattenedTreeParent(); - if (!parent) - break; - anc1 = parent; - } - nsIContent *anc2 = aNode2; - for (;;) { - --offset; - nsIContent* parent = anc2->GetFlattenedTreeParent(); - if (!parent) - break; - anc2 = parent; - } - if (anc1 == anc2) { - anc1 = aNode1; - anc2 = aNode2; - while (offset > 0) { - anc1 = anc1->GetFlattenedTreeParent(); - --offset; - } - while (offset < 0) { - anc2 = anc2->GetFlattenedTreeParent(); - ++offset; - } - while (anc1 != anc2) { - anc1 = anc1->GetFlattenedTreeParent(); - anc2 = anc2->GetFlattenedTreeParent(); - } - return anc1; - } + if (!aNode1 || !aNode2) { + return nullptr; } - return nullptr; + return nsContentUtils::GetCommonFlattenedTreeAncestor(aNode1, aNode2); } /* static */