LCOV - code coverage report
Current view: top level - layout/generic - nsContainerFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 277 985 28.1 %
Date: 2017-07-14 16:53:18 Functions: 32 69 46.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /* base class #1 for rendering objects that have child lists */
       7             : 
       8             : #include "nsContainerFrame.h"
       9             : 
      10             : #include "mozilla/dom/HTMLDetailsElement.h"
      11             : #include "mozilla/dom/HTMLSummaryElement.h"
      12             : #include "nsAbsoluteContainingBlock.h"
      13             : #include "nsAttrValue.h"
      14             : #include "nsAttrValueInlines.h"
      15             : #include "nsIDocument.h"
      16             : #include "nsPresContext.h"
      17             : #include "nsStyleContext.h"
      18             : #include "nsRect.h"
      19             : #include "nsPoint.h"
      20             : #include "nsStyleConsts.h"
      21             : #include "nsView.h"
      22             : #include "nsIPresShell.h"
      23             : #include "nsCOMPtr.h"
      24             : #include "nsGkAtoms.h"
      25             : #include "nsViewManager.h"
      26             : #include "nsIWidget.h"
      27             : #include "nsCSSRendering.h"
      28             : #include "nsError.h"
      29             : #include "nsDisplayList.h"
      30             : #include "nsIBaseWindow.h"
      31             : #include "nsBoxLayoutState.h"
      32             : #include "nsCSSFrameConstructor.h"
      33             : #include "nsBlockFrame.h"
      34             : #include "nsBulletFrame.h"
      35             : #include "nsPlaceholderFrame.h"
      36             : #include "mozilla/AutoRestore.h"
      37             : #include "nsIFrameInlines.h"
      38             : #include "nsPrintfCString.h"
      39             : #include <algorithm>
      40             : 
      41             : using namespace mozilla;
      42             : using namespace mozilla::dom;
      43             : using namespace mozilla::layout;
      44             : 
      45          76 : nsContainerFrame::~nsContainerFrame()
      46             : {
      47          76 : }
      48             : 
      49        7329 : NS_QUERYFRAME_HEAD(nsContainerFrame)
      50         344 :   NS_QUERYFRAME_ENTRY(nsContainerFrame)
      51        6985 : NS_QUERYFRAME_TAIL_INHERITING(nsSplittableFrame)
      52             : 
      53             : void
      54         448 : nsContainerFrame::Init(nsIContent*       aContent,
      55             :                        nsContainerFrame* aParent,
      56             :                        nsIFrame*         aPrevInFlow)
      57             : {
      58         448 :   nsSplittableFrame::Init(aContent, aParent, aPrevInFlow);
      59         448 :   if (aPrevInFlow) {
      60             :     // Make sure we copy bits from our prev-in-flow that will affect
      61             :     // us. A continuation for a container frame needs to know if it
      62             :     // has a child with a view so that we'll properly reposition it.
      63           0 :     if (aPrevInFlow->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)
      64           0 :       AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
      65             :   }
      66         448 : }
      67             : 
      68             : void
      69         414 : nsContainerFrame::SetInitialChildList(ChildListID  aListID,
      70             :                                       nsFrameList& aChildList)
      71             : {
      72             : #ifdef DEBUG
      73         414 :   nsFrame::VerifyDirtyBitSet(aChildList);
      74             : #endif
      75         414 :   if (aListID == kPrincipalList) {
      76         414 :     MOZ_ASSERT(mFrames.IsEmpty(),
      77             :                "unexpected second call to SetInitialChildList");
      78         414 :     mFrames.SetFrames(aChildList);
      79           0 :   } else if (aListID == kBackdropList) {
      80           0 :     MOZ_ASSERT(StyleDisplay()->mTopLayer != NS_STYLE_TOP_LAYER_NONE,
      81             :                "Only top layer frames should have backdrop");
      82           0 :     MOZ_ASSERT(GetStateBits() & NS_FRAME_OUT_OF_FLOW,
      83             :                "Top layer frames should be out-of-flow");
      84           0 :     MOZ_ASSERT(!GetProperty(BackdropProperty()),
      85             :                "We shouldn't have setup backdrop frame list before");
      86             : #ifdef DEBUG
      87             :     {
      88           0 :       nsIFrame* placeholder = aChildList.FirstChild();
      89           0 :       MOZ_ASSERT(aChildList.OnlyChild(), "Should have only one backdrop");
      90           0 :       MOZ_ASSERT(placeholder->IsPlaceholderFrame(),
      91             :                 "The frame to be stored should be a placeholder");
      92           0 :       MOZ_ASSERT(static_cast<nsPlaceholderFrame*>(placeholder)->
      93             :                 GetOutOfFlowFrame()->IsBackdropFrame(),
      94             :                 "The placeholder should points to a backdrop frame");
      95             :     }
      96             : #endif
      97             :     nsFrameList* list =
      98           0 :       new (PresContext()->PresShell()) nsFrameList(aChildList);
      99           0 :     SetProperty(BackdropProperty(), list);
     100             :   } else {
     101           0 :     MOZ_ASSERT_UNREACHABLE("Unexpected child list");
     102             :   }
     103         414 : }
     104             : 
     105             : void
     106          23 : nsContainerFrame::AppendFrames(ChildListID  aListID,
     107             :                                nsFrameList& aFrameList)
     108             : {
     109          23 :   MOZ_ASSERT(aListID == kPrincipalList || aListID == kNoReflowPrincipalList,
     110             :              "unexpected child list");
     111             : 
     112          23 :   if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
     113          23 :     return;
     114             :   }
     115             : 
     116           0 :   DrainSelfOverflowList(); // ensure the last frame is in mFrames
     117           0 :   mFrames.AppendFrames(this, aFrameList);
     118             : 
     119           0 :   if (aListID != kNoReflowPrincipalList) {
     120           0 :     PresContext()->PresShell()->
     121           0 :       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     122           0 :                        NS_FRAME_HAS_DIRTY_CHILDREN);
     123             :   }
     124             : }
     125             : 
     126             : void
     127           0 : nsContainerFrame::InsertFrames(ChildListID aListID,
     128             :                                nsIFrame* aPrevFrame,
     129             :                                nsFrameList& aFrameList)
     130             : {
     131           0 :   MOZ_ASSERT(aListID == kPrincipalList || aListID == kNoReflowPrincipalList,
     132             :              "unexpected child list");
     133           0 :   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
     134             :                "inserting after sibling frame with different parent");
     135             : 
     136           0 :   if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
     137           0 :     return;
     138             :   }
     139             : 
     140           0 :   DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
     141           0 :   mFrames.InsertFrames(this, aPrevFrame, aFrameList);
     142             : 
     143           0 :   if (aListID != kNoReflowPrincipalList) {
     144           0 :     PresContext()->PresShell()->
     145           0 :       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     146           0 :                        NS_FRAME_HAS_DIRTY_CHILDREN);
     147             :   }
     148             : }
     149             : 
     150             : void
     151           0 : nsContainerFrame::RemoveFrame(ChildListID aListID,
     152             :                               nsIFrame* aOldFrame)
     153             : {
     154           0 :   MOZ_ASSERT(aListID == kPrincipalList || aListID == kNoReflowPrincipalList,
     155             :              "unexpected child list");
     156             : 
     157             :   // Loop and destroy aOldFrame and all of its continuations.
     158             :   // Request a reflow on the parent frames involved unless we were explicitly
     159             :   // told not to (kNoReflowPrincipalList).
     160           0 :   bool generateReflowCommand = true;
     161           0 :   if (kNoReflowPrincipalList == aListID) {
     162           0 :     generateReflowCommand = false;
     163             :   }
     164           0 :   nsIPresShell* shell = PresContext()->PresShell();
     165           0 :   nsContainerFrame* lastParent = nullptr;
     166           0 :   while (aOldFrame) {
     167           0 :     nsIFrame* oldFrameNextContinuation = aOldFrame->GetNextContinuation();
     168           0 :     nsContainerFrame* parent = aOldFrame->GetParent();
     169             :     // Please note that 'parent' may not actually be where 'aOldFrame' lives.
     170             :     // We really MUST use StealFrame() and nothing else here.
     171             :     // @see nsInlineFrame::StealFrame for details.
     172           0 :     parent->StealFrame(aOldFrame);
     173           0 :     aOldFrame->Destroy();
     174           0 :     aOldFrame = oldFrameNextContinuation;
     175           0 :     if (parent != lastParent && generateReflowCommand) {
     176             :       shell->FrameNeedsReflow(parent, nsIPresShell::eTreeChange,
     177           0 :                               NS_FRAME_HAS_DIRTY_CHILDREN);
     178           0 :       lastParent = parent;
     179             :     }
     180             :   }
     181           0 : }
     182             : 
     183             : void
     184          92 : nsContainerFrame::DestroyAbsoluteFrames(nsIFrame* aDestructRoot)
     185             : {
     186          92 :   if (IsAbsoluteContainer()) {
     187           2 :     GetAbsoluteContainingBlock()->DestroyFrames(this, aDestructRoot);
     188           2 :     MarkAsNotAbsoluteContainingBlock();
     189             :   }
     190          92 : }
     191             : 
     192             : void
     193           0 : nsContainerFrame::SafelyDestroyFrameListProp(nsIFrame* aDestructRoot,
     194             :                                              nsIPresShell* aPresShell,
     195             :                                              FrameListPropertyDescriptor aProp)
     196             : {
     197             :   // Note that the last frame can be removed through another route and thus
     198             :   // delete the property -- that's why we fetch the property again before
     199             :   // removing each frame rather than fetching it once and iterating the list.
     200           0 :   while (nsFrameList* frameList = GetProperty(aProp)) {
     201           0 :     nsIFrame* frame = frameList->RemoveFirstChild();
     202           0 :     if (MOZ_LIKELY(frame)) {
     203           0 :       frame->DestroyFrom(aDestructRoot);
     204             :     } else {
     205           0 :       RemoveProperty(aProp);
     206           0 :       frameList->Delete(aPresShell);
     207           0 :       return;
     208             :     }
     209           0 :   }
     210             : }
     211             : 
     212             : void
     213          76 : nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot)
     214             : {
     215             :   // Prevent event dispatch during destruction.
     216          76 :   if (HasView()) {
     217           9 :     GetView()->SetFrame(nullptr);
     218             :   }
     219             : 
     220          76 :   DestroyAbsoluteFrames(aDestructRoot);
     221             : 
     222             :   // Destroy frames on the principal child list.
     223          76 :   mFrames.DestroyFramesFrom(aDestructRoot);
     224             : 
     225             :   // If we have any IB split siblings, clear their references to us.
     226          76 :   if (HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) {
     227             :     // Delete previous sibling's reference to me.
     228           0 :     nsIFrame* prevSib = GetProperty(nsIFrame::IBSplitPrevSibling());
     229           0 :     if (prevSib) {
     230           0 :       NS_WARNING_ASSERTION(
     231             :         this == prevSib->GetProperty(nsIFrame::IBSplitSibling()),
     232             :         "IB sibling chain is inconsistent");
     233           0 :       prevSib->DeleteProperty(nsIFrame::IBSplitSibling());
     234             :     }
     235             : 
     236             :     // Delete next sibling's reference to me.
     237           0 :     nsIFrame* nextSib = GetProperty(nsIFrame::IBSplitSibling());
     238           0 :     if (nextSib) {
     239           0 :       NS_WARNING_ASSERTION(
     240             :         this == nextSib->GetProperty(nsIFrame::IBSplitPrevSibling()),
     241             :         "IB sibling chain is inconsistent");
     242           0 :       nextSib->DeleteProperty(nsIFrame::IBSplitPrevSibling());
     243             :     }
     244             : 
     245             : #ifdef DEBUG
     246             :     // This is just so we can assert it's not set in nsFrame::DestroyFrom.
     247           0 :     RemoveStateBits(NS_FRAME_PART_OF_IBSPLIT);
     248             : #endif
     249             :   }
     250             : 
     251          76 :   if (MOZ_UNLIKELY(!mProperties.IsEmpty())) {
     252             :     using T = mozilla::FrameProperties::UntypedDescriptor;
     253          22 :     bool hasO = false, hasOC = false, hasEOC = false, hasBackdrop = false;
     254          46 :     mProperties.ForEach([&] (const T& aProp, void*) {
     255          24 :       if (aProp == OverflowProperty()) {
     256           0 :         hasO = true;
     257          24 :       } else if (aProp == OverflowContainersProperty()) {
     258           0 :         hasOC = true;
     259          24 :       } else if (aProp == ExcessOverflowContainersProperty()) {
     260           0 :         hasEOC = true;
     261          24 :       } else if (aProp == BackdropProperty()) {
     262           0 :         hasBackdrop = true;
     263             :       }
     264          24 :       return true;
     265          44 :     });
     266             : 
     267             :     // Destroy frames on the auxiliary frame lists and delete the lists.
     268          22 :     nsPresContext* pc = PresContext();
     269          22 :     nsIPresShell* shell = pc->PresShell();
     270          22 :     if (hasO) {
     271           0 :       SafelyDestroyFrameListProp(aDestructRoot, shell, OverflowProperty());
     272             :     }
     273             : 
     274          22 :     MOZ_ASSERT(IsFrameOfType(eCanContainOverflowContainers) ||
     275             :                !(hasOC || hasEOC),
     276             :                "this type of frame shouldn't have overflow containers");
     277          22 :     if (hasOC) {
     278           0 :       SafelyDestroyFrameListProp(aDestructRoot, shell,
     279           0 :                                  OverflowContainersProperty());
     280             :     }
     281          22 :     if (hasEOC) {
     282           0 :       SafelyDestroyFrameListProp(aDestructRoot, shell,
     283           0 :                                  ExcessOverflowContainersProperty());
     284             :     }
     285             : 
     286          22 :     MOZ_ASSERT(!GetProperty(BackdropProperty()) ||
     287             :                StyleDisplay()->mTopLayer != NS_STYLE_TOP_LAYER_NONE,
     288             :                "only top layer frame may have backdrop");
     289          22 :     if (hasBackdrop) {
     290           0 :       SafelyDestroyFrameListProp(aDestructRoot, shell, BackdropProperty());
     291             :     }
     292             :   }
     293             : 
     294          76 :   nsSplittableFrame::DestroyFrom(aDestructRoot);
     295          76 : }
     296             : 
     297             : /////////////////////////////////////////////////////////////////////////////
     298             : // Child frame enumeration
     299             : 
     300             : const nsFrameList&
     301        6161 : nsContainerFrame::GetChildList(ChildListID aListID) const
     302             : {
     303             :   // We only know about the principal child list, the overflow lists,
     304             :   // and the backdrop list.
     305        6161 :   switch (aListID) {
     306             :     case kPrincipalList:
     307        6135 :       return mFrames;
     308             :     case kOverflowList: {
     309           0 :       nsFrameList* list = GetOverflowFrames();
     310           0 :       return list ? *list : nsFrameList::EmptyList();
     311             :     }
     312             :     case kOverflowContainersList: {
     313           0 :       nsFrameList* list = GetPropTableFrames(OverflowContainersProperty());
     314           0 :       return list ? *list : nsFrameList::EmptyList();
     315             :     }
     316             :     case kExcessOverflowContainersList: {
     317             :       nsFrameList* list =
     318           0 :         GetPropTableFrames(ExcessOverflowContainersProperty());
     319           0 :       return list ? *list : nsFrameList::EmptyList();
     320             :     }
     321             :     case kBackdropList: {
     322           0 :       nsFrameList* list = GetPropTableFrames(BackdropProperty());
     323           0 :       return list ? *list : nsFrameList::EmptyList();
     324             :     }
     325             :     default:
     326          26 :       return nsSplittableFrame::GetChildList(aListID);
     327             :   }
     328             : }
     329             : 
     330             : void
     331        4822 : nsContainerFrame::GetChildLists(nsTArray<ChildList>* aLists) const
     332             : {
     333        4822 :   mFrames.AppendIfNonempty(aLists, kPrincipalList);
     334             : 
     335             :   using T = mozilla::FrameProperties::UntypedDescriptor;
     336        7152 :   mProperties.ForEach([this, aLists] (const T& aProp, void* aValue) {
     337             :     typedef const nsFrameList* L;
     338        2330 :     if (aProp == OverflowProperty()) {
     339           0 :       L(aValue)->AppendIfNonempty(aLists, kOverflowList);
     340        2330 :     } else if (aProp == OverflowContainersProperty()) {
     341           0 :       MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
     342             :                  "found unexpected OverflowContainersProperty");
     343           0 :       Unused << this; // silence clang -Wunused-lambda-capture in opt builds
     344           0 :       L(aValue)->AppendIfNonempty(aLists, kOverflowContainersList);
     345        2330 :     } else if (aProp == ExcessOverflowContainersProperty()) {
     346           0 :       MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
     347             :                  "found unexpected ExcessOverflowContainersProperty");
     348           0 :       Unused << this; // silence clang -Wunused-lambda-capture in opt builds
     349           0 :       L(aValue)->AppendIfNonempty(aLists, kExcessOverflowContainersList);
     350        2330 :     } else if (aProp == BackdropProperty()) {
     351           0 :       L(aValue)->AppendIfNonempty(aLists, kBackdropList);
     352             :     }
     353        2330 :     return true;
     354        9644 :   });
     355             : 
     356        4822 :   nsSplittableFrame::GetChildLists(aLists);
     357        4822 : }
     358             : 
     359             : /////////////////////////////////////////////////////////////////////////////
     360             : // Painting/Events
     361             : 
     362             : void
     363           0 : nsContainerFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     364             :                                    const nsRect&           aDirtyRect,
     365             :                                    const nsDisplayListSet& aLists)
     366             : {
     367           0 :   DisplayBorderBackgroundOutline(aBuilder, aLists);
     368             : 
     369           0 :   BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists);
     370           0 : }
     371             : 
     372             : void
     373          63 : nsContainerFrame::BuildDisplayListForNonBlockChildren(nsDisplayListBuilder*   aBuilder,
     374             :                                                       const nsRect&           aDirtyRect,
     375             :                                                       const nsDisplayListSet& aLists,
     376             :                                                       uint32_t                aFlags)
     377             : {
     378          63 :   nsIFrame* kid = mFrames.FirstChild();
     379             :   // Put each child's background directly onto the content list
     380          63 :   nsDisplayListSet set(aLists, aLists.Content());
     381             :   // The children should be in content order
     382         233 :   while (kid) {
     383          85 :     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, set, aFlags);
     384          85 :     kid = kid->GetNextSibling();
     385             :   }
     386          63 : }
     387             : 
     388             : /* virtual */ void
     389         429 : nsContainerFrame::ChildIsDirty(nsIFrame* aChild)
     390             : {
     391         429 :   NS_ASSERTION(NS_SUBTREE_DIRTY(aChild), "child isn't actually dirty");
     392             : 
     393         429 :   AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
     394         429 : }
     395             : 
     396             : nsIFrame::FrameSearchResult
     397           0 : nsContainerFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
     398             : {
     399           0 :   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
     400             :   // Don't allow the caret to stay in an empty (leaf) container frame.
     401           0 :   return CONTINUE_EMPTY;
     402             : }
     403             : 
     404             : nsIFrame::FrameSearchResult
     405           0 : nsContainerFrame::PeekOffsetCharacter(
     406             :                     bool aForward, int32_t* aOffset,
     407             :                     PeekOffsetCharacterOptions aOptions)
     408             : {
     409           0 :   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
     410             :   // Don't allow the caret to stay in an empty (leaf) container frame.
     411           0 :   return CONTINUE_EMPTY;
     412             : }
     413             : 
     414             : /////////////////////////////////////////////////////////////////////////////
     415             : // Helper member functions
     416             : 
     417             : /**
     418             :  * Position the view associated with |aKidFrame|, if there is one. A
     419             :  * container frame should call this method after positioning a frame,
     420             :  * but before |Reflow|.
     421             :  */
     422             : void
     423        2140 : nsContainerFrame::PositionFrameView(nsIFrame* aKidFrame)
     424             : {
     425        2140 :   nsIFrame* parentFrame = aKidFrame->GetParent();
     426        2140 :   if (!aKidFrame->HasView() || !parentFrame)
     427        4212 :     return;
     428             : 
     429          34 :   nsView* view = aKidFrame->GetView();
     430          34 :   nsViewManager* vm = view->GetViewManager();
     431          34 :   nsPoint pt;
     432          34 :   nsView* ancestorView = parentFrame->GetClosestView(&pt);
     433             : 
     434          34 :   if (ancestorView != view->GetParent()) {
     435           0 :     NS_ASSERTION(ancestorView == view->GetParent()->GetParent(),
     436             :                  "Allowed only one anonymous view between frames");
     437             :     // parentFrame is responsible for positioning aKidFrame's view
     438             :     // explicitly
     439           0 :     return;
     440             :   }
     441             : 
     442          34 :   pt += aKidFrame->GetPosition();
     443          34 :   vm->MoveViewTo(view, pt.x, pt.y);
     444             : }
     445             : 
     446             : nsresult
     447           0 : nsContainerFrame::ReparentFrameView(nsIFrame* aChildFrame,
     448             :                                     nsIFrame* aOldParentFrame,
     449             :                                     nsIFrame* aNewParentFrame)
     450             : {
     451           0 :   NS_PRECONDITION(aChildFrame, "null child frame pointer");
     452           0 :   NS_PRECONDITION(aOldParentFrame, "null old parent frame pointer");
     453           0 :   NS_PRECONDITION(aNewParentFrame, "null new parent frame pointer");
     454           0 :   NS_PRECONDITION(aOldParentFrame != aNewParentFrame, "same old and new parent frame");
     455             : 
     456             :   // See if either the old parent frame or the new parent frame have a view
     457           0 :   while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) {
     458             :     // Walk up both the old parent frame and the new parent frame nodes
     459             :     // stopping when we either find a common parent or views for one
     460             :     // or both of the frames.
     461             :     //
     462             :     // This works well in the common case where we push/pull and the old parent
     463             :     // frame and the new parent frame are part of the same flow. They will
     464             :     // typically be the same distance (height wise) from the
     465           0 :     aOldParentFrame = aOldParentFrame->GetParent();
     466           0 :     aNewParentFrame = aNewParentFrame->GetParent();
     467             : 
     468             :     // We should never walk all the way to the root frame without finding
     469             :     // a view
     470           0 :     NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view");
     471             : 
     472             :     // See if we reached a common ancestor
     473           0 :     if (aOldParentFrame == aNewParentFrame) {
     474           0 :       break;
     475             :     }
     476             :   }
     477             : 
     478             :   // See if we found a common parent frame
     479           0 :   if (aOldParentFrame == aNewParentFrame) {
     480             :     // We found a common parent and there are no views between the old parent
     481             :     // and the common parent or the new parent frame and the common parent.
     482             :     // Because neither the old parent frame nor the new parent frame have views,
     483             :     // then any child views don't need reparenting
     484           0 :     return NS_OK;
     485             :   }
     486             : 
     487             :   // We found views for one or both of the ancestor frames before we
     488             :   // found a common ancestor.
     489           0 :   nsView* oldParentView = aOldParentFrame->GetClosestView();
     490           0 :   nsView* newParentView = aNewParentFrame->GetClosestView();
     491             : 
     492             :   // See if the old parent frame and the new parent frame are in the
     493             :   // same view sub-hierarchy. If they are then we don't have to do
     494             :   // anything
     495           0 :   if (oldParentView != newParentView) {
     496             :     // They're not so we need to reparent any child views
     497           0 :     aChildFrame->ReparentFrameViewTo(oldParentView->GetViewManager(),
     498             :                                      newParentView,
     499           0 :                                      oldParentView);
     500             :   }
     501             : 
     502           0 :   return NS_OK;
     503             : }
     504             : 
     505             : nsresult
     506           0 : nsContainerFrame::ReparentFrameViewList(const nsFrameList& aChildFrameList,
     507             :                                         nsIFrame*          aOldParentFrame,
     508             :                                         nsIFrame*          aNewParentFrame)
     509             : {
     510           0 :   NS_PRECONDITION(aChildFrameList.NotEmpty(), "empty child frame list");
     511           0 :   NS_PRECONDITION(aOldParentFrame, "null old parent frame pointer");
     512           0 :   NS_PRECONDITION(aNewParentFrame, "null new parent frame pointer");
     513           0 :   NS_PRECONDITION(aOldParentFrame != aNewParentFrame, "same old and new parent frame");
     514             : 
     515             :   // See if either the old parent frame or the new parent frame have a view
     516           0 :   while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) {
     517             :     // Walk up both the old parent frame and the new parent frame nodes
     518             :     // stopping when we either find a common parent or views for one
     519             :     // or both of the frames.
     520             :     //
     521             :     // This works well in the common case where we push/pull and the old parent
     522             :     // frame and the new parent frame are part of the same flow. They will
     523             :     // typically be the same distance (height wise) from the
     524           0 :     aOldParentFrame = aOldParentFrame->GetParent();
     525           0 :     aNewParentFrame = aNewParentFrame->GetParent();
     526             : 
     527             :     // We should never walk all the way to the root frame without finding
     528             :     // a view
     529           0 :     NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view");
     530             : 
     531             :     // See if we reached a common ancestor
     532           0 :     if (aOldParentFrame == aNewParentFrame) {
     533           0 :       break;
     534             :     }
     535             :   }
     536             : 
     537             : 
     538             :   // See if we found a common parent frame
     539           0 :   if (aOldParentFrame == aNewParentFrame) {
     540             :     // We found a common parent and there are no views between the old parent
     541             :     // and the common parent or the new parent frame and the common parent.
     542             :     // Because neither the old parent frame nor the new parent frame have views,
     543             :     // then any child views don't need reparenting
     544           0 :     return NS_OK;
     545             :   }
     546             : 
     547             :   // We found views for one or both of the ancestor frames before we
     548             :   // found a common ancestor.
     549           0 :   nsView* oldParentView = aOldParentFrame->GetClosestView();
     550           0 :   nsView* newParentView = aNewParentFrame->GetClosestView();
     551             : 
     552             :   // See if the old parent frame and the new parent frame are in the
     553             :   // same view sub-hierarchy. If they are then we don't have to do
     554             :   // anything
     555           0 :   if (oldParentView != newParentView) {
     556           0 :     nsViewManager* viewManager = oldParentView->GetViewManager();
     557             : 
     558             :     // They're not so we need to reparent any child views
     559           0 :     for (nsFrameList::Enumerator e(aChildFrameList); !e.AtEnd(); e.Next()) {
     560           0 :       e.get()->ReparentFrameViewTo(viewManager, newParentView, oldParentView);
     561             :     }
     562             :   }
     563             : 
     564           0 :   return NS_OK;
     565             : }
     566             : 
     567             : static nsIWidget*
     568          50 : GetPresContextContainerWidget(nsPresContext* aPresContext)
     569             : {
     570         100 :   nsCOMPtr<nsISupports> container = aPresContext->Document()->GetContainer();
     571         100 :   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
     572          50 :   if (!baseWindow)
     573           0 :     return nullptr;
     574             : 
     575         100 :   nsCOMPtr<nsIWidget> mainWidget;
     576          50 :   baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
     577          50 :   return mainWidget;
     578             : }
     579             : 
     580             : static bool
     581          50 : IsTopLevelWidget(nsIWidget* aWidget)
     582             : {
     583          50 :   nsWindowType windowType = aWidget->WindowType();
     584           6 :   return windowType == eWindowType_toplevel ||
     585           6 :          windowType == eWindowType_dialog ||
     586          56 :          windowType == eWindowType_popup ||
     587          50 :          windowType == eWindowType_sheet;
     588             : }
     589             : 
     590             : void
     591         114 : nsContainerFrame::SyncWindowProperties(nsPresContext*       aPresContext,
     592             :                                        nsIFrame*            aFrame,
     593             :                                        nsView*              aView,
     594             :                                        gfxContext*          aRC,
     595             :                                        uint32_t             aFlags)
     596             : {
     597             : #ifdef MOZ_XUL
     598         114 :   if (!aView || !nsCSSRendering::IsCanvasFrame(aFrame) || !aView->HasWidget())
     599         158 :     return;
     600             : 
     601          70 :   nsCOMPtr<nsIWidget> windowWidget = GetPresContextContainerWidget(aPresContext);
     602          50 :   if (!windowWidget || !IsTopLevelWidget(windowWidget))
     603           6 :     return;
     604             : 
     605          44 :   nsViewManager* vm = aView->GetViewManager();
     606          44 :   nsView* rootView = vm->GetRootView();
     607             : 
     608          44 :   if (aView != rootView)
     609           0 :     return;
     610             : 
     611          44 :   Element* rootElement = aPresContext->Document()->GetRootElement();
     612          44 :   if (!rootElement || !rootElement->IsXULElement()) {
     613             :     // Scrollframes use native widgets which don't work well with
     614             :     // translucent windows, at least in Windows XP. So if the document
     615             :     // has a root scrollrame it's useless to try to make it transparent,
     616             :     // we'll just get something broken.
     617             :     // nsCSSFrameConstructor::ConstructRootFrame constructs root
     618             :     // scrollframes whenever the root element is not a XUL element, so
     619             :     // we test for that here. We can't just call
     620             :     // presShell->GetRootScrollFrame() since that might not have
     621             :     // been constructed yet.
     622             :     // We can change this to allow translucent toplevel HTML documents
     623             :     // (e.g. to do something like Dashboard widgets), once we
     624             :     // have broad support for translucent scrolled documents, but be
     625             :     // careful because apparently some Firefox extensions expect
     626             :     // openDialog("something.html") to produce an opaque window
     627             :     // even if the HTML doesn't have a background-color set.
     628           0 :     return;
     629             :   }
     630             : 
     631          44 :   nsIFrame *rootFrame = aPresContext->PresShell()->FrameConstructor()->GetRootElementStyleFrame();
     632          44 :   if (!rootFrame)
     633           1 :     return;
     634             : 
     635          43 :   if (aFlags & SET_ASYNC) {
     636          23 :     aView->SetNeedsWindowPropertiesSync();
     637          23 :     return;
     638             :   }
     639             : 
     640          40 :   RefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
     641          40 :   AutoWeakFrame weak(rootFrame);
     642             : 
     643          20 :   nsTransparencyMode mode = nsLayoutUtils::GetFrameTransparency(aFrame, rootFrame);
     644          20 :   int32_t shadow = rootFrame->StyleUIReset()->mWindowShadow;
     645          40 :   nsCOMPtr<nsIWidget> viewWidget = aView->GetWidget();
     646          20 :   viewWidget->SetTransparencyMode(mode);
     647          20 :   windowWidget->SetWindowShadowStyle(shadow);
     648             : 
     649          20 :   if (!aRC)
     650           0 :     return;
     651             : 
     652          20 :   if (!weak.IsAlive()) {
     653           0 :     return;
     654             :   }
     655             : 
     656          40 :   nsBoxLayoutState aState(aPresContext, aRC);
     657          20 :   nsSize minSize = rootFrame->GetXULMinSize(aState);
     658          20 :   nsSize maxSize = rootFrame->GetXULMaxSize(aState);
     659             : 
     660          20 :   SetSizeConstraints(aPresContext, windowWidget, minSize, maxSize);
     661             : #endif
     662             : }
     663             : 
     664          20 : void nsContainerFrame::SetSizeConstraints(nsPresContext* aPresContext,
     665             :                                           nsIWidget* aWidget,
     666             :                                           const nsSize& aMinSize,
     667             :                                           const nsSize& aMaxSize)
     668             : {
     669          20 :   LayoutDeviceIntSize devMinSize(aPresContext->AppUnitsToDevPixels(aMinSize.width),
     670          40 :                                  aPresContext->AppUnitsToDevPixels(aMinSize.height));
     671          20 :   LayoutDeviceIntSize devMaxSize(aMaxSize.width == NS_INTRINSICSIZE ? NS_MAXSIZE :
     672           0 :                                  aPresContext->AppUnitsToDevPixels(aMaxSize.width),
     673          20 :                                  aMaxSize.height == NS_INTRINSICSIZE ? NS_MAXSIZE :
     674          40 :                                  aPresContext->AppUnitsToDevPixels(aMaxSize.height));
     675             : 
     676             :   // MinSize has a priority over MaxSize
     677          20 :   if (devMinSize.width > devMaxSize.width)
     678           0 :     devMaxSize.width = devMinSize.width;
     679          20 :   if (devMinSize.height > devMaxSize.height)
     680           0 :     devMaxSize.height = devMinSize.height;
     681             : 
     682          20 :   widget::SizeConstraints constraints(devMinSize, devMaxSize);
     683             : 
     684             :   // The sizes are in inner window sizes, so convert them into outer window sizes.
     685             :   // Use a size of (200, 200) as only the difference between the inner and outer
     686             :   // size is needed.
     687             :   LayoutDeviceIntSize windowSize =
     688          20 :     aWidget->ClientToWindowSize(LayoutDeviceIntSize(200, 200));
     689          20 :   if (constraints.mMinSize.width)
     690          20 :     constraints.mMinSize.width += windowSize.width - 200;
     691          20 :   if (constraints.mMinSize.height)
     692          20 :     constraints.mMinSize.height += windowSize.height - 200;
     693          20 :   if (constraints.mMaxSize.width != NS_MAXSIZE)
     694           0 :     constraints.mMaxSize.width += windowSize.width - 200;
     695          20 :   if (constraints.mMaxSize.height != NS_MAXSIZE)
     696           0 :     constraints.mMaxSize.height += windowSize.height - 200;
     697             : 
     698          20 :   aWidget->SetSizeConstraints(constraints);
     699          20 : }
     700             : 
     701             : void
     702         205 : nsContainerFrame::SyncFrameViewAfterReflow(nsPresContext* aPresContext,
     703             :                                            nsIFrame*       aFrame,
     704             :                                            nsView*        aView,
     705             :                                            const nsRect&   aVisualOverflowArea,
     706             :                                            uint32_t        aFlags)
     707             : {
     708         205 :   if (!aView) {
     709         129 :     return;
     710             :   }
     711             : 
     712             :   // Make sure the view is sized and positioned correctly
     713          76 :   if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
     714          72 :     PositionFrameView(aFrame);
     715             :   }
     716             : 
     717          76 :   if (0 == (aFlags & NS_FRAME_NO_SIZE_VIEW)) {
     718          76 :     nsViewManager* vm = aView->GetViewManager();
     719             : 
     720          76 :     vm->ResizeView(aView, aVisualOverflowArea, true);
     721             :   }
     722             : }
     723             : 
     724           0 : static nscoord GetCoord(const nsStyleCoord& aCoord, nscoord aIfNotCoord)
     725             : {
     726           0 :   if (aCoord.ConvertsToLength()) {
     727           0 :     return nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
     728             :   }
     729           0 :   return aIfNotCoord;
     730             : }
     731             : 
     732             : void
     733           0 : nsContainerFrame::DoInlineIntrinsicISize(gfxContext *aRenderingContext,
     734             :                                          InlineIntrinsicISizeData *aData,
     735             :                                          nsLayoutUtils::IntrinsicISizeType aType)
     736             : {
     737           0 :   if (GetPrevInFlow())
     738           0 :     return; // Already added.
     739             : 
     740           0 :   NS_PRECONDITION(aType == nsLayoutUtils::MIN_ISIZE ||
     741             :                   aType == nsLayoutUtils::PREF_ISIZE, "bad type");
     742             : 
     743           0 :   WritingMode wm = GetWritingMode();
     744             :   mozilla::Side startSide =
     745           0 :     wm.PhysicalSideForInlineAxis(eLogicalEdgeStart);
     746             :   mozilla::Side endSide =
     747           0 :     wm.PhysicalSideForInlineAxis(eLogicalEdgeEnd);
     748             : 
     749           0 :   const nsStylePadding *stylePadding = StylePadding();
     750           0 :   const nsStyleBorder *styleBorder = StyleBorder();
     751           0 :   const nsStyleMargin *styleMargin = StyleMargin();
     752             : 
     753             :   // This goes at the beginning no matter how things are broken and how
     754             :   // messy the bidi situations are, since per CSS2.1 section 8.6
     755             :   // (implemented in bug 328168), the startSide border is always on the
     756             :   // first line.
     757             :   // This frame is a first-in-flow, but it might have a previous bidi
     758             :   // continuation, in which case that continuation should handle the startSide
     759             :   // border.
     760             :   // For box-decoration-break:clone we setup clonePBM = startPBM + endPBM and
     761             :   // add that to each line.  For box-decoration-break:slice clonePBM is zero.
     762           0 :   nscoord clonePBM = 0; // PBM = PaddingBorderMargin
     763             :   const bool sliceBreak =
     764           0 :     styleBorder->mBoxDecorationBreak == StyleBoxDecorationBreak::Slice;
     765           0 :   if (!GetPrevContinuation()) {
     766             :     nscoord startPBM =
     767             :       // clamp negative calc() to 0
     768           0 :       std::max(GetCoord(stylePadding->mPadding.Get(startSide), 0), 0) +
     769           0 :       styleBorder->GetComputedBorderWidth(startSide) +
     770           0 :       GetCoord(styleMargin->mMargin.Get(startSide), 0);
     771           0 :     if (MOZ_LIKELY(sliceBreak)) {
     772           0 :       aData->mCurrentLine += startPBM;
     773             :     } else {
     774           0 :       clonePBM = startPBM;
     775             :     }
     776             :   }
     777             : 
     778             :   nscoord endPBM =
     779             :     // clamp negative calc() to 0
     780           0 :     std::max(GetCoord(stylePadding->mPadding.Get(endSide), 0), 0) +
     781           0 :     styleBorder->GetComputedBorderWidth(endSide) +
     782           0 :     GetCoord(styleMargin->mMargin.Get(endSide), 0);
     783           0 :   if (MOZ_UNLIKELY(!sliceBreak)) {
     784           0 :     clonePBM += endPBM;
     785             :   }
     786             : 
     787           0 :   const nsLineList_iterator* savedLine = aData->mLine;
     788           0 :   nsIFrame* const savedLineContainer = aData->LineContainer();
     789             : 
     790             :   nsContainerFrame *lastInFlow;
     791           0 :   for (nsContainerFrame *nif = this; nif;
     792           0 :        nif = static_cast<nsContainerFrame*>(nif->GetNextInFlow())) {
     793           0 :     if (aData->mCurrentLine == 0) {
     794           0 :       aData->mCurrentLine = clonePBM;
     795             :     }
     796           0 :     for (nsIFrame* kid : nif->mFrames) {
     797           0 :       if (aType == nsLayoutUtils::MIN_ISIZE)
     798             :         kid->AddInlineMinISize(aRenderingContext,
     799           0 :                                static_cast<InlineMinISizeData*>(aData));
     800             :       else
     801             :         kid->AddInlinePrefISize(aRenderingContext,
     802           0 :                                 static_cast<InlinePrefISizeData*>(aData));
     803             :     }
     804             : 
     805             :     // After we advance to our next-in-flow, the stored line and line container
     806             :     // may no longer be correct. Just forget them.
     807           0 :     aData->mLine = nullptr;
     808           0 :     aData->SetLineContainer(nullptr);
     809             : 
     810           0 :     lastInFlow = nif;
     811             :   }
     812             : 
     813           0 :   aData->mLine = savedLine;
     814           0 :   aData->SetLineContainer(savedLineContainer);
     815             : 
     816             :   // This goes at the end no matter how things are broken and how
     817             :   // messy the bidi situations are, since per CSS2.1 section 8.6
     818             :   // (implemented in bug 328168), the endSide border is always on the
     819             :   // last line.
     820             :   // We reached the last-in-flow, but it might have a next bidi
     821             :   // continuation, in which case that continuation should handle
     822             :   // the endSide border.
     823           0 :   if (MOZ_LIKELY(!lastInFlow->GetNextContinuation() && sliceBreak)) {
     824           0 :     aData->mCurrentLine += endPBM;
     825             :   }
     826             : }
     827             : 
     828             : /* virtual */
     829             : LogicalSize
     830         341 : nsContainerFrame::ComputeAutoSize(gfxContext*         aRenderingContext,
     831             :                                   WritingMode         aWM,
     832             :                                   const LogicalSize&  aCBSize,
     833             :                                   nscoord             aAvailableISize,
     834             :                                   const LogicalSize&  aMargin,
     835             :                                   const LogicalSize&  aBorder,
     836             :                                   const LogicalSize&  aPadding,
     837             :                                   ComputeSizeFlags    aFlags)
     838             : {
     839         341 :   LogicalSize result(aWM, 0xdeadbeef, NS_UNCONSTRAINEDSIZE);
     840         682 :   nscoord availBased = aAvailableISize - aMargin.ISize(aWM) -
     841         682 :                        aBorder.ISize(aWM) - aPadding.ISize(aWM);
     842             :   // replaced elements always shrink-wrap
     843         341 :   if ((aFlags & ComputeSizeFlags::eShrinkWrap) || IsFrameOfType(eReplaced)) {
     844             :     // don't bother setting it if the result won't be used
     845         123 :     if (StylePosition()->ISize(aWM).GetUnit() == eStyleUnit_Auto) {
     846         119 :       result.ISize(aWM) = ShrinkWidthToFit(aRenderingContext, availBased, aFlags);
     847             :     }
     848             :   } else {
     849         218 :     result.ISize(aWM) = availBased;
     850             :   }
     851             : 
     852         341 :   if (IsTableCaption()) {
     853             :     // If we're a container for font size inflation, then shrink
     854             :     // wrapping inside of us should not apply font size inflation.
     855           0 :     AutoMaybeDisableFontInflation an(this);
     856             : 
     857           0 :     WritingMode tableWM = GetParent()->GetWritingMode();
     858           0 :     uint8_t captionSide = StyleTableBorder()->mCaptionSide;
     859             : 
     860           0 :     if (aWM.IsOrthogonalTo(tableWM)) {
     861           0 :       if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
     862           0 :           captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
     863           0 :           captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
     864             :           captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) {
     865             :         // For an orthogonal caption on a block-dir side of the table,
     866             :         // shrink-wrap to min-isize.
     867           0 :         result.ISize(aWM) = GetMinISize(aRenderingContext);
     868             :       } else {
     869             :         // An orthogonal caption on an inline-dir side of the table
     870             :         // is constrained to the containing block.
     871           0 :         nscoord pref = GetPrefISize(aRenderingContext);
     872           0 :         if (pref > aCBSize.ISize(aWM)) {
     873           0 :           pref = aCBSize.ISize(aWM);
     874             :         }
     875           0 :         if (pref < result.ISize(aWM)) {
     876           0 :           result.ISize(aWM) = pref;
     877             :         }
     878             :       }
     879             :     } else {
     880           0 :       if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
     881             :           captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
     882           0 :         result.ISize(aWM) = GetMinISize(aRenderingContext);
     883           0 :       } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
     884             :                  captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
     885             :         // The outer frame constrains our available isize to the isize of
     886             :         // the table.  Grow if our min-isize is bigger than that, but not
     887             :         // larger than the containing block isize.  (It would really be nice
     888             :         // to transmit that information another way, so we could grow up to
     889             :         // the table's available isize, but that's harder.)
     890           0 :         nscoord min = GetMinISize(aRenderingContext);
     891           0 :         if (min > aCBSize.ISize(aWM)) {
     892           0 :           min = aCBSize.ISize(aWM);
     893             :         }
     894           0 :         if (min > result.ISize(aWM)) {
     895           0 :           result.ISize(aWM) = min;
     896             :         }
     897             :       }
     898             :     }
     899             :   }
     900         341 :   return result;
     901             : }
     902             : 
     903             : void
     904         172 : nsContainerFrame::ReflowChild(nsIFrame*                aKidFrame,
     905             :                               nsPresContext*           aPresContext,
     906             :                               ReflowOutput&            aDesiredSize,
     907             :                               const ReflowInput&       aReflowInput,
     908             :                               const WritingMode&       aWM,
     909             :                               const LogicalPoint&      aPos,
     910             :                               const nsSize&            aContainerSize,
     911             :                               uint32_t                 aFlags,
     912             :                               nsReflowStatus&          aStatus,
     913             :                               nsOverflowContinuationTracker* aTracker)
     914             : {
     915         172 :   NS_PRECONDITION(aReflowInput.mFrame == aKidFrame, "bad reflow state");
     916         172 :   if (aWM.IsVerticalRL() || (!aWM.IsVertical() && !aWM.IsBidiLTR())) {
     917           0 :     NS_ASSERTION(aContainerSize.width != NS_UNCONSTRAINEDSIZE,
     918             :                  "ReflowChild with unconstrained container width!");
     919             :   }
     920         172 :   MOZ_ASSERT(aDesiredSize.VisualOverflow() == nsRect(0,0,0,0) &&
     921             :              aDesiredSize.ScrollableOverflow() == nsRect(0,0,0,0),
     922             :              "please reset the overflow areas before calling ReflowChild");
     923             : 
     924             :   // Position the child frame and its view if requested.
     925         172 :   if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
     926          45 :     aKidFrame->SetPosition(aWM, aPos, aContainerSize);
     927             :   }
     928             : 
     929         172 :   if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
     930          45 :     PositionFrameView(aKidFrame);
     931          45 :     PositionChildViews(aKidFrame);
     932             :   }
     933             : 
     934             :   // Reflow the child frame
     935         172 :   aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
     936             : 
     937             :   // If the child frame is complete, delete any next-in-flows,
     938             :   // but only if the NO_DELETE_NEXT_IN_FLOW flag isn't set.
     939         516 :   if (!aStatus.IsInlineBreakBefore() &&
     940         344 :       aStatus.IsFullyComplete() &&
     941         172 :       !(aFlags & NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD)) {
     942         172 :     nsIFrame* kidNextInFlow = aKidFrame->GetNextInFlow();
     943         172 :     if (kidNextInFlow) {
     944             :       // Remove all of the childs next-in-flows. Make sure that we ask
     945             :       // the right parent to do the removal (it's possible that the
     946             :       // parent is not this because we are executing pullup code)
     947           0 :       nsOverflowContinuationTracker::AutoFinish fini(aTracker, aKidFrame);
     948           0 :       kidNextInFlow->GetParent()->DeleteNextInFlowChild(kidNextInFlow, true);
     949             :     }
     950             :   }
     951         172 : }
     952             : 
     953             : //XXX temporary: hold on to a copy of the old physical version of
     954             : //    ReflowChild so that we can convert callers incrementally.
     955             : void
     956         105 : nsContainerFrame::ReflowChild(nsIFrame*                aKidFrame,
     957             :                               nsPresContext*           aPresContext,
     958             :                               ReflowOutput&     aDesiredSize,
     959             :                               const ReflowInput& aReflowInput,
     960             :                               nscoord                  aX,
     961             :                               nscoord                  aY,
     962             :                               uint32_t                 aFlags,
     963             :                               nsReflowStatus&          aStatus,
     964             :                               nsOverflowContinuationTracker* aTracker)
     965             : {
     966         105 :   NS_PRECONDITION(aReflowInput.mFrame == aKidFrame, "bad reflow state");
     967             : 
     968             :   // Position the child frame and its view if requested.
     969         105 :   if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
     970         101 :     aKidFrame->SetPosition(nsPoint(aX, aY));
     971             :   }
     972             : 
     973         105 :   if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
     974         101 :     PositionFrameView(aKidFrame);
     975         101 :     PositionChildViews(aKidFrame);
     976             :   }
     977             : 
     978             :   // Reflow the child frame
     979         105 :   aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
     980             : 
     981             :   // If the child frame is complete, delete any next-in-flows,
     982             :   // but only if the NO_DELETE_NEXT_IN_FLOW flag isn't set.
     983         210 :   if (aStatus.IsFullyComplete() &&
     984         105 :       !(aFlags & NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD)) {
     985         105 :     nsIFrame* kidNextInFlow = aKidFrame->GetNextInFlow();
     986         105 :     if (kidNextInFlow) {
     987             :       // Remove all of the childs next-in-flows. Make sure that we ask
     988             :       // the right parent to do the removal (it's possible that the
     989             :       // parent is not this because we are executing pullup code)
     990           0 :       nsOverflowContinuationTracker::AutoFinish fini(aTracker, aKidFrame);
     991           0 :       kidNextInFlow->GetParent()->DeleteNextInFlowChild(kidNextInFlow, true);
     992             :     }
     993             :   }
     994         105 : }
     995             : 
     996             : 
     997             : /**
     998             :  * Position the views of |aFrame|'s descendants. A container frame
     999             :  * should call this method if it moves a frame after |Reflow|.
    1000             :  */
    1001             : void
    1002        2831 : nsContainerFrame::PositionChildViews(nsIFrame* aFrame)
    1003             : {
    1004        2831 :   if (!(aFrame->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)) {
    1005        1718 :     return;
    1006             :   }
    1007             : 
    1008             :   // Recursively walk aFrame's child frames.
    1009             :   // Process the additional child lists, but skip the popup list as the
    1010             :   // view for popups is managed by the parent. Currently only nsMenuFrame
    1011             :   // and nsPopupSetFrame have a popupList and during layout will adjust the
    1012             :   // view manually to position the popup.
    1013        2226 :   ChildListIterator lists(aFrame);
    1014        3991 :   for (; !lists.IsDone(); lists.Next()) {
    1015        1439 :     if (lists.CurrentID() == kPopupList) {
    1016         348 :       continue;
    1017             :     }
    1018        1091 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    1019        5367 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    1020             :       // Position the frame's view (if it has one) otherwise recursively
    1021             :       // process its children
    1022        2138 :       nsIFrame* childFrame = childFrames.get();
    1023        2138 :       if (childFrame->HasView()) {
    1024          25 :         PositionFrameView(childFrame);
    1025             :       } else {
    1026        2113 :         PositionChildViews(childFrame);
    1027             :       }
    1028             :     }
    1029             :   }
    1030             : }
    1031             : 
    1032             : /**
    1033             :  * The second half of frame reflow. Does the following:
    1034             :  * - sets the frame's bounds
    1035             :  * - sizes and positions (if requested) the frame's view. If the frame's final
    1036             :  *   position differs from the current position and the frame itself does not
    1037             :  *   have a view, then any child frames with views are positioned so they stay
    1038             :  *   in sync
    1039             :  * - sets the view's visibility, opacity, content transparency, and clip
    1040             :  * - invoked the DidReflow() function
    1041             :  *
    1042             :  * Flags:
    1043             :  * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this
    1044             :  *    case. Also implies NS_FRAME_NO_MOVE_VIEW
    1045             :  * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
    1046             :  *    don't want to automatically sync the frame and view
    1047             :  * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view
    1048             :  */
    1049             : void
    1050         182 : nsContainerFrame::FinishReflowChild(nsIFrame*                  aKidFrame,
    1051             :                                     nsPresContext*             aPresContext,
    1052             :                                     const ReflowOutput& aDesiredSize,
    1053             :                                     const ReflowInput*   aReflowInput,
    1054             :                                     const WritingMode&         aWM,
    1055             :                                     const LogicalPoint&        aPos,
    1056             :                                     const nsSize&              aContainerSize,
    1057             :                                     uint32_t                   aFlags)
    1058             : {
    1059         182 :   if (aWM.IsVerticalRL() || (!aWM.IsVertical() && !aWM.IsBidiLTR())) {
    1060           0 :     NS_ASSERTION(aContainerSize.width != NS_UNCONSTRAINEDSIZE,
    1061             :                  "FinishReflowChild with unconstrained container width!");
    1062             :   }
    1063             : 
    1064         182 :   nsPoint curOrigin = aKidFrame->GetPosition();
    1065         182 :   WritingMode outerWM = aDesiredSize.GetWritingMode();
    1066         364 :   LogicalSize convertedSize = aDesiredSize.Size(outerWM).ConvertTo(aWM,
    1067         182 :                                                                    outerWM);
    1068             : 
    1069         182 :   if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
    1070         110 :     aKidFrame->SetRect(aWM, LogicalRect(aWM, aPos, convertedSize),
    1071          55 :                        aContainerSize);
    1072             :   } else {
    1073         127 :     aKidFrame->SetSize(aWM, convertedSize);
    1074             :   }
    1075             : 
    1076         182 :   if (aKidFrame->HasView()) {
    1077           0 :     nsView* view = aKidFrame->GetView();
    1078             :     // Make sure the frame's view is properly sized and positioned and has
    1079             :     // things like opacity correct
    1080           0 :     SyncFrameViewAfterReflow(aPresContext, aKidFrame, view,
    1081           0 :                              aDesiredSize.VisualOverflow(), aFlags);
    1082             :   }
    1083             : 
    1084         182 :   nsPoint newOrigin = aKidFrame->GetPosition();
    1085         182 :   if (!(aFlags & NS_FRAME_NO_MOVE_VIEW) && curOrigin != newOrigin) {
    1086           2 :     if (!aKidFrame->HasView()) {
    1087             :       // If the frame has moved, then we need to make sure any child views are
    1088             :       // correctly positioned
    1089           2 :       PositionChildViews(aKidFrame);
    1090             :     }
    1091             :   }
    1092             : 
    1093         182 :   aKidFrame->DidReflow(aPresContext, aReflowInput, nsDidReflowStatus::FINISHED);
    1094         182 : }
    1095             : 
    1096             : //XXX temporary: hold on to a copy of the old physical version of
    1097             : //    FinishReflowChild so that we can convert callers incrementally.
    1098             : void
    1099         231 : nsContainerFrame::FinishReflowChild(nsIFrame*                  aKidFrame,
    1100             :                                     nsPresContext*             aPresContext,
    1101             :                                     const ReflowOutput& aDesiredSize,
    1102             :                                     const ReflowInput*   aReflowInput,
    1103             :                                     nscoord                    aX,
    1104             :                                     nscoord                    aY,
    1105             :                                     uint32_t                   aFlags)
    1106             : {
    1107         231 :   nsPoint curOrigin = aKidFrame->GetPosition();
    1108             : 
    1109         231 :   if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
    1110         101 :     aKidFrame->SetRect(nsRect(aX, aY, aDesiredSize.Width(), aDesiredSize.Height()));
    1111             :   } else {
    1112         130 :     aKidFrame->SetSize(nsSize(aDesiredSize.Width(), aDesiredSize.Height()));
    1113             :   }
    1114             : 
    1115         231 :   if (aKidFrame->HasView()) {
    1116           4 :     nsView* view = aKidFrame->GetView();
    1117             :     // Make sure the frame's view is properly sized and positioned and has
    1118             :     // things like opacity correct
    1119           4 :     SyncFrameViewAfterReflow(aPresContext, aKidFrame, view,
    1120           4 :                              aDesiredSize.VisualOverflow(), aFlags);
    1121             :   }
    1122             : 
    1123         332 :   if (!(aFlags & NS_FRAME_NO_MOVE_VIEW) &&
    1124         202 :       (curOrigin.x != aX || curOrigin.y != aY)) {
    1125           0 :     if (!aKidFrame->HasView()) {
    1126             :       // If the frame has moved, then we need to make sure any child views are
    1127             :       // correctly positioned
    1128           0 :       PositionChildViews(aKidFrame);
    1129             :     }
    1130             :   }
    1131             : 
    1132         231 :   aKidFrame->DidReflow(aPresContext, aReflowInput, nsDidReflowStatus::FINISHED);
    1133         231 : }
    1134             : 
    1135             : void
    1136           0 : nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext*           aPresContext,
    1137             :                                                   const ReflowInput& aReflowInput,
    1138             :                                                   nsOverflowAreas&         aOverflowRects,
    1139             :                                                   uint32_t                 aFlags,
    1140             :                                                   nsReflowStatus&          aStatus,
    1141             :                                                   ChildFrameMerger         aMergeFunc)
    1142             : {
    1143           0 :   NS_PRECONDITION(aPresContext, "null pointer");
    1144             : 
    1145           0 :   nsFrameList* overflowContainers = DrainExcessOverflowContainersList(aMergeFunc);
    1146           0 :   if (!overflowContainers) {
    1147           0 :     return; // nothing to reflow
    1148             :   }
    1149             : 
    1150           0 :   nsOverflowContinuationTracker tracker(this, false, false);
    1151           0 :   bool shouldReflowAllKids = aReflowInput.ShouldReflowAllKids();
    1152             : 
    1153           0 :   for (nsIFrame* frame : *overflowContainers) {
    1154           0 :     if (frame->GetPrevInFlow()->GetParent() != GetPrevInFlow()) {
    1155             :       // frame's prevInFlow has moved, skip reflowing this frame;
    1156             :       // it will get reflowed once it's been placed
    1157           0 :       continue;
    1158             :     }
    1159             :     // If the available vertical height has changed, we need to reflow
    1160             :     // even if the frame isn't dirty.
    1161           0 :     if (shouldReflowAllKids || NS_SUBTREE_DIRTY(frame)) {
    1162             :       // Get prev-in-flow
    1163           0 :       nsIFrame* prevInFlow = frame->GetPrevInFlow();
    1164           0 :       NS_ASSERTION(prevInFlow,
    1165             :                    "overflow container frame must have a prev-in-flow");
    1166           0 :       NS_ASSERTION(frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
    1167             :                    "overflow container frame must have overflow container bit set");
    1168           0 :       WritingMode wm = frame->GetWritingMode();
    1169           0 :       nsSize containerSize = aReflowInput.AvailableSize(wm).GetPhysicalSize(wm);
    1170           0 :       LogicalRect prevRect = prevInFlow->GetLogicalRect(wm, containerSize);
    1171             : 
    1172             :       // Initialize reflow params
    1173           0 :       LogicalSize availSpace(wm, prevRect.ISize(wm),
    1174           0 :                              aReflowInput.AvailableSize(wm).BSize(wm));
    1175           0 :       ReflowOutput desiredSize(aReflowInput);
    1176             :       ReflowInput frameState(aPresContext, aReflowInput,
    1177           0 :                                    frame, availSpace);
    1178           0 :       nsReflowStatus frameStatus;
    1179             : 
    1180             :       // Reflow
    1181           0 :       LogicalPoint pos(wm, prevRect.IStart(wm), 0);
    1182             :       ReflowChild(frame, aPresContext, desiredSize, frameState,
    1183           0 :                   wm, pos, containerSize, aFlags, frameStatus, &tracker);
    1184             :       //XXXfr Do we need to override any shrinkwrap effects here?
    1185             :       // e.g. desiredSize.Width() = prevRect.width;
    1186             :       FinishReflowChild(frame, aPresContext, desiredSize, &frameState,
    1187           0 :                         wm, pos, containerSize, aFlags);
    1188             : 
    1189             :       // Handle continuations
    1190           0 :       if (!frameStatus.IsFullyComplete()) {
    1191           0 :         if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    1192             :           // Abspos frames can't cause their parent to be incomplete,
    1193             :           // only overflow incomplete.
    1194           0 :           frameStatus.SetOverflowIncomplete();
    1195             :         }
    1196             :         else {
    1197           0 :           NS_ASSERTION(frameStatus.IsComplete(),
    1198             :                        "overflow container frames can't be incomplete, only overflow-incomplete");
    1199             :         }
    1200             : 
    1201             :         // Acquire a next-in-flow, creating it if necessary
    1202           0 :         nsIFrame* nif = frame->GetNextInFlow();
    1203           0 :         if (!nif) {
    1204           0 :           NS_ASSERTION(frameStatus.NextInFlowNeedsReflow(),
    1205             :                        "Someone forgot a NextInFlowNeedsReflow flag");
    1206             :           nif = aPresContext->PresShell()->FrameConstructor()->
    1207           0 :             CreateContinuingFrame(aPresContext, frame, this);
    1208             :         }
    1209           0 :         else if (!(nif->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
    1210             :           // used to be a normal next-in-flow; steal it from the child list
    1211           0 :           nsresult rv = nif->GetParent()->StealFrame(nif);
    1212           0 :           if (NS_FAILED(rv)) {
    1213           0 :             return;
    1214             :           }
    1215             :         }
    1216             : 
    1217           0 :         tracker.Insert(nif, frameStatus);
    1218             :       }
    1219           0 :       aStatus.MergeCompletionStatusFrom(frameStatus);
    1220             :       // At this point it would be nice to assert !frame->GetOverflowRect().IsEmpty(),
    1221             :       // but we have some unsplittable frames that, when taller than
    1222             :       // availableHeight will push zero-height content into a next-in-flow.
    1223             :     }
    1224             :     else {
    1225           0 :       tracker.Skip(frame, aStatus);
    1226           0 :       if (aReflowInput.mFloatManager) {
    1227           0 :         nsBlockFrame::RecoverFloatsFor(frame, *aReflowInput.mFloatManager,
    1228             :                                        aReflowInput.GetWritingMode(),
    1229           0 :                                        aReflowInput.ComputedPhysicalSize());
    1230             :       }
    1231             :     }
    1232           0 :     ConsiderChildOverflow(aOverflowRects, frame);
    1233             :   }
    1234             : }
    1235             : 
    1236             : void
    1237           0 : nsContainerFrame::DisplayOverflowContainers(nsDisplayListBuilder*   aBuilder,
    1238             :                                             const nsRect&           aDirtyRect,
    1239             :                                             const nsDisplayListSet& aLists)
    1240             : {
    1241           0 :   nsFrameList* overflowconts = GetPropTableFrames(OverflowContainersProperty());
    1242           0 :   if (overflowconts) {
    1243           0 :     for (nsIFrame* frame : *overflowconts) {
    1244           0 :       BuildDisplayListForChild(aBuilder, frame, aDirtyRect, aLists);
    1245             :     }
    1246             :   }
    1247           0 : }
    1248             : 
    1249             : static bool
    1250           0 : TryRemoveFrame(nsIFrame* aFrame,
    1251             :                nsContainerFrame::FrameListPropertyDescriptor aProp,
    1252             :                nsIFrame* aChildToRemove)
    1253             : {
    1254           0 :   nsFrameList* list = aFrame->GetProperty(aProp);
    1255           0 :   if (list && list->StartRemoveFrame(aChildToRemove)) {
    1256             :     // aChildToRemove *may* have been removed from this list.
    1257           0 :     if (list->IsEmpty()) {
    1258           0 :       aFrame->RemoveProperty(aProp);
    1259           0 :       list->Delete(aFrame->PresContext()->PresShell());
    1260             :     }
    1261           0 :     return true;
    1262             :   }
    1263           0 :   return false;
    1264             : }
    1265             : 
    1266             : bool
    1267           0 : nsContainerFrame::MaybeStealOverflowContainerFrame(nsIFrame* aChild)
    1268             : {
    1269           0 :   bool removed = false;
    1270           0 :   if (MOZ_UNLIKELY(aChild->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
    1271             :     // Try removing from the overflow container list.
    1272           0 :     removed = ::TryRemoveFrame(this, OverflowContainersProperty(),
    1273           0 :                                aChild);
    1274           0 :     if (!removed) {
    1275             :       // It might be in the excess overflow container list.
    1276           0 :       removed = ::TryRemoveFrame(this,
    1277             :                                  ExcessOverflowContainersProperty(),
    1278           0 :                                  aChild);
    1279             :     }
    1280             :   }
    1281           0 :   return removed;
    1282             : }
    1283             : 
    1284             : nsresult
    1285           0 : nsContainerFrame::StealFrame(nsIFrame* aChild)
    1286             : {
    1287             : #ifdef DEBUG
    1288           0 :   if (!mFrames.ContainsFrame(aChild)) {
    1289           0 :     nsFrameList* list = GetOverflowFrames();
    1290           0 :     if (!list || !list->ContainsFrame(aChild)) {
    1291           0 :       list = GetProperty(OverflowContainersProperty());
    1292           0 :       if (!list || !list->ContainsFrame(aChild)) {
    1293           0 :         list = GetProperty(ExcessOverflowContainersProperty());
    1294           0 :         MOZ_ASSERT(list && list->ContainsFrame(aChild), "aChild isn't our child"
    1295             :                    " or on a frame list not supported by StealFrame");
    1296             :       }
    1297             :     }
    1298             :   }
    1299             : #endif
    1300             : 
    1301           0 :   bool removed = MaybeStealOverflowContainerFrame(aChild);
    1302           0 :   if (!removed) {
    1303             :     // NOTE nsColumnSetFrame and nsCanvasFrame have their overflow containers
    1304             :     // on the normal lists so we might get here also if the frame bit
    1305             :     // NS_FRAME_IS_OVERFLOW_CONTAINER is set.
    1306           0 :     removed = mFrames.StartRemoveFrame(aChild);
    1307           0 :     if (!removed) {
    1308             :       // We didn't find the child in our principal child list.
    1309             :       // Maybe it's on the overflow list?
    1310           0 :       nsFrameList* frameList = GetOverflowFrames();
    1311           0 :       if (frameList) {
    1312           0 :         removed = frameList->ContinueRemoveFrame(aChild);
    1313           0 :         if (frameList->IsEmpty()) {
    1314           0 :           DestroyOverflowList();
    1315             :         }
    1316             :       }
    1317             :     }
    1318             :   }
    1319             : 
    1320           0 :   NS_POSTCONDITION(removed, "StealFrame: can't find aChild");
    1321           0 :   return removed ? NS_OK : NS_ERROR_UNEXPECTED;
    1322             : }
    1323             : 
    1324             : nsFrameList
    1325           0 : nsContainerFrame::StealFramesAfter(nsIFrame* aChild)
    1326             : {
    1327           0 :   NS_ASSERTION(!aChild ||
    1328             :                !(aChild->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER),
    1329             :                "StealFramesAfter doesn't handle overflow containers");
    1330           0 :   NS_ASSERTION(!IsBlockFrame(), "unexpected call");
    1331             : 
    1332           0 :   if (!aChild) {
    1333           0 :     nsFrameList copy(mFrames);
    1334           0 :     mFrames.Clear();
    1335           0 :     return copy;
    1336             :   }
    1337             : 
    1338           0 :   for (nsFrameList::FrameLinkEnumerator iter(mFrames); !iter.AtEnd();
    1339           0 :        iter.Next()) {
    1340           0 :     if (iter.PrevFrame() == aChild) {
    1341           0 :       return mFrames.ExtractTail(iter);
    1342             :     }
    1343             :   }
    1344             : 
    1345             :   // We didn't find the child in the principal child list.
    1346             :   // Maybe it's on the overflow list?
    1347           0 :   nsFrameList* overflowFrames = GetOverflowFrames();
    1348           0 :   if (overflowFrames) {
    1349           0 :     for (nsFrameList::FrameLinkEnumerator iter(*overflowFrames); !iter.AtEnd();
    1350           0 :          iter.Next()) {
    1351           0 :       if (iter.PrevFrame() == aChild) {
    1352           0 :         return overflowFrames->ExtractTail(iter);
    1353             :       }
    1354             :     }
    1355             :   }
    1356             : 
    1357           0 :   NS_ERROR("StealFramesAfter: can't find aChild");
    1358           0 :   return nsFrameList::EmptyList();
    1359             : }
    1360             : 
    1361             : /*
    1362             :  * Create a next-in-flow for aFrame. Will return the newly created
    1363             :  * frame <b>if and only if</b> a new frame is created; otherwise
    1364             :  * nullptr is returned.
    1365             :  */
    1366             : nsIFrame*
    1367           0 : nsContainerFrame::CreateNextInFlow(nsIFrame* aFrame)
    1368             : {
    1369           0 :   NS_PRECONDITION(!IsBlockFrame(),
    1370             :                   "you should have called nsBlockFrame::CreateContinuationFor instead");
    1371           0 :   NS_PRECONDITION(mFrames.ContainsFrame(aFrame), "expected an in-flow child frame");
    1372             : 
    1373           0 :   nsPresContext* pc = PresContext();
    1374           0 :   nsIFrame* nextInFlow = aFrame->GetNextInFlow();
    1375           0 :   if (nullptr == nextInFlow) {
    1376             :     // Create a continuation frame for the child frame and insert it
    1377             :     // into our child list.
    1378             :     nextInFlow = pc->PresShell()->FrameConstructor()->
    1379           0 :       CreateContinuingFrame(pc, aFrame, this);
    1380           0 :     mFrames.InsertFrame(nullptr, aFrame, nextInFlow);
    1381             : 
    1382           0 :     NS_FRAME_LOG(NS_FRAME_TRACE_NEW_FRAMES,
    1383             :        ("nsContainerFrame::CreateNextInFlow: frame=%p nextInFlow=%p",
    1384             :         aFrame, nextInFlow));
    1385             : 
    1386           0 :     return nextInFlow;
    1387             :   }
    1388           0 :   return nullptr;
    1389             : }
    1390             : 
    1391             : /**
    1392             :  * Remove and delete aNextInFlow and its next-in-flows. Updates the sibling and flow
    1393             :  * pointers
    1394             :  */
    1395             : void
    1396           0 : nsContainerFrame::DeleteNextInFlowChild(nsIFrame* aNextInFlow,
    1397             :                                         bool      aDeletingEmptyFrames)
    1398             : {
    1399             : #ifdef DEBUG
    1400           0 :   nsIFrame* prevInFlow = aNextInFlow->GetPrevInFlow();
    1401             : #endif
    1402           0 :   NS_PRECONDITION(prevInFlow, "bad prev-in-flow");
    1403             : 
    1404             :   // If the next-in-flow has a next-in-flow then delete it, too (and
    1405             :   // delete it first).
    1406             :   // Do this in a loop so we don't overflow the stack for frames
    1407             :   // with very many next-in-flows
    1408           0 :   nsIFrame* nextNextInFlow = aNextInFlow->GetNextInFlow();
    1409           0 :   if (nextNextInFlow) {
    1410           0 :     AutoTArray<nsIFrame*, 8> frames;
    1411           0 :     for (nsIFrame* f = nextNextInFlow; f; f = f->GetNextInFlow()) {
    1412           0 :       frames.AppendElement(f);
    1413             :     }
    1414           0 :     for (int32_t i = frames.Length() - 1; i >= 0; --i) {
    1415           0 :       nsIFrame* delFrame = frames.ElementAt(i);
    1416           0 :       delFrame->GetParent()->
    1417           0 :         DeleteNextInFlowChild(delFrame, aDeletingEmptyFrames);
    1418             :     }
    1419             :   }
    1420             : 
    1421             :   // Take the next-in-flow out of the parent's child list
    1422           0 :   DebugOnly<nsresult> rv = StealFrame(aNextInFlow);
    1423           0 :   NS_ASSERTION(NS_SUCCEEDED(rv), "StealFrame failure");
    1424             : 
    1425             : #ifdef DEBUG
    1426           0 :   if (aDeletingEmptyFrames) {
    1427           0 :     nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(aNextInFlow);
    1428             :   }
    1429             : #endif
    1430             : 
    1431             :   // Delete the next-in-flow frame and its descendants. This will also
    1432             :   // remove it from its next-in-flow/prev-in-flow chain.
    1433           0 :   aNextInFlow->Destroy();
    1434             : 
    1435           0 :   NS_POSTCONDITION(!prevInFlow->GetNextInFlow(), "non null next-in-flow");
    1436           0 : }
    1437             : 
    1438             : /**
    1439             :  * Set the frames on the overflow list
    1440             :  */
    1441             : void
    1442           0 : nsContainerFrame::SetOverflowFrames(const nsFrameList& aOverflowFrames)
    1443             : {
    1444           0 :   NS_PRECONDITION(aOverflowFrames.NotEmpty(), "Shouldn't be called");
    1445             : 
    1446           0 :   nsPresContext* pc = PresContext();
    1447           0 :   nsFrameList* newList = new (pc->PresShell()) nsFrameList(aOverflowFrames);
    1448             : 
    1449           0 :   SetProperty(OverflowProperty(), newList);
    1450           0 : }
    1451             : 
    1452             : nsFrameList*
    1453         185 : nsContainerFrame::GetPropTableFrames(
    1454             :   FrameListPropertyDescriptor aProperty) const
    1455             : {
    1456         185 :   return GetProperty(aProperty);
    1457             : }
    1458             : 
    1459             : nsFrameList*
    1460           0 : nsContainerFrame::RemovePropTableFrames(FrameListPropertyDescriptor aProperty)
    1461             : {
    1462           0 :   return RemoveProperty(aProperty);
    1463             : }
    1464             : 
    1465             : void
    1466           0 : nsContainerFrame::SetPropTableFrames(nsFrameList* aFrameList,
    1467             :                                      FrameListPropertyDescriptor aProperty)
    1468             : {
    1469           0 :   NS_PRECONDITION(aProperty && aFrameList, "null ptr");
    1470           0 :   NS_PRECONDITION(
    1471             :     (aProperty != nsContainerFrame::OverflowContainersProperty() &&
    1472             :      aProperty != nsContainerFrame::ExcessOverflowContainersProperty()) ||
    1473             :     IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
    1474             :     "this type of frame can't have overflow containers");
    1475           0 :   MOZ_ASSERT(!GetPropTableFrames(aProperty));
    1476           0 :   SetProperty(aProperty, aFrameList);
    1477           0 : }
    1478             : 
    1479             : /**
    1480             :  * Push aFromChild and its next siblings to the next-in-flow. Change the
    1481             :  * geometric parent of each frame that's pushed. If there is no next-in-flow
    1482             :  * the frames are placed on the overflow list (and the geometric parent is
    1483             :  * left unchanged).
    1484             :  *
    1485             :  * Updates the next-in-flow's child count. Does <b>not</b> update the
    1486             :  * pusher's child count.
    1487             :  *
    1488             :  * @param   aFromChild the first child frame to push. It is disconnected from
    1489             :  *            aPrevSibling
    1490             :  * @param   aPrevSibling aFromChild's previous sibling. Must not be null. It's
    1491             :  *            an error to push a parent's first child frame
    1492             :  */
    1493             : void
    1494           0 : nsContainerFrame::PushChildren(nsIFrame* aFromChild,
    1495             :                                nsIFrame* aPrevSibling)
    1496             : {
    1497           0 :   NS_PRECONDITION(aFromChild, "null pointer");
    1498           0 :   NS_PRECONDITION(aPrevSibling, "pushing first child");
    1499           0 :   NS_PRECONDITION(aPrevSibling->GetNextSibling() == aFromChild, "bad prev sibling");
    1500             : 
    1501             :   // Disconnect aFromChild from its previous sibling
    1502           0 :   nsFrameList tail = mFrames.RemoveFramesAfter(aPrevSibling);
    1503             : 
    1504             :   nsContainerFrame* nextInFlow =
    1505           0 :     static_cast<nsContainerFrame*>(GetNextInFlow());
    1506           0 :   if (nextInFlow) {
    1507             :     // XXX This is not a very good thing to do. If it gets removed
    1508             :     // then remove the copy of this routine that doesn't do this from
    1509             :     // nsInlineFrame.
    1510             :     // When pushing and pulling frames we need to check for whether any
    1511             :     // views need to be reparented.
    1512           0 :     for (nsIFrame* f = aFromChild; f; f = f->GetNextSibling()) {
    1513           0 :       nsContainerFrame::ReparentFrameView(f, this, nextInFlow);
    1514             :     }
    1515           0 :     nextInFlow->mFrames.InsertFrames(nextInFlow, nullptr, tail);
    1516             :   }
    1517             :   else {
    1518             :     // Add the frames to our overflow list
    1519           0 :     SetOverflowFrames(tail);
    1520             :   }
    1521           0 : }
    1522             : 
    1523             : /**
    1524             :  * Moves any frames on the overflow lists (the prev-in-flow's overflow list and
    1525             :  * the receiver's overflow list) to the child list.
    1526             :  *
    1527             :  * Updates this frame's child count and content mapping.
    1528             :  *
    1529             :  * @return  true if any frames were moved and false otherwise
    1530             :  */
    1531             : bool
    1532           0 : nsContainerFrame::MoveOverflowToChildList()
    1533             : {
    1534           0 :   bool result = false;
    1535             : 
    1536             :   // Check for an overflow list with our prev-in-flow
    1537           0 :   nsContainerFrame* prevInFlow = (nsContainerFrame*)GetPrevInFlow();
    1538           0 :   if (nullptr != prevInFlow) {
    1539             :     AutoFrameListPtr prevOverflowFrames(PresContext(),
    1540           0 :                                         prevInFlow->StealOverflowFrames());
    1541           0 :     if (prevOverflowFrames) {
    1542             :       // Tables are special; they can have repeated header/footer
    1543             :       // frames on mFrames at this point.
    1544           0 :       NS_ASSERTION(mFrames.IsEmpty() || IsTableFrame(), "bad overflow list");
    1545             :       // When pushing and pulling frames we need to check for whether any
    1546             :       // views need to be reparented.
    1547           0 :       nsContainerFrame::ReparentFrameViewList(*prevOverflowFrames,
    1548           0 :                                               prevInFlow, this);
    1549           0 :       mFrames.AppendFrames(this, *prevOverflowFrames);
    1550           0 :       result = true;
    1551             :     }
    1552             :   }
    1553             : 
    1554             :   // It's also possible that we have an overflow list for ourselves.
    1555           0 :   return DrainSelfOverflowList() || result;
    1556             : }
    1557             : 
    1558             : bool
    1559          32 : nsContainerFrame::DrainSelfOverflowList()
    1560             : {
    1561          64 :   AutoFrameListPtr overflowFrames(PresContext(), StealOverflowFrames());
    1562          32 :   if (overflowFrames) {
    1563           0 :     mFrames.AppendFrames(nullptr, *overflowFrames);
    1564           0 :     return true;
    1565             :   }
    1566          32 :   return false;
    1567             : }
    1568             : 
    1569             : nsFrameList*
    1570           0 : nsContainerFrame::DrainExcessOverflowContainersList(ChildFrameMerger aMergeFunc)
    1571             : {
    1572             :   nsFrameList* overflowContainers =
    1573           0 :     GetPropTableFrames(OverflowContainersProperty());
    1574             : 
    1575           0 :   NS_ASSERTION(!(overflowContainers && GetPrevInFlow()
    1576             :                  && static_cast<nsContainerFrame*>(GetPrevInFlow())
    1577             :                       ->GetPropTableFrames(ExcessOverflowContainersProperty())),
    1578             :                "conflicting overflow containers lists");
    1579             : 
    1580           0 :   if (!overflowContainers) {
    1581             :     // Drain excess from previnflow
    1582           0 :     nsContainerFrame* prev = (nsContainerFrame*) GetPrevInFlow();
    1583           0 :     if (prev) {
    1584             :       nsFrameList* excessFrames =
    1585           0 :         prev->RemovePropTableFrames(ExcessOverflowContainersProperty());
    1586           0 :       if (excessFrames) {
    1587           0 :         excessFrames->ApplySetParent(this);
    1588           0 :         nsContainerFrame::ReparentFrameViewList(*excessFrames, prev, this);
    1589           0 :         overflowContainers = excessFrames;
    1590           0 :         SetPropTableFrames(overflowContainers, OverflowContainersProperty());
    1591             :       }
    1592             :     }
    1593             :   }
    1594             : 
    1595             :   // Our own excess overflow containers from a previous reflow can still be
    1596             :   // present if our next-in-flow hasn't been reflown yet.  Move any children
    1597             :   // from it that don't have a continuation in this frame to the
    1598             :   // OverflowContainers list.
    1599             :   nsFrameList* selfExcessOCFrames =
    1600           0 :     RemovePropTableFrames(ExcessOverflowContainersProperty());
    1601           0 :   if (selfExcessOCFrames) {
    1602           0 :     nsFrameList toMove;
    1603           0 :     auto child = selfExcessOCFrames->FirstChild();
    1604           0 :     while (child) {
    1605           0 :       auto next = child->GetNextSibling();
    1606           0 :       MOZ_ASSERT(child->GetPrevInFlow(),
    1607             :                  "ExcessOverflowContainers frames must be continuations");
    1608           0 :       if (child->GetPrevInFlow()->GetParent() != this) {
    1609           0 :         selfExcessOCFrames->RemoveFrame(child);
    1610           0 :         toMove.AppendFrame(nullptr, child);
    1611             :       }
    1612           0 :       child = next;
    1613             :     }
    1614           0 :     if (toMove.IsEmpty()) {
    1615           0 :       SetPropTableFrames(selfExcessOCFrames, ExcessOverflowContainersProperty());
    1616           0 :     } else if (overflowContainers) {
    1617           0 :       aMergeFunc(*overflowContainers, toMove, this);
    1618           0 :       if (selfExcessOCFrames->IsEmpty()) {
    1619           0 :         selfExcessOCFrames->Delete(PresContext()->PresShell());
    1620             :       } else {
    1621           0 :         SetPropTableFrames(selfExcessOCFrames, ExcessOverflowContainersProperty());
    1622             :       }
    1623             :     } else {
    1624           0 :       if (selfExcessOCFrames->IsEmpty()) {
    1625           0 :         *selfExcessOCFrames = toMove;
    1626           0 :         overflowContainers = selfExcessOCFrames;
    1627             :       } else {
    1628           0 :         SetPropTableFrames(selfExcessOCFrames, ExcessOverflowContainersProperty());
    1629           0 :         auto shell = PresContext()->PresShell();
    1630           0 :         overflowContainers = new (shell) nsFrameList(toMove);
    1631             :       }
    1632           0 :       SetPropTableFrames(overflowContainers, OverflowContainersProperty());
    1633             :     }
    1634             :   }
    1635             : 
    1636           0 :   return overflowContainers;
    1637             : }
    1638             : 
    1639             : nsIFrame*
    1640           0 : nsContainerFrame::GetNextInFlowChild(ContinuationTraversingState& aState,
    1641             :                                      bool* aIsInOverflow)
    1642             : {
    1643           0 :   nsContainerFrame*& nextInFlow = aState.mNextInFlow;
    1644           0 :   while (nextInFlow) {
    1645             :     // See if there is any frame in the container
    1646           0 :     nsIFrame* frame = nextInFlow->mFrames.FirstChild();
    1647           0 :     if (frame) {
    1648           0 :       if (aIsInOverflow) {
    1649           0 :         *aIsInOverflow = false;
    1650             :       }
    1651           0 :       return frame;
    1652             :     }
    1653             :     // No frames in the principal list, try its overflow list
    1654           0 :     nsFrameList* overflowFrames = nextInFlow->GetOverflowFrames();
    1655           0 :     if (overflowFrames) {
    1656           0 :       if (aIsInOverflow) {
    1657           0 :         *aIsInOverflow = true;
    1658             :       }
    1659           0 :       return overflowFrames->FirstChild();
    1660             :     }
    1661           0 :     nextInFlow = static_cast<nsContainerFrame*>(nextInFlow->GetNextInFlow());
    1662             :   }
    1663           0 :   return nullptr;
    1664             : }
    1665             : 
    1666             : nsIFrame*
    1667           0 : nsContainerFrame::PullNextInFlowChild(ContinuationTraversingState& aState)
    1668             : {
    1669             :   bool isInOverflow;
    1670           0 :   nsIFrame* frame = GetNextInFlowChild(aState, &isInOverflow);
    1671           0 :   if (frame) {
    1672           0 :     nsContainerFrame* nextInFlow = aState.mNextInFlow;
    1673           0 :     if (isInOverflow) {
    1674           0 :       nsFrameList* overflowFrames = nextInFlow->GetOverflowFrames();
    1675           0 :       overflowFrames->RemoveFirstChild();
    1676           0 :       if (overflowFrames->IsEmpty()) {
    1677           0 :         nextInFlow->DestroyOverflowList();
    1678             :       }
    1679             :     } else {
    1680           0 :       nextInFlow->mFrames.RemoveFirstChild();
    1681             :     }
    1682             : 
    1683             :     // Move the frame to the principal frame list of this container
    1684           0 :     mFrames.AppendFrame(this, frame);
    1685             :     // AppendFrame has reparented the frame, we need
    1686             :     // to reparent the frame view then.
    1687           0 :     nsContainerFrame::ReparentFrameView(frame, nextInFlow, this);
    1688             :   }
    1689           0 :   return frame;
    1690             : }
    1691             : 
    1692             : bool
    1693           0 : nsContainerFrame::ResolvedOrientationIsVertical()
    1694             : {
    1695           0 :   StyleOrient orient = StyleDisplay()->mOrient;
    1696           0 :   switch (orient) {
    1697             :     case StyleOrient::Horizontal:
    1698           0 :       return false;
    1699             :     case StyleOrient::Vertical:
    1700           0 :       return true;
    1701             :     case StyleOrient::Inline:
    1702           0 :       return GetWritingMode().IsVertical();
    1703             :     case StyleOrient::Block:
    1704           0 :       return !GetWritingMode().IsVertical();
    1705             :   }
    1706           0 :   NS_NOTREACHED("unexpected -moz-orient value");
    1707           0 :   return false;
    1708             : }
    1709             : 
    1710             : // static
    1711             : bool
    1712         229 : nsContainerFrame::FrameStartsCounterScope(nsIFrame* aFrame)
    1713             : {
    1714         229 :   nsIContent* content = aFrame->GetContent();
    1715         229 :   if (!content || !content->IsHTMLElement())
    1716         159 :     return false;
    1717             : 
    1718          70 :   nsIAtom* localName = content->NodeInfo()->NameAtom();
    1719         140 :   return localName == nsGkAtoms::ol ||
    1720         140 :          localName == nsGkAtoms::ul ||
    1721         210 :          localName == nsGkAtoms::dir ||
    1722         140 :          localName == nsGkAtoms::menu;
    1723             : }
    1724             : 
    1725             : bool
    1726         229 : nsContainerFrame::RenumberList()
    1727             : {
    1728         229 :   if (!FrameStartsCounterScope(this)) {
    1729             :     // If this frame doesn't start a counter scope then we don't need
    1730             :     // to renumber child list items.
    1731         229 :     return false;
    1732             :   }
    1733             : 
    1734           0 :   MOZ_ASSERT(mContent->IsHTMLElement(),
    1735             :              "FrameStartsCounterScope should only return true for HTML elements");
    1736             : 
    1737             :   // Setup initial list ordinal value
    1738             :   // XXX Map html's start property to counter-reset style
    1739           0 :   int32_t ordinal = 1;
    1740             :   int32_t increment;
    1741           0 :   if (mContent->IsHTMLElement(nsGkAtoms::ol) &&
    1742           0 :       mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::reversed)) {
    1743           0 :     increment = -1;
    1744             :   } else {
    1745           0 :     increment = 1;
    1746             :   }
    1747             : 
    1748           0 :   nsGenericHTMLElement* hc = nsGenericHTMLElement::FromContent(mContent);
    1749             :   // Must be non-null, since FrameStartsCounterScope only returns true
    1750             :   // for HTML elements.
    1751           0 :   MOZ_ASSERT(hc, "How is mContent not HTML?");
    1752           0 :   const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::start);
    1753           0 :   nsContainerFrame* fif = static_cast<nsContainerFrame*>(FirstInFlow());
    1754           0 :   if (attr && attr->Type() == nsAttrValue::eInteger) {
    1755           0 :     ordinal = attr->GetIntegerValue();
    1756           0 :   } else if (increment < 0) {
    1757             :     // <ol reversed> case, or some other case with a negative increment: count
    1758             :     // up the child list
    1759           0 :     ordinal = 0;
    1760           0 :     fif->RenumberChildFrames(&ordinal, 0, -increment, true);
    1761             :   }
    1762             : 
    1763           0 :   return fif->RenumberChildFrames(&ordinal, 0, increment, false);
    1764             : }
    1765             : 
    1766             : // add in a sanity check for absurdly deep frame trees.  See bug 42138
    1767             : // can't just use IsFrameTreeTooDeep() because that method has side effects we don't want
    1768             : #define MAX_DEPTH_FOR_LIST_RENUMBERING 200  // 200 open displayable tags is pretty unrealistic
    1769             : 
    1770             : bool
    1771           0 : nsContainerFrame::RenumberFrameAndDescendants(int32_t* aOrdinal,
    1772             :                                               int32_t aDepth,
    1773             :                                               int32_t aIncrement,
    1774             :                                               bool aForCounting)
    1775             : {
    1776           0 :   NS_PRECONDITION(aOrdinal, "null params are immoral!");
    1777             : 
    1778             :   // add in a sanity check for absurdly deep frame trees.  See bug 42138
    1779           0 :   if (MAX_DEPTH_FOR_LIST_RENUMBERING < aDepth) {
    1780           0 :     return false;
    1781             :   }
    1782           0 :   const nsStyleDisplay* display = StyleDisplay();
    1783             : 
    1784             :   // drill down through any wrappers to the real frame
    1785           0 :   nsIFrame* kid = GetContentInsertionFrame();
    1786           0 :   if (!kid) {
    1787           0 :     return false;
    1788             :   }
    1789             : 
    1790             :   // Do not renumber list for summary elements.
    1791             :   HTMLSummaryElement* summary =
    1792           0 :     HTMLSummaryElement::FromContent(kid->GetContent());
    1793           0 :   if (summary && summary->IsMainSummary()) {
    1794           0 :     return false;
    1795             :   }
    1796             : 
    1797           0 :   bool kidRenumberedABullet = false;
    1798             : 
    1799             :   // If the frame is a list-item and the frame implements our
    1800             :   // block frame API then get its bullet and set the list item
    1801             :   // ordinal.
    1802           0 :   if (mozilla::StyleDisplay::ListItem == display->mDisplay) {
    1803             :     // Make certain that the frame is a block frame in case
    1804             :     // something foreign has crept in.
    1805           0 :     nsBlockFrame* listItem = nsLayoutUtils::GetAsBlock(kid);
    1806           0 :     if (listItem) {
    1807           0 :       nsBulletFrame* bullet = listItem->GetBullet();
    1808           0 :       if (bullet) {
    1809           0 :         if (!aForCounting) {
    1810             :           bool changed;
    1811           0 :           *aOrdinal = bullet->SetListItemOrdinal(*aOrdinal, &changed, aIncrement);
    1812           0 :           if (changed) {
    1813           0 :             kidRenumberedABullet = true;
    1814             : 
    1815             :             // The ordinal changed - mark the bullet frame, and any
    1816             :             // intermediate frames between it and the block (are there
    1817             :             // ever any?), dirty.
    1818             :             // The calling code will make the necessary FrameNeedsReflow
    1819             :             // call for the list ancestor.
    1820           0 :             bullet->AddStateBits(NS_FRAME_IS_DIRTY);
    1821           0 :             nsIFrame *f = bullet;
    1822           0 :             do {
    1823           0 :               nsIFrame *parent = f->GetParent();
    1824           0 :               parent->ChildIsDirty(f);
    1825           0 :               f = parent;
    1826           0 :             } while (f != listItem);
    1827             :           }
    1828             :         } else {
    1829             :           // We're only counting the number of children,
    1830             :           // not restyling them. Don't take |value|
    1831             :           // into account when incrementing the ordinal
    1832             :           // or dirty the bullet.
    1833           0 :           *aOrdinal += aIncrement;
    1834             :         }
    1835             :       }
    1836             : 
    1837             :       // XXX temporary? if the list-item has child list-items they
    1838             :       // should be numbered too; especially since the list-item is
    1839             :       // itself (ASSUMED!) not to be a counter-resetter.
    1840           0 :       bool meToo = listItem->RenumberChildFrames(aOrdinal, aDepth + 1,
    1841           0 :                                                  aIncrement, aForCounting);
    1842           0 :       if (meToo) {
    1843           0 :         kidRenumberedABullet = true;
    1844             :       }
    1845             :     }
    1846           0 :   } else if (display->mDisplay == mozilla::StyleDisplay::Block ||
    1847           0 :              display->mDisplay == mozilla::StyleDisplay::Flex ||
    1848           0 :              display->mDisplay == mozilla::StyleDisplay::Grid) {
    1849           0 :     if (FrameStartsCounterScope(kid)) {
    1850             :       // Don't bother recursing into a frame that is a new counter scope.
    1851             :       // Any list-items in there will be handled by it.
    1852             :     } else {
    1853           0 :       nsContainerFrame* container = do_QueryFrame(kid);
    1854           0 :       if (container) {
    1855             :         kidRenumberedABullet =
    1856           0 :           container->RenumberChildFrames(aOrdinal, aDepth + 1,
    1857           0 :                                          aIncrement, aForCounting);
    1858             :       }
    1859             :     }
    1860             :   }
    1861           0 :   return kidRenumberedABullet;
    1862             : }
    1863             : 
    1864             : bool
    1865           0 : nsContainerFrame::RenumberChildFrames(int32_t* aOrdinal,
    1866             :                                       int32_t aDepth,
    1867             :                                       int32_t aIncrement,
    1868             :                                       bool aForCounting)
    1869             : {
    1870           0 :   bool renumbered = false;
    1871           0 :   for (auto kid : mFrames) {
    1872             :     bool kidRenumbered =
    1873           0 :       kid->RenumberFrameAndDescendants(aOrdinal, aDepth, aIncrement, aForCounting);
    1874           0 :     if (!aForCounting && kidRenumbered) {
    1875           0 :       renumbered = true;
    1876             :     }
    1877             :   }
    1878             : 
    1879             :   // We need to set NS_FRAME_HAS_DIRTY_CHILDREN bits up the tree between
    1880             :   // the bullet and the caller of RenumberLists.  But the caller itself
    1881             :   // has to be responsible for setting the bit itself, since that caller
    1882             :   // might be making a FrameNeedsReflow call, which requires that the
    1883             :   // bit not be set yet.
    1884           0 :   if (renumbered && aDepth != 0) {
    1885           0 :     AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
    1886             :   }
    1887             : 
    1888           0 :   return renumbered;
    1889             : }
    1890             : 
    1891             : uint16_t
    1892           0 : nsContainerFrame::CSSAlignmentForAbsPosChild(const ReflowInput& aChildRI,
    1893             :                                              LogicalAxis aLogicalAxis) const
    1894             : {
    1895           0 :   MOZ_ASSERT(aChildRI.mFrame->IsAbsolutelyPositioned(),
    1896             :              "This method should only be called for abspos children");
    1897           0 :   NS_ERROR("Child classes that use css box alignment for abspos children "
    1898             :            "should provide their own implementation of this method!");
    1899             : 
    1900             :   // In the unexpected/unlikely event that this implementation gets invoked,
    1901             :   // just use "start" alignment.
    1902           0 :   return NS_STYLE_ALIGN_START;
    1903             : }
    1904             : 
    1905             : nsresult
    1906         134 : nsContainerFrame::AttributeChanged(int32_t         aNameSpaceID,
    1907             :                                    nsIAtom*        aAttribute,
    1908             :                                    int32_t         aModType)
    1909             : {
    1910         134 :   nsresult rv = nsSplittableFrame::AttributeChanged(aNameSpaceID,
    1911         134 :                                                     aAttribute, aModType);
    1912         134 :   if (NS_FAILED(rv)) {
    1913           0 :     return rv;
    1914             :   }
    1915         268 :   if (nsGkAtoms::start == aAttribute ||
    1916         134 :       (nsGkAtoms::reversed == aAttribute &&
    1917           0 :        mContent->IsHTMLElement(nsGkAtoms::ol))) {
    1918             : 
    1919             :     // XXX Not sure if this is necessary anymore
    1920           0 :     if (RenumberList()) {
    1921           0 :       PresContext()->PresShell()->
    1922           0 :         FrameNeedsReflow(this, nsIPresShell::eStyleChange,
    1923           0 :                          NS_FRAME_HAS_DIRTY_CHILDREN);
    1924             :     }
    1925             :   }
    1926         134 :   return rv;
    1927             : }
    1928             : 
    1929         185 : nsOverflowContinuationTracker::nsOverflowContinuationTracker(nsContainerFrame* aFrame,
    1930             :                                                              bool              aWalkOOFFrames,
    1931         185 :                                                              bool              aSkipOverflowContainerChildren)
    1932             :   : mOverflowContList(nullptr),
    1933             :     mPrevOverflowCont(nullptr),
    1934             :     mSentry(nullptr),
    1935             :     mParent(aFrame),
    1936             :     mSkipOverflowContainerChildren(aSkipOverflowContainerChildren),
    1937         185 :     mWalkOOFFrames(aWalkOOFFrames)
    1938             : {
    1939         185 :   NS_PRECONDITION(aFrame, "null frame pointer");
    1940         185 :   SetupOverflowContList();
    1941         185 : }
    1942             : 
    1943             : void
    1944         185 : nsOverflowContinuationTracker::SetupOverflowContList()
    1945             : {
    1946         185 :   NS_PRECONDITION(mParent, "null frame pointer");
    1947         185 :   NS_PRECONDITION(!mOverflowContList, "already have list");
    1948             :   nsContainerFrame* nif =
    1949         185 :     static_cast<nsContainerFrame*>(mParent->GetNextInFlow());
    1950         185 :   if (nif) {
    1951           0 :     mOverflowContList = nif->GetPropTableFrames(
    1952             :       nsContainerFrame::OverflowContainersProperty());
    1953           0 :     if (mOverflowContList) {
    1954           0 :       mParent = nif;
    1955           0 :       SetUpListWalker();
    1956             :     }
    1957             :   }
    1958         185 :   if (!mOverflowContList) {
    1959         185 :     mOverflowContList = mParent->GetPropTableFrames(
    1960             :       nsContainerFrame::ExcessOverflowContainersProperty());
    1961         185 :     if (mOverflowContList) {
    1962           0 :       SetUpListWalker();
    1963             :     }
    1964             :   }
    1965         185 : }
    1966             : 
    1967             : /**
    1968             :  * Helper function to walk past overflow continuations whose prev-in-flow
    1969             :  * isn't a normal child and to set mSentry and mPrevOverflowCont correctly.
    1970             :  */
    1971             : void
    1972           0 : nsOverflowContinuationTracker::SetUpListWalker()
    1973             : {
    1974           0 :   NS_ASSERTION(!mSentry && !mPrevOverflowCont,
    1975             :                "forgot to reset mSentry or mPrevOverflowCont");
    1976           0 :   if (mOverflowContList) {
    1977           0 :     nsIFrame* cur = mOverflowContList->FirstChild();
    1978           0 :     if (mSkipOverflowContainerChildren) {
    1979           0 :       while (cur && (cur->GetPrevInFlow()->GetStateBits()
    1980           0 :                      & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
    1981           0 :         mPrevOverflowCont = cur;
    1982           0 :         cur = cur->GetNextSibling();
    1983             :       }
    1984           0 :       while (cur && (!(cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
    1985           0 :                      == mWalkOOFFrames)) {
    1986           0 :         mPrevOverflowCont = cur;
    1987           0 :         cur = cur->GetNextSibling();
    1988             :       }
    1989             :     }
    1990           0 :     if (cur) {
    1991           0 :       mSentry = cur->GetPrevInFlow();
    1992             :     }
    1993             :   }
    1994           0 : }
    1995             : 
    1996             : /**
    1997             :  * Helper function to step forward through the overflow continuations list.
    1998             :  * Sets mSentry and mPrevOverflowCont, skipping over OOF or non-OOF frames
    1999             :  * as appropriate. May only be called when we have already set up an
    2000             :  * mOverflowContList; mOverflowContList cannot be null.
    2001             :  */
    2002             : void
    2003           0 : nsOverflowContinuationTracker::StepForward()
    2004             : {
    2005           0 :   NS_PRECONDITION(mOverflowContList, "null list");
    2006             : 
    2007             :   // Step forward
    2008           0 :   if (mPrevOverflowCont) {
    2009           0 :     mPrevOverflowCont = mPrevOverflowCont->GetNextSibling();
    2010             :   }
    2011             :   else {
    2012           0 :     mPrevOverflowCont = mOverflowContList->FirstChild();
    2013             :   }
    2014             : 
    2015             :   // Skip over oof or non-oof frames as appropriate
    2016           0 :   if (mSkipOverflowContainerChildren) {
    2017           0 :     nsIFrame* cur = mPrevOverflowCont->GetNextSibling();
    2018           0 :     while (cur && (!(cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
    2019           0 :                    == mWalkOOFFrames)) {
    2020           0 :       mPrevOverflowCont = cur;
    2021           0 :       cur = cur->GetNextSibling();
    2022             :     }
    2023             :   }
    2024             : 
    2025             :   // Set up the sentry
    2026           0 :   mSentry = (mPrevOverflowCont->GetNextSibling())
    2027           0 :             ? mPrevOverflowCont->GetNextSibling()->GetPrevInFlow()
    2028             :             : nullptr;
    2029           0 : }
    2030             : 
    2031             : nsresult
    2032           0 : nsOverflowContinuationTracker::Insert(nsIFrame*       aOverflowCont,
    2033             :                                       nsReflowStatus& aReflowStatus)
    2034             : {
    2035           0 :   NS_PRECONDITION(aOverflowCont, "null frame pointer");
    2036           0 :   NS_PRECONDITION(!mSkipOverflowContainerChildren || mWalkOOFFrames ==
    2037             :                   !!(aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
    2038             :                   "shouldn't insert frame that doesn't match walker type");
    2039           0 :   NS_PRECONDITION(aOverflowCont->GetPrevInFlow(),
    2040             :                   "overflow containers must have a prev-in-flow");
    2041           0 :   nsresult rv = NS_OK;
    2042           0 :   bool reparented = false;
    2043           0 :   nsPresContext* presContext = aOverflowCont->PresContext();
    2044           0 :   bool addToList = !mSentry || aOverflowCont != mSentry->GetNextInFlow();
    2045             : 
    2046             :   // If we have a list and aOverflowCont is already in it then don't try to
    2047             :   // add it again.
    2048           0 :   if (addToList && aOverflowCont->GetParent() == mParent &&
    2049           0 :       (aOverflowCont->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) &&
    2050           0 :       mOverflowContList && mOverflowContList->ContainsFrame(aOverflowCont)) {
    2051           0 :     addToList = false;
    2052           0 :     mPrevOverflowCont = aOverflowCont->GetPrevSibling();
    2053             :   }
    2054             : 
    2055           0 :   if (addToList) {
    2056           0 :     if (aOverflowCont->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
    2057             :       // aOverflowCont is in some other overflow container list,
    2058             :       // steal it first
    2059           0 :       NS_ASSERTION(!(mOverflowContList &&
    2060             :                      mOverflowContList->ContainsFrame(aOverflowCont)),
    2061             :                    "overflow containers out of order");
    2062           0 :       rv = aOverflowCont->GetParent()->StealFrame(aOverflowCont);
    2063           0 :       NS_ENSURE_SUCCESS(rv, rv);
    2064             :     }
    2065             :     else {
    2066           0 :       aOverflowCont->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
    2067             :     }
    2068           0 :     if (!mOverflowContList) {
    2069           0 :       mOverflowContList = new (presContext->PresShell()) nsFrameList();
    2070           0 :       mParent->SetPropTableFrames(mOverflowContList,
    2071           0 :         nsContainerFrame::ExcessOverflowContainersProperty());
    2072           0 :       SetUpListWalker();
    2073             :     }
    2074           0 :     if (aOverflowCont->GetParent() != mParent) {
    2075             :       nsContainerFrame::ReparentFrameView(aOverflowCont,
    2076           0 :                                           aOverflowCont->GetParent(),
    2077           0 :                                           mParent);
    2078           0 :       reparented = true;
    2079             :     }
    2080             : 
    2081             :     // If aOverflowCont has a prev/next-in-flow that might be in
    2082             :     // mOverflowContList we need to find it and insert after/before it to
    2083             :     // maintain the order amongst next-in-flows in this list.
    2084           0 :     nsIFrame* pif = aOverflowCont->GetPrevInFlow();
    2085           0 :     nsIFrame* nif = aOverflowCont->GetNextInFlow();
    2086           0 :     if ((pif && pif->GetParent() == mParent && pif != mPrevOverflowCont) ||
    2087           0 :         (nif && nif->GetParent() == mParent && mPrevOverflowCont)) {
    2088           0 :       for (nsFrameList::Enumerator e(*mOverflowContList); !e.AtEnd(); e.Next()) {
    2089           0 :         nsIFrame* f = e.get();
    2090           0 :         if (f == pif) {
    2091           0 :           mPrevOverflowCont = pif;
    2092           0 :           break;
    2093             :         }
    2094           0 :         if (f == nif) {
    2095           0 :           mPrevOverflowCont = f->GetPrevSibling();
    2096           0 :           break;
    2097             :         }
    2098             :       }
    2099             :     }
    2100             : 
    2101           0 :     mOverflowContList->InsertFrame(mParent, mPrevOverflowCont, aOverflowCont);
    2102           0 :     aReflowStatus.SetNextInFlowNeedsReflow();
    2103             :   }
    2104             : 
    2105             :   // If we need to reflow it, mark it dirty
    2106           0 :   if (aReflowStatus.NextInFlowNeedsReflow())
    2107           0 :     aOverflowCont->AddStateBits(NS_FRAME_IS_DIRTY);
    2108             : 
    2109             :   // It's in our list, just step forward
    2110           0 :   StepForward();
    2111           0 :   NS_ASSERTION(mPrevOverflowCont == aOverflowCont ||
    2112             :                (mSkipOverflowContainerChildren &&
    2113             :                 (mPrevOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW) !=
    2114             :                 (aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW)),
    2115             :               "OverflowContTracker in unexpected state");
    2116             : 
    2117           0 :   if (addToList) {
    2118             :     // Convert all non-overflow-container continuations of aOverflowCont
    2119             :     // into overflow containers and move them to our overflow
    2120             :     // tracker. This preserves the invariant that the next-continuations
    2121             :     // of an overflow container are also overflow containers.
    2122           0 :     nsIFrame* f = aOverflowCont->GetNextContinuation();
    2123           0 :     if (f && (!(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) ||
    2124           0 :               (!reparented && f->GetParent() == mParent) ||
    2125           0 :               (reparented && f->GetParent() != mParent))) {
    2126           0 :       if (!(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
    2127           0 :         rv = f->GetParent()->StealFrame(f);
    2128           0 :         NS_ENSURE_SUCCESS(rv, rv);
    2129             :       }
    2130           0 :       Insert(f, aReflowStatus);
    2131             :     }
    2132             :   }
    2133           0 :   return rv;
    2134             : }
    2135             : 
    2136             : void
    2137           0 : nsOverflowContinuationTracker::BeginFinish(nsIFrame* aChild)
    2138             : {
    2139           0 :   NS_PRECONDITION(aChild, "null ptr");
    2140           0 :   NS_PRECONDITION(aChild->GetNextInFlow(),
    2141             :                   "supposed to call Finish *before* deleting next-in-flow!");
    2142           0 :   for (nsIFrame* f = aChild; f; f = f->GetNextInFlow()) {
    2143             :     // We'll update these in EndFinish after the next-in-flows are gone.
    2144           0 :     if (f == mPrevOverflowCont) {
    2145           0 :       mSentry = nullptr;
    2146           0 :       mPrevOverflowCont = nullptr;
    2147           0 :       break;
    2148             :     }
    2149           0 :     if (f == mSentry) {
    2150           0 :       mSentry = nullptr;
    2151           0 :       break;
    2152             :     }
    2153             :   }
    2154           0 : }
    2155             : 
    2156             : void
    2157           0 : nsOverflowContinuationTracker::EndFinish(nsIFrame* aChild)
    2158             : {
    2159           0 :   if (!mOverflowContList) {
    2160           0 :     return;
    2161             :   }
    2162             :   // Forget mOverflowContList if it was deleted.
    2163           0 :   nsFrameList* eoc = mParent->GetProperty
    2164           0 :     (nsContainerFrame::ExcessOverflowContainersProperty());
    2165           0 :   if (eoc != mOverflowContList) {
    2166           0 :     nsFrameList* oc = static_cast<nsFrameList*>(mParent->GetProperty
    2167           0 :                         (nsContainerFrame::OverflowContainersProperty()));
    2168           0 :     if (oc != mOverflowContList) {
    2169             :       // mOverflowContList was deleted
    2170           0 :       mPrevOverflowCont = nullptr;
    2171           0 :       mSentry = nullptr;
    2172           0 :       mParent = aChild->GetParent();
    2173           0 :       mOverflowContList = nullptr;
    2174           0 :       SetupOverflowContList();
    2175           0 :       return;
    2176             :     }
    2177             :   }
    2178             :   // The list survived, update mSentry if needed.
    2179           0 :   if (!mSentry) {
    2180           0 :     if (!mPrevOverflowCont) {
    2181           0 :       SetUpListWalker();
    2182             :     } else {
    2183           0 :       mozilla::AutoRestore<nsIFrame*> saved(mPrevOverflowCont);
    2184             :       // step backward to make StepForward() use our current mPrevOverflowCont
    2185           0 :       mPrevOverflowCont = mPrevOverflowCont->GetPrevSibling();
    2186           0 :       StepForward();
    2187             :     }
    2188             :   }
    2189             : }
    2190             : 
    2191             : /////////////////////////////////////////////////////////////////////////////
    2192             : // Debugging
    2193             : 
    2194             : #ifdef DEBUG_FRAME_DUMP
    2195             : void
    2196           0 : nsContainerFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
    2197             : {
    2198           0 :   nsCString str;
    2199           0 :   ListGeneric(str, aPrefix, aFlags);
    2200             : 
    2201             :   // Output the children
    2202           0 :   bool outputOneList = false;
    2203           0 :   ChildListIterator lists(this);
    2204           0 :   for (; !lists.IsDone(); lists.Next()) {
    2205           0 :     if (outputOneList) {
    2206           0 :       str += aPrefix;
    2207             :     }
    2208           0 :     if (lists.CurrentID() != kPrincipalList) {
    2209           0 :       if (!outputOneList) {
    2210           0 :         str += "\n";
    2211           0 :         str += aPrefix;
    2212             :       }
    2213           0 :       str += nsPrintfCString("%s %p ", mozilla::layout::ChildListName(lists.CurrentID()),
    2214           0 :                              &GetChildList(lists.CurrentID()));
    2215             :     }
    2216           0 :     fprintf_stderr(out, "%s<\n", str.get());
    2217           0 :     str = "";
    2218           0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    2219           0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    2220           0 :       nsIFrame* kid = childFrames.get();
    2221             :       // Verify the child frame's parent frame pointer is correct
    2222           0 :       NS_ASSERTION(kid->GetParent() == this, "bad parent frame pointer");
    2223             : 
    2224             :       // Have the child frame list
    2225           0 :       nsCString pfx(aPrefix);
    2226           0 :       pfx += "  ";
    2227           0 :       kid->List(out, pfx.get(), aFlags);
    2228             :     }
    2229           0 :     fprintf_stderr(out, "%s>\n", aPrefix);
    2230           0 :     outputOneList = true;
    2231             :   }
    2232             : 
    2233           0 :   if (!outputOneList) {
    2234           0 :     fprintf_stderr(out, "%s<>\n", str.get());
    2235             :   }
    2236           0 : }
    2237             : #endif

Generated by: LCOV version 1.13