Bug 1552719 - Make nsLayoutUtils::DoCompareTreePosition handle pseudos more diligently. r=mats
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 21 May 2019 17:29:17 +0000
changeset 474799 e7dcf2a302c50c9c9e2336f18a057dc8f6edb1a1
parent 474798 d008903b2ace15bfc40d9255c295a58300eb298d
child 474800 209e8a6ae29dee097af3e40613c8f0842ffcaa7d
push id36046
push useraiakab@mozilla.com
push dateTue, 21 May 2019 21:45:52 +0000
treeherdermozilla-central@257f2c96cef5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs1552719
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1552719 - Make nsLayoutUtils::DoCompareTreePosition handle pseudos more diligently. r=mats I'm going to need it to fix the counters code in presence of nested pseudo-elements. Differential Revision: https://phabricator.services.mozilla.com/D31988
layout/base/nsLayoutUtils.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1709,52 +1709,44 @@ int32_t nsLayoutUtils::DoCompareTreePosi
 #endif            // DEBUG
   if (!parent) {  // different documents??
     return 0;
   }
 
   int32_t index1 = parent->ComputeIndexOf(content1Ancestor);
   int32_t index2 = parent->ComputeIndexOf(content2Ancestor);
 
-  // If either of the nodes are anonymous, then handle the relative ordering.
-  // We consider all anonymous content to be behind regular siblings, with the
-  // exception of ::after.
-  if (index1 < 0) {
-    if (content1Ancestor->IsContent() &&
-        content1Ancestor->AsContent()->IsGeneratedContentContainerForAfter()) {
-      // If content1 is ::after, then it must be after content2.
-      MOZ_ASSERT(!content2Ancestor->IsContent() ||
-                 !content2Ancestor->AsContent()
-                      ->IsGeneratedContentContainerForAfter());
-      return 1;
-    }
-    if (index2 >= 0 || (content2Ancestor->IsContent() &&
-                        content2Ancestor->AsContent()
-                            ->IsGeneratedContentContainerForAfter())) {
-      // content1 is anonymous, so if content2 is a regular sibling or ::after,
-      // then we must be before it.
-      return -1;
-    }
-    // Both nodes are anonymous, so no relative ordering.
+  // None of the nodes are anonymous, just do a regular comparison.
+  if (index1 >= 0 && index2 >= 0) {
+    return index1 - index2;
+  }
+
+  // Otherwise handle pseudo-element and anonymous content ordering.
+  //
+  // ::marker -> ::before -> anon siblings -> regular siblings -> ::after
+  auto PseudoIndex = [](const nsINode* aNode, int32_t aNodeIndex) -> int32_t {
+    if (aNodeIndex >= 0) {
+      return 1;  // Not a pseudo.
+    }
+    if (aNode->IsContent()) {
+      if (aNode->AsContent()->IsGeneratedContentContainerForMarker()) {
+        return -2;
+      }
+      if (aNode->AsContent()->IsGeneratedContentContainerForBefore()) {
+        return -1;
+      }
+      if (aNode->AsContent()->IsGeneratedContentContainerForAfter()) {
+        return 2;
+      }
+    }
     return 0;
-  }
-  if (index2 < 0) {
-    // content1 is a regular sibling, so if content2 is ::after, then
-    // content1 comes first.
-    if (content2Ancestor->IsContent() &&
-        content2Ancestor->AsContent()->IsGeneratedContentContainerForAfter()) {
-      MOZ_ASSERT(!content1Ancestor->IsContent() ||
-                 !content1Ancestor->AsContent()
-                      ->IsGeneratedContentContainerForAfter());
-      return -1;
-    }
-    return 1;
-  }
-
-  return index1 - index2;
+  };
+
+  return PseudoIndex(content1Ancestor, index1) -
+         PseudoIndex(content2Ancestor, index2);
 }
 
 // static
 nsIFrame* nsLayoutUtils::FillAncestors(nsIFrame* aFrame,
                                        nsIFrame* aStopAtAncestor,
                                        nsTArray<nsIFrame*>* aAncestors) {
   while (aFrame && aFrame != aStopAtAncestor) {
     aAncestors->AppendElement(aFrame);
@@ -9984,17 +9976,17 @@ Maybe<MotionPathData> nsLayoutUtils::Res
     }
 
     // Per the spec, we have to convert offset distance to pixels, with 100%
     // being converted to total length. So here |gfxPath| is built with CSS
     // pixel, and we calculate |pathLength| and |computedDistance| with CSS
     // pixel as well.
     gfx::Float pathLength = gfxPath->ComputeLength();
     gfx::Float usedDistance =
-      display->mOffsetDistance.ResolveToCSSPixels(CSSCoord(pathLength));
+        display->mOffsetDistance.ResolveToCSSPixels(CSSCoord(pathLength));
     if (!path.empty() && path.rbegin()->IsClosePath()) {
       // Per the spec, let used offset distance be equal to offset distance
       // modulus the total length of the path. If the total length of the path
       // is 0, used offset distance is also 0.
       usedDistance = pathLength > 0.0 ? fmod(usedDistance, pathLength) : 0.0;
       // We make sure |usedDistance| is 0.0 or a positive value.
       // https://github.com/w3c/fxtf-drafts/issues/339
       if (usedDistance < 0.0) {