Bug 1297572 - Handle the root scroll frame in AllChildrenIterator. r=heycam
authorBobby Holley <bobbyholley@gmail.com>
Tue, 23 Aug 2016 18:19:10 -0700
changeset 311351 6789cc1bb12a
parent 311350 e6a1ddda457e
child 311352 5c03203fbf49
push id30607
push userryanvm@gmail.com
push date2016-08-26 13:37 +0000
treeherdermozilla-central@a65b35c8e5b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1297572
milestone51.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 1297572 - Handle the root scroll frame in AllChildrenIterator. r=heycam
dom/base/ChildIterator.cpp
dom/base/ChildIterator.h
--- a/dom/base/ChildIterator.cpp
+++ b/dom/base/ChildIterator.cpp
@@ -370,16 +370,41 @@ AllChildrenIterator::Seek(nsIContent* aC
   nsIContent* child = nullptr;
   do {
     child = GetNextChild();
   } while (child && child != aChildToFind);
 
   return child == aChildToFind;
 }
 
+void
+AllChildrenIterator::AppendNativeAnonymousChildren()
+{
+  AppendNativeAnonymousChildrenFromFrame(mOriginalContent->GetPrimaryFrame());
+
+  // The root scroll frame is not the primary frame of the root element.
+  // Detect and handle this case.
+  if (mOriginalContent == mOriginalContent->OwnerDoc()->GetRootElement()) {
+    nsIPresShell* presShell = mOriginalContent->OwnerDoc()->GetShell();
+    nsIFrame* scrollFrame = presShell ? presShell->GetRootScrollFrame() : nullptr;
+    if (scrollFrame) {
+      AppendNativeAnonymousChildrenFromFrame(scrollFrame);
+    }
+  }
+}
+
+void
+AllChildrenIterator::AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame)
+{
+  nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame);
+  if (ac) {
+    ac->AppendAnonymousContentTo(mAnonKids, mFlags);
+  }
+}
+
 nsIContent*
 AllChildrenIterator::GetNextChild()
 {
   if (mPhase == eAtBegin) {
     mPhase = eAtExplicitKids;
     nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
     if (frame) {
       nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
@@ -401,21 +426,17 @@ AllChildrenIterator::GetNextChild()
       return kid;
     }
     mPhase = eAtAnonKids;
   }
 
   if (mPhase == eAtAnonKids) {
     if (mAnonKids.IsEmpty()) {
       MOZ_ASSERT(mAnonKidsIdx == UINT32_MAX);
-      nsIAnonymousContentCreator* ac =
-        do_QueryFrame(mOriginalContent->GetPrimaryFrame());
-      if (ac) {
-        ac->AppendAnonymousContentTo(mAnonKids, mFlags);
-      }
+      AppendNativeAnonymousChildren();
       mAnonKidsIdx = 0;
     }
     else {
       if (mAnonKidsIdx == UINT32_MAX) {
         mAnonKidsIdx = 0;
       }
       else {
         mAnonKidsIdx++;
@@ -457,22 +478,18 @@ AllChildrenIterator::GetPreviousChild()
   }
 
   if (mPhase == eAtAfterKid) {
     mPhase = eAtAnonKids;
   }
 
   if (mPhase == eAtAnonKids) {
     if (mAnonKids.IsEmpty()) {
-      nsIAnonymousContentCreator* ac =
-        do_QueryFrame(mOriginalContent->GetPrimaryFrame());
-      if (ac) {
-        ac->AppendAnonymousContentTo(mAnonKids, mFlags);
-        mAnonKidsIdx = mAnonKids.Length();
-      }
+      AppendNativeAnonymousChildren();
+      mAnonKidsIdx = mAnonKids.Length();
     }
 
     // If 0 then it turns into UINT32_MAX, which indicates the iterator is
     // before the anonymous children.
     --mAnonKidsIdx;
     if (mAnonKidsIdx < mAnonKids.Length()) {
       return mAnonKids[mAnonKidsIdx];
     }
--- a/dom/base/ChildIterator.h
+++ b/dom/base/ChildIterator.h
@@ -220,16 +220,20 @@ public:
     eAtExplicitKids,
     eAtAnonKids,
     eAtAfterKid,
     eAtEnd
   };
   IteratorPhase Phase() const { return mPhase; }
 
 private:
+  // Helpers.
+  void AppendNativeAnonymousChildren();
+  void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame);
+
   nsIContent* mOriginalContent;
 
   // mAnonKids is an array of native anonymous children, mAnonKidsIdx is index
   // in the array. If mAnonKidsIdx < mAnonKids.Length() and mPhase is
   // eAtAnonKids then the iterator points at a child at mAnonKidsIdx index. If
   // mAnonKidsIdx == mAnonKids.Length() then the iterator is somewhere after
   // the last native anon child. If mAnonKidsIdx == UINT32_MAX then the iterator
   // is somewhere before the first native anon child.