Back out 3 changesets (bug 1216001) for Win8 reftest failures in 1193519-sideways-lr-3.html and 1193519-sideways-lr-4.html and intermittent OS X failures in font-display-2.html
authorPhil Ringnalda <philringnalda@gmail.com>
Thu, 11 Feb 2016 20:43:41 -0800
changeset 320417 d8804baafb3fac3199037f5f6c35b92f56eb190c
parent 320416 9479748cba304928d6146426dce23ef1800f9c21
child 320418 9320c843aa7e99ad88c20367841be0254d676a11
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1216001, 1193519
milestone47.0a1
backs outdbadb8fe5803dd33231bda873ffc0a0d4007c4dd
a30593ebd58e6bf9f31db4a1c9d9382d2591940a
c1646ffa71b40babef414c91078eaee3d5e9b0d7
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
Back out 3 changesets (bug 1216001) for Win8 reftest failures in 1193519-sideways-lr-3.html and 1193519-sideways-lr-4.html and intermittent OS X failures in font-display-2.html CLOSED TREE Backed out changeset dbadb8fe5803 (bug 1216001) Backed out changeset a30593ebd58e (bug 1216001) Backed out changeset c1646ffa71b4 (bug 1216001)
dom/base/nsRange.cpp
dom/base/nsRange.h
dom/base/test/test_user_select.html
layout/base/nsDisplayList.h
layout/generic/nsTextFrame.cpp
mfbt/BinarySearch.h
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -146,92 +146,43 @@ GetNextRangeCommonAncestor(nsINode* aNod
     if (!aNode->IsDescendantOfCommonAncestorForRangeInSelection()) {
       return nullptr;
     }
     aNode = aNode->GetParentNode();
   }
   return aNode;
 }
 
