Backed out 5 changesets (bug 1302470) for causing bug 1323200 a=backout
authorWes Kocher <wkocher@mozilla.com>
Fri, 16 Dec 2016 16:45:09 -0800
changeset 326242 34a1ab064cb5b868fa75cb74d052e978eb34d6c1
parent 326241 119f24606f99d82c6539763a778bb24f9df28037
child 326243 38e6552bbf0f202980cb7a37f2939813593fd4ef
child 326258 ea640163f898cdc3dfe3dea222c2a01897c0889e
child 326284 da15ea8d6fa5433e275cffe3ec820a74d413c938
push id35182
push userkwierso@gmail.com
push dateSat, 17 Dec 2016 00:53:10 +0000
treeherderautoland@38e6552bbf0f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1302470, 1323200
milestone53.0a1
backs out005adbf78cd24afd81a24902ad8802d1b1d0c5aa
113f7b13475cc8de15f8d253cee720e3a9df8ce1
3d2569996ebc5b4625f9a221c78c00cb982a8735
b92b78271941789fc06c7b9ec7cd9c566b7fc20a
5b92678afff8770634c1125fd48d63f6a0c3ba23
first release with
nightly linux32
34a1ab064cb5 / 53.0a1 / 20161217030205 / files
nightly linux64
34a1ab064cb5 / 53.0a1 / 20161217030205 / files
nightly mac
34a1ab064cb5 / 53.0a1 / 20161217030205 / files
nightly win32
34a1ab064cb5 / 53.0a1 / 20161217030205 / files
nightly win64
34a1ab064cb5 / 53.0a1 / 20161217030205 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 5 changesets (bug 1302470) for causing bug 1323200 a=backout Backed out changeset 005adbf78cd2 (bug 1302470) Backed out changeset 113f7b13475c (bug 1302470) Backed out changeset 3d2569996ebc (bug 1302470) Backed out changeset b92b78271941 (bug 1302470) Backed out changeset 5b92678afff8 (bug 1302470) MozReview-Commit-ID: FgeA5OQV8WP
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/forms/nsHTMLButtonControlFrame.cpp
toolkit/components/typeaheadfind/nsITypeAheadFind.idl
toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
toolkit/components/typeaheadfind/nsTypeAheadFind.h
toolkit/modules/FinderHighlighter.jsm
toolkit/modules/FinderIterator.jsm
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3168,33 +3168,32 @@ nsLayoutUtils::GetFramesForArea(nsIFrame
     if (rootScrollFrame) {
       builder.SetIgnoreScrollFrame(rootScrollFrame);
     }
   }
   if (aFlags & IGNORE_CROSS_DOC) {
     builder.SetDescendIntoSubdocuments(false);
   }
 
-  builder.SetHitTestShouldStopAtFirstOpaque(aFlags & ONLY_VISIBLE);
-
   builder.EnterPresShell(aFrame);
   aFrame->BuildDisplayListForStackingContext(&builder, aRect, &list);
   builder.LeavePresShell(aFrame, nullptr);
 
 #ifdef MOZ_DUMP_PAINTING
   if (gDumpEventList) {
     fprintf_stderr(stderr, "Event handling --- (%d,%d):\n", aRect.x, aRect.y);
 
     std::stringstream ss;
     nsFrame::PrintDisplayList(&builder, list, ss);
     print_stderr(ss);
   }
 #endif
 
   nsDisplayItem::HitTestState hitTestState;
