Backed out changeset 17660bff0c23 (bug 1423331) for 4 failures in layout/base/tests/test_reftests_with_caret.html r=backout on a CLOSED TREE
authorMargareta Eliza Balazs <ebalazs@mozilla.com>
Tue, 09 Jan 2018 17:49:00 +0200
changeset 452650 c9e79ef9bb1f25bd3c4ebabefcf8de5641f6d571
parent 452649 89d7ac0fbdc8374277a47f77f41e482504a46f6e
child 452651 b3beb896ac263884c7dc9d17c8e5d1d052598eb2
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1423331
milestone59.0a1
backs out17660bff0c23f8fa046c368ee6c3eb50afe1a7ce
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
Backed out changeset 17660bff0c23 (bug 1423331) for 4 failures in layout/base/tests/test_reftests_with_caret.html r=backout on a CLOSED TREE
layout/generic/nsFrame.cpp
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4700,73 +4700,68 @@ struct MOZ_STACK_CLASS FrameContentRange
     content(aContent), start(aStart), end(aEnd) { }
   nsCOMPtr<nsIContent> content;
   int32_t start;
   int32_t end;
 };
 
 // Retrieve the content offsets of a frame
 static FrameContentRange GetRangeForFrame(nsIFrame* aFrame) {
-  nsIContent* content = aFrame->GetContent();
+  nsCOMPtr<nsIContent> content, parent;
+  content = aFrame->GetContent();
   if (!content) {
     NS_WARNING("Frame has no content");
     return FrameContentRange(nullptr, -1, -1);
   }
-
   LayoutFrameType type = aFrame->Type();
   if (type == LayoutFrameType::Text) {
     int32_t offset, offsetEnd;
     aFrame->GetOffsets(offset, offsetEnd);
     return FrameContentRange(content, offset, offsetEnd);
   }
-
   if (type == LayoutFrameType::Br) {
-    nsIContent* parent = content->GetParent();
+    parent = content->GetParent();
     int32_t beginOffset = parent->IndexOf(content);
     return FrameContentRange(parent, beginOffset, beginOffset);
   }
-
-  while (content->IsRootOfAnonymousSubtree()) {
-    content = content->GetParent();
-  }
-
-  nsIContent* parent = content->GetParent();
-  if (nsLayoutUtils::GetAsBlock(aFrame) || !parent) {
-    return FrameContentRange(content, 0, content->GetChildCount());
-  }
-
-  // TODO(emilio): Revise this in presence of Shadow DOM / display: contents,
-  // it's likely that we don't want to just walk the light tree, and we need to
-  // change the representation of FrameContentRange.
-  int32_t index = parent->IndexOf(content);
-  MOZ_ASSERT(index >= 0);
-  return FrameContentRange(parent, index, index + 1);
+  // Loop to deal with anonymous content, which has no index; this loop
+  // probably won't run more than twice under normal conditions
+  do {
+    parent  = content->GetParent();
+    if (parent) {
+      int32_t beginOffset = parent->IndexOf(content);
+      if (beginOffset >= 0)
+        return FrameContentRange(parent, beginOffset, beginOffset + 1);
+      content = parent;
+    }
+  } while (parent);
+
+  // The root content node must act differently
+  return FrameContentRange(content, 0, content->GetChildCount());
 }
 
 // The FrameTarget represents the closest frame to a point that can be selected
 // The frame is the frame represented, frameEdge says whether one end of the
 // frame is the result (in which case different handling is needed), and
 // afterFrame says which end is repersented if frameEdge is true
 struct FrameTarget {
-  FrameTarget(nsIFrame* aFrame, bool aFrameEdge, bool aAfterFrame)
-    : frame(aFrame)
-    , frameEdge(aFrameEdge)
-    , afterFrame(aAfterFrame)
-  {}
-
+  FrameTarget(nsIFrame* aFrame, bool aFrameEdge, bool aAfterFrame,
+              bool aEmptyBlock = false) :
+    frame(aFrame), frameEdge(aFrameEdge), afterFrame(aAfterFrame),
+    emptyBlock(aEmptyBlock) { }
   static FrameTarget Null() {
     return FrameTarget(nullptr, false, false);
   }
-
   bool IsNull() {
     return !frame;
   }
   nsIFrame* frame;
   bool frameEdge;
   bool afterFrame;
+  bool emptyBlock;
 };
 
 // See function implementation for information
 static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame,
                                             const nsPoint& aPoint,
                                             uint32_t aFlags);
 
 static bool SelfIsSelectable(nsIFrame* aFrame, uint32_t aFlags)