-/**
- * A Comparator suitable for mozilla::BinarySearchIf for searching a collection
- * of nsRange* for an overlap of (mNode, mStartOffset) .. (mNode, mEndOffset).
- */
-struct IsItemInRangeComparator
-{
-  nsINode* mNode;
-  uint32_t mStartOffset;
-  uint32_t mEndOffset;
-
-  int operator()(const nsRange* const aRange) const
-  {
-    int32_t cmp = nsContentUtils::ComparePoints(mNode, mEndOffset,
-                                                aRange->GetStartParent(),
-                                                aRange->StartOffset());
-    if (cmp == 1) {
-      cmp = nsContentUtils::ComparePoints(mNode, mStartOffset,
-                                          aRange->GetEndParent(),
-                                          aRange->EndOffset());
-      if (cmp == -1) {
-        return 0;
-      }
-      return 1;
-    }
-    return -1;
-  }
-};
-
 /* static */ bool
 nsRange::IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
                         uint32_t aEndOffset)
 {
   NS_PRECONDITION(aNode, "bad arg");
 
   nsINode* n = GetNextRangeCommonAncestor(aNode);
   NS_ASSERTION(n || !aNode->IsSelectionDescendant(),
                "orphan selection descendant");
-
-  // Collect the potential ranges and their selection objects.
-  RangeHashTable ancestorSelectionRanges;
-  nsTHashtable<nsPtrHashKey<Selection>> ancestorSelections;
-  uint32_t maxRangeCount = 0;
   for (; n; n = GetNextRangeCommonAncestor(n->GetParentNode())) {
     RangeHashTable* ranges =
       static_cast<RangeHashTable*>(n->GetProperty(nsGkAtoms::range));
     for (auto iter = ranges->ConstIter(); !iter.Done(); iter.Next()) {
       nsRange* range = iter.Get()->GetKey();
       if (range->IsInSelection() && !range->Collapsed()) {
-        ancestorSelectionRanges.PutEntry(range);
-        Selection* selection = range->mSelection;
-        ancestorSelections.PutEntry(selection);
-        maxRangeCount = std::max(maxRangeCount, selection->RangeCount());
-      }
-    }
-  }
-
-  if (!ancestorSelectionRanges.IsEmpty()) {
-    nsTArray<const nsRange*> sortedRanges(maxRangeCount);
-    for (auto iter = ancestorSelections.ConstIter(); !iter.Done(); iter.Next()) {
-      Selection* selection = iter.Get()->GetKey();
-      // Sort the found ranges for |selection| in document order
-      // (Selection::GetRangeAt returns its ranges ordered).
-      for (uint32_t i = 0, len = selection->RangeCount(); i < len; ++i) {
-        nsRange* range = selection->GetRangeAt(i);
-        if (ancestorSelectionRanges.Contains(range)) {
-          sortedRanges.AppendElement(range);
+        int32_t cmp = nsContentUtils::ComparePoints(aNode, aEndOffset,
+                                                    range->GetStartParent(),
+                                                    range->StartOffset());
+        if (cmp == 1) {
+          cmp = nsContentUtils::ComparePoints(aNode, aStartOffset,
+                                              range->GetEndParent(),
+                                              range->EndOffset());
+          if (cmp == -1) {
+            return true;
+          }
         }
       }
-      MOZ_ASSERT(!sortedRanges.IsEmpty());
-      // Binary search the now sorted ranges.
-      IsItemInRangeComparator comparator = { aNode, aStartOffset, aEndOffset };
-      size_t unused;
-      if (mozilla::BinarySearchIf(sortedRanges, 0, sortedRanges.Length(), comparator, &unused)) {
-        return true;
-      }
-      sortedRanges.ClearAndRetainStorage();
     }
   }
   return false;
 }
 
 /******************************************************
  * constructor/destructor
  ******************************************************/
@@ -3149,22 +3100,16 @@ nsRange::Constructor(const GlobalObject&
   if (!window || !window->GetDoc()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   return window->GetDoc()->CreateRange(aRv);
 }
 
-static bool ExcludeIfNextToNonSelectable(nsIContent* aContent)
-{
-  return aContent->IsNodeOfType(nsINode::eTEXT) &&
-    aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE);
-}
-
 void
 nsRange::ExcludeNonSelectableNodes(nsTArray<RefPtr<nsRange>>* aOutRanges)
 {
   MOZ_ASSERT(mIsPositioned);
   MOZ_ASSERT(mEndParent);
   MOZ_ASSERT(mStartParent);
 
   nsRange* range = this;
@@ -3173,42 +3118,31 @@ nsRange::ExcludeNonSelectableNodes(nsTAr
     nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
     nsresult rv = iter->Init(range);
     if (NS_FAILED(rv)) {
       return;
     }
 
     bool added = false;
     bool seenSelectable = false;
-    // |firstNonSelectableContent| is the first node in a consecutive sequence
-    // of non-IsSelectable nodes.  When we find a selectable node after such
-    // a sequence we'll end the last nsRange, create a new one and restart
-    // the outer loop.
     nsIContent* firstNonSelectableContent = nullptr;
     while (true) {
       ErrorResult err;
       nsINode* node = iter->GetCurrentNode();
       iter->Next();
       bool selectable = true;
       nsIContent* content =
         node && node->IsContent() ? node->AsContent() : nullptr;
       if (content) {
-        if (firstNonSelectableContent && ExcludeIfNextToNonSelectable(content)) {
-          // Ignorable whitespace next to a sequence of non-selectable nodes
-          // counts as non-selectable (bug 1216001).
-          selectable = false;
+        nsIFrame* frame = content->GetPrimaryFrame();
+        for (nsIContent* p = content; !frame && (p = p->GetParent()); ) {
+          frame = p->GetPrimaryFrame();
         }
-        if (selectable) {
-          nsIFrame* frame = content->GetPrimaryFrame();
-          for (nsIContent* p = content; !frame && (p = p->GetParent()); ) {
-            frame = p->GetPrimaryFrame();
-          }
-          if (frame) {
-            frame->IsSelectable(&selectable, nullptr);
-          }
+        if (frame) {
+          frame->IsSelectable(&selectable, nullptr);
         }
       }
 
       if (!selectable) {
         if (!firstNonSelectableContent) {
           firstNonSelectableContent = content;
         }
         if (iter->IsDone() && seenSelectable) {
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -247,24 +247,16 @@ public:
  *
  *  XXX - callers responsibility to ensure node in same doc as range!
  *
  *****************************************************************************/
   static nsresult CompareNodeToRange(nsINode* aNode, nsRange* aRange,
                                      bool *outNodeBefore,
                                      bool *outNodeAfter);
 
-  /**
-   * Return true if any part of (aNode, aStartOffset) .. (aNode, aEndOffset)
-   * overlaps any nsRange in aNode's GetNextRangeCommonAncestor ranges (i.e.
-   * where aNode is a descendant of a range's common ancestor node).
-   * If a nsRange starts in (aNode, aEndOffset) or if it ends in
-   * (aNode, aStartOffset) then it is non-overlapping and the result is false
-   * for that nsRange.  Collapsed ranges always counts as non-overlapping.
-   */
   static bool IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
                              uint32_t aEndOffset);
 
   static void CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
                                  nsRange* aRange,
                                  nsINode* aStartParent, int32_t aStartOffset,
                                  nsINode* aEndParent, int32_t aEndOffset,
                                  bool aClampToEdge, bool aFlushLayout);
@@ -301,24 +293,16 @@ protected:
    * ancestor for the range.  This method uses the selection bits and
    * nsGkAtoms::range property on the nodes to quickly find the ancestor.
    * That is, it's a faster version of GetCommonAncestor that only works
    * for ranges in a Selection.  The method will assert and the behavior
    * is undefined if called on a range where IsInSelection() is false.
    */
   nsINode* GetRegisteredCommonAncestor();
 
-  // Helper to IsNodeSelected.
-  static bool IsNodeInSortedRanges(nsINode* aNode,
-                                   uint32_t aStartOffset,
-                                   uint32_t aEndOffset,
-                                   const nsTArray<const nsRange*>& aRanges,
-                                   size_t aRangeStart,
-                                   size_t aRangeEnd);
-
   struct MOZ_STACK_CLASS AutoInvalidateSelection
   {
     explicit AutoInvalidateSelection(nsRange* aRange) : mRange(aRange)
     {
 #ifdef DEBUG
       mWasInSelection = mRange->IsInSelection();
 #endif
       if (!mRange->IsInSelection() || mIsNested) {
--- a/dom/base/test/test_user_select.html
+++ b/dom/base/test/test_user_select.html
@@ -7,17 +7,17 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
 <style type="text/css">
 @font-face {
   font-family: Ahem;
   src: url("Ahem.ttf");
 }
 body { font-family: Ahem; font-size: 20px; }
-s, .non-selectable { -moz-user-select: none; }
+s { -moz-user-select: none; }
 n { display: none; }
 a { position:absolute; bottom: 0; right:0; }
 .text { -moz-user-select: text; }
 </style>
 
 </head>
 <body>
 
@@ -29,26 +29,16 @@ a { position:absolute; bottom: 0; right:
 <div id="test6">aaaaaaabbbbbbbb<x><s>ccccccc</s></x></div>
 <div id="test7">aaaaaaa<x><s><n>bbbb</n>bbbb</s></x>ccccccc</div>
 <div id="test8"><x><s>aa<n>aaa</n>aa</s></x>bbbbbbbbccccccc</div>
 <div id="test9">aaaaaaabbbbbbbb<x><s>cc<n>ccccc</n></s></x></div>
 <div id="testA">aaaaaaa<n>bbb<s>bbbbb</s></n>ccccccc</div>
 <div id="testB"><n><s>aaaa</s>aaa</n>bbbbbbbbccccccc</div>
 <div id="testC">aaaaaaabbbbbbbb<n>cc<s>c</s>cccc</n></div>
 <div id="testE">aaa<s id="testEc1">aaaa<a class="text">bbbb</a>dd<a>cccc</a>ddddddd</s>eeee</div>
-<div id="testF">aaaa
-<div class="non-selectable">x</div>
-<div class="non-selectable">x</div>
-<div class="non-selectable">x</div>
-bbbb</div>
-<div id="testG" style="white-space:pre">aaaa
-<div class="non-selectable">x</div>
-<div class="non-selectable">x</div>
-<div class="non-selectable">x</div>
-bbbb</div>
 
 <iframe id="testD" src="data:text/html,<body>aaaa<span style='-moz-user-select:none'>bbbb</span>cccc"></iframe>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 function test()
 {
@@ -105,21 +95,19 @@ function test()
   }
 
   function checkRangeText(text, index)
   {
     var r = window.getSelection().getRangeAt(index);
     is(NL(r.toString()), text, e.id + ": range["+index+"].toString()")
   }
 
-  function node(e, arg)
+  function node(e, index)
   {
-    if (typeof arg == "number")
-      return arg == -1 ? e : e.childNodes[arg];
-    return arg;
+    return index == -1 ? e : e.childNodes[index];
   }
 
   function checkRangeCount(n, e)
   {
     var sel = window.getSelection();
     is(sel.rangeCount, n, e.id + ": Selection range count");
   }
 
@@ -265,32 +253,16 @@ function test()
   checkRangeText('ccccccc', 0);
   checkText('', e);
   shiftClick(e, 20);
   checkRangeText('aaaaaabbbbbbbb', 0);
   checkText('aaaaaabbbbbbbb', e);
   checkRanges([[0,1,-1,1]], e);
   doneTest(e);
 
-  clear();
-  e = document.getElementById('testF');
-  synthesizeMouse(e, 1, 1, {});
-  synthesizeMouse(e, 400, 100, { shiftKey: true });
-  checkText("aaaa bbbb", e);
-  checkRanges([[0,0,-1,1],[6,0,6,5]], e);
-  doneTest(e);
-
-  clear();
-  e = document.getElementById('testG');
-  synthesizeMouse(e, 1, 1, {});
-  synthesizeMouse(e, 400, 180, { shiftKey: true });
-  checkText("aaaa bbbb", e); // XXX this doesn't seem right - bug 1247799
-  checkRanges([[0,0,-1,1],[2,0,-1,3],[4,0,-1,5],[6,0,6,5]], e);
-  doneTest(e);
-
   // ======================================================
   // ==================== Script tests ====================
   // ======================================================
 
   clear();
   e = document.getElementById('testD');
   clear(e.contentWindow);
   sel = e.contentWindow.getSelection();
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -22,17 +22,16 @@
 #include "nsRect.h"
 #include "plarena.h"
 #include "nsRegion.h"
 #include "nsDisplayListInvalidation.h"
 #include "nsRenderingContext.h"
 #include "DisplayListClipState.h"
 #include "LayerState.h"
 #include "FrameMetrics.h"
-#include "mozilla/Maybe.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/UserData.h"
 
 #include <stdint.h>
 #include "nsTHashtable.h"
 
 #include <stdlib.h>
 #include <algorithm>
@@ -4371,18 +4370,16 @@ public:
       ? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr;
   }
 
   // Lengths measured from the visual inline start and end sides
   // (i.e. left and right respectively in horizontal writing modes,
   // regardless of bidi directionality; top and bottom in vertical modes).
   nscoord mVisIStartEdge;
   nscoord mVisIEndEdge;
-  // Cached result of mFrame->IsSelected().  Only initialized when needed.
-  mutable mozilla::Maybe<bool> mIsFrameSelected;
 };
 
 /**
  * A wrapper layer that wraps its children in a container, then renders
  * everything with an appropriate VR effect based on the HMDInfo.
  */
 
 class nsDisplayVR : public nsDisplayOwnLayer {
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4652,22 +4652,20 @@ nsTextFrame::CharacterDataChanged(Charac
     }
   }
 
   return NS_OK;
 }
 
 class nsDisplayText : public nsCharClipDisplayItem {
 public:
-  nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame,
-                Maybe<bool> aIsSelected) :
+  nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame) :
     nsCharClipDisplayItem(aBuilder, aFrame),
     mOpacity(1.0f),
     mDisableSubpixelAA(false) {
-    mIsFrameSelected = aIsSelected;
     MOZ_COUNT_CTOR(nsDisplayText);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayText() {
     MOZ_COUNT_DTOR(nsDisplayText);
   }
 #endif
 
@@ -4831,32 +4829,28 @@ nsTextFrame::BuildDisplayList(nsDisplayL
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
     return;
   
   DO_GLOBAL_REFLOW_COUNT_DSP("nsTextFrame");
 
-  Maybe<bool> isSelected;
   if (((GetStateBits() & TEXT_NO_RENDERED_GLYPHS) ||
        (NS_GET_A(StyleColor()->mColor) == 0 && !StyleText()->HasTextShadow())) &&
-      aBuilder->IsForPainting() && !IsSVGText()) {
-    isSelected.emplace(IsSelected());
-    if (!isSelected) {
-      TextDecorations textDecs;
-      GetTextDecorations(PresContext(), eResolvedColors, textDecs);
-      if (!textDecs.HasDecorationLines()) {
-        return;
-      }
+      aBuilder->IsForPainting() && !IsSVGText() && !IsSelected()) {
+    TextDecorations textDecs;
+    GetTextDecorations(PresContext(), eResolvedColors, textDecs);
+    if (!textDecs.HasDecorationLines()) {
+      return;
     }
   }
 
   aLists.Content()->AppendNewToTop(
-    new (aBuilder) nsDisplayText(aBuilder, this, isSelected));
+    new (aBuilder) nsDisplayText(aBuilder, this));
 }
 
 static nsIFrame*
 GetGeneratedContentOwner(nsIFrame* aFrame, bool* aIsBefore)
 {
   *aIsBefore = false;
   while (aFrame && (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
     if (aFrame->StyleContext()->GetPseudo() == nsCSSPseudoElements::before) {
@@ -6491,22 +6485,19 @@ nsTextFrame::PaintText(nsRenderingContex
   // Don't pass in aRenderingContext here, because we need a *reference*
   // context and aRenderingContext might have some transform in it
   // XXX get the block and line passed to us somehow! This is slow!
   gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
   if (!mTextRun)
     return;
 
   PropertyProvider provider(this, iter, nsTextFrame::eInflated);
-  if (aItem.mIsFrameSelected.isNothing()) {
-    aItem.mIsFrameSelected.emplace(IsSelected());
-  }
   // Trim trailing whitespace, unless we're painting a selection highlight,
   // which should include trailing spaces if present (bug 1146754).
-  provider.InitializeForDisplay(!aItem.mIsFrameSelected.value());
+  provider.InitializeForDisplay(!IsSelected());
 
   gfxContext* ctx = aRenderingContext->ThebesContext();
   const bool reversed = mTextRun->IsInlineReversed();
   const bool verticalRun = mTextRun->IsVertical();
   WritingMode wm = GetWritingMode();
   const nscoord frameWidth = GetSize().width;
   gfxPoint framePt(aPt.x, aPt.y);
   gfxPoint textBaselinePt;
@@ -6540,17 +6531,17 @@ nsTextFrame::PaintText(nsRenderingContex
   nsCharClipDisplayItem::ClipEdges clipEdges(aItem, snappedStartEdge,
                                              snappedEndEdge);
   nsTextPaintStyle textPaintStyle(this);
   textPaintStyle.SetResolveColors(!aCallbacks);
 
   gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y,
                     aDirtyRect.width, aDirtyRect.height);
   // Fork off to the (slower) paint-with-selection path if necessary.
-  if (aItem.mIsFrameSelected.value()) {
+  if (IsSelected()) {
     MOZ_ASSERT(aOpacity == 1.0f, "We don't support opacity with selections!");
     gfxSkipCharsIterator tmp(provider.GetStart());
     int32_t contentOffset = tmp.ConvertSkippedToOriginal(startOffset);
     int32_t contentLength =
       tmp.ConvertSkippedToOriginal(startOffset + maxLength) - contentOffset;
     if (PaintTextWithSelection(ctx, framePt, textBaselinePt, dirtyRect,
                                provider, contentOffset, contentLength,
                                textPaintStyle, clipEdges, aContextPaint,
--- a/mfbt/BinarySearch.h
+++ b/mfbt/BinarySearch.h
@@ -42,17 +42,17 @@ namespace mozilla {
  *
  * the value.
  *
  * Example:
  *
  *   struct Comparator {
  *     int operator()(int val) const {
  *       if (mTarget < val) return -1;
- *       if (mTarget > val) return 1;
+ *       if (mValue > val) return 1;
  *       return 0;
  *     }
  *     Comparator(int target) : mTarget(target) {}
        const int mTarget;
  *   };
  *
  *   Vector<int> sortedInts = ...
  *