+  builder.SetHitTestShouldStopAtFirstOpaque(aFlags & ONLY_VISIBLE);
   list.HitTest(&builder, aRect, &hitTestState, &aOutFrames);
   list.DeleteAll();
   return NS_OK;
 }
 
 // aScrollFrameAsScrollable must be non-nullptr and queryable to an nsIFrame
 FrameMetrics
 nsLayoutUtils::CalculateBasicFrameMetrics(nsIScrollableFrame* aScrollFrame) {
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -820,17 +820,17 @@ public:
   static nsIFrame* GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt,
                                     uint32_t aFlags = 0);
 
   /**
    * Given aFrame, the root frame of a stacking context, find all descendant
    * frames under the area of a rectangle that receives a mouse event,
    * or nullptr if there is no such frame.
    * @param aRect the rect, relative to the frame origin
-   * @param aOutFrames an array to append all the frames found
+   * @param aOutFrames an array to add all the frames found
    * @param aFlags some combination of FrameForPointFlags
    */
   static nsresult GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
                                    nsTArray<nsIFrame*> &aOutFrames,
                                    uint32_t aFlags = 0);
 
   /**
    * Transform aRect relative to aFrame up to the coordinate system of
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -114,17 +114,17 @@ nsHTMLButtonControlFrame::BuildDisplayLi
   nsDisplayList onTop;
   if (IsVisibleForPainting(aBuilder)) {
     mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop);
   }
 
   nsDisplayListCollection set;
 
   // Do not allow the child subtree to receive events.
-  if (!isForEventDelivery || aBuilder->HitTestShouldStopAtFirstOpaque()) {
+  if (!isForEventDelivery) {
     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
 
     if (ShouldClipPaintingToBorderBox()) {
       nsMargin border = StyleBorder()->GetComputedBorder();
       nsRect rect(aBuilder->ToReferenceFrame(this), GetSize());
       rect.Deflate(border);
       nscoord radii[8];
       bool hasRadii = GetPaddingBoxBorderRadii(radii);
--- a/toolkit/components/typeaheadfind/nsITypeAheadFind.idl
+++ b/toolkit/components/typeaheadfind/nsITypeAheadFind.idl
@@ -13,17 +13,17 @@
 /******************************** Declarations *******************************/
 
 interface mozIDOMWindow;
 interface nsIDocShell;
 
 
 /****************************** nsTypeAheadFind ******************************/
 
-[scriptable, uuid(3cfe7906-f189-45a0-8abe-8e4437a23cae)]
+[scriptable, uuid(ae501e28-c57f-4692-ac74-410e1bed98b7)]
 interface nsITypeAheadFind : nsISupports
 {
   /****************************** Initializer ******************************/
 
   /* Necessary initialization that can't happen in the constructor, either
    * because function calls here may fail, or because the docShell is
    * required. */
   void init(in nsIDocShell aDocShell);
@@ -53,17 +53,17 @@ interface nsITypeAheadFind : nsISupports
   void setSelectionModeAndRepaint(in short toggle);
 
   /* Collapse the "found match" selection to its start.  Because not all
    * matches are owned by the same selection controller, this doesn't
    * necessarily happen automatically. */
   void collapseSelection();
 
   /* Check if a range is visible */
-  boolean isRangeVisible(in nsIDOMRange aRange, in boolean aFlushLayout);
+  boolean isRangeVisible(in nsIDOMRange aRange, in boolean aMustBeInViewPort);
 
   /******************************* Attributes ******************************/
 
   readonly attribute AString searchString;
                                         // Most recent search string
   attribute boolean caseSensitive;      // Searches are case sensitive
   attribute boolean entireWord;         // Search for whole words only
   readonly attribute nsIDOMElement foundLink;
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -47,17 +47,16 @@
 #include "nsNameSpaceManager.h"
 #include "nsIWindowWatcher.h"
 #include "nsIObserverService.h"
 #include "nsFocusManager.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Link.h"
 #include "nsRange.h"
 #include "nsXBLBinding.h"
-#include "nsLayoutUtils.h"
 
 #include "nsTypeAheadFind.h"
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTypeAheadFind)
   NS_INTERFACE_MAP_ENTRY(nsITypeAheadFind)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITypeAheadFind)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
@@ -66,16 +65,18 @@ NS_INTERFACE_MAP_END
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTypeAheadFind)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTypeAheadFind)
 
 NS_IMPL_CYCLE_COLLECTION(nsTypeAheadFind, mFoundLink, mFoundEditable,
                          mCurrentWindow, mStartFindRange, mSearchRange,
                          mStartPointRange, mEndPointRange, mSoundInterface,
                          mFind, mFoundRange)
 
+static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
+
 #define NS_FIND_CONTRACTID "@mozilla.org/embedcomp/rangefind;1"
 
 nsTypeAheadFind::nsTypeAheadFind():
   mStartLinksOnlyPref(false),
   mCaretBrowsingOn(false),
   mDidAddObservers(false),
   mLastFindLength(0),
   mIsSoundInitialized(false),