@@ -4846,22 +4841,21 @@ static FrameTarget DrillDownToSelectionF
 // This method finds the closest valid FrameTarget on a given line; if there is
 // no valid FrameTarget on the line, it returns a null FrameTarget
 static FrameTarget GetSelectionClosestFrameForLine(
                       nsBlockFrame* aParent,
                       nsBlockFrame::LineIterator aLine,
                       const nsPoint& aPoint,
                       uint32_t aFlags)
 {
+  nsIFrame *frame = aLine->mFirstChild;
   // Account for end of lines (any iterator from the block is valid)
   if (aLine == aParent->LinesEnd())
     return DrillDownToSelectionFrame(aParent, true, aFlags);
-  nsIFrame* frame = aLine->mFirstChild;
-  nsIFrame* closestFromIStart = nullptr;
-  nsIFrame* closestFromIEnd = nullptr;
+  nsIFrame *closestFromIStart = nullptr, *closestFromIEnd = nullptr;
   nscoord closestIStart = aLine->IStart(), closestIEnd = aLine->IEnd();
   WritingMode wm = aLine->mWritingMode;
   LogicalPoint pt(wm, aPoint, aLine->mContainerSize);
   bool canSkipBr = false;
   for (int32_t n = aLine->GetChildCount(); n;
        --n, frame = frame->GetNextSibling()) {
     // Skip brFrames. Can only skip if the line contains at least
     // one selectable and non-empty frame before
@@ -4910,77 +4904,82 @@ static FrameTarget GetSelectionClosestFr
                                                     const nsPoint& aPoint,
                                                     uint32_t aFlags)
 {
   nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(aFrame); // used only for QI
   if (!bf)
     return FrameTarget::Null();
 
   // This code searches for the correct line
+  nsBlockFrame::LineIterator firstLine = bf->LinesBegin();
   nsBlockFrame::LineIterator end = bf->LinesEnd();
-  nsBlockFrame::LineIterator curLine = bf->LinesBegin();
+  if (firstLine == end) {
+    nsIContent *blockContent = aFrame->GetContent();
+    if (blockContent) {
+      // Return with empty flag true.
+      return FrameTarget(aFrame, false, false, true);
+    }
+    return FrameTarget::Null();
+  }
+  nsBlockFrame::LineIterator curLine = firstLine;
   nsBlockFrame::LineIterator closestLine = end;
-
-  if (curLine != end) {
-    // Convert aPoint into a LogicalPoint in the writing-mode of this block
-    WritingMode wm = curLine->mWritingMode;
-    LogicalPoint pt(wm, aPoint, curLine->mContainerSize);
-    do {
-      // Check to see if our point lies within the line's block-direction bounds
-      nscoord BCoord = pt.B(wm) - curLine->BStart();
-      nscoord BSize = curLine->BSize();
-      if (BCoord >= 0 && BCoord < BSize) {
-        closestLine = curLine;
-        break; // We found the line; stop looking
-      }
-      if (BCoord < 0)
-        break;
-      ++curLine;
-    } while (curLine != end);
-
-    if (closestLine == end) {
-      nsBlockFrame::LineIterator prevLine = curLine.prev();
-      nsBlockFrame::LineIterator nextLine = curLine;
-      // Avoid empty lines
-      while (nextLine != end && nextLine->IsEmpty())
-        ++nextLine;
-      while (prevLine != end && prevLine->IsEmpty())
-        --prevLine;
-
-      // This hidden pref dictates whether a point above or below all lines comes
-      // up with a line or the beginning or end of the frame; 0 on Windows,
-      // 1 on other platforms by default at the writing of this code
-      int32_t dragOutOfFrame =
-        Preferences::GetInt("browser.drag_out_of_frame_style");
-
-      if (prevLine == end) {
-        if (dragOutOfFrame == 1 || nextLine == end)
-          return DrillDownToSelectionFrame(aFrame, false, aFlags);
+  // Convert aPoint into a LogicalPoint in the writing-mode of this block
+  WritingMode wm = curLine->mWritingMode;
+  LogicalPoint pt(wm, aPoint, curLine->mContainerSize);
+  while (curLine != end) {
+    // Check to see if our point lies within the line's block-direction bounds
+    nscoord BCoord = pt.B(wm) - curLine->BStart();
+    nscoord BSize = curLine->BSize();
+    if (BCoord >= 0 && BCoord < BSize) {
+      closestLine = curLine;
+      break; // We found the line; stop looking
+    }
+    if (BCoord < 0)
+      break;
+    ++curLine;
+  }
+
+  if (closestLine == end) {
+    nsBlockFrame::LineIterator prevLine = curLine.prev();
+    nsBlockFrame::LineIterator nextLine = curLine;
+    // Avoid empty lines
+    while (nextLine != end && nextLine->IsEmpty())
+      ++nextLine;
+    while (prevLine != end && prevLine->IsEmpty())
+      --prevLine;
+
+    // This hidden pref dictates whether a point above or below all lines comes
+    // up with a line or the beginning or end of the frame; 0 on Windows,
+    // 1 on other platforms by default at the writing of this code
+    int32_t dragOutOfFrame =
+      Preferences::GetInt("browser.drag_out_of_frame_style");
+
+    if (prevLine == end) {
+      if (dragOutOfFrame == 1 || nextLine == end)
+        return DrillDownToSelectionFrame(aFrame, false, aFlags);
+      closestLine = nextLine;
+    } else if (nextLine == end) {
+      if (dragOutOfFrame == 1)
+        return DrillDownToSelectionFrame(aFrame, true, aFlags);
+      closestLine = prevLine;
+    } else { // Figure out which line is closer
+      if (pt.B(wm) - prevLine->BEnd() < nextLine->BStart() - pt.B(wm))
+        closestLine = prevLine;
+      else
         closestLine = nextLine;
-      } else if (nextLine == end) {
-        if (dragOutOfFrame == 1)
-          return DrillDownToSelectionFrame(aFrame, true, aFlags);
-        closestLine = prevLine;
-      } else { // Figure out which line is closer
-        if (pt.B(wm) - prevLine->BEnd() < nextLine->BStart() - pt.B(wm))
-          closestLine = prevLine;
-        else
-          closestLine = nextLine;
-      }
     }
   }
 
   do {
     FrameTarget target = GetSelectionClosestFrameForLine(bf, closestLine,
                                                          aPoint, aFlags);
     if (!target.IsNull())
       return target;
     ++closestLine;
   } while (closestLine != end);
-
   // Fall back to just targeting the last targetable place
   return DrillDownToSelectionFrame(aFrame, true, aFlags);
 }
 
 // GetSelectionClosestFrame is the helper function that calculates the closest
 // frame to the given point.
 // It doesn't completely account for offset styles, so needs to be used in
 // restricted environments.
@@ -5108,16 +5107,27 @@ nsIFrame::ContentOffsets nsIFrame::GetCo
       adjustedFrame = adjustedFrame->GetParent();
   }
 
   nsPoint adjustedPoint = aPoint + this->GetOffsetTo(adjustedFrame);
 
   FrameTarget closest =
     GetSelectionClosestFrame(adjustedFrame, adjustedPoint, aFlags);
 
+  if (closest.emptyBlock) {
+    ContentOffsets offsets;
+    NS_ASSERTION(closest.frame,
+                 "closest.frame must not be null when it's empty");
+    offsets.content = closest.frame->GetContent();
+    offsets.offset = 0;
+    offsets.secondaryOffset = 0;
+    offsets.associate = CARET_ASSOCIATE_AFTER;
+    return offsets;
+  }
+
   // If the correct offset is at one end of a frame, use offset-based
   // calculation method
   if (closest.frameEdge) {
     ContentOffsets offsets;
     FrameContentRange range = GetRangeForFrame(closest.frame);
     offsets.content = range.content;
     if (closest.afterFrame)
       offsets.offset = range.end;
@@ -8330,17 +8340,17 @@ FindBlockFrameOrBR(nsIFrame* aFrame, nsD
 }
 
 nsresult
 nsIFrame::PeekOffsetParagraph(nsPeekOffsetStruct *aPos)
 {
   nsIFrame* frame = this;
   nsContentAndOffset blockFrameOrBR;
   blockFrameOrBR.mContent = nullptr;
-  bool reachedBlockAncestor = !!nsLayoutUtils::GetAsBlock(frame);
+  bool reachedBlockAncestor = false;
 
   // Go through containing frames until reaching a block frame.
   // In each step, search the previous (or next) siblings for the closest
   // "stop frame" (a block frame or a BRFrame).
   // If found, set it to be the selection boundray and abort.
 
   if (aPos->mDirection == eDirPrevious) {
     while (!reachedBlockAncestor) {
@@ -8381,17 +8391,17 @@ nsIFrame::PeekOffsetParagraph(nsPeekOffs
         sibling = sibling->GetNextSibling();
       }
       if (blockFrameOrBR.mContent) {
         aPos->mResultContent = blockFrameOrBR.mContent;
         aPos->mContentOffset = blockFrameOrBR.mOffset;
         break;
       }
       frame = parent;
-      reachedBlockAncestor = !!nsLayoutUtils::GetAsBlock(frame);
+      reachedBlockAncestor = (nsLayoutUtils::GetAsBlock(frame) != nullptr);
     }
     if (reachedBlockAncestor) { // no "stop frame" found
       aPos->mResultContent = frame->GetContent();
       if (aPos->mResultContent)
         aPos->mContentOffset = aPos->mResultContent->GetChildCount();
     }
   }
   return NS_OK;