@@ -416,31 +417,32 @@ nsTypeAheadFind::FindItNow(nsIPresShell 
     return NS_ERROR_FAILURE;
 
   mFind->SetFindBackwards(aFindPrev);
 
   while (true) {    // ----- Outer while loop: go through all docs -----
     while (true) {  // === Inner while loop: go through a single doc ===
       mFind->Find(mTypeAheadBuffer.get(), mSearchRange, mStartPointRange,
                   mEndPointRange, getter_AddRefs(returnRange));
-
+      
       if (!returnRange)
         break;  // Nothing found in this doc, go to outer loop (try next doc)
 
       // ------- Test resulting found range for success conditions ------
       bool isInsideLink = false, isStartingLink = false;
 
       if (aIsLinksOnly) {
         // Don't check if inside link when searching all text
         RangeStartsInsideLink(returnRange, presShell, &isInsideLink,
                               &isStartingLink);
       }
 
       bool usesIndependentSelection;
-      if (!IsRangeVisible(presShell, presContext, returnRange, true,
+      if (!IsRangeVisible(presShell, presContext, returnRange,
+                          aIsFirstVisiblePreferred, false,
                           getter_AddRefs(mStartPointRange), 
                           &usesIndependentSelection) ||
           (aIsLinksOnly && !isInsideLink) ||
           (mStartLinksOnlyPref && aIsLinksOnly && !isStartingLink)) {
         // ------ Failure ------
         // At this point mStartPointRange got updated to the first
         // visible range in the viewport.  We _may_ be able to just
         // start there, if it's not taking us in the wrong direction.
@@ -810,17 +812,18 @@ nsTypeAheadFind::GetSearchContainers(nsI
     if (selection)
       selection->GetRangeAt(0, getter_AddRefs(currentSelectionRange));
   }
 
   if (!currentSelectionRange) {
     // Ensure visible range, move forward if necessary
     // This uses ignores the return value, but usese the side effect of
     // IsRangeVisible. It returns the first visible range after searchRange
-    IsRangeVisible(presShell, presContext, mSearchRange, true,
+    IsRangeVisible(presShell, presContext, mSearchRange, 
+                   aIsFirstVisiblePreferred, true, 
                    getter_AddRefs(mStartPointRange), nullptr);
   }
   else {
     int32_t startOffset;
     nsCOMPtr<nsIDOMNode> startNode;
     if (aFindPrev) {
       currentSelectionRange->GetStartContainer(getter_AddRefs(startNode));
       currentSelectionRange->GetStartOffset(&startOffset);
@@ -1000,28 +1003,28 @@ nsTypeAheadFind::Find(const nsAString& a
     // is typed
     mStartFindRange = nullptr;
     mSelectionController = nullptr;
 
     *aResult = FIND_FOUND;
     return NS_OK;
   }
 
-  bool atEnd = false;
+  bool atEnd = false;    
   if (mTypeAheadBuffer.Length()) {
     const nsAString& oldStr = Substring(mTypeAheadBuffer, 0, mTypeAheadBuffer.Length());
     const nsAString& newStr = Substring(aSearchString, 0, mTypeAheadBuffer.Length());
     if (oldStr.Equals(newStr))
       atEnd = true;
-
+  
     const nsAString& newStr2 = Substring(aSearchString, 0, aSearchString.Length());
     const nsAString& oldStr2 = Substring(mTypeAheadBuffer, 0, aSearchString.Length());
     if (oldStr2.Equals(newStr2))
       atEnd = true;
-
+    
     if (!atEnd)
       mStartFindRange = nullptr;
   }
 
   if (!mIsSoundInitialized && !mNotFoundSoundURL.IsEmpty()) {
     // This makes sure system sound library is loaded so that
     // there's no lag before the first sound is played
     // by waiting for the first keystroke, we still get the startup time benefits.
@@ -1153,122 +1156,160 @@ nsTypeAheadFind::GetFoundRange(nsIDOMRan
   }
 
   mFoundRange->CloneRange(aFoundRange);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTypeAheadFind::IsRangeVisible(nsIDOMRange *aRange,
-                                bool aFlushLayout,
+                                bool aMustBeInViewPort,
                                 bool *aResult)
 {
   // Jump through hoops to extract the docShell from the range.
   nsCOMPtr<nsIDOMNode> node;
   aRange->GetStartContainer(getter_AddRefs(node));
   nsCOMPtr<nsIDOMDocument> document;
   node->GetOwnerDocument(getter_AddRefs(document));
   nsCOMPtr<mozIDOMWindowProxy> window;
   document->GetDefaultView(getter_AddRefs(window));
   nsCOMPtr<nsIWebNavigation> navNav (do_GetInterface(window));
   nsCOMPtr<nsIDocShell> docShell (do_GetInterface(navNav));
 
   // Set up the arguments needed to check if a range is visible.
   nsCOMPtr<nsIPresShell> presShell (docShell->GetPresShell());
   RefPtr<nsPresContext> presContext = presShell->GetPresContext();
   nsCOMPtr<nsIDOMRange> startPointRange = new nsRange(presShell->GetDocument());
-  *aResult = IsRangeVisible(presShell, presContext, aRange, aFlushLayout,
+  *aResult = IsRangeVisible(presShell, presContext, aRange,
+                            aMustBeInViewPort, false,
                             getter_AddRefs(startPointRange),
                             nullptr);
   return NS_OK;
 }
 
 bool
 nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell,
                                 nsPresContext *aPresContext,
-                                nsIDOMRange *aRange,
-                                bool aFlushLayout,
+                                nsIDOMRange *aRange, bool aMustBeInViewPort,
+                                bool aGetTopVisibleLeaf,
                                 nsIDOMRange **aFirstVisibleRange,
                                 bool *aUsesIndependentSelection)
 {
   NS_ASSERTION(aPresShell && aPresContext && aRange && aFirstVisibleRange, 
                "params are invalid");
 
-  // We need to know if the range start and end are both visible.
-  // In all cases, return the first visible range in aFirstVisibleRange.
-  aRange->CloneRange(aFirstVisibleRange);
+  // We need to know if the range start is visible.
+  // Otherwise, return the first visible range start 
+  // in aFirstVisibleRange
 
-  if (aFlushLayout) {
-    aPresShell->FlushPendingNotifications(Flush_Layout);
-  }
-
+  aRange->CloneRange(aFirstVisibleRange);
   nsCOMPtr<nsIDOMNode> node;
-  aRange->GetCommonAncestorContainer(getter_AddRefs(node));
+  aRange->GetStartContainer(getter_AddRefs(node));
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(node));
-  if (!content) {
+  if (!content)
     return false;
-  }
 
   nsIFrame *frame = content->GetPrimaryFrame();
-  if (!frame) {
+  if (!frame)    
     return false;  // No frame! Not visible then.
-  }
-
-  // Having a primary frame doesn't mean that the range is visible inside the
-  // viewport. Do a hit-test to determine that quickly and properly.
-  bool foundContent = false;
-  AutoTArray<nsIFrame*,8> frames;
-  nsIFrame *rootFrame = aPresShell->GetRootFrame();
-  RefPtr<nsRange> range = static_cast<nsRange*>(aRange);
-  RefPtr<mozilla::dom::DOMRectList> rects = range->GetClientRects(true, false);
-  for (uint32_t i = 0; i < rects->Length(); ++i) {
-    RefPtr<mozilla::dom::DOMRect> rect = rects->Item(i);
-    nsRect r(nsPresContext::CSSPixelsToAppUnits((float)rect->X()),
-             nsPresContext::CSSPixelsToAppUnits((float)rect->Y()),
-             nsPresContext::CSSPixelsToAppUnits((float)rect->Width()),
-             nsPresContext::CSSPixelsToAppUnits((float)rect->Height()));
-    // Append visible frames to frames array.
-    nsLayoutUtils::GetFramesForArea(rootFrame, r, frames,
-      nsLayoutUtils::IGNORE_PAINT_SUPPRESSION |
-      nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME |
-      nsLayoutUtils::ONLY_VISIBLE);
 
-    // See if any of the frames contain the content. If they do, then the range
-    // is visible. We search for the content rather than the original frame,
-    // because nsTextContinuation frames might be returned instead of the
-    // original frame.
-    for (const auto &f: frames) {
-      if (f->GetContent() == content) {
-        foundContent = true;
-        break;
-      }
-    }
-
-    if (foundContent) {
-      break;
-    }
-
-    frames.ClearAndRetainStorage();
-  }
-
-  // Test that content appears in the list of framesForArea. If it does, then
-  // that means that content is at least partly visible.
-  if (!foundContent) {
+  if (!frame->StyleVisibility()->IsVisible())
     return false;
-  }
 
   // Detect if we are _inside_ a text control, or something else with its own
   // selection controller.
   if (aUsesIndependentSelection) {
     *aUsesIndependentSelection = 
       (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
   }
 
-  return true;
+  // ---- We have a frame ----
+  if (!aMustBeInViewPort)   
+    return true; //  Don't need it to be on screen, just in rendering tree
+
+  // Get the next in flow frame that contains the range start
+  int32_t startRangeOffset, startFrameOffset, endFrameOffset;
+  aRange->GetStartOffset(&startRangeOffset);
+  while (true) {
+    frame->GetOffsets(startFrameOffset, endFrameOffset);
+    if (startRangeOffset < endFrameOffset)
+      break;
+
+    nsIFrame *nextContinuationFrame = frame->GetNextContinuation();
+    if (nextContinuationFrame)
+      frame = nextContinuationFrame;
+    else
+      break;
+  }
+
+  // Set up the variables we need, return true if we can't get at them all
+  const uint16_t kMinPixels  = 12;
+  nscoord minDistance = nsPresContext::CSSPixelsToAppUnits(kMinPixels);
+
+  // Get the bounds of the current frame, relative to the current view.
+  // We don't use the more accurate AccGetBounds, because that is
+  // more expensive and the STATE_OFFSCREEN flag that this is used
+  // for only needs to be a rough indicator
+  nsRectVisibility rectVisibility = nsRectVisibility_kAboveViewport;
+
+  if (!aGetTopVisibleLeaf && !frame->GetRect().IsEmpty()) {
+    rectVisibility =
+      aPresShell->GetRectVisibility(frame,
+                                    nsRect(nsPoint(0,0), frame->GetSize()),
+                                    minDistance);
+
+    if (rectVisibility != nsRectVisibility_kAboveViewport) {
+      return true;
+    }
+  }
+
+  // We know that the target range isn't usable because it's not in the
+  // view port. Move range forward to first visible point,
+  // this speeds us up a lot in long documents
+  nsCOMPtr<nsIFrameEnumerator> frameTraversal;
+  nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID));
+  if (trav)
+    trav->NewFrameTraversal(getter_AddRefs(frameTraversal),
+                            aPresContext, frame,
+                            eLeaf,
+                            false, // aVisual
+                            false, // aLockInScrollView
+                            false, // aFollowOOFs
+                            false  // aSkipPopupChecks
+                            );
+
+  if (!frameTraversal)
+    return false;
+
+  while (rectVisibility == nsRectVisibility_kAboveViewport) {
+    frameTraversal->Next();
+    frame = frameTraversal->CurrentItem();
+    if (!frame)
+      return false;
+
+    if (!frame->GetRect().IsEmpty()) {
+      rectVisibility =
+        aPresShell->GetRectVisibility(frame,
+                                      nsRect(nsPoint(0,0), frame->GetSize()),
+                                      minDistance);
+    }
+  }
+
+  if (frame) {
+    nsCOMPtr<nsIDOMNode> firstVisibleNode = do_QueryInterface(frame->GetContent());
+
+    if (firstVisibleNode) {
+      frame->GetOffsets(startFrameOffset, endFrameOffset);
+      (*aFirstVisibleRange)->SetStart(firstVisibleNode, startFrameOffset);
+      (*aFirstVisibleRange)->SetEnd(firstVisibleNode, endFrameOffset);
+    }
+  }
+
+  return false;
 }
 
 already_AddRefed<nsIPresShell>
 nsTypeAheadFind::GetPresShell()
 {
   if (!mPresShell)
     return nullptr;
 
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.h
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.h
@@ -51,18 +51,18 @@ protected:
   void RangeStartsInsideLink(nsIDOMRange *aRange, nsIPresShell *aPresShell, 
                              bool *aIsInsideLink, bool *aIsStartingLink);
 
   void GetSelection(nsIPresShell *aPresShell, nsISelectionController **aSelCon, 
                     nsISelection **aDomSel);
   // *aNewRange may not be collapsed.  If you want to collapse it in a
   // particular way, you need to do it yourself.
   bool IsRangeVisible(nsIPresShell *aPresShell, nsPresContext *aPresContext,
-                        nsIDOMRange *aRange, bool aFlushLayout,
-                        nsIDOMRange **aNewRange,
+                        nsIDOMRange *aRange, bool aMustBeVisible, 
+                        bool aGetTopVisibleLeaf, nsIDOMRange **aNewRange,
                         bool *aUsesIndependentSelection);
   nsresult FindItNow(nsIPresShell *aPresShell, bool aIsLinksOnly,
                      bool aIsFirstVisiblePreferred, bool aFindPrev,
                      uint16_t* aResult);
   nsresult GetSearchContainers(nsISupports *aContainer,
                                nsISelectionController *aSelectionController,
                                bool aIsFirstVisiblePreferred,
                                bool aFindPrev, nsIPresShell **aPresShell,
@@ -90,17 +90,17 @@ protected:
   // mLastFindLength is the character length of the last find string.  It is used for
   // disabling the "not found" sound when using backspace or delete
   uint32_t mLastFindLength;
 
   // Sound is played asynchronously on some platforms.
   // If we destroy mSoundInterface before sound has played, it won't play
   nsCOMPtr<nsISound> mSoundInterface;
   bool mIsSoundInitialized;
-
+  
   // where selection was when user started the find
   nsCOMPtr<nsIDOMRange> mStartFindRange;
   nsCOMPtr<nsIDOMRange> mSearchRange;
   nsCOMPtr<nsIDOMRange> mStartPointRange;
   nsCOMPtr<nsIDOMRange> mEndPointRange;
 
   // Cached useful interfaces
   nsCOMPtr<nsIFind> mFind;
--- a/toolkit/modules/FinderHighlighter.jsm
+++ b/toolkit/modules/FinderHighlighter.jsm
@@ -1132,19 +1132,16 @@ FinderHighlighter.prototype = {
     this._updateRangeOutline(dict);
 
     let allRects = [];
     if (paintContent || dict.modalHighlightAllMask) {
       this._updateDynamicRangesRects(dict);
 
       let DOMRect = window.DOMRect;
       for (let [range, rectsAndTexts] of dict.modalHighlightRectsMap) {
-        if (!this.finder._fastFind.isRangeVisible(range, false))
-          continue;
-
         if (dict.updateAllRanges)
           rectsAndTexts = this._updateRangeRects(range);
 
         // If a geometry change was detected, we bail out right away here, because
         // the current set of ranges has been invalidated.
         if (dict.detectedGeometryChange)
           return;
 
--- a/toolkit/modules/FinderIterator.jsm
+++ b/toolkit/modules/FinderIterator.jsm
@@ -562,17 +562,23 @@ this.FinderIterator = {
       return frames;
 
     // Casting `window.frames` to an Iterator doesn't work, so we're stuck with
     // a plain, old for-loop.
     for (let i = 0, l = window.frames.length; i < l; ++i) {
       let frame = window.frames[i];
       // Don't count matches in hidden frames.
       let frameEl = frame && frame.frameElement;
-      if (!frameEl || !frameEl.getClientRects().length)
+      if (!frameEl)
+        continue;
+      // Construct a range around the frame element to check its visiblity.
+      let range = window.document.createRange();
+      range.setStart(frameEl, 0);
+      range.setEnd(frameEl, 0);
+      if (!finder._fastFind.isRangeVisible(range, this._getDocShell(range), true))
         continue;
       // All conditions pass, so push the current frame and its children on the
       // stack.
       frames.push(frame, ...this._collectFrames(frame, finder));
     }
 
     return frames;
   },