LCOV - code coverage report
Current view: top level - layout/base - nsCSSFrameConstructor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 718 4226 17.0 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * construction of a frame tree that is nearly isomorphic to the content
       9             :  * tree and updating of that tree in response to dynamic changes
      10             :  */
      11             : 
      12             : #include "nsCSSFrameConstructor.h"
      13             : 
      14             : #include "mozilla/AutoRestore.h"
      15             : #include "mozilla/ComputedStyleInlines.h"
      16             : #include "mozilla/DebugOnly.h"
      17             : #include "mozilla/ErrorResult.h"
      18             : #include "mozilla/dom/HTMLDetailsElement.h"
      19             : #include "mozilla/dom/HTMLSelectElement.h"
      20             : #include "mozilla/dom/HTMLSummaryElement.h"
      21             : #include "mozilla/EventStates.h"
      22             : #include "mozilla/Likely.h"
      23             : #include "mozilla/LinkedList.h"
      24             : #include "mozilla/MemoryReporting.h"
      25             : #include "mozilla/PresShell.h"
      26             : #include "mozilla/ServoBindings.h"
      27             : #include "mozilla/ServoStyleSetInlines.h"
      28             : #include "mozilla/StaticPrefs.h"
      29             : #include "nsAbsoluteContainingBlock.h"
      30             : #include "nsCSSPseudoElements.h"
      31             : #include "nsAtom.h"
      32             : #include "nsIFrameInlines.h"
      33             : #include "nsGkAtoms.h"
      34             : #include "nsPresContext.h"
      35             : #include "nsIDocument.h"
      36             : #include "nsIDocumentInlines.h"
      37             : #include "nsTableFrame.h"
      38             : #include "nsTableColFrame.h"
      39             : #include "nsTableRowFrame.h"
      40             : #include "nsTableCellFrame.h"
      41             : #include "nsHTMLParts.h"
      42             : #include "nsIPresShell.h"
      43             : #include "nsUnicharUtils.h"
      44             : #include "nsViewManager.h"
      45             : #include "nsStyleConsts.h"
      46             : #ifdef MOZ_XUL
      47             : #include "nsXULElement.h"
      48             : #include "mozilla/dom/BoxObject.h"
      49             : #endif // MOZ_XUL
      50             : #include "nsContainerFrame.h"
      51             : #include "nsNameSpaceManager.h"
      52             : #include "nsIComboboxControlFrame.h"
      53             : #include "nsComboboxControlFrame.h"
      54             : #include "nsIListControlFrame.h"
      55             : #include "nsPlaceholderFrame.h"
      56             : #include "nsTableRowGroupFrame.h"
      57             : #include "nsIFormControl.h"
      58             : #include "nsCSSAnonBoxes.h"
      59             : #include "nsTextFragment.h"
      60             : #include "nsIAnonymousContentCreator.h"
      61             : #include "nsBindingManager.h"
      62             : #include "nsXBLBinding.h"
      63             : #include "nsContentUtils.h"
      64             : #include "nsIScriptError.h"
      65             : #ifdef XP_MACOSX
      66             : #include "nsIDocShell.h"
      67             : #endif
      68             : #include "ChildIterator.h"
      69             : #include "nsError.h"
      70             : #include "nsLayoutUtils.h"
      71             : #include "nsAutoPtr.h"
      72             : #include "nsBoxFrame.h"
      73             : #include "nsBoxLayout.h"
      74             : #include "nsFlexContainerFrame.h"
      75             : #include "nsGridContainerFrame.h"
      76             : #include "RubyUtils.h"
      77             : #include "nsRubyFrame.h"
      78             : #include "nsRubyBaseFrame.h"
      79             : #include "nsRubyBaseContainerFrame.h"
      80             : #include "nsRubyTextFrame.h"
      81             : #include "nsRubyTextContainerFrame.h"
      82             : #include "nsImageFrame.h"
      83             : #include "nsIObjectLoadingContent.h"
      84             : #include "nsTArray.h"
      85             : #include "mozilla/dom/CharacterData.h"
      86             : #include "mozilla/dom/Element.h"
      87             : #include "mozilla/dom/ElementInlines.h"
      88             : #include "nsAutoLayoutPhase.h"
      89             : #include "nsStyleStructInlines.h"
      90             : #include "nsPageContentFrame.h"
      91             : #include "mozilla/RestyleManager.h"
      92             : #include "StickyScrollContainer.h"
      93             : #include "nsFieldSetFrame.h"
      94             : #include "nsInlineFrame.h"
      95             : #include "nsBlockFrame.h"
      96             : #include "nsCanvasFrame.h"
      97             : #include "nsFirstLetterFrame.h"
      98             : #include "nsGfxScrollFrame.h"
      99             : #include "nsPageFrame.h"
     100             : #include "nsSimplePageSequenceFrame.h"
     101             : #include "nsTableWrapperFrame.h"
     102             : #include "nsIScrollableFrame.h"
     103             : #include "nsBackdropFrame.h"
     104             : #include "nsTransitionManager.h"
     105             : #include "DetailsFrame.h"
     106             : #include "nsThemeConstants.h"
     107             : 
     108             : #ifdef MOZ_XUL
     109             : #include "nsIRootBox.h"
     110             : #endif
     111             : #ifdef ACCESSIBILITY
     112             : #include "nsAccessibilityService.h"
     113             : #endif
     114             : 
     115             : #include "nsXBLService.h"
     116             : 
     117             : #undef NOISY_FIRST_LETTER
     118             : 
     119             : #include "nsMathMLParts.h"
     120             : #include "mozilla/dom/SVGTests.h"
     121             : #include "nsSVGUtils.h"
     122             : 
     123             : #include "nsRefreshDriver.h"
     124             : #include "nsTextNode.h"
     125             : #include "ActiveLayerTracker.h"
     126             : #include "nsIPresShellInlines.h"
     127             : 
     128             : using namespace mozilla;
     129             : using namespace mozilla::dom;
     130             : 
     131             : // An alias for convenience.
     132             : static const nsIFrame::ChildListID kPrincipalList = nsIFrame::kPrincipalList;
     133             : 
     134             : nsIFrame*
     135             : NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     136             : 
     137             : nsIFrame*
     138             : NS_NewHTMLVideoFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     139             : 
     140             : nsContainerFrame*
     141             : NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     142             : nsContainerFrame*
     143             : NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     144             : nsIFrame*
     145             : NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     146             : nsIFrame*
     147             : NS_NewSVGGeometryFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     148             : nsIFrame*
     149             : NS_NewSVGGFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     150             : nsIFrame*
     151             : NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     152             : nsContainerFrame*
     153             : NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     154             : nsIFrame*
     155             : NS_NewSVGAFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     156             : nsIFrame*
     157             : NS_NewSVGSwitchFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     158             : nsIFrame*
     159             : NS_NewSVGSymbolFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     160             : nsIFrame*
     161             : NS_NewSVGTextFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     162             : nsIFrame*
     163             : NS_NewSVGContainerFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     164             : nsIFrame*
     165             : NS_NewSVGUseFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     166             : nsIFrame*
     167             : NS_NewSVGViewFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     168             : extern nsIFrame*
     169             : NS_NewSVGLinearGradientFrame(nsIPresShell *aPresShell, ComputedStyle* aStyle);
     170             : extern nsIFrame*
     171             : NS_NewSVGRadialGradientFrame(nsIPresShell *aPresShell, ComputedStyle* aStyle);
     172             : extern nsIFrame*
     173             : NS_NewSVGStopFrame(nsIPresShell *aPresShell, ComputedStyle* aStyle);
     174             : nsContainerFrame*
     175             : NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     176             : nsContainerFrame*
     177             : NS_NewSVGMarkerAnonChildFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     178             : extern nsIFrame*
     179             : NS_NewSVGImageFrame(nsIPresShell *aPresShell, ComputedStyle* aStyle);
     180             : nsIFrame*
     181             : NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     182             : nsIFrame*
     183             : NS_NewSVGFilterFrame(nsIPresShell *aPresShell, ComputedStyle* aStyle);
     184             : nsIFrame*
     185             : NS_NewSVGPatternFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     186             : nsIFrame*
     187             : NS_NewSVGMaskFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     188             : nsIFrame*
     189             : NS_NewSVGFEContainerFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     190             : nsIFrame*
     191             : NS_NewSVGFELeafFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     192             : nsIFrame*
     193             : NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     194             : nsIFrame*
     195             : NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     196             : 
     197             : #include "mozilla/dom/NodeInfo.h"
     198             : #include "prenv.h"
     199             : #include "nsNodeInfoManager.h"
     200             : #include "nsContentCreatorFunctions.h"
     201             : 
     202             : #ifdef DEBUG
     203             : // Set the environment variable GECKO_FRAMECTOR_DEBUG_FLAGS to one or
     204             : // more of the following flags (comma separated) for handy debug
     205             : // output.
     206             : static bool gNoisyContentUpdates = false;
     207             : static bool gReallyNoisyContentUpdates = false;
     208             : static bool gNoisyInlineConstruction = false;
     209             : 
     210             : struct FrameCtorDebugFlags {
     211             :   const char* name;
     212             :   bool* on;
     213             : };
     214             : 
     215             : static FrameCtorDebugFlags gFlags[] = {
     216             :   { "content-updates",              &gNoisyContentUpdates },
     217             :   { "really-noisy-content-updates", &gReallyNoisyContentUpdates },
     218             :   { "noisy-inline",                 &gNoisyInlineConstruction }
     219             : };
     220             : 
     221             : #define NUM_DEBUG_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
     222             : #endif
     223             : 
     224             : 
     225             : #ifdef MOZ_XUL
     226             : #include "nsMenuFrame.h"
     227             : #include "nsPopupSetFrame.h"
     228             : #include "nsTreeColFrame.h"
     229             : #include "nsIBoxObject.h"
     230             : #include "nsPIListBoxObject.h"
     231             : #include "nsListBoxBodyFrame.h"
     232             : #include "nsListItemFrame.h"
     233             : #include "nsXULLabelFrame.h"
     234             : 
     235             : //------------------------------------------------------------------
     236             : 
     237             : nsContainerFrame*
     238             : NS_NewRootBoxFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     239             : 
     240             : nsContainerFrame*
     241             : NS_NewDocElementBoxFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     242             : 
     243             : nsIFrame*
     244             : NS_NewDeckFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     245             : 
     246             : nsIFrame*
     247             : NS_NewLeafBoxFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     248             : 
     249             : nsIFrame*
     250             : NS_NewStackFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     251             : 
     252             : nsIFrame*
     253             : NS_NewProgressMeterFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     254             : 
     255             : nsIFrame*
     256             : NS_NewRangeFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     257             : 
     258             : nsIFrame*
     259             : NS_NewImageBoxFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     260             : 
     261             : nsIFrame*
     262             : NS_NewTextBoxFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     263             : 
     264             : nsIFrame*
     265             : NS_NewGroupBoxFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     266             : 
     267             : nsIFrame*
     268             : NS_NewButtonBoxFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     269             : 
     270             : nsIFrame*
     271             : NS_NewSplitterFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     272             : 
     273             : nsIFrame*
     274             : NS_NewMenuPopupFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     275             : 
     276             : nsIFrame*
     277             : NS_NewPopupSetFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
     278             : 
     279             : nsIFrame*
     280             : NS_NewMenuFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle, uint32_t aFlags);
     281             : 
     282             : nsIFrame*
     283             : NS_NewMenuBarFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     284             : 
     285             : nsIFrame*
     286             : NS_NewTreeBodyFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     287             : 
     288             : // grid
     289             : nsresult
     290             : NS_NewGridLayout2 ( nsIPresShell* aPresShell, nsBoxLayout** aNewLayout );
     291             : nsIFrame*
     292             : NS_NewGridRowLeafFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     293             : nsIFrame*
     294             : NS_NewGridRowGroupFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     295             : 
     296             : // end grid
     297             : 
     298             : nsIFrame*
     299             : NS_NewTitleBarFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     300             : 
     301             : nsIFrame*
     302             : NS_NewResizerFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     303             : 
     304             : 
     305             : #endif
     306             : 
     307             : nsHTMLScrollFrame*
     308             : NS_NewHTMLScrollFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle, bool aIsRoot);
     309             : 
     310             : nsXULScrollFrame*
     311             : NS_NewXULScrollFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle,
     312             :                      bool aIsRoot, bool aClipAllDescendants);
     313             : 
     314             : nsIFrame*
     315             : NS_NewSliderFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     316             : 
     317             : nsIFrame*
     318             : NS_NewScrollbarFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     319             : 
     320             : nsIFrame*
     321             : NS_NewScrollbarButtonFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
     322             : 
     323             : 
     324             : #ifdef NOISY_FINDFRAME
     325             : static int32_t FFWC_totalCount=0;
     326             : static int32_t FFWC_doLoop=0;
     327             : static int32_t FFWC_doSibling=0;
     328             : static int32_t FFWC_recursions=0;
     329             : static int32_t FFWC_nextInFlows=0;
     330             : #endif
     331             : 
     332             : #ifdef MOZ_XUL
     333             : 
     334             : static bool
     335           0 : IsXULListBox(nsIContent* aContainer)
     336             : {
     337           0 :   return aContainer->IsXULElement(nsGkAtoms::listbox);
     338             : }
     339             : 
     340             : static
     341             : nsListBoxBodyFrame*
     342           0 : MaybeGetListBoxBodyFrame(nsIContent* aChild)
     343             : {
     344           0 :   if (aChild->IsXULElement(nsGkAtoms::listitem) && aChild->GetParent() &&
     345           0 :       IsXULListBox(aChild->GetParent())) {
     346             :     RefPtr<nsXULElement> xulElement =
     347           0 :       nsXULElement::FromNode(aChild->GetParent());
     348           0 :     nsCOMPtr<nsIBoxObject> boxObject = xulElement->GetBoxObject(IgnoreErrors());
     349           0 :     nsCOMPtr<nsPIListBoxObject> listBoxObject = do_QueryInterface(boxObject);
     350           0 :     if (listBoxObject) {
     351           0 :       return listBoxObject->GetListBoxBody(false);
     352             :     }
     353             :   }
     354             : 
     355             :   return nullptr;
     356             : }
     357             : #endif // MOZ_XUL
     358             : 
     359             : // Returns true if aFrame is an anonymous flex/grid item.
     360             : static inline bool
     361           0 : IsAnonymousFlexOrGridItem(const nsIFrame* aFrame)
     362             : {
     363           0 :   const nsAtom* pseudoType = aFrame->Style()->GetPseudo();
     364           0 :   return pseudoType == nsCSSAnonBoxes::anonymousFlexItem ||
     365           0 :          pseudoType == nsCSSAnonBoxes::anonymousGridItem;
     366             : }
     367             : 
     368             : // Returns true if aFrame is a flex/grid container.
     369             : static inline bool
     370           0 : IsFlexOrGridContainer(const nsIFrame* aFrame)
     371             : {
     372           0 :   const LayoutFrameType t = aFrame->Type();
     373           0 :   return t == LayoutFrameType::FlexContainer ||
     374           0 :          t == LayoutFrameType::GridContainer;
     375             : }
     376             : 
     377             : // Returns true IFF the given nsIFrame is a nsFlexContainerFrame and
     378             : // represents a -webkit-{inline-}box or -moz-{inline-}box container.
     379             : static inline bool
     380           0 : IsFlexContainerForLegacyBox(const nsIFrame* aFrame)
     381             : {
     382           0 :   return aFrame->IsFlexContainerFrame() &&
     383           0 :          aFrame->HasAnyStateBits(NS_STATE_FLEX_IS_EMULATING_LEGACY_BOX);
     384             : }
     385             : 
     386             : #if DEBUG
     387             : static void
     388           0 : AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
     389             :                                     const nsIFrame* aParent)
     390             : {
     391           0 :   MOZ_ASSERT(IsAnonymousFlexOrGridItem(aChild),
     392             :              "expected an anonymous flex or grid item child frame");
     393           0 :   MOZ_ASSERT(aParent, "expected a parent frame");
     394           0 :   const nsAtom* pseudoType = aChild->Style()->GetPseudo();
     395           0 :   if (pseudoType == nsCSSAnonBoxes::anonymousFlexItem) {
     396           0 :     MOZ_ASSERT(aParent->IsFlexContainerFrame(),
     397             :                "anonymous flex items should only exist as children "
     398             :                "of flex container frames");
     399             :   } else {
     400           0 :     MOZ_ASSERT(aParent->IsGridContainerFrame(),
     401             :                "anonymous grid items should only exist as children "
     402             :                "of grid container frames");
     403             :   }
     404           0 : }
     405             : #else
     406             : #define AssertAnonymousFlexOrGridItemParent(x, y) do { /* nothing */ } while(0)
     407             : #endif
     408             : 
     409             : static inline nsContainerFrame*
     410           0 : GetFieldSetBlockFrame(nsIFrame* aFieldsetFrame)
     411             : {
     412             :   // Depends on the fieldset child frame order - see ConstructFieldSetFrame() below.
     413           0 :   nsIFrame* firstChild = aFieldsetFrame->PrincipalChildList().FirstChild();
     414           0 :   nsIFrame* inner = firstChild && firstChild->GetNextSibling() ? firstChild->GetNextSibling() : firstChild;
     415           0 :   return inner ? inner->GetContentInsertionFrame() : nullptr;
     416             : }
     417             : 
     418             : #define FCDATA_DECL(_flags, _func)                            \
     419             :   { _flags, { (FrameCreationFunc)_func }, nullptr, nullptr }
     420             : #define FCDATA_WITH_WRAPPING_BLOCK(_flags, _func, _anon_box)  \
     421             :   { _flags | FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS,        \
     422             :       { (FrameCreationFunc)_func }, nullptr, &_anon_box }
     423             : 
     424             : #define UNREACHABLE_FCDATA()                                  \
     425             :   { 0, { (FrameCreationFunc)nullptr }, nullptr, nullptr }
     426             : //----------------------------------------------------------------------
     427             : 
     428             : /**
     429             :  * True if aFrame is an actual inline frame in the sense of non-replaced
     430             :  * display:inline CSS boxes.  In other words, it can be affected by {ib}
     431             :  * splitting and can contain first-letter frames.  Basically, this is either an
     432             :  * inline frame (positioned or otherwise) or an line frame (this last because
     433             :  * it can contain first-letter and because inserting blocks in the middle of it
     434             :  * needs to terminate it).
     435             :  */
     436             : static bool
     437           0 : IsInlineFrame(const nsIFrame* aFrame)
     438             : {
     439           0 :   return aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
     440             : }
     441             : 
     442             : /**
     443             :  * True for display: contents elements.
     444             :  */
     445             : static inline bool
     446             : IsDisplayContents(const Element* aElement)
     447             : {
     448           0 :   return aElement->IsDisplayContents();
     449             : }
     450             : 
     451             : static inline bool
     452           0 : IsDisplayContents(const nsIContent* aContent)
     453             : {
     454           0 :   return aContent->IsElement() && IsDisplayContents(aContent->AsElement());
     455             : }
     456             : 
     457             : /**
     458             :  * True if aFrame is an instance of an SVG frame class or is an inline/block
     459             :  * frame being used for SVG text.
     460             :  */
     461             : static bool
     462           0 : IsFrameForSVG(const nsIFrame* aFrame)
     463             : {
     464           0 :   return aFrame->IsFrameOfType(nsIFrame::eSVG) ||
     465           0 :          nsSVGUtils::IsInSVGTextSubtree(aFrame);
     466             : }
     467             : 
     468             : /**
     469             :  * Returns true iff aFrame explicitly prevents its descendants from floating
     470             :  * (at least, down to the level of descendants which themselves are
     471             :  * float-containing blocks -- those will manage the floating status of any
     472             :  * lower-level descendents inside them, of course).
     473             :  */
     474             : static bool
     475           0 : ShouldSuppressFloatingOfDescendants(nsIFrame* aFrame)
     476             : {
     477           0 :   return aFrame->IsFrameOfType(nsIFrame::eMathML) ||
     478           0 :     aFrame->IsXULBoxFrame() ||
     479           0 :     ::IsFlexOrGridContainer(aFrame);
     480             : }
     481             : 
     482             : /**
     483             :  * If any children require a block parent, return the first such child.
     484             :  * Otherwise return null.
     485             :  */
     486             : static nsIContent*
     487           0 : AnyKidsNeedBlockParent(nsIFrame *aFrameList)
     488             : {
     489           0 :   for (nsIFrame *k = aFrameList; k; k = k->GetNextSibling()) {
     490             :     // Line participants, such as text and inline frames, can't be
     491             :     // directly inside a XUL box; they must be wrapped in an
     492             :     // intermediate block.
     493           0 :     if (k->IsFrameOfType(nsIFrame::eLineParticipant)) {
     494           0 :       return k->GetContent();
     495             :     }
     496             :   }
     497             :   return nullptr;
     498             : }
     499             : 
     500             : // Reparent a frame into a wrapper frame that is a child of its old parent.
     501             : static void
     502           0 : ReparentFrame(RestyleManager* aRestyleManager,
     503             :               nsContainerFrame* aNewParentFrame,
     504             :               nsIFrame* aFrame,
     505             :               bool aForceStyleReparent)
     506             : {
     507           0 :   aFrame->SetParent(aNewParentFrame);
     508             :   // We reparent frames for two reasons: to put them inside ::first-line, and to
     509             :   // put them inside some wrapper anonymous boxes.
     510           0 :   if (aForceStyleReparent) {
     511           0 :     aRestyleManager->ReparentComputedStyleForFirstLine(aFrame);
     512             :   }
     513           0 : }
     514             : 
     515             : static void
     516           0 : ReparentFrames(nsCSSFrameConstructor* aFrameConstructor,
     517             :                nsContainerFrame* aNewParentFrame,
     518             :                const nsFrameList& aFrameList,
     519             :                bool aForceStyleReparent)
     520             : {
     521           0 :   RestyleManager* restyleManager = aFrameConstructor->RestyleManager();
     522           0 :   for (nsIFrame* f : aFrameList) {
     523           0 :     ReparentFrame(restyleManager, aNewParentFrame, f, aForceStyleReparent);
     524             :   }
     525           0 : }
     526             : 
     527             : //----------------------------------------------------------------------
     528             : //
     529             : // When inline frames get weird and have block frames in them, we
     530             : // annotate them to help us respond to incremental content changes
     531             : // more easily.
     532             : 
     533             : static inline bool
     534           0 : IsFramePartOfIBSplit(nsIFrame* aFrame)
     535             : {
     536           0 :   bool result = (aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) != 0;
     537           0 :   MOZ_ASSERT(!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) ||
     538             :                         static_cast<nsInlineFrame*>(do_QueryFrame(aFrame)),
     539             :              "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT");
     540           0 :   return result;
     541             : }
     542             : 
     543           0 : static nsContainerFrame* GetIBSplitSibling(nsIFrame* aFrame)
     544             : {
     545           0 :   MOZ_ASSERT(IsFramePartOfIBSplit(aFrame), "Shouldn't call this");
     546             : 
     547             :   // We only store the "ib-split sibling" annotation with the first
     548             :   // frame in the continuation chain. Walk back to find that frame now.
     549           0 :   return aFrame->FirstContinuation()->
     550           0 :            GetProperty(nsIFrame::IBSplitSibling());
     551             : }
     552             : 
     553           0 : static nsContainerFrame* GetIBSplitPrevSibling(nsIFrame* aFrame)
     554             : {
     555           0 :   MOZ_ASSERT(IsFramePartOfIBSplit(aFrame), "Shouldn't call this");
     556             : 
     557             :   // We only store the ib-split sibling annotation with the first
     558             :   // frame in the continuation chain. Walk back to find that frame now.
     559           0 :   return aFrame->FirstContinuation()->
     560           0 :            GetProperty(nsIFrame::IBSplitPrevSibling());
     561             : }
     562             : 
     563             : static nsContainerFrame*
     564           0 : GetLastIBSplitSibling(nsIFrame* aFrame)
     565             : {
     566           0 :   for (nsIFrame* frame = aFrame, *next; ; frame = next) {
     567           0 :     next = GetIBSplitSibling(frame);
     568           0 :     if (!next) {
     569             :       return static_cast<nsContainerFrame*>(frame);
     570             :     }
     571             :   }
     572             :   NS_NOTREACHED("unreachable code");
     573             :   return nullptr;
     574             : }
     575             : 
     576             : static void
     577           0 : SetFrameIsIBSplit(nsContainerFrame* aFrame, nsContainerFrame* aIBSplitSibling)
     578             : {
     579           0 :   MOZ_ASSERT(aFrame, "bad args!");
     580             : 
     581             :   // We should be the only continuation
     582           0 :   NS_ASSERTION(!aFrame->GetPrevContinuation(),
     583             :                "assigning ib-split sibling to other than first continuation!");
     584           0 :   NS_ASSERTION(!aFrame->GetNextContinuation() ||
     585             :                IsFramePartOfIBSplit(aFrame->GetNextContinuation()),
     586             :                "should have no non-ib-split continuations here");
     587             : 
     588             :   // Mark the frame as ib-split.
     589           0 :   aFrame->AddStateBits(NS_FRAME_PART_OF_IBSPLIT);
     590             : 
     591           0 :   if (aIBSplitSibling) {
     592           0 :     NS_ASSERTION(!aIBSplitSibling->GetPrevContinuation(),
     593             :                  "assigning something other than the first continuation as the "
     594             :                  "ib-split sibling");
     595             : 
     596             :     // Store the ib-split sibling (if we were given one) with the
     597             :     // first frame in the flow.
     598           0 :     aFrame->SetProperty(nsIFrame::IBSplitSibling(), aIBSplitSibling);
     599           0 :     aIBSplitSibling->SetProperty(nsIFrame::IBSplitPrevSibling(), aFrame);
     600             :   }
     601           0 : }
     602             : 
     603             : static nsIFrame*
     604           0 : GetIBContainingBlockFor(nsIFrame* aFrame)
     605             : {
     606           0 :   MOZ_ASSERT(IsFramePartOfIBSplit(aFrame),
     607             :              "GetIBContainingBlockFor() should only be called on known IB frames");
     608             : 
     609             :   // Get the first "normal" ancestor of the target frame.
     610             :   nsIFrame* parentFrame;
     611             :   do {
     612           0 :     parentFrame = aFrame->GetParent();
     613             : 
     614           0 :     if (! parentFrame) {
     615           0 :       NS_ERROR("no unsplit block frame in IB hierarchy");
     616           0 :       return aFrame;
     617             :     }
     618             : 
     619             :     // Note that we ignore non-ib-split frames which have a pseudo on their
     620             :     // ComputedStyle -- they're not the frames we're looking for!  In
     621             :     // particular, they may be hiding a real parent that _is_ in an ib-split.
     622           0 :     if (!IsFramePartOfIBSplit(parentFrame) &&
     623           0 :         !parentFrame->Style()->GetPseudo())
     624             :       break;
     625             : 
     626             :     aFrame = parentFrame;
     627             :   } while (1);
     628             : 
     629             :   // post-conditions
     630             :   NS_ASSERTION(parentFrame, "no normal ancestor found for ib-split frame "
     631             :                             "in GetIBContainingBlockFor");
     632           0 :   NS_ASSERTION(parentFrame != aFrame, "parentFrame is actually the child frame - bogus reslt");
     633             : 
     634             :   return parentFrame;
     635             : }
     636             : 
     637             : // This is a bit slow, but sometimes we need it.
     638             : static bool
     639           0 : ParentIsWrapperAnonBox(nsIFrame* aParent)
     640             : {
     641           0 :   nsIFrame* maybeAnonBox = aParent;
     642           0 :   if (maybeAnonBox->Style()->GetPseudo() ==
     643             :         nsCSSAnonBoxes::cellContent) {
     644             :     // The thing that would maybe be a wrapper anon box is the cell.
     645           0 :     maybeAnonBox = maybeAnonBox->GetParent();
     646             :   }
     647           0 :   return maybeAnonBox->Style()->IsWrapperAnonBox();
     648             : }
     649             : 
     650             : //----------------------------------------------------------------------
     651             : 
     652             : // Block/inline frame construction logic. We maintain a few invariants here:
     653             : //
     654             : // 1. Block frames contain block and inline frames.
     655             : //
     656             : // 2. Inline frames only contain inline frames. If an inline parent has a block
     657             : // child then the block child is migrated upward until it lands in a block
     658             : // parent (the inline frames containing block is where it will end up).
     659             : 
     660             : // After this function returns, aLink is pointing to the first link at or
     661             : // after its starting position for which the next frame is a block.  If there
     662             : // is no such link, it points to the end of the list.
     663             : static void
     664           0 : FindFirstBlock(nsFrameList::FrameLinkEnumerator& aLink)
     665             : {
     666           0 :   for ( ; !aLink.AtEnd(); aLink.Next()) {
     667           0 :     if (!aLink.NextFrame()->IsInlineOutside()) {
     668             :       return;
     669             :     }
     670             :   }
     671             : }
     672             : 
     673             : // This function returns a frame link enumerator pointing to the first link in
     674             : // the list for which the next frame is not block.  If there is no such link,
     675             : // it points to the end of the list.
     676             : static nsFrameList::FrameLinkEnumerator
     677           0 : FindFirstNonBlock(const nsFrameList& aList)
     678             : {
     679           0 :   nsFrameList::FrameLinkEnumerator link(aList);
     680           0 :   for (; !link.AtEnd(); link.Next()) {
     681           0 :     if (link.NextFrame()->IsInlineOutside()) {
     682             :       break;
     683             :     }
     684             :   }
     685           0 :   return link;
     686             : }
     687             : 
     688             : inline void
     689           0 : SetInitialSingleChild(nsContainerFrame* aParent, nsIFrame* aFrame)
     690             : {
     691           0 :   MOZ_ASSERT(!aFrame->GetNextSibling(), "Should be using a frame list");
     692           0 :   nsFrameList temp(aFrame, aFrame);
     693           0 :   aParent->SetInitialChildList(kPrincipalList, temp);
     694           0 : }
     695             : 
     696             : // -----------------------------------------------------------
     697             : 
     698             : // Structure used when constructing formatting object trees.
     699           0 : struct nsFrameItems : public nsFrameList
     700             : {
     701             :   // Appends the frame to the end of the list
     702             :   void AddChild(nsIFrame* aChild);
     703             : };
     704             : 
     705             : void
     706           0 : nsFrameItems::AddChild(nsIFrame* aChild)
     707             : {
     708           0 :   MOZ_ASSERT(aChild, "nsFrameItems::AddChild");
     709             : 
     710             :   // It'd be really nice if we could just AppendFrames(kPrincipalList, aChild) here,
     711             :   // but some of our callers put frames that have different
     712             :   // parents (caption, I'm looking at you) on the same framelist, and
     713             :   // nsFrameList asserts if you try to do that.
     714           0 :   if (IsEmpty()) {
     715           0 :     SetFrames(aChild);
     716             :   }
     717             :   else {
     718           0 :     NS_ASSERTION(aChild != mLastChild,
     719             :                  "Same frame being added to frame list twice?");
     720           0 :     mLastChild->SetNextSibling(aChild);
     721           0 :     mLastChild = nsLayoutUtils::GetLastSibling(aChild);
     722             :   }
     723           0 : }
     724             : 
     725             : // -----------------------------------------------------------
     726             : 
     727             : // Structure used when constructing formatting object trees. Contains
     728             : // state information needed for absolutely positioned elements
     729             : struct nsAbsoluteItems : nsFrameItems {
     730             :   // containing block for absolutely positioned elements
     731             :   nsContainerFrame* containingBlock;
     732             : 
     733             :   explicit nsAbsoluteItems(nsContainerFrame* aContainingBlock);
     734             : #ifdef DEBUG
     735             :   // XXXbz Does this need a debug-only assignment operator that nulls out the
     736             :   // childList in the nsAbsoluteItems we're copying?  Introducing a difference
     737             :   // between debug and non-debug behavior seems bad, so I guess not...
     738           0 :   ~nsAbsoluteItems() {
     739           0 :     NS_ASSERTION(!FirstChild(),
     740             :                  "Dangling child list.  Someone forgot to insert it?");
     741           0 :   }
     742             : #endif
     743             : 
     744             :   // Appends the frame to the end of the list
     745             :   void AddChild(nsIFrame* aChild);
     746             : };
     747             : 
     748           0 : nsAbsoluteItems::nsAbsoluteItems(nsContainerFrame* aContainingBlock)
     749           0 :   : containingBlock(aContainingBlock)
     750             : {
     751           0 : }
     752             : 
     753             : // Additional behavior is that it sets the frame's NS_FRAME_OUT_OF_FLOW flag
     754             : void
     755           0 : nsAbsoluteItems::AddChild(nsIFrame* aChild)
     756             : {
     757           0 :   aChild->AddStateBits(NS_FRAME_OUT_OF_FLOW);
     758           0 :   NS_ASSERTION(aChild->GetPlaceholderFrame(),
     759             :                "Child without placeholder being added to nsAbsoluteItems?");
     760           0 :   nsFrameItems::AddChild(aChild);
     761           0 : }
     762             : 
     763             : // -----------------------------------------------------------
     764             : 
     765             : // Structure for saving the existing state when pushing/poping containing
     766             : // blocks. The destructor restores the state to its previous state
     767             : class MOZ_STACK_CLASS nsFrameConstructorSaveState {
     768             : public:
     769             :   typedef nsIFrame::ChildListID ChildListID;
     770             :   nsFrameConstructorSaveState();
     771             :   ~nsFrameConstructorSaveState();
     772             : 
     773             : private:
     774             :   nsAbsoluteItems* mItems;      // pointer to struct whose data we save/restore
     775             :   nsAbsoluteItems  mSavedItems; // copy of original data
     776             : 
     777             :   // The name of the child list in which our frames would belong
     778             :   ChildListID mChildListID;
     779             :   nsFrameConstructorState* mState;
     780             : 
     781             :   // State used only when we're saving the abs-pos state for a transformed
     782             :   // element.
     783             :   nsAbsoluteItems mSavedFixedItems;
     784             : 
     785             :   bool mSavedFixedPosIsAbsPos;
     786             : 
     787             :   friend class nsFrameConstructorState;
     788             : };
     789             : 
     790             : // Structure used to keep track of a list of bindings we need to call
     791             : // AddToAttachedQueue on.  These should be in post-order depth-first
     792             : // flattened tree traversal order.
     793             : struct PendingBinding : public LinkedListElement<PendingBinding>
     794             : {
     795             : #ifdef NS_BUILD_REFCNT_LOGGING
     796           0 :   PendingBinding() {
     797           0 :     MOZ_COUNT_CTOR(PendingBinding);
     798           0 :   }
     799           0 :   ~PendingBinding() {
     800           0 :     MOZ_COUNT_DTOR(PendingBinding);
     801           0 :   }
     802             : #endif
     803             : 
     804             :   RefPtr<nsXBLBinding> mBinding;
     805             : };
     806             : 
     807             : // Structure used for maintaining state information during the
     808             : // frame construction process
     809             : class MOZ_STACK_CLASS nsFrameConstructorState {
     810             : public:
     811             :   typedef nsIFrame::ChildListID ChildListID;
     812             : 
     813             :   nsPresContext            *mPresContext;
     814             :   nsIPresShell             *mPresShell;
     815             :   nsFrameManager           *mFrameManager;
     816             : 
     817             : #ifdef MOZ_XUL
     818             :   // Frames destined for the kPopupList.
     819             :   nsAbsoluteItems           mPopupItems;
     820             : #endif
     821             : 
     822             :   // Containing block information for out-of-flow frames.
     823             :   nsAbsoluteItems           mFixedItems;
     824             :   nsAbsoluteItems           mAbsoluteItems;
     825             :   nsAbsoluteItems           mFloatedItems;
     826             :   // The containing block of a frame in the top layer is defined by the
     827             :   // spec: fixed-positioned frames are children of the viewport frame,
     828             :   // and absolutely-positioned frames are children of the initial
     829             :   // containing block. They would not be caught by any other containing
     830             :   // block, e.g. frames with transform or filter.
     831             :   nsAbsoluteItems           mTopLayerFixedItems;
     832             :   nsAbsoluteItems           mTopLayerAbsoluteItems;
     833             : 
     834             :   nsCOMPtr<nsILayoutHistoryState> mFrameState;
     835             :   // These bits will be added to the state bits of any frame we construct
     836             :   // using this state.
     837             :   nsFrameState              mAdditionalStateBits;
     838             : 
     839             :   // When working with the transform and filter properties, we want to hook
     840             :   // the abs-pos and fixed-pos lists together, since such
     841             :   // elements are fixed-pos containing blocks.  This flag determines
     842             :   // whether or not we want to wire the fixed-pos and abs-pos lists
     843             :   // together.
     844             :   bool                      mFixedPosIsAbsPos;
     845             : 
     846             :   // A boolean to indicate whether we have a "pending" popupgroup.  That is, we
     847             :   // have already created the FrameConstructionItem for the root popupgroup but
     848             :   // we have not yet created the relevant frame.
     849             :   bool                      mHavePendingPopupgroup;
     850             : 
     851             :   // If false (which is the default) then call SetPrimaryFrame() as needed
     852             :   // during frame construction.  If true, don't make any SetPrimaryFrame()
     853             :   // calls, except for generated content which doesn't have a primary frame
     854             :   // yet.  The mCreatingExtraFrames == true mode is meant to be used for
     855             :   // construction of random "extra" frames for elements via normal frame
     856             :   // construction APIs (e.g. replication of things across pages in paginated
     857             :   // mode).
     858             :   bool                      mCreatingExtraFrames;
     859             : 
     860             :   nsCOMArray<nsIContent>    mGeneratedTextNodesWithInitializer;
     861             : 
     862             :   // Constructor
     863             :   // Use the passed-in history state.
     864             :   nsFrameConstructorState(
     865             :     nsIPresShell* aPresShell,
     866             :     nsContainerFrame* aFixedContainingBlock,
     867             :     nsContainerFrame* aAbsoluteContainingBlock,
     868             :     nsContainerFrame* aFloatContainingBlock,
     869             :     already_AddRefed<nsILayoutHistoryState> aHistoryState);
     870             :   // Get the history state from the pres context's pres shell.
     871             :   nsFrameConstructorState(nsIPresShell* aPresShell,
     872             :                           nsContainerFrame* aFixedContainingBlock,
     873             :                           nsContainerFrame* aAbsoluteContainingBlock,
     874             :                           nsContainerFrame* aFloatContainingBlock);
     875             : 
     876             :   ~nsFrameConstructorState();
     877             : 
     878             :   // Function to push the existing absolute containing block state and
     879             :   // create a new scope. Code that uses this function should get matching
     880             :   // logic in GetAbsoluteContainingBlock.
     881             :   // Also makes aNewAbsoluteContainingBlock the containing block for
     882             :   // fixed-pos elements if necessary.
     883             :   // aPositionedFrame is the frame whose style actually makes
     884             :   // aNewAbsoluteContainingBlock a containing block. E.g. for a scrollable element
     885             :   // aPositionedFrame is the element's primary frame and
     886             :   // aNewAbsoluteContainingBlock is the scrolled frame.
     887             :   void PushAbsoluteContainingBlock(nsContainerFrame* aNewAbsoluteContainingBlock,
     888             :                                    nsIFrame* aPositionedFrame,
     889             :                                    nsFrameConstructorSaveState& aSaveState);
     890             : 
     891             :   // Function to push the existing float containing block state and
     892             :   // create a new scope. Code that uses this function should get matching
     893             :   // logic in GetFloatContainingBlock.
     894             :   // Pushing a null float containing block forbids any frames from being
     895             :   // floated until a new float containing block is pushed.
     896             :   // XXX we should get rid of null float containing blocks and teach the
     897             :   // various frame classes to deal with floats instead.
     898             :   void PushFloatContainingBlock(nsContainerFrame* aNewFloatContainingBlock,
     899             :                                 nsFrameConstructorSaveState& aSaveState);
     900             : 
     901             :   // Function to return the proper geometric parent for a frame with display
     902             :   // struct given by aStyleDisplay and parent's frame given by
     903             :   // aContentParentFrame.
     904             :   nsContainerFrame* GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
     905             :                                        nsContainerFrame* aContentParentFrame) const;
     906             : 
     907             :   /**
     908             :    * Function to add a new frame to the right frame list.  This MUST be called
     909             :    * on frames before their children have been processed if the frames might
     910             :    * conceivably be out-of-flow; otherwise cleanup in error cases won't work
     911             :    * right.  Also, this MUST be called on frames after they have been
     912             :    * initialized.
     913             :    * @param aNewFrame the frame to add
     914             :    * @param aFrameItems the list to add in-flow frames to
     915             :    * @param aContent the content pointer for aNewFrame
     916             :    * @param aParentFrame the parent frame for the content if it were in-flow
     917             :    * @param aCanBePositioned pass false if the frame isn't allowed to be
     918             :    *        positioned
     919             :    * @param aCanBeFloated pass false if the frame isn't allowed to be
     920             :    *        floated
     921             :    * @param aIsOutOfFlowPopup pass true if the frame is an out-of-flow popup
     922             :    *        (XUL-only)
     923             :    */
     924             :   void AddChild(nsIFrame* aNewFrame,
     925             :                 nsFrameItems& aFrameItems,
     926             :                 nsIContent* aContent,
     927             :                 nsContainerFrame* aParentFrame,
     928             :                 bool aCanBePositioned = true,
     929             :                 bool aCanBeFloated = true,
     930             :                 bool aIsOutOfFlowPopup = false,
     931             :                 bool aInsertAfter = false,
     932             :                 nsIFrame* aInsertAfterFrame = nullptr);
     933             : 
     934             :   /**
     935             :    * Function to return the fixed-pos element list.  Normally this will just hand back the
     936             :    * fixed-pos element list, but in case we're dealing with a transformed element that's
     937             :    * acting as an abs-pos and fixed-pos container, we'll hand back the abs-pos list.  Callers should
     938             :    * use this function if they want to get the list acting as the fixed-pos item parent.
     939             :    */
     940             :   nsAbsoluteItems& GetFixedItems()
     941             :   {
     942           0 :     return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
     943             :   }
     944             :   const nsAbsoluteItems& GetFixedItems() const
     945             :   {
     946           0 :     return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
     947             :   }
     948             : 
     949             : 
     950             :   /**
     951             :    * class to automatically push and pop a pending binding in the frame
     952             :    * constructor state.  See nsCSSFrameConstructor::FrameConstructionItem
     953             :    * mPendingBinding documentation.
     954             :    */
     955             :   class PendingBindingAutoPusher;
     956             :   friend class PendingBindingAutoPusher;
     957             :   class MOZ_STACK_CLASS PendingBindingAutoPusher {
     958             :   public:
     959             :     PendingBindingAutoPusher(nsFrameConstructorState& aState,
     960             :                              PendingBinding* aPendingBinding) :
     961             :       mState(aState),
     962           0 :       mPendingBinding(aState.mCurrentPendingBindingInsertionPoint)
     963             :         {
     964           0 :           if (aPendingBinding) {
     965           0 :             aState.mCurrentPendingBindingInsertionPoint = aPendingBinding;
     966             :           }
     967             :         }
     968             : 
     969             :     ~PendingBindingAutoPusher()
     970             :       {
     971           0 :         mState.mCurrentPendingBindingInsertionPoint = mPendingBinding;
     972             :       }
     973             : 
     974             :   private:
     975             :     nsFrameConstructorState& mState;
     976             :     PendingBinding* mPendingBinding;
     977             :   };
     978             : 
     979             :   /**
     980             :    * Add a new pending binding to the list
     981             :    */
     982           0 :   void AddPendingBinding(PendingBinding* aPendingBinding) {
     983           0 :     if (mCurrentPendingBindingInsertionPoint) {
     984           0 :       mCurrentPendingBindingInsertionPoint->setPrevious(aPendingBinding);
     985             :     } else {
     986           0 :       mPendingBindings.insertBack(aPendingBinding);
     987             :     }
     988           0 :   }
     989             : 
     990             : protected:
     991             :   friend class nsFrameConstructorSaveState;
     992             : 
     993             :   /**
     994             :    * ProcessFrameInsertions takes the frames in aFrameItems and adds them as
     995             :    * kids to the aChildListID child list of |aFrameItems.containingBlock|.
     996             :    */
     997             :   void ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
     998             :                               ChildListID aChildListID);
     999             : 
    1000             :   /**
    1001             :    * GetOutOfFlowFrameItems selects the out-of-flow frame list the new
    1002             :    * frame should be added to. If the frame shouldn't be added to any
    1003             :    * out-of-flow list, it returns nullptr. The corresponding type of
    1004             :    * placeholder is also returned via the aPlaceholderType parameter
    1005             :    * if this method doesn't return nullptr. The caller should check
    1006             :    * whether the returned list really has a containing block.
    1007             :    */
    1008             :   nsAbsoluteItems* GetOutOfFlowFrameItems(nsIFrame* aNewFrame,
    1009             :                                           bool aCanBePositioned,
    1010             :                                           bool aCanBeFloated,
    1011             :                                           bool aIsOutOfFlowPopup,
    1012             :                                           nsFrameState* aPlaceholderType);
    1013             : 
    1014             :   void ConstructBackdropFrameFor(nsIContent* aContent, nsIFrame* aFrame);
    1015             : 
    1016             :   // Our list of all pending bindings.  When we're done, we need to call
    1017             :   // AddToAttachedQueue on all of them, in order.
    1018             :   LinkedList<PendingBinding> mPendingBindings;
    1019             : 
    1020             :   PendingBinding* mCurrentPendingBindingInsertionPoint;
    1021             : };
    1022             : 
    1023           0 : nsFrameConstructorState::nsFrameConstructorState(
    1024             :   nsIPresShell* aPresShell,
    1025             :   nsContainerFrame* aFixedContainingBlock,
    1026             :   nsContainerFrame* aAbsoluteContainingBlock,
    1027             :   nsContainerFrame* aFloatContainingBlock,
    1028           0 :   already_AddRefed<nsILayoutHistoryState> aHistoryState)
    1029           0 :   : mPresContext(aPresShell->GetPresContext()),
    1030             :     mPresShell(aPresShell),
    1031           0 :     mFrameManager(aPresShell->FrameConstructor()),
    1032             : #ifdef MOZ_XUL
    1033             :     mPopupItems(nullptr),
    1034             : #endif
    1035             :     mFixedItems(aFixedContainingBlock),
    1036             :     mAbsoluteItems(aAbsoluteContainingBlock),
    1037             :     mFloatedItems(aFloatContainingBlock),
    1038             :     mTopLayerFixedItems(
    1039           0 :       static_cast<nsContainerFrame*>(mFrameManager->GetRootFrame())),
    1040             :     mTopLayerAbsoluteItems(
    1041             :       aPresShell->FrameConstructor()->GetDocElementContainingBlock()),
    1042             :     // See PushAbsoluteContaningBlock below
    1043             :     mFrameState(aHistoryState),
    1044             :     mAdditionalStateBits(nsFrameState(0)),
    1045             :     // If the fixed-pos containing block is equal to the abs-pos containing
    1046             :     // block, use the abs-pos containing block's abs-pos list for fixed-pos
    1047             :     // frames.
    1048           0 :     mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
    1049             :     mHavePendingPopupgroup(false),
    1050             :     mCreatingExtraFrames(false),
    1051           0 :     mCurrentPendingBindingInsertionPoint(nullptr)
    1052             : {
    1053             : #ifdef MOZ_XUL
    1054           0 :   nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
    1055           0 :   if (rootBox) {
    1056           0 :     mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
    1057             :   }
    1058             : #endif
    1059           0 :   MOZ_COUNT_CTOR(nsFrameConstructorState);
    1060           0 : }
    1061             : 
    1062           0 : nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
    1063             :                                                  nsContainerFrame* aFixedContainingBlock,
    1064             :                                                  nsContainerFrame* aAbsoluteContainingBlock,
    1065           0 :                                                  nsContainerFrame* aFloatContainingBlock)
    1066             :   : nsFrameConstructorState(aPresShell,
    1067             :                             aFixedContainingBlock,
    1068             :                             aAbsoluteContainingBlock,
    1069             :                             aFloatContainingBlock,
    1070           0 :                             aPresShell->GetDocument()->GetLayoutHistoryState())
    1071             : {
    1072           0 : }
    1073             : 
    1074           0 : nsFrameConstructorState::~nsFrameConstructorState()
    1075             : {
    1076           0 :   MOZ_COUNT_DTOR(nsFrameConstructorState);
    1077           0 :   ProcessFrameInsertions(mTopLayerFixedItems, nsIFrame::kFixedList);
    1078           0 :   ProcessFrameInsertions(mTopLayerAbsoluteItems, nsIFrame::kAbsoluteList);
    1079           0 :   ProcessFrameInsertions(mFloatedItems, nsIFrame::kFloatList);
    1080           0 :   ProcessFrameInsertions(mAbsoluteItems, nsIFrame::kAbsoluteList);
    1081           0 :   ProcessFrameInsertions(mFixedItems, nsIFrame::kFixedList);
    1082             : #ifdef MOZ_XUL
    1083           0 :   ProcessFrameInsertions(mPopupItems, nsIFrame::kPopupList);
    1084             : #endif
    1085           0 :   for (int32_t i = mGeneratedTextNodesWithInitializer.Count() - 1; i >= 0; --i) {
    1086           0 :     mGeneratedTextNodesWithInitializer[i]->
    1087           0 :       DeleteProperty(nsGkAtoms::genConInitializerProperty);
    1088             :   }
    1089           0 :   if (!mPendingBindings.isEmpty()) {
    1090           0 :     nsBindingManager* bindingManager = mPresShell->GetDocument()->BindingManager();
    1091           0 :     do {
    1092           0 :       nsAutoPtr<PendingBinding> pendingBinding;
    1093           0 :       pendingBinding = mPendingBindings.popFirst();
    1094           0 :       bindingManager->AddToAttachedQueue(pendingBinding->mBinding);
    1095           0 :     } while (!mPendingBindings.isEmpty());
    1096           0 :     mCurrentPendingBindingInsertionPoint = nullptr;
    1097             :   }
    1098           0 : }
    1099             : 
    1100             : static nsContainerFrame*
    1101           0 : AdjustAbsoluteContainingBlock(nsContainerFrame* aContainingBlockIn)
    1102             : {
    1103           0 :   if (!aContainingBlockIn) {
    1104             :     return nullptr;
    1105             :   }
    1106             : 
    1107             :   // Always use the container's first continuation. (Inline frames can have
    1108             :   // non-fluid bidi continuations...)
    1109           0 :   return static_cast<nsContainerFrame*>(aContainingBlockIn->FirstContinuation());
    1110             : }
    1111             : 
    1112             : void
    1113           0 : nsFrameConstructorState::PushAbsoluteContainingBlock(nsContainerFrame* aNewAbsoluteContainingBlock,
    1114             :                                                      nsIFrame* aPositionedFrame,
    1115             :                                                      nsFrameConstructorSaveState& aSaveState)
    1116             : {
    1117           0 :   aSaveState.mItems = &mAbsoluteItems;
    1118           0 :   aSaveState.mSavedItems = mAbsoluteItems;
    1119           0 :   aSaveState.mChildListID = nsIFrame::kAbsoluteList;
    1120           0 :   aSaveState.mState = this;
    1121           0 :   aSaveState.mSavedFixedPosIsAbsPos = mFixedPosIsAbsPos;
    1122             : 
    1123           0 :   if (mFixedPosIsAbsPos) {
    1124             :     // Since we're going to replace mAbsoluteItems, we need to save it into
    1125             :     // mFixedItems now (and save the current value of mFixedItems).
    1126           0 :     aSaveState.mSavedFixedItems = mFixedItems;
    1127           0 :     mFixedItems = mAbsoluteItems;
    1128             :   }
    1129             : 
    1130           0 :   mAbsoluteItems =
    1131           0 :     nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock));
    1132             : 
    1133             :   /* See if we're wiring the fixed-pos and abs-pos lists together.  This happens iff
    1134             :    * we're a transformed element.
    1135             :    */
    1136           0 :   mFixedPosIsAbsPos = aPositionedFrame &&
    1137           0 :       aPositionedFrame->IsFixedPosContainingBlock();
    1138             : 
    1139           0 :   if (aNewAbsoluteContainingBlock) {
    1140           0 :     aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
    1141             :   }
    1142           0 : }
    1143             : 
    1144             : void
    1145           0 : nsFrameConstructorState::PushFloatContainingBlock(nsContainerFrame* aNewFloatContainingBlock,
    1146             :                                                   nsFrameConstructorSaveState& aSaveState)
    1147             : {
    1148           0 :   MOZ_ASSERT(!aNewFloatContainingBlock ||
    1149             :              aNewFloatContainingBlock->IsFloatContainingBlock(),
    1150             :              "Please push a real float containing block!");
    1151           0 :   NS_ASSERTION(!aNewFloatContainingBlock ||
    1152             :                !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock),
    1153             :                "We should not push a frame that is supposed to _suppress_ "
    1154             :                "floats as a float containing block!");
    1155           0 :   aSaveState.mItems = &mFloatedItems;
    1156           0 :   aSaveState.mSavedItems = mFloatedItems;
    1157           0 :   aSaveState.mChildListID = nsIFrame::kFloatList;
    1158           0 :   aSaveState.mState = this;
    1159           0 :   mFloatedItems = nsAbsoluteItems(aNewFloatContainingBlock);
    1160           0 : }
    1161             : 
    1162             : nsContainerFrame*
    1163           0 : nsFrameConstructorState::GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
    1164             :                                             nsContainerFrame* aContentParentFrame) const
    1165             : {
    1166           0 :   MOZ_ASSERT(aStyleDisplay, "Must have display struct!");
    1167             : 
    1168             :   // If there is no container for a fixed, absolute, or floating root
    1169             :   // frame, we will ignore the positioning.  This hack is originally
    1170             :   // brought to you by the letter T: tables, since other roots don't
    1171             :   // even call into this code.  See bug 178855.
    1172             :   //
    1173             :   // XXX Disabling positioning in this case is a hack.  If one was so inclined,
    1174             :   // one could support this either by (1) inserting a dummy block between the
    1175             :   // table and the canvas or (2) teaching the canvas how to reflow positioned
    1176             :   // elements. (1) has the usual problems when multiple frames share the same
    1177             :   // content (notice all the special cases in this file dealing with inner
    1178             :   // tables and table wrappers which share the same content). (2) requires some
    1179             :   // work and possible factoring.
    1180             :   //
    1181             :   // XXXbz couldn't we just force position to "static" on roots and
    1182             :   // float to "none"?  That's OK per CSS 2.1, as far as I can tell.
    1183             : 
    1184           0 :   if (aContentParentFrame &&
    1185           0 :       nsSVGUtils::IsInSVGTextSubtree(aContentParentFrame)) {
    1186             :     return aContentParentFrame;
    1187             :   }
    1188             : 
    1189           0 :   if (aStyleDisplay->IsFloatingStyle() && mFloatedItems.containingBlock) {
    1190           0 :     NS_ASSERTION(!aStyleDisplay->IsAbsolutelyPositionedStyle(),
    1191             :                  "Absolutely positioned _and_ floating?");
    1192           0 :     return mFloatedItems.containingBlock;
    1193             :   }
    1194             : 
    1195           0 :   if (aStyleDisplay->mTopLayer != NS_STYLE_TOP_LAYER_NONE) {
    1196           0 :     MOZ_ASSERT(aStyleDisplay->mTopLayer == NS_STYLE_TOP_LAYER_TOP,
    1197             :                "-moz-top-layer should be either none or top");
    1198           0 :     MOZ_ASSERT(aStyleDisplay->IsAbsolutelyPositionedStyle(),
    1199             :                "Top layer items should always be absolutely positioned");
    1200           0 :     if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED) {
    1201           0 :       MOZ_ASSERT(mTopLayerFixedItems.containingBlock, "No root frame?");
    1202             :       return mTopLayerFixedItems.containingBlock;
    1203             :     }
    1204           0 :     MOZ_ASSERT(aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE);
    1205           0 :     MOZ_ASSERT(mTopLayerAbsoluteItems.containingBlock);
    1206             :     return mTopLayerAbsoluteItems.containingBlock;
    1207             :   }
    1208             : 
    1209           0 :   if (aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
    1210           0 :       mAbsoluteItems.containingBlock) {
    1211             :     return mAbsoluteItems.containingBlock;
    1212             :   }
    1213             : 
    1214           0 :   if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
    1215           0 :       GetFixedItems().containingBlock) {
    1216           0 :     return GetFixedItems().containingBlock;
    1217             :   }
    1218             : 
    1219             :   return aContentParentFrame;
    1220             : }
    1221             : 
    1222             : nsAbsoluteItems*
    1223           0 : nsFrameConstructorState::GetOutOfFlowFrameItems(nsIFrame* aNewFrame,
    1224             :                                                 bool aCanBePositioned,
    1225             :                                                 bool aCanBeFloated,
    1226             :                                                 bool aIsOutOfFlowPopup,
    1227             :                                                 nsFrameState* aPlaceholderType)
    1228             : {
    1229             : #ifdef MOZ_XUL
    1230           0 :   if (MOZ_UNLIKELY(aIsOutOfFlowPopup)) {
    1231           0 :     MOZ_ASSERT(mPopupItems.containingBlock, "Must have a popup set frame!");
    1232           0 :     *aPlaceholderType = PLACEHOLDER_FOR_POPUP;
    1233           0 :     return &mPopupItems;
    1234             :   }
    1235             : #endif // MOZ_XUL
    1236           0 :   if (aCanBeFloated && aNewFrame->IsFloating()) {
    1237           0 :     *aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
    1238           0 :     return &mFloatedItems;
    1239             :   }
    1240             : 
    1241           0 :   if (aCanBePositioned) {
    1242           0 :     const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
    1243           0 :     if (disp->mTopLayer != NS_STYLE_TOP_LAYER_NONE) {
    1244           0 :       *aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
    1245           0 :       if (disp->mPosition == NS_STYLE_POSITION_FIXED) {
    1246           0 :         *aPlaceholderType |= PLACEHOLDER_FOR_FIXEDPOS;
    1247           0 :         return &mTopLayerFixedItems;
    1248             :       }
    1249           0 :       *aPlaceholderType |= PLACEHOLDER_FOR_ABSPOS;
    1250           0 :       return &mTopLayerAbsoluteItems;
    1251             :     }
    1252           0 :     if (disp->mPosition == NS_STYLE_POSITION_ABSOLUTE) {
    1253           0 :       *aPlaceholderType = PLACEHOLDER_FOR_ABSPOS;
    1254           0 :       return &mAbsoluteItems;
    1255             :     }
    1256           0 :     if (disp->mPosition == NS_STYLE_POSITION_FIXED) {
    1257           0 :       *aPlaceholderType = PLACEHOLDER_FOR_FIXEDPOS;
    1258             :       return &GetFixedItems();
    1259             :     }
    1260             :   }
    1261             :   return nullptr;
    1262             : }
    1263             : 
    1264             : void
    1265           0 : nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
    1266             :                                                    nsIFrame* aFrame)
    1267             : {
    1268           0 :   MOZ_ASSERT(aFrame->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
    1269           0 :   nsContainerFrame* frame = do_QueryFrame(aFrame);
    1270           0 :   if (!frame) {
    1271           0 :     NS_WARNING("Cannot create backdrop frame for non-container frame");
    1272           0 :     return;
    1273             :   }
    1274             : 
    1275           0 :   RefPtr<ComputedStyle> style = mPresShell->StyleSet()->
    1276           0 :     ResolvePseudoElementStyle(aContent->AsElement(),
    1277             :                               CSSPseudoElementType::backdrop,
    1278             :                               /* aParentComputedStyle */ nullptr,
    1279           0 :                               /* aPseudoElement */ nullptr);
    1280           0 :   MOZ_ASSERT(style->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
    1281             :   nsContainerFrame* parentFrame =
    1282           0 :     GetGeometricParent(style->StyleDisplay(), nullptr);
    1283             : 
    1284           0 :   nsBackdropFrame* backdropFrame = new (mPresShell) nsBackdropFrame(style);
    1285           0 :   backdropFrame->Init(aContent, parentFrame, nullptr);
    1286             : 
    1287             :   nsFrameState placeholderType;
    1288             :   nsAbsoluteItems* frameItems = GetOutOfFlowFrameItems(backdropFrame,
    1289             :                                                        true, true, false,
    1290           0 :                                                        &placeholderType);
    1291           0 :   MOZ_ASSERT(placeholderType & PLACEHOLDER_FOR_TOPLAYER);
    1292             : 
    1293             :   nsIFrame* placeholder = nsCSSFrameConstructor::
    1294           0 :     CreatePlaceholderFrameFor(mPresShell, aContent, backdropFrame,
    1295           0 :                               frame, nullptr, placeholderType);
    1296           0 :   nsFrameList temp(placeholder, placeholder);
    1297           0 :   frame->SetInitialChildList(nsIFrame::kBackdropList, temp);
    1298             : 
    1299           0 :   frameItems->AddChild(backdropFrame);
    1300             : }
    1301             : 
    1302             : void
    1303           0 : nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
    1304             :                                   nsFrameItems& aFrameItems,
    1305             :                                   nsIContent* aContent,
    1306             :                                   nsContainerFrame* aParentFrame,
    1307             :                                   bool aCanBePositioned,
    1308             :                                   bool aCanBeFloated,
    1309             :                                   bool aIsOutOfFlowPopup,
    1310             :                                   bool aInsertAfter,
    1311             :                                   nsIFrame* aInsertAfterFrame)
    1312             : {
    1313           0 :   MOZ_ASSERT(!aNewFrame->GetNextSibling(), "Shouldn't happen");
    1314             : 
    1315             :   nsFrameState placeholderType;
    1316             :   nsAbsoluteItems* outOfFlowFrameItems =
    1317           0 :     GetOutOfFlowFrameItems(aNewFrame, aCanBePositioned, aCanBeFloated,
    1318           0 :                            aIsOutOfFlowPopup, &placeholderType);
    1319             : 
    1320             :   // The comments in GetGeometricParent regarding root table frames
    1321             :   // all apply here, unfortunately. Thus, we need to check whether
    1322             :   // the returned frame items really has containing block.
    1323             :   nsFrameItems* frameItems;
    1324           0 :   if (outOfFlowFrameItems && outOfFlowFrameItems->containingBlock) {
    1325           0 :     MOZ_ASSERT(aNewFrame->GetParent() == outOfFlowFrameItems->containingBlock,
    1326             :                "Parent of the frame is not the containing block?");
    1327             :     frameItems = outOfFlowFrameItems;
    1328             :   } else {
    1329           0 :     frameItems = &aFrameItems;
    1330           0 :     placeholderType = nsFrameState(0);
    1331             :   }
    1332             : 
    1333           0 :   if (placeholderType) {
    1334           0 :     NS_ASSERTION(frameItems != &aFrameItems,
    1335             :                  "Putting frame in-flow _and_ want a placeholder?");
    1336             :     nsIFrame* placeholderFrame =
    1337           0 :       nsCSSFrameConstructor::CreatePlaceholderFrameFor(mPresShell,
    1338             :                                                        aContent,
    1339             :                                                        aNewFrame,
    1340             :                                                        aParentFrame,
    1341             :                                                        nullptr,
    1342           0 :                                                        placeholderType);
    1343             : 
    1344           0 :     placeholderFrame->AddStateBits(mAdditionalStateBits);
    1345             :     // Add the placeholder frame to the flow
    1346           0 :     aFrameItems.AddChild(placeholderFrame);
    1347             : 
    1348           0 :     if (placeholderType & PLACEHOLDER_FOR_TOPLAYER) {
    1349           0 :       ConstructBackdropFrameFor(aContent, aNewFrame);
    1350             :     }
    1351             :   }
    1352             : #ifdef DEBUG
    1353             :   else {
    1354           0 :     NS_ASSERTION(aNewFrame->GetParent() == aParentFrame,
    1355             :                  "In-flow frame has wrong parent");
    1356             :   }
    1357             : #endif
    1358             : 
    1359           0 :   if (aInsertAfter) {
    1360           0 :     frameItems->InsertFrame(nullptr, aInsertAfterFrame, aNewFrame);
    1361             :   } else {
    1362           0 :     frameItems->AddChild(aNewFrame);
    1363             :   }
    1364           0 : }
    1365             : 
    1366             : void
    1367           0 : nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
    1368             :                                                 ChildListID aChildListID)
    1369             : {
    1370             : #define NS_NONXUL_LIST_TEST (&aFrameItems == &mFloatedItems &&            \
    1371             :                              aChildListID == nsIFrame::kFloatList)    ||  \
    1372             :                             ((&aFrameItems == &mAbsoluteItems ||          \
    1373             :                               &aFrameItems == &mTopLayerAbsoluteItems) && \
    1374             :                              aChildListID == nsIFrame::kAbsoluteList) ||  \
    1375             :                             ((&aFrameItems == &mFixedItems ||             \
    1376             :                               &aFrameItems == &mTopLayerFixedItems) &&    \
    1377             :                              aChildListID == nsIFrame::kFixedList)
    1378             : #ifdef MOZ_XUL
    1379           0 :   MOZ_ASSERT(NS_NONXUL_LIST_TEST ||
    1380             :              (&aFrameItems == &mPopupItems &&
    1381             :               aChildListID == nsIFrame::kPopupList),
    1382             :              "Unexpected aFrameItems/aChildListID combination");
    1383             : #else
    1384             :   MOZ_ASSERT(NS_NONXUL_LIST_TEST,
    1385             :              "Unexpected aFrameItems/aChildListID combination");
    1386             : #endif
    1387             : 
    1388           0 :   if (aFrameItems.IsEmpty()) {
    1389             :     return;
    1390             :   }
    1391             : 
    1392           0 :   nsContainerFrame* containingBlock = aFrameItems.containingBlock;
    1393             : 
    1394           0 :   NS_ASSERTION(containingBlock,
    1395             :                "Child list without containing block?");
    1396             : 
    1397           0 :   if (aChildListID == nsIFrame::kFixedList) {
    1398             :     // Put this frame on the transformed-frame's abs-pos list instead, if
    1399             :     // it has abs-pos children instead of fixed-pos children.
    1400           0 :     aChildListID = containingBlock->GetAbsoluteListID();
    1401             :   }
    1402             : 
    1403             :   // Insert the frames hanging out in aItems.  We can use SetInitialChildList()
    1404             :   // if the containing block hasn't been reflowed yet (so NS_FRAME_FIRST_REFLOW
    1405             :   // is set) and doesn't have any frames in the aChildListID child list yet.
    1406           0 :   const nsFrameList& childList = containingBlock->GetChildList(aChildListID);
    1407           0 :   if (childList.IsEmpty() &&
    1408           0 :       (containingBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    1409             :     // If we're injecting absolutely positioned frames, inject them on the
    1410             :     // absolute containing block
    1411           0 :     if (aChildListID == containingBlock->GetAbsoluteListID()) {
    1412             :       containingBlock->GetAbsoluteContainingBlock()->
    1413           0 :         SetInitialChildList(containingBlock, aChildListID, aFrameItems);
    1414             :     } else {
    1415           0 :       containingBlock->SetInitialChildList(aChildListID, aFrameItems);
    1416             :     }
    1417           0 :   } else if (aChildListID == nsIFrame::kFixedList ||
    1418           0 :              aChildListID == nsIFrame::kAbsoluteList) {
    1419             :     // The order is not important for abs-pos/fixed-pos frame list, just
    1420             :     // append the frame items to the list directly.
    1421           0 :     mFrameManager->AppendFrames(containingBlock, aChildListID, aFrameItems);
    1422             :   } else {
    1423             :     // Note that whether the frame construction context is doing an append or
    1424             :     // not is not helpful here, since it could be appending to some frame in
    1425             :     // the middle of the document, which means we're not necessarily
    1426             :     // appending to the children of the containing block.
    1427             :     //
    1428             :     // We need to make sure the 'append to the end of document' case is fast.
    1429             :     // So first test the last child of the containing block
    1430           0 :     nsIFrame* lastChild = childList.LastChild();
    1431             : 
    1432             :     // CompareTreePosition uses placeholder hierarchy for out of flow frames,
    1433             :     // so this will make out-of-flows respect the ordering of placeholders,
    1434             :     // which is great because it takes care of anonymous content.
    1435           0 :     nsIFrame* firstNewFrame = aFrameItems.FirstChild();
    1436             : 
    1437             :     // Cache the ancestor chain so that we can reuse it if needed.
    1438           0 :     AutoTArray<nsIFrame*, 20> firstNewFrameAncestors;
    1439           0 :     nsIFrame* notCommonAncestor = nullptr;
    1440           0 :     if (lastChild) {
    1441             :       notCommonAncestor = nsLayoutUtils::FillAncestors(firstNewFrame,
    1442             :                                                        containingBlock,
    1443           0 :                                                        &firstNewFrameAncestors);
    1444             :     }
    1445             : 
    1446           0 :     if (!lastChild ||
    1447           0 :         nsLayoutUtils::CompareTreePosition(lastChild, firstNewFrame,
    1448             :                                            firstNewFrameAncestors,
    1449             :                                            notCommonAncestor ?
    1450             :                                              containingBlock : nullptr) < 0) {
    1451             :       // no lastChild, or lastChild comes before the new children, so just append
    1452           0 :       mFrameManager->AppendFrames(containingBlock, aChildListID, aFrameItems);
    1453             :     } else {
    1454             :       // Try the other children. First collect them to an array so that a
    1455             :       // reasonable fast binary search can be used to find the insertion point.
    1456           0 :       AutoTArray<nsIFrame*, 128> children;
    1457           0 :       for (nsIFrame* f = childList.FirstChild(); f != lastChild;
    1458           0 :            f = f->GetNextSibling()) {
    1459           0 :         children.AppendElement(f);
    1460             :       }
    1461             : 
    1462           0 :       nsIFrame* insertionPoint = nullptr;
    1463           0 :       int32_t imin = 0;
    1464           0 :       int32_t max = children.Length();
    1465           0 :       while (max > imin) {
    1466           0 :         int32_t imid = imin + ((max - imin) / 2);
    1467           0 :         nsIFrame* f = children[imid];
    1468             :         int32_t compare =
    1469           0 :           nsLayoutUtils::CompareTreePosition(f, firstNewFrame, firstNewFrameAncestors,
    1470           0 :                                              notCommonAncestor ? containingBlock : nullptr);
    1471           0 :         if (compare > 0) {
    1472             :           // f is after the new frame.
    1473           0 :           max = imid;
    1474           0 :           insertionPoint = imid > 0 ? children[imid - 1] : nullptr;
    1475           0 :         } else if (compare < 0) {
    1476             :           // f is before the new frame.
    1477           0 :           imin = imid + 1;
    1478           0 :           insertionPoint = f;
    1479             :         } else {
    1480             :           // This is for the old behavior. Should be removed once it is
    1481             :           // guaranteed that CompareTreePosition can't return 0!
    1482             :           // See bug 928645.
    1483           0 :           NS_WARNING("Something odd happening???");
    1484           0 :           insertionPoint = nullptr;
    1485           0 :           for (uint32_t i = 0; i < children.Length(); ++i) {
    1486           0 :             nsIFrame* f = children[i];
    1487           0 :             if (nsLayoutUtils::CompareTreePosition(f, firstNewFrame,
    1488             :                                                    firstNewFrameAncestors,
    1489             :                                                    notCommonAncestor ?
    1490             :                                                      containingBlock : nullptr) > 0) {
    1491             :               break;
    1492             :             }
    1493           0 :             insertionPoint = f;
    1494             :           }
    1495             :           break;
    1496             :         }
    1497             :       }
    1498           0 :       mFrameManager->InsertFrames(containingBlock, aChildListID,
    1499           0 :                                   insertionPoint, aFrameItems);
    1500             :     }
    1501             :   }
    1502             : 
    1503           0 :   MOZ_ASSERT(aFrameItems.IsEmpty(), "How did that happen?");
    1504             : }
    1505             : 
    1506             : 
    1507           0 : nsFrameConstructorSaveState::nsFrameConstructorSaveState()
    1508             :   : mItems(nullptr),
    1509             :     mSavedItems(nullptr),
    1510             :     mChildListID(kPrincipalList),
    1511             :     mState(nullptr),
    1512             :     mSavedFixedItems(nullptr),
    1513           0 :     mSavedFixedPosIsAbsPos(false)
    1514             : {
    1515           0 : }
    1516             : 
    1517           0 : nsFrameConstructorSaveState::~nsFrameConstructorSaveState()
    1518             : {
    1519             :   // Restore the state
    1520           0 :   if (mItems) {
    1521           0 :     NS_ASSERTION(mState, "Can't have mItems set without having a state!");
    1522           0 :     mState->ProcessFrameInsertions(*mItems, mChildListID);
    1523           0 :     *mItems = mSavedItems;
    1524             : #ifdef DEBUG
    1525             :     // We've transferred the child list, so drop the pointer we held to it.
    1526             :     // Note that this only matters for the assert in ~nsAbsoluteItems.
    1527           0 :     mSavedItems.Clear();
    1528             : #endif
    1529           0 :     if (mItems == &mState->mAbsoluteItems) {
    1530           0 :       mState->mFixedPosIsAbsPos = mSavedFixedPosIsAbsPos;
    1531           0 :       if (mSavedFixedPosIsAbsPos) {
    1532             :         // mAbsoluteItems was moved to mFixedItems, so move mFixedItems back
    1533             :         // and repair the old mFixedItems now.
    1534           0 :         mState->mAbsoluteItems = mState->mFixedItems;
    1535           0 :         mState->mFixedItems = mSavedFixedItems;
    1536             : #ifdef DEBUG
    1537           0 :         mSavedFixedItems.Clear();
    1538             : #endif
    1539             :       }
    1540             :     }
    1541           0 :     NS_ASSERTION(!mItems->LastChild() || !mItems->LastChild()->GetNextSibling(),
    1542             :                  "Something corrupted our list");
    1543             :   }
    1544           0 : }
    1545             : 
    1546             : /**
    1547             :  * Moves aFrameList from aOldParent to aNewParent.  This updates the parent
    1548             :  * pointer of the frames in the list, and reparents their views as needed.
    1549             :  * nsFrame::SetParent sets the NS_FRAME_HAS_VIEW bit on aNewParent and its
    1550             :  * ancestors as needed. Then it sets the list as the initial child list
    1551             :  * on aNewParent, unless aNewParent either already has kids or has been
    1552             :  * reflowed; in that case it appends the new frames.  Note that this
    1553             :  * method differs from ReparentFrames in that it doesn't change the kids'
    1554             :  * style.
    1555             :  */
    1556             : // XXXbz Since this is only used for {ib} splits, could we just copy the view
    1557             : // bits from aOldParent to aNewParent and then use the
    1558             : // nsFrameList::ApplySetParent?  That would still leave us doing two passes
    1559             : // over the list, of course; if we really wanted to we could factor out the
    1560             : // relevant part of ReparentFrameViewList, I suppose...  Or just get rid of
    1561             : // views, which would make most of this function go away.
    1562             : static void
    1563           0 : MoveChildrenTo(nsIFrame* aOldParent,
    1564             :                nsContainerFrame* aNewParent,
    1565             :                nsFrameList& aFrameList)
    1566             : {
    1567           0 :   bool sameGrandParent = aOldParent->GetParent() == aNewParent->GetParent();
    1568             : 
    1569           0 :   if (aNewParent->HasView() || aOldParent->HasView() || !sameGrandParent) {
    1570             :     // Move the frames into the new view
    1571           0 :     nsContainerFrame::ReparentFrameViewList(aFrameList, aOldParent, aNewParent);
    1572             :   }
    1573             : 
    1574           0 :   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
    1575           0 :     e.get()->SetParent(aNewParent);
    1576             :   }
    1577             : 
    1578           0 :   if (aNewParent->PrincipalChildList().IsEmpty() &&
    1579           0 :       (aNewParent->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    1580           0 :     aNewParent->SetInitialChildList(kPrincipalList, aFrameList);
    1581             :   } else {
    1582           0 :     aNewParent->AppendFrames(kPrincipalList, aFrameList);
    1583             :   }
    1584           0 : }
    1585             : 
    1586             : //----------------------------------------------------------------------
    1587             : 
    1588           0 : nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument* aDocument,
    1589           0 :                                              nsIPresShell* aPresShell)
    1590             :   : nsFrameManager(aPresShell)
    1591             :   , mDocument(aDocument)
    1592             :   , mRootElementFrame(nullptr)
    1593             :   , mRootElementStyleFrame(nullptr)
    1594             :   , mDocElementContainingBlock(nullptr)
    1595             :   , mPageSequenceFrame(nullptr)
    1596             :   , mFirstFreeFCItem(nullptr)
    1597             :   , mFCItemsInUse(0)
    1598             :   , mCurrentDepth(0)
    1599             :   , mQuotesDirty(false)
    1600             :   , mCountersDirty(false)
    1601             :   , mIsDestroyingFrameTree(false)
    1602             :   , mHasRootAbsPosContainingBlock(false)
    1603           0 :   , mAlwaysCreateFramesForIgnorableWhitespace(false)
    1604             : {
    1605             : #ifdef DEBUG
    1606             :   static bool gFirstTime = true;
    1607           0 :   if (gFirstTime) {
    1608           0 :     gFirstTime = false;
    1609           0 :     char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
    1610           0 :     if (flags) {
    1611             :       bool error = false;
    1612             :       for (;;) {
    1613           0 :         char* comma = PL_strchr(flags, ',');
    1614           0 :         if (comma)
    1615           0 :           *comma = '\0';
    1616             : 
    1617             :         bool found = false;
    1618             :         FrameCtorDebugFlags* flag = gFlags;
    1619             :         FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
    1620           0 :         while (flag < limit) {
    1621           0 :           if (PL_strcasecmp(flag->name, flags) == 0) {
    1622           0 :             *(flag->on) = true;
    1623           0 :             printf("nsCSSFrameConstructor: setting %s debug flag on\n", flag->name);
    1624           0 :             found = true;
    1625           0 :             break;
    1626             :           }
    1627           0 :           ++flag;
    1628             :         }
    1629             : 
    1630           0 :         if (! found)
    1631           0 :           error = true;
    1632             : 
    1633           0 :         if (! comma)
    1634             :           break;
    1635             : 
    1636           0 :         *comma = ',';
    1637           0 :         flags = comma + 1;
    1638           0 :       }
    1639             : 
    1640           0 :       if (error) {
    1641           0 :         printf("Here are the available GECKO_FRAMECTOR_DEBUG_FLAGS:\n");
    1642           0 :         FrameCtorDebugFlags* flag = gFlags;
    1643           0 :         FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
    1644           0 :         while (flag < limit) {
    1645           0 :           printf("  %s\n", flag->name);
    1646           0 :           ++flag;
    1647             :         }
    1648           0 :         printf("Note: GECKO_FRAMECTOR_DEBUG_FLAGS is a comma separated list of flag\n");
    1649             :         printf("names (no whitespace)\n");
    1650             :       }
    1651             :     }
    1652             :   }
    1653             : #endif
    1654           0 : }
    1655             : 
    1656             : void
    1657           0 : nsCSSFrameConstructor::NotifyDestroyingFrame(nsIFrame* aFrame)
    1658             : {
    1659           0 :   if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
    1660           0 :     if (mQuoteList.DestroyNodesFor(aFrame))
    1661           0 :       QuotesDirty();
    1662             :   }
    1663             : 
    1664           0 :   if (aFrame->HasAnyStateBits(NS_FRAME_HAS_CSS_COUNTER_STYLE) &&
    1665           0 :       mCounterManager.DestroyNodesFor(aFrame)) {
    1666             :     // Technically we don't need to update anything if we destroyed only
    1667             :     // USE nodes.  However, this is unlikely to happen in the real world
    1668             :     // since USE nodes generally go along with INCREMENT nodes.
    1669           0 :     CountersDirty();
    1670             :   }
    1671             : 
    1672           0 :   RestyleManager()->NotifyDestroyingFrame(aFrame);
    1673           0 : }
    1674             : 
    1675           0 : struct nsGenConInitializer {
    1676             :   nsAutoPtr<nsGenConNode> mNode;
    1677             :   nsGenConList*           mList;
    1678             :   void (nsCSSFrameConstructor::*mDirtyAll)();
    1679             : 
    1680             :   nsGenConInitializer(nsGenConNode* aNode, nsGenConList* aList,
    1681             :                       void (nsCSSFrameConstructor::*aDirtyAll)())
    1682           0 :     : mNode(aNode), mList(aList), mDirtyAll(aDirtyAll) {}
    1683             : };
    1684             : 
    1685             : already_AddRefed<nsIContent>
    1686           0 : nsCSSFrameConstructor::CreateGenConTextNode(nsFrameConstructorState& aState,
    1687             :                                             const nsString& aString,
    1688             :                                             RefPtr<nsTextNode>* aText,
    1689             :                                             nsGenConInitializer* aInitializer)
    1690             : {
    1691           0 :   RefPtr<nsTextNode> content = new nsTextNode(mDocument->NodeInfoManager());
    1692           0 :   content->SetText(aString, false);
    1693           0 :   if (aText) {
    1694           0 :     *aText = content;
    1695             :   }
    1696           0 :   if (aInitializer) {
    1697           0 :     content->SetProperty(nsGkAtoms::genConInitializerProperty, aInitializer,
    1698           0 :                          nsINode::DeleteProperty<nsGenConInitializer>);
    1699           0 :     aState.mGeneratedTextNodesWithInitializer.AppendObject(content);
    1700             :   }
    1701           0 :   return content.forget();
    1702             : }
    1703             : 
    1704             : already_AddRefed<nsIContent>
    1705           0 : nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
    1706             :                                               Element* aParentContent,
    1707             :                                               ComputedStyle* aComputedStyle,
    1708             :                                               uint32_t        aContentIndex)
    1709             : {
    1710             :   // Get the content value
    1711             :   const nsStyleContentData &data =
    1712           0 :     aComputedStyle->StyleContent()->ContentAt(aContentIndex);
    1713           0 :   nsStyleContentType type = data.GetType();
    1714             : 
    1715           0 :   switch (type) {
    1716             :     case eStyleContentType_Image: {
    1717           0 :       imgRequestProxy* image = data.GetImage();
    1718           0 :       if (!image) {
    1719             :         // CSS had something specified that couldn't be converted to an
    1720             :         // image object
    1721             :         return nullptr;
    1722             :       }
    1723             : 
    1724             :       // Create an image content object and pass it the image request.
    1725             :       // XXX Check if it's an image type we can handle...
    1726             : 
    1727           0 :       return CreateGenConImageContent(mDocument, image);
    1728             :     }
    1729             : 
    1730             :     case eStyleContentType_String:
    1731             :       return CreateGenConTextNode(aState,
    1732           0 :                                   nsDependentString(data.GetString()),
    1733           0 :                                   nullptr, nullptr);
    1734             : 
    1735             :     case eStyleContentType_Attr: {
    1736           0 :       const nsStyleContentAttr* attr = data.GetAttr();
    1737           0 :       RefPtr<nsAtom> attrName = attr->mName;
    1738           0 :       int32_t attrNameSpace = kNameSpaceID_None;
    1739           0 :       if (RefPtr<nsAtom> ns = attr->mNamespaceURL) {
    1740             :         nsresult rv =
    1741           0 :           nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns.forget(), attrNameSpace);
    1742           0 :         NS_ENSURE_SUCCESS(rv, nullptr);
    1743             :       }
    1744             : 
    1745           0 :       if (mDocument->IsHTMLDocument() && aParentContent->IsHTMLElement()) {
    1746           0 :         ToLowerCaseASCII(attrName);
    1747             :       }
    1748             : 
    1749           0 :       nsCOMPtr<nsIContent> content;
    1750           0 :       NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1751           0 :                              attrNameSpace, attrName, getter_AddRefs(content));
    1752           0 :       return content.forget();
    1753             :     }
    1754             : 
    1755             :     case eStyleContentType_Counter:
    1756             :     case eStyleContentType_Counters: {
    1757           0 :       nsStyleContentData::CounterFunction* counters = data.GetCounters();
    1758             :       nsCounterList* counterList =
    1759           0 :         mCounterManager.CounterListFor(counters->mIdent);
    1760             : 
    1761             :       nsCounterUseNode* node =
    1762             :         new nsCounterUseNode(counters, aContentIndex,
    1763           0 :                              type == eStyleContentType_Counters);
    1764             : 
    1765             :       nsGenConInitializer* initializer =
    1766             :         new nsGenConInitializer(node, counterList,
    1767           0 :                                 &nsCSSFrameConstructor::CountersDirty);
    1768             :       return CreateGenConTextNode(aState, EmptyString(), &node->mText,
    1769           0 :                                   initializer);
    1770             :     }
    1771             : 
    1772             :     case eStyleContentType_OpenQuote:
    1773             :     case eStyleContentType_CloseQuote:
    1774             :     case eStyleContentType_NoOpenQuote:
    1775             :     case eStyleContentType_NoCloseQuote: {
    1776             :       nsQuoteNode* node =
    1777           0 :         new nsQuoteNode(type, aContentIndex);
    1778             : 
    1779             :       nsGenConInitializer* initializer =
    1780             :         new nsGenConInitializer(node, &mQuoteList,
    1781           0 :                                 &nsCSSFrameConstructor::QuotesDirty);
    1782             :       return CreateGenConTextNode(aState, EmptyString(), &node->mText,
    1783           0 :                                   initializer);
    1784             :     }
    1785             : 
    1786             :     case eStyleContentType_AltContent: {
    1787             :       // Use the "alt" attribute; if that fails and the node is an HTML
    1788             :       // <input>, try the value attribute and then fall back to some default
    1789             :       // localized text we have.
    1790             :       // XXX what if the 'alt' attribute is added later, how will we
    1791             :       // detect that and do the right thing here?
    1792           0 :       if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::alt)) {
    1793           0 :         nsCOMPtr<nsIContent> content;
    1794           0 :         NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1795           0 :                                kNameSpaceID_None, nsGkAtoms::alt, getter_AddRefs(content));
    1796           0 :         return content.forget();
    1797             :       }
    1798             : 
    1799           0 :       if (aParentContent->IsHTMLElement(nsGkAtoms::input)) {
    1800           0 :         if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    1801           0 :           nsCOMPtr<nsIContent> content;
    1802           0 :           NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1803           0 :                                  kNameSpaceID_None, nsGkAtoms::value, getter_AddRefs(content));
    1804           0 :           return content.forget();
    1805             :         }
    1806             : 
    1807           0 :         nsAutoString temp;
    1808             :         nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
    1809           0 :                                            "Submit", temp);
    1810           0 :         return CreateGenConTextNode(aState, temp, nullptr, nullptr);
    1811             :       }
    1812             : 
    1813             :       break;
    1814             :     }
    1815             : 
    1816             :     case eStyleContentType_Uninitialized:
    1817           0 :       NS_NOTREACHED("uninitialized content type");
    1818             :       return nullptr;
    1819             :   }
    1820             : 
    1821             :   return nullptr;
    1822             : }
    1823             : 
    1824             : /*
    1825             :  * aParentFrame - the frame that should be the parent of the generated
    1826             :  *   content.  This is the frame for the corresponding content node,
    1827             :  *   which must not be a leaf frame.
    1828             :  *
    1829             :  * Any items created are added to aItems.
    1830             :  *
    1831             :  * We create an XML element (tag _moz_generated_content_before or
    1832             :  * _moz_generated_content_after) representing the pseudoelement. We
    1833             :  * create a DOM node for each 'content' item and make those nodes the
    1834             :  * children of the XML element. Then we create a frame subtree for
    1835             :  * the XML element as if it were a regular child of
    1836             :  * aParentFrame/aParentContent, giving the XML element the ::before or
    1837             :  * ::after style.
    1838             :  */
    1839             : void
    1840           0 : nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aState,
    1841             :                                                   nsContainerFrame* aParentFrame,
    1842             :                                                   Element* aParentContent,
    1843             :                                                   ComputedStyle*  aComputedStyle,
    1844             :                                                   CSSPseudoElementType aPseudoElement,
    1845             :                                                   FrameConstructionItemList& aItems)
    1846             : {
    1847           0 :   MOZ_ASSERT(aPseudoElement == CSSPseudoElementType::before ||
    1848             :              aPseudoElement == CSSPseudoElementType::after,
    1849             :              "unexpected aPseudoElement");
    1850             : 
    1851           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
    1852             : 
    1853             :   // Probe for the existence of the pseudo-element
    1854           0 :   RefPtr<ComputedStyle> pseudoComputedStyle;
    1855             :   pseudoComputedStyle =
    1856           0 :     styleSet->ProbePseudoElementStyle(aParentContent, aPseudoElement,
    1857           0 :                                       aComputedStyle);
    1858           0 :   if (!pseudoComputedStyle)
    1859           0 :     return;
    1860             : 
    1861           0 :   bool isBefore = aPseudoElement == CSSPseudoElementType::before;
    1862             : 
    1863             :   // |ProbePseudoStyleFor| checked the 'display' property and the
    1864             :   // |ContentCount()| of the 'content' property for us.
    1865           0 :   RefPtr<NodeInfo> nodeInfo;
    1866             :   nsAtom* elemName = isBefore ?
    1867           0 :     nsGkAtoms::mozgeneratedcontentbefore : nsGkAtoms::mozgeneratedcontentafter;
    1868           0 :   nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(elemName, nullptr,
    1869             :                                                        kNameSpaceID_None,
    1870           0 :                                                        nsINode::ELEMENT_NODE);
    1871           0 :   nsCOMPtr<Element> container;
    1872           0 :   nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
    1873           0 :   if (NS_FAILED(rv))
    1874           0 :     return;
    1875             : 
    1876             :   // Cleared when the pseudo is unbound from the tree, so no need to store a
    1877             :   // strong reference, nor a destructor.
    1878             :   nsAtom* property = isBefore
    1879           0 :     ? nsGkAtoms::beforePseudoProperty : nsGkAtoms::afterPseudoProperty;
    1880           0 :   aParentContent->SetProperty(property, container.get());
    1881             : 
    1882           0 :   container->SetIsNativeAnonymousRoot();
    1883           0 :   container->SetPseudoElementType(aPseudoElement);
    1884             : 
    1885             :   // If the parent is in a shadow tree, make sure we don't
    1886             :   // bind with a document because shadow roots and its descendants
    1887             :   // are not in document.
    1888             :   nsIDocument* bindDocument =
    1889           0 :     aParentContent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
    1890           0 :   rv = container->BindToTree(bindDocument, aParentContent, aParentContent, true);
    1891           0 :   if (NS_FAILED(rv)) {
    1892           0 :     container->UnbindFromTree();
    1893           0 :     return;
    1894             :   }
    1895             : 
    1896             :   // Servo has already eagerly computed the style for the container, so we can
    1897             :   // just stick the style on the element and avoid an additional traversal.
    1898             :   //
    1899             :   // We don't do this for pseudos that may trigger animations or transitions,
    1900             :   // since those need to be kicked off by the traversal machinery.
    1901             :   bool hasServoAnimations =
    1902           0 :     Servo_ComputedValues_SpecifiesAnimationsOrTransitions(pseudoComputedStyle);
    1903           0 :   if (!hasServoAnimations) {
    1904           0 :     Servo_SetExplicitStyle(container, pseudoComputedStyle);
    1905             :   } else {
    1906             :     // If animations are involved, we avoid the SetExplicitStyle optimization
    1907             :     // above. We need to grab style with animations from the pseudo element
    1908             :     // and replace old one.
    1909           0 :     mPresShell->StyleSet()->StyleNewSubtree(container);
    1910           0 :     pseudoComputedStyle = styleSet->ResolveServoStyle(container);
    1911             :   }
    1912             : 
    1913           0 :   uint32_t contentCount = pseudoComputedStyle->StyleContent()->ContentCount();
    1914           0 :   for (uint32_t contentIndex = 0; contentIndex < contentCount; contentIndex++) {
    1915             :     nsCOMPtr<nsIContent> content =
    1916           0 :       CreateGeneratedContent(aState, aParentContent, pseudoComputedStyle,
    1917           0 :                              contentIndex);
    1918           0 :     if (content) {
    1919           0 :       container->AppendChildTo(content, false);
    1920           0 :       if (content->IsElement()) {
    1921             :         // If we created any children elements, Servo needs to traverse them, but
    1922             :         // the root is already set up.
    1923           0 :         mPresShell->StyleSet()->StyleNewSubtree(content->AsElement());
    1924             :       }
    1925             :     }
    1926             :   }
    1927             : 
    1928           0 :   AddFrameConstructionItemsInternal(aState, container, aParentFrame, true,
    1929             :                                     pseudoComputedStyle,
    1930             :                                     ITEM_IS_GENERATED_CONTENT, nullptr,
    1931           0 :                                     aItems);
    1932             : }
    1933             : 
    1934             : /****************************************************
    1935             :  **  BEGIN TABLE SECTION
    1936             :  ****************************************************/
    1937             : 
    1938             : // The term pseudo frame is being used instead of anonymous frame, since anonymous
    1939             : // frame has been used elsewhere to refer to frames that have generated content
    1940             : 
    1941             : // Return whether the given frame is a table pseudo-frame. Note that
    1942             : // cell-content and table-outer frames have pseudo-types, but are always
    1943             : // created, even for non-anonymous cells and tables respectively.  So for those
    1944             : // we have to examine the cell or table frame to see whether it's a pseudo
    1945             : // frame. In particular, a lone table caption will have a table wrapper as its
    1946             : // parent, but will also trigger construction of an empty inner table, which
    1947             : // will be the one we can examine to see whether the wrapper was a pseudo-frame.
    1948             : static bool
    1949           0 : IsTablePseudo(nsIFrame* aFrame)
    1950             : {
    1951           0 :   nsAtom* pseudoType = aFrame->Style()->GetPseudo();
    1952           0 :   return pseudoType &&
    1953           0 :     (pseudoType == nsCSSAnonBoxes::table ||
    1954           0 :      pseudoType == nsCSSAnonBoxes::inlineTable ||
    1955           0 :      pseudoType == nsCSSAnonBoxes::tableColGroup ||
    1956           0 :      pseudoType == nsCSSAnonBoxes::tableRowGroup ||
    1957           0 :      pseudoType == nsCSSAnonBoxes::tableRow ||
    1958           0 :      pseudoType == nsCSSAnonBoxes::tableCell ||
    1959           0 :      (pseudoType == nsCSSAnonBoxes::cellContent &&
    1960           0 :       aFrame->GetParent()->Style()->GetPseudo() ==
    1961           0 :         nsCSSAnonBoxes::tableCell) ||
    1962           0 :      (pseudoType == nsCSSAnonBoxes::tableWrapper &&
    1963           0 :       (aFrame->PrincipalChildList().FirstChild()->Style()->GetPseudo() ==
    1964           0 :          nsCSSAnonBoxes::table ||
    1965           0 :        aFrame->PrincipalChildList().FirstChild()->Style()->GetPseudo() ==
    1966           0 :          nsCSSAnonBoxes::inlineTable)));
    1967             : }
    1968             : 
    1969             : static bool
    1970           0 : IsRubyPseudo(nsIFrame* aFrame)
    1971             : {
    1972           0 :   return RubyUtils::IsRubyPseudo(aFrame->Style()->GetPseudo());
    1973             : }
    1974             : 
    1975             : static bool
    1976           0 : IsTableOrRubyPseudo(nsIFrame* aFrame)
    1977             : {
    1978           0 :   return IsTablePseudo(aFrame) || IsRubyPseudo(aFrame);
    1979             : }
    1980             : 
    1981             : /* static */
    1982             : nsCSSFrameConstructor::ParentType
    1983           0 : nsCSSFrameConstructor::GetParentType(LayoutFrameType aFrameType)
    1984             : {
    1985           0 :   if (aFrameType == LayoutFrameType::Table) {
    1986             :     return eTypeTable;
    1987             :   }
    1988           0 :   if (aFrameType == LayoutFrameType::TableRowGroup) {
    1989             :     return eTypeRowGroup;
    1990             :   }
    1991           0 :   if (aFrameType == LayoutFrameType::TableRow) {
    1992             :     return eTypeRow;
    1993             :   }
    1994           0 :   if (aFrameType == LayoutFrameType::TableColGroup) {
    1995             :     return eTypeColGroup;
    1996             :   }
    1997           0 :   if (aFrameType == LayoutFrameType::RubyBaseContainer) {
    1998             :     return eTypeRubyBaseContainer;
    1999             :   }
    2000           0 :   if (aFrameType == LayoutFrameType::RubyTextContainer) {
    2001             :     return eTypeRubyTextContainer;
    2002             :   }
    2003           0 :   if (aFrameType == LayoutFrameType::Ruby) {
    2004             :     return eTypeRuby;
    2005             :   }
    2006             : 
    2007           0 :   return eTypeBlock;
    2008             : }
    2009             : 
    2010             : static nsContainerFrame*
    2011           0 : AdjustCaptionParentFrame(nsContainerFrame* aParentFrame)
    2012             : {
    2013           0 :   if (aParentFrame->IsTableFrame()) {
    2014           0 :     return aParentFrame->GetParent();
    2015             :   }
    2016             :   return aParentFrame;
    2017             : }
    2018             : 
    2019             : /**
    2020             :  * If the parent frame is a |tableFrame| and the child is a
    2021             :  * |captionFrame|, then we want to insert the frames beneath the
    2022             :  * |tableFrame|'s parent frame. Returns |true| if the parent frame
    2023             :  * needed to be fixed up.
    2024             :  */
    2025             : static bool
    2026           0 : GetCaptionAdjustedParent(nsContainerFrame*  aParentFrame,
    2027             :                          const nsIFrame*    aChildFrame,
    2028             :                          nsContainerFrame** aAdjParentFrame)
    2029             : {
    2030           0 :   *aAdjParentFrame = aParentFrame;
    2031           0 :   bool haveCaption = false;
    2032             : 
    2033           0 :   if (aChildFrame->IsTableCaption()) {
    2034           0 :     haveCaption = true;
    2035           0 :     *aAdjParentFrame = ::AdjustCaptionParentFrame(aParentFrame);
    2036             :   }
    2037           0 :   return haveCaption;
    2038             : }
    2039             : 
    2040             : void
    2041           0 : nsCSSFrameConstructor::AdjustParentFrame(nsContainerFrame**           aParentFrame,
    2042             :                                          const FrameConstructionData* aFCData,
    2043             :                                          ComputedStyle*              aComputedStyle)
    2044             : {
    2045           0 :   MOZ_ASSERT(aComputedStyle, "Must have child's style");
    2046           0 :   MOZ_ASSERT(aFCData, "Must have frame construction data");
    2047             : 
    2048           0 :   bool tablePart = ((aFCData->mBits & FCDATA_IS_TABLE_PART) != 0);
    2049             : 
    2050           0 :   if (tablePart && aComputedStyle->StyleDisplay()->mDisplay ==
    2051             :       StyleDisplay::TableCaption) {
    2052           0 :     *aParentFrame = ::AdjustCaptionParentFrame(*aParentFrame);
    2053             :   }
    2054           0 : }
    2055             : 
    2056             : // Pull all the captions present in aItems out  into aCaptions
    2057             : static void
    2058           0 : PullOutCaptionFrames(nsFrameItems& aItems, nsFrameItems& aCaptions)
    2059             : {
    2060           0 :   nsIFrame* child = aItems.FirstChild();
    2061           0 :   while (child) {
    2062           0 :     nsIFrame* nextSibling = child->GetNextSibling();
    2063           0 :     if (child->IsTableCaption()) {
    2064           0 :       aItems.RemoveFrame(child);
    2065           0 :       aCaptions.AddChild(child);
    2066             :     }
    2067             :     child = nextSibling;
    2068             :   }
    2069           0 : }
    2070             : 
    2071             : 
    2072             : // Construct the outer, inner table frames and the children frames for the table.
    2073             : // XXX Page break frames for pseudo table frames are not constructed to avoid the risk
    2074             : // associated with revising the pseudo frame mechanism. The long term solution
    2075             : // of having frames handle page-break-before/after will solve the problem.
    2076             : nsIFrame*
    2077           0 : nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
    2078             :                                       FrameConstructionItem&   aItem,
    2079             :                                       nsContainerFrame*        aParentFrame,
    2080             :                                       const nsStyleDisplay*    aDisplay,
    2081             :                                       nsFrameItems&            aFrameItems)
    2082             : {
    2083           0 :   MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::Table ||
    2084             :              aDisplay->mDisplay == StyleDisplay::InlineTable,
    2085             :              "Unexpected call");
    2086             : 
    2087           0 :   nsIContent* const content = aItem.mContent;
    2088           0 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    2089           0 :   const bool isMathMLContent = content->IsMathMLElement();
    2090             : 
    2091             :   // create the pseudo SC for the table wrapper as a child of the inner SC
    2092           0 :   RefPtr<ComputedStyle> outerComputedStyle;
    2093           0 :   outerComputedStyle = mPresShell->StyleSet()->
    2094           0 :     ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::tableWrapper,
    2095           0 :                                        computedStyle);
    2096             : 
    2097             :   // Create the table wrapper frame which holds the caption and inner table frame
    2098             :   nsContainerFrame* newFrame;
    2099           0 :   if (isMathMLContent)
    2100           0 :     newFrame = NS_NewMathMLmtableOuterFrame(mPresShell, outerComputedStyle);
    2101             :   else
    2102           0 :     newFrame = NS_NewTableWrapperFrame(mPresShell, outerComputedStyle);
    2103             : 
    2104             :   nsContainerFrame* geometricParent =
    2105           0 :     aState.GetGeometricParent(outerComputedStyle->StyleDisplay(),
    2106           0 :                               aParentFrame);
    2107             : 
    2108             :   // Init the table wrapper frame
    2109           0 :   InitAndRestoreFrame(aState, content, geometricParent, newFrame);
    2110             : 
    2111             :   // Create the inner table frame
    2112             :   nsContainerFrame* innerFrame;
    2113           0 :   if (isMathMLContent)
    2114           0 :     innerFrame = NS_NewMathMLmtableFrame(mPresShell, computedStyle);
    2115             :   else
    2116           0 :     innerFrame = NS_NewTableFrame(mPresShell, computedStyle);
    2117             : 
    2118           0 :   InitAndRestoreFrame(aState, content, newFrame, innerFrame);
    2119           0 :   innerFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2120             : 
    2121             :   // Put the newly created frames into the right child list
    2122           0 :   SetInitialSingleChild(newFrame, innerFrame);
    2123             : 
    2124           0 :   aState.AddChild(newFrame, aFrameItems, content, aParentFrame);
    2125             : 
    2126           0 :   if (!mRootElementFrame) {
    2127             :     // The frame we're constructing will be the root element frame.
    2128             :     // Set mRootElementFrame before processing children.
    2129           0 :     mRootElementFrame = newFrame;
    2130             :   }
    2131             : 
    2132           0 :   nsFrameItems childItems;
    2133             : 
    2134             :   // Process children
    2135           0 :   nsFrameConstructorSaveState absoluteSaveState;
    2136           0 :   const nsStyleDisplay* display = outerComputedStyle->StyleDisplay();
    2137             : 
    2138             :   // Mark the table frame as an absolute container if needed
    2139           0 :   newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2140           0 :   if (display->IsAbsPosContainingBlock(newFrame)) {
    2141           0 :     aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
    2142             :   }
    2143           0 :   NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
    2144             :                "nsIAnonymousContentCreator::CreateAnonymousContent "
    2145             :                "implementations for table frames are not currently expected "
    2146             :                "to output a list where the items have their own children");
    2147           0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    2148           0 :     ConstructFramesFromItemList(aState, aItem.mChildItems,
    2149             :                                 innerFrame,
    2150           0 :                                 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX,
    2151           0 :                                 childItems);
    2152             :   } else {
    2153           0 :     ProcessChildren(aState, content, computedStyle, innerFrame,
    2154           0 :                     true, childItems, false, aItem.mPendingBinding);
    2155             :   }
    2156             : 
    2157           0 :   nsFrameItems captionItems;
    2158           0 :   PullOutCaptionFrames(childItems, captionItems);
    2159             : 
    2160             :   // Set the inner table frame's initial primary list
    2161           0 :   innerFrame->SetInitialChildList(kPrincipalList, childItems);
    2162             : 
    2163             :   // Set the table wrapper frame's secondary childlist lists
    2164           0 :   if (captionItems.NotEmpty()) {
    2165           0 :     newFrame->SetInitialChildList(nsIFrame::kCaptionList, captionItems);
    2166             :   }
    2167             : 
    2168           0 :   return newFrame;
    2169             : }
    2170             : 
    2171             : static void
    2172           0 : MakeTablePartAbsoluteContainingBlockIfNeeded(nsFrameConstructorState&     aState,
    2173             :                                              const nsStyleDisplay*        aDisplay,
    2174             :                                              nsFrameConstructorSaveState& aAbsSaveState,
    2175             :                                              nsContainerFrame*            aFrame)
    2176             : {
    2177             :   // If we're positioned, then we need to become an absolute containing block
    2178             :   // for any absolutely positioned children and register for post-reflow fixup.
    2179             :   //
    2180             :   // Note that usually if a frame type can be an absolute containing block, we
    2181             :   // always set NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN, whether it actually is or not.
    2182             :   // However, in this case flag serves the additional purpose of indicating that
    2183             :   // the frame was registered with its table frame. This allows us to avoid the
    2184             :   // overhead of unregistering the frame in most cases.
    2185           0 :   if (aDisplay->IsAbsPosContainingBlock(aFrame)) {
    2186           0 :     aFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2187           0 :     aState.PushAbsoluteContainingBlock(aFrame, aFrame, aAbsSaveState);
    2188           0 :     nsTableFrame::RegisterPositionedTablePart(aFrame);
    2189             :   }
    2190           0 : }
    2191             : 
    2192             : nsIFrame*
    2193           0 : nsCSSFrameConstructor::ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
    2194             :                                                    FrameConstructionItem&   aItem,
    2195             :                                                    nsContainerFrame*        aParentFrame,
    2196             :                                                    const nsStyleDisplay*    aDisplay,
    2197             :                                                    nsFrameItems&            aFrameItems)
    2198             : {
    2199           0 :   MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::TableRow ||
    2200             :              aDisplay->mDisplay == StyleDisplay::TableRowGroup ||
    2201             :              aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
    2202             :              aDisplay->mDisplay == StyleDisplay::TableHeaderGroup,
    2203             :              "Not a row or row group");
    2204           0 :   MOZ_ASSERT(aItem.mComputedStyle->StyleDisplay() == aDisplay,
    2205             :              "Display style doesn't match style");
    2206           0 :   nsIContent* const content = aItem.mContent;
    2207           0 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    2208             : 
    2209             :   nsContainerFrame* newFrame;
    2210           0 :   if (aDisplay->mDisplay == StyleDisplay::TableRow) {
    2211           0 :     if (content->IsMathMLElement())
    2212           0 :       newFrame = NS_NewMathMLmtrFrame(mPresShell, computedStyle);
    2213             :     else
    2214           0 :       newFrame = NS_NewTableRowFrame(mPresShell, computedStyle);
    2215             :   } else {
    2216           0 :     newFrame = NS_NewTableRowGroupFrame(mPresShell, computedStyle);
    2217             :   }
    2218             : 
    2219           0 :   InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
    2220             : 
    2221           0 :   nsFrameConstructorSaveState absoluteSaveState;
    2222             :   MakeTablePartAbsoluteContainingBlockIfNeeded(aState, aDisplay,
    2223             :                                                absoluteSaveState,
    2224           0 :                                                newFrame);
    2225             : 
    2226           0 :   nsFrameItems childItems;
    2227           0 :   NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
    2228             :                "nsIAnonymousContentCreator::CreateAnonymousContent "
    2229             :                "implementations for table frames are not currently expected "
    2230             :                "to output a list where the items have their own children");
    2231           0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    2232           0 :     ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
    2233           0 :                                 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX,
    2234           0 :                                 childItems);
    2235             :   } else {
    2236           0 :     ProcessChildren(aState, content, computedStyle, newFrame,
    2237           0 :                     true, childItems, false, aItem.mPendingBinding);
    2238             :   }
    2239             : 
    2240           0 :   newFrame->SetInitialChildList(kPrincipalList, childItems);
    2241           0 :   aFrameItems.AddChild(newFrame);
    2242           0 :   return newFrame;
    2243             : }
    2244             : 
    2245             : nsIFrame*
    2246           0 : nsCSSFrameConstructor::ConstructTableCol(nsFrameConstructorState& aState,
    2247             :                                          FrameConstructionItem&   aItem,
    2248             :                                          nsContainerFrame*        aParentFrame,
    2249             :                                          const nsStyleDisplay*    aStyleDisplay,
    2250             :                                          nsFrameItems&            aFrameItems)
    2251             : {
    2252           0 :   nsIContent* const content = aItem.mContent;
    2253           0 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    2254             : 
    2255           0 :   nsTableColFrame* colFrame = NS_NewTableColFrame(mPresShell, computedStyle);
    2256           0 :   InitAndRestoreFrame(aState, content, aParentFrame, colFrame);
    2257             : 
    2258           0 :   NS_ASSERTION(colFrame->Style() == computedStyle, "Unexpected style");
    2259             : 
    2260           0 :   aFrameItems.AddChild(colFrame);
    2261             : 
    2262             :   // construct additional col frames if the col frame has a span > 1
    2263           0 :   int32_t span = colFrame->GetSpan();
    2264           0 :   for (int32_t spanX = 1; spanX < span; spanX++) {
    2265           0 :     nsTableColFrame* newCol = NS_NewTableColFrame(mPresShell, computedStyle);
    2266           0 :     InitAndRestoreFrame(aState, content, aParentFrame, newCol, false);
    2267           0 :     aFrameItems.LastChild()->SetNextContinuation(newCol);
    2268           0 :     newCol->SetPrevContinuation(aFrameItems.LastChild());
    2269           0 :     aFrameItems.AddChild(newCol);
    2270           0 :     newCol->SetColType(eColAnonymousCol);
    2271             :   }
    2272             : 
    2273           0 :   return colFrame;
    2274             : }
    2275             : 
    2276             : nsIFrame*
    2277           0 : nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState,
    2278             :                                           FrameConstructionItem&   aItem,
    2279             :                                           nsContainerFrame*        aParentFrame,
    2280             :                                           const nsStyleDisplay*    aDisplay,
    2281             :                                           nsFrameItems&            aFrameItems)
    2282             : {
    2283           0 :   MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::TableCell,
    2284             :              "Unexpected call");
    2285             : 
    2286           0 :   nsIContent* const content = aItem.mContent;
    2287           0 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    2288           0 :   const bool isMathMLContent = content->IsMathMLElement();
    2289             : 
    2290             :   nsTableFrame* tableFrame =
    2291           0 :     static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
    2292             :   nsContainerFrame* newFrame;
    2293             :   // <mtable> is border separate in mathml.css and the MathML code doesn't implement
    2294             :   // border collapse. For those users who style <mtable> with border collapse,
    2295             :   // give them the default non-MathML table frames that understand border collapse.
    2296             :   // This won't break us because MathML table frames are all subclasses of the default
    2297             :   // table code, and so we can freely mix <mtable> with <mtr> or <tr>, <mtd> or <td>.
    2298             :   // What will happen is just that non-MathML frames won't understand MathML attributes
    2299             :   // and will therefore miss the special handling that the MathML code does.
    2300           0 :   if (isMathMLContent && !tableFrame->IsBorderCollapse()) {
    2301           0 :     newFrame = NS_NewMathMLmtdFrame(mPresShell, computedStyle, tableFrame);
    2302             :   } else {
    2303             :     // Warning: If you change this and add a wrapper frame around table cell
    2304             :     // frames, make sure Bug 368554 doesn't regress!
    2305             :     // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
    2306           0 :     newFrame = NS_NewTableCellFrame(mPresShell, computedStyle, tableFrame);
    2307             :   }
    2308             : 
    2309             :   // Initialize the table cell frame
    2310           0 :   InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
    2311           0 :   newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2312             : 
    2313             :   // Resolve pseudo style and initialize the body cell frame
    2314           0 :   RefPtr<ComputedStyle> innerPseudoStyle;
    2315           0 :   innerPseudoStyle = mPresShell->StyleSet()->
    2316           0 :     ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::cellContent,
    2317           0 :                                        computedStyle);
    2318             : 
    2319             :   // Create a block frame that will format the cell's content
    2320             :   bool isBlock;
    2321             :   nsContainerFrame* cellInnerFrame;
    2322           0 :   if (isMathMLContent) {
    2323           0 :     cellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
    2324           0 :     isBlock = false;
    2325             :   } else {
    2326           0 :     cellInnerFrame = NS_NewBlockFormattingContext(mPresShell, innerPseudoStyle);
    2327           0 :     isBlock = true;
    2328             :   }
    2329             : 
    2330           0 :   InitAndRestoreFrame(aState, content, newFrame, cellInnerFrame);
    2331             : 
    2332           0 :   nsFrameConstructorSaveState absoluteSaveState;
    2333             :   MakeTablePartAbsoluteContainingBlockIfNeeded(aState, aDisplay,
    2334             :                                                absoluteSaveState,
    2335           0 :                                                newFrame);
    2336             : 
    2337           0 :   nsFrameItems childItems;
    2338           0 :   NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
    2339             :                "nsIAnonymousContentCreator::CreateAnonymousContent "
    2340             :                "implementations for table frames are not currently expected "
    2341             :                "to output a list where the items have their own children");
    2342           0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    2343             :     // Need to push ourselves as a float containing block.
    2344             :     // XXXbz it might be nice to work on getting the parent
    2345             :     // FrameConstructionItem down into ProcessChildren and just making use of
    2346             :     // the push there, but that's a bit of work.
    2347           0 :     nsFrameConstructorSaveState floatSaveState;
    2348           0 :     if (!isBlock) { /* MathML case */
    2349           0 :       aState.PushFloatContainingBlock(nullptr, floatSaveState);
    2350             :     } else {
    2351           0 :       aState.PushFloatContainingBlock(cellInnerFrame, floatSaveState);
    2352             :     }
    2353             : 
    2354           0 :     ConstructFramesFromItemList(aState, aItem.mChildItems, cellInnerFrame,
    2355           0 :                                 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX,
    2356           0 :                                 childItems);
    2357             :   } else {
    2358             :     // Process the child content
    2359           0 :     ProcessChildren(aState, content, computedStyle, cellInnerFrame,
    2360           0 :                     true, childItems, isBlock, aItem.mPendingBinding);
    2361             :   }
    2362             : 
    2363           0 :   cellInnerFrame->SetInitialChildList(kPrincipalList, childItems);
    2364           0 :   SetInitialSingleChild(newFrame, cellInnerFrame);
    2365           0 :   aFrameItems.AddChild(newFrame);
    2366           0 :   return newFrame;
    2367             : }
    2368             : 
    2369             : static inline bool
    2370           0 : NeedFrameFor(const nsFrameConstructorState& aState,
    2371             :              nsIFrame*   aParentFrame,
    2372             :              nsIContent* aChildContent)
    2373             : {
    2374             :   // XXX the GetContent() != aChildContent check is needed due to bug 135040.
    2375             :   // Remove it once that's fixed.
    2376           0 :   MOZ_ASSERT(!aChildContent->GetPrimaryFrame() ||
    2377             :              aState.mCreatingExtraFrames ||
    2378             :              aChildContent->GetPrimaryFrame()->GetContent() != aChildContent,
    2379             :              "Why did we get called?");
    2380             : 
    2381             :   // don't create a whitespace frame if aParentFrame doesn't want it.
    2382             :   // always create frames for children in generated content. counter(),
    2383             :   // quotes, and attr() content can easily change dynamically and we don't
    2384             :   // want to be reconstructing frames. It's not even clear that these
    2385             :   // should be considered ignorable just because they evaluate to
    2386             :   // whitespace.
    2387             : 
    2388             :   // We could handle all this in CreateNeededPseudoContainers or some other
    2389             :   // place after we build our frame construction items, but that would involve
    2390             :   // creating frame construction items for whitespace kids of
    2391             :   // eExcludesIgnorableWhitespace frames, where we know we'll be dropping them
    2392             :   // all anyway, and involve an extra walk down the frame construction item
    2393             :   // list.
    2394           0 :   if ((aParentFrame &&
    2395           0 :        (!aParentFrame->IsFrameOfType(nsIFrame::eExcludesIgnorableWhitespace) ||
    2396           0 :         aParentFrame->IsGeneratedContentFrame())) ||
    2397           0 :       !aChildContent->IsText()) {
    2398             :     return true;
    2399             :   }
    2400             : 
    2401           0 :   aChildContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
    2402           0 :                           NS_REFRAME_IF_WHITESPACE);
    2403           0 :   return !aChildContent->TextIsOnlyWhitespace();
    2404             : }
    2405             : 
    2406             : /***********************************************
    2407             :  * END TABLE SECTION
    2408             :  ***********************************************/
    2409             : 
    2410             : nsIFrame*
    2411           0 : nsCSSFrameConstructor::ConstructDocElementFrame(Element*                 aDocElement,
    2412             :                                                 nsILayoutHistoryState*   aFrameState)
    2413             : {
    2414           0 :   MOZ_ASSERT(GetRootFrame(),
    2415             :              "No viewport?  Someone forgot to call ConstructRootFrame!");
    2416           0 :   MOZ_ASSERT(!mDocElementContainingBlock,
    2417             :              "Shouldn't have a doc element containing block here");
    2418             : 
    2419             :   // Resolve a new style for the viewport since it may be affected by a new root
    2420             :   // element style (e.g. a propagated 'direction').
    2421             :   //
    2422             :   // @see ComputedStyle::ApplyStyleFixups
    2423             :   {
    2424           0 :     RefPtr<ComputedStyle> sc = mPresShell->StyleSet()->
    2425           0 :       ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::viewport, nullptr);
    2426           0 :     GetRootFrame()->SetComputedStyleWithoutNotification(sc);
    2427             :   }
    2428             : 
    2429             :   // Make sure to call UpdateViewportScrollbarStylesOverride before
    2430             :   // SetUpDocElementContainingBlock, since it sets up our scrollbar state
    2431             :   // properly.
    2432           0 :   DebugOnly<nsIContent*> propagatedScrollFrom;
    2433           0 :   if (nsPresContext* presContext = mPresShell->GetPresContext()) {
    2434           0 :     propagatedScrollFrom = presContext->UpdateViewportScrollbarStylesOverride();
    2435             :   }
    2436             : 
    2437           0 :   SetUpDocElementContainingBlock(aDocElement);
    2438             : 
    2439           0 :   NS_ASSERTION(mDocElementContainingBlock, "Should have parent by now");
    2440             :   nsFrameConstructorState state(mPresShell,
    2441           0 :                                 GetAbsoluteContainingBlock(mDocElementContainingBlock, FIXED_POS),
    2442             :                                 nullptr,
    2443           0 :                                 nullptr, do_AddRef(aFrameState));
    2444             : 
    2445             :   // XXXbz why, exactly?
    2446           0 :   if (!mTempFrameTreeState)
    2447           0 :     state.mPresShell->CaptureHistoryState(getter_AddRefs(mTempFrameTreeState));
    2448             : 
    2449             :   // --------- CREATE AREA OR BOX FRAME -------
    2450           0 :   ServoStyleSet* set = mPresShell->StyleSet();
    2451             :   // Ensure the document element is styled at this point.
    2452           0 :   if (!aDocElement->HasServoData()) {
    2453             :     // NOTE(emilio): If the root has a non-null binding, we'll stop at the
    2454             :     // document element and won't process any children, loading the bindings
    2455             :     // (or failing to do so) will take care of the rest.
    2456           0 :     set->StyleNewSubtree(aDocElement);
    2457             :   }
    2458             : 
    2459             :   RefPtr<ComputedStyle> computedStyle =
    2460           0 :     mPresShell->StyleSet()->ResolveServoStyle(aDocElement);
    2461             : 
    2462           0 :   const nsStyleDisplay* display = computedStyle->StyleDisplay();
    2463             : 
    2464             :   // Ensure that our XBL bindings are installed.
    2465           0 :   if (display->mBinding) {
    2466             :     // Get the XBL loader.
    2467             :     nsresult rv;
    2468             :     bool resolveStyle;
    2469             : 
    2470           0 :     nsXBLService* xblService = nsXBLService::GetInstance();
    2471           0 :     if (!xblService) {
    2472           0 :       return nullptr;
    2473             :     }
    2474             : 
    2475           0 :     RefPtr<nsXBLBinding> binding;
    2476           0 :     rv = xblService->LoadBindings(aDocElement, display->mBinding->GetURI(),
    2477           0 :                                   display->mBinding->mExtraData->GetPrincipal(),
    2478           0 :                                   getter_AddRefs(binding), &resolveStyle);
    2479           0 :     if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED) {
    2480             :       // Binding will load asynchronously.
    2481           0 :       return nullptr;
    2482             :     }
    2483             : 
    2484           0 :     if (binding) {
    2485             :       // For backwards compat, keep firing the root's constructor
    2486             :       // after all of its kids' constructors.  So tell the binding
    2487             :       // manager about it right now.
    2488           0 :       mDocument->BindingManager()->AddToAttachedQueue(binding);
    2489             :     }
    2490             : 
    2491           0 :     if (resolveStyle) {
    2492           0 :       computedStyle = mPresShell->StyleSet()->ResolveServoStyle(aDocElement);
    2493           0 :       display = computedStyle->StyleDisplay();
    2494             :     }
    2495             :   }
    2496             : 
    2497             :   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
    2498             : 
    2499           0 :   NS_ASSERTION(!display->IsScrollableOverflow() ||
    2500             :                state.mPresContext->IsPaginated() ||
    2501             :                propagatedScrollFrom == aDocElement,
    2502             :                "Scrollbars should have been propagated to the viewport");
    2503             : 
    2504           0 :   if (MOZ_UNLIKELY(display->mDisplay == StyleDisplay::None)) {
    2505             :     return nullptr;
    2506             :   }
    2507             : 
    2508             :   // Make sure to start any background image loads for the root element now.
    2509           0 :   computedStyle->StartBackgroundImageLoads();
    2510             : 
    2511           0 :   nsFrameConstructorSaveState docElementContainingBlockAbsoluteSaveState;
    2512           0 :   if (mHasRootAbsPosContainingBlock) {
    2513             :     // Push the absolute containing block now so we can absolutely position
    2514             :     // the root element
    2515           0 :     mDocElementContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2516             :     state.PushAbsoluteContainingBlock(mDocElementContainingBlock,
    2517           0 :                                       mDocElementContainingBlock,
    2518           0 :                                       docElementContainingBlockAbsoluteSaveState);
    2519             :   }
    2520             : 
    2521             :   // The rules from CSS 2.1, section 9.2.4, have already been applied
    2522             :   // by the style system, so we can assume that display->mDisplay is
    2523             :   // either NONE, BLOCK, or TABLE.
    2524             : 
    2525             :   // contentFrame is the primary frame for the root element. newFrame
    2526             :   // is the frame that will be the child of the initial containing block.
    2527             :   // These are usually the same frame but they can be different, in
    2528             :   // particular if the root frame is positioned, in which case
    2529             :   // contentFrame is the out-of-flow frame and newFrame is the
    2530             :   // placeholder.
    2531             :   nsContainerFrame* contentFrame;
    2532             :   nsIFrame* newFrame;
    2533           0 :   bool processChildren = false;
    2534             : 
    2535           0 :   nsFrameConstructorSaveState absoluteSaveState;
    2536             : 
    2537             :   // Check whether we need to build a XUL box or SVG root frame
    2538             : #ifdef MOZ_XUL
    2539           0 :   if (aDocElement->IsXULElement()) {
    2540           0 :     contentFrame = NS_NewDocElementBoxFrame(mPresShell, computedStyle);
    2541           0 :     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
    2542           0 :                         contentFrame);
    2543           0 :     newFrame = contentFrame;
    2544           0 :     processChildren = true;
    2545             :   }
    2546             :   else
    2547             : #endif
    2548           0 :   if (aDocElement->IsSVGElement()) {
    2549           0 :     if (!aDocElement->IsSVGElement(nsGkAtoms::svg)) {
    2550           0 :       return nullptr;
    2551             :     }
    2552             :     // We're going to call the right function ourselves, so no need to give a
    2553             :     // function to this FrameConstructionData.
    2554             : 
    2555             :     // XXXbz on the other hand, if we converted this whole function to
    2556             :     // FrameConstructionData/Item, then we'd need the right function
    2557             :     // here... but would probably be able to get away with less code in this
    2558             :     // function in general.
    2559             :     // Use a null PendingBinding, since our binding is not in fact pending.
    2560             :     static const FrameConstructionData rootSVGData = FCDATA_DECL(0, nullptr);
    2561             :     already_AddRefed<ComputedStyle> extraRef =
    2562           0 :       RefPtr<ComputedStyle>(computedStyle).forget();
    2563           0 :     AutoFrameConstructionItem item(this, &rootSVGData, aDocElement,
    2564           0 :                                    nullptr, extraRef, true, nullptr);
    2565             : 
    2566           0 :     nsFrameItems frameItems;
    2567           0 :     contentFrame = static_cast<nsContainerFrame*>(
    2568           0 :       ConstructOuterSVG(state, item, mDocElementContainingBlock,
    2569             :                         computedStyle->StyleDisplay(),
    2570             :                         frameItems));
    2571           0 :     newFrame = frameItems.FirstChild();
    2572           0 :     NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
    2573           0 :   } else if (display->mDisplay == StyleDisplay::Flex ||
    2574           0 :              display->mDisplay == StyleDisplay::WebkitBox ||
    2575           1 :              (StaticPrefs::layout_css_emulate_moz_box_with_flex() &&
    2576           0 :               display->mDisplay == StyleDisplay::MozBox)) {
    2577           0 :     contentFrame = NS_NewFlexContainerFrame(mPresShell, computedStyle);
    2578           0 :     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
    2579           0 :                         contentFrame);
    2580           0 :     newFrame = contentFrame;
    2581           0 :     processChildren = true;
    2582             : 
    2583           0 :     newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2584           0 :     if (display->IsAbsPosContainingBlock(newFrame)) {
    2585             :       state.PushAbsoluteContainingBlock(contentFrame, newFrame,
    2586           0 :                                         absoluteSaveState);
    2587             :     }
    2588             : 
    2589           0 :   } else if (display->mDisplay == StyleDisplay::Grid) {
    2590           0 :     contentFrame = NS_NewGridContainerFrame(mPresShell, computedStyle);
    2591           0 :     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
    2592           0 :                         contentFrame);
    2593           0 :     newFrame = contentFrame;
    2594           0 :     processChildren = true;
    2595             : 
    2596           0 :     newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2597           0 :     if (display->IsAbsPosContainingBlock(newFrame)) {
    2598             :       state.PushAbsoluteContainingBlock(contentFrame, newFrame,
    2599           0 :                                         absoluteSaveState);
    2600             :     }
    2601           0 :   } else if (display->mDisplay == StyleDisplay::Table) {
    2602             :     // We're going to call the right function ourselves, so no need to give a
    2603             :     // function to this FrameConstructionData.
    2604             : 
    2605             :     // XXXbz on the other hand, if we converted this whole function to
    2606             :     // FrameConstructionData/Item, then we'd need the right function
    2607             :     // here... but would probably be able to get away with less code in this
    2608             :     // function in general.
    2609             :     // Use a null PendingBinding, since our binding is not in fact pending.
    2610             :     static const FrameConstructionData rootTableData = FCDATA_DECL(0, nullptr);
    2611             :     already_AddRefed<ComputedStyle> extraRef =
    2612           0 :       RefPtr<ComputedStyle>(computedStyle).forget();
    2613           0 :     AutoFrameConstructionItem item(this, &rootTableData, aDocElement,
    2614           0 :                                    nullptr, extraRef, true, nullptr);
    2615             : 
    2616           0 :     nsFrameItems frameItems;
    2617             :     // if the document is a table then just populate it.
    2618           0 :     contentFrame = static_cast<nsContainerFrame*>(
    2619           0 :       ConstructTable(state, item, mDocElementContainingBlock,
    2620             :                      computedStyle->StyleDisplay(),
    2621             :                      frameItems));
    2622           0 :     newFrame = frameItems.FirstChild();
    2623           0 :     NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
    2624             :   } else {
    2625           0 :     MOZ_ASSERT(display->mDisplay == StyleDisplay::Block ||
    2626             :                display->mDisplay == StyleDisplay::FlowRoot,
    2627             :                "Unhandled display type for root element");
    2628           0 :     contentFrame = NS_NewBlockFormattingContext(mPresShell, computedStyle);
    2629           0 :     nsFrameItems frameItems;
    2630             :     // Use a null PendingBinding, since our binding is not in fact pending.
    2631           0 :     ConstructBlock(state, aDocElement,
    2632             :                    state.GetGeometricParent(display,
    2633             :                                             mDocElementContainingBlock),
    2634             :                    mDocElementContainingBlock, computedStyle,
    2635             :                    &contentFrame, frameItems,
    2636           0 :                    display->IsAbsPosContainingBlock(contentFrame) ? contentFrame : nullptr,
    2637           0 :                    nullptr);
    2638           0 :     newFrame = frameItems.FirstChild();
    2639           0 :     NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
    2640             :   }
    2641             : 
    2642           0 :   MOZ_ASSERT(newFrame);
    2643           0 :   MOZ_ASSERT(contentFrame);
    2644             : 
    2645           0 :   NS_ASSERTION(processChildren ? !mRootElementFrame :
    2646             :                  mRootElementFrame == contentFrame,
    2647             :                "unexpected mRootElementFrame");
    2648           0 :   mRootElementFrame = contentFrame;
    2649             : 
    2650             :   // Figure out which frame has the main style for the document element,
    2651             :   // assigning it to mRootElementStyleFrame.
    2652             :   // Backgrounds should be propagated from that frame to the viewport.
    2653           0 :   contentFrame->GetParentComputedStyle(&mRootElementStyleFrame);
    2654           0 :   bool isChild = mRootElementStyleFrame &&
    2655           0 :                  mRootElementStyleFrame->GetParent() == contentFrame;
    2656           0 :   if (!isChild) {
    2657           0 :     mRootElementStyleFrame = mRootElementFrame;
    2658             :   }
    2659             : 
    2660           0 :   if (processChildren) {
    2661             :     // Still need to process the child content
    2662           0 :     nsFrameItems childItems;
    2663             : 
    2664           0 :     NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame) &&
    2665             :                  !contentFrame->IsFrameOfType(nsIFrame::eSVG),
    2666             :                  "Only XUL frames should reach here");
    2667             :     // Use a null PendingBinding, since our binding is not in fact pending.
    2668           0 :     ProcessChildren(state, aDocElement, computedStyle, contentFrame, true,
    2669           0 :                     childItems, false, nullptr);
    2670             : 
    2671             :     // Set the initial child lists
    2672           0 :     contentFrame->SetInitialChildList(kPrincipalList, childItems);
    2673             :   }
    2674             : 
    2675             :   // set the primary frame
    2676           0 :   aDocElement->SetPrimaryFrame(contentFrame);
    2677             : 
    2678           0 :   SetInitialSingleChild(mDocElementContainingBlock, newFrame);
    2679             : 
    2680             :   // Create frames for anonymous contents if there is a canvas frame.
    2681           0 :   if (mDocElementContainingBlock->IsCanvasFrame()) {
    2682           0 :     ConstructAnonymousContentForCanvas(state, mDocElementContainingBlock,
    2683           0 :                                        aDocElement);
    2684             :   }
    2685             : 
    2686             :   return newFrame;
    2687             : }
    2688             : 
    2689             : 
    2690             : nsIFrame*
    2691           0 : nsCSSFrameConstructor::ConstructRootFrame()
    2692             : {
    2693           0 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    2694             : 
    2695           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
    2696             : 
    2697             :   // --------- BUILD VIEWPORT -----------
    2698             :   RefPtr<ComputedStyle> viewportPseudoStyle =
    2699           0 :     styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::viewport,
    2700           0 :                                                  nullptr);
    2701             :   ViewportFrame* viewportFrame =
    2702           0 :     NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
    2703             : 
    2704             :   // XXXbz do we _have_ to pass a null content pointer to that frame?
    2705             :   // Would it really kill us to pass in the root element or something?
    2706             :   // What would that break?
    2707           0 :   viewportFrame->Init(nullptr, nullptr, nullptr);
    2708             : 
    2709           0 :   viewportFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2710             : 
    2711             :   // Bind the viewport frame to the root view
    2712           0 :   nsView* rootView = mPresShell->GetViewManager()->GetRootView();
    2713           0 :   viewportFrame->SetView(rootView);
    2714             : 
    2715           0 :   viewportFrame->SyncFrameViewProperties(rootView);
    2716           0 :   nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
    2717           0 :                                          rootView, nullptr, nsContainerFrame::SET_ASYNC);
    2718             : 
    2719             :   // Make it an absolute container for fixed-pos elements
    2720           0 :   viewportFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2721           0 :   viewportFrame->MarkAsAbsoluteContainingBlock();
    2722             : 
    2723           0 :   return viewportFrame;
    2724             : }
    2725             : 
    2726             : void
    2727           0 : nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
    2728             : {
    2729           0 :   MOZ_ASSERT(aDocElement, "No element?");
    2730           0 :   MOZ_ASSERT(!aDocElement->GetParent(), "Not root content?");
    2731           0 :   MOZ_ASSERT(aDocElement->GetUncomposedDoc(), "Not in a document?");
    2732           0 :   MOZ_ASSERT(aDocElement->GetUncomposedDoc()->GetRootElement() ==
    2733             :                   aDocElement, "Not the root of the document?");
    2734             : 
    2735             :   /*
    2736             :     how the root frame hierarchy should look
    2737             : 
    2738             :   Galley presentation, non-XUL, with scrolling:
    2739             : 
    2740             :       ViewportFrame [fixed-cb]
    2741             :         nsHTMLScrollFrame
    2742             :           nsCanvasFrame [abs-cb]
    2743             :             root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2744             :                                 nsTableWrapperFrame, nsPlaceholderFrame)
    2745             : 
    2746             :   Galley presentation, XUL
    2747             : 
    2748             :       ViewportFrame [fixed-cb]
    2749             :         nsRootBoxFrame
    2750             :           root element frame (nsDocElementBoxFrame)
    2751             : 
    2752             :   Print presentation, non-XUL
    2753             : 
    2754             :       ViewportFrame
    2755             :         nsSimplePageSequenceFrame
    2756             :           nsPageFrame
    2757             :             nsPageContentFrame [fixed-cb]
    2758             :               nsCanvasFrame [abs-cb]
    2759             :                 root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2760             :                                     nsTableWrapperFrame, nsPlaceholderFrame)
    2761             : 
    2762             :   Print-preview presentation, non-XUL
    2763             : 
    2764             :       ViewportFrame
    2765             :         nsHTMLScrollFrame
    2766             :           nsSimplePageSequenceFrame
    2767             :             nsPageFrame
    2768             :               nsPageContentFrame [fixed-cb]
    2769             :                 nsCanvasFrame [abs-cb]
    2770             :                   root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2771             :                                       nsTableWrapperFrame, nsPlaceholderFrame)
    2772             : 
    2773             :   Print/print preview of XUL is not supported.
    2774             :   [fixed-cb]: the default containing block for fixed-pos content
    2775             :   [abs-cb]: the default containing block for abs-pos content
    2776             : 
    2777             :   Meaning of nsCSSFrameConstructor fields:
    2778             :     mRootElementFrame is "root element frame".  This is the primary frame for
    2779             :       the root element.
    2780             :     mDocElementContainingBlock is the parent of mRootElementFrame
    2781             :       (i.e. nsCanvasFrame or nsRootBoxFrame)
    2782             : 
    2783             :     mPageSequenceFrame is the nsSimplePageSequenceFrame, or null if there isn't one
    2784             :   */
    2785             : 
    2786             :   // --------- CREATE ROOT FRAME -------
    2787             : 
    2788             : 
    2789             :   // Create the root frame. The document element's frame is a child of the
    2790             :   // root frame.
    2791             :   //
    2792             :   // The root frame serves two purposes:
    2793             :   // - reserves space for any margins needed for the document element's frame
    2794             :   // - renders the document element's background. This ensures the background covers
    2795             :   //   the entire canvas as specified by the CSS2 spec
    2796             : 
    2797           0 :   nsPresContext* presContext = mPresShell->GetPresContext();
    2798           0 :   bool isPaginated = presContext->IsRootPaginatedDocument();
    2799           0 :   nsContainerFrame* viewportFrame = static_cast<nsContainerFrame*>(GetRootFrame());
    2800           0 :   ComputedStyle* viewportPseudoStyle = viewportFrame->Style();
    2801             : 
    2802           0 :   nsContainerFrame* rootFrame = nullptr;
    2803             :   nsAtom* rootPseudo;
    2804             : 
    2805           0 :   if (!isPaginated) {
    2806             : #ifdef MOZ_XUL
    2807           0 :     if (aDocElement->IsXULElement())
    2808             :     {
    2809             :       // pass a temporary stylecontext, the correct one will be set later
    2810           0 :       rootFrame = NS_NewRootBoxFrame(mPresShell, viewportPseudoStyle);
    2811             :     } else
    2812             : #endif
    2813             :     {
    2814             :       // pass a temporary stylecontext, the correct one will be set later
    2815           0 :       rootFrame = NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
    2816           0 :       mHasRootAbsPosContainingBlock = true;
    2817             :     }
    2818             : 
    2819           0 :     rootPseudo = nsCSSAnonBoxes::canvas;
    2820           0 :     mDocElementContainingBlock = rootFrame;
    2821             :   } else {
    2822             :     // Create a page sequence frame
    2823           0 :     rootFrame = NS_NewSimplePageSequenceFrame(mPresShell, viewportPseudoStyle);
    2824           0 :     mPageSequenceFrame = rootFrame;
    2825           0 :     rootPseudo = nsCSSAnonBoxes::pageSequence;
    2826           0 :     rootFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2827             :   }
    2828             : 
    2829             : 
    2830             :   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
    2831             : 
    2832             :   // If the device supports scrolling (e.g., in galley mode on the screen and
    2833             :   // for print-preview, but not when printing), then create a scroll frame that
    2834             :   // will act as the scrolling mechanism for the viewport.
    2835             :   // XXX Do we even need a viewport when printing to a printer?
    2836             : 
    2837           0 :   bool isHTML = aDocElement->IsHTMLElement();
    2838           0 :   bool isXUL = false;
    2839             : 
    2840           0 :   if (!isHTML) {
    2841           0 :     isXUL = aDocElement->IsXULElement();
    2842             :   }
    2843             : 
    2844             :   // Never create scrollbars for XUL documents
    2845           0 :   bool isScrollable = isPaginated ? presContext->HasPaginatedScrolling() : !isXUL;
    2846             : 
    2847             :   // We no longer need to do overflow propagation here. It's taken care of
    2848             :   // when we construct frames for the element whose overflow might be
    2849             :   // propagated
    2850           0 :   NS_ASSERTION(!isScrollable || !isXUL,
    2851             :                "XUL documents should never be scrollable - see above");
    2852             : 
    2853           0 :   nsContainerFrame* newFrame = rootFrame;
    2854           0 :   RefPtr<ComputedStyle> rootPseudoStyle;
    2855             :   // we must create a state because if the scrollbars are GFX it needs the
    2856             :   // state to build the scrollbar frames.
    2857           0 :   nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
    2858             : 
    2859             :   // Start off with the viewport as parent; we'll adjust it as needed.
    2860           0 :   nsContainerFrame* parentFrame = viewportFrame;
    2861             : 
    2862           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
    2863             :   // If paginated, make sure we don't put scrollbars in
    2864           0 :   if (!isScrollable) {
    2865             :     rootPseudoStyle =
    2866           0 :       styleSet->ResolveInheritingAnonymousBoxStyle(rootPseudo,
    2867           0 :                                                    viewportPseudoStyle);
    2868             :   } else {
    2869           0 :       if (rootPseudo == nsCSSAnonBoxes::canvas) {
    2870           0 :         rootPseudo = nsCSSAnonBoxes::scrolledCanvas;
    2871             :       } else {
    2872           0 :         NS_ASSERTION(rootPseudo == nsCSSAnonBoxes::pageSequence,
    2873             :                      "Unknown root pseudo");
    2874           0 :         rootPseudo = nsCSSAnonBoxes::scrolledPageSequence;
    2875             :       }
    2876             : 
    2877             :       // Build the frame. We give it the content we are wrapping which is the
    2878             :       // document element, the root frame, the parent view port frame, and we
    2879             :       // should get back the new frame and the scrollable view if one was
    2880             :       // created.
    2881             : 
    2882             :       // resolve a context for the scrollframe
    2883             :       RefPtr<ComputedStyle>  computedStyle =
    2884           0 :         styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::viewportScroll,
    2885           0 :                                                      viewportPseudoStyle);
    2886             : 
    2887             :       // Note that the viewport scrollframe is always built with
    2888             :       // overflow:auto style. This forces the scroll frame to create
    2889             :       // anonymous content for both scrollbars. This is necessary even
    2890             :       // if the HTML or BODY elements are overriding the viewport
    2891             :       // scroll style to 'hidden' --- dynamic style changes might put
    2892             :       // scrollbars back on the viewport and we don't want to have to
    2893             :       // reframe the viewport to create the scrollbar content.
    2894           0 :       newFrame = nullptr;
    2895           0 :       rootPseudoStyle = BeginBuildingScrollFrame( state,
    2896             :                                                   aDocElement,
    2897             :                                                   computedStyle,
    2898             :                                                   viewportFrame,
    2899             :                                                   rootPseudo,
    2900             :                                                   true,
    2901           0 :                                                   newFrame);
    2902           0 :       parentFrame = newFrame;
    2903             :   }
    2904             : 
    2905           0 :   rootFrame->SetComputedStyleWithoutNotification(rootPseudoStyle);
    2906           0 :   rootFrame->Init(aDocElement, parentFrame, nullptr);
    2907             : 
    2908           0 :   if (isScrollable) {
    2909           0 :     FinishBuildingScrollFrame(parentFrame, rootFrame);
    2910             :   }
    2911             : 
    2912           0 :   if (isPaginated) {
    2913             :     // Create the first page
    2914             :     // Set the initial child lists
    2915             :     nsContainerFrame* canvasFrame;
    2916             :     nsContainerFrame* pageFrame =
    2917           0 :       ConstructPageFrame(mPresShell, rootFrame, nullptr, canvasFrame);
    2918           0 :     pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2919           0 :     SetInitialSingleChild(rootFrame, pageFrame);
    2920             : 
    2921             :     // The eventual parent of the document element frame.
    2922             :     // XXX should this be set for every new page (in ConstructPageFrame)?
    2923           0 :     mDocElementContainingBlock = canvasFrame;
    2924           0 :     mHasRootAbsPosContainingBlock = true;
    2925             :   }
    2926             : 
    2927           0 :   if (viewportFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
    2928           0 :     SetInitialSingleChild(viewportFrame, newFrame);
    2929             :   } else {
    2930           0 :     nsFrameList newFrameList(newFrame, newFrame);
    2931           0 :     viewportFrame->AppendFrames(kPrincipalList, newFrameList);
    2932             :   }
    2933           0 : }
    2934             : 
    2935             : void
    2936           0 : nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
    2937             :                                                           nsIFrame* aFrame,
    2938             :                                                           nsIContent* aDocElement)
    2939             : {
    2940           0 :   NS_ASSERTION(aFrame->IsCanvasFrame(), "aFrame should be canvas frame!");
    2941             : 
    2942           0 :   AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
    2943           0 :   GetAnonymousContent(aDocElement, aFrame, anonymousItems);
    2944           0 :   if (anonymousItems.IsEmpty()) {
    2945           0 :     return;
    2946             :   }
    2947             : 
    2948           0 :   AutoFrameConstructionItemList itemsToConstruct(this);
    2949           0 :   nsContainerFrame* frameAsContainer = do_QueryFrame(aFrame);
    2950           0 :   AddFCItemsForAnonymousContent(aState, frameAsContainer, anonymousItems, itemsToConstruct);
    2951             : 
    2952           0 :   nsFrameItems frameItems;
    2953             :   ConstructFramesFromItemList(aState, itemsToConstruct, frameAsContainer,
    2954             :                               /* aParentIsWrapperAnonBox = */ false,
    2955           0 :                               frameItems);
    2956           0 :   frameAsContainer->AppendFrames(kPrincipalList, frameItems);
    2957             : }
    2958             : 
    2959             : nsContainerFrame*
    2960           0 : nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell*  aPresShell,
    2961             :                                           nsContainerFrame* aParentFrame,
    2962             :                                           nsIFrame*      aPrevPageFrame,
    2963             :                                           nsContainerFrame*& aCanvasFrame)
    2964             : {
    2965           0 :   ComputedStyle* parentComputedStyle = aParentFrame->Style();
    2966           0 :   ServoStyleSet* styleSet = aPresShell->StyleSet();
    2967             : 
    2968           0 :   RefPtr<ComputedStyle> pagePseudoStyle;
    2969             :   pagePseudoStyle =
    2970           0 :     styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::page,
    2971           0 :                                                  parentComputedStyle);
    2972             : 
    2973           0 :   nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
    2974             : 
    2975             :   // Initialize the page frame and force it to have a view. This makes printing of
    2976             :   // the pages easier and faster.
    2977           0 :   pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
    2978             : 
    2979           0 :   RefPtr<ComputedStyle> pageContentPseudoStyle;
    2980             :   pageContentPseudoStyle =
    2981           0 :     styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::pageContent,
    2982           0 :                                                  pagePseudoStyle);
    2983             : 
    2984             :   nsContainerFrame* pageContentFrame =
    2985           0 :     NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
    2986             : 
    2987             :   // Initialize the page content frame and force it to have a view. Also make it the
    2988             :   // containing block for fixed elements which are repeated on every page.
    2989           0 :   nsIFrame* prevPageContentFrame = nullptr;
    2990           0 :   if (aPrevPageFrame) {
    2991           0 :     prevPageContentFrame = aPrevPageFrame->PrincipalChildList().FirstChild();
    2992           0 :     NS_ASSERTION(prevPageContentFrame, "missing page content frame");
    2993             :   }
    2994           0 :   pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
    2995           0 :   if (!prevPageContentFrame) {
    2996           0 :     pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2997             :   }
    2998           0 :   SetInitialSingleChild(pageFrame, pageContentFrame);
    2999             :   // Make it an absolute container for fixed-pos elements
    3000           0 :   pageContentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    3001           0 :   pageContentFrame->MarkAsAbsoluteContainingBlock();
    3002             : 
    3003           0 :   RefPtr<ComputedStyle> canvasPseudoStyle;
    3004             :   canvasPseudoStyle =
    3005           0 :     styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::canvas,
    3006           0 :                                                  pageContentPseudoStyle);
    3007             : 
    3008           0 :   aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
    3009             : 
    3010           0 :   nsIFrame* prevCanvasFrame = nullptr;
    3011           0 :   if (prevPageContentFrame) {
    3012           0 :     prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
    3013           0 :     NS_ASSERTION(prevCanvasFrame, "missing canvas frame");
    3014             :   }
    3015           0 :   aCanvasFrame->Init(nullptr, pageContentFrame, prevCanvasFrame);
    3016           0 :   SetInitialSingleChild(pageContentFrame, aCanvasFrame);
    3017           0 :   return pageFrame;
    3018             : }
    3019             : 
    3020             : /* static */
    3021             : nsIFrame*
    3022           0 : nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell*     aPresShell,
    3023             :                                                  nsIContent*       aContent,
    3024             :                                                  nsIFrame*         aFrame,
    3025             :                                                  nsContainerFrame* aParentFrame,
    3026             :                                                  nsIFrame*         aPrevInFlow,
    3027             :                                                  nsFrameState      aTypeBit)
    3028             : {
    3029             :   RefPtr<ComputedStyle> placeholderStyle = aPresShell->StyleSet()->
    3030           0 :     ResolveStyleForPlaceholder();
    3031             : 
    3032             :   // The placeholder frame gets a pseudo style.
    3033             :   nsPlaceholderFrame* placeholderFrame =
    3034           0 :     (nsPlaceholderFrame*)NS_NewPlaceholderFrame(aPresShell, placeholderStyle,
    3035           0 :                                                 aTypeBit);
    3036             : 
    3037           0 :   placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow);
    3038             : 
    3039             :   // Associate the placeholder/out-of-flow with each other.
    3040           0 :   placeholderFrame->SetOutOfFlowFrame(aFrame);
    3041           0 :   aFrame->SetProperty(nsIFrame::PlaceholderFrameProperty(), placeholderFrame);
    3042             : 
    3043           0 :   aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
    3044             : 
    3045           0 :   return placeholderFrame;
    3046             : }
    3047             : 
    3048             : // Clears any lazy bits set in the range [aStartContent, aEndContent).  If
    3049             : // aEndContent is null, that means to clear bits in all siblings starting with
    3050             : // aStartContent.  aStartContent must not be null unless aEndContent is also
    3051             : // null.  We do this so that when new children are inserted under elements whose
    3052             : // frame is a leaf the new children don't cause us to try to construct frames
    3053             : // for the existing children again.
    3054             : static inline void
    3055           0 : ClearLazyBits(nsIContent* aStartContent, nsIContent* aEndContent)
    3056             : {
    3057           0 :   MOZ_ASSERT(aStartContent || !aEndContent,
    3058             :              "Must have start child if we have an end child");
    3059             : 
    3060           0 :   for (nsIContent* cur = aStartContent; cur != aEndContent;
    3061           0 :        cur = cur->GetNextSibling()) {
    3062           0 :     cur->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
    3063             :   }
    3064           0 : }
    3065             : 
    3066             : nsIFrame*
    3067           0 : nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
    3068             :                                             FrameConstructionItem&   aItem,
    3069             :                                             nsContainerFrame*        aParentFrame,
    3070             :                                             const nsStyleDisplay*    aStyleDisplay,
    3071             :                                             nsFrameItems&            aFrameItems)
    3072             : {
    3073           0 :   nsIContent* const content = aItem.mContent;
    3074           0 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    3075             : 
    3076             :   // Construct a frame-based listbox or combobox
    3077           0 :   dom::HTMLSelectElement* sel = dom::HTMLSelectElement::FromNode(content);
    3078           0 :   MOZ_ASSERT(sel);
    3079           0 :   if (sel->IsCombobox()) {
    3080             :     // Construct a frame-based combo box.
    3081             :     // The frame-based combo box is built out of three parts. A display area, a button and
    3082             :     // a dropdown list. The display area and button are created through anonymous content.
    3083             :     // The drop-down list's frame is created explicitly. The combobox frame shares its content
    3084             :     // with the drop-down list.
    3085           0 :     nsFrameState flags = NS_BLOCK_FLOAT_MGR;
    3086             :     nsComboboxControlFrame* comboboxFrame =
    3087           0 :       NS_NewComboboxControlFrame(mPresShell, computedStyle, flags);
    3088             : 
    3089             :     // Save the history state so we don't restore during construction
    3090             :     // since the complete tree is required before we restore.
    3091           0 :     nsILayoutHistoryState *historyState = aState.mFrameState;
    3092           0 :     aState.mFrameState = nullptr;
    3093             :     // Initialize the combobox frame
    3094           0 :     InitAndRestoreFrame(aState, content,
    3095             :                         aState.GetGeometricParent(aStyleDisplay, aParentFrame),
    3096           0 :                         comboboxFrame);
    3097             : 
    3098           0 :     comboboxFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    3099             : 
    3100           0 :     aState.AddChild(comboboxFrame, aFrameItems, content, aParentFrame);
    3101             : 
    3102             :     // Resolve pseudo element style for the dropdown list
    3103           0 :     RefPtr<ComputedStyle> listStyle;
    3104           0 :     listStyle = mPresShell->StyleSet()->
    3105           0 :       ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::dropDownList,
    3106           0 :                                          computedStyle);
    3107             : 
    3108             :     // Create a listbox
    3109           0 :     nsContainerFrame* listFrame = NS_NewListControlFrame(mPresShell, listStyle);
    3110             : 
    3111             :     // Notify the listbox that it is being used as a dropdown list.
    3112           0 :     nsIListControlFrame * listControlFrame = do_QueryFrame(listFrame);
    3113           0 :     if (listControlFrame) {
    3114           0 :       listControlFrame->SetComboboxFrame(comboboxFrame);
    3115             :     }
    3116             :     // Notify combobox that it should use the listbox as it's popup
    3117           0 :     comboboxFrame->SetDropDown(listFrame);
    3118             : 
    3119           0 :     if (!nsLayoutUtils::IsContentSelectEnabled()) {
    3120             :       // TODO(kuoe0) Remove this assertion when content-select is shipped.
    3121           0 :       NS_ASSERTION(!listFrame->IsAbsPosContainingBlock(),
    3122             :                    "Ended up with positioned dropdown list somehow.");
    3123             :     }
    3124           0 :     NS_ASSERTION(!listFrame->IsFloating(),
    3125             :                  "Ended up with floating dropdown list somehow.");
    3126             : 
    3127             :     // child frames of combobox frame
    3128           0 :     nsFrameItems childItems;
    3129             : 
    3130             :     // Initialize the scroll frame positioned. Note that it is NOT
    3131             :     // initialized as absolutely positioned.
    3132             :     nsContainerFrame* scrolledFrame =
    3133           0 :       NS_NewSelectsAreaFrame(mPresShell, computedStyle, flags);
    3134             : 
    3135           0 :     InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
    3136             :                           comboboxFrame, listStyle, true,
    3137           0 :                           aItem.mPendingBinding, childItems);
    3138             : 
    3139           0 :     if (!nsLayoutUtils::IsContentSelectEnabled()) {
    3140             :       // TODO(kuoe0) Remove this assertion when content-select is shipped.
    3141           0 :       NS_ASSERTION(listFrame->GetView(), "ListFrame's view is nullptr");
    3142             :     }
    3143             : 
    3144             :     // Create display and button frames from the combobox's anonymous content.
    3145             :     // The anonymous content is appended to existing anonymous content for this
    3146             :     // element (the scrollbars).
    3147             :     //
    3148             :     // nsComboboxControlFrame needs special frame creation behavior for its first
    3149             :     // piece of anonymous content, which means that we can't take the normal
    3150             :     // ProcessChildren path.
    3151           0 :     AutoTArray<nsIAnonymousContentCreator::ContentInfo, 2> newAnonymousItems;
    3152           0 :     DebugOnly<nsresult> rv = GetAnonymousContent(content, comboboxFrame, newAnonymousItems);
    3153           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3154           0 :     MOZ_ASSERT(newAnonymousItems.Length() == 2);
    3155             : 
    3156             :     // Manually create a frame for the special NAC.
    3157           0 :     MOZ_ASSERT(newAnonymousItems[0].mContent == comboboxFrame->GetDisplayNode());
    3158           0 :     newAnonymousItems.RemoveElementAt(0);
    3159           0 :     nsIFrame* customFrame = comboboxFrame->CreateFrameForDisplayNode();
    3160           0 :     MOZ_ASSERT(customFrame);
    3161           0 :     customFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
    3162           0 :     childItems.AddChild(customFrame);
    3163             : 
    3164             :     // The other piece of NAC can take the normal path.
    3165           0 :     AutoFrameConstructionItemList fcItems(this);
    3166             :     AddFCItemsForAnonymousContent(aState, comboboxFrame, newAnonymousItems,
    3167           0 :                                   fcItems);
    3168             :     ConstructFramesFromItemList(aState, fcItems, comboboxFrame,
    3169             :                                 /* aParentIsWrapperAnonBox = */ false,
    3170           0 :                                 childItems);
    3171             : 
    3172           0 :     comboboxFrame->SetInitialChildList(kPrincipalList, childItems);
    3173             : 
    3174           0 :     if (!nsLayoutUtils::IsContentSelectEnabled()) {
    3175             :       // Initialize the additional popup child list which contains the
    3176             :       // dropdown list frame.
    3177           0 :       nsFrameItems popupItems;
    3178           0 :       popupItems.AddChild(listFrame);
    3179             :       comboboxFrame->SetInitialChildList(nsIFrame::kSelectPopupList,
    3180           0 :                                          popupItems);
    3181             :     }
    3182             : 
    3183           0 :     aState.mFrameState = historyState;
    3184           0 :     if (aState.mFrameState) {
    3185             :       // Restore frame state for the entire subtree of |comboboxFrame|.
    3186           0 :       RestoreFrameState(comboboxFrame, aState.mFrameState);
    3187             :     }
    3188             :     return comboboxFrame;
    3189             :   }
    3190             : 
    3191             :   // Listbox, not combobox
    3192             :   nsContainerFrame* listFrame =
    3193           0 :     NS_NewListControlFrame(mPresShell, computedStyle);
    3194             : 
    3195           0 :   nsContainerFrame* scrolledFrame = NS_NewSelectsAreaFrame(
    3196           0 :       mPresShell, computedStyle, NS_BLOCK_FLOAT_MGR);
    3197             : 
    3198             :   // ******* this code stolen from Initialze ScrollFrame ********
    3199             :   // please adjust this code to use BuildScrollFrame.
    3200             : 
    3201           0 :   InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
    3202             :                         aParentFrame, computedStyle, false,
    3203           0 :                         aItem.mPendingBinding, aFrameItems);
    3204             : 
    3205           0 :   return listFrame;
    3206             : }
    3207             : 
    3208             : /**
    3209             :  * Used to be InitializeScrollFrame but now it's only used for the select tag
    3210             :  * But the select tag should really be fixed to use GFX scrollbars that can
    3211             :  * be create with BuildScrollFrame.
    3212             :  */
    3213             : void
    3214           0 : nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
    3215             :                                              nsContainerFrame*        scrollFrame,
    3216             :                                              nsContainerFrame*        scrolledFrame,
    3217             :                                              nsIContent*              aContent,
    3218             :                                              nsContainerFrame*        aParentFrame,
    3219             :                                              ComputedStyle*          aComputedStyle,
    3220             :                                              bool                     aBuildCombobox,
    3221             :                                              PendingBinding*          aPendingBinding,
    3222             :                                              nsFrameItems&            aFrameItems)
    3223             : {
    3224             :   // Initialize it
    3225             :   nsContainerFrame* geometricParent =
    3226           0 :     aState.GetGeometricParent(aComputedStyle->StyleDisplay(), aParentFrame);
    3227             : 
    3228             :   // We don't call InitAndRestoreFrame for scrollFrame because we can only
    3229             :   // restore the frame state after its parts have been created (in particular,
    3230             :   // the scrollable view). So we have to split Init and Restore.
    3231             : 
    3232           0 :   scrollFrame->Init(aContent, geometricParent, nullptr);
    3233             : 
    3234           0 :   if (!aBuildCombobox || nsLayoutUtils::IsContentSelectEnabled()) {
    3235           0 :     aState.AddChild(scrollFrame, aFrameItems, aContent, aParentFrame);
    3236             :   }
    3237             : 
    3238             :   BuildScrollFrame(aState, aContent, aComputedStyle, scrolledFrame,
    3239           0 :                    geometricParent, scrollFrame);
    3240             : 
    3241           0 :   if (aState.mFrameState) {
    3242             :     // Restore frame state for the scroll frame
    3243           0 :     RestoreFrameStateFor(scrollFrame, aState.mFrameState);
    3244             :   }
    3245             : 
    3246             :   // Process children
    3247           0 :   nsFrameItems                childItems;
    3248             : 
    3249             :   ProcessChildren(aState, aContent, aComputedStyle, scrolledFrame, false,
    3250           0 :                   childItems, false, aPendingBinding);
    3251             : 
    3252             :   // Set the scrolled frame's initial child lists
    3253           0 :   scrolledFrame->SetInitialChildList(kPrincipalList, childItems);
    3254           0 : }
    3255             : 
    3256             : nsIFrame*
    3257           0 : nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
    3258             :                                               FrameConstructionItem&   aItem,
    3259             :                                               nsContainerFrame*        aParentFrame,
    3260             :                                               const nsStyleDisplay*    aStyleDisplay,
    3261             :                                               nsFrameItems&            aFrameItems)
    3262             : {
    3263           0 :   nsIContent* const content = aItem.mContent;
    3264           0 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    3265             : 
    3266             :   nsContainerFrame* fieldsetFrame =
    3267           0 :     NS_NewFieldSetFrame(mPresShell, computedStyle);
    3268             : 
    3269             :   // Initialize it
    3270           0 :   InitAndRestoreFrame(aState, content,
    3271             :                       aState.GetGeometricParent(aStyleDisplay, aParentFrame),
    3272           0 :                       fieldsetFrame);
    3273             : 
    3274           0 :   fieldsetFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    3275             : 
    3276             :   // Resolve style and initialize the frame
    3277           0 :   RefPtr<ComputedStyle> fieldsetContentStyle;
    3278           0 :   fieldsetContentStyle = mPresShell->StyleSet()->
    3279           0 :     ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::fieldsetContent,
    3280           0 :                                        computedStyle);
    3281             : 
    3282           0 :   const nsStyleDisplay* fieldsetContentDisplay = fieldsetContentStyle->StyleDisplay();
    3283           0 :   bool isScrollable = fieldsetContentDisplay->IsScrollableOverflow();
    3284           0 :   nsContainerFrame* scrollFrame = nullptr;
    3285           0 :   if (isScrollable) {
    3286             :     fieldsetContentStyle =
    3287           0 :       BeginBuildingScrollFrame(aState, content, fieldsetContentStyle,
    3288             :                                fieldsetFrame, nsCSSAnonBoxes::scrolledContent,
    3289           0 :                                false, scrollFrame);
    3290             :   }
    3291             : 
    3292           0 :   nsContainerFrame* absPosContainer = nullptr;
    3293           0 :   if (fieldsetFrame->IsAbsPosContainingBlock()) {
    3294           0 :     absPosContainer = fieldsetFrame;
    3295             :   }
    3296             : 
    3297             :   // Create the inner ::-moz-fieldset-content frame.
    3298             :   nsContainerFrame* contentFrameTop;
    3299             :   nsContainerFrame* contentFrame;
    3300           0 :   auto parent = scrollFrame ? scrollFrame : fieldsetFrame;
    3301           0 :   switch (fieldsetContentDisplay->mDisplay) {
    3302             :     case StyleDisplay::Flex:
    3303           0 :       contentFrame = NS_NewFlexContainerFrame(mPresShell, fieldsetContentStyle);
    3304           0 :       InitAndRestoreFrame(aState, content, parent, contentFrame);
    3305           0 :       contentFrameTop = contentFrame;
    3306           0 :       break;
    3307             :     case StyleDisplay::Grid:
    3308           0 :       contentFrame = NS_NewGridContainerFrame(mPresShell, fieldsetContentStyle);
    3309           0 :       InitAndRestoreFrame(aState, content, parent, contentFrame);
    3310           0 :       contentFrameTop = contentFrame;
    3311           0 :       break;
    3312             :     default: {
    3313           0 :       MOZ_ASSERT(fieldsetContentDisplay->mDisplay == StyleDisplay::Block,
    3314             :                  "bug in nsRuleNode::ComputeDisplayData?");
    3315             : 
    3316           0 :       nsContainerFrame* columnSetFrame = nullptr;
    3317           0 :       RefPtr<ComputedStyle> innerSC = fieldsetContentStyle;
    3318           0 :       const nsStyleColumn* columns = fieldsetContentStyle->StyleColumn();
    3319           0 :       if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
    3320           0 :           columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
    3321             :         columnSetFrame =
    3322           0 :           NS_NewColumnSetFrame(mPresShell, fieldsetContentStyle,
    3323           0 :                                nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
    3324           0 :         InitAndRestoreFrame(aState, content, parent, columnSetFrame);
    3325           0 :         innerSC = mPresShell->StyleSet()->
    3326           0 :           ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::columnContent,
    3327           0 :                                              fieldsetContentStyle);
    3328           0 :         if (absPosContainer) {
    3329           0 :           absPosContainer = columnSetFrame;
    3330             :         }
    3331             :       }
    3332           0 :       contentFrame = NS_NewBlockFormattingContext(mPresShell, innerSC);
    3333           0 :       if (columnSetFrame) {
    3334           0 :         InitAndRestoreFrame(aState, content, columnSetFrame, contentFrame);
    3335           0 :         SetInitialSingleChild(columnSetFrame, contentFrame);
    3336           0 :         contentFrameTop = columnSetFrame;
    3337             :       } else {
    3338           0 :         InitAndRestoreFrame(aState, content, parent, contentFrame);
    3339           0 :         contentFrameTop = contentFrame;
    3340             :       }
    3341             :       break;
    3342             :     }
    3343             :   }
    3344             : 
    3345           0 :   aState.AddChild(fieldsetFrame, aFrameItems, content, aParentFrame);
    3346             : 
    3347             :   // Process children
    3348           0 :   nsFrameConstructorSaveState absoluteSaveState;
    3349           0 :   nsFrameItems                childItems;
    3350             : 
    3351           0 :   contentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    3352           0 :   if (absPosContainer) {
    3353           0 :     aState.PushAbsoluteContainingBlock(contentFrame, absPosContainer, absoluteSaveState);
    3354             :   }
    3355             : 
    3356           0 :   ProcessChildren(aState, content, computedStyle, contentFrame, true,
    3357           0 :                   childItems, true, aItem.mPendingBinding);
    3358             : 
    3359           0 :   nsFrameItems fieldsetKids;
    3360           0 :   fieldsetKids.AddChild(scrollFrame ? scrollFrame : contentFrameTop);
    3361             : 
    3362           0 :   for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
    3363           0 :     nsIFrame* child = e.get();
    3364           0 :     nsContainerFrame* cif = child->GetContentInsertionFrame();
    3365           0 :     if (cif && cif->IsLegendFrame()) {
    3366             :       // We want the legend to be the first frame in the fieldset child list.
    3367             :       // That way the EventStateManager will do the right thing when tabbing
    3368             :       // from a selection point within the legend (bug 236071), which is
    3369             :       // used for implementing legend access keys (bug 81481).
    3370             :       // GetAdjustedParentFrame() below depends on this frame order.
    3371           0 :       childItems.RemoveFrame(child);
    3372             :       // Make sure to reparent the legend so it has the fieldset as the parent.
    3373           0 :       fieldsetKids.InsertFrame(fieldsetFrame, nullptr, child);
    3374           0 :       if (scrollFrame) {
    3375             :         StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary(
    3376           0 :             child, contentFrame);
    3377             :       }
    3378             :       break;
    3379             :     }
    3380             :   }
    3381             : 
    3382           0 :   if (isScrollable) {
    3383           0 :     FinishBuildingScrollFrame(scrollFrame, contentFrameTop);
    3384             :   }
    3385             : 
    3386             :   // Set the inner frame's initial child lists
    3387           0 :   contentFrame->SetInitialChildList(kPrincipalList, childItems);
    3388             : 
    3389             :   // Set the outer frame's initial child list
    3390           0 :   fieldsetFrame->SetInitialChildList(kPrincipalList, fieldsetKids);
    3391             : 
    3392             :   // Our new frame returned is the outer frame, which is the fieldset frame.
    3393           0 :   return fieldsetFrame;
    3394             : }
    3395             : 
    3396             : nsIFrame*
    3397           0 : nsCSSFrameConstructor::ConstructDetailsFrame(nsFrameConstructorState& aState,
    3398             :                                              FrameConstructionItem& aItem,
    3399             :                                              nsContainerFrame* aParentFrame,
    3400             :                                              const nsStyleDisplay* aStyleDisplay,
    3401             :                                              nsFrameItems& aFrameItems)
    3402             : {
    3403           0 :   if (!aStyleDisplay->IsScrollableOverflow()) {
    3404             :     return ConstructNonScrollableBlockWithConstructor(aState, aItem, aParentFrame,
    3405             :                                                       aStyleDisplay, aFrameItems,
    3406           0 :                                                       NS_NewDetailsFrame);
    3407             :   }
    3408             : 
    3409             :   // Build a scroll frame to wrap details frame if necessary.
    3410             :   return ConstructScrollableBlockWithConstructor(aState, aItem, aParentFrame,
    3411             :                                                  aStyleDisplay, aFrameItems,
    3412           0 :                                                  NS_NewDetailsFrame);
    3413             : }
    3414             : 
    3415             : static nsIFrame*
    3416           0 : FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame)
    3417             : {
    3418           0 :   for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) {
    3419           0 :     NS_ASSERTION(f->IsGeneratedContentFrame(),
    3420             :                  "should not have exited generated content");
    3421           0 :     nsAtom* pseudo = f->Style()->GetPseudo();
    3422           0 :     if (pseudo == nsCSSPseudoElements::before ||
    3423           0 :         pseudo == nsCSSPseudoElements::after)
    3424             :       return f;
    3425             :   }
    3426             :   return nullptr;
    3427             : }
    3428             : 
    3429             : #define SIMPLE_FCDATA(_func) FCDATA_DECL(0, _func)
    3430             : #define FULL_CTOR_FCDATA(_flags, _func)                             \
    3431             :   { _flags | FCDATA_FUNC_IS_FULL_CTOR, { nullptr }, _func, nullptr }
    3432             : 
    3433             : /* static */
    3434             : const nsCSSFrameConstructor::FrameConstructionData*
    3435           0 : nsCSSFrameConstructor::FindTextData(nsIFrame* aParentFrame,
    3436             :                                     nsIContent* aTextContent)
    3437             : {
    3438           0 :   MOZ_ASSERT(aTextContent, "How?");
    3439           0 :   if (aParentFrame && IsFrameForSVG(aParentFrame)) {
    3440             :     nsIFrame* ancestorFrame =
    3441           0 :       nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
    3442           0 :     if (!ancestorFrame || !nsSVGUtils::IsInSVGTextSubtree(ancestorFrame)) {
    3443             :       return nullptr;
    3444             :     }
    3445             : 
    3446             :     // Don't render stuff in display: contents / Shadow DOM subtrees, because
    3447             :     // TextCorrespondenceRecorder in the SVG text code doesn't really know how
    3448             :     // to deal with it. This kinda sucks. :(
    3449           0 :     if (aParentFrame->GetContent() != aTextContent->GetParent()) {
    3450             :       return nullptr;
    3451             :     }
    3452             : 
    3453             :     static const FrameConstructionData sSVGTextData =
    3454             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | FCDATA_IS_SVG_TEXT,
    3455             :                   NS_NewTextFrame);
    3456           0 :     return &sSVGTextData;
    3457             :   }
    3458             : 
    3459             :   static const FrameConstructionData sTextData =
    3460             :     FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT, NS_NewTextFrame);
    3461             :   return &sTextData;
    3462             : }
    3463             : 
    3464             : void
    3465           0 : nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
    3466             :                                           nsFrameConstructorState& aState,
    3467             :                                           nsIContent*              aContent,
    3468             :                                           nsContainerFrame*        aParentFrame,
    3469             :                                           ComputedStyle*          aComputedStyle,
    3470             :                                           nsFrameItems&            aFrameItems)
    3471             : {
    3472           0 :   MOZ_ASSERT(aData, "Must have frame construction data");
    3473             : 
    3474           0 :   nsIFrame* newFrame = (*aData->mFunc.mCreationFunc)(mPresShell, aComputedStyle);
    3475             : 
    3476           0 :   InitAndRestoreFrame(aState, aContent, aParentFrame, newFrame);
    3477             : 
    3478             :   // We never need to create a view for a text frame.
    3479             : 
    3480           0 :   if (newFrame->IsGeneratedContentFrame()) {
    3481           0 :     nsAutoPtr<nsGenConInitializer> initializer;
    3482             :     initializer =
    3483             :       static_cast<nsGenConInitializer*>(
    3484           0 :         aContent->UnsetProperty(nsGkAtoms::genConInitializerProperty));
    3485           0 :     if (initializer) {
    3486           0 :       if (initializer->mNode->InitTextFrame(initializer->mList,
    3487           0 :               FindAncestorWithGeneratedContentPseudo(newFrame), newFrame)) {
    3488           0 :         (this->*(initializer->mDirtyAll))();
    3489             :       }
    3490           0 :       initializer->mNode.forget();
    3491             :     }
    3492             :   }
    3493             : 
    3494             :   // Add the newly constructed frame to the flow
    3495           0 :   aFrameItems.AddChild(newFrame);
    3496             : 
    3497           0 :   if (!aState.mCreatingExtraFrames)
    3498           0 :     aContent->SetPrimaryFrame(newFrame);
    3499           0 : }
    3500             : 
    3501             : /* static */
    3502             : const nsCSSFrameConstructor::FrameConstructionData*
    3503           0 : nsCSSFrameConstructor::FindDataByInt(int32_t aInt,
    3504             :                                      Element* aElement,
    3505             :                                      ComputedStyle* aComputedStyle,
    3506             :                                      const FrameConstructionDataByInt* aDataPtr,
    3507             :                                      uint32_t aDataLength)
    3508             : {
    3509           0 :   for (const FrameConstructionDataByInt *curData = aDataPtr,
    3510           0 :          *endData = aDataPtr + aDataLength;
    3511           0 :        curData != endData;
    3512             :        ++curData) {
    3513           0 :     if (curData->mInt == aInt) {
    3514           0 :       const FrameConstructionData* data = &curData->mData;
    3515           0 :       if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) {
    3516           0 :         return data->mFunc.mDataGetter(aElement, aComputedStyle);
    3517             :       }
    3518             : 
    3519             :       return data;
    3520             :     }
    3521             :   }
    3522             : 
    3523             :   return nullptr;
    3524             : }
    3525             : 
    3526             : /* static */
    3527             : const nsCSSFrameConstructor::FrameConstructionData*
    3528           0 : nsCSSFrameConstructor::FindDataByTag(nsAtom* aTag,
    3529             :                                      Element* aElement,
    3530             :                                      ComputedStyle* aComputedStyle,
    3531             :                                      const FrameConstructionDataByTag* aDataPtr,
    3532             :                                      uint32_t aDataLength)
    3533             : {
    3534           0 :   for (const FrameConstructionDataByTag *curData = aDataPtr,
    3535           0 :          *endData = aDataPtr + aDataLength;
    3536           0 :        curData != endData;
    3537             :        ++curData) {
    3538           0 :     if (*curData->mTag == aTag) {
    3539           0 :       const FrameConstructionData* data = &curData->mData;
    3540           0 :       if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) {
    3541           0 :         return data->mFunc.mDataGetter(aElement, aComputedStyle);
    3542             :       }
    3543             : 
    3544             :       return data;
    3545             :     }
    3546             :   }
    3547             : 
    3548             :   return nullptr;
    3549             : }
    3550             : 
    3551             : #define SUPPRESS_FCDATA() FCDATA_DECL(FCDATA_SUPPRESS_FRAME, nullptr)
    3552             : #define SIMPLE_INT_CREATE(_int, _func) { _int, SIMPLE_FCDATA(_func) }
    3553             : #define SIMPLE_INT_CHAIN(_int, _func)                       \
    3554             :   { _int, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER, _func) }
    3555             : #define COMPLEX_INT_CREATE(_int, _func)         \
    3556             :   { _int, FULL_CTOR_FCDATA(0, _func) }
    3557             : 
    3558             : #define SIMPLE_TAG_CREATE(_tag, _func)          \
    3559             :   { &nsGkAtoms::_tag, SIMPLE_FCDATA(_func) }
    3560             : #define SIMPLE_TAG_CHAIN(_tag, _func)                                   \
    3561             :   { &nsGkAtoms::_tag, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER,  _func) }
    3562             : #define COMPLEX_TAG_CREATE(_tag, _func)             \
    3563             :   { &nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
    3564             : 
    3565             : static bool
    3566           0 : IsFrameForFieldSet(nsIFrame* aFrame)
    3567             : {
    3568           0 :   nsAtom* pseudo = aFrame->Style()->GetPseudo();
    3569           0 :   if (pseudo == nsCSSAnonBoxes::fieldsetContent ||
    3570           0 :       pseudo == nsCSSAnonBoxes::scrolledContent ||
    3571           0 :       pseudo == nsCSSAnonBoxes::columnContent) {
    3572           0 :     return IsFrameForFieldSet(aFrame->GetParent());
    3573             :   }
    3574           0 :   return aFrame->IsFieldSetFrame();
    3575             : }
    3576             : 
    3577             : /* static */
    3578             : const nsCSSFrameConstructor::FrameConstructionData*
    3579           0 : nsCSSFrameConstructor::FindHTMLData(Element* aElement,
    3580             :                                     nsAtom* aTag,
    3581             :                                     int32_t aNameSpaceID,
    3582             :                                     nsIFrame* aParentFrame,
    3583             :                                     ComputedStyle* aComputedStyle)
    3584             : {
    3585             :   // Ignore the tag if it's not HTML content and if it doesn't extend (via XBL)
    3586             :   // a valid HTML namespace.  This check must match the one in
    3587             :   // ShouldHaveFirstLineStyle.
    3588           0 :   if (aNameSpaceID != kNameSpaceID_XHTML) {
    3589             :     return nullptr;
    3590             :   }
    3591             : 
    3592           0 :   NS_ASSERTION(!aParentFrame ||
    3593             :                aParentFrame->Style()->GetPseudo() !=
    3594             :                  nsCSSAnonBoxes::fieldsetContent ||
    3595             :                aParentFrame->GetParent()->IsFieldSetFrame(),
    3596             :                "Unexpected parent for fieldset content anon box");
    3597           0 :   if (aTag == nsGkAtoms::legend &&
    3598           0 :       (!aParentFrame || !IsFrameForFieldSet(aParentFrame) ||
    3599           0 :        aComputedStyle->StyleDisplay()->IsFloatingStyle() ||
    3600           0 :        aComputedStyle->StyleDisplay()->IsAbsolutelyPositionedStyle())) {
    3601             :     // <legend> is only special inside fieldset, we only check the frame tree
    3602             :     // parent because the content tree parent may not be a <fieldset> due to
    3603             :     // display:contents, Shadow DOM, or XBL. For floated or absolutely
    3604             :     // positioned legends we want to construct by display type and
    3605             :     // not do special legend stuff.
    3606             :     return nullptr;
    3607             :   }
    3608             : 
    3609             :   static const FrameConstructionDataByTag sHTMLData[] = {
    3610             :     SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData),
    3611             :     SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,
    3612             :                      nsCSSFrameConstructor::FindImgData),
    3613             :     { &nsGkAtoms::br,
    3614             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | FCDATA_IS_LINE_BREAK,
    3615             :                   NS_NewBRFrame) },
    3616             :     SIMPLE_TAG_CREATE(wbr, NS_NewWBRFrame),
    3617             :     SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData),
    3618             :     SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame),
    3619             :     COMPLEX_TAG_CREATE(select, &nsCSSFrameConstructor::ConstructSelectFrame),
    3620             :     SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData),
    3621             :     SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
    3622             :     COMPLEX_TAG_CREATE(fieldset,
    3623             :                        &nsCSSFrameConstructor::ConstructFieldSetFrame),
    3624             :     { &nsGkAtoms::legend,
    3625             :       FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES | FCDATA_MAY_NEED_SCROLLFRAME,
    3626             :                   NS_NewLegendFrame) },
    3627             :     SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
    3628             :     SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
    3629             :     { &nsGkAtoms::button,
    3630             :       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_ALLOW_BLOCK_STYLES |
    3631             :                                  FCDATA_ALLOW_GRID_FLEX_COLUMNSET,
    3632             :                                  NS_NewHTMLButtonControlFrame,
    3633             :                                  nsCSSAnonBoxes::buttonContent) },
    3634             :     SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
    3635             :     SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
    3636             :     SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
    3637             :     SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame),
    3638             :     SIMPLE_TAG_CREATE(meter, NS_NewMeterFrame),
    3639             :     COMPLEX_TAG_CREATE(details, &nsCSSFrameConstructor::ConstructDetailsFrame)
    3640             :   };
    3641             : 
    3642             :   return FindDataByTag(aTag, aElement, aComputedStyle, sHTMLData,
    3643           0 :                        ArrayLength(sHTMLData));
    3644             : }
    3645             : 
    3646             : /* static */
    3647             : const nsCSSFrameConstructor::FrameConstructionData*
    3648           0 : nsCSSFrameConstructor::FindImgData(Element* aElement,
    3649             :                                    ComputedStyle* aComputedStyle)
    3650             : {
    3651           0 :   if (!nsImageFrame::ShouldCreateImageFrameFor(aElement, aComputedStyle)) {
    3652             :     return nullptr;
    3653             :   }
    3654             : 
    3655             :   static const FrameConstructionData sImgData = SIMPLE_FCDATA(NS_NewImageFrame);
    3656           0 :   return &sImgData;
    3657             : }
    3658             : 
    3659             : /* static */
    3660             : const nsCSSFrameConstructor::FrameConstructionData*
    3661           0 : nsCSSFrameConstructor::FindImgControlData(Element* aElement,
    3662             :                                           ComputedStyle* aComputedStyle)
    3663             : {
    3664           0 :   if (!nsImageFrame::ShouldCreateImageFrameFor(aElement, aComputedStyle)) {
    3665             :     return nullptr;
    3666             :   }
    3667             : 
    3668             :   static const FrameConstructionData sImgControlData =
    3669             :     SIMPLE_FCDATA(NS_NewImageControlFrame);
    3670           0 :   return &sImgControlData;
    3671             : }
    3672             : 
    3673             : /* static */
    3674             : const nsCSSFrameConstructor::FrameConstructionData*
    3675           0 : nsCSSFrameConstructor::FindInputData(Element* aElement,
    3676             :                                      ComputedStyle* aComputedStyle)
    3677             : {
    3678             :   static const FrameConstructionDataByInt sInputData[] = {
    3679             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_CHECKBOX, NS_NewCheckboxRadioFrame),
    3680             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_RADIO, NS_NewCheckboxRadioFrame),
    3681             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_FILE, NS_NewFileControlFrame),
    3682             :     SIMPLE_INT_CHAIN(NS_FORM_INPUT_IMAGE,
    3683             :                      nsCSSFrameConstructor::FindImgControlData),
    3684             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_EMAIL, NS_NewTextControlFrame),
    3685             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_SEARCH, NS_NewTextControlFrame),
    3686             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TEXT, NS_NewTextControlFrame),
    3687             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TEL, NS_NewTextControlFrame),
    3688             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_URL, NS_NewTextControlFrame),
    3689             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_RANGE, NS_NewRangeFrame),
    3690             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_PASSWORD, NS_NewTextControlFrame),
    3691             :     { NS_FORM_INPUT_COLOR,
    3692             :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewColorControlFrame,
    3693             :                                  nsCSSAnonBoxes::buttonContent) },
    3694             :     // TODO: this is temporary until a frame is written: bug 635240.
    3695             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_NUMBER, NS_NewNumberControlFrame),
    3696             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewDateTimeControlFrame),
    3697             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewDateTimeControlFrame),
    3698             :     // TODO: this is temporary until a frame is written: bug 888320
    3699             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_MONTH, NS_NewTextControlFrame),
    3700             :     // TODO: this is temporary until a frame is written: bug 888320
    3701             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_WEEK, NS_NewTextControlFrame),
    3702             :     // TODO: this is temporary until a frame is written: bug 888320
    3703             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_DATETIME_LOCAL, NS_NewTextControlFrame),
    3704             :     { NS_FORM_INPUT_SUBMIT,
    3705             :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3706             :                                  nsCSSAnonBoxes::buttonContent) },
    3707             :     { NS_FORM_INPUT_RESET,
    3708             :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3709             :                                  nsCSSAnonBoxes::buttonContent) },
    3710             :     { NS_FORM_INPUT_BUTTON,
    3711             :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3712             :                                  nsCSSAnonBoxes::buttonContent) }
    3713             :     // Keeping hidden inputs out of here on purpose for so they get frames by
    3714             :     // display (in practice, none).
    3715             :   };
    3716             : 
    3717           0 :   nsCOMPtr<nsIFormControl> control = do_QueryInterface(aElement);
    3718           0 :   NS_ASSERTION(control, "input doesn't implement nsIFormControl?");
    3719             : 
    3720           0 :   auto controlType = control->ControlType();
    3721             : 
    3722             :   // radio and checkbox inputs with appearance:none should be constructed
    3723             :   // by display type.  (Note that we're not checking that appearance is
    3724             :   // not (respectively) NS_THEME_RADIO and NS_THEME_CHECKBOX.)
    3725           0 :   if ((controlType == NS_FORM_INPUT_CHECKBOX ||
    3726           0 :        controlType == NS_FORM_INPUT_RADIO) &&
    3727           0 :       aComputedStyle->StyleDisplay()->mAppearance == NS_THEME_NONE) {
    3728             :     return nullptr;
    3729             :   }
    3730             : 
    3731           0 :   return FindDataByInt(controlType, aElement, aComputedStyle,
    3732           0 :                        sInputData, ArrayLength(sInputData));
    3733             : }
    3734             : 
    3735             : /* static */
    3736             : const nsCSSFrameConstructor::FrameConstructionData*
    3737           0 : nsCSSFrameConstructor::FindObjectData(Element* aElement,
    3738             :                                       ComputedStyle* aComputedStyle)
    3739             : {
    3740             :   // GetDisplayedType isn't necessarily nsIObjectLoadingContent::TYPE_NULL for
    3741             :   // cases when the object is broken/suppressed/etc (e.g. a broken image), but
    3742             :   // we want to treat those cases as TYPE_NULL
    3743             :   uint32_t type;
    3744           0 :   if (aElement->State().HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
    3745             :                                               NS_EVENT_STATE_USERDISABLED |
    3746             :                                               NS_EVENT_STATE_SUPPRESSED)) {
    3747           0 :     type = nsIObjectLoadingContent::TYPE_NULL;
    3748             :   } else {
    3749           0 :     nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(aElement));
    3750           0 :     NS_ASSERTION(objContent,
    3751             :                  "embed and object must implement "
    3752             :                  "nsIObjectLoadingContent!");
    3753             : 
    3754           0 :     objContent->GetDisplayedType(&type);
    3755             :   }
    3756             : 
    3757             :   static const FrameConstructionDataByInt sObjectData[] = {
    3758             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_LOADING,
    3759             :                       NS_NewEmptyFrame),
    3760             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_PLUGIN,
    3761             :                       NS_NewObjectFrame),
    3762             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_IMAGE,
    3763             :                       NS_NewImageFrame),
    3764             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_DOCUMENT,
    3765             :                       NS_NewSubDocumentFrame),
    3766             :     // Fake plugin handlers load as documents
    3767             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_FAKE_PLUGIN,
    3768             :                       NS_NewSubDocumentFrame)
    3769             :     // Nothing for TYPE_NULL so we'll construct frames by display there
    3770             :   };
    3771             : 
    3772           0 :   return FindDataByInt((int32_t)type, aElement, aComputedStyle,
    3773           0 :                        sObjectData, ArrayLength(sObjectData));
    3774             : }
    3775             : 
    3776             : /* static */
    3777             : const nsCSSFrameConstructor::FrameConstructionData*
    3778           0 : nsCSSFrameConstructor::FindCanvasData(Element* aElement,
    3779             :                                       ComputedStyle* aComputedStyle)
    3780             : {
    3781             :   // We want to check whether script is enabled on the document that
    3782             :   // could be painting to the canvas.  That's the owner document of
    3783             :   // the canvas, except when the owner document is a static document,
    3784             :   // in which case it's the original document it was cloned from.
    3785           0 :   nsIDocument* doc = aElement->OwnerDoc();
    3786           0 :   if (doc->IsStaticDocument()) {
    3787           0 :     doc = doc->GetOriginalDocument();
    3788             :   }
    3789           0 :   if (!doc->IsScriptEnabled()) {
    3790             :     return nullptr;
    3791             :   }
    3792             : 
    3793             :   static const FrameConstructionData sCanvasData =
    3794             :     FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewHTMLCanvasFrame,
    3795             :                                nsCSSAnonBoxes::htmlCanvasContent);
    3796           0 :   return &sCanvasData;
    3797             : }
    3798             : 
    3799             : void
    3800           0 : nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
    3801             :                                                       nsFrameConstructorState& aState,
    3802             :                                                       nsContainerFrame* aParentFrame,
    3803             :                                                       nsFrameItems& aFrameItems)
    3804             : {
    3805           0 :   const FrameConstructionData* data = aItem.mFCData;
    3806           0 :   NS_ASSERTION(data, "Must have frame construction data");
    3807             : 
    3808           0 :   uint32_t bits = data->mBits;
    3809             : 
    3810           0 :   NS_ASSERTION(!(bits & FCDATA_FUNC_IS_DATA_GETTER),
    3811             :                "Should have dealt with this inside the data finder");
    3812             : 
    3813             :   // Some sets of bits are not compatible with each other
    3814             : #define CHECK_ONLY_ONE_BIT(_bit1, _bit2)               \
    3815             :   NS_ASSERTION(!(bits & _bit1) || !(bits & _bit2),     \
    3816             :                "Only one of these bits should be set")
    3817           0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_FORCE_NULL_ABSPOS_CONTAINER);
    3818           0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_WRAP_KIDS_IN_BLOCKS);
    3819           0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_MAY_NEED_SCROLLFRAME);
    3820           0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_IS_POPUP);
    3821           0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_SKIP_ABSPOS_PUSH);
    3822           0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
    3823             :                      FCDATA_DISALLOW_GENERATED_CONTENT);
    3824           0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_ALLOW_BLOCK_STYLES);
    3825           0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
    3826             :                      FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
    3827           0 :   CHECK_ONLY_ONE_BIT(FCDATA_WRAP_KIDS_IN_BLOCKS,
    3828             :                      FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
    3829             : #undef CHECK_ONLY_ONE_BIT
    3830           0 :   NS_ASSERTION(!(bits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) ||
    3831             :                ((bits & FCDATA_FUNC_IS_FULL_CTOR) &&
    3832             :                 data->mFullConstructor ==
    3833             :                   &nsCSSFrameConstructor::ConstructNonScrollableBlock),
    3834             :                "Unexpected FCDATA_FORCED_NON_SCROLLABLE_BLOCK flag");
    3835           0 :   MOZ_ASSERT(!(bits & FCDATA_IS_WRAPPER_ANON_BOX) ||
    3836             :              (bits & FCDATA_USE_CHILD_ITEMS),
    3837             :              "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS");
    3838             : 
    3839             :   // Don't create a subdocument frame for iframes if we're creating extra frames
    3840           0 :   if (aState.mCreatingExtraFrames &&
    3841           0 :       aItem.mContent->IsHTMLElement(nsGkAtoms::iframe))
    3842             :   {
    3843             :     return;
    3844             :   }
    3845             : 
    3846           0 :   nsIContent* const content = aItem.mContent;
    3847             :   nsIFrame* newFrame;
    3848             :   nsIFrame* primaryFrame;
    3849           0 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    3850           0 :   const nsStyleDisplay* display = computedStyle->StyleDisplay();
    3851           0 :   if (bits & FCDATA_FUNC_IS_FULL_CTOR) {
    3852           0 :     newFrame =
    3853           0 :       (this->*(data->mFullConstructor))(aState, aItem, aParentFrame,
    3854           0 :                                         display, aFrameItems);
    3855           0 :     MOZ_ASSERT(newFrame, "Full constructor failed");
    3856             :     primaryFrame = newFrame;
    3857             :   } else {
    3858           0 :     newFrame =
    3859           0 :       (*data->mFunc.mCreationFunc)(mPresShell, computedStyle);
    3860             : 
    3861           0 :     bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW);
    3862           0 :     bool isPopup = aItem.mIsPopup;
    3863           0 :     NS_ASSERTION(!isPopup ||
    3864             :                  (aState.mPopupItems.containingBlock &&
    3865             :                   aState.mPopupItems.containingBlock->IsPopupSetFrame()),
    3866             :                  "Should have a containing block here!");
    3867             : 
    3868             :     nsContainerFrame* geometricParent =
    3869           0 :       isPopup ? aState.mPopupItems.containingBlock :
    3870           0 :       (allowOutOfFlow ? aState.GetGeometricParent(display, aParentFrame)
    3871           0 :                       : aParentFrame);
    3872             : 
    3873             :     // Must init frameToAddToList to null, since it's inout
    3874           0 :     nsIFrame* frameToAddToList = nullptr;
    3875           0 :     if ((bits & FCDATA_MAY_NEED_SCROLLFRAME) &&
    3876             :         display->IsScrollableOverflow()) {
    3877           0 :       nsContainerFrame* scrollframe = nullptr;
    3878             :       BuildScrollFrame(aState, content, computedStyle, newFrame,
    3879           0 :                        geometricParent, scrollframe);
    3880           0 :       frameToAddToList = scrollframe;
    3881             :     } else {
    3882           0 :       InitAndRestoreFrame(aState, content, geometricParent, newFrame);
    3883           0 :       frameToAddToList = newFrame;
    3884             :     }
    3885             : 
    3886             :     // Use frameToAddToList as the primary frame.  In the non-scrollframe case
    3887             :     // they're equal, but in the scrollframe case newFrame is the scrolled
    3888             :     // frame, while frameToAddToList is the scrollframe (and should be the
    3889             :     // primary frame).
    3890           0 :     primaryFrame = frameToAddToList;
    3891             : 
    3892             :     // If we need to create a block formatting context to wrap our
    3893             :     // kids, do it now.
    3894           0 :     const nsStyleDisplay* maybeAbsoluteContainingBlockDisplay = display;
    3895           0 :     nsIFrame* maybeAbsoluteContainingBlockStyleFrame = primaryFrame;
    3896           0 :     nsIFrame* maybeAbsoluteContainingBlock = newFrame;
    3897           0 :     nsIFrame* possiblyLeafFrame = newFrame;
    3898           0 :     if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS) {
    3899           0 :       RefPtr<ComputedStyle> outerSC = mPresShell->StyleSet()->
    3900           0 :         ResolveInheritingAnonymousBoxStyle(*data->mAnonBoxPseudo,
    3901           0 :                                            computedStyle);
    3902             : #ifdef DEBUG
    3903           0 :       nsContainerFrame* containerFrame = do_QueryFrame(newFrame);
    3904           0 :       MOZ_ASSERT(containerFrame);
    3905             : #endif
    3906           0 :       nsContainerFrame* container = static_cast<nsContainerFrame*>(newFrame);
    3907             :       nsContainerFrame* outerFrame;
    3908             :       nsContainerFrame* innerFrame;
    3909           0 :       if (bits & FCDATA_ALLOW_GRID_FLEX_COLUMNSET) {
    3910           0 :         switch (display->mDisplay) {
    3911             :           case StyleDisplay::Flex:
    3912             :           case StyleDisplay::InlineFlex:
    3913           0 :             outerFrame = NS_NewFlexContainerFrame(mPresShell, outerSC);
    3914           0 :             InitAndRestoreFrame(aState, content, container, outerFrame);
    3915           0 :             innerFrame = outerFrame;
    3916           0 :             break;
    3917             :           case StyleDisplay::Grid:
    3918             :           case StyleDisplay::InlineGrid:
    3919           0 :             outerFrame = NS_NewGridContainerFrame(mPresShell, outerSC);
    3920           0 :             InitAndRestoreFrame(aState, content, container, outerFrame);
    3921           0 :             innerFrame = outerFrame;
    3922           0 :             break;
    3923             :           default: {
    3924           0 :             nsContainerFrame* columnSetFrame = nullptr;
    3925           0 :             RefPtr<ComputedStyle> innerSC = outerSC;
    3926           0 :             const nsStyleColumn* columns = outerSC->StyleColumn();
    3927           0 :             if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
    3928           0 :                 columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
    3929             :               columnSetFrame =
    3930           0 :                 NS_NewColumnSetFrame(mPresShell, outerSC,
    3931           0 :                                      nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
    3932           0 :               InitAndRestoreFrame(aState, content, container, columnSetFrame);
    3933           0 :               innerSC = mPresShell->StyleSet()->
    3934           0 :                 ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::columnContent,
    3935           0 :                                                    outerSC);
    3936             :             }
    3937           0 :             innerFrame = NS_NewBlockFormattingContext(mPresShell, innerSC);
    3938           0 :             if (columnSetFrame) {
    3939           0 :               InitAndRestoreFrame(aState, content, columnSetFrame, innerFrame);
    3940           0 :               SetInitialSingleChild(columnSetFrame, innerFrame);
    3941           0 :               outerFrame = columnSetFrame;
    3942             :             } else {
    3943           0 :               InitAndRestoreFrame(aState, content, container, innerFrame);
    3944           0 :               outerFrame = innerFrame;
    3945             :             }
    3946             :             break;
    3947             :           }
    3948             :         }
    3949             :       } else {
    3950           0 :         innerFrame = NS_NewBlockFormattingContext(mPresShell, outerSC);
    3951           0 :         InitAndRestoreFrame(aState, content, container, innerFrame);
    3952           0 :         outerFrame = innerFrame;
    3953             :       }
    3954             : 
    3955           0 :       SetInitialSingleChild(container, outerFrame);
    3956             : 
    3957           0 :       container->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    3958             : 
    3959             :       // Now figure out whether newFrame or outerFrame should be the
    3960             :       // absolute container.
    3961           0 :       auto outerDisplay = outerSC->StyleDisplay();
    3962           0 :       if (outerDisplay->IsAbsPosContainingBlock(outerFrame)) {
    3963           0 :         maybeAbsoluteContainingBlockDisplay = outerDisplay;
    3964           0 :         maybeAbsoluteContainingBlock = outerFrame;
    3965           0 :         maybeAbsoluteContainingBlockStyleFrame = outerFrame;
    3966           0 :         innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    3967             :       }
    3968             : 
    3969             :       // Our kids should go into the innerFrame.
    3970           0 :       newFrame = innerFrame;
    3971             :     }
    3972             : 
    3973           0 :     aState.AddChild(frameToAddToList, aFrameItems, content, aParentFrame,
    3974           0 :                     allowOutOfFlow, allowOutOfFlow, isPopup);
    3975             : 
    3976           0 :     nsContainerFrame* newFrameAsContainer = do_QueryFrame(newFrame);
    3977           0 :     if (newFrameAsContainer) {
    3978             : #ifdef MOZ_XUL
    3979             :       // Icky XUL stuff, sadly
    3980             : 
    3981           0 :       if (aItem.mIsRootPopupgroup) {
    3982           0 :         NS_ASSERTION(nsIRootBox::GetRootBox(mPresShell) &&
    3983             :                      nsIRootBox::GetRootBox(mPresShell)->GetPopupSetFrame() ==
    3984             :                      newFrame,
    3985             :                      "Unexpected PopupSetFrame");
    3986           0 :         aState.mPopupItems.containingBlock = newFrameAsContainer;
    3987           0 :         aState.mHavePendingPopupgroup = false;
    3988             :       }
    3989             : #endif /* MOZ_XUL */
    3990             : 
    3991             :       // Process the child content if requested
    3992           0 :       nsFrameItems childItems;
    3993           0 :       nsFrameConstructorSaveState absoluteSaveState;
    3994             : 
    3995           0 :       if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER) {
    3996           0 :         aState.PushAbsoluteContainingBlock(nullptr, nullptr, absoluteSaveState);
    3997           0 :       } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH)) {
    3998           0 :         maybeAbsoluteContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    3999             :         // This check is identical to nsStyleDisplay::IsAbsPosContainingBlock
    4000             :         // except without the assertion that the style display and frame match.
    4001             :         // When constructing scroll frames we intentionally use the style
    4002             :         // display for the outer, but make the inner the containing block.
    4003           0 :         if ((maybeAbsoluteContainingBlockDisplay->IsAbsolutelyPositionedStyle() ||
    4004           0 :              maybeAbsoluteContainingBlockDisplay->IsRelativelyPositionedStyle() ||
    4005           0 :              maybeAbsoluteContainingBlockDisplay->IsFixedPosContainingBlock(
    4006           0 :                  maybeAbsoluteContainingBlockStyleFrame)) &&
    4007           0 :             !nsSVGUtils::IsInSVGTextSubtree(maybeAbsoluteContainingBlockStyleFrame)) {
    4008             :           nsContainerFrame* cf = static_cast<nsContainerFrame*>(
    4009           0 :               maybeAbsoluteContainingBlock);
    4010           0 :           aState.PushAbsoluteContainingBlock(cf, cf, absoluteSaveState);
    4011             :         }
    4012             :       }
    4013             : 
    4014           0 :       if (!aItem.mAnonChildren.IsEmpty()) {
    4015           0 :         NS_ASSERTION(!(bits & FCDATA_USE_CHILD_ITEMS),
    4016             :                      "We should not have both anonymous and non-anonymous "
    4017             :                      "children in a given FrameConstructorItem");
    4018           0 :         AddFCItemsForAnonymousContent(aState, newFrameAsContainer, aItem.mAnonChildren,
    4019           0 :                                       aItem.mChildItems);
    4020           0 :         bits |= FCDATA_USE_CHILD_ITEMS;
    4021             :       }
    4022             : 
    4023           0 :       if (bits & FCDATA_USE_CHILD_ITEMS) {
    4024           0 :         nsFrameConstructorSaveState floatSaveState;
    4025             : 
    4026           0 :         if (ShouldSuppressFloatingOfDescendants(newFrame)) {
    4027           0 :           aState.PushFloatContainingBlock(nullptr, floatSaveState);
    4028           0 :         } else if (newFrame->IsFloatContainingBlock()) {
    4029           0 :           aState.PushFloatContainingBlock(newFrameAsContainer, floatSaveState);
    4030             :         }
    4031           0 :         ConstructFramesFromItemList(aState, aItem.mChildItems,
    4032             :                                     newFrameAsContainer,
    4033           0 :                                     bits & FCDATA_IS_WRAPPER_ANON_BOX,
    4034           0 :                                     childItems);
    4035             :       } else {
    4036             :         // Process the child frames.
    4037           0 :         ProcessChildren(aState, content, computedStyle, newFrameAsContainer,
    4038           0 :                         !(bits & FCDATA_DISALLOW_GENERATED_CONTENT),
    4039             :                         childItems,
    4040           0 :                         (bits & FCDATA_ALLOW_BLOCK_STYLES) != 0,
    4041           0 :                         aItem.mPendingBinding, possiblyLeafFrame);
    4042             :       }
    4043             : 
    4044           0 :       if (bits & FCDATA_WRAP_KIDS_IN_BLOCKS) {
    4045           0 :         nsFrameItems newItems;
    4046             :         nsFrameItems currentBlockItems;
    4047             :         nsIFrame* f;
    4048           0 :         while ((f = childItems.FirstChild()) != nullptr) {
    4049           0 :           bool wrapFrame = IsInlineFrame(f) || IsFramePartOfIBSplit(f);
    4050           0 :           if (!wrapFrame) {
    4051             :             FlushAccumulatedBlock(aState, content, newFrameAsContainer,
    4052           0 :                                   currentBlockItems, newItems);
    4053             :           }
    4054             : 
    4055           0 :           childItems.RemoveFrame(f);
    4056           0 :           if (wrapFrame) {
    4057           0 :             currentBlockItems.AddChild(f);
    4058             :           } else {
    4059           0 :             newItems.AddChild(f);
    4060             :           }
    4061             :         }
    4062             :         FlushAccumulatedBlock(aState, content, newFrameAsContainer,
    4063           0 :                               currentBlockItems, newItems);
    4064             : 
    4065           0 :         if (childItems.NotEmpty()) {
    4066             :           // an error must have occurred, delete unprocessed frames
    4067           0 :           childItems.DestroyFrames();
    4068             :         }
    4069             : 
    4070           0 :         childItems = newItems;
    4071             :       }
    4072             : 
    4073             :       // Set the frame's initial child list
    4074             :       // Note that MathML depends on this being called even if
    4075             :       // childItems is empty!
    4076           0 :       newFrameAsContainer->SetInitialChildList(kPrincipalList, childItems);
    4077             :     }
    4078             :   }
    4079             : 
    4080           0 :   NS_ASSERTION(newFrame->IsFrameOfType(nsIFrame::eLineParticipant) ==
    4081             :                ((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),
    4082             :                "Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits");
    4083             : 
    4084           0 :   if (aItem.mIsAnonymousContentCreatorContent) {
    4085             :     primaryFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
    4086             :   }
    4087             : 
    4088             :   // Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
    4089             :   // generated content that doesn't have one yet.  Note that we have to examine
    4090             :   // the frame bit, because by this point mIsGeneratedContent has been cleared
    4091             :   // on aItem.
    4092           0 :   if ((!aState.mCreatingExtraFrames ||
    4093           0 :        (primaryFrame->HasAnyStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT |
    4094           0 :                                       NS_FRAME_GENERATED_CONTENT) &&
    4095           0 :         !aItem.mContent->GetPrimaryFrame())) &&
    4096           0 :        !(bits & FCDATA_SKIP_FRAMESET)) {
    4097           0 :     aItem.mContent->SetPrimaryFrame(primaryFrame);
    4098           0 :     ActiveLayerTracker::TransferActivityToFrame(aItem.mContent, primaryFrame);
    4099             :   }
    4100             : }
    4101             : 
    4102             : static void
    4103           0 : SetFlagsOnSubtree(nsIContent *aNode, uintptr_t aFlagsToSet)
    4104             : {
    4105             : #ifdef DEBUG
    4106             :   // Make sure that the node passed to us doesn't have any XBL children
    4107             :   {
    4108           0 :     FlattenedChildIterator iter(aNode);
    4109           0 :     NS_ASSERTION(!iter.XBLInvolved() || !iter.GetNextChild(),
    4110             :                  "The node should not have any XBL children");
    4111             :   }
    4112             : #endif
    4113             : 
    4114             :   // Set the flag on the node itself
    4115           0 :   aNode->SetFlags(aFlagsToSet);
    4116             : 
    4117             :   // Set the flag on all of its children recursively
    4118           0 :   for (nsIContent* child = aNode->GetFirstChild(); child;
    4119           0 :        child = child->GetNextSibling()) {
    4120           0 :     SetFlagsOnSubtree(child, aFlagsToSet);
    4121             :   }
    4122           0 : }
    4123             : 
    4124             : /**
    4125             :  * This function takes a tree of nsIAnonymousContentCreator::ContentInfo
    4126             :  * objects where the nsIContent nodes have just been created, and appends the
    4127             :  * nsIContent children in the tree to their parent. The leaf nsIContent objects
    4128             :  * are appended first to minimize the number of notifications that are sent
    4129             :  * out (i.e. by appending as many descendants as posible while their parent is
    4130             :  * not yet in the document tree).
    4131             :  *
    4132             :  * This function is used simply as a convenience so that implementations of
    4133             :  * nsIAnonymousContentCreator::CreateAnonymousContent don't all have to have
    4134             :  * their own code to connect the elements that they create.
    4135             :  */
    4136             : static void
    4137           0 : ConnectAnonymousTreeDescendants(nsIContent* aParent,
    4138             :                                 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
    4139             : {
    4140           0 :   uint32_t count = aContent.Length();
    4141           0 :   for (uint32_t i=0; i < count; i++) {
    4142           0 :     nsIContent* content = aContent[i].mContent;
    4143           0 :     NS_ASSERTION(content, "null anonymous content?");
    4144             : 
    4145           0 :     ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
    4146             : 
    4147           0 :     aParent->AppendChildTo(content, false);
    4148             :   }
    4149           0 : }
    4150             : 
    4151             : nsresult
    4152           0 : nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
    4153             :                                            nsIFrame* aParentFrame,
    4154             :                                            nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
    4155             : {
    4156           0 :   nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
    4157           0 :   if (!creator)
    4158             :     return NS_OK;
    4159             : 
    4160           0 :   nsresult rv = creator->CreateAnonymousContent(aContent);
    4161           0 :   if (NS_FAILED(rv)) {
    4162             :     // CreateAnonymousContent failed, e.g. because the page has a <use> loop.
    4163             :     return rv;
    4164             :   }
    4165             : 
    4166           0 :   uint32_t count = aContent.Length();
    4167           0 :   for (uint32_t i=0; i < count; i++) {
    4168             :     // get our child's content and set its parent to our content
    4169           0 :     nsIContent* content = aContent[i].mContent;
    4170           0 :     NS_ASSERTION(content, "null anonymous content?");
    4171             : 
    4172           0 :     ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
    4173             : 
    4174           0 :     if (aParentFrame->IsSVGUseFrame()) {
    4175             :       // least-surprise CSS binding until we do the SVG specified
    4176             :       // cascading rules for <svg:use> - bug 265894
    4177           0 :       content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
    4178             :     } else {
    4179           0 :       content->SetIsNativeAnonymousRoot();
    4180             :     }
    4181             : 
    4182           0 :     bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
    4183             : 
    4184             :     // If the parent is in a shadow tree, make sure we don't
    4185             :     // bind with a document because shadow roots and its descendants
    4186             :     // are not in document.
    4187             :     nsIDocument* bindDocument =
    4188           0 :       aParent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
    4189           0 :     rv = content->BindToTree(bindDocument, aParent, aParent, true);
    4190             :     // If the anonymous content creator requested that the content should be
    4191             :     // editable, honor its request.
    4192             :     // We need to set the flag on the whole subtree, because existing
    4193             :     // children's flags have already been set as part of the BindToTree operation.
    4194           0 :     if (anonContentIsEditable) {
    4195           0 :       NS_ASSERTION(aParentFrame->IsTextInputFrame(),
    4196             :                    "We only expect this for anonymous content under a text control frame");
    4197           0 :       SetFlagsOnSubtree(content, NODE_IS_EDITABLE);
    4198             :     }
    4199           0 :     if (NS_FAILED(rv)) {
    4200           0 :       content->UnbindFromTree();
    4201           0 :       return rv;
    4202             :     }
    4203             :   }
    4204             : 
    4205           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
    4206             :   // Eagerly compute styles for the anonymous content tree.
    4207           0 :   for (auto& info : aContent) {
    4208           0 :     if (info.mContent->IsElement()) {
    4209           0 :       styleSet->StyleNewSubtree(info.mContent->AsElement());
    4210             :     }
    4211             :   }
    4212             : 
    4213           0 :   return NS_OK;
    4214             : }
    4215             : 
    4216             : static
    4217           0 : bool IsXULDisplayType(const nsStyleDisplay* aDisplay)
    4218             : {
    4219             :   // -moz-{inline-}box is XUL, unless we're emulating it with flexbox.
    4220           0 :   if (!StaticPrefs::layout_css_emulate_moz_box_with_flex() &&
    4221           0 :       (aDisplay->mDisplay == StyleDisplay::MozInlineBox ||
    4222             :        aDisplay->mDisplay == StyleDisplay::MozBox)) {
    4223             :     return true;
    4224             :   }
    4225             : 
    4226             : #ifdef MOZ_XUL
    4227           0 :   return (aDisplay->mDisplay == StyleDisplay::MozInlineGrid ||
    4228           0 :           aDisplay->mDisplay == StyleDisplay::MozInlineStack ||
    4229           0 :           aDisplay->mDisplay == StyleDisplay::MozGrid ||
    4230           0 :           aDisplay->mDisplay == StyleDisplay::MozStack ||
    4231           0 :           aDisplay->mDisplay == StyleDisplay::MozGridGroup ||
    4232           0 :           aDisplay->mDisplay == StyleDisplay::MozGridLine ||
    4233           0 :           aDisplay->mDisplay == StyleDisplay::MozDeck ||
    4234           0 :           aDisplay->mDisplay == StyleDisplay::MozPopup ||
    4235             :           aDisplay->mDisplay == StyleDisplay::MozGroupbox);
    4236             : #else
    4237             :   return false;
    4238             : #endif
    4239             : }
    4240             : 
    4241             : 
    4242             : // XUL frames are not allowed to be out of flow.
    4243             : #define SIMPLE_XUL_FCDATA(_func)                                        \
    4244             :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH,    \
    4245             :               _func)
    4246             : #define SCROLLABLE_XUL_FCDATA(_func)                                    \
    4247             :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |   \
    4248             :               FCDATA_MAY_NEED_SCROLLFRAME, _func)
    4249             : // .. but we allow some XUL frames to be _containers_ for out-of-flow content
    4250             : // (This is the same as SCROLLABLE_XUL_FCDATA, but w/o FCDATA_SKIP_ABSPOS_PUSH)
    4251             : #define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func)                   \
    4252             :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
    4253             :               FCDATA_MAY_NEED_SCROLLFRAME, _func)
    4254             : 
    4255             : #define SIMPLE_XUL_CREATE(_tag, _func)            \
    4256             :   { &nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func) }
    4257             : #define SCROLLABLE_XUL_CREATE(_tag, _func)            \
    4258             :   { &nsGkAtoms::_tag, SCROLLABLE_XUL_FCDATA(_func) }
    4259             : #define SIMPLE_XUL_DISPLAY_CREATE(_display, _func)      \
    4260             :   FCDATA_FOR_DISPLAY(_display, SIMPLE_XUL_FCDATA(_func))
    4261             : #define SCROLLABLE_XUL_DISPLAY_CREATE(_display, _func)                          \
    4262             :   FCDATA_FOR_DISPLAY(_display, SCROLLABLE_XUL_FCDATA(_func))
    4263             : #define SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(_display, _func)         \
    4264             :   FCDATA_FOR_DISPLAY(_display, SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func))
    4265             : 
    4266             : static
    4267           0 : nsIFrame* NS_NewGridBoxFrame(nsIPresShell* aPresShell,
    4268             :                              ComputedStyle* aComputedStyle)
    4269             : {
    4270           0 :   nsCOMPtr<nsBoxLayout> layout;
    4271           0 :   NS_NewGridLayout2(aPresShell, getter_AddRefs(layout));
    4272           0 :   return NS_NewBoxFrame(aPresShell, aComputedStyle, false, layout);
    4273             : }
    4274             : 
    4275             : /* static */
    4276             : const nsCSSFrameConstructor::FrameConstructionData*
    4277           0 : nsCSSFrameConstructor::FindXULTagData(Element* aElement,
    4278             :                                       nsAtom* aTag,
    4279             :                                       int32_t aNameSpaceID,
    4280             :                                       ComputedStyle* aComputedStyle)
    4281             : {
    4282           0 :   if (aNameSpaceID != kNameSpaceID_XUL) {
    4283             :     return nullptr;
    4284             :   }
    4285             : 
    4286             :   static const FrameConstructionDataByTag sXULTagData[] = {
    4287             : #ifdef MOZ_XUL
    4288             :     SCROLLABLE_XUL_CREATE(button, NS_NewButtonBoxFrame),
    4289             :     SCROLLABLE_XUL_CREATE(thumb, NS_NewButtonBoxFrame),
    4290             :     SCROLLABLE_XUL_CREATE(checkbox, NS_NewButtonBoxFrame),
    4291             :     SCROLLABLE_XUL_CREATE(radio, NS_NewButtonBoxFrame),
    4292             :     SCROLLABLE_XUL_CREATE(titlebar, NS_NewTitleBarFrame),
    4293             :     SCROLLABLE_XUL_CREATE(resizer, NS_NewResizerFrame),
    4294             :     SCROLLABLE_XUL_CREATE(toolbarpaletteitem, NS_NewBoxFrame),
    4295             :     SIMPLE_XUL_CREATE(image, NS_NewImageBoxFrame),
    4296             :     SIMPLE_XUL_CREATE(spring, NS_NewLeafBoxFrame),
    4297             :     SIMPLE_XUL_CREATE(spacer, NS_NewLeafBoxFrame),
    4298             :     SIMPLE_XUL_CREATE(treechildren, NS_NewTreeBodyFrame),
    4299             :     SIMPLE_XUL_CREATE(treecol, NS_NewTreeColFrame),
    4300             :     SIMPLE_XUL_CREATE(text, NS_NewTextBoxFrame),
    4301             :     SIMPLE_TAG_CHAIN(label, nsCSSFrameConstructor::FindXULLabelData),
    4302             :     SIMPLE_TAG_CHAIN(description, nsCSSFrameConstructor::FindXULDescriptionData),
    4303             :     SIMPLE_XUL_CREATE(menu, NS_NewMenuFrame),
    4304             :     SIMPLE_XUL_CREATE(menubutton, NS_NewMenuFrame),
    4305             :     SIMPLE_XUL_CREATE(menuitem, NS_NewMenuItemFrame),
    4306             : #ifdef XP_MACOSX
    4307             :     SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData),
    4308             : #else
    4309             :     SIMPLE_XUL_CREATE(menubar, NS_NewMenuBarFrame),
    4310             : #endif /* XP_MACOSX */
    4311             :     SIMPLE_TAG_CHAIN(popupgroup, nsCSSFrameConstructor::FindPopupGroupData),
    4312             :     SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame),
    4313             :     SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame),
    4314             :     SIMPLE_XUL_CREATE(browser, NS_NewSubDocumentFrame),
    4315             :     SIMPLE_XUL_CREATE(progressmeter, NS_NewProgressMeterFrame),
    4316             :     SIMPLE_XUL_CREATE(splitter, NS_NewSplitterFrame),
    4317             :     SIMPLE_TAG_CHAIN(listboxbody,
    4318             :                      nsCSSFrameConstructor::FindXULListBoxBodyData),
    4319             :     SIMPLE_TAG_CHAIN(listitem, nsCSSFrameConstructor::FindXULListItemData),
    4320             : #endif /* MOZ_XUL */
    4321             :     SIMPLE_XUL_CREATE(slider, NS_NewSliderFrame),
    4322             :     SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame),
    4323             :     SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame)
    4324             :   };
    4325             : 
    4326             :   return FindDataByTag(aTag, aElement, aComputedStyle, sXULTagData,
    4327           0 :                        ArrayLength(sXULTagData));
    4328             : }
    4329             : 
    4330             : #ifdef MOZ_XUL
    4331             : /* static */
    4332             : const nsCSSFrameConstructor::FrameConstructionData*
    4333           0 : nsCSSFrameConstructor::FindPopupGroupData(Element* aElement,
    4334             :                                           ComputedStyle* /* unused */)
    4335             : {
    4336           0 :   if (!aElement->IsRootOfNativeAnonymousSubtree()) {
    4337             :     return nullptr;
    4338             :   }
    4339             : 
    4340             :   static const FrameConstructionData sPopupSetData =
    4341             :     SIMPLE_XUL_FCDATA(NS_NewPopupSetFrame);
    4342           0 :   return &sPopupSetData;
    4343             : }
    4344             : 
    4345             : /* static */
    4346             : const nsCSSFrameConstructor::FrameConstructionData
    4347             : nsCSSFrameConstructor::sXULTextBoxData = SIMPLE_XUL_FCDATA(NS_NewTextBoxFrame);
    4348             : 
    4349             : /* static */
    4350             : const nsCSSFrameConstructor::FrameConstructionData*
    4351           0 : nsCSSFrameConstructor::FindXULLabelData(Element* aElement,
    4352             :                                         ComputedStyle* /* unused */)
    4353             : {
    4354           0 :   if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    4355             :     return &sXULTextBoxData;
    4356             :   }
    4357             : 
    4358             :   static const FrameConstructionData sLabelData =
    4359             :     SIMPLE_XUL_FCDATA(NS_NewXULLabelFrame);
    4360           0 :   return &sLabelData;
    4361             : }
    4362             : 
    4363             : static nsIFrame*
    4364           0 : NS_NewXULDescriptionFrame(nsIPresShell* aPresShell, ComputedStyle *aContext)
    4365             : {
    4366             :   // XXXbz do we really need to set up the block formatting context root? If the
    4367             :   // parent is not a block we'll get it anyway, and if it is, do we want it?
    4368           0 :   return NS_NewBlockFormattingContext(aPresShell, aContext);
    4369             : }
    4370             : 
    4371             : /* static */
    4372             : const nsCSSFrameConstructor::FrameConstructionData*
    4373           0 : nsCSSFrameConstructor::FindXULDescriptionData(Element* aElement,
    4374             :                                               ComputedStyle* /* unused */)
    4375             : {
    4376           0 :   if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    4377             :     return &sXULTextBoxData;
    4378             :   }
    4379             : 
    4380             :   static const FrameConstructionData sDescriptionData =
    4381             :     SIMPLE_XUL_FCDATA(NS_NewXULDescriptionFrame);
    4382           0 :   return &sDescriptionData;
    4383             : }
    4384             : 
    4385             : #ifdef XP_MACOSX
    4386             : /* static */
    4387             : const nsCSSFrameConstructor::FrameConstructionData*
    4388             : nsCSSFrameConstructor::FindXULMenubarData(Element* aElement,
    4389             :                                           ComputedStyle* aComputedStyle)
    4390             : {
    4391             :   nsCOMPtr<nsIDocShell> treeItem = aElement->OwnerDoc()->GetDocShell();
    4392             :   if (treeItem && nsIDocShellTreeItem::typeChrome == treeItem->ItemType()) {
    4393             :     nsCOMPtr<nsIDocShellTreeItem> parent;
    4394             :     treeItem->GetParent(getter_AddRefs(parent));
    4395             :     if (!parent) {
    4396             :       // This is the root.  Suppress the menubar, since on Mac
    4397             :       // window menus are not attached to the window.
    4398             :       static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
    4399             :       return &sSuppressData;
    4400             :     }
    4401             :   }
    4402             : 
    4403             :   static const FrameConstructionData sMenubarData =
    4404             :     SIMPLE_XUL_FCDATA(NS_NewMenuBarFrame);
    4405             :   return &sMenubarData;
    4406             : }
    4407             : #endif /* XP_MACOSX */
    4408             : 
    4409             : /* static */
    4410             : const nsCSSFrameConstructor::FrameConstructionData*
    4411           0 : nsCSSFrameConstructor::FindXULListBoxBodyData(Element* aElement,
    4412             :                                               ComputedStyle* aComputedStyle)
    4413             : {
    4414           0 :   if (aComputedStyle->StyleDisplay()->mDisplay !=
    4415             :         StyleDisplay::MozGridGroup) {
    4416             :     return nullptr;
    4417             :   }
    4418             : 
    4419             :   static const FrameConstructionData sListBoxBodyData =
    4420             :     SCROLLABLE_XUL_FCDATA(NS_NewListBoxBodyFrame);
    4421           0 :   return &sListBoxBodyData;
    4422             : }
    4423             : 
    4424             : /* static */
    4425             : const nsCSSFrameConstructor::FrameConstructionData*
    4426           0 : nsCSSFrameConstructor::FindXULListItemData(Element* aElement,
    4427             :                                            ComputedStyle* aComputedStyle)
    4428             : {
    4429           0 :   if (aComputedStyle->StyleDisplay()->mDisplay != StyleDisplay::MozGridLine) {
    4430             :     return nullptr;
    4431             :   }
    4432             : 
    4433             :   static const FrameConstructionData sListItemData =
    4434             :     SCROLLABLE_XUL_FCDATA(NS_NewListItemFrame);
    4435           0 :   return &sListItemData;
    4436             : }
    4437             : 
    4438             : #endif /* MOZ_XUL */
    4439             : 
    4440             : /* static */
    4441             : const nsCSSFrameConstructor::FrameConstructionData*
    4442           0 : nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay,
    4443             :                                           Element* aElement,
    4444             :                                           ComputedStyle* aComputedStyle)
    4445             : {
    4446             :   static const FrameConstructionDataByDisplay sXULDisplayData[] = {
    4447             :     SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::MozBox,
    4448             :                                                    NS_NewBoxFrame),
    4449             :     SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineBox,
    4450             :                                                    NS_NewBoxFrame),
    4451             : #ifdef MOZ_XUL
    4452             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGrid, NS_NewGridBoxFrame),
    4453             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineGrid, NS_NewGridBoxFrame),
    4454             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGridGroup,
    4455             :                                   NS_NewGridRowGroupFrame),
    4456             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGridLine,
    4457             :                                   NS_NewGridRowLeafFrame),
    4458             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozStack, NS_NewStackFrame),
    4459             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineStack, NS_NewStackFrame),
    4460             :     SIMPLE_XUL_DISPLAY_CREATE(StyleDisplay::MozDeck, NS_NewDeckFrame),
    4461             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGroupbox, NS_NewGroupBoxFrame),
    4462             :     FCDATA_FOR_DISPLAY(StyleDisplay::MozPopup,
    4463             :       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
    4464             :                   FCDATA_SKIP_ABSPOS_PUSH, NS_NewMenuPopupFrame))
    4465             : #endif /* MOZ_XUL */
    4466             :   };
    4467             : 
    4468           0 :   if (aDisplay->mDisplay < StyleDisplay::MozBox) {
    4469             :     return nullptr;
    4470             :   }
    4471             : 
    4472         120 :   MOZ_ASSERT(aDisplay->mDisplay <= StyleDisplay::MozPopup,
    4473             :              "Someone added a new display value?");
    4474             : 
    4475         120 :   if (aDisplay->mDisplay == StyleDisplay::MozBox ||
    4476             :       aDisplay->mDisplay == StyleDisplay::MozInlineBox) {
    4477           0 :     if (!aElement->IsInNativeAnonymousSubtree() &&
    4478           1 :         aElement->OwnerDoc()->IsContentDocument()) {
    4479           0 :       aElement->OwnerDoc()->WarnOnceAbout(nsIDocument::eMozBoxOrInlineBoxDisplay);
    4480             :     }
    4481             : 
    4482             :     // If we're emulating -moz-box with flexbox, then treat it as non-XUL and
    4483             :     // return null (except for scrollcorners which have to be XUL becuase their
    4484             :     // parent reflows them with BoxReflow() which means they have to get
    4485             :     // actual-XUL frames).
    4486          70 :     if (StaticPrefs::layout_css_emulate_moz_box_with_flex() &&
    4487           0 :         !aElement->IsXULElement(nsGkAtoms::scrollcorner)) {
    4488             :       return nullptr;
    4489             :     }
    4490             :   }
    4491             : 
    4492             :   const FrameConstructionDataByDisplay& data =
    4493         120 :     sXULDisplayData[size_t(aDisplay->mDisplay) - size_t(StyleDisplay::MozBox)];
    4494         120 :   MOZ_ASSERT(aDisplay->mDisplay == data.mDisplay,
    4495             :              "Did someone mess with the order?");
    4496             : 
    4497         120 :   return &data.mData;
    4498             : }
    4499             : 
    4500             : already_AddRefed<ComputedStyle>
    4501          30 : nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
    4502             :                                                 nsIContent*              aContent,
    4503             :                                                 ComputedStyle*           aContentStyle,
    4504             :                                                 nsContainerFrame*        aParentFrame,
    4505             :                                                 nsAtom*                  aScrolledPseudo,
    4506             :                                                 bool                     aIsRoot,
    4507             :                                                 nsContainerFrame*&       aNewFrame)
    4508             : {
    4509           0 :   nsContainerFrame* gfxScrollFrame = aNewFrame;
    4510             : 
    4511          30 :   nsFrameItems anonymousItems;
    4512             : 
    4513          60 :   RefPtr<ComputedStyle> contentStyle = aContentStyle;
    4514             : 
    4515           0 :   if (!gfxScrollFrame) {
    4516             :     // Build a XULScrollFrame when the child is a box, otherwise an
    4517             :     // HTMLScrollFrame
    4518             :     // XXXbz this is the lone remaining consumer of IsXULDisplayType.
    4519             :     // I wonder whether we can eliminate that somehow.
    4520           0 :     const nsStyleDisplay* displayStyle = aContentStyle->StyleDisplay();
    4521          30 :     if (IsXULDisplayType(displayStyle)) {
    4522          18 :       gfxScrollFrame = NS_NewXULScrollFrame(mPresShell, contentStyle, aIsRoot,
    4523           0 :           displayStyle->mDisplay == StyleDisplay::MozStack ||
    4524           9 :           displayStyle->mDisplay == StyleDisplay::MozInlineStack);
    4525             :     } else {
    4526          42 :       gfxScrollFrame = NS_NewHTMLScrollFrame(mPresShell, contentStyle, aIsRoot);
    4527             :     }
    4528             : 
    4529          30 :     InitAndRestoreFrame(aState, aContent, aParentFrame, gfxScrollFrame);
    4530             :   }
    4531             : 
    4532             :   // if there are any anonymous children for the scroll frame, create
    4533             :   // frames for them.
    4534             :   //
    4535             :   // We can't take the normal ProcessChildren path, because the NAC needs to
    4536             :   // be parented to the scrollframe, and everything else needs to be parented
    4537             :   // to the scrolledframe.
    4538          60 :   AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> scrollNAC;
    4539          90 :   DebugOnly<nsresult> rv = GetAnonymousContent(aContent, gfxScrollFrame, scrollNAC);
    4540           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    4541          30 :   if (scrollNAC.Length() > 0) {
    4542          10 :     AutoFrameConstructionItemList items(this);
    4543           0 :     AddFCItemsForAnonymousContent(aState, gfxScrollFrame, scrollNAC, items);
    4544             :     ConstructFramesFromItemList(aState, items, gfxScrollFrame,
    4545             :                                 /* aParentIsWrapperAnonBox = */ false,
    4546           5 :                                 anonymousItems);
    4547             :   }
    4548             : 
    4549           0 :   aNewFrame = gfxScrollFrame;
    4550          60 :   gfxScrollFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    4551             : 
    4552             :   // we used the style that was passed in. So resolve another one.
    4553          60 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
    4554             :   RefPtr<ComputedStyle> scrolledChildStyle =
    4555           0 :     styleSet->ResolveInheritingAnonymousBoxStyle(aScrolledPseudo, contentStyle);
    4556             : 
    4557          30 :   if (gfxScrollFrame) {
    4558          30 :      gfxScrollFrame->SetInitialChildList(kPrincipalList, anonymousItems);
    4559             :   }
    4560             : 
    4561          60 :   return scrolledChildStyle.forget();
    4562             : }
    4563             : 
    4564             : void
    4565          30 : nsCSSFrameConstructor::FinishBuildingScrollFrame(nsContainerFrame* aScrollFrame,
    4566             :                                                  nsIFrame* aScrolledFrame)
    4567             : {
    4568          30 :   nsFrameList scrolled(aScrolledFrame, aScrolledFrame);
    4569          30 :   aScrollFrame->AppendFrames(kPrincipalList, scrolled);
    4570          30 : }
    4571             : 
    4572             : /**
    4573             :  * Called to wrap a gfx scrollframe around a frame. The hierarchy will look like this
    4574             :  *
    4575             :  * ------- for gfx scrollbars ------
    4576             :  *
    4577             :  *
    4578             :  *            ScrollFrame
    4579             :  *                 ^
    4580             :  *                 |
    4581             :  *               Frame (scrolled frame you passed in)
    4582             :  *
    4583             :  *
    4584             :  *-----------------------------------
    4585             :  * LEGEND:
    4586             :  *
    4587             :  * ScrollFrame: This is a frame that manages gfx cross platform frame based scrollbars.
    4588             :  *
    4589             :  * @param aContent the content node of the child to wrap.
    4590             :  * @param aScrolledFrame The frame of the content to wrap. This should not be
    4591             :  *                    Initialized. This method will initialize it with a scrolled pseudo
    4592             :  *                    and no nsIContent. The content will be attached to the scrollframe
    4593             :  *                    returned.
    4594             :  * @param aContentStyle the style that has already been resolved for the content
    4595             :  *                      being passed in.
    4596             :  *
    4597             :  * @param aParentFrame The parent to attach the scroll frame to
    4598             :  *
    4599             :  * @param aNewFrame The new scrollframe or gfx scrollframe that we create. It will contain the
    4600             :  *                  scrolled frame you passed in. (returned)
    4601             :  *                  If this is not null, we'll just use it
    4602             :  * @param aScrolledContentStyle the style that was resolved for the scrolled frame. (returned)
    4603             :  */
    4604             : void
    4605           9 : nsCSSFrameConstructor::BuildScrollFrame(nsFrameConstructorState& aState,
    4606             :                                         nsIContent*              aContent,
    4607             :                                         ComputedStyle*           aContentStyle,
    4608             :                                         nsIFrame*                aScrolledFrame,
    4609             :                                         nsContainerFrame*        aParentFrame,
    4610             :                                         nsContainerFrame*&       aNewFrame)
    4611             : {
    4612             :   RefPtr<ComputedStyle> scrolledContentStyle =
    4613          18 :     BeginBuildingScrollFrame(aState, aContent, aContentStyle, aParentFrame,
    4614             :                              nsCSSAnonBoxes::scrolledContent,
    4615           0 :                              false, aNewFrame);
    4616             : 
    4617           9 :   aScrolledFrame->SetComputedStyleWithoutNotification(scrolledContentStyle);
    4618           0 :   InitAndRestoreFrame(aState, aContent, aNewFrame, aScrolledFrame);
    4619             : 
    4620           9 :   FinishBuildingScrollFrame(aNewFrame, aScrolledFrame);
    4621           9 : }
    4622             : 
    4623             : const nsCSSFrameConstructor::FrameConstructionData*
    4624          10 : nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
    4625             :                                        Element* aElement,
    4626             :                                        ComputedStyle* aComputedStyle)
    4627             : {
    4628             :   static_assert(eParentTypeCount < (1 << (32 - FCDATA_PARENT_TYPE_OFFSET)),
    4629             :                 "Check eParentTypeCount should not overflow");
    4630             : 
    4631             :   // The style system ensures that floated and positioned frames are
    4632             :   // block-level.
    4633          20 :   NS_ASSERTION(!(aDisplay->IsFloatingStyle() ||
    4634             :                  aDisplay->IsAbsolutelyPositionedStyle()) ||
    4635             :                aDisplay->IsBlockOutsideStyle() ||
    4636             :                aDisplay->mDisplay == StyleDisplay::Contents,
    4637             :                "Style system did not apply CSS2.1 section 9.7 fixups");
    4638             : 
    4639             :   // If this is "body", try propagating its scroll style to the viewport
    4640             :   // Note that we need to do this even if the body is NOT scrollable;
    4641             :   // it might have dynamically changed from scrollable to not scrollable,
    4642             :   // and that might need to be propagated.
    4643             :   // XXXbz is this the right place to do this?  If this code moves,
    4644             :   // make this function static.
    4645          10 :   bool propagatedScrollToViewport = false;
    4646          10 :   if (aElement->IsHTMLElement(nsGkAtoms::body)) {
    4647           0 :     if (nsPresContext* presContext = mPresShell->GetPresContext()) {
    4648           3 :       propagatedScrollToViewport =
    4649           3 :         presContext->UpdateViewportScrollbarStylesOverride() == aElement;
    4650             :     }
    4651             :   }
    4652             : 
    4653          10 :   NS_ASSERTION(!propagatedScrollToViewport ||
    4654             :                !mPresShell->GetPresContext()->IsPaginated(),
    4655             :                "Shouldn't propagate scroll in paginated contexts");
    4656             : 
    4657           0 :   if (aDisplay->IsBlockInsideStyle()) {
    4658             :     // If the frame is a block-level frame and is scrollable, then wrap it in a
    4659             :     // scroll frame.  Except we don't want to do that for paginated contexts for
    4660             :     // frames that are block-outside and aren't frames for native anonymous stuff.
    4661             :     // XXX Ignore tables for the time being (except caption)
    4662             :     const uint32_t kCaptionCtorFlags =
    4663           0 :       FCDATA_IS_TABLE_PART | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable);
    4664           0 :     bool caption = aDisplay->mDisplay == StyleDisplay::TableCaption;
    4665           0 :     bool suppressScrollFrame = false;
    4666           0 :     bool needScrollFrame = aDisplay->IsScrollableOverflow() &&
    4667          10 :                            !propagatedScrollToViewport;
    4668          10 :     if (needScrollFrame) {
    4669          12 :       suppressScrollFrame = mPresShell->GetPresContext()->IsPaginated() &&
    4670           3 :                             aDisplay->IsBlockOutsideStyle() &&
    4671           0 :                             !aElement->IsInNativeAnonymousSubtree();
    4672           3 :       if (!suppressScrollFrame) {
    4673             :         static const FrameConstructionData sScrollableBlockData[2] =
    4674             :           { FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructScrollableBlock),
    4675             :             FULL_CTOR_FCDATA(kCaptionCtorFlags,
    4676             :                              &nsCSSFrameConstructor::ConstructScrollableBlock) };
    4677           3 :         return &sScrollableBlockData[caption];
    4678             :       }
    4679             : 
    4680             :       // If the scrollable frame would have propagated its scrolling to the
    4681             :       // viewport, we still want to construct a regular block rather than a
    4682             :       // scrollframe so that it paginates correctly, but we don't want to set
    4683             :       // the bit on the block that tells it to clip at paint time.
    4684           0 :       if (mPresShell->GetPresContext()->
    4685           0 :             ElementWouldPropagateScrollbarStyles(aElement)) {
    4686           0 :         suppressScrollFrame = false;
    4687             :       }
    4688             :     }
    4689             : 
    4690             :     // Handle various non-scrollable blocks.
    4691             :     static const FrameConstructionData sNonScrollableBlockData[2][2] = {
    4692             :       { FULL_CTOR_FCDATA(0,
    4693             :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock),
    4694             :         FULL_CTOR_FCDATA(kCaptionCtorFlags,
    4695             :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock) },
    4696             :       { FULL_CTOR_FCDATA(FCDATA_FORCED_NON_SCROLLABLE_BLOCK,
    4697             :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock),
    4698             :         FULL_CTOR_FCDATA(FCDATA_FORCED_NON_SCROLLABLE_BLOCK | kCaptionCtorFlags,
    4699             :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock) }
    4700             :     };
    4701           0 :     return &sNonScrollableBlockData[suppressScrollFrame][caption];
    4702             :   }
    4703             : 
    4704             :   // If this is for a <body> node and we've propagated the scroll-frame to the
    4705             :   // viewport, we need to make sure not to add another layer of scrollbars, so
    4706             :   // we use a different FCData struct without FCDATA_MAY_NEED_SCROLLFRAME.
    4707           0 :   if (propagatedScrollToViewport && aDisplay->IsScrollableOverflow()) {
    4708           0 :     if (aDisplay->mDisplay == StyleDisplay::Flex ||
    4709           0 :         aDisplay->mDisplay == StyleDisplay::WebkitBox ||
    4710           0 :         (StaticPrefs::layout_css_emulate_moz_box_with_flex() &&
    4711           0 :          aDisplay->mDisplay == StyleDisplay::MozBox)) {
    4712             :       static const FrameConstructionData sNonScrollableFlexData =
    4713             :         FCDATA_DECL(0, NS_NewFlexContainerFrame);
    4714             :       return &sNonScrollableFlexData;
    4715             :     }
    4716           0 :     if (aDisplay->mDisplay == StyleDisplay::Grid) {
    4717             :       static const FrameConstructionData sNonScrollableGridData =
    4718             :         FCDATA_DECL(0, NS_NewGridContainerFrame);
    4719             :       return &sNonScrollableGridData;
    4720             :     }
    4721             :   }
    4722             : 
    4723             :   // NOTE: Make sure to keep this up to date with the StyleDisplay definition!
    4724             :   static const FrameConstructionDataByDisplay sDisplayData[] = {
    4725             :     FCDATA_FOR_DISPLAY(StyleDisplay::None, UNREACHABLE_FCDATA()),
    4726             :     FCDATA_FOR_DISPLAY(StyleDisplay::Block, UNREACHABLE_FCDATA()),
    4727             :     FCDATA_FOR_DISPLAY(StyleDisplay::FlowRoot, UNREACHABLE_FCDATA()),
    4728             :     // To keep the hash table small don't add inline frames (they're
    4729             :     // typically things like FONT and B), because we can quickly
    4730             :     // find them if we need to.
    4731             :     // XXXbz the "quickly" part is a bald-faced lie!
    4732             :     FCDATA_FOR_DISPLAY(StyleDisplay::Inline,
    4733             :       FULL_CTOR_FCDATA(FCDATA_IS_INLINE | FCDATA_IS_LINE_PARTICIPANT,
    4734             :                        &nsCSSFrameConstructor::ConstructInline)),
    4735             :     FCDATA_FOR_DISPLAY(StyleDisplay::InlineBlock, UNREACHABLE_FCDATA()),
    4736             :     FCDATA_FOR_DISPLAY(StyleDisplay::ListItem, UNREACHABLE_FCDATA()),
    4737             :     FCDATA_FOR_DISPLAY(StyleDisplay::Table,
    4738             :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable)),
    4739             :     FCDATA_FOR_DISPLAY(StyleDisplay::InlineTable,
    4740             :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable)),
    4741             :     // NOTE: In the unlikely event that we add another table-part here that has
    4742             :     // a desired-parent-type (& hence triggers table fixup), we'll need to also
    4743             :     // update the flexbox chunk in ComputedStyle::ApplyStyleFixups().
    4744             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableRowGroup,
    4745             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4746             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4747             :                        &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
    4748             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableColumn,
    4749             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4750             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup),
    4751             :                        &nsCSSFrameConstructor::ConstructTableCol)),
    4752             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableColumnGroup,
    4753             :       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
    4754             :                   FCDATA_SKIP_ABSPOS_PUSH |
    4755             :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4756             :                   NS_NewTableColGroupFrame)),
    4757             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableHeaderGroup,
    4758             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4759             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4760             :                        &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
    4761             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableFooterGroup,
    4762             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4763             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4764             :                        &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
    4765             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableRow,
    4766             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4767             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
    4768             :                        &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
    4769             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableCell,
    4770             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4771             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
    4772             :                        &nsCSSFrameConstructor::ConstructTableCell)),
    4773             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableCaption, UNREACHABLE_FCDATA()),
    4774             :     FCDATA_FOR_DISPLAY(StyleDisplay::Flex,
    4775             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4776             :     FCDATA_FOR_DISPLAY(StyleDisplay::InlineFlex,
    4777             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4778             :     FCDATA_FOR_DISPLAY(StyleDisplay::Grid,
    4779             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame)),
    4780             :     FCDATA_FOR_DISPLAY(StyleDisplay::InlineGrid,
    4781             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame)),
    4782             :     FCDATA_FOR_DISPLAY(StyleDisplay::Ruby,
    4783             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT, NS_NewRubyFrame)),
    4784             :     FCDATA_FOR_DISPLAY(StyleDisplay::RubyBase,
    4785             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
    4786             :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer),
    4787             :                   NS_NewRubyBaseFrame)),
    4788             :     FCDATA_FOR_DISPLAY(StyleDisplay::RubyBaseContainer,
    4789             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
    4790             :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
    4791             :                   NS_NewRubyBaseContainerFrame)),
    4792             :     FCDATA_FOR_DISPLAY(StyleDisplay::RubyText,
    4793             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
    4794             :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer),
    4795             :                   NS_NewRubyTextFrame)),
    4796             :     FCDATA_FOR_DISPLAY(StyleDisplay::RubyTextContainer,
    4797             :       FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
    4798             :                   NS_NewRubyTextContainerFrame)),
    4799             :     FCDATA_FOR_DISPLAY(StyleDisplay::Contents, UNREACHABLE_FCDATA()),
    4800             :     FCDATA_FOR_DISPLAY(StyleDisplay::WebkitBox,
    4801             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4802             :     FCDATA_FOR_DISPLAY(StyleDisplay::WebkitInlineBox,
    4803             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4804             :     FCDATA_FOR_DISPLAY(StyleDisplay::MozBox,
    4805             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4806             :     FCDATA_FOR_DISPLAY(StyleDisplay::MozInlineBox,
    4807             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4808             :   };
    4809             :   static_assert(ArrayLength(sDisplayData) == size_t(StyleDisplay::MozInlineBox) + 1,
    4810             :                 "Be sure to update sDisplayData if you touch StyleDisplay");
    4811           0 :   MOZ_ASSERT(StaticPrefs::layout_css_emulate_moz_box_with_flex() ||
    4812             :              (aDisplay->mDisplay != StyleDisplay::MozBox &&
    4813             :               aDisplay->mDisplay != StyleDisplay::MozInlineBox),
    4814             :              "-moz-{inline-}box as XUL should have already been handled");
    4815           0 :   MOZ_ASSERT(size_t(aDisplay->mDisplay) < ArrayLength(sDisplayData),
    4816             :              "XUL display data should have already been handled");
    4817             : 
    4818             :   // See the mDisplay fixup code in nsRuleNode::ComputeDisplayData.
    4819           0 :   MOZ_ASSERT(aDisplay->mDisplay != StyleDisplay::Contents ||
    4820             :              !aElement->IsRootOfNativeAnonymousSubtree(),
    4821             :              "display:contents on anonymous content is unsupported");
    4822             : 
    4823             :   const FrameConstructionDataByDisplay& data =
    4824           0 :     sDisplayData[size_t(aDisplay->mDisplay)];
    4825             : 
    4826           0 :   MOZ_ASSERT(data.mDisplay == aDisplay->mDisplay,
    4827             :              "Someone messed up the order in the display values");
    4828             : 
    4829           0 :   return &data.mData;
    4830             : }
    4831             : 
    4832             : nsIFrame*
    4833           3 : nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
    4834             :                                                 FrameConstructionItem&   aItem,
    4835             :                                                 nsContainerFrame*        aParentFrame,
    4836             :                                                 const nsStyleDisplay*    aDisplay,
    4837             :                                                 nsFrameItems&            aFrameItems)
    4838             : {
    4839             :   return ConstructScrollableBlockWithConstructor(aState, aItem, aParentFrame,
    4840             :                                                  aDisplay, aFrameItems,
    4841           3 :                                                  NS_NewBlockFormattingContext);
    4842             : }
    4843             : 
    4844             : nsIFrame*
    4845           3 : nsCSSFrameConstructor::ConstructScrollableBlockWithConstructor(
    4846             :   nsFrameConstructorState& aState,
    4847             :   FrameConstructionItem& aItem,
    4848             :   nsContainerFrame* aParentFrame,
    4849             :   const nsStyleDisplay* aDisplay,
    4850             :   nsFrameItems& aFrameItems,
    4851             :   BlockFrameCreationFunc aConstructor)
    4852             : {
    4853           3 :   nsIContent* const content = aItem.mContent;
    4854           6 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    4855             : 
    4856           3 :   nsContainerFrame* newFrame = nullptr;
    4857             :   RefPtr<ComputedStyle> scrolledContentStyle
    4858           6 :     = BeginBuildingScrollFrame(aState, content, computedStyle,
    4859             :                                aState.GetGeometricParent(aDisplay, aParentFrame),
    4860             :                                nsCSSAnonBoxes::scrolledContent,
    4861           6 :                                false, newFrame);
    4862             : 
    4863             :   // Create our block frame
    4864             :   // pass a temporary stylecontext, the correct one will be set later
    4865           0 :   nsContainerFrame* scrolledFrame = aConstructor(mPresShell, computedStyle);
    4866             : 
    4867             :   // Make sure to AddChild before we call ConstructBlock so that we
    4868             :   // end up before our descendants in fixed-pos lists as needed.
    4869           0 :   aState.AddChild(newFrame, aFrameItems, content, aParentFrame);
    4870             : 
    4871           0 :   nsFrameItems blockItem;
    4872           9 :   ConstructBlock(aState, content, newFrame, newFrame, scrolledContentStyle,
    4873             :                  &scrolledFrame, blockItem,
    4874           3 :                  aDisplay->IsAbsPosContainingBlock(newFrame) ? newFrame : nullptr,
    4875           0 :                  aItem.mPendingBinding);
    4876             : 
    4877           3 :   MOZ_ASSERT(blockItem.OnlyChild() == scrolledFrame,
    4878             :              "Scrollframe's frameItems should be exactly the scrolled frame!");
    4879           0 :   FinishBuildingScrollFrame(newFrame, scrolledFrame);
    4880             : 
    4881           6 :   return newFrame;
    4882             : }
    4883             : 
    4884             : nsIFrame*
    4885           7 : nsCSSFrameConstructor::ConstructNonScrollableBlock(nsFrameConstructorState& aState,
    4886             :                                                    FrameConstructionItem&   aItem,
    4887             :                                                    nsContainerFrame*        aParentFrame,
    4888             :                                                    const nsStyleDisplay*    aDisplay,
    4889             :                                                    nsFrameItems&            aFrameItems)
    4890             : {
    4891             :   return ConstructNonScrollableBlockWithConstructor(aState, aItem, aParentFrame,
    4892             :                                                     aDisplay, aFrameItems,
    4893           7 :                                                     NS_NewBlockFrame);
    4894             : }
    4895             : 
    4896             : nsIFrame*
    4897           7 : nsCSSFrameConstructor::ConstructNonScrollableBlockWithConstructor(
    4898             :   nsFrameConstructorState& aState,
    4899             :   FrameConstructionItem& aItem,
    4900             :   nsContainerFrame* aParentFrame,
    4901             :   const nsStyleDisplay* aDisplay,
    4902             :   nsFrameItems& aFrameItems,
    4903             :   BlockFrameCreationFunc aConstructor)
    4904             : {
    4905          14 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    4906             : 
    4907             :   // We want a block formatting context root in paginated contexts for
    4908             :   // every block that would be scrollable in a non-paginated context.
    4909             :   // We mark our blocks with a bit here if this condition is true, so
    4910             :   // we can check it later in nsFrame::ApplyPaginatedOverflowClipping.
    4911             :   bool clipPaginatedOverflow =
    4912           0 :     (aItem.mFCData->mBits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) != 0;
    4913           0 :   nsFrameState flags = nsFrameState(0);
    4914           0 :   if ((aDisplay->IsAbsolutelyPositionedStyle() ||
    4915           6 :        aDisplay->IsFloatingStyle() ||
    4916           6 :        StyleDisplay::InlineBlock == aDisplay->mDisplay ||
    4917          11 :        clipPaginatedOverflow) &&
    4918           4 :       !nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
    4919           0 :     flags = NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS;
    4920           0 :     if (clipPaginatedOverflow) {
    4921             :       flags |= NS_BLOCK_CLIP_PAGINATED_OVERFLOW;
    4922             :     }
    4923             :   }
    4924             : 
    4925           0 :   nsContainerFrame* newFrame = aConstructor(mPresShell, computedStyle);
    4926           0 :   newFrame->AddStateBits(flags);
    4927           0 :   ConstructBlock(aState, aItem.mContent,
    4928             :                  aState.GetGeometricParent(aDisplay, aParentFrame),
    4929             :                  aParentFrame, computedStyle, &newFrame,
    4930             :                  aFrameItems,
    4931           7 :                  aDisplay->IsAbsPosContainingBlock(newFrame) ? newFrame : nullptr,
    4932           0 :                  aItem.mPendingBinding);
    4933           7 :   return newFrame;
    4934             : }
    4935             : 
    4936             : 
    4937             : void
    4938           0 : nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
    4939             :                                            nsIContent*              aContent,
    4940             :                                            nsContainerFrame*        aParentFrame,
    4941             :                                            nsIFrame*                aNewFrame,
    4942             :                                            bool                     aAllowCounters)
    4943             : {
    4944           0 :   MOZ_ASSERT(aNewFrame, "Null frame cannot be initialized");
    4945             : 
    4946             :   // Initialize the frame
    4947         331 :   aNewFrame->Init(aContent, aParentFrame, nullptr);
    4948         662 :   aNewFrame->AddStateBits(aState.mAdditionalStateBits);
    4949             : 
    4950           0 :   if (aState.mFrameState) {
    4951             :     // Restore frame state for just the newly created frame.
    4952          98 :     RestoreFrameStateFor(aNewFrame, aState.mFrameState);
    4953             :   }
    4954             : 
    4955         659 :   if (aAllowCounters &&
    4956           0 :       mCounterManager.AddCounterResetsAndIncrements(aNewFrame)) {
    4957           0 :     CountersDirty();
    4958             :   }
    4959         331 : }
    4960             : 
    4961             : already_AddRefed<ComputedStyle>
    4962         502 : nsCSSFrameConstructor::ResolveComputedStyle(nsIContent* aContent)
    4963             : {
    4964           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
    4965             : 
    4966        1004 :   if (aContent->IsElement()) {
    4967         459 :     return styleSet->ResolveServoStyle(aContent->AsElement());
    4968             :   }
    4969             : 
    4970          43 :   MOZ_ASSERT(aContent->IsText(),
    4971             :              "shouldn't waste time creating ComputedStyles for "
    4972             :              "comments and processing instructions");
    4973             : 
    4974          43 :   Element* parent = aContent->GetFlattenedTreeParentElement();
    4975          43 :   MOZ_ASSERT(parent, "Text out of the flattened tree?");
    4976             : 
    4977             :   // FIXME(emilio): We can't use ResolveServoStyle properly because this text
    4978             :   // node can come from non-lazy frame construction, in which case the style we
    4979             :   // inherit from can indeed be out-of-date. After an eventual XBL removal, this
    4980             :   // can go. Note that this is not a correctness issue, since we'll restyle
    4981             :   // later in any case.
    4982             :   //
    4983             :   // Also, this probably doesn't need to be a strong ref...
    4984             :   //
    4985             :   // Do NOT add new callers to this function in this file, ever, or I'll find
    4986             :   // out.
    4987             :   RefPtr<ComputedStyle> parentStyle =
    4988           0 :     Servo_Element_GetPrimaryComputedValues(parent).Consume();
    4989          43 :   return styleSet->ResolveStyleForText(aContent, parentStyle);
    4990             : }
    4991             : 
    4992             : // MathML Mod - RBS
    4993             : void
    4994           0 : nsCSSFrameConstructor::FlushAccumulatedBlock(nsFrameConstructorState& aState,
    4995             :                                              nsIContent* aContent,
    4996             :                                              nsContainerFrame* aParentFrame,
    4997             :                                              nsFrameItems& aBlockItems,
    4998             :                                              nsFrameItems& aNewItems)
    4999             : {
    5000           0 :   if (aBlockItems.IsEmpty()) {
    5001             :     // Nothing to do
    5002           0 :     return;
    5003             :   }
    5004             : 
    5005           0 :   nsAtom* anonPseudo = nsCSSAnonBoxes::mozMathMLAnonymousBlock;
    5006             : 
    5007             :   ComputedStyle* parentContext =
    5008             :     nsFrame::CorrectStyleParentFrame(aParentFrame,
    5009           0 :                                      anonPseudo)->Style();
    5010           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
    5011           0 :   RefPtr<ComputedStyle> blockContext;
    5012             :   blockContext = styleSet->
    5013           0 :     ResolveInheritingAnonymousBoxStyle(anonPseudo, parentContext);
    5014             : 
    5015             :   // then, create a block frame that will wrap the child frames. Make it a
    5016             :   // MathML frame so that Get(Absolute/Float)ContainingBlockFor know that this
    5017             :   // is not a suitable block.
    5018             :   nsContainerFrame* blockFrame =
    5019           0 :     NS_NewMathMLmathBlockFrame(mPresShell, blockContext);
    5020             : 
    5021           0 :   InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
    5022           0 :   ReparentFrames(this, blockFrame, aBlockItems, false);
    5023             :   // We have to walk over aBlockItems before we hand it over to blockFrame.
    5024           0 :   for (nsIFrame* f : aBlockItems) {
    5025           0 :     f->SetParentIsWrapperAnonBox();
    5026             :   }
    5027             :   // abs-pos and floats are disabled in MathML children so we don't have to
    5028             :   // worry about messing up those.
    5029           0 :   blockFrame->SetInitialChildList(kPrincipalList, aBlockItems);
    5030           0 :   NS_ASSERTION(aBlockItems.IsEmpty(), "What happened?");
    5031           0 :   aBlockItems.Clear();
    5032           0 :   aNewItems.AddChild(blockFrame);
    5033             : }
    5034             : 
    5035             : // Only <math> elements can be floated or positioned.  All other MathML
    5036             : // should be in-flow.
    5037             : #define SIMPLE_MATHML_CREATE(_tag, _func)                               \
    5038             :   { &nsGkAtoms::_tag,                                                   \
    5039             :       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                         \
    5040             :                   FCDATA_FORCE_NULL_ABSPOS_CONTAINER |                  \
    5041             :                   FCDATA_WRAP_KIDS_IN_BLOCKS, _func) }
    5042             : 
    5043             : /* static */
    5044             : const nsCSSFrameConstructor::FrameConstructionData*
    5045           0 : nsCSSFrameConstructor::FindMathMLData(Element* aElement,
    5046             :                                       nsAtom* aTag,
    5047             :                                       int32_t aNameSpaceID,
    5048             :                                       ComputedStyle* aComputedStyle)
    5049             : {
    5050             :   // Make sure that we remain confined in the MathML world
    5051         145 :   if (aNameSpaceID != kNameSpaceID_MathML)
    5052             :     return nullptr;
    5053             : 
    5054             :   // Handle <math> specially, because it sometimes produces inlines
    5055           0 :   if (aTag == nsGkAtoms::math) {
    5056             :     // This needs to match the test in EnsureBlockDisplay in
    5057             :     // nsRuleNode.cpp.  Though the behavior here for the display:table
    5058             :     // case is pretty weird...
    5059           0 :     if (aComputedStyle->StyleDisplay()->IsBlockOutsideStyle()) {
    5060             :       static const FrameConstructionData sBlockMathData =
    5061             :         FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
    5062             :                     FCDATA_WRAP_KIDS_IN_BLOCKS,
    5063             :                     NS_NewMathMLmathBlockFrame);
    5064             :       return &sBlockMathData;
    5065             :     }
    5066             : 
    5067             :     static const FrameConstructionData sInlineMathData =
    5068             :       FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
    5069             :                   FCDATA_IS_LINE_PARTICIPANT |
    5070             :                   FCDATA_WRAP_KIDS_IN_BLOCKS,
    5071             :                   NS_NewMathMLmathInlineFrame);
    5072           0 :     return &sInlineMathData;
    5073             :   }
    5074             : 
    5075             : 
    5076             :   static const FrameConstructionDataByTag sMathMLData[] = {
    5077             :     SIMPLE_MATHML_CREATE(annotation_, NS_NewMathMLTokenFrame),
    5078             :     SIMPLE_MATHML_CREATE(annotation_xml_, NS_NewMathMLmrowFrame),
    5079             :     SIMPLE_MATHML_CREATE(mi_, NS_NewMathMLTokenFrame),
    5080             :     SIMPLE_MATHML_CREATE(mn_, NS_NewMathMLTokenFrame),
    5081             :     SIMPLE_MATHML_CREATE(ms_, NS_NewMathMLTokenFrame),
    5082             :     SIMPLE_MATHML_CREATE(mtext_, NS_NewMathMLTokenFrame),
    5083             :     SIMPLE_MATHML_CREATE(mo_, NS_NewMathMLmoFrame),
    5084             :     SIMPLE_MATHML_CREATE(mfrac_, NS_NewMathMLmfracFrame),
    5085             :     SIMPLE_MATHML_CREATE(msup_, NS_NewMathMLmmultiscriptsFrame),
    5086             :     SIMPLE_MATHML_CREATE(msub_, NS_NewMathMLmmultiscriptsFrame),
    5087             :     SIMPLE_MATHML_CREATE(msubsup_, NS_NewMathMLmmultiscriptsFrame),
    5088             :     SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderoverFrame),
    5089             :     SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmunderoverFrame),
    5090             :     SIMPLE_MATHML_CREATE(munderover_, NS_NewMathMLmunderoverFrame),
    5091             :     SIMPLE_MATHML_CREATE(mphantom_, NS_NewMathMLmrowFrame),
    5092             :     SIMPLE_MATHML_CREATE(mpadded_, NS_NewMathMLmpaddedFrame),
    5093             :     SIMPLE_MATHML_CREATE(mspace_, NS_NewMathMLmspaceFrame),
    5094             :     SIMPLE_MATHML_CREATE(none, NS_NewMathMLmspaceFrame),
    5095             :     SIMPLE_MATHML_CREATE(mprescripts_, NS_NewMathMLmspaceFrame),
    5096             :     SIMPLE_MATHML_CREATE(mfenced_, NS_NewMathMLmfencedFrame),
    5097             :     SIMPLE_MATHML_CREATE(mmultiscripts_, NS_NewMathMLmmultiscriptsFrame),
    5098             :     SIMPLE_MATHML_CREATE(mstyle_, NS_NewMathMLmrowFrame),
    5099             :     SIMPLE_MATHML_CREATE(msqrt_, NS_NewMathMLmsqrtFrame),
    5100             :     SIMPLE_MATHML_CREATE(mroot_, NS_NewMathMLmrootFrame),
    5101             :     SIMPLE_MATHML_CREATE(maction_, NS_NewMathMLmactionFrame),
    5102             :     SIMPLE_MATHML_CREATE(mrow_, NS_NewMathMLmrowFrame),
    5103             :     SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame),
    5104             :     SIMPLE_MATHML_CREATE(menclose_, NS_NewMathMLmencloseFrame),
    5105             :     SIMPLE_MATHML_CREATE(semantics_, NS_NewMathMLsemanticsFrame)
    5106             :   };
    5107             : 
    5108             :   return FindDataByTag(aTag, aElement, aComputedStyle, sMathMLData,
    5109           0 :                        ArrayLength(sMathMLData));
    5110             : }
    5111             : 
    5112             : 
    5113             : nsContainerFrame*
    5114          13 : nsCSSFrameConstructor::ConstructFrameWithAnonymousChild(
    5115             :                                    nsFrameConstructorState& aState,
    5116             :                                    FrameConstructionItem&   aItem,
    5117             :                                    nsContainerFrame*        aParentFrame,
    5118             :                                    nsFrameItems&            aFrameItems,
    5119             :                                    ContainerFrameCreationFunc aConstructor,
    5120             :                                    ContainerFrameCreationFunc aInnerConstructor,
    5121             :                                    nsICSSAnonBoxPseudo*     aInnerPseudo,
    5122             :                                    bool                     aCandidateRootFrame)
    5123             : {
    5124           0 :   nsIContent* const content = aItem.mContent;
    5125          26 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
    5126             : 
    5127             :   // Create the outer frame:
    5128          13 :   nsContainerFrame* newFrame = aConstructor(mPresShell, computedStyle);
    5129             : 
    5130           0 :   InitAndRestoreFrame(aState, content,
    5131             :                       aCandidateRootFrame ?
    5132          13 :                         aState.GetGeometricParent(computedStyle->StyleDisplay(),
    5133             :                                                   aParentFrame) :
    5134             :                         aParentFrame,
    5135           0 :                       newFrame);
    5136          26 :   newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    5137             : 
    5138             :   // Create the pseudo SC for the anonymous wrapper child as a child of the SC:
    5139          26 :   RefPtr<ComputedStyle> scForAnon;
    5140           0 :   scForAnon = mPresShell->StyleSet()->
    5141          13 :     ResolveInheritingAnonymousBoxStyle(aInnerPseudo, computedStyle);
    5142             : 
    5143             :   // Create the anonymous inner wrapper frame
    5144          13 :   nsContainerFrame* innerFrame = aInnerConstructor(mPresShell, scForAnon);
    5145             : 
    5146           0 :   InitAndRestoreFrame(aState, content, newFrame, innerFrame);
    5147             : 
    5148             :   // Put the newly created frames into the right child list
    5149          13 :   SetInitialSingleChild(newFrame, innerFrame);
    5150             : 
    5151           0 :   aState.AddChild(newFrame, aFrameItems, content, aParentFrame,
    5152          13 :                   aCandidateRootFrame, aCandidateRootFrame);
    5153             : 
    5154           0 :   if (!mRootElementFrame && aCandidateRootFrame) {
    5155             :     // The frame we're constructing will be the root element frame.
    5156             :     // Set mRootElementFrame before processing children.
    5157           0 :     mRootElementFrame = newFrame;
    5158             :   }
    5159             : 
    5160          13 :   nsFrameItems childItems;
    5161             : 
    5162             :   // Process children
    5163          26 :   NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
    5164             :                "nsIAnonymousContentCreator::CreateAnonymousContent should not "
    5165             :                "be implemented for frames for which we explicitly create an "
    5166             :                "anonymous child to wrap its child frames");
    5167           0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    5168           0 :     ConstructFramesFromItemList(aState, aItem.mChildItems,
    5169             :                                 innerFrame,
    5170           0 :                                 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX,
    5171           0 :                                 childItems);
    5172             :   } else {
    5173          13 :     ProcessChildren(aState, content, computedStyle, innerFrame,
    5174           0 :                     true, childItems, false, aItem.mPendingBinding);
    5175             :   }
    5176             : 
    5177             :   // Set the inner wrapper frame's initial primary list
    5178           0 :   innerFrame->SetInitialChildList(kPrincipalList, childItems);
    5179             : 
    5180          13 :   return newFrame;
    5181             : }
    5182             : 
    5183             : nsIFrame*
    5184           0 : nsCSSFrameConstructor::ConstructOuterSVG(nsFrameConstructorState& aState,
    5185             :                                          FrameConstructionItem&   aItem,
    5186             :                                          nsContainerFrame*        aParentFrame,
    5187             :                                          const nsStyleDisplay*    aDisplay,
    5188             :                                          nsFrameItems&            aFrameItems)
    5189             : {
    5190          13 :   return ConstructFrameWithAnonymousChild(
    5191             :       aState, aItem, aParentFrame, aFrameItems,
    5192             :       NS_NewSVGOuterSVGFrame, NS_NewSVGOuterSVGAnonChildFrame,
    5193          13 :       nsCSSAnonBoxes::mozSVGOuterSVGAnonChild, true);
    5194             : }
    5195             : 
    5196             : nsIFrame*
    5197           0 : nsCSSFrameConstructor::ConstructMarker(nsFrameConstructorState& aState,
    5198             :                                        FrameConstructionItem&   aItem,
    5199             :                                        nsContainerFrame*        aParentFrame,
    5200             :                                        const nsStyleDisplay*    aDisplay,
    5201             :                                        nsFrameItems&            aFrameItems)
    5202             : {
    5203           0 :   return ConstructFrameWithAnonymousChild(
    5204             :       aState, aItem, aParentFrame, aFrameItems,
    5205             :       NS_NewSVGMarkerFrame, NS_NewSVGMarkerAnonChildFrame,
    5206           0 :       nsCSSAnonBoxes::mozSVGMarkerAnonChild, false);
    5207             : }
    5208             : 
    5209             : // Only outer <svg> elements can be floated or positioned.  All other SVG
    5210             : // should be in-flow.
    5211             : #define SIMPLE_SVG_FCDATA(_func)                                        \
    5212             :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
    5213             :               FCDATA_SKIP_ABSPOS_PUSH |                                 \
    5214             :               FCDATA_DISALLOW_GENERATED_CONTENT,  _func)
    5215             : #define SIMPLE_SVG_CREATE(_tag, _func)            \
    5216             :   { &nsGkAtoms::_tag, SIMPLE_SVG_FCDATA(_func) }
    5217             : 
    5218             : static bool
    5219           0 : IsFilterPrimitiveChildTag(const nsAtom* aTag)
    5220             : {
    5221           0 :   return aTag == nsGkAtoms::feDistantLight ||
    5222           0 :          aTag == nsGkAtoms::fePointLight ||
    5223          30 :          aTag == nsGkAtoms::feSpotLight ||
    5224          30 :          aTag == nsGkAtoms::feFuncR ||
    5225          30 :          aTag == nsGkAtoms::feFuncG ||
    5226          30 :          aTag == nsGkAtoms::feFuncB ||
    5227           0 :          aTag == nsGkAtoms::feFuncA ||
    5228          30 :          aTag == nsGkAtoms::feMergeNode;
    5229             : }
    5230             : 
    5231             : /* static */
    5232             : const nsCSSFrameConstructor::FrameConstructionData*
    5233         145 : nsCSSFrameConstructor::FindSVGData(Element* aElement,
    5234             :                                    nsAtom* aTag,
    5235             :                                    int32_t aNameSpaceID,
    5236             :                                    nsIFrame* aParentFrame,
    5237             :                                    bool aIsWithinSVGText,
    5238             :                                    bool aAllowsTextPathChild,
    5239             :                                    ComputedStyle* aComputedStyle)
    5240             : {
    5241         145 :   if (aNameSpaceID != kNameSpaceID_SVG) {
    5242             :     return nullptr;
    5243             :   }
    5244             : 
    5245             :   static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
    5246             :   static const FrameConstructionData sContainerData =
    5247             :     SIMPLE_SVG_FCDATA(NS_NewSVGContainerFrame);
    5248             : 
    5249          15 :   bool parentIsSVG = aIsWithinSVGText;
    5250             :   nsIContent* parentContent =
    5251          30 :     aParentFrame ? aParentFrame->GetContent() : nullptr;
    5252             : 
    5253             :   // XXXbz should this really be based on the tag of the parent frame's content?
    5254             :   // Should it not be based on the type of the parent frame (e.g. whether it's
    5255             :   // an SVG frame)?
    5256           0 :   if (parentContent) {
    5257             :     // It's not clear whether the SVG spec intends to allow any SVG
    5258             :     // content within svg:foreignObject at all (SVG 1.1, section
    5259             :     // 23.2), but if it does, it better be svg:svg.  So given that
    5260             :     // we're allowing it, treat it as a non-SVG parent.
    5261             :     parentIsSVG =
    5262           0 :       parentContent->IsSVGElement() &&
    5263          30 :       parentContent->NodeInfo()->NameAtom() != nsGkAtoms::foreignObject;
    5264             :   }
    5265             : 
    5266          30 :   if ((aTag != nsGkAtoms::svg && !parentIsSVG) ||
    5267          45 :       (aTag == nsGkAtoms::desc || aTag == nsGkAtoms::title ||
    5268          15 :        aTag == nsGkAtoms::metadata)) {
    5269             :     // Sections 5.1 and G.4 of SVG 1.1 say that SVG elements other than
    5270             :     // svg:svg not contained within svg:svg are incorrect, although they
    5271             :     // don't seem to specify error handling.  Ignore them, since many of
    5272             :     // our frame classes can't deal.  It *may* be that the document
    5273             :     // should at that point be considered in error according to F.2, but
    5274             :     // it's hard to tell.
    5275             :     //
    5276             :     // Style mutation can't change this situation, so don't bother
    5277             :     // adding to the undisplayed content map.
    5278             :     //
    5279             :     // We don't currently handle any UI for desc/title/metadata
    5280             :     return &sSuppressData;
    5281             :   }
    5282             : 
    5283             :   // We don't need frames for animation elements
    5284          15 :   if (aElement->IsNodeOfType(nsINode::eANIMATION)) {
    5285             :     return &sSuppressData;
    5286             :   }
    5287             : 
    5288          15 :   if (aTag == nsGkAtoms::svg && !parentIsSVG) {
    5289             :     // We need outer <svg> elements to have an nsSVGOuterSVGFrame regardless
    5290             :     // of whether they fail conditional processing attributes, since various
    5291             :     // SVG frames assume that one exists.  We handle the non-rendering
    5292             :     // of failing outer <svg> element contents like <switch> statements,
    5293             :     // and do the PassesConditionalProcessingTests call in
    5294             :     // nsSVGOuterSVGFrame::Init.
    5295             :     static const FrameConstructionData sOuterSVGData =
    5296             :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructOuterSVG);
    5297             :     return &sOuterSVGData;
    5298             :   }
    5299             : 
    5300           0 :   if (aTag == nsGkAtoms::marker) {
    5301             :     static const FrameConstructionData sMarkerSVGData =
    5302             :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructMarker);
    5303             :     return &sMarkerSVGData;
    5304             :   }
    5305             : 
    5306          30 :   nsCOMPtr<SVGTests> tests(do_QueryInterface(aElement));
    5307          15 :   if (tests && !tests->PassesConditionalProcessingTests()) {
    5308             :     // Elements with failing conditional processing attributes never get
    5309             :     // rendered.  Note that this is not where we select which frame in a
    5310             :     // <switch> to render!  That happens in nsSVGSwitchFrame::PaintSVG.
    5311           0 :     if (aIsWithinSVGText) {
    5312             :       // SVGTextFrame doesn't handle conditional processing attributes,
    5313             :       // so don't create frames for descendants of <text> with failing
    5314             :       // attributes.  We need frames not to be created so that text layout
    5315             :       // is correct.
    5316             :       return &sSuppressData;
    5317             :     }
    5318             :     // If we're not inside <text>, create an nsSVGContainerFrame (which is a
    5319             :     // frame that doesn't render) so that paint servers can still be referenced,
    5320             :     // even if they live inside an element with failing conditional processing
    5321             :     // attributes.
    5322           0 :     return &sContainerData;
    5323             :   }
    5324             : 
    5325             :   // Ensure that a stop frame is a child of a gradient and that gradients
    5326             :   // can only have stop children.
    5327             :   bool parentIsGradient =
    5328          30 :     aParentFrame && (aParentFrame->IsSVGLinearGradientFrame() ||
    5329          30 :                      aParentFrame->IsSVGRadialGradientFrame());
    5330          15 :   bool stop = (aTag == nsGkAtoms::stop);
    5331          15 :   if ((parentIsGradient && !stop) ||
    5332             :       (!parentIsGradient && stop)) {
    5333             :     return &sSuppressData;
    5334             :   }
    5335             : 
    5336             :   // Prevent bad frame types being children of filters or parents of filter
    5337             :   // primitives.  If aParentFrame is null, we know that the frame that will
    5338             :   // be created will be an nsInlineFrame, so it can never be a filter.
    5339          15 :   bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
    5340          15 :   bool filterPrimitive = aElement->IsNodeOfType(nsINode::eFILTER);
    5341          15 :   if ((parentIsFilter && !filterPrimitive) ||
    5342             :       (!parentIsFilter && filterPrimitive)) {
    5343             :     return &sSuppressData;
    5344             :   }
    5345             : 
    5346             :   // Prevent bad frame types being children of filter primitives or parents of
    5347             :   // filter primitive children.  If aParentFrame is null, we know that the frame
    5348             :   // that will be created will be an nsInlineFrame, so it can never be a filter
    5349             :   // primitive.
    5350             :   bool parentIsFEContainerFrame =
    5351          15 :     aParentFrame && aParentFrame->IsSVGFEContainerFrame();
    5352          30 :   if ((parentIsFEContainerFrame && !IsFilterPrimitiveChildTag(aTag)) ||
    5353          15 :       (!parentIsFEContainerFrame && IsFilterPrimitiveChildTag(aTag))) {
    5354             :     return &sSuppressData;
    5355             :   }
    5356             : 
    5357             :   // Special cases for text/tspan/textPath, because the kind of frame
    5358             :   // they get depends on the parent frame.  We ignore 'a' elements when
    5359             :   // determining the parent, however.
    5360          15 :   if (aIsWithinSVGText) {
    5361             :     // If aIsWithinSVGText is true, then we know that the "SVG text uses
    5362             :     // CSS frames" pref was true when this SVG fragment was first constructed.
    5363             : 
    5364             :     // We don't use ConstructInline because we want different behavior
    5365             :     // for generated content.
    5366             :     static const FrameConstructionData sTSpanData =
    5367             :       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |
    5368             :                   FCDATA_SKIP_ABSPOS_PUSH |
    5369             :                   FCDATA_DISALLOW_GENERATED_CONTENT |
    5370             :                   FCDATA_IS_LINE_PARTICIPANT |
    5371             :                   FCDATA_IS_INLINE |
    5372             :                   FCDATA_USE_CHILD_ITEMS,
    5373             :                   NS_NewInlineFrame);
    5374           0 :     if (aTag == nsGkAtoms::textPath) {
    5375           0 :       if (aAllowsTextPathChild) {
    5376             :         return &sTSpanData;
    5377             :       }
    5378           0 :     } else if (aTag == nsGkAtoms::tspan ||
    5379           0 :                aTag == nsGkAtoms::a) {
    5380             :       return &sTSpanData;
    5381             :     }
    5382           0 :     return &sSuppressData;
    5383          30 :   } else if (aTag == nsGkAtoms::tspan ||
    5384          15 :              aTag == nsGkAtoms::textPath) {
    5385             :     return &sSuppressData;
    5386             :   }
    5387             : 
    5388             :   static const FrameConstructionDataByTag sSVGData[] = {
    5389             :     SIMPLE_SVG_CREATE(svg, NS_NewSVGInnerSVGFrame),
    5390             :     SIMPLE_SVG_CREATE(g, NS_NewSVGGFrame),
    5391             :     SIMPLE_SVG_CREATE(svgSwitch, NS_NewSVGSwitchFrame),
    5392             :     SIMPLE_SVG_CREATE(symbol, NS_NewSVGSymbolFrame),
    5393             :     SIMPLE_SVG_CREATE(polygon, NS_NewSVGGeometryFrame),
    5394             :     SIMPLE_SVG_CREATE(polyline, NS_NewSVGGeometryFrame),
    5395             :     SIMPLE_SVG_CREATE(circle, NS_NewSVGGeometryFrame),
    5396             :     SIMPLE_SVG_CREATE(ellipse, NS_NewSVGGeometryFrame),
    5397             :     SIMPLE_SVG_CREATE(line, NS_NewSVGGeometryFrame),
    5398             :     SIMPLE_SVG_CREATE(rect, NS_NewSVGGeometryFrame),
    5399             :     SIMPLE_SVG_CREATE(path, NS_NewSVGGeometryFrame),
    5400             :     SIMPLE_SVG_CREATE(defs, NS_NewSVGContainerFrame),
    5401             :     SIMPLE_SVG_CREATE(generic_, NS_NewSVGGenericContainerFrame),
    5402             :     { &nsGkAtoms::text,
    5403             :       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_DISALLOW_OUT_OF_FLOW |
    5404             :                                  FCDATA_ALLOW_BLOCK_STYLES,
    5405             :                                  NS_NewSVGTextFrame,
    5406             :                                  nsCSSAnonBoxes::mozSVGText) },
    5407             :     { &nsGkAtoms::foreignObject,
    5408             :       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_DISALLOW_OUT_OF_FLOW,
    5409             :                                  NS_NewSVGForeignObjectFrame,
    5410             :                                  nsCSSAnonBoxes::mozSVGForeignContent) },
    5411             :     SIMPLE_SVG_CREATE(a, NS_NewSVGAFrame),
    5412             :     SIMPLE_SVG_CREATE(linearGradient, NS_NewSVGLinearGradientFrame),
    5413             :     SIMPLE_SVG_CREATE(radialGradient, NS_NewSVGRadialGradientFrame),
    5414             :     SIMPLE_SVG_CREATE(stop, NS_NewSVGStopFrame),
    5415             :     SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame),
    5416             :     SIMPLE_SVG_CREATE(view, NS_NewSVGViewFrame),
    5417             :     SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame),
    5418             :     SIMPLE_SVG_CREATE(clipPath, NS_NewSVGClipPathFrame),
    5419             :     SIMPLE_SVG_CREATE(filter, NS_NewSVGFilterFrame),
    5420             :     SIMPLE_SVG_CREATE(pattern, NS_NewSVGPatternFrame),
    5421             :     SIMPLE_SVG_CREATE(mask, NS_NewSVGMaskFrame),
    5422             :     SIMPLE_SVG_CREATE(feDistantLight, NS_NewSVGFEUnstyledLeafFrame),
    5423             :     SIMPLE_SVG_CREATE(fePointLight, NS_NewSVGFEUnstyledLeafFrame),
    5424             :     SIMPLE_SVG_CREATE(feSpotLight, NS_NewSVGFEUnstyledLeafFrame),
    5425             :     SIMPLE_SVG_CREATE(feBlend, NS_NewSVGFELeafFrame),
    5426             :     SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGFELeafFrame),
    5427             :     SIMPLE_SVG_CREATE(feFuncR, NS_NewSVGFEUnstyledLeafFrame),
    5428             :     SIMPLE_SVG_CREATE(feFuncG, NS_NewSVGFEUnstyledLeafFrame),
    5429             :     SIMPLE_SVG_CREATE(feFuncB, NS_NewSVGFEUnstyledLeafFrame),
    5430             :     SIMPLE_SVG_CREATE(feFuncA, NS_NewSVGFEUnstyledLeafFrame),
    5431             :     SIMPLE_SVG_CREATE(feComposite, NS_NewSVGFELeafFrame),
    5432             :     SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGFEContainerFrame),
    5433             :     SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGFELeafFrame),
    5434             :     SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGFEContainerFrame),
    5435             :     SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGFELeafFrame),
    5436             :     SIMPLE_SVG_CREATE(feDropShadow, NS_NewSVGFELeafFrame),
    5437             :     SIMPLE_SVG_CREATE(feFlood, NS_NewSVGFELeafFrame),
    5438             :     SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGFELeafFrame),
    5439             :     SIMPLE_SVG_CREATE(feImage, NS_NewSVGFEImageFrame),
    5440             :     SIMPLE_SVG_CREATE(feMerge, NS_NewSVGFEContainerFrame),
    5441             :     SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGFEUnstyledLeafFrame),
    5442             :     SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGFELeafFrame),
    5443             :     SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame),
    5444             :     SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame),
    5445             :     SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame),
    5446             :     SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame)
    5447             :   };
    5448             : 
    5449             :   const FrameConstructionData* data =
    5450             :     FindDataByTag(aTag, aElement, aComputedStyle, sSVGData,
    5451          15 :                   ArrayLength(sSVGData));
    5452             : 
    5453          15 :   if (!data) {
    5454           0 :     data = &sContainerData;
    5455             :   }
    5456             : 
    5457             :   return data;
    5458             : }
    5459             : 
    5460             : void
    5461           0 : nsCSSFrameConstructor::AddPageBreakItem(nsIContent* aContent,
    5462             :                                         FrameConstructionItemList& aItems)
    5463             : {
    5464             :   RefPtr<ComputedStyle> pseudoStyle =
    5465           0 :     mPresShell->StyleSet()->
    5466           0 :       ResolveNonInheritingAnonymousBoxStyle(nsCSSAnonBoxes::pageBreak);
    5467             : 
    5468           0 :   MOZ_ASSERT(pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block,
    5469             :              "Unexpected display");
    5470             : 
    5471             :   static const FrameConstructionData sPageBreakData =
    5472             :     FCDATA_DECL(FCDATA_SKIP_FRAMESET, NS_NewPageBreakFrame);
    5473             : 
    5474             :   aItems.AppendItem(this, &sPageBreakData, aContent, nullptr,
    5475           0 :                     pseudoStyle.forget(), true, nullptr);
    5476           0 : }
    5477             : 
    5478             : bool
    5479         419 : nsCSSFrameConstructor::ShouldCreateItemsForChild(nsFrameConstructorState& aState,
    5480             :                                                  nsIContent* aContent,
    5481             :                                                  nsContainerFrame* aParentFrame)
    5482             : {
    5483         419 :   aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
    5484             :   // XXX the GetContent() != aContent check is needed due to bug 135040.
    5485             :   // Remove it once that's fixed.
    5486         838 :   if (aContent->GetPrimaryFrame() &&
    5487         419 :       aContent->GetPrimaryFrame()->GetContent() == aContent &&
    5488           0 :       !aState.mCreatingExtraFrames) {
    5489             :     // This condition is known to be reachable for listitems, assert fatally
    5490             :     // elsewhere.
    5491           0 :     MOZ_ASSERT(MaybeGetListBoxBodyFrame(aContent),
    5492             :                "asked to create frame construction item for a node that "
    5493             :                "already has a frame");
    5494           0 :     NS_ERROR("asked to create frame construction item for a node that already "
    5495             :              "has a frame");
    5496           0 :     return false;
    5497             :   }
    5498             : 
    5499             :   // don't create a whitespace frame if aParent doesn't want it
    5500         419 :   if (!NeedFrameFor(aState, aParentFrame, aContent)) {
    5501             :     return false;
    5502             :   }
    5503             : 
    5504             :   // never create frames for comments or PIs
    5505         419 :   if (aContent->IsComment() || aContent->IsProcessingInstruction()) {
    5506             :     return false;
    5507             :   }
    5508             : 
    5509         415 :   return true;
    5510             : }
    5511             : 
    5512             : void
    5513         415 : nsCSSFrameConstructor::DoAddFrameConstructionItems(nsFrameConstructorState& aState,
    5514             :                                                    nsIContent* aContent,
    5515             :                                                    ComputedStyle* aComputedStyle,
    5516             :                                                    bool aSuppressWhiteSpaceOptimizations,
    5517             :                                                    nsContainerFrame* aParentFrame,
    5518             :                                                    nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
    5519             :                                                    FrameConstructionItemList& aItems)
    5520             : {
    5521           0 :   uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK;
    5522           0 :   if (aParentFrame) {
    5523         415 :     if (nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
    5524           0 :       flags |= ITEM_IS_WITHIN_SVG_TEXT;
    5525             :     }
    5526         441 :     if (aParentFrame->IsBlockFrame() && aParentFrame->GetParent() &&
    5527          26 :         aParentFrame->GetParent()->IsSVGTextFrame()) {
    5528           0 :       flags |= ITEM_ALLOWS_TEXT_PATH_CHILD;
    5529             :     }
    5530             :   }
    5531         415 :   AddFrameConstructionItemsInternal(aState, aContent, aParentFrame,
    5532             :                                     aSuppressWhiteSpaceOptimizations,
    5533             :                                     aComputedStyle,
    5534             :                                     flags, aAnonChildren,
    5535         415 :                                     aItems);
    5536         415 : }
    5537             : 
    5538             : void
    5539           0 : nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState,
    5540             :                                                  nsIContent* aContent,
    5541             :                                                  bool aSuppressWhiteSpaceOptimizations,
    5542             :                                                  const InsertionPoint& aInsertion,
    5543             :                                                  FrameConstructionItemList& aItems)
    5544             : {
    5545         419 :   nsContainerFrame* parentFrame = aInsertion.mParentFrame;
    5546           0 :   if (!ShouldCreateItemsForChild(aState, aContent, parentFrame)) {
    5547           4 :     return;
    5548             :   }
    5549        1245 :   RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
    5550         830 :   DoAddFrameConstructionItems(aState, aContent, computedStyle,
    5551             :                               aSuppressWhiteSpaceOptimizations, parentFrame,
    5552         415 :                               nullptr, aItems);
    5553             : }
    5554             : 
    5555             : // Whether we should suppress frames for a child under a <select> frame.
    5556             : //
    5557             : // Never create frames for non-option/optgroup kids of <select> and non-option
    5558             : // kids of <optgroup> inside a <select>.
    5559             : // XXXbz it's not clear how this should best work with XBL.
    5560             : static bool
    5561         300 : ShouldSuppressFrameInSelect(const nsIContent* aParent,
    5562             :                             const nsIContent* aChild)
    5563             : {
    5564         600 :   if (!aParent ||
    5565         300 :       !aParent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup)) {
    5566             :     return false;
    5567             :   }
    5568             : 
    5569             :   // If we're in any display: contents subtree, just suppress the frame.
    5570             :   //
    5571             :   // We can't be regular NAC, since display: contents has no frame to generate
    5572             :   // them off.
    5573           0 :   if (aChild->GetParent() != aParent) {
    5574             :     return true;
    5575             :   }
    5576             : 
    5577             :   // Option is always fine.
    5578           0 :   if (aChild->IsHTMLElement(nsGkAtoms::option)) {
    5579             :     return false;
    5580             :   }
    5581             : 
    5582             :   // <optgroup> is OK in <select> but not in <optgroup>.
    5583           0 :   if (aChild->IsHTMLElement(nsGkAtoms::optgroup) &&
    5584           0 :       aParent->IsHTMLElement(nsGkAtoms::select)) {
    5585             :     return false;
    5586             :   }
    5587             : 
    5588             :   // Allow native anonymous content no matter what.
    5589           0 :   if (aChild->IsRootOfAnonymousSubtree()) {
    5590             :     return false;
    5591             :   }
    5592             : 
    5593           0 :   return true;
    5594             : }
    5595             : 
    5596             : static bool
    5597         300 : ShouldSuppressFrameInNonOpenDetails(const HTMLDetailsElement* aDetails,
    5598             :                                     const nsIContent* aChild)
    5599             : {
    5600         300 :   if (!aDetails || aDetails->Open()) {
    5601             :     return false;
    5602             :   }
    5603             : 
    5604           0 :   if (aChild->GetParent() != aDetails) {
    5605             :     return true;
    5606             :   }
    5607             : 
    5608           0 :   auto* summary = HTMLSummaryElement::FromNode(aChild);
    5609           0 :   if (summary && summary->IsMainSummary()) {
    5610             :     return false;
    5611             :   }
    5612             : 
    5613             :   // Don't suppress NAC, unless it's ::before or ::after.
    5614           0 :   if (aChild->IsRootOfAnonymousSubtree() &&
    5615           0 :       !aChild->IsGeneratedContentContainerForBefore() &&
    5616           0 :       !aChild->IsGeneratedContentContainerForAfter()) {
    5617             :     return false;
    5618             :   }
    5619             : 
    5620           0 :   return true;
    5621             : }
    5622             : 
    5623             : void
    5624         506 : nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
    5625             :                                                          nsIContent* aContent,
    5626             :                                                          nsContainerFrame* aParentFrame,
    5627             :                                                          bool aSuppressWhiteSpaceOptimizations,
    5628             :                                                          ComputedStyle* aComputedStyle,
    5629             :                                                          uint32_t aFlags,
    5630             :                                                          nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
    5631             :                                                          FrameConstructionItemList& aItems)
    5632             : {
    5633         969 :   MOZ_ASSERT(aContent->IsText() || aContent->IsElement(),
    5634             :              "Shouldn't get anything else here!");
    5635         506 :   MOZ_ASSERT(aContent->IsInComposedDoc());
    5636           0 :   MOZ_ASSERT(!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames ||
    5637             :              aContent->NodeInfo()->NameAtom() == nsGkAtoms::area);
    5638             : 
    5639             :   // The following code allows the user to specify the base tag
    5640             :   // of an element using XBL.  XUL and HTML objects (like boxes, menus, etc.)
    5641             :   // can then be extended arbitrarily.
    5642           0 :   const nsStyleDisplay* display = aComputedStyle->StyleDisplay();
    5643         778 :   RefPtr<ComputedStyle> computedStyle(aComputedStyle);
    5644         506 :   PendingBinding* pendingBinding = nullptr;
    5645           0 :   nsAtom* tag = aContent->NodeInfo()->NameAtom();
    5646           0 :   int32_t namespaceId = aContent->GetNameSpaceID();
    5647           0 :   if (aFlags & ITEM_ALLOW_XBL_BASE) {
    5648        1004 :     if (display->mBinding) {
    5649             :       // Ensure that our XBL bindings are installed.
    5650             : 
    5651           0 :       nsXBLService* xblService = nsXBLService::GetInstance();
    5652         146 :       if (!xblService)
    5653           0 :         return;
    5654             : 
    5655             :       bool resolveStyle;
    5656             : 
    5657           0 :       nsAutoPtr<PendingBinding> newPendingBinding(new PendingBinding());
    5658             : 
    5659         584 :       nsresult rv = xblService->LoadBindings(
    5660           0 :         aContent->AsElement(), display->mBinding->GetURI(),
    5661           0 :         display->mBinding->mExtraData->GetPrincipal(),
    5662         438 :         getter_AddRefs(newPendingBinding->mBinding), &resolveStyle);
    5663           0 :       if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED)
    5664           0 :         return;
    5665             : 
    5666           0 :       if (newPendingBinding->mBinding) {
    5667         119 :         pendingBinding = newPendingBinding;
    5668             :         // aState takes over owning newPendingBinding
    5669         119 :         aState.AddPendingBinding(newPendingBinding.forget());
    5670             :       }
    5671             : 
    5672           0 :       if (resolveStyle) {
    5673             :         computedStyle =
    5674         160 :           mPresShell->StyleSet()->ResolveServoStyle(aContent->AsElement());
    5675             :       }
    5676             : 
    5677           0 :       display = computedStyle->StyleDisplay();
    5678           0 :       aComputedStyle = computedStyle;
    5679           0 :       if (namespaceId == kNameSpaceID_XUL) {
    5680             :         // Only allow overriding from & to XUL.
    5681             :         int32_t overridenNamespace;
    5682             :         nsAtom* overridenTag =
    5683         290 :           mDocument->BindingManager()->ResolveTag(aContent, &overridenNamespace);
    5684         145 :         if (overridenNamespace == kNameSpaceID_XUL) {
    5685           0 :           tag = overridenTag;
    5686             :         }
    5687             :       }
    5688             :     }
    5689             :   }
    5690             : 
    5691           0 :   const bool isGeneratedContent = !!(aFlags & ITEM_IS_GENERATED_CONTENT);
    5692           0 :   MOZ_ASSERT(!isGeneratedContent || computedStyle->GetPseudo(),
    5693             :              "Generated content should be a pseudo-element");
    5694             : 
    5695           0 :   FrameConstructionItem* item = nullptr;
    5696         506 :   auto cleanupGeneratedContent = mozilla::MakeScopeExit([&]() {
    5697           0 :     if (isGeneratedContent && !item) {
    5698           0 :       MOZ_ASSERT(!IsDisplayContents(aContent),
    5699             :                  "This would need to change if we support display: contents "
    5700             :                  "in generated content");
    5701           0 :       aContent->UnbindFromTree();
    5702             :     }
    5703        1284 :   });
    5704             : 
    5705             :   // Pre-check for display "none" - if we find that, don't create
    5706             :   // any frame at all
    5707         506 :   if (display->mDisplay == StyleDisplay::None) {
    5708           0 :     return;
    5709             :   }
    5710             : 
    5711           0 :   if (display->mDisplay == StyleDisplay::Contents) {
    5712           0 :     CreateGeneratedContentItem(aState, aParentFrame, aContent->AsElement(),
    5713             :                                computedStyle, CSSPseudoElementType::before,
    5714           0 :                                aItems);
    5715             : 
    5716           0 :     FlattenedChildIterator iter(aContent);
    5717           0 :     for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
    5718           0 :       if (!ShouldCreateItemsForChild(aState, child, aParentFrame)) {
    5719           0 :         continue;
    5720             :       }
    5721             : 
    5722           0 :       RefPtr<ComputedStyle> childContext = ResolveComputedStyle(child);
    5723           0 :       DoAddFrameConstructionItems(aState, child, childContext,
    5724             :                                   aSuppressWhiteSpaceOptimizations,
    5725           0 :                                   aParentFrame, aAnonChildren, aItems);
    5726             :     }
    5727           0 :     aItems.SetParentHasNoXBLChildren(!iter.XBLInvolved());
    5728             : 
    5729           0 :     CreateGeneratedContentItem(aState, aParentFrame, aContent->AsElement(),
    5730             :                                computedStyle, CSSPseudoElementType::after,
    5731           0 :                                aItems);
    5732             :     return;
    5733             :   }
    5734             : 
    5735         600 :   nsIContent* parent = aParentFrame ? aParentFrame->GetContent() : nullptr;
    5736         300 :   if (ShouldSuppressFrameInSelect(parent, aContent)) {
    5737             :     return;
    5738             :   }
    5739             : 
    5740             :   // When constructing a child of a non-open <details>, create only the frame
    5741             :   // for the main <summary> element, and skip other elements.  This only applies
    5742             :   // to things that are not roots of native anonymous subtrees (except for
    5743             :   // ::before and ::after); we always want to create "internal" anonymous
    5744             :   // content.
    5745           0 :   auto* details = HTMLDetailsElement::FromNodeOrNull(parent);
    5746         300 :   if (ShouldSuppressFrameInNonOpenDetails(details, aContent)) {
    5747             :     return;
    5748             :   }
    5749             : 
    5750           0 :   bool isPopup = false;
    5751         600 :   const bool isText = !aContent->IsElement();
    5752             :   // Try to find frame construction data for this content
    5753             :   const FrameConstructionData* data;
    5754         300 :   if (isText) {
    5755           0 :     data = FindTextData(aParentFrame, aContent);
    5756          43 :     if (!data) {
    5757             :       // Nothing to do here; suppressed text inside SVG
    5758             :       return;
    5759             :     }
    5760             :   } else {
    5761           0 :     Element* element = aContent->AsElement();
    5762             : 
    5763             :     // Don't create frames for non-SVG element children of SVG elements.
    5764         514 :     if (namespaceId != kNameSpaceID_SVG &&
    5765         242 :         ((aParentFrame &&
    5766           0 :           IsFrameForSVG(aParentFrame) &&
    5767         242 :           !aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)) ||
    5768           0 :          (aFlags & ITEM_IS_WITHIN_SVG_TEXT))) {
    5769             :       return;
    5770             :     }
    5771             : 
    5772           0 :     data = FindHTMLData(element, tag, namespaceId, aParentFrame,
    5773             :                         computedStyle);
    5774           0 :     if (!data) {
    5775           0 :       data = FindXULTagData(element, tag, namespaceId, computedStyle);
    5776             :     }
    5777           0 :     if (!data) {
    5778         145 :       data = FindMathMLData(element, tag, namespaceId, computedStyle);
    5779             :     }
    5780         257 :     if (!data) {
    5781         435 :       data = FindSVGData(element, tag, namespaceId, aParentFrame,
    5782           0 :                          aFlags & ITEM_IS_WITHIN_SVG_TEXT,
    5783           0 :                          aFlags & ITEM_ALLOWS_TEXT_PATH_CHILD,
    5784             :                          computedStyle);
    5785             :     }
    5786             : 
    5787             :     // Now check for XUL display types
    5788           0 :     if (!data) {
    5789         130 :       data = FindXULDisplayData(display, element, computedStyle);
    5790             :     }
    5791             : 
    5792             :     // And general display types
    5793           0 :     if (!data) {
    5794          10 :       data = FindDisplayData(display, element, computedStyle);
    5795             :     }
    5796             : 
    5797         257 :     MOZ_ASSERT(data, "Should have frame construction data now");
    5798             : 
    5799           0 :     if (data->mBits & FCDATA_SUPPRESS_FRAME) {
    5800             :       return;
    5801             :     }
    5802             : 
    5803             : #ifdef MOZ_XUL
    5804         514 :     if ((data->mBits & FCDATA_IS_POPUP) &&
    5805          37 :         (!aParentFrame || // Parent is inline
    5806          37 :          !aParentFrame->IsMenuFrame())) {
    5807          24 :       if (!aState.mPopupItems.containingBlock &&
    5808           1 :           !aState.mHavePendingPopupgroup) {
    5809             :         return;
    5810             :       }
    5811             : 
    5812             :       isPopup = true;
    5813             :     }
    5814             : #endif /* MOZ_XUL */
    5815             :   }
    5816             : 
    5817         272 :   uint32_t bits = data->mBits;
    5818             : 
    5819             :   // Inside colgroups, suppress everything except columns.
    5820         544 :   if (aParentFrame && aParentFrame->IsTableColGroupFrame() &&
    5821           0 :       (!(bits & FCDATA_IS_TABLE_PART) ||
    5822           0 :        display->mDisplay != StyleDisplay::TableColumn)) {
    5823             :     return;
    5824             :   }
    5825             : 
    5826             :   bool canHavePageBreak =
    5827           0 :     (aFlags & ITEM_ALLOW_PAGE_BREAK) && aState.mPresContext->IsPaginated() &&
    5828           0 :     !display->IsAbsolutelyPositionedStyle() &&
    5829           0 :     !(aParentFrame && aParentFrame->IsGridContainerFrame()) &&
    5830           0 :     !(bits & FCDATA_IS_TABLE_PART) && !(bits & FCDATA_IS_SVG_TEXT);
    5831             : 
    5832           0 :   if (canHavePageBreak && display->mBreakBefore) {
    5833           0 :     AddPageBreakItem(aContent, aItems);
    5834             :   }
    5835             : 
    5836           0 :   if (details && details->Open()) {
    5837           0 :     auto* summary = HTMLSummaryElement::FromNode(aContent);
    5838           0 :     if (summary && summary->IsMainSummary()) {
    5839             :       // If details is open, the main summary needs to be rendered as if it is
    5840             :       // the first child, so add the item to the front of the item list.
    5841           0 :       item = aItems.PrependItem(this, data, aContent, pendingBinding,
    5842           0 :                                 computedStyle.forget(),
    5843             :                                 aSuppressWhiteSpaceOptimizations,
    5844             :                                 aAnonChildren);
    5845             :     }
    5846             :   }
    5847             : 
    5848           0 :   if (!item) {
    5849           0 :     item = aItems.AppendItem(this, data, aContent, pendingBinding,
    5850           0 :                              computedStyle.forget(),
    5851             :                              aSuppressWhiteSpaceOptimizations, aAnonChildren);
    5852             :   }
    5853         272 :   item->mIsText = isText;
    5854           0 :   item->mIsGeneratedContent = isGeneratedContent;
    5855         272 :   item->mIsAnonymousContentCreatorContent =
    5856           0 :     aFlags & ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT;
    5857           0 :   if (isGeneratedContent) {
    5858             :     // We need to keep this alive until the frame takes ownership.
    5859             :     // This corresponds to the Release in ConstructFramesFromItem.
    5860           0 :     item->mContent->AddRef();
    5861             :   }
    5862           0 :   item->mIsRootPopupgroup =
    5863           0 :     namespaceId == kNameSpaceID_XUL && tag == nsGkAtoms::popupgroup &&
    5864           0 :     aContent->IsRootOfNativeAnonymousSubtree();
    5865         272 :   if (item->mIsRootPopupgroup) {
    5866           0 :     aState.mHavePendingPopupgroup = true;
    5867             :   }
    5868         272 :   item->mIsPopup = isPopup;
    5869         287 :   item->mIsForSVGAElement = namespaceId == kNameSpaceID_SVG &&
    5870           0 :                             tag == nsGkAtoms::a;
    5871             : 
    5872         272 :   if (canHavePageBreak && display->mBreakAfter) {
    5873           0 :     AddPageBreakItem(aContent, aItems);
    5874             :   }
    5875             : 
    5876           0 :   if (bits & FCDATA_IS_INLINE) {
    5877             :     // To correctly set item->mIsAllInline we need to build up our child items
    5878             :     // right now.
    5879           0 :     BuildInlineChildItems(aState, *item,
    5880           0 :                           aFlags & ITEM_IS_WITHIN_SVG_TEXT,
    5881           0 :                           aFlags & ITEM_ALLOWS_TEXT_PATH_CHILD);
    5882           0 :     item->mHasInlineEnds = true;
    5883           0 :     item->mIsBlock = false;
    5884             :   } else {
    5885             :     // Compute a boolean isInline which is guaranteed to be false for blocks
    5886             :     // (but may also be false for some inlines).
    5887             :     bool isInline =
    5888             :       // Table-internal things are inline-outside if and only if they're kids of
    5889             :       // inlines, since they'll trigger construction of inline-table
    5890             :       // pseudos.
    5891           0 :       ((bits & FCDATA_IS_TABLE_PART) &&
    5892           0 :        (!aParentFrame || // No aParentFrame means inline
    5893         272 :         aParentFrame->StyleDisplay()->mDisplay == StyleDisplay::Inline)) ||
    5894             :       // Things that are inline-outside but aren't inline frames are inline
    5895         777 :       display->IsInlineOutsideStyle() ||
    5896             :       // Popups that are certainly out of flow.
    5897           0 :       isPopup;
    5898             : 
    5899             :     // Set mIsAllInline conservatively.  It just might be that even an inline
    5900             :     // that has mIsAllInline false doesn't need an {ib} split.  So this is just
    5901             :     // an optimization to keep from doing too much work in cases when we can
    5902             :     // show that mIsAllInline is true..
    5903         754 :     item->mIsAllInline = item->mHasInlineEnds = isInline ||
    5904             :       // Figure out whether we're guaranteed this item will be out of flow.
    5905             :       // This is not a precise test, since one of our ancestor inlines might add
    5906             :       // an absolute containing block (if it's relatively positioned) when there
    5907             :       // wasn't such a containing block before.  But it's conservative in the
    5908             :       // sense that anything that will really end up as an in-flow non-inline
    5909             :       // will test false here.  In other words, if this test is true we're
    5910             :       // guaranteed to be inline; if it's false we don't know what we'll end up
    5911             :       // as.
    5912             :       //
    5913             :       // If we make this test precise, we can remove some of the code dealing
    5914             :       // with the imprecision in ConstructInline and adjust the comments on
    5915             :       // mIsAllInline and mIsBlock in the header.  And probably remove mIsBlock
    5916             :       // altogether, since then it will always be equal to !mHasInlineEnds.
    5917         218 :       (!(bits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
    5918           8 :        aState.GetGeometricParent(display, nullptr));
    5919             : 
    5920             :     // Set mIsBlock conservatively.  It's OK to set it false for some real
    5921             :     // blocks, but not OK to set it true for things that aren't blocks.  Since
    5922             :     // isOutOfFlow might be false even in cases when the frame will end up
    5923             :     // out-of-flow, we can't use it here.  But we _can_ say that the frame will
    5924             :     // for sure end up in-flow if it's not floated or absolutely positioned.
    5925           0 :     item->mIsBlock = !isInline &&
    5926           0 :                      !display->IsAbsolutelyPositionedStyle() &&
    5927           0 :                      !display->IsFloatingStyle() &&
    5928           0 :                      !(bits & FCDATA_IS_SVG_TEXT);
    5929             :   }
    5930             : 
    5931         272 :   if (item->mIsAllInline) {
    5932          67 :     aItems.InlineItemAdded();
    5933         205 :   } else if (item->mIsBlock) {
    5934         205 :     aItems.BlockItemAdded();
    5935             :   }
    5936             : 
    5937             :   // Our item should be treated as a line participant if we have the relevant
    5938             :   // bit and are going to be in-flow.  Note that this really only matters if
    5939             :   // our ancestor is a box or some such, so the fact that we might have an
    5940             :   // inline ancestor that might become a containing block is not relevant here.
    5941         560 :   if ((bits & FCDATA_IS_LINE_PARTICIPANT) &&
    5942          32 :       ((bits & FCDATA_DISALLOW_OUT_OF_FLOW) ||
    5943          16 :        !aState.GetGeometricParent(display, nullptr))) {
    5944          16 :     item->mIsLineParticipant = true;
    5945          16 :     aItems.LineParticipantItemAdded();
    5946             :   }
    5947             : }
    5948             : 
    5949             : /**
    5950             :  * Return true if the frame construction item pointed to by aIter will
    5951             :  * create a frame adjacent to a line boundary in the frame tree, and that
    5952             :  * line boundary is induced by a content node adjacent to the frame's
    5953             :  * content node in the content tree. The latter condition is necessary so
    5954             :  * that ContentAppended/ContentInserted/ContentRemoved can easily find any
    5955             :  * text nodes that were suppressed here.
    5956             :  */
    5957             : bool
    5958           0 : nsCSSFrameConstructor::AtLineBoundary(FCItemIterator& aIter)
    5959             : {
    5960           0 :   if (aIter.item().mSuppressWhiteSpaceOptimizations) {
    5961             :     return false;
    5962             :   }
    5963             : 
    5964           0 :   if (aIter.AtStart()) {
    5965           0 :     if (aIter.List()->HasLineBoundaryAtStart() &&
    5966           0 :         !aIter.item().mContent->GetPreviousSibling())
    5967             :       return true;
    5968             :   } else {
    5969           1 :     FCItemIterator prev = aIter;
    5970           1 :     prev.Prev();
    5971           0 :     if (prev.item().IsLineBoundary() &&
    5972           0 :         !prev.item().mSuppressWhiteSpaceOptimizations &&
    5973           0 :         aIter.item().mContent->GetPreviousSibling() == prev.item().mContent)
    5974           0 :       return true;
    5975             :   }
    5976             : 
    5977          10 :   FCItemIterator next = aIter;
    5978           0 :   next.Next();
    5979           0 :   if (next.IsDone()) {
    5980           0 :     if (aIter.List()->HasLineBoundaryAtEnd() &&
    5981           2 :         !aIter.item().mContent->GetNextSibling())
    5982             :       return true;
    5983             :   } else {
    5984           8 :     if (next.item().IsLineBoundary() &&
    5985           5 :         !next.item().mSuppressWhiteSpaceOptimizations &&
    5986           2 :         aIter.item().mContent->GetNextSibling() == next.item().mContent)
    5987             :       return true;
    5988             :   }
    5989             : 
    5990             :   return false;
    5991             : }
    5992             : 
    5993             : void
    5994           0 : nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState& aState,
    5995             :                                                FCItemIterator& aIter,
    5996             :                                                nsContainerFrame* aParentFrame,
    5997             :                                                nsFrameItems& aFrameItems)
    5998             : {
    5999         272 :   nsContainerFrame* adjParentFrame = aParentFrame;
    6000         272 :   FrameConstructionItem& item = aIter.item();
    6001         544 :   ComputedStyle* computedStyle = item.mComputedStyle;
    6002         272 :   AdjustParentFrame(&adjParentFrame, item.mFCData, computedStyle);
    6003             : 
    6004         272 :   if (item.mIsText) {
    6005             :     // If this is collapsible whitespace next to a line boundary,
    6006             :     // don't create a frame. item.IsWhitespace() also sets the
    6007             :     // NS_CREATE_FRAME_IF_NON_WHITESPACE flag in the text node. (If we
    6008             :     // end up creating a frame, nsTextFrame::Init will clear the flag.)
    6009             :     // We don't do this for generated content, because some generated
    6010             :     // text content is empty text nodes that are about to be initialized.
    6011             :     // (We check mAdditionalStateBits because only the generated content
    6012             :     // container's frame construction item is marked with
    6013             :     // mIsGeneratedContent, and we might not have an aParentFrame.)
    6014             :     // We don't do it for content that may have XBL anonymous siblings,
    6015             :     // because they make it difficult to correctly create the frame
    6016             :     // due to dynamic changes.
    6017             :     // We don't do it for SVG text, since we might need to position and
    6018             :     // measure the white space glyphs due to x/y/dx/dy attributes.
    6019           0 :     if (AtLineBoundary(aIter) &&
    6020           0 :         !computedStyle->StyleText()->WhiteSpaceOrNewlineIsSignificant() &&
    6021           0 :         aIter.List()->ParentHasNoXBLChildren() &&
    6022          14 :         !(aState.mAdditionalStateBits & NS_FRAME_GENERATED_CONTENT) &&
    6023           0 :         (item.mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) &&
    6024           6 :         !(item.mFCData->mBits & FCDATA_IS_SVG_TEXT) &&
    6025           0 :         !mAlwaysCreateFramesForIgnorableWhitespace &&
    6026           0 :         item.IsWhitespace(aState))
    6027          15 :       return;
    6028             : 
    6029           9 :     ConstructTextFrame(item.mFCData, aState, item.mContent,
    6030             :                        adjParentFrame, computedStyle,
    6031           0 :                        aFrameItems);
    6032           9 :     return;
    6033             :   }
    6034             : 
    6035             :   // Start background loads during frame construction so that we're
    6036             :   // guaranteed that they will be started before onload fires.
    6037           0 :   computedStyle->StartBackgroundImageLoads();
    6038             : 
    6039         257 :   nsFrameState savedStateBits = aState.mAdditionalStateBits;
    6040         257 :   if (item.mIsGeneratedContent) {
    6041             :     // Ensure that frames created here are all tagged with
    6042             :     // NS_FRAME_GENERATED_CONTENT.
    6043           0 :     aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
    6044             :   }
    6045             : 
    6046             :   // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
    6047         257 :   ConstructFrameFromItemInternal(item, aState, adjParentFrame, aFrameItems);
    6048             : 
    6049         257 :   if (item.mIsGeneratedContent) {
    6050             :     // This corresponds to the AddRef in AddFrameConstructionItemsInternal.
    6051             :     // The frame owns the generated content now.
    6052           4 :     item.mContent->Release();
    6053             : 
    6054             :     // Now that we've passed ownership of item.mContent to the frame, unset
    6055             :     // our generated content flag so we don't release or unbind it ourselves.
    6056           4 :     item.mIsGeneratedContent = false;
    6057             :   }
    6058             : 
    6059         257 :   aState.mAdditionalStateBits = savedStateBits;
    6060             : }
    6061             : 
    6062             : 
    6063             : inline bool
    6064             : IsRootBoxFrame(nsIFrame *aFrame)
    6065             : {
    6066             :   return (aFrame->IsRootFrame());
    6067             : }
    6068             : 
    6069             : void
    6070           0 : nsCSSFrameConstructor::ReconstructDocElementHierarchy(InsertionKind aInsertionKind)
    6071             : {
    6072           0 :   Element* rootElement = mDocument->GetRootElement();
    6073           0 :   if (!rootElement) {
    6074             :     /* nothing to do */
    6075             :     return;
    6076             :   }
    6077           0 :   RecreateFramesForContent(rootElement, aInsertionKind);
    6078             : }
    6079             : 
    6080             : nsContainerFrame*
    6081           0 : nsCSSFrameConstructor::GetAbsoluteContainingBlock(nsIFrame* aFrame,
    6082             :                                                   ContainingBlockType aType)
    6083             : {
    6084             :   // Starting with aFrame, look for a frame that is absolutely positioned or
    6085             :   // relatively positioned (and transformed, if aType is FIXED)
    6086         498 :   for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
    6087         475 :     if (frame->IsFrameOfType(nsIFrame::eMathML)) {
    6088             :       // If it's mathml, bail out -- no absolute positioning out from inside
    6089             :       // mathml frames.  Note that we don't make this part of the loop
    6090             :       // condition because of the stuff at the end of this method...
    6091             :       return nullptr;
    6092             :     }
    6093             : 
    6094             :     // Look for the ICB.
    6095         475 :     if (aType == FIXED_POS) {
    6096         296 :       LayoutFrameType t = frame->Type();
    6097         296 :       if (t == LayoutFrameType::Viewport || t == LayoutFrameType::PageContent) {
    6098             :         return static_cast<nsContainerFrame*>(frame);
    6099             :       }
    6100             :     }
    6101             : 
    6102             :     // If the frame is positioned, we will probably return it as the containing
    6103             :     // block (see the exceptions below).  Otherwise, we'll start looking at the
    6104             :     // parent frame, unless we're dealing with a scrollframe.
    6105             :     // Scrollframes are special since they're not positioned, but their
    6106             :     // scrolledframe might be.  So, we need to check this special case to return
    6107             :     // the correct containing block (the scrolledframe) in that case.
    6108             :     // If we're looking for a fixed-pos containing block and the frame is
    6109             :     // not transformed, skip it.
    6110           0 :     if (!frame->IsAbsPosContainingBlock() ||
    6111           0 :         (aType == FIXED_POS &&
    6112           0 :          !frame->IsFixedPosContainingBlock())) {
    6113             :       continue;
    6114             :     }
    6115          14 :     nsIFrame* absPosCBCandidate = frame;
    6116           0 :     LayoutFrameType type = absPosCBCandidate->Type();
    6117          14 :     if (type == LayoutFrameType::FieldSet) {
    6118           0 :       absPosCBCandidate = static_cast<nsFieldSetFrame*>(absPosCBCandidate)->GetInner();
    6119           0 :       if (!absPosCBCandidate) {
    6120             :         continue;
    6121             :       }
    6122           0 :       type = absPosCBCandidate->Type();
    6123             :     }
    6124           0 :     if (type == LayoutFrameType::Scroll) {
    6125           0 :       nsIScrollableFrame* scrollFrame = do_QueryFrame(absPosCBCandidate);
    6126           0 :       absPosCBCandidate = scrollFrame->GetScrolledFrame();
    6127           0 :       if (!absPosCBCandidate) {
    6128             :         continue;
    6129             :       }
    6130           0 :       type = absPosCBCandidate->Type();
    6131             :     }
    6132             :     // Only first continuations can be containing blocks.
    6133          14 :     absPosCBCandidate = absPosCBCandidate->FirstContinuation();
    6134             :     // Is the frame really an absolute container?
    6135          28 :     if (!absPosCBCandidate->IsAbsoluteContainer()) {
    6136             :       continue;
    6137             :     }
    6138             : 
    6139             :     // For tables, skip the inner frame and consider the table wrapper frame.
    6140          13 :     if (type == LayoutFrameType::Table) {
    6141             :       continue;
    6142             :     }
    6143             :     // For table wrapper frames, we can just return absPosCBCandidate.
    6144          13 :     MOZ_ASSERT((nsContainerFrame*)do_QueryFrame(absPosCBCandidate),
    6145             :                "abs.pos. containing block must be nsContainerFrame sub-class");
    6146             :     return static_cast<nsContainerFrame*>(absPosCBCandidate);
    6147             :   }
    6148             : 
    6149          23 :   MOZ_ASSERT(aType != FIXED_POS, "no ICB in this frame tree?");
    6150             : 
    6151             :   // It is possible for the search for the containing block to fail, because
    6152             :   // no absolute container can be found in the parent chain.  In those cases,
    6153             :   // we fall back to the document element's containing block.
    6154          23 :   return mHasRootAbsPosContainingBlock ? mDocElementContainingBlock : nullptr;
    6155             : }
    6156             : 
    6157             : nsContainerFrame*
    6158           0 : nsCSSFrameConstructor::GetFloatContainingBlock(nsIFrame* aFrame)
    6159             : {
    6160             :   // Starting with aFrame, look for a frame that is a float containing block.
    6161             :   // IF we hit a mathml frame, bail out; we don't allow floating out of mathml
    6162             :   // frames, because they don't seem to be able to deal.
    6163             :   // The logic here needs to match the logic in ProcessChildren()
    6164         220 :   for (nsIFrame* containingBlock = aFrame;
    6165         207 :        containingBlock &&
    6166          97 :          !ShouldSuppressFloatingOfDescendants(containingBlock);
    6167             :        containingBlock = containingBlock->GetParent()) {
    6168          73 :     if (containingBlock->IsFloatContainingBlock()) {
    6169           8 :       MOZ_ASSERT((nsContainerFrame*)do_QueryFrame(containingBlock),
    6170             :                  "float containing block must be nsContainerFrame sub-class");
    6171             :       return static_cast<nsContainerFrame*>(containingBlock);
    6172             :     }
    6173             :   }
    6174             : 
    6175             :   // If we didn't find a containing block, then there just isn't
    6176             :   // one.... return null
    6177             :   return nullptr;
    6178             : }
    6179             : 
    6180             : /**
    6181             :  * This function will get the previous sibling to use for an append operation.
    6182             :  *
    6183             :  * It takes a parent frame (must not be null) and the next insertion sibling, if
    6184             :  * the parent content is display: contents or has ::after content (may be null).
    6185             :  */
    6186             : static nsIFrame*
    6187           0 : FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aNextSibling)
    6188             : {
    6189          27 :   aParentFrame->DrainSelfOverflowList();
    6190             : 
    6191          27 :   if (aNextSibling) {
    6192           0 :     MOZ_ASSERT(aNextSibling->GetParent() == aParentFrame, "Wrong parent");
    6193           0 :     return aNextSibling->GetPrevSibling();
    6194             :   }
    6195             : 
    6196          27 :   return aParentFrame->GetChildList(kPrincipalList).LastChild();
    6197             : }
    6198             : 
    6199             : /**
    6200             :  * Finds the right parent frame to append content to aParentFrame.
    6201             :  *
    6202             :  * Cannot return or receive null.
    6203             :  */
    6204             : static nsContainerFrame*
    6205          27 : ContinuationToAppendTo(nsContainerFrame* aParentFrame)
    6206             : {
    6207          27 :   MOZ_ASSERT(aParentFrame);
    6208             : 
    6209          27 :   if (IsFramePartOfIBSplit(aParentFrame)) {
    6210             :     // If the frame we are manipulating is a ib-split frame (that is, one that's
    6211             :     // been created as a result of a block-in-inline situation) then we need to
    6212             :     // append to the last ib-split sibling, not to the frame itself.
    6213             :     //
    6214             :     // Always make sure to look at the last continuation of the frame for the
    6215             :     // {ib} case, even if that continuation is empty.
    6216             :     //
    6217             :     // We don't do this for the non-ib-split-frame case, since in the other
    6218             :     // cases appending to the last nonempty continuation is fine and in fact not
    6219             :     // doing that can confuse code that doesn't know to pull kids from
    6220             :     // continuations other than its next one.
    6221           0 :     return static_cast<nsContainerFrame*>(GetLastIBSplitSibling(aParentFrame)->LastContinuation());
    6222             :   }
    6223             : 
    6224          27 :   return nsLayoutUtils::LastContinuationWithChild(aParentFrame);
    6225             : }
    6226             : 
    6227             : /**
    6228             :  * This function will get the next sibling for a frame insert operation given
    6229             :  * the parent and previous sibling.  aPrevSibling may be null.
    6230             :  */
    6231             : static nsIFrame*
    6232           0 : GetInsertNextSibling(nsIFrame* aParentFrame, nsIFrame* aPrevSibling)
    6233             : {
    6234          29 :   if (aPrevSibling) {
    6235           9 :     return aPrevSibling->GetNextSibling();
    6236             :   }
    6237             : 
    6238          20 :   return aParentFrame->PrincipalChildList().FirstChild();
    6239             : }
    6240             : 
    6241             : /**
    6242             :  * This function is called by ContentAppended() and ContentInserted() when
    6243             :  * appending flowed frames to a parent's principal child list. It handles the
    6244             :  * case where the parent is the trailing inline of an {ib} split.
    6245             :  */
    6246             : void
    6247           0 : nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&       aState,
    6248             :                                             nsContainerFrame*              aParentFrame,
    6249             :                                             nsFrameItems&                  aFrameList,
    6250             :                                             nsIFrame*                      aPrevSibling,
    6251             :                                             bool                           aIsRecursiveCall)
    6252             : {
    6253           9 :   MOZ_ASSERT(!IsFramePartOfIBSplit(aParentFrame) ||
    6254             :              !GetIBSplitSibling(aParentFrame) ||
    6255             :              !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild(),
    6256             :              "aParentFrame has a ib-split sibling with kids?");
    6257           9 :   MOZ_ASSERT(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame,
    6258             :              "Parent and prevsibling don't match");
    6259             : 
    6260           9 :   nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
    6261             : 
    6262           9 :   NS_ASSERTION(nextSibling ||
    6263             :                !aParentFrame->GetNextContinuation() ||
    6264             :                !aParentFrame->GetNextContinuation()->PrincipalChildList().FirstChild() ||
    6265             :                aIsRecursiveCall,
    6266             :                "aParentFrame has later continuations with kids?");
    6267           9 :   NS_ASSERTION(nextSibling ||
    6268             :                !IsFramePartOfIBSplit(aParentFrame) ||
    6269             :                (IsInlineFrame(aParentFrame) &&
    6270             :                 !GetIBSplitSibling(aParentFrame) &&
    6271             :                 !aParentFrame->GetNextContinuation()) ||
    6272             :                aIsRecursiveCall,
    6273             :                "aParentFrame is not last?");
    6274             : 
    6275             :   // If we're inserting a list of frames at the end of the trailing inline
    6276             :   // of an {ib} split, we may need to create additional {ib} siblings to parent
    6277             :   // them.
    6278           9 :   if (!nextSibling && IsFramePartOfIBSplit(aParentFrame)) {
    6279             :     // When we get here, our frame list might start with a block.  If it does
    6280             :     // so, and aParentFrame is an inline, and it and all its previous
    6281             :     // continuations have no siblings, then put the initial blocks from the
    6282             :     // frame list into the previous block of the {ib} split.  Note that we
    6283             :     // didn't want to stop at the block part of the split when figuring out
    6284             :     // initial parent, because that could screw up float parenting; it's easier
    6285             :     // to do this little fixup here instead.
    6286           0 :     if (aFrameList.NotEmpty() && !aFrameList.FirstChild()->IsInlineOutside()) {
    6287             :       // See whether our trailing inline is empty
    6288           0 :       nsIFrame* firstContinuation = aParentFrame->FirstContinuation();
    6289           0 :       if (firstContinuation->PrincipalChildList().IsEmpty()) {
    6290             :         // Our trailing inline is empty.  Collect our starting blocks from
    6291             :         // aFrameList, get the right parent frame for them, and put them in.
    6292             :         nsFrameList::FrameLinkEnumerator firstNonBlockEnumerator =
    6293           0 :           FindFirstNonBlock(aFrameList);
    6294           0 :         nsFrameList blockKids = aFrameList.ExtractHead(firstNonBlockEnumerator);
    6295           0 :         NS_ASSERTION(blockKids.NotEmpty(), "No blocks?");
    6296             : 
    6297           0 :         nsContainerFrame* prevBlock = GetIBSplitPrevSibling(firstContinuation);
    6298           0 :         prevBlock = static_cast<nsContainerFrame*>(prevBlock->LastContinuation());
    6299           0 :         NS_ASSERTION(prevBlock, "Should have previous block here");
    6300             : 
    6301           0 :         MoveChildrenTo(aParentFrame, prevBlock, blockKids);
    6302             :       }
    6303             :     }
    6304             : 
    6305             :     // We want to put some of the frames into this inline frame.
    6306           0 :     nsFrameList::FrameLinkEnumerator firstBlockEnumerator(aFrameList);
    6307           0 :     FindFirstBlock(firstBlockEnumerator);
    6308             : 
    6309           0 :     nsFrameList inlineKids = aFrameList.ExtractHead(firstBlockEnumerator);
    6310           0 :     if (!inlineKids.IsEmpty()) {
    6311           0 :       AppendFrames(aParentFrame, kPrincipalList, inlineKids);
    6312             :     }
    6313             : 
    6314           0 :     if (!aFrameList.IsEmpty()) {
    6315           0 :       bool positioned = aParentFrame->IsRelativelyPositioned();
    6316           0 :       nsFrameItems ibSiblings;
    6317           0 :       CreateIBSiblings(aState, aParentFrame, positioned, aFrameList,
    6318           0 :                        ibSiblings);
    6319             : 
    6320             :       // Make sure to trigger reflow of the inline that used to be our
    6321             :       // last one and now isn't anymore, since its GetSkipSides() has
    6322             :       // changed.
    6323           0 :       mPresShell->FrameNeedsReflow(aParentFrame,
    6324             :                                    nsIPresShell::eTreeChange,
    6325           0 :                                    NS_FRAME_HAS_DIRTY_CHILDREN);
    6326             : 
    6327             :       // Recurse so we create new ib siblings as needed for aParentFrame's parent
    6328           0 :       return AppendFramesToParent(aState, aParentFrame->GetParent(), ibSiblings,
    6329           0 :                                    aParentFrame, true);
    6330             :     }
    6331             :     return;
    6332             :   }
    6333             : 
    6334             :   // Insert the frames after our aPrevSibling
    6335           9 :   InsertFrames(aParentFrame, kPrincipalList, aPrevSibling, aFrameList);
    6336             : }
    6337             : 
    6338             : #define UNSET_DISPLAY static_cast<StyleDisplay>(255)
    6339             : 
    6340             : // This gets called to see if the frames corresponding to aSibling and aContent
    6341             : // should be siblings in the frame tree. Although (1) rows and cols, (2) row
    6342             : // groups and col groups, (3) row groups and captions, (4) legends and content
    6343             : // inside fieldsets, (5) popups and other kids of the menu are siblings from a
    6344             : // content perspective, they are not considered siblings in the frame tree.
    6345             : bool
    6346           9 : nsCSSFrameConstructor::IsValidSibling(nsIFrame*              aSibling,
    6347             :                                       nsIContent*            aContent,
    6348             :                                       StyleDisplay&          aDisplay)
    6349             : {
    6350           0 :   nsIFrame* parentFrame = aSibling->GetParent();
    6351           0 :   LayoutFrameType parentType = parentFrame->Type();
    6352             : 
    6353           0 :   StyleDisplay siblingDisplay = aSibling->GetDisplay();
    6354           0 :   if (StyleDisplay::TableColumnGroup == siblingDisplay ||
    6355           9 :       StyleDisplay::TableColumn      == siblingDisplay ||
    6356           9 :       StyleDisplay::TableCaption     == siblingDisplay ||
    6357           0 :       StyleDisplay::TableHeaderGroup == siblingDisplay ||
    6358           0 :       StyleDisplay::TableRowGroup    == siblingDisplay ||
    6359          18 :       StyleDisplay::TableFooterGroup == siblingDisplay ||
    6360           9 :       LayoutFrameType::Menu == parentType) {
    6361             :     // if we haven't already, resolve a style to find the display type of
    6362             :     // aContent.
    6363           0 :     if (UNSET_DISPLAY == aDisplay) {
    6364           0 :       if (aContent->IsComment() || aContent->IsProcessingInstruction()) {
    6365             :         // Comments and processing instructions never have frames, so we should
    6366             :         // not try to generate styles for them.
    6367           0 :         return false;
    6368             :       }
    6369             :       // FIXME(emilio): This is buggy some times, see bug 1424656.
    6370           0 :       RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
    6371           0 :       const nsStyleDisplay* display = computedStyle->StyleDisplay();
    6372           0 :       aDisplay = display->mDisplay;
    6373             :     }
    6374           0 :     if (LayoutFrameType::Menu == parentType) {
    6375             :       return
    6376           0 :         (StyleDisplay::MozPopup == aDisplay) ==
    6377           0 :         (StyleDisplay::MozPopup == siblingDisplay);
    6378             :     }
    6379             :     // To have decent performance we want to return false in cases in which
    6380             :     // reordering the two siblings has no effect on display.  To ensure
    6381             :     // correctness, we MUST return false in cases where the two siblings have
    6382             :     // the same desired parent type and live on different display lists.
    6383             :     // Specificaly, columns and column groups should only consider columns and
    6384             :     // column groups as valid siblings.  Captions should only consider other
    6385             :     // captions.  All other things should consider each other as valid
    6386             :     // siblings.  The restriction in the |if| above on siblingDisplay is ok,
    6387             :     // because for correctness the only part that really needs to happen is to
    6388             :     // not consider captions, column groups, and row/header/footer groups
    6389             :     // siblings of each other.  Treating a column or colgroup as a valid
    6390             :     // sibling of a non-table-related frame will just mean we end up reframing.
    6391           0 :     if ((siblingDisplay == StyleDisplay::TableCaption) !=
    6392           0 :         (aDisplay == StyleDisplay::TableCaption)) {
    6393             :       // One's a caption and the other is not.  Not valid siblings.
    6394             :       return false;
    6395             :     }
    6396             : 
    6397           0 :     if ((siblingDisplay == StyleDisplay::TableColumnGroup ||
    6398           0 :          siblingDisplay == StyleDisplay::TableColumn) !=
    6399           0 :         (aDisplay == StyleDisplay::TableColumnGroup ||
    6400             :          aDisplay == StyleDisplay::TableColumn)) {
    6401             :       // One's a column or column group and the other is not.  Not valid
    6402             :       // siblings.
    6403             :       return false;
    6404             :     }
    6405             :     // Fall through; it's possible that the display type was overridden and
    6406             :     // a different sort of frame was constructed, so we may need to return false
    6407             :     // below.
    6408             :   }
    6409             : 
    6410           0 :   if (IsFrameForFieldSet(parentFrame)) {
    6411             :     // Legends can be sibling of legends but not of other content in the fieldset
    6412           0 :     if (nsContainerFrame* cif = aSibling->GetContentInsertionFrame()) {
    6413           0 :       aSibling = cif;
    6414             :     }
    6415           0 :     LayoutFrameType sibType = aSibling->Type();
    6416           0 :     bool legendContent = aContent->IsHTMLElement(nsGkAtoms::legend);
    6417             : 
    6418           0 :     if ((legendContent && (LayoutFrameType::Legend != sibType)) ||
    6419             :         (!legendContent && (LayoutFrameType::Legend == sibType)))
    6420             :       return false;
    6421             :   }
    6422             : 
    6423             :   return true;
    6424             : }
    6425             : 
    6426             : // FIXME(emilio): If we ever kill IsValidSibling() we can simplify this quite a
    6427             : // bit (no need to pass aTargetContent or aTargetContentDisplay, and the
    6428             : // adjust() calls can be responsibility of the caller).
    6429             : template<nsCSSFrameConstructor::SiblingDirection aDirection>
    6430             : nsIFrame*
    6431           0 : nsCSSFrameConstructor::FindSiblingInternal(
    6432             :   FlattenedChildIterator& aIter,
    6433             :   nsIContent* aTargetContent,
    6434             :   StyleDisplay& aTargetContentDisplay)
    6435             : {
    6436          42 :   auto adjust = [&](nsIFrame* aPotentialSiblingFrame) -> nsIFrame* {
    6437          42 :     return AdjustSiblingFrame(
    6438           0 :       aPotentialSiblingFrame, aTargetContent, aTargetContentDisplay,
    6439          42 :       aDirection);
    6440          42 :   };
    6441             : 
    6442             :   auto nextDomSibling = [](FlattenedChildIterator& aIter) -> nsIContent* {
    6443             :     return aDirection == SiblingDirection::Forward
    6444           0 :       ? aIter.GetNextChild() : aIter.GetPreviousChild();
    6445             :   };
    6446             : 
    6447             :   auto getNearPseudo = [](const nsIContent* aContent) -> nsIFrame* {
    6448             :     return aDirection == SiblingDirection::Forward
    6449             :       ? nsLayoutUtils::GetBeforeFrame(aContent)
    6450           0 :       : nsLayoutUtils::GetAfterFrame(aContent);
    6451             :   };
    6452             : 
    6453             :   auto getFarPseudo = [](const nsIContent* aContent) -> nsIFrame* {
    6454             :     return aDirection == SiblingDirection::Forward
    6455             :       ? nsLayoutUtils::GetAfterFrame(aContent)
    6456          33 :       : nsLayoutUtils::GetBeforeFrame(aContent);
    6457             :   };
    6458             : 
    6459          55 :   while (nsIContent* sibling = nextDomSibling(aIter)) {
    6460             :     // NOTE(emilio): It's important to check GetPrimaryFrame() before
    6461             :     // IsDisplayContents to get the correct insertion point when multiple
    6462             :     // siblings go from display: non-none to display: contents.
    6463          22 :     if (nsIFrame* primaryFrame = sibling->GetPrimaryFrame()) {
    6464             :       // XXX the GetContent() == sibling check is needed due to bug 135040.
    6465             :       // Remove it once that's fixed.
    6466           9 :       if (primaryFrame->GetContent() == sibling) {
    6467           0 :         if (nsIFrame* frame = adjust(primaryFrame)) {
    6468             :           return frame;
    6469             :         }
    6470             :       }
    6471             :     }
    6472             : 
    6473           0 :     if (IsDisplayContents(sibling)) {
    6474           0 :       if (nsIFrame* frame = adjust(getNearPseudo(sibling))) {
    6475           0 :         return frame;
    6476             :       }
    6477             : 
    6478           0 :       const bool startFromBeginning = aDirection == SiblingDirection::Forward;
    6479           0 :       FlattenedChildIterator iter(sibling, startFromBeginning);
    6480           0 :       nsIFrame* sibling = FindSiblingInternal<aDirection>(
    6481           0 :         iter, aTargetContent, aTargetContentDisplay);
    6482           0 :       if (sibling) {
    6483           0 :         return sibling;
    6484             :       }
    6485             :     }
    6486             :   }
    6487             : 
    6488          66 :   return adjust(getFarPseudo(aIter.Parent()));
    6489             : }
    6490             : 
    6491             : nsIFrame*
    6492           0 : nsCSSFrameConstructor::AdjustSiblingFrame(
    6493             :   nsIFrame* aSibling,
    6494             :   nsIContent* aTargetContent,
    6495             :   mozilla::StyleDisplay& aTargetContentDisplay,
    6496             :   SiblingDirection aDirection)
    6497             : {
    6498           0 :   if (!aSibling) {
    6499             :     return nullptr;
    6500             :   }
    6501             : 
    6502           0 :   if (aSibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    6503           0 :     aSibling = aSibling->GetPlaceholderFrame();
    6504           0 :     MOZ_ASSERT(aSibling);
    6505             :   }
    6506             : 
    6507           9 :   MOZ_ASSERT(!aSibling->GetPrevContinuation(), "How?");
    6508           9 :   if (aDirection == SiblingDirection::Backward) {
    6509             :     // The frame may be a ib-split frame (a split inline frame that contains a
    6510             :     // block).  Get the last part of that split.
    6511           0 :     if (IsFramePartOfIBSplit(aSibling)) {
    6512           0 :       aSibling = GetLastIBSplitSibling(aSibling);
    6513             :     }
    6514             : 
    6515             :     // The frame may have a continuation. If so, we want the last
    6516             :     // non-overflow-container continuation as our previous sibling.
    6517           5 :     aSibling = aSibling->GetTailContinuation();
    6518             :   }
    6519             : 
    6520           9 :   if (!IsValidSibling(aSibling, aTargetContent, aTargetContentDisplay)) {
    6521             :     return nullptr;
    6522             :   }
    6523             : 
    6524           9 :   return aSibling;
    6525             : }
    6526             : 
    6527             : nsIFrame*
    6528           0 : nsCSSFrameConstructor::FindPreviousSibling(const FlattenedChildIterator& aIter,
    6529             :                                            StyleDisplay& aTargetContentDisplay)
    6530             : {
    6531          11 :   return FindSibling<SiblingDirection::Backward>(aIter, aTargetContentDisplay);
    6532             : }
    6533             : 
    6534             : nsIFrame*
    6535           0 : nsCSSFrameConstructor::FindNextSibling(const FlattenedChildIterator& aIter,
    6536             :                                        StyleDisplay& aTargetContentDisplay)
    6537             : {
    6538          31 :   return FindSibling<SiblingDirection::Forward>(aIter, aTargetContentDisplay);
    6539             : }
    6540             : 
    6541             : template<nsCSSFrameConstructor::SiblingDirection aDirection>
    6542             : nsIFrame*
    6543           0 : nsCSSFrameConstructor::FindSibling(const FlattenedChildIterator& aIter,
    6544             :                                    StyleDisplay& aTargetContentDisplay)
    6545             : {
    6546          42 :   nsIContent* targetContent = aIter.Get();
    6547          84 :   FlattenedChildIterator siblingIter = aIter;
    6548             :   nsIFrame* sibling = FindSiblingInternal<aDirection>(
    6549          42 :     siblingIter, targetContent, aTargetContentDisplay);
    6550          42 :   if (sibling) {
    6551             :     return sibling;
    6552             :   }
    6553             : 
    6554             :   // Our siblings (if any) do not have a frame to guide us. The frame for the
    6555             :   // target content should be inserted whereever a frame for the container would
    6556             :   // be inserted. This is needed when inserting into display: contents nodes.
    6557           0 :   const nsIContent* current = aIter.Parent();
    6558           0 :   while (IsDisplayContents(current)) {
    6559           0 :     const nsIContent* parent = current->GetFlattenedTreeParent();
    6560           0 :     MOZ_ASSERT(parent, "No display: contents on the root");
    6561             : 
    6562           0 :     FlattenedChildIterator iter(parent);
    6563           0 :     iter.Seek(current);
    6564           0 :     sibling = FindSiblingInternal<aDirection>(
    6565             :         iter, targetContent, aTargetContentDisplay);
    6566           0 :     if (sibling) {
    6567           0 :       return sibling;
    6568             :     }
    6569             : 
    6570           0 :     current = parent;
    6571             :   }
    6572             : 
    6573             :   return nullptr;
    6574             : }
    6575             : 
    6576             : // For fieldsets, returns the area frame, if the child is not a legend.
    6577             : static nsContainerFrame*
    6578           2 : GetAdjustedParentFrame(nsContainerFrame* aParentFrame,
    6579             :                        nsIContent* aChildContent)
    6580             : {
    6581           2 :   MOZ_ASSERT(!aParentFrame->IsTableWrapperFrame(), "Shouldn't be happening!");
    6582             : 
    6583           0 :   nsContainerFrame* newParent = nullptr;
    6584             : 
    6585           2 :   if (aParentFrame->IsFieldSetFrame()) {
    6586             :     // If the parent is a fieldSet, use the fieldSet's area frame as the
    6587             :     // parent unless the new content is a legend.
    6588           0 :     if (!aChildContent->IsHTMLElement(nsGkAtoms::legend)) {
    6589           0 :       newParent = GetFieldSetBlockFrame(aParentFrame);
    6590             :     }
    6591             :   }
    6592           2 :   return newParent ? newParent : aParentFrame;
    6593             : }
    6594             : 
    6595             : nsIFrame*
    6596          11 : nsCSSFrameConstructor::GetInsertionPrevSibling(InsertionPoint* aInsertion,
    6597             :                                                nsIContent* aChild,
    6598             :                                                bool*       aIsAppend,
    6599             :                                                bool*       aIsRangeInsertSafe,
    6600             :                                                nsIContent* aStartSkipChild,
    6601             :                                                nsIContent* aEndSkipChild)
    6602             : {
    6603          11 :   MOZ_ASSERT(aInsertion->mParentFrame, "Must have parent frame to start with");
    6604             : 
    6605           0 :   *aIsAppend = false;
    6606             : 
    6607             :   // Find the frame that precedes the insertion point. Walk backwards
    6608             :   // from the parent frame to get the parent content, because if an
    6609             :   // XBL insertion point is involved, we'll need to use _that_ to find
    6610             :   // the preceding frame.
    6611          22 :   FlattenedChildIterator iter(aInsertion->mContainer);
    6612           0 :   bool xblCase = iter.XBLInvolved() ||
    6613           0 :          aInsertion->mParentFrame->GetContent() != aInsertion->mContainer;
    6614          11 :   if (xblCase || !aChild->IsRootOfAnonymousSubtree()) {
    6615             :     // The check for IsRootOfAnonymousSubtree() is because editor is
    6616             :     // severely broken and calls us directly for native anonymous
    6617             :     // nodes that it creates.
    6618          11 :     if (aStartSkipChild) {
    6619           0 :       iter.Seek(aStartSkipChild);
    6620             :     } else {
    6621          11 :       iter.Seek(aChild);
    6622             :     }
    6623             :   } else {
    6624             :     // Prime the iterator for the call to FindPreviousSibling.
    6625           0 :     iter.GetNextChild();
    6626           0 :     MOZ_ASSERT(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode),
    6627             :                "Someone passed native anonymous content directly into frame "
    6628             :                "construction.  Stop doing that!");
    6629             :   }
    6630             : 
    6631             :   // Note that FindPreviousSibling is passed the iterator by value, so that
    6632             :   // the later usage of the iterator starts from the same place.
    6633           0 :   StyleDisplay childDisplay = UNSET_DISPLAY;
    6634           0 :   nsIFrame* prevSibling = FindPreviousSibling(iter, childDisplay);
    6635             : 
    6636             :   // Now, find the geometric parent so that we can handle
    6637             :   // continuations properly. Use the prev sibling if we have it;
    6638             :   // otherwise use the next sibling.
    6639           0 :   if (prevSibling) {
    6640           0 :     aInsertion->mParentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
    6641             :   } else {
    6642             :     // If there is no previous sibling, then find the frame that follows
    6643             :     //
    6644             :     // FIXME(emilio): This is really complex and probably shouldn't be.
    6645           6 :     if (aEndSkipChild) {
    6646           0 :       iter.Seek(aEndSkipChild);
    6647           0 :       iter.GetPreviousChild();
    6648             :     }
    6649           0 :     if (nsIFrame* nextSibling = FindNextSibling(iter, childDisplay)) {
    6650           4 :       aInsertion->mParentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
    6651             :     } else {
    6652             :       // No previous or next sibling, so treat this like an appended frame.
    6653           0 :       *aIsAppend = true;
    6654           0 :       aInsertion->mParentFrame =
    6655           2 :         ::ContinuationToAppendTo(aInsertion->mParentFrame);
    6656             : 
    6657             :       // Deal with fieldsets.
    6658           0 :       aInsertion->mParentFrame =
    6659           0 :         ::GetAdjustedParentFrame(aInsertion->mParentFrame, aChild);
    6660           2 :       prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, nullptr);
    6661             :     }
    6662             :   }
    6663             : 
    6664          11 :   *aIsRangeInsertSafe = (childDisplay == UNSET_DISPLAY);
    6665          22 :   return prevSibling;
    6666             : }
    6667             : 
    6668             : nsContainerFrame*
    6669          90 : nsCSSFrameConstructor::GetContentInsertionFrameFor(nsIContent* aContent)
    6670             : {
    6671             :   nsIFrame* frame;
    6672           0 :   while (!(frame = aContent->GetPrimaryFrame())) {
    6673          32 :     if (!IsDisplayContents(aContent)) {
    6674             :       return nullptr;
    6675             :     }
    6676             : 
    6677           0 :     aContent = aContent->GetFlattenedTreeParent();
    6678           0 :     if (!aContent) {
    6679             :       return nullptr;
    6680             :     }
    6681             :   }
    6682             : 
    6683             :   // If the content of the frame is not the desired content then this is not
    6684             :   // really a frame for the desired content.
    6685             :   // XXX This check is needed due to bug 135040. Remove it once that's fixed.
    6686           0 :   if (frame->GetContent() != aContent) {
    6687             :     return nullptr;
    6688             :   }
    6689             : 
    6690          58 :   nsContainerFrame* insertionFrame = frame->GetContentInsertionFrame();
    6691             : 
    6692          58 :   NS_ASSERTION(!insertionFrame || insertionFrame == frame || !frame->IsLeaf(),
    6693             :     "The insertion frame is the primary frame or the primary frame isn't a leaf");
    6694             : 
    6695             :   return insertionFrame;
    6696             : }
    6697             : 
    6698             : static bool
    6699           0 : IsSpecialFramesetChild(nsIContent* aContent)
    6700             : {
    6701             :   // IMPORTANT: This must match the conditions in nsHTMLFramesetFrame::Init.
    6702           0 :   return aContent->IsAnyOfHTMLElements(nsGkAtoms::frameset, nsGkAtoms::frame);
    6703             : }
    6704             : 
    6705             : static void
    6706             : InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node);
    6707             : 
    6708             : void
    6709           0 : nsCSSFrameConstructor::AddTextItemIfNeeded(nsFrameConstructorState& aState,
    6710             :                                            const InsertionPoint& aInsertion,
    6711             :                                            nsIContent* aPossibleTextContent,
    6712             :                                            FrameConstructionItemList& aItems)
    6713             : {
    6714          27 :   MOZ_ASSERT(aPossibleTextContent, "Must have node");
    6715          54 :   if (!aPossibleTextContent->IsText() ||
    6716          27 :       !aPossibleTextContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) ||
    6717           0 :       aPossibleTextContent->HasFlag(NODE_NEEDS_FRAME)) {
    6718             :     // Not text, or not suppressed due to being all-whitespace (if it were being
    6719             :     // suppressed, it would have the NS_CREATE_FRAME_IF_NON_WHITESPACE flag), or
    6720             :     // going to be reframed anyway.
    6721             :     return;
    6722             :   }
    6723           0 :   MOZ_ASSERT(!aPossibleTextContent->GetPrimaryFrame(),
    6724             :              "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
    6725             :   AddFrameConstructionItems(aState, aPossibleTextContent, false,
    6726           0 :                             aInsertion, aItems);
    6727             : }
    6728             : 
    6729             : void
    6730           0 : nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aContent)
    6731             : {
    6732           0 :   if (!aContent->IsText() ||
    6733           0 :       !aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) ||
    6734           0 :       aContent->HasFlag(NODE_NEEDS_FRAME)) {
    6735             :     // Not text, or not suppressed due to being all-whitespace (if it were being
    6736             :     // suppressed, it would have the NS_CREATE_FRAME_IF_NON_WHITESPACE flag), or
    6737             :     // going to be reframed anyway.
    6738             :     return;
    6739             :   }
    6740           0 :   MOZ_ASSERT(!aContent->GetPrimaryFrame(),
    6741             :              "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
    6742           0 :   ContentInserted(aContent, nullptr, InsertionKind::Async);
    6743             : }
    6744             : 
    6745             : #ifdef DEBUG
    6746             : void
    6747          22 : nsCSSFrameConstructor::CheckBitsForLazyFrameConstruction(nsIContent* aParent)
    6748             : {
    6749             :   // If we hit a node with no primary frame, or the NODE_NEEDS_FRAME bit set
    6750             :   // we want to assert, but leaf frames that process their own children and may
    6751             :   // ignore anonymous children (eg framesets) make this complicated. So we set
    6752             :   // these two booleans if we encounter these situations and unset them if we
    6753             :   // hit a node with a leaf frame.
    6754             :   //
    6755             :   // It's fine if one of node without primary frame is in a display:none
    6756             :   // subtree.
    6757             :   //
    6758             :   // Also, it's fine if one of the nodes without primary frame is a display:
    6759             :   // contents node.
    6760          22 :   bool noPrimaryFrame = false;
    6761           0 :   bool needsFrameBitSet = false;
    6762           0 :   nsIContent* content = aParent;
    6763          84 :   while (content && !content->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
    6764           0 :     if (content->GetPrimaryFrame() && content->GetPrimaryFrame()->IsLeaf()) {
    6765           1 :       noPrimaryFrame = needsFrameBitSet = false;
    6766             :     }
    6767          31 :     if (!noPrimaryFrame && !content->GetPrimaryFrame()) {
    6768           0 :       noPrimaryFrame = !IsDisplayContents(content);
    6769             :     }
    6770           0 :     if (!needsFrameBitSet && content->HasFlag(NODE_NEEDS_FRAME)) {
    6771           0 :       needsFrameBitSet = true;
    6772             :     }
    6773             : 
    6774           0 :     content = content->GetFlattenedTreeParent();
    6775             :   }
    6776           0 :   if (content && content->GetPrimaryFrame() &&
    6777           4 :       content->GetPrimaryFrame()->IsLeaf()) {
    6778           0 :     noPrimaryFrame = needsFrameBitSet = false;
    6779             :   }
    6780          22 :   MOZ_ASSERT(!noPrimaryFrame, "Ancestors of nodes with frames to be "
    6781             :     "constructed lazily should have frames");
    6782          22 :   MOZ_ASSERT(!needsFrameBitSet, "Ancestors of nodes with frames to be "
    6783             :     "constructed lazily should not have NEEDS_FRAME bit set");
    6784          22 : }
    6785             : #endif
    6786             : 
    6787             : // Returns true if this operation can be lazy, false if not.
    6788             : //
    6789             : // FIXME(emilio, bug 1410020): This function assumes that the flattened tree
    6790             : // parent of all the appended children is the same, which, afaict, is not
    6791             : // necessarily true.
    6792             : //
    6793             : // NOTE(emilio): The IsXULElement checks are pretty unfortunate, but there's
    6794             : // tons of browser chrome code that rely on XBL bindings getting synchronously
    6795             : // loaded as soon as the elements get inserted in the DOM.
    6796             : bool
    6797           0 : nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
    6798             :                                             nsIContent* aChild)
    6799             : {
    6800          33 :   MOZ_ASSERT(aChild->GetParent());
    6801           0 :   if (aOperation == CONTENTINSERT) {
    6802           4 :     MOZ_ASSERT(!aChild->IsRootOfAnonymousSubtree());
    6803           0 :     if (aChild->IsXULElement()) {
    6804             :       return false;
    6805             :     }
    6806             :   } else { // CONTENTAPPEND
    6807          29 :     MOZ_ASSERT(aOperation == CONTENTAPPEND,
    6808             :                "operation should be either insert or append");
    6809          81 :     for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
    6810          33 :       MOZ_ASSERT(!child->IsRootOfAnonymousSubtree());
    6811          33 :       if (child->IsXULElement()) {
    6812             :         return false;
    6813             :       }
    6814             :     }
    6815             :   }
    6816             : 
    6817             :   // We can construct lazily; just need to set suitable bits in the content
    6818             :   // tree.
    6819           0 :   Element* parent = aChild->GetFlattenedTreeParentElement();
    6820          22 :   if (!parent) {
    6821             :     // Not part of the flat tree, nothing to do.
    6822             :     return true;
    6823             :   }
    6824             : 
    6825          22 :   if (Servo_Element_IsDisplayNone(parent)) {
    6826             :     // Nothing to do either.
    6827             :     //
    6828             :     // FIXME(emilio): This should be an assert, except for weird <frameset>
    6829             :     // stuff that does its own frame construction. Such an assert would fire in
    6830             :     // layout/style/crashtests/1411478.html, for example.
    6831             :     return true;
    6832             :   }
    6833             : 
    6834             :   // Set NODE_NEEDS_FRAME on the new nodes.
    6835          22 :   if (aOperation == CONTENTINSERT) {
    6836           0 :     NS_ASSERTION(!aChild->GetPrimaryFrame() ||
    6837             :                  aChild->GetPrimaryFrame()->GetContent() != aChild,
    6838             :                  //XXX the aChild->GetPrimaryFrame()->GetContent() != aChild
    6839             :                  // check is needed due to bug 135040. Remove it once that's
    6840             :                  // fixed.
    6841             :                  "setting NEEDS_FRAME on a node that already has a frame?");
    6842           0 :     aChild->SetFlags(NODE_NEEDS_FRAME);
    6843             :   } else { // CONTENTAPPEND
    6844          74 :     for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
    6845           0 :       NS_ASSERTION(!child->GetPrimaryFrame() ||
    6846             :                    child->GetPrimaryFrame()->GetContent() != child,
    6847             :                    //XXX the child->GetPrimaryFrame()->GetContent() != child
    6848             :                    // check is needed due to bug 135040. Remove it once that's
    6849             :                    // fixed.
    6850             :                    "setting NEEDS_FRAME on a node that already has a frame?");
    6851          26 :       child->SetFlags(NODE_NEEDS_FRAME);
    6852             :     }
    6853             :   }
    6854             : 
    6855          22 :   CheckBitsForLazyFrameConstruction(parent);
    6856          22 :   parent->NoteDescendantsNeedFramesForServo();
    6857             : 
    6858          22 :   return true;
    6859             : }
    6860             : 
    6861             : 
    6862             : void
    6863           0 : nsCSSFrameConstructor::IssueSingleInsertNofications(nsIContent* aStartChild,
    6864             :                                                     nsIContent* aEndChild,
    6865             :                                                     InsertionKind aInsertionKind)
    6866             : {
    6867           6 :   for (nsIContent* child = aStartChild;
    6868           0 :        child != aEndChild;
    6869           0 :        child = child->GetNextSibling()) {
    6870             :     // listboxes suck.
    6871           0 :     MOZ_ASSERT(MaybeGetListBoxBodyFrame(child) || !child->GetPrimaryFrame());
    6872             : 
    6873             :     // Call ContentRangeInserted with this node.
    6874           0 :     ContentRangeInserted(child, child->GetNextSibling(),
    6875           3 :                          mTempFrameTreeState, aInsertionKind);
    6876             :   }
    6877           3 : }
    6878             : 
    6879             : bool
    6880          63 : nsCSSFrameConstructor::InsertionPoint::IsMultiple() const
    6881             : {
    6882           0 :   if (!mParentFrame) {
    6883             :     return false;
    6884             :   }
    6885             : 
    6886             :   // Fieldset frames have multiple normal flow child frame lists so handle it
    6887             :   // the same as if it had multiple content insertion points.
    6888           0 :   if (mParentFrame->IsFieldSetFrame()) {
    6889             :     return true;
    6890             :   }
    6891             : 
    6892             :   // A details frame moves the first summary frame to be its first child, so we
    6893             :   // treat it as if it has multiple content insertion points.
    6894          47 :   if (mParentFrame->IsDetailsFrame()) {
    6895             :     return true;
    6896             :   }
    6897             : 
    6898          47 :   return false;
    6899             : }
    6900             : 
    6901             : nsCSSFrameConstructor::InsertionPoint
    6902          66 : nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aStartChild,
    6903             :                                               nsIContent* aEndChild,
    6904             :                                               InsertionKind aInsertionKind)
    6905             : {
    6906          66 :   MOZ_ASSERT(aStartChild);
    6907          66 :   MOZ_ASSERT(aStartChild->GetParent());
    6908             : 
    6909           0 :   nsIContent* parent = aStartChild->GetParent();
    6910             : 
    6911             :   // If the children of the container may be distributed to different insertion
    6912             :   // points, insert them separately and bail out, letting ContentInserted handle
    6913             :   // the mess.
    6914          66 :   if (parent->GetShadowRoot() || parent->GetXBLBinding()) {
    6915           0 :     IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
    6916           0 :     return { };
    6917             :   }
    6918             : 
    6919             : #ifdef DEBUG
    6920             :   {
    6921          63 :     nsIContent* expectedParent = aStartChild->GetFlattenedTreeParent();
    6922          75 :     for (nsIContent* child = aStartChild->GetNextSibling(); child;
    6923          12 :          child = child->GetNextSibling()) {
    6924          12 :       MOZ_ASSERT(child->GetFlattenedTreeParent() == expectedParent);
    6925             :     }
    6926             :   }
    6927             : #endif
    6928             : 
    6929             :   // Now the flattened tree parent of all the siblings is the same, just use the
    6930             :   // same insertion point and take the fast path, unless it's a multiple
    6931             :   // insertion point.
    6932           0 :   InsertionPoint ip = GetInsertionPoint(aStartChild);
    6933          63 :   if (ip.IsMultiple()) {
    6934           0 :     IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
    6935           0 :     return { };
    6936             :   }
    6937             : 
    6938          63 :   return ip;
    6939             : }
    6940             : 
    6941             : bool
    6942           0 : nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
    6943             :                                                 nsIContent* aStartChild,
    6944             :                                                 nsIContent* aEndChild)
    6945             : {
    6946          36 :   if (aParentFrame->IsFrameSetFrame()) {
    6947             :     // Check whether we have any kids we care about.
    6948           0 :     for (nsIContent* cur = aStartChild;
    6949           0 :          cur != aEndChild;
    6950           0 :          cur = cur->GetNextSibling()) {
    6951           0 :       if (IsSpecialFramesetChild(cur)) {
    6952             :         // Just reframe the parent, since framesets are weird like that.
    6953           0 :         RecreateFramesForContent(aParentFrame->GetContent(),
    6954           0 :                                  InsertionKind::Async);
    6955           0 :         return true;
    6956             :       }
    6957             :     }
    6958             :   }
    6959             :   return false;
    6960             : }
    6961             : 
    6962             : void
    6963           0 : nsCSSFrameConstructor::LazilyStyleNewChildRange(nsIContent* aStartChild,
    6964             :                                                 nsIContent* aEndChild)
    6965             : {
    6966           0 :   for (nsIContent* child = aStartChild; child != aEndChild;
    6967          48 :        child = child->GetNextSibling()) {
    6968          96 :     if (child->IsElement()) {
    6969          28 :       child->AsElement()->NoteDirtyForServo();
    6970             :     }
    6971             :   }
    6972           0 : }
    6973             : 
    6974             : #ifdef DEBUG
    6975             : static bool
    6976           0 : IsFlattenedTreeChild(nsIContent* aParent, nsIContent* aChild)
    6977             : {
    6978          22 :   FlattenedChildIterator iter(aParent);
    6979          83 :   for (nsIContent* node = iter.GetNextChild();
    6980          83 :        node;
    6981             :        node = iter.GetNextChild()) {
    6982          83 :     if (node == aChild) {
    6983             :       return true;
    6984             :     }
    6985             :   }
    6986             :   return false;
    6987             : }
    6988             : #endif
    6989             : 
    6990             : void
    6991           0 : nsCSSFrameConstructor::StyleNewChildRange(nsIContent* aStartChild,
    6992             :                                           nsIContent* aEndChild)
    6993             : {
    6994          22 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
    6995             : 
    6996           0 :   for (nsIContent* child = aStartChild; child != aEndChild;
    6997          11 :        child = child->GetNextSibling()) {
    6998          22 :     if (!child->IsElement()) {
    6999             :       continue;
    7000             :     }
    7001             : 
    7002          11 :     Element* childElement = child->AsElement();
    7003             : 
    7004             :     // We only come in here from non-lazy frame construction, so the children
    7005             :     // should be unstyled.
    7006          11 :     MOZ_ASSERT(!childElement->HasServoData());
    7007             : 
    7008             : #ifdef DEBUG
    7009             :     {
    7010             :       // Furthermore, all of them should have the same flattened tree parent
    7011             :       // (GetRangeInsertionPoint ensures it). And that parent should be styled,
    7012             :       // otherwise we would've never found an insertion point at all.
    7013          11 :       Element* parent = childElement->GetFlattenedTreeParentElement();
    7014          11 :       MOZ_ASSERT(parent);
    7015           0 :       MOZ_ASSERT(parent->HasServoData());
    7016          11 :       MOZ_ASSERT(IsFlattenedTreeChild(parent, child),
    7017             :                  "GetFlattenedTreeParent and ChildIterator don't agree, fix this!");
    7018             :     }
    7019             : #endif
    7020             : 
    7021          11 :     styleSet->StyleNewSubtree(childElement);
    7022             :   }
    7023           0 : }
    7024             : 
    7025             : nsIFrame*
    7026           0 : nsCSSFrameConstructor::FindNextSiblingForAppend(const InsertionPoint& aInsertion)
    7027             : {
    7028           0 :   auto SlowPath = [&]() -> nsIFrame* {
    7029          25 :     FlattenedChildIterator iter(aInsertion.mContainer,
    7030           0 :                                 /* aStartAtBeginning = */ false);
    7031           0 :     iter.GetPreviousChild(); // Prime the iterator.
    7032           0 :     StyleDisplay unused = UNSET_DISPLAY;
    7033          75 :     return FindNextSibling(iter, unused);
    7034          25 :   };
    7035             : 
    7036           0 :   if (!IsDisplayContents(aInsertion.mContainer) &&
    7037          25 :       !nsLayoutUtils::GetAfterFrame(aInsertion.mContainer)) {
    7038          25 :     MOZ_ASSERT(!SlowPath());
    7039             :     return nullptr;
    7040             :   }
    7041             : 
    7042           0 :   return SlowPath();
    7043             : }
    7044             : 
    7045             : void
    7046           0 : nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
    7047             :                                        InsertionKind aInsertionKind)
    7048             : {
    7049           0 :   MOZ_ASSERT(aInsertionKind == InsertionKind::Sync ||
    7050             :              !RestyleManager()->IsInStyleRefresh());
    7051             : 
    7052         157 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    7053             : 
    7054             : #ifdef DEBUG
    7055           1 :   if (gNoisyContentUpdates) {
    7056           0 :     printf("nsCSSFrameConstructor::ContentAppended container=%p "
    7057             :            "first-child=%p lazy=%d\n",
    7058             :            aFirstNewContent->GetParent(),
    7059             :            aFirstNewContent,
    7060           0 :            aInsertionKind == InsertionKind::Async);
    7061           0 :     if (gReallyNoisyContentUpdates && aFirstNewContent->GetParent()) {
    7062           0 :       aFirstNewContent->GetParent()->List(stdout, 0);
    7063             :     }
    7064             :   }
    7065             : 
    7066          78 :   for (nsIContent* child = aFirstNewContent;
    7067         144 :        child;
    7068          78 :        child = child->GetNextSibling()) {
    7069             :     // XXX the GetContent() != child check is needed due to bug 135040.
    7070             :     // Remove it once that's fixed.
    7071           0 :     MOZ_ASSERT(!child->GetPrimaryFrame() ||
    7072             :                child->GetPrimaryFrame()->GetContent() != child,
    7073             :                "asked to construct a frame for a node that already has a frame");
    7074             :   }
    7075             : #endif
    7076             : 
    7077          66 :   LAYOUT_PHASE_TEMP_EXIT();
    7078             :   InsertionPoint insertion =
    7079          66 :     GetRangeInsertionPoint(aFirstNewContent, nullptr, aInsertionKind);
    7080          66 :   nsContainerFrame*& parentFrame = insertion.mParentFrame;
    7081           0 :   LAYOUT_PHASE_TEMP_REENTER();
    7082           0 :   if (!parentFrame) {
    7083             :     // We're punting on frame construction because there's no container frame.
    7084             :     // The Servo-backed style system handles this case like the lazy frame
    7085             :     // construction case, except when we're already constructing frames, in
    7086             :     // which case we shouldn't need to do anything else.
    7087           0 :     if (aInsertionKind == InsertionKind::Async) {
    7088           0 :       LazilyStyleNewChildRange(aFirstNewContent, nullptr);
    7089             :     }
    7090           0 :     return;
    7091             :   }
    7092             : 
    7093          47 :   if (aInsertionKind == InsertionKind::Async) {
    7094          29 :     if (MaybeConstructLazily(CONTENTAPPEND, aFirstNewContent)) {
    7095           0 :       LazilyStyleNewChildRange(aFirstNewContent, nullptr);
    7096          22 :       return;
    7097             :     }
    7098             :     // We couldn't construct lazily. Make Servo eagerly traverse the new content
    7099             :     // if needed (when aInsertionKind == InsertionKind::Sync, we know that the
    7100             :     // styles are up-to-date already).
    7101           0 :     StyleNewChildRange(aFirstNewContent, nullptr);
    7102             :   }
    7103             : 
    7104             : 
    7105          25 :   LAYOUT_PHASE_TEMP_EXIT();
    7106           0 :   if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) {
    7107           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7108           0 :     return;
    7109             :   }
    7110           0 :   LAYOUT_PHASE_TEMP_REENTER();
    7111             : 
    7112          25 :   if (parentFrame->IsLeaf()) {
    7113             :     // Nothing to do here; we shouldn't be constructing kids of leaves
    7114             :     // Clear lazy bits so we don't try to construct again.
    7115           0 :     ClearLazyBits(aFirstNewContent, nullptr);
    7116           0 :     return;
    7117             :   }
    7118             : 
    7119          25 :   if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) {
    7120           0 :     LAYOUT_PHASE_TEMP_EXIT();
    7121           0 :     RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
    7122           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7123           0 :     return;
    7124             :   }
    7125             : 
    7126             : #ifdef DEBUG
    7127          25 :   if (gNoisyContentUpdates && IsFramePartOfIBSplit(parentFrame)) {
    7128           0 :     printf("nsCSSFrameConstructor::ContentAppended: parentFrame=");
    7129           0 :     nsFrame::ListTag(stdout, parentFrame);
    7130             :     printf(" is ib-split\n");
    7131             :   }
    7132             : #endif
    7133             : 
    7134             :   // We should never get here with fieldsets or details, since they have
    7135             :   // multiple insertion points.
    7136          25 :   MOZ_ASSERT(!parentFrame->IsFieldSetFrame() && !parentFrame->IsDetailsFrame(),
    7137             :              "Parent frame should not be fieldset or details!");
    7138             : 
    7139          25 :   nsIFrame* nextSibling = FindNextSiblingForAppend(insertion);
    7140          25 :   if (nextSibling) {
    7141           0 :     parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
    7142             :   } else {
    7143          25 :     parentFrame =
    7144          25 :       ::ContinuationToAppendTo(parentFrame);
    7145             :   }
    7146             : 
    7147          25 :   nsContainerFrame* containingBlock = GetFloatContainingBlock(parentFrame);
    7148             : 
    7149             :   // See if the containing block has :first-letter style applied.
    7150             :   const bool haveFirstLetterStyle =
    7151          25 :     containingBlock && HasFirstLetterStyle(containingBlock);
    7152             : 
    7153             :   const bool haveFirstLineStyle =
    7154          32 :     containingBlock &&
    7155          21 :     ShouldHaveFirstLineStyle(containingBlock->GetContent(),
    7156           0 :                              containingBlock->Style());
    7157             : 
    7158          25 :   if (haveFirstLetterStyle) {
    7159           0 :     AutoWeakFrame wf(nextSibling);
    7160             : 
    7161             :     // Before we get going, remove the current letter frames
    7162           0 :     RemoveLetterFrames(mPresShell, containingBlock);
    7163             : 
    7164             :     // Reget nextSibling, since we may have killed it.
    7165             :     //
    7166             :     // FIXME(emilio): This kinda sucks! :(
    7167           0 :     if (nextSibling && !wf) {
    7168           0 :       nextSibling = FindNextSiblingForAppend(insertion);
    7169           0 :       if (nextSibling) {
    7170           0 :         parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
    7171           0 :         containingBlock = GetFloatContainingBlock(parentFrame);
    7172             :       }
    7173             :     }
    7174             :   }
    7175             : 
    7176             :   // Create some new frames
    7177             :   nsFrameConstructorState state(mPresShell,
    7178             :                                 GetAbsoluteContainingBlock(parentFrame, FIXED_POS),
    7179             :                                 GetAbsoluteContainingBlock(parentFrame, ABS_POS),
    7180          50 :                                 containingBlock);
    7181             : 
    7182           0 :   LayoutFrameType frameType = parentFrame->Type();
    7183             : 
    7184          50 :   FlattenedChildIterator iter(insertion.mContainer);
    7185          25 :   const bool haveNoXBLChildren = !iter.XBLInvolved() || !iter.GetNextChild();
    7186             : 
    7187          50 :   AutoFrameConstructionItemList items(this);
    7188          68 :   if (aFirstNewContent->GetPreviousSibling() &&
    7189          43 :       GetParentType(frameType) == eTypeBlock &&
    7190             :       haveNoXBLChildren) {
    7191             :     // If there's a text node in the normal content list just before the new
    7192             :     // items, and it has no frame, make a frame construction item for it. If it
    7193             :     // doesn't need a frame, ConstructFramesFromItemList below won't give it
    7194             :     // one.  No need to do all this if our parent type is not block, though,
    7195             :     // since WipeContainingBlock already handles that situation.
    7196             :     //
    7197             :     // Because we're appending, we don't need to worry about any text
    7198             :     // after the appended content; there can only be XBL anonymous content
    7199             :     // (text in an XBL binding is not suppressed) or generated content
    7200             :     // (and bare text nodes are not generated). Native anonymous content
    7201             :     // generated by frames never participates in inline layout.
    7202           0 :     AddTextItemIfNeeded(state,
    7203             :                         insertion,
    7204             :                         aFirstNewContent->GetPreviousSibling(),
    7205          18 :                         items);
    7206             :   }
    7207           0 :   for (nsIContent* child = aFirstNewContent;
    7208          58 :        child;
    7209          33 :        child = child->GetNextSibling()) {
    7210          33 :     AddFrameConstructionItems(state, child, false, insertion, items);
    7211             :   }
    7212             : 
    7213           0 :   nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, nextSibling);
    7214             : 
    7215             :   // Perform special check for diddling around with the frames in
    7216             :   // a ib-split inline frame.
    7217             :   // If we're appending before :after content, then we're not really
    7218             :   // appending, so let WipeContainingBlock know that.
    7219           0 :   LAYOUT_PHASE_TEMP_EXIT();
    7220          25 :   if (WipeContainingBlock(state, containingBlock, parentFrame, items,
    7221             :                           true, prevSibling)) {
    7222           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7223           0 :     return;
    7224             :   }
    7225           0 :   LAYOUT_PHASE_TEMP_REENTER();
    7226             : 
    7227             :   // If the parent is a block frame, and we're not in a special case
    7228             :   // where frames can be moved around, determine if the list is for the
    7229             :   // start or end of the block.
    7230          57 :   if (nsLayoutUtils::GetAsBlock(parentFrame) && !haveFirstLetterStyle &&
    7231          32 :       !haveFirstLineStyle && !IsFramePartOfIBSplit(parentFrame)) {
    7232           7 :     items.SetLineBoundaryAtStart(!prevSibling ||
    7233           0 :                                  !prevSibling->IsInlineOutside() ||
    7234           0 :                                  prevSibling->IsBrFrame());
    7235             :     // :after content can't be <br> so no need to check it
    7236             :     //
    7237             :     // FIXME(emilio): A display: contents sibling could! Write a test-case and
    7238             :     // fix.
    7239           7 :     items.SetLineBoundaryAtEnd(
    7240           0 :         !nextSibling || !nextSibling->IsInlineOutside());
    7241             :   }
    7242             :   // To suppress whitespace-only text frames, we have to verify that
    7243             :   // our container's DOM child list matches its flattened tree child list.
    7244          50 :   items.SetParentHasNoXBLChildren(haveNoXBLChildren);
    7245             : 
    7246           0 :   nsFrameItems frameItems;
    7247           0 :   ConstructFramesFromItemList(state, items, parentFrame,
    7248          25 :                               ParentIsWrapperAnonBox(parentFrame),
    7249          25 :                               frameItems);
    7250             : 
    7251          58 :   for (nsIContent* child = aFirstNewContent;
    7252          58 :        child;
    7253           0 :        child = child->GetNextSibling()) {
    7254             :     // Invalidate now instead of before the WipeContainingBlock call, just in
    7255             :     // case we do wipe; in that case we don't need to do this walk at all.
    7256             :     // XXXbz does that matter?  Would it make more sense to save some virtual
    7257             :     // GetChildAt_Deprecated calls instead and do this during construction of
    7258             :     // our FrameConstructionItemList?
    7259           0 :     InvalidateCanvasIfNeeded(mPresShell, child);
    7260             :   }
    7261             : 
    7262             :   // If the container is a table and a caption was appended, it needs to be put
    7263             :   // in the table wrapper frame's additional child list.
    7264          25 :   nsFrameItems captionItems;
    7265          25 :   if (LayoutFrameType::Table == frameType) {
    7266             :     // Pull out the captions.  Note that we don't want to do that as we go,
    7267             :     // because processing a single caption can add a whole bunch of things to
    7268             :     // the frame items due to pseudoframe processing.  So we'd have to pull
    7269             :     // captions from a list anyway; might as well do that here.
    7270             :     // XXXbz this is no longer true; we could pull captions directly out of the
    7271             :     // FrameConstructionItemList now.
    7272           0 :     PullOutCaptionFrames(frameItems, captionItems);
    7273             :   }
    7274             : 
    7275          25 :   if (haveFirstLineStyle && parentFrame == containingBlock) {
    7276             :     // It's possible that some of the new frames go into a
    7277             :     // first-line frame. Look at them and see...
    7278           0 :     AppendFirstLineFrames(state, containingBlock->GetContent(),
    7279           0 :                           containingBlock, frameItems);
    7280             :     // That moved things into line frames as needed, reparenting their
    7281             :     // styles.  Nothing else needs to be done.
    7282          75 :   } else if (parentFrame->Style()->HasPseudoElementData()) {
    7283             :     // parentFrame might be inside a ::first-line frame.  Check whether it is,
    7284             :     // and if so fix up our styles.
    7285           0 :     CheckForFirstLineInsertion(parentFrame, frameItems);
    7286           0 :     CheckForFirstLineInsertion(parentFrame, captionItems);
    7287             :   }
    7288             : 
    7289             :   // Notify the parent frame passing it the list of new frames
    7290             :   // Append the flowed frames to the principal child list; captions
    7291             :   // need special treatment
    7292           0 :   if (captionItems.NotEmpty()) { // append the caption to the table wrapper
    7293           0 :     NS_ASSERTION(LayoutFrameType::Table == frameType, "how did that happen?");
    7294           0 :     nsContainerFrame* outerTable = parentFrame->GetParent();
    7295           0 :     AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
    7296             :   }
    7297             : 
    7298           0 :   if (frameItems.NotEmpty()) { // append the in-flow kids
    7299           8 :     AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
    7300             :   }
    7301             : 
    7302             :   // Recover first-letter frames
    7303           1 :   if (haveFirstLetterStyle) {
    7304           0 :     RecoverLetterFrames(containingBlock);
    7305             :   }
    7306             : 
    7307             : #ifdef DEBUG
    7308          25 :   if (gReallyNoisyContentUpdates) {
    7309           0 :     printf("nsCSSFrameConstructor::ContentAppended: resulting frame model:\n");
    7310           0 :     parentFrame->List(stdout, 0);
    7311             :   }
    7312             : #endif
    7313             : 
    7314             : #ifdef ACCESSIBILITY
    7315          25 :   if (nsAccessibilityService* accService = nsIPresShell::AccService()) {
    7316           0 :     accService->ContentRangeInserted(mPresShell, aFirstNewContent, nullptr);
    7317             :   }
    7318             : #endif
    7319             : }
    7320             : 
    7321             : #ifdef MOZ_XUL
    7322             : 
    7323             : enum content_operation
    7324             : {
    7325             :     CONTENT_INSERTED,
    7326             :     CONTENT_REMOVED
    7327             : };
    7328             : 
    7329             : // Helper function to lookup the listbox body frame and send a notification
    7330             : // for insertion or removal of content
    7331             : static bool
    7332          12 : NotifyListBoxBody(nsPresContext*    aPresContext,
    7333             :                   nsIContent*        aChild,
    7334             :                   // Only used for the removed notification
    7335             :                   nsIContent*        aOldNextSibling,
    7336             :                   nsIFrame*          aChildFrame,
    7337             :                   content_operation  aOperation)
    7338             : {
    7339           0 :   nsListBoxBodyFrame* listBoxBodyFrame = MaybeGetListBoxBodyFrame(aChild);
    7340           0 :   if (listBoxBodyFrame) {
    7341           0 :     if (aOperation == CONTENT_REMOVED) {
    7342             :       // Except if we have an aChildFrame and its parent is not the right
    7343             :       // thing, then we don't do this.  Pseudo frames are so much fun....
    7344           0 :       if (!aChildFrame || aChildFrame->GetParent() == listBoxBodyFrame) {
    7345           0 :         listBoxBodyFrame->OnContentRemoved(aPresContext, aChild->GetParent(),
    7346           0 :                                            aChildFrame, aOldNextSibling);
    7347           0 :         return true;
    7348             :       }
    7349             :     } else {
    7350           0 :       listBoxBodyFrame->OnContentInserted(aChild);
    7351           0 :       return true;
    7352             :     }
    7353             :   }
    7354             : 
    7355             :   return false;
    7356             : }
    7357             : #endif // MOZ_XUL
    7358             : 
    7359             : void
    7360          23 : nsCSSFrameConstructor::ContentInserted(nsIContent* aChild,
    7361             :                                        nsILayoutHistoryState* aFrameState,
    7362             :                                        InsertionKind aInsertionKind)
    7363             : {
    7364          23 :   ContentRangeInserted(aChild,
    7365             :                        aChild->GetNextSibling(),
    7366             :                        aFrameState,
    7367          23 :                        aInsertionKind);
    7368          23 : }
    7369             : 
    7370             : // ContentRangeInserted handles creating frames for a range of nodes that
    7371             : // aren't at the end of their childlist. ContentRangeInserted isn't a real
    7372             : // content notification, but rather it handles regular ContentInserted calls
    7373             : // for a single node as well as the lazy construction of frames for a range of
    7374             : // nodes when called from CreateNeededFrames. For a range of nodes to be
    7375             : // suitable to have its frames constructed all at once they must meet the same
    7376             : // conditions that ContentAppended imposes (GetRangeInsertionPoint checks
    7377             : // these), plus more. Namely when finding the insertion prevsibling we must not
    7378             : // need to consult something specific to any one node in the range, so that the
    7379             : // insertion prevsibling would be the same for each node in the range. So we
    7380             : // pass the first node in the range to GetInsertionPrevSibling, and if
    7381             : // IsValidSibling (the only place GetInsertionPrevSibling might look at the
    7382             : // passed in node itself) needs to resolve style on the node we record this and
    7383             : // return that this range needs to be split up and inserted separately. Table
    7384             : // captions need extra attention as we need to determine where to insert them
    7385             : // in the caption list, while skipping any nodes in the range being inserted
    7386             : // (because when we treat the caption frames the other nodes have had their
    7387             : // frames constructed but not yet inserted into the frame tree).
    7388             : void
    7389          33 : nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
    7390             :                                             nsIContent* aEndChild,
    7391             :                                             nsILayoutHistoryState* aFrameState,
    7392             :                                             InsertionKind aInsertionKind)
    7393             : {
    7394          33 :   MOZ_ASSERT(aInsertionKind == InsertionKind::Sync ||
    7395             :              !RestyleManager()->IsInStyleRefresh());
    7396             : 
    7397           1 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    7398             : 
    7399          33 :   MOZ_ASSERT(aStartChild, "must always pass a child");
    7400             : 
    7401             : #ifdef DEBUG
    7402           1 :   if (gNoisyContentUpdates) {
    7403           0 :     printf("nsCSSFrameConstructor::ContentRangeInserted container=%p "
    7404             :            "start-child=%p end-child=%p lazy=%d\n",
    7405             :            aStartChild->GetParent(),
    7406             :            aStartChild,
    7407             :            aEndChild,
    7408           0 :            aInsertionKind == InsertionKind::Async);
    7409           0 :     if (gReallyNoisyContentUpdates) {
    7410           0 :       if (aStartChild->GetParent()) {
    7411           0 :         aStartChild->GetParent()->List(stdout,0);
    7412             :       } else {
    7413           0 :         aStartChild->List(stdout, 0);
    7414             :       }
    7415             :     }
    7416             :   }
    7417             : 
    7418          33 :   for (nsIContent* child = aStartChild;
    7419          66 :        child != aEndChild;
    7420          33 :        child = child->GetNextSibling()) {
    7421             :     // XXX the GetContent() != child check is needed due to bug 135040.
    7422             :     // Remove it once that's fixed.
    7423          33 :     NS_ASSERTION(!child->GetPrimaryFrame() ||
    7424             :                  child->GetPrimaryFrame()->GetContent() != child,
    7425             :                  "asked to construct a frame for a node that already has a frame");
    7426             :   }
    7427             : #endif
    7428             : 
    7429             : 
    7430          33 :   bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
    7431          33 :   NS_ASSERTION(isSingleInsert ||
    7432             :                aInsertionKind == InsertionKind::Sync,
    7433             :                "range insert shouldn't be lazy");
    7434          33 :   NS_ASSERTION(isSingleInsert || aEndChild,
    7435             :                "range should not include all nodes after aStartChild");
    7436             : 
    7437             : #ifdef MOZ_XUL
    7438          33 :   if (aStartChild->GetParent() && IsXULListBox(aStartChild->GetParent())) {
    7439           0 :     if (isSingleInsert) {
    7440             :       // The insert case in NotifyListBoxBody doesn't use "old next sibling".
    7441           0 :       if (NotifyListBoxBody(mPresShell->GetPresContext(),
    7442             :                             aStartChild, nullptr, nullptr, CONTENT_INSERTED)) {
    7443           1 :         return;
    7444             :       }
    7445             :     } else {
    7446             :       // We don't handle a range insert to a listbox parent, issue single
    7447             :       // ContertInserted calls for each node inserted.
    7448           0 :       LAYOUT_PHASE_TEMP_EXIT();
    7449           0 :       IssueSingleInsertNofications(aStartChild, aEndChild, InsertionKind::Sync);
    7450           0 :       LAYOUT_PHASE_TEMP_REENTER();
    7451           0 :       return;
    7452             :     }
    7453             :   }
    7454             : #endif // MOZ_XUL
    7455             : 
    7456             :   // If we have a null parent, then this must be the document element being
    7457             :   // inserted, or some other child of the document in the DOM (might be a PI,
    7458             :   // say).
    7459          33 :   if (!aStartChild->GetParent()) {
    7460          19 :     MOZ_ASSERT(isSingleInsert,
    7461             :                "root node insertion should be a single insertion");
    7462          19 :     Element* docElement = mDocument->GetRootElement();
    7463             : 
    7464          19 :     if (aStartChild != docElement) {
    7465             :       // Not the root element; just bail out
    7466             :       return;
    7467             :     }
    7468             : 
    7469           0 :     MOZ_ASSERT(!mRootElementFrame, "root element frame already created");
    7470             : 
    7471             :     // Create frames for the document element and its child elements
    7472           1 :     if (ConstructDocElementFrame(docElement, aFrameState)) {
    7473          19 :       InvalidateCanvasIfNeeded(mPresShell, aStartChild);
    7474             : #ifdef DEBUG
    7475          19 :       if (gReallyNoisyContentUpdates) {
    7476             :         printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
    7477           0 :                "model:\n");
    7478           0 :         mRootElementFrame->List(stdout, 0);
    7479             :       }
    7480             : #endif
    7481             :     }
    7482             : 
    7483          19 :     if (aFrameState) {
    7484             :       // Restore frame state for the root scroll frame if there is one
    7485           0 :       if (nsIFrame* rootScrollFrame = mPresShell->GetRootScrollFrame()) {
    7486           0 :         RestoreFrameStateFor(rootScrollFrame, aFrameState);
    7487             :       }
    7488             :     }
    7489             : 
    7490             : #ifdef ACCESSIBILITY
    7491          19 :     if (nsAccessibilityService* accService = nsIPresShell::AccService()) {
    7492           0 :       accService->ContentRangeInserted(mPresShell, aStartChild, aEndChild);
    7493             :     }
    7494             : #endif
    7495             : 
    7496             :     return;
    7497             :   }
    7498             : 
    7499          14 :   InsertionPoint insertion;
    7500          14 :   if (isSingleInsert) {
    7501             :     // See if we have an XBL insertion point. If so, then that's our
    7502             :     // real parent frame; if not, then the frame hasn't been built yet
    7503             :     // and we just bail.
    7504           0 :     insertion = GetInsertionPoint(aStartChild);
    7505             :   } else {
    7506             :     // Get our insertion point. If we need to issue single ContentInserteds
    7507             :     // GetRangeInsertionPoint will take care of that for us.
    7508           0 :     LAYOUT_PHASE_TEMP_EXIT();
    7509           0 :     insertion = GetRangeInsertionPoint(aStartChild, aEndChild, aInsertionKind);
    7510           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7511             :   }
    7512             : 
    7513           0 :   if (!insertion.mParentFrame) {
    7514             :     // We're punting on frame construction because there's no container frame.
    7515             :     // The Servo-backed style system handles this case like the lazy frame
    7516             :     // construction case, except when we're already constructing frames, in
    7517             :     // which case we shouldn't need to do anything else.
    7518           0 :     if (aInsertionKind == InsertionKind::Async) {
    7519           0 :       LazilyStyleNewChildRange(aStartChild, aEndChild);
    7520             :     }
    7521             :     return;
    7522             :   }
    7523             : 
    7524          11 :   if (aInsertionKind == InsertionKind::Async) {
    7525           4 :     if (MaybeConstructLazily(CONTENTINSERT, aStartChild)) {
    7526           0 :       LazilyStyleNewChildRange(aStartChild, aEndChild);
    7527           0 :       return;
    7528             :     }
    7529             :     // We couldn't construct lazily. Make Servo eagerly traverse the new content
    7530             :     // if needed (when aInsertionKind == InsertionKind::Sync, we know that the
    7531             :     // styles are up-to-date already).
    7532           4 :     StyleNewChildRange(aStartChild, aEndChild);
    7533             :   }
    7534             : 
    7535             :   bool isAppend, isRangeInsertSafe;
    7536             :   nsIFrame* prevSibling = GetInsertionPrevSibling(&insertion, aStartChild,
    7537           0 :                                                   &isAppend, &isRangeInsertSafe);
    7538             : 
    7539             :   // check if range insert is safe
    7540          11 :   if (!isSingleInsert && !isRangeInsertSafe) {
    7541             :     // must fall back to a single ContertInserted for each child in the range
    7542           0 :     LAYOUT_PHASE_TEMP_EXIT();
    7543           0 :     IssueSingleInsertNofications(aStartChild, aEndChild, InsertionKind::Sync);
    7544           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7545           0 :     return;
    7546             :   }
    7547             : 
    7548           0 :   LayoutFrameType frameType = insertion.mParentFrame->Type();
    7549          11 :   LAYOUT_PHASE_TEMP_EXIT();
    7550          11 :   if (MaybeRecreateForFrameset(insertion.mParentFrame, aStartChild, aEndChild)) {
    7551           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7552           0 :     return;
    7553             :   }
    7554           0 :   LAYOUT_PHASE_TEMP_REENTER();
    7555             : 
    7556             :   // We should only get here with fieldsets when doing a single insert, because
    7557             :   // fieldsets have multiple insertion points.
    7558          11 :   NS_ASSERTION(isSingleInsert || frameType != LayoutFrameType::FieldSet,
    7559             :                "Unexpected parent");
    7560          11 :   if (IsFrameForFieldSet(insertion.mParentFrame) &&
    7561           0 :       aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
    7562             :     // Just reframe the parent, since figuring out whether this
    7563             :     // should be the new legend and then handling it is too complex.
    7564             :     // We could do a little better here --- check if the fieldset already
    7565             :     // has a legend which occurs earlier in its child list than this node,
    7566             :     // and if so, proceed. But we'd have to extend nsFieldSetFrame
    7567             :     // to locate this legend in the inserted frames and extract it.
    7568           0 :     LAYOUT_PHASE_TEMP_EXIT();
    7569           0 :     RecreateFramesForContent(insertion.mParentFrame->GetContent(),
    7570           0 :                              InsertionKind::Async);
    7571           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7572           0 :     return;
    7573             :   }
    7574             : 
    7575             :   // We should only get here with details when doing a single insertion because
    7576             :   // we treat details frame as if it has multiple insertion points.
    7577           0 :   MOZ_ASSERT(isSingleInsert || frameType != LayoutFrameType::Details);
    7578           0 :   if (frameType == LayoutFrameType::Details) {
    7579             :     // When inserting an element into <details>, just reframe the details frame
    7580             :     // and let it figure out where the element should be laid out. It might seem
    7581             :     // expensive to recreate the entire details frame, but it's the simplest way
    7582             :     // to handle the insertion.
    7583           0 :     LAYOUT_PHASE_TEMP_EXIT();
    7584           0 :     RecreateFramesForContent(insertion.mParentFrame->GetContent(),
    7585           0 :                              InsertionKind::Async);
    7586           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7587           0 :     return;
    7588             :   }
    7589             : 
    7590             :   // Don't construct kids of leaves
    7591          11 :   if (insertion.mParentFrame->IsLeaf()) {
    7592             :     // Clear lazy bits so we don't try to construct again.
    7593           0 :     ClearLazyBits(aStartChild, aEndChild);
    7594           0 :     return;
    7595             :   }
    7596             : 
    7597             :   // FIXME(emilio): This looks terribly inefficient if you insert elements deep
    7598             :   // in a MathML subtree.
    7599          11 :   if (insertion.mParentFrame->IsFrameOfType(nsIFrame::eMathML)) {
    7600           0 :     LAYOUT_PHASE_TEMP_EXIT();
    7601           0 :     RecreateFramesForContent(insertion.mParentFrame->GetContent(),
    7602           0 :                              InsertionKind::Async);
    7603           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7604           0 :     return;
    7605             :   }
    7606             : 
    7607             :   nsFrameConstructorState state(mPresShell,
    7608          11 :                                 GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS),
    7609          11 :                                 GetAbsoluteContainingBlock(insertion.mParentFrame, ABS_POS),
    7610          11 :                                 GetFloatContainingBlock(insertion.mParentFrame),
    7611          55 :                                 do_AddRef(aFrameState));
    7612             : 
    7613             :   // Recover state for the containing block - we need to know if
    7614             :   // it has :first-letter or :first-line style applied to it. The
    7615             :   // reason we care is that the internal structure in these cases
    7616             :   // is not the normal structure and requires custom updating
    7617             :   // logic.
    7618          11 :   nsContainerFrame* containingBlock = state.mFloatedItems.containingBlock;
    7619          11 :   bool haveFirstLetterStyle = false;
    7620           0 :   bool haveFirstLineStyle = false;
    7621             : 
    7622             :   // In order to shave off some cycles, we only dig up the
    7623             :   // containing block haveFirst* flags if the parent frame where
    7624             :   // the insertion/append is occurring is an inline or block
    7625             :   // container. For other types of containers this isn't relevant.
    7626           0 :   StyleDisplay parentDisplay = insertion.mParentFrame->GetDisplay();
    7627             : 
    7628             :   // Examine the insertion.mParentFrame where the insertion is taking
    7629             :   // place. If it's a certain kind of container then some special
    7630             :   // processing is done.
    7631           0 :   if ((StyleDisplay::Block == parentDisplay) ||
    7632          11 :       (StyleDisplay::ListItem == parentDisplay) ||
    7633           0 :       (StyleDisplay::Inline == parentDisplay) ||
    7634             :       (StyleDisplay::InlineBlock == parentDisplay)) {
    7635             :     // Recover the special style flags for the containing block
    7636           3 :     if (containingBlock) {
    7637           0 :       haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
    7638             :       haveFirstLineStyle =
    7639           0 :         ShouldHaveFirstLineStyle(containingBlock->GetContent(),
    7640           0 :                                  containingBlock->Style());
    7641             :     }
    7642             : 
    7643           0 :     if (haveFirstLetterStyle) {
    7644             :       // If our current insertion.mParentFrame is a Letter frame, use its parent as our
    7645             :       // new parent hint
    7646           0 :       if (insertion.mParentFrame->IsLetterFrame()) {
    7647             :         // If insertion.mParentFrame is out of flow, then we actually want the parent of
    7648             :         // the placeholder frame.
    7649           0 :         if (insertion.mParentFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    7650             :           nsPlaceholderFrame* placeholderFrame =
    7651           0 :             insertion.mParentFrame->GetPlaceholderFrame();
    7652           0 :           NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?");
    7653           0 :           insertion.mParentFrame = placeholderFrame->GetParent();
    7654             :         } else {
    7655           0 :           insertion.mParentFrame = insertion.mParentFrame->GetParent();
    7656             :         }
    7657             :       }
    7658             : 
    7659             :       // Remove the old letter frames before doing the insertion
    7660           0 :       RemoveLetterFrames(mPresShell, state.mFloatedItems.containingBlock);
    7661             : 
    7662             :       // Removing the letterframes messes around with the frame tree, removing
    7663             :       // and creating frames.  We need to reget our prevsibling, parent frame,
    7664             :       // etc.
    7665             :       prevSibling = GetInsertionPrevSibling(&insertion, aStartChild, &isAppend,
    7666           0 :                                             &isRangeInsertSafe);
    7667             : 
    7668             :       // Need check whether a range insert is still safe.
    7669           0 :       if (!isSingleInsert && !isRangeInsertSafe) {
    7670             :         // Need to recover the letter frames first.
    7671           0 :         RecoverLetterFrames(state.mFloatedItems.containingBlock);
    7672             : 
    7673             :         // must fall back to a single ContertInserted for each child in the range
    7674           0 :         LAYOUT_PHASE_TEMP_EXIT();
    7675           0 :         IssueSingleInsertNofications(aStartChild, aEndChild, InsertionKind::Sync);
    7676           0 :         LAYOUT_PHASE_TEMP_REENTER();
    7677           0 :         return;
    7678             :       }
    7679             : 
    7680           0 :       frameType = insertion.mParentFrame->Type();
    7681             :     }
    7682             :   }
    7683             : 
    7684          22 :   AutoFrameConstructionItemList items(this);
    7685          11 :   ParentType parentType = GetParentType(frameType);
    7686          22 :   FlattenedChildIterator iter(insertion.mContainer);
    7687          11 :   bool haveNoXBLChildren = !iter.XBLInvolved() || !iter.GetNextChild();
    7688          22 :   if (aStartChild->GetPreviousSibling() &&
    7689           0 :       parentType == eTypeBlock && haveNoXBLChildren) {
    7690             :     // If there's a text node in the normal content list just before the
    7691             :     // new nodes, and it has no frame, make a frame construction item for
    7692             :     // it, because it might need a frame now.  No need to do this if our
    7693             :     // parent type is not block, though, since WipeContainingBlock
    7694             :     // already handles that sitation.
    7695           0 :     AddTextItemIfNeeded(state, insertion, aStartChild->GetPreviousSibling(),
    7696           0 :                         items);
    7697             :   }
    7698             : 
    7699           0 :   if (isSingleInsert) {
    7700           0 :     AddFrameConstructionItems(state, aStartChild,
    7701           0 :                               aStartChild->IsRootOfAnonymousSubtree(),
    7702          11 :                               insertion, items);
    7703             :   } else {
    7704           0 :     for (nsIContent* child = aStartChild;
    7705           0 :          child != aEndChild;
    7706           0 :          child = child->GetNextSibling()){
    7707           0 :       AddFrameConstructionItems(state, child, false, insertion, items);
    7708             :     }
    7709             :   }
    7710             : 
    7711           0 :   if (aEndChild && parentType == eTypeBlock && haveNoXBLChildren) {
    7712             :     // If there's a text node in the normal content list just after the
    7713             :     // new nodes, and it has no frame, make a frame construction item for
    7714             :     // it, because it might need a frame now.  No need to do this if our
    7715             :     // parent type is not block, though, since WipeContainingBlock
    7716             :     // already handles that sitation.
    7717           5 :     AddTextItemIfNeeded(state, insertion, aEndChild, items);
    7718             :   }
    7719             : 
    7720             :   // Perform special check for diddling around with the frames in
    7721             :   // a special inline frame.
    7722             :   // If we're appending before :after content, then we're not really
    7723             :   // appending, so let WipeContainingBlock know that.
    7724           0 :   LAYOUT_PHASE_TEMP_EXIT();
    7725          11 :   if (WipeContainingBlock(state, containingBlock, insertion.mParentFrame, items,
    7726             :                           isAppend, prevSibling)) {
    7727           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7728           0 :     return;
    7729             :   }
    7730           0 :   LAYOUT_PHASE_TEMP_REENTER();
    7731             : 
    7732             :   // If the container is a table and a caption will be appended, it needs to be
    7733             :   // put in the table wrapper frame's additional child list.
    7734             :   // We make no attempt here to set flags to indicate whether the list
    7735             :   // will be at the start or end of a block. It doesn't seem worthwhile.
    7736           0 :   nsFrameItems frameItems, captionItems;
    7737           0 :   ConstructFramesFromItemList(state, items, insertion.mParentFrame,
    7738           0 :                               ParentIsWrapperAnonBox(insertion.mParentFrame),
    7739           0 :                               frameItems);
    7740             : 
    7741          11 :   if (frameItems.NotEmpty()) {
    7742           0 :     for (nsIContent* child = aStartChild;
    7743           0 :          child != aEndChild;
    7744           0 :          child = child->GetNextSibling()){
    7745           9 :       InvalidateCanvasIfNeeded(mPresShell, child);
    7746             :     }
    7747             : 
    7748           0 :     if (LayoutFrameType::Table == frameType ||
    7749           9 :         LayoutFrameType::TableWrapper == frameType) {
    7750           0 :       PullOutCaptionFrames(frameItems, captionItems);
    7751             :     }
    7752             :   }
    7753             : 
    7754           0 :   if (haveFirstLineStyle && insertion.mParentFrame == containingBlock && isAppend) {
    7755             :     // It's possible that the new frame goes into a first-line
    7756             :     // frame. Look at it and see...
    7757           0 :     AppendFirstLineFrames(state, containingBlock->GetContent(),
    7758           0 :                           containingBlock, frameItems);
    7759          33 :   } else if (insertion.mParentFrame->Style()->HasPseudoElementData()) {
    7760           0 :     CheckForFirstLineInsertion(insertion.mParentFrame, frameItems);
    7761           0 :     CheckForFirstLineInsertion(insertion.mParentFrame, captionItems);
    7762             :   }
    7763             : 
    7764             :   // We might have captions; put them into the caption list of the
    7765             :   // table wrapper frame.
    7766          11 :   if (captionItems.NotEmpty()) {
    7767           0 :     NS_ASSERTION(LayoutFrameType::Table == frameType ||
    7768             :                  LayoutFrameType::TableWrapper == frameType,
    7769             :                  "parent for caption is not table?");
    7770             :     // We need to determine where to put the caption items; start with the
    7771             :     // the parent frame that has already been determined and get the insertion
    7772             :     // prevsibling of the first caption item.
    7773             :     bool captionIsAppend;
    7774           0 :     nsIFrame* captionPrevSibling = nullptr;
    7775             : 
    7776             :     // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
    7777             :     bool ignored;
    7778           0 :     InsertionPoint captionInsertion(insertion.mParentFrame, insertion.mContainer);
    7779           0 :     if (isSingleInsert) {
    7780             :       captionPrevSibling =
    7781             :         GetInsertionPrevSibling(&captionInsertion, aStartChild,
    7782           0 :                                 &captionIsAppend, &ignored);
    7783             :     } else {
    7784           0 :       nsIContent* firstCaption = captionItems.FirstChild()->GetContent();
    7785             :       // It is very important here that we skip the children in
    7786             :       // [aStartChild,aEndChild) when looking for a
    7787             :       // prevsibling.
    7788             :       captionPrevSibling =
    7789             :         GetInsertionPrevSibling(&captionInsertion, firstCaption,
    7790             :                                 &captionIsAppend, &ignored,
    7791           0 :                                 aStartChild, aEndChild);
    7792             :     }
    7793             : 
    7794           0 :     nsContainerFrame* outerTable = nullptr;
    7795           0 :     if (GetCaptionAdjustedParent(captionInsertion.mParentFrame,
    7796           0 :                                  captionItems.FirstChild(),
    7797             :                                  &outerTable)) {
    7798             :       // If the parent is not a table wrapper frame we will try to add frames
    7799             :       // to a named child list that the parent does not honor and the frames
    7800             :       // will get lost.
    7801           0 :       NS_ASSERTION(outerTable->IsTableWrapperFrame(),
    7802             :                    "Pseudo frame construction failure; "
    7803             :                    "a caption can be only a child of a table wrapper frame");
    7804             : 
    7805             :       // If the parent of our current prevSibling is different from the frame
    7806             :       // we'll actually use as the parent, then the calculated insertion
    7807             :       // point is now invalid (bug 341382).
    7808           0 :       if (captionPrevSibling &&
    7809           0 :           captionPrevSibling->GetParent() != outerTable) {
    7810           0 :           captionPrevSibling = nullptr;
    7811             :       }
    7812           0 :       if (captionIsAppend) {
    7813           0 :         AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
    7814             :       } else {
    7815           0 :         InsertFrames(outerTable, nsIFrame::kCaptionList,
    7816           0 :                      captionPrevSibling, captionItems);
    7817             :       }
    7818             :     }
    7819             :   }
    7820             : 
    7821          11 :   if (frameItems.NotEmpty()) {
    7822             :     // Notify the parent frame
    7823           9 :     if (isAppend) {
    7824           0 :       AppendFramesToParent(state, insertion.mParentFrame, frameItems, prevSibling);
    7825             :     } else {
    7826           8 :       InsertFrames(insertion.mParentFrame, kPrincipalList, prevSibling, frameItems);
    7827             :     }
    7828             :   }
    7829             : 
    7830          11 :   if (haveFirstLetterStyle) {
    7831             :     // Recover the letter frames for the containing block when
    7832             :     // it has first-letter style.
    7833           0 :     RecoverLetterFrames(state.mFloatedItems.containingBlock);
    7834             :   }
    7835             : 
    7836             : #ifdef DEBUG
    7837          11 :   if (gReallyNoisyContentUpdates && insertion.mParentFrame) {
    7838           0 :     printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame model:\n");
    7839           0 :     insertion.mParentFrame->List(stdout, 0);
    7840             :   }
    7841             : #endif
    7842             : 
    7843             : #ifdef ACCESSIBILITY
    7844          11 :   if (nsAccessibilityService* accService = nsIPresShell::AccService()) {
    7845           0 :     accService->ContentRangeInserted(mPresShell, aStartChild, aEndChild);
    7846             :   }
    7847             : #endif
    7848             : }
    7849             : 
    7850             : bool
    7851          12 : nsCSSFrameConstructor::ContentRemoved(nsIContent* aChild,
    7852             :                                       nsIContent* aOldNextSibling,
    7853             :                                       RemoveFlags aFlags)
    7854             : {
    7855          12 :   MOZ_ASSERT(aChild);
    7856          12 :   MOZ_ASSERT(!aChild->IsRootOfAnonymousSubtree() || !aOldNextSibling,
    7857             :              "Anonymous roots don't have siblings");
    7858          36 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    7859          24 :   nsPresContext* presContext = mPresShell->GetPresContext();
    7860          12 :   MOZ_ASSERT(presContext, "Our presShell should have a valid presContext");
    7861             : 
    7862             :   // We want to detect when the viewport override element stored in the
    7863             :   // prescontext is in the subtree being removed.  Except in fullscreen cases
    7864             :   // (which are handled in Element::UnbindFromTree and do not get stored on the
    7865             :   // prescontext), the override element is always either the root element or a
    7866             :   // <body> child of the root element.  So we can only be removing the stored
    7867             :   // override element if the thing being removed is either the override element
    7868             :   // itself or the root element (which can be a parent of the override element).
    7869          36 :   if (aChild == presContext->GetViewportScrollbarStylesOverrideElement() ||
    7870          35 :       (aChild->IsElement() && !aChild->GetParent())) {
    7871             :     // We might be removing the element that we propagated viewport scrollbar
    7872             :     // styles from.  Recompute those. (This clause covers two of the three
    7873             :     // possible scrollbar-propagation sources: the <body> [as aChild or a
    7874             :     // descendant] and the root node. The other possible scrollbar-propagation
    7875             :     // source is a fullscreen element, and we have code elsewhere to update
    7876             :     // scrollbars after fullscreen elements are removed -- specifically, it's
    7877             :     // part of the fullscreen cleanup code called by Element::UnbindFromTree.
    7878             :     // We don't handle the fullscreen case here, because it doesn't change the
    7879             :     // scrollbar styles override element stored on the prescontext.)
    7880             :     Element* newOverrideElement =
    7881           0 :       presContext->UpdateViewportScrollbarStylesOverride();
    7882             : 
    7883             :     // If aChild is the root, then we don't need to do any reframing of
    7884             :     // newOverrideElement, because we're about to tear down the whole frame tree
    7885             :     // anyway.  And we need to make sure we don't do any such reframing, because
    7886             :     // reframing the <body> can trigger a reframe of the <html> and then reenter
    7887             :     // here.
    7888             :     //
    7889             :     // But if aChild is not the root, and if newOverrideElement is not
    7890             :     // the root and isn't aChild (which it could be if all we're doing
    7891             :     // here is reframing the current override element), it needs
    7892             :     // reframing.  In particular, it used to have a scrollframe
    7893             :     // (because its overflow was not "visible"), but now it will
    7894             :     // propagate its overflow to the viewport, so it should not need a
    7895             :     // scrollframe anymore.
    7896           0 :     if (aChild->GetParent() && newOverrideElement &&
    7897           0 :         newOverrideElement->GetParent() && newOverrideElement != aChild) {
    7898           0 :       LAYOUT_PHASE_TEMP_EXIT();
    7899           0 :       RecreateFramesForContent(newOverrideElement, InsertionKind::Async);
    7900           0 :       LAYOUT_PHASE_TEMP_REENTER();
    7901             :     }
    7902             :   }
    7903             : 
    7904             : #ifdef DEBUG
    7905           1 :   if (gNoisyContentUpdates) {
    7906           0 :     printf("nsCSSFrameConstructor::ContentRemoved container=%p child=%p "
    7907             :            "old-next-sibling=%p\n",
    7908             :            aChild->GetParent(),
    7909             :            aChild,
    7910           0 :            aOldNextSibling);
    7911           0 :     if (gReallyNoisyContentUpdates) {
    7912           0 :       aChild->GetParent()->List(stdout, 0);
    7913             :     }
    7914             :   }
    7915             : #endif
    7916             : 
    7917          12 :   nsIFrame* childFrame = aChild->GetPrimaryFrame();
    7918          21 :   if (!childFrame || childFrame->GetContent() != aChild) {
    7919             :     // XXXbz the GetContent() != aChild check is needed due to bug 135040.
    7920             :     // Remove it once that's fixed.
    7921           3 :     childFrame = nullptr;
    7922             :   }
    7923             : 
    7924             : #ifdef MOZ_XUL
    7925          12 :   if (NotifyListBoxBody(presContext, aChild, aOldNextSibling,
    7926             :                         childFrame, CONTENT_REMOVED)) {
    7927             :     return false;
    7928             :   }
    7929             : #endif // MOZ_XUL
    7930             : 
    7931             :   // If we're removing the root, then make sure to remove things starting at
    7932             :   // the viewport's child instead of the primary frame (which might even be
    7933             :   // null if the root had an XBL binding or display:none, even though the
    7934             :   // frames above it got created).  Detecting removal of a root is a little
    7935             :   // exciting; in particular, having no parent is necessary but NOT sufficient.
    7936             :   // Due to how we process reframes, the content node might not even be in our
    7937             :   // document by now.  So explicitly check whether the viewport's first kid's
    7938             :   // content node is aChild.
    7939             :   //
    7940             :   // FIXME(emilio): I think the "might not be in our document" bit is impossible
    7941             :   // now.
    7942           0 :   bool isRoot = false;
    7943           0 :   if (!aChild->GetParent()) {
    7944           0 :     if (nsIFrame* viewport = GetRootFrame()) {
    7945           0 :       nsIFrame* firstChild = viewport->PrincipalChildList().FirstChild();
    7946           0 :       if (firstChild && firstChild->GetContent() == aChild) {
    7947           0 :         isRoot = true;
    7948           0 :         childFrame = firstChild;
    7949           0 :         NS_ASSERTION(!childFrame->GetNextSibling(), "How did that happen?");
    7950             :       }
    7951             :     }
    7952             :   }
    7953             : 
    7954             :   // We need to be conservative about when to determine whether something has
    7955             :   // display: contents or not because at this point our actual display may be
    7956             :   // different.
    7957             :   //
    7958             :   // Consider the case of:
    7959             :   //
    7960             :   //   <div id="A" style="display: contents"><div id="B"></div></div>
    7961             :   //
    7962             :   // If we reconstruct A because its display changed to "none", we still need to
    7963             :   // cleanup the frame on B, but A's display is now "none", so we can't poke at
    7964             :   // the style of it.
    7965             :   //
    7966             :   // FIXME(emilio, bug 1450366): We can make this faster without adding much
    7967             :   // complexity for the display: none -> other case, which right now
    7968             :   // unnecessarily walks the content tree down.
    7969           3 :   auto CouldHaveBeenDisplayContents = [aFlags](nsIContent* aContent) -> bool {
    7970           3 :     return aFlags == REMOVE_FOR_RECONSTRUCTION || IsDisplayContents(aContent);
    7971           0 :   };
    7972             : 
    7973           0 :   if (!childFrame && CouldHaveBeenDisplayContents(aChild)) {
    7974             :     // NOTE(emilio): We may iterate through ::before and ::after here and they
    7975             :     // may be gone after the respective ContentRemoved call. Right now
    7976             :     // StyleChildrenIterator handles that properly, so it's not an issue.
    7977           0 :     StyleChildrenIterator iter(aChild);
    7978           0 :     for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
    7979           0 :       if (c->GetPrimaryFrame() || CouldHaveBeenDisplayContents(aChild)) {
    7980           0 :         LAYOUT_PHASE_TEMP_EXIT();
    7981             :         bool didReconstruct =
    7982           0 :           ContentRemoved(c, nullptr, REMOVE_FOR_RECONSTRUCTION);
    7983           0 :         LAYOUT_PHASE_TEMP_REENTER();
    7984           0 :         if (didReconstruct) {
    7985             :           return true;
    7986             :         }
    7987             :       }
    7988             :     }
    7989             :     return false;
    7990             :   }
    7991             : 
    7992             : 
    7993           0 :   if (childFrame) {
    7994           0 :     InvalidateCanvasIfNeeded(mPresShell, aChild);
    7995             : 
    7996             :     // See whether we need to remove more than just childFrame
    7997           9 :     LAYOUT_PHASE_TEMP_EXIT();
    7998           9 :     if (MaybeRecreateContainerForFrameRemoval(childFrame)) {
    7999           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8000           0 :       return true;
    8001             :     }
    8002           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8003             : 
    8004             :     // Get the childFrame's parent frame
    8005           0 :     nsIFrame* parentFrame = childFrame->GetParent();
    8006           0 :     LayoutFrameType parentType = parentFrame->Type();
    8007             : 
    8008           0 :     if (parentType == LayoutFrameType::FrameSet &&
    8009           0 :         IsSpecialFramesetChild(aChild)) {
    8010             :       // Just reframe the parent, since framesets are weird like that.
    8011           0 :       LAYOUT_PHASE_TEMP_EXIT();
    8012           0 :       RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
    8013           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8014           0 :       return true;
    8015             :     }
    8016             : 
    8017             :     // If we're a child of MathML, then we should reframe the MathML content.
    8018             :     // If we're non-MathML, then we would be wrapped in a block so we need to
    8019             :     // check our grandparent in that case.
    8020             :     nsIFrame* possibleMathMLAncestor = parentType == LayoutFrameType::Block
    8021           0 :                                          ? parentFrame->GetParent()
    8022           9 :                                          : parentFrame;
    8023           9 :     if (possibleMathMLAncestor->IsFrameOfType(nsIFrame::eMathML)) {
    8024           0 :       LAYOUT_PHASE_TEMP_EXIT();
    8025           0 :       RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
    8026           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8027           0 :       return true;
    8028             :     }
    8029             : 
    8030             :     // Undo XUL wrapping if it's no longer needed.
    8031             :     // (If we're in the XUL block-wrapping situation, parentFrame is the
    8032             :     // wrapper frame.)
    8033           0 :     nsIFrame* grandparentFrame = parentFrame->GetParent();
    8034           0 :     if (grandparentFrame && grandparentFrame->IsXULBoxFrame() &&
    8035           0 :         (grandparentFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
    8036             :         // check if this frame is the only one needing wrapping
    8037           0 :         aChild == AnyKidsNeedBlockParent(parentFrame->PrincipalChildList().FirstChild()) &&
    8038           0 :         !AnyKidsNeedBlockParent(childFrame->GetNextSibling())) {
    8039           0 :       LAYOUT_PHASE_TEMP_EXIT();
    8040           0 :       RecreateFramesForContent(grandparentFrame->GetContent(),
    8041           0 :                                InsertionKind::Async);
    8042           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8043           0 :       return true;
    8044             :     }
    8045             : 
    8046             : #ifdef ACCESSIBILITY
    8047           9 :     if (nsAccessibilityService* accService = nsIPresShell::AccService()) {
    8048           0 :       accService->ContentRemoved(mPresShell, aChild);
    8049             :     }
    8050             : #endif
    8051             : 
    8052             :     // Examine the containing-block for the removed content and see if
    8053             :     // :first-letter style applies.
    8054           0 :     nsIFrame* inflowChild = childFrame;
    8055           0 :     if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    8056           0 :       inflowChild = childFrame->GetPlaceholderFrame();
    8057           0 :       NS_ASSERTION(inflowChild, "No placeholder for out-of-flow?");
    8058             :     }
    8059             :     nsContainerFrame* containingBlock =
    8060           9 :       GetFloatContainingBlock(inflowChild->GetParent());
    8061           9 :     bool haveFLS = containingBlock && HasFirstLetterStyle(containingBlock);
    8062           9 :     if (haveFLS) {
    8063             :       // Trap out to special routine that handles adjusting a blocks
    8064             :       // frame tree when first-letter style is present.
    8065             : #ifdef NOISY_FIRST_LETTER
    8066             :       printf("ContentRemoved: containingBlock=");
    8067             :       nsFrame::ListTag(stdout, containingBlock);
    8068             :       printf(" parentFrame=");
    8069             :       nsFrame::ListTag(stdout, parentFrame);
    8070             :       printf(" childFrame=");
    8071             :       nsFrame::ListTag(stdout, childFrame);
    8072             :       printf("\n");
    8073             : #endif
    8074             : 
    8075             :       // First update the containing blocks structure by removing the
    8076             :       // existing letter frames. This makes the subsequent logic
    8077             :       // simpler.
    8078           0 :       RemoveLetterFrames(mPresShell, containingBlock);
    8079             : 
    8080             :       // Recover childFrame and parentFrame
    8081           0 :       childFrame = aChild->GetPrimaryFrame();
    8082           0 :       if (!childFrame || childFrame->GetContent() != aChild) {
    8083             :         // XXXbz the GetContent() != aChild check is needed due to bug 135040.
    8084             :         // Remove it once that's fixed.
    8085             :         return false;
    8086             :       }
    8087           0 :       parentFrame = childFrame->GetParent();
    8088           0 :       parentType = parentFrame->Type();
    8089             : 
    8090             : #ifdef NOISY_FIRST_LETTER
    8091             :       printf("  ==> revised parentFrame=");
    8092             :       nsFrame::ListTag(stdout, parentFrame);
    8093             :       printf(" childFrame=");
    8094             :       nsFrame::ListTag(stdout, childFrame);
    8095             :       printf("\n");
    8096             : #endif
    8097             :     }
    8098             : 
    8099             : #ifdef DEBUG
    8100           9 :     if (gReallyNoisyContentUpdates) {
    8101           0 :       printf("nsCSSFrameConstructor::ContentRemoved: childFrame=");
    8102           0 :       nsFrame::ListTag(stdout, childFrame);
    8103           0 :       putchar('\n');
    8104           0 :       parentFrame->List(stdout, 0);
    8105             :     }
    8106             : #endif
    8107             : 
    8108             :     // Notify the parent frame that it should delete the frame
    8109           0 :     if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    8110           0 :       childFrame = childFrame->GetPlaceholderFrame();
    8111           0 :       NS_ASSERTION(childFrame, "Missing placeholder frame for out of flow.");
    8112           0 :       parentFrame = childFrame->GetParent();
    8113             :     }
    8114             : 
    8115           0 :     RemoveFrame(nsLayoutUtils::GetChildListNameFor(childFrame), childFrame);
    8116             : 
    8117             :     // NOTE(emilio): aChild could be dead here already if it is a ::before or
    8118             :     // ::after pseudo-element (since in that case it was owned by childFrame,
    8119             :     // which we just destroyed).
    8120             : 
    8121           9 :     if (isRoot) {
    8122           0 :       mRootElementFrame = nullptr;
    8123           0 :       mRootElementStyleFrame = nullptr;
    8124           0 :       mDocElementContainingBlock = nullptr;
    8125           0 :       mPageSequenceFrame = nullptr;
    8126           0 :       mHasRootAbsPosContainingBlock = false;
    8127             :     }
    8128             : 
    8129           9 :     if (haveFLS && mRootElementFrame) {
    8130           0 :       RecoverLetterFrames(containingBlock);
    8131             :     }
    8132             : 
    8133             :     // If we're just reconstructing frames for the element, then the
    8134             :     // following ContentInserted notification on the element will
    8135             :     // take care of fixing up any adjacent text nodes.  We don't need
    8136             :     // to do this if the table parent type of our parent type is not
    8137             :     // eTypeBlock, though, because in that case the whitespace isn't
    8138             :     // being suppressed due to us anyway.
    8139           9 :     if (aOldNextSibling && aFlags == REMOVE_CONTENT &&
    8140           0 :         GetParentType(parentType) == eTypeBlock) {
    8141           0 :       MOZ_ASSERT(aChild->GetParentNode(),
    8142             :                  "How did we have a sibling without a parent?");
    8143             :       // Adjacent whitespace-only text nodes might have been suppressed if
    8144             :       // this node does not have inline ends. Create frames for them now
    8145             :       // if necessary.
    8146             :       // Reframe any text node just before the node being removed, if there is
    8147             :       // one, and if it's not the last child or the first child. If a whitespace
    8148             :       // textframe was being suppressed and it's now the last child or first
    8149             :       // child then it can stay suppressed since the parent must be a block
    8150             :       // and hence it's adjacent to a block end.
    8151             :       // If aOldNextSibling is null, then the text node before the node being
    8152             :       // removed is the last node, and we don't need to worry about it.
    8153             :       //
    8154             :       // FIXME(emilio): This should probably use the lazy frame construction
    8155             :       // bits if possible instead of reframing it in place.
    8156           0 :       nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
    8157           0 :       if (prevSibling && prevSibling->GetPreviousSibling()) {
    8158           0 :         LAYOUT_PHASE_TEMP_EXIT();
    8159           0 :         ReframeTextIfNeeded(prevSibling);
    8160           0 :         LAYOUT_PHASE_TEMP_REENTER();
    8161             :       }
    8162             :       // Reframe any text node just after the node being removed, if there is
    8163             :       // one, and if it's not the last child or the first child.
    8164           0 :       if (aOldNextSibling->GetNextSibling() &&
    8165           0 :           aOldNextSibling->GetPreviousSibling()) {
    8166           0 :         LAYOUT_PHASE_TEMP_EXIT();
    8167           0 :         ReframeTextIfNeeded(aOldNextSibling);
    8168           0 :         LAYOUT_PHASE_TEMP_REENTER();
    8169             :       }
    8170             :     }
    8171             : 
    8172             : #ifdef DEBUG
    8173           9 :     if (gReallyNoisyContentUpdates && parentFrame) {
    8174           0 :       printf("nsCSSFrameConstructor::ContentRemoved: resulting frame model:\n");
    8175           0 :       parentFrame->List(stdout, 0);
    8176             :     }
    8177             : #endif
    8178             :   }
    8179             : 
    8180             :   return false;
    8181             : }
    8182             : 
    8183             : /**
    8184             :  * This method invalidates the canvas when frames are removed or added for a
    8185             :  * node that might have its background propagated to the canvas, i.e., a
    8186             :  * document root node or an HTML BODY which is a child of the root node.
    8187             :  *
    8188             :  * @param aFrame a frame for a content node about to be removed or a frame that
    8189             :  *               was just created for a content node that was inserted.
    8190             :  */
    8191             : static void
    8192          70 : InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node)
    8193             : {
    8194           0 :   MOZ_ASSERT(presShell->GetRootFrame(), "What happened here?");
    8195           0 :   MOZ_ASSERT(presShell->GetPresContext(), "Say what?");
    8196             : 
    8197             :   //  Note that both in ContentRemoved and ContentInserted the content node
    8198             :   //  will still have the right parent pointer, so looking at that is ok.
    8199             : 
    8200          70 :   nsIContent* parent = node->GetParent();
    8201          70 :   if (parent) {
    8202             :     // Has a parent; might not be what we want
    8203          51 :     nsIContent* grandParent = parent->GetParent();
    8204           0 :     if (grandParent) {
    8205             :       // Has a grandparent, so not what we want
    8206             :       return;
    8207             :     }
    8208             : 
    8209             :     // Check whether it's an HTML body
    8210          19 :     if (!node->IsHTMLElement(nsGkAtoms::body)) {
    8211             :       return;
    8212             :     }
    8213             :   }
    8214             : 
    8215             :   // At this point the node has no parent or it's an HTML <body> child of the
    8216             :   // root.  We might not need to invalidate in this case (eg we might be in
    8217             :   // XHTML or something), but chances are we want to.  Play it safe.
    8218             :   // Invalidate the viewport.
    8219             : 
    8220          38 :   nsIFrame* rootFrame = presShell->GetRootFrame();
    8221          19 :   rootFrame->InvalidateFrameSubtree();
    8222             : }
    8223             : 
    8224             : bool
    8225           0 : nsCSSFrameConstructor::EnsureFrameForTextNodeIsCreatedAfterFlush(
    8226             :   CharacterData* aContent)
    8227             : {
    8228           0 :   if (!aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
    8229             :     return false;
    8230             :   }
    8231             : 
    8232           0 :   if (mAlwaysCreateFramesForIgnorableWhitespace) {
    8233             :     return false;
    8234             :   }
    8235             : 
    8236             :   // Text frame may have been suppressed. Disable suppression and signal that a
    8237             :   // flush should be performed. We do this on a document-wide basis so that
    8238             :   // pages that repeatedly query metrics for collapsed-whitespace text nodes
    8239             :   // don't trigger pathological behavior.
    8240           0 :   mAlwaysCreateFramesForIgnorableWhitespace = true;
    8241           0 :   Element* root = mDocument->GetRootElement();
    8242           0 :   if (!root) {
    8243             :     return false;
    8244             :   }
    8245             : 
    8246           0 :   RestyleManager()->PostRestyleEvent(
    8247           0 :     root, nsRestyleHint(0), nsChangeHint_ReconstructFrame);
    8248           0 :   return true;
    8249             : }
    8250             : 
    8251             : void
    8252           0 : nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
    8253             :                                             const CharacterDataChangeInfo& aInfo)
    8254             : {
    8255           6 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    8256             : 
    8257           0 :   if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
    8258           4 :        !aContent->TextIsOnlyWhitespace()) ||
    8259           2 :       (aContent->HasFlag(NS_REFRAME_IF_WHITESPACE) &&
    8260           0 :        aContent->TextIsOnlyWhitespace())) {
    8261             : #ifdef DEBUG
    8262           0 :     nsIFrame* frame = aContent->GetPrimaryFrame();
    8263           0 :     NS_ASSERTION(!frame || !frame->IsGeneratedContentFrame(),
    8264             :                  "Bit should never be set on generated content");
    8265             : #endif
    8266           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8267           0 :     RecreateFramesForContent(aContent, InsertionKind::Async);
    8268           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8269           0 :     return;
    8270             :   }
    8271             : 
    8272             : 
    8273             :   // It's possible the frame whose content changed isn't inserted into the
    8274             :   // frame hierarchy yet, or that there is no frame that maps the content
    8275           2 :   if (nsIFrame* frame = aContent->GetPrimaryFrame()) {
    8276             : #if 0
    8277             :     NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
    8278             :        ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p",
    8279             :         aContent, ContentTag(aContent, 0),
    8280             :         aSubContent, frame));
    8281             : #endif
    8282             : 
    8283             :     // Special check for text content that is a child of a letter frame.  If
    8284             :     // this happens, we should remove the letter frame, do whatever we're
    8285             :     // planning to do with this notification, then put the letter frame back.
    8286             :     // Note that this is basically what RecreateFramesForContent ends up doing;
    8287             :     // the reason we dont' want to call that here is that our text content
    8288             :     // could be native anonymous, in which case RecreateFramesForContent would
    8289             :     // completely barf on it.  And recreating the non-anonymous ancestor would
    8290             :     // just lead us to come back into this notification (e.g. if quotes or
    8291             :     // counters are involved), leading to a loop.
    8292           0 :     nsContainerFrame* block = GetFloatContainingBlock(frame);
    8293           0 :     bool haveFirstLetterStyle = false;
    8294           0 :     if (block) {
    8295             :       // See if the block has first-letter style applied to it.
    8296           0 :       haveFirstLetterStyle = HasFirstLetterStyle(block);
    8297           0 :       if (haveFirstLetterStyle) {
    8298           0 :         RemoveLetterFrames(mPresShell, block);
    8299             :         // Reget |frame|, since we might have killed it.
    8300             :         // Do we really need to call CharacterDataChanged in this case, though?
    8301           0 :         frame = aContent->GetPrimaryFrame();
    8302           0 :         NS_ASSERTION(frame, "Should have frame here!");
    8303             :       }
    8304             :     }
    8305             : 
    8306             :     // Notify the first frame that maps the content. It will generate a reflow
    8307             :     // command
    8308           0 :     frame->CharacterDataChanged(aInfo);
    8309             : 
    8310           0 :     if (haveFirstLetterStyle) {
    8311           0 :       RecoverLetterFrames(block);
    8312             :     }
    8313             :   }
    8314             : }
    8315             : 
    8316             : void
    8317           0 : nsCSSFrameConstructor::RecalcQuotesAndCounters()
    8318             : {
    8319         159 :   nsAutoScriptBlocker scriptBlocker;
    8320             : 
    8321           0 :   if (mQuotesDirty) {
    8322           0 :     mQuotesDirty = false;
    8323           0 :     mQuoteList.RecalcAll();
    8324             :   }
    8325             : 
    8326           0 :   if (mCountersDirty) {
    8327           0 :     mCountersDirty = false;
    8328           0 :     mCounterManager.RecalcAll();
    8329             :   }
    8330             : 
    8331          53 :   NS_ASSERTION(!mQuotesDirty, "Quotes updates will be lost");
    8332           0 :   NS_ASSERTION(!mCountersDirty, "Counter updates will be lost");
    8333           0 : }
    8334             : 
    8335             : void
    8336           0 : nsCSSFrameConstructor::NotifyCounterStylesAreDirty()
    8337             : {
    8338           0 :   mCounterManager.SetAllDirty();
    8339           0 :   CountersDirty();
    8340           0 : }
    8341             : 
    8342             : void
    8343           0 : nsCSSFrameConstructor::WillDestroyFrameTree()
    8344             : {
    8345             : #if defined(DEBUG_dbaron_off)
    8346             :   mCounterManager.Dump();
    8347             : #endif
    8348             : 
    8349           0 :   mIsDestroyingFrameTree = true;
    8350             : 
    8351             :   // Prevent frame tree destruction from being O(N^2)
    8352           8 :   mQuoteList.Clear();
    8353          16 :   mCounterManager.Clear();
    8354           8 :   nsFrameManager::Destroy();
    8355           8 : }
    8356             : 
    8357             : //STATIC
    8358             : 
    8359             : // XXXbz I'd really like this method to go away. Once we have inline-block and
    8360             : // I can just use that for sized broken images, that can happen, maybe.
    8361             : void
    8362           0 : nsCSSFrameConstructor::GetAlternateTextFor(Element* aElement,
    8363             :                                            nsAtom* aTag,
    8364             :                                            nsAString& aAltText)
    8365             : {
    8366             :   // The "alt" attribute specifies alternate text that is rendered
    8367             :   // when the image can not be displayed.
    8368           0 :   if (aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aAltText)) {
    8369             :     return;
    8370             :   }
    8371             : 
    8372           0 :   if (nsGkAtoms::input == aTag) {
    8373             :     // If there's no "alt" attribute, and aContent is an input element, then use
    8374             :     // the value of the "value" attribute
    8375           0 :     if (aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aAltText)) {
    8376             :       return;
    8377             :     }
    8378             : 
    8379             :     // If there's no "value" attribute either, then use the localized string for
    8380             :     // "Submit" as the alternate text.
    8381             :     nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
    8382           0 :                                        "Submit", aAltText);
    8383             :   }
    8384             : }
    8385             : 
    8386             : nsIFrame*
    8387           0 : nsCSSFrameConstructor::CreateContinuingOuterTableFrame(nsIPresShell*     aPresShell,
    8388             :                                                        nsPresContext*    aPresContext,
    8389             :                                                        nsIFrame*         aFrame,
    8390             :                                                        nsContainerFrame* aParentFrame,
    8391             :                                                        nsIContent*       aContent,
    8392             :                                                        ComputedStyle*   aComputedStyle)
    8393             : {
    8394           0 :   nsTableWrapperFrame* newFrame = NS_NewTableWrapperFrame(aPresShell, aComputedStyle);
    8395             : 
    8396           0 :   newFrame->Init(aContent, aParentFrame, aFrame);
    8397             : 
    8398             :   // Create a continuing inner table frame, and if there's a caption then
    8399             :   // replicate the caption
    8400           0 :   nsFrameItems  newChildFrames;
    8401             : 
    8402           0 :   nsIFrame* childFrame = aFrame->PrincipalChildList().FirstChild();
    8403           0 :   if (childFrame) {
    8404             :     nsIFrame* continuingTableFrame =
    8405           0 :       CreateContinuingFrame(aPresContext, childFrame, newFrame);
    8406           0 :     newChildFrames.AddChild(continuingTableFrame);
    8407             : 
    8408           0 :     NS_ASSERTION(!childFrame->GetNextSibling(),"there can be only one inner table frame");
    8409             :   }
    8410             : 
    8411             :   // Set the table wrapper's initial child list
    8412           0 :   newFrame->SetInitialChildList(kPrincipalList, newChildFrames);
    8413             : 
    8414           0 :   return newFrame;
    8415             : }
    8416             : 
    8417             : nsIFrame*
    8418           0 : nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell*     aPresShell,
    8419             :                                                   nsIFrame*         aFrame,
    8420             :                                                   nsContainerFrame* aParentFrame,
    8421             :                                                   nsIContent*       aContent,
    8422             :                                                   ComputedStyle*   aComputedStyle)
    8423             : {
    8424           0 :   nsTableFrame* newFrame = NS_NewTableFrame(aPresShell, aComputedStyle);
    8425             : 
    8426           0 :   newFrame->Init(aContent, aParentFrame, aFrame);
    8427             : 
    8428             :   // Replicate any header/footer frames
    8429           0 :   nsFrameItems  childFrames;
    8430           0 :   for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
    8431             :     // See if it's a header/footer, possibly wrapped in a scroll frame.
    8432             :     nsTableRowGroupFrame* rowGroupFrame =
    8433           0 :       static_cast<nsTableRowGroupFrame*>(childFrame);
    8434             :     // If the row group was continued, then don't replicate it.
    8435           0 :     nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
    8436           0 :     if (rgNextInFlow) {
    8437           0 :       rowGroupFrame->SetRepeatable(false);
    8438             :     }
    8439           0 :     else if (rowGroupFrame->IsRepeatable()) {
    8440             :       // Replicate the header/footer frame.
    8441             :       nsTableRowGroupFrame*   headerFooterFrame;
    8442           0 :       nsFrameItems            childItems;
    8443             : 
    8444             :       nsFrameConstructorState state(mPresShell,
    8445             :                                     GetAbsoluteContainingBlock(newFrame, FIXED_POS),
    8446             :                                     GetAbsoluteContainingBlock(newFrame, ABS_POS),
    8447           0 :                                     nullptr);
    8448           0 :       state.mCreatingExtraFrames = true;
    8449             : 
    8450           0 :       ComputedStyle* const headerFooterComputedStyle = rowGroupFrame->Style();
    8451             :       headerFooterFrame = static_cast<nsTableRowGroupFrame*>
    8452           0 :                                      (NS_NewTableRowGroupFrame(aPresShell, headerFooterComputedStyle));
    8453             : 
    8454           0 :       nsIContent* headerFooter = rowGroupFrame->GetContent();
    8455           0 :       headerFooterFrame->Init(headerFooter, newFrame, nullptr);
    8456             : 
    8457           0 :       nsFrameConstructorSaveState absoluteSaveState;
    8458           0 :       MakeTablePartAbsoluteContainingBlockIfNeeded(state,
    8459             :                                                    headerFooterComputedStyle->StyleDisplay(),
    8460             :                                                    absoluteSaveState,
    8461           0 :                                                    headerFooterFrame);
    8462             : 
    8463           0 :       ProcessChildren(state, headerFooter, rowGroupFrame->Style(),
    8464             :                       headerFooterFrame, true, childItems, false,
    8465           0 :                       nullptr);
    8466           0 :       NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
    8467           0 :       headerFooterFrame->SetInitialChildList(kPrincipalList, childItems);
    8468           0 :       headerFooterFrame->SetRepeatable(true);
    8469             : 
    8470             :       // Table specific initialization
    8471           0 :       headerFooterFrame->InitRepeatedFrame(rowGroupFrame);
    8472             : 
    8473             :       // XXX Deal with absolute and fixed frames...
    8474           0 :       childFrames.AddChild(headerFooterFrame);
    8475             :     }
    8476             :   }
    8477             : 
    8478             :   // Set the table frame's initial child list
    8479           0 :   newFrame->SetInitialChildList(kPrincipalList, childFrames);
    8480             : 
    8481           0 :   return newFrame;
    8482             : }
    8483             : 
    8484             : nsIFrame*
    8485           0 : nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext*    aPresContext,
    8486             :                                              nsIFrame*         aFrame,
    8487             :                                              nsContainerFrame* aParentFrame,
    8488             :                                              bool              aIsFluid)
    8489             : {
    8490           0 :   nsIPresShell*              shell = aPresContext->PresShell();
    8491           0 :   ComputedStyle*             computedStyle = aFrame->Style();
    8492           0 :   nsIFrame*                  newFrame = nullptr;
    8493           0 :   nsIFrame*                  nextContinuation = aFrame->GetNextContinuation();
    8494           0 :   nsIFrame*                  nextInFlow = aFrame->GetNextInFlow();
    8495             : 
    8496             :   // Use the frame type to determine what type of frame to create
    8497           0 :   LayoutFrameType frameType = aFrame->Type();
    8498           0 :   nsIContent* content = aFrame->GetContent();
    8499             : 
    8500           0 :   NS_ASSERTION(aFrame->GetSplittableType() != NS_FRAME_NOT_SPLITTABLE,
    8501             :                "why CreateContinuingFrame for a non-splittable frame?");
    8502             : 
    8503           0 :   if (LayoutFrameType::Text == frameType) {
    8504           0 :     newFrame = NS_NewContinuingTextFrame(shell, computedStyle);
    8505           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8506           0 :   } else if (LayoutFrameType::Inline == frameType) {
    8507           0 :     newFrame = NS_NewInlineFrame(shell, computedStyle);
    8508           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8509           0 :   } else if (LayoutFrameType::Block == frameType) {
    8510           0 :     MOZ_ASSERT(!aFrame->IsTableCaption(),
    8511             :                "no support for fragmenting table captions yet");
    8512           0 :     newFrame = NS_NewBlockFrame(shell, computedStyle);
    8513           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8514             : #ifdef MOZ_XUL
    8515           0 :   } else if (LayoutFrameType::XULLabel == frameType) {
    8516           0 :     newFrame = NS_NewXULLabelFrame(shell, computedStyle);
    8517           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8518             : #endif
    8519           0 :   } else if (LayoutFrameType::ColumnSet == frameType) {
    8520           0 :     MOZ_ASSERT(!aFrame->IsTableCaption(),
    8521             :                "no support for fragmenting table captions yet");
    8522           0 :     newFrame = NS_NewColumnSetFrame(shell, computedStyle, nsFrameState(0));
    8523           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8524           0 :   } else if (LayoutFrameType::Page == frameType) {
    8525             :     nsContainerFrame* canvasFrame;
    8526           0 :     newFrame = ConstructPageFrame(shell, aParentFrame, aFrame, canvasFrame);
    8527           0 :   } else if (LayoutFrameType::TableWrapper == frameType) {
    8528             :     newFrame =
    8529             :       CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
    8530           0 :                                       content, computedStyle);
    8531             : 
    8532           0 :   } else if (LayoutFrameType::Table == frameType) {
    8533             :     newFrame =
    8534             :       CreateContinuingTableFrame(shell, aFrame, aParentFrame,
    8535           0 :                                  content, computedStyle);
    8536             : 
    8537           0 :   } else if (LayoutFrameType::TableRowGroup == frameType) {
    8538           0 :     newFrame = NS_NewTableRowGroupFrame(shell, computedStyle);
    8539           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8540           0 :     if (newFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
    8541           0 :       nsTableFrame::RegisterPositionedTablePart(newFrame);
    8542             :     }
    8543           0 :   } else if (LayoutFrameType::TableRow == frameType) {
    8544           0 :     nsTableRowFrame* rowFrame = NS_NewTableRowFrame(shell, computedStyle);
    8545             : 
    8546           0 :     rowFrame->Init(content, aParentFrame, aFrame);
    8547           0 :     if (rowFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
    8548           0 :       nsTableFrame::RegisterPositionedTablePart(rowFrame);
    8549             :     }
    8550             : 
    8551             :     // Create a continuing frame for each table cell frame
    8552           0 :     nsFrameItems  newChildList;
    8553           0 :     nsIFrame* cellFrame = aFrame->PrincipalChildList().FirstChild();
    8554           0 :     while (cellFrame) {
    8555             :       // See if it's a table cell frame
    8556           0 :       if (IS_TABLE_CELL(cellFrame->Type())) {
    8557             :         nsIFrame* continuingCellFrame =
    8558           0 :           CreateContinuingFrame(aPresContext, cellFrame, rowFrame);
    8559           0 :         newChildList.AddChild(continuingCellFrame);
    8560             :       }
    8561           0 :       cellFrame = cellFrame->GetNextSibling();
    8562             :     }
    8563             : 
    8564           0 :     rowFrame->SetInitialChildList(kPrincipalList, newChildList);
    8565           0 :     newFrame = rowFrame;
    8566             : 
    8567           0 :   } else if (IS_TABLE_CELL(frameType)) {
    8568             :     // Warning: If you change this and add a wrapper frame around table cell
    8569             :     // frames, make sure Bug 368554 doesn't regress!
    8570             :     // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
    8571             :     nsTableFrame* tableFrame =
    8572           0 :       static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
    8573             :     nsTableCellFrame* cellFrame =
    8574           0 :       NS_NewTableCellFrame(shell, computedStyle, tableFrame);
    8575             : 
    8576           0 :     cellFrame->Init(content, aParentFrame, aFrame);
    8577           0 :     if (cellFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
    8578           0 :       nsTableFrame::RegisterPositionedTablePart(cellFrame);
    8579             :     }
    8580             : 
    8581             :     // Create a continuing area frame
    8582           0 :     nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
    8583             :     nsIFrame* continuingBlockFrame =
    8584             :       CreateContinuingFrame(aPresContext, blockFrame,
    8585           0 :                             static_cast<nsContainerFrame*>(cellFrame));
    8586             : 
    8587           0 :     SetInitialSingleChild(cellFrame, continuingBlockFrame);
    8588           0 :     newFrame = cellFrame;
    8589           0 :   } else if (LayoutFrameType::Line == frameType) {
    8590           0 :     newFrame = NS_NewFirstLineFrame(shell, computedStyle);
    8591           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8592           0 :   } else if (LayoutFrameType::Letter == frameType) {
    8593           0 :     newFrame = NS_NewFirstLetterFrame(shell, computedStyle);
    8594           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8595           0 :   } else if (LayoutFrameType::Image == frameType) {
    8596           0 :     newFrame = NS_NewImageFrame(shell, computedStyle);
    8597           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8598           0 :   } else if (LayoutFrameType::ImageControl == frameType) {
    8599           0 :     newFrame = NS_NewImageControlFrame(shell, computedStyle);
    8600           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8601           0 :   } else if (LayoutFrameType::Placeholder == frameType) {
    8602             :     // create a continuing out of flow frame
    8603           0 :     nsIFrame* oofFrame = nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
    8604             :     nsIFrame* oofContFrame =
    8605           0 :       CreateContinuingFrame(aPresContext, oofFrame, aParentFrame);
    8606             :     newFrame =
    8607           0 :       CreatePlaceholderFrameFor(shell, content, oofContFrame,
    8608             :                                 aParentFrame, aFrame,
    8609           0 :                                 aFrame->GetStateBits() & PLACEHOLDER_TYPE_MASK);
    8610           0 :   } else if (LayoutFrameType::FieldSet == frameType) {
    8611           0 :     nsContainerFrame* fieldset = NS_NewFieldSetFrame(shell, computedStyle);
    8612             : 
    8613           0 :     fieldset->Init(content, aParentFrame, aFrame);
    8614             : 
    8615             :     // Create a continuing area frame
    8616             :     // XXXbz we really shouldn't have to do this by hand!
    8617           0 :     nsContainerFrame* blockFrame = GetFieldSetBlockFrame(aFrame);
    8618           0 :     if (blockFrame) {
    8619             :       nsIFrame* continuingBlockFrame =
    8620           0 :         CreateContinuingFrame(aPresContext, blockFrame, fieldset);
    8621             :       // Set the fieldset's initial child list
    8622           0 :       SetInitialSingleChild(fieldset, continuingBlockFrame);
    8623             :     } else {
    8624           0 :       MOZ_ASSERT(aFrame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
    8625             :                  "FieldSet block may only be null for overflow containers");
    8626             :     }
    8627             :     newFrame = fieldset;
    8628           0 :   } else if (LayoutFrameType::Legend == frameType) {
    8629           0 :     newFrame = NS_NewLegendFrame(shell, computedStyle);
    8630           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8631           0 :   } else if (LayoutFrameType::FlexContainer == frameType) {
    8632           0 :     newFrame = NS_NewFlexContainerFrame(shell, computedStyle);
    8633           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8634           0 :   } else if (LayoutFrameType::GridContainer == frameType) {
    8635           0 :     newFrame = NS_NewGridContainerFrame(shell, computedStyle);
    8636           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8637           0 :   } else if (LayoutFrameType::Ruby == frameType) {
    8638           0 :     newFrame = NS_NewRubyFrame(shell, computedStyle);
    8639           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8640           0 :   } else if (LayoutFrameType::RubyBaseContainer == frameType) {
    8641           0 :     newFrame = NS_NewRubyBaseContainerFrame(shell, computedStyle);
    8642           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8643           0 :   } else if (LayoutFrameType::RubyTextContainer == frameType) {
    8644           0 :     newFrame = NS_NewRubyTextContainerFrame(shell, computedStyle);
    8645           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8646           0 :   } else if (LayoutFrameType::Details == frameType) {
    8647           0 :     newFrame = NS_NewDetailsFrame(shell, computedStyle);
    8648           0 :     newFrame->Init(content, aParentFrame, aFrame);
    8649             :   } else {
    8650           0 :     MOZ_CRASH("unexpected frame type");
    8651             :   }
    8652             : 
    8653             :   // Init() set newFrame to be a fluid continuation of aFrame.
    8654             :   // If we want a non-fluid continuation, we need to call SetPrevContinuation()
    8655             :   // to reset NS_FRAME_IS_FLUID_CONTINUATION.
    8656           0 :   if (!aIsFluid) {
    8657           0 :     newFrame->SetPrevContinuation(aFrame);
    8658             :   }
    8659             : 
    8660             :   // A continuation of generated content is also generated content
    8661           0 :   if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
    8662             :     newFrame->AddStateBits(NS_FRAME_GENERATED_CONTENT);
    8663             :   }
    8664             : 
    8665             :   // A continuation of nsIAnonymousContentCreator content is also
    8666             :   // nsIAnonymousContentCreator created content
    8667           0 :   if (aFrame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
    8668             :     newFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
    8669             :   }
    8670             : 
    8671             :   // A continuation of an out-of-flow is also an out-of-flow
    8672           0 :   if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    8673             :     newFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
    8674             :   }
    8675             : 
    8676           0 :   if (nextInFlow) {
    8677           0 :     nextInFlow->SetPrevInFlow(newFrame);
    8678           0 :     newFrame->SetNextInFlow(nextInFlow);
    8679           0 :   } else if (nextContinuation) {
    8680           0 :     nextContinuation->SetPrevContinuation(newFrame);
    8681           0 :     newFrame->SetNextContinuation(nextContinuation);
    8682             :   }
    8683             : 
    8684           0 :   MOZ_ASSERT(!newFrame->GetNextSibling(), "unexpected sibling");
    8685           0 :   return newFrame;
    8686             : }
    8687             : 
    8688             : nsresult
    8689           0 : nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
    8690             : {
    8691             :   // Now deal with fixed-pos things....  They should appear on all pages,
    8692             :   // so we want to move over the placeholders when processing the child
    8693             :   // of the pageContentFrame.
    8694             : 
    8695           0 :   nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
    8696           0 :   if (!prevPageContentFrame) {
    8697             :     return NS_OK;
    8698             :   }
    8699             :   nsContainerFrame* canvasFrame =
    8700           0 :     do_QueryFrame(aParentFrame->PrincipalChildList().FirstChild());
    8701           0 :   nsIFrame* prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
    8702           0 :   if (!canvasFrame || !prevCanvasFrame) {
    8703             :     // document's root element frame missing
    8704             :     return NS_ERROR_UNEXPECTED;
    8705             :   }
    8706             : 
    8707           0 :   nsFrameItems fixedPlaceholders;
    8708           0 :   nsIFrame* firstFixed = prevPageContentFrame->GetChildList(nsIFrame::kFixedList).FirstChild();
    8709           0 :   if (!firstFixed) {
    8710             :     return NS_OK;
    8711             :   }
    8712             : 
    8713             :   // Don't allow abs-pos descendants of the fixed content to escape the content.
    8714             :   // This should not normally be possible (because fixed-pos elements should
    8715             :   // be absolute containers) but fixed-pos tables currently aren't abs-pos
    8716             :   // containers.
    8717             :   nsFrameConstructorState state(mPresShell,
    8718             :                                 aParentFrame,
    8719             :                                 nullptr,
    8720           0 :                                 mRootElementFrame);
    8721           0 :   state.mCreatingExtraFrames = true;
    8722             : 
    8723             :   // We can't use an ancestor filter here, because we're not going to
    8724             :   // be usefully recurring down the tree.  This means that other
    8725             :   // places in frame construction can't assume a filter is
    8726             :   // initialized!
    8727             : 
    8728             :   // Iterate across fixed frames and replicate each whose placeholder is a
    8729             :   // descendant of aFrame. (We don't want to explicitly copy placeholders that
    8730             :   // are within fixed frames, because that would cause duplicates on the new
    8731             :   // page - bug 389619)
    8732           0 :   for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
    8733           0 :     nsIFrame* prevPlaceholder = fixed->GetPlaceholderFrame();
    8734           0 :     if (prevPlaceholder &&
    8735           0 :         nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) {
    8736             :       // We want to use the same style as the primary style frame for
    8737             :       // our content
    8738           0 :       nsIContent* content = fixed->GetContent();
    8739             :       ComputedStyle* computedStyle =
    8740           0 :         nsLayoutUtils::GetStyleFrame(content)->Style();
    8741           0 :       AutoFrameConstructionItemList items(this);
    8742             :       AddFrameConstructionItemsInternal(state, content, canvasFrame,
    8743             :                                         true,
    8744             :                                         computedStyle,
    8745             :                                         ITEM_ALLOW_XBL_BASE |
    8746             :                                           ITEM_ALLOW_PAGE_BREAK,
    8747           0 :                                         nullptr, items);
    8748             :       ConstructFramesFromItemList(state, items, canvasFrame,
    8749             :                                   /* aParentIsWrapperAnonBox = */ false,
    8750           0 :                                   fixedPlaceholders);
    8751             :     }
    8752             :   }
    8753             : 
    8754             :   // Add the placeholders to our primary child list.
    8755             :   // XXXbz this is a little screwed up, since the fixed frames will have
    8756             :   // broken auto-positioning. Oh, well.
    8757           0 :   NS_ASSERTION(!canvasFrame->PrincipalChildList().FirstChild(),
    8758             :                "leaking frames; doc root continuation must be empty");
    8759           0 :   canvasFrame->SetInitialChildList(kPrincipalList, fixedPlaceholders);
    8760             :   return NS_OK;
    8761             : }
    8762             : 
    8763             : nsCSSFrameConstructor::InsertionPoint
    8764          90 : nsCSSFrameConstructor::GetInsertionPoint(nsIContent* aChild)
    8765             : {
    8766          90 :   MOZ_ASSERT(aChild);
    8767          90 :   nsIContent* insertionElement = aChild->GetFlattenedTreeParent();
    8768           0 :   if (!insertionElement) {
    8769             :     // The element doesn't belong in the flattened tree, and thus we don't want
    8770             :     // to render it.
    8771           0 :     return { };
    8772             :   }
    8773             : 
    8774           0 :   return { GetContentInsertionFrameFor(insertionElement), insertionElement };
    8775             : }
    8776             : 
    8777             : // Capture state for the frame tree rooted at the frame associated with the
    8778             : // content object, aContent
    8779             : void
    8780           0 : nsCSSFrameConstructor::CaptureStateForFramesOf(nsIContent* aContent,
    8781             :                                                nsILayoutHistoryState* aHistoryState)
    8782             : {
    8783           7 :   if (!aHistoryState) {
    8784             :     return;
    8785             :   }
    8786           0 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    8787           7 :   if (frame == mRootElementFrame) {
    8788           0 :     frame = mRootElementFrame ?
    8789             :       GetAbsoluteContainingBlock(mRootElementFrame, FIXED_POS) :
    8790           0 :       GetRootFrame();
    8791             :   }
    8792          21 :   for ( ; frame;
    8793             :         frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
    8794           0 :     CaptureFrameState(frame, aHistoryState);
    8795             :   }
    8796             : }
    8797             : 
    8798             : 
    8799             : static bool
    8800          12 : IsWhitespaceFrame(nsIFrame* aFrame)
    8801             : {
    8802          12 :   MOZ_ASSERT(aFrame, "invalid argument");
    8803           0 :   return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
    8804             : }
    8805             : 
    8806             : static nsIFrame*
    8807           0 : FindFirstNonWhitespaceChild(nsIFrame* aParentFrame)
    8808             : {
    8809           0 :   nsIFrame* f = aParentFrame->PrincipalChildList().FirstChild();
    8810           0 :   while (f && IsWhitespaceFrame(f)) {
    8811           0 :     f = f->GetNextSibling();
    8812             :   }
    8813           0 :   return f;
    8814             : }
    8815             : 
    8816             : static nsIFrame*
    8817           0 : FindNextNonWhitespaceSibling(nsIFrame* aFrame)
    8818             : {
    8819          16 :   nsIFrame* f = aFrame;
    8820          16 :   do {
    8821           0 :     f = f->GetNextSibling();
    8822          16 :   } while (f && IsWhitespaceFrame(f));
    8823           0 :   return f;
    8824             : }
    8825             : 
    8826             : static nsIFrame*
    8827           0 : FindPreviousNonWhitespaceSibling(nsIFrame* aFrame)
    8828             : {
    8829           0 :   nsIFrame* f = aFrame;
    8830           0 :   do {
    8831           0 :     f = f->GetPrevSibling();
    8832           0 :   } while (f && IsWhitespaceFrame(f));
    8833           0 :   return f;
    8834             : }
    8835             : 
    8836             : bool
    8837          16 : nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame)
    8838             : {
    8839          16 :   MOZ_ASSERT(aFrame, "Must have a frame");
    8840          16 :   MOZ_ASSERT(aFrame->GetParent(), "Frame shouldn't be root");
    8841          16 :   MOZ_ASSERT(aFrame == aFrame->FirstContinuation(),
    8842             :              "aFrame not the result of GetPrimaryFrame()?");
    8843             : 
    8844           1 :   if (IsFramePartOfIBSplit(aFrame)) {
    8845             :     // The removal functions can't handle removal of an {ib} split directly; we
    8846             :     // need to rebuild the containing block.
    8847             : #ifdef DEBUG
    8848           0 :     if (gNoisyContentUpdates) {
    8849             :       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    8850           0 :              "frame=");
    8851           0 :       nsFrame::ListTag(stdout, aFrame);
    8852             :       printf(" is ib-split\n");
    8853             :     }
    8854             : #endif
    8855             : 
    8856           0 :     ReframeContainingBlock(aFrame);
    8857           0 :     return true;
    8858             :   }
    8859             : 
    8860          16 :   nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame();
    8861          16 :   if (insertionFrame && insertionFrame->IsLegendFrame() &&
    8862           0 :       aFrame->GetParent()->IsFieldSetFrame()) {
    8863           0 :     RecreateFramesForContent(aFrame->GetParent()->GetContent(),
    8864           0 :                              InsertionKind::Async);
    8865           0 :     return true;
    8866             :   }
    8867             : 
    8868             :   nsIFrame* inFlowFrame =
    8869          32 :     (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) ?
    8870           0 :       aFrame->GetPlaceholderFrame() : aFrame;
    8871          16 :   MOZ_ASSERT(inFlowFrame, "How did that happen?");
    8872           0 :   MOZ_ASSERT(inFlowFrame == inFlowFrame->FirstContinuation(),
    8873             :              "placeholder for primary frame has previous continuations?");
    8874          16 :   nsIFrame* parent = inFlowFrame->GetParent();
    8875             : 
    8876          16 :   if (parent && parent->IsDetailsFrame()) {
    8877             :     HTMLSummaryElement* summary =
    8878           0 :       HTMLSummaryElement::FromNode(aFrame->GetContent());
    8879           0 :     DetailsFrame* detailsFrame = static_cast<DetailsFrame*>(parent);
    8880             : 
    8881             :     // Unlike adding summary element cases, we need to check children of the
    8882             :     // parent details frame since at this moment the summary element has been
    8883             :     // already removed from the parent details element's child list.
    8884           0 :     if (summary && detailsFrame->HasMainSummaryFrame(aFrame)) {
    8885             :       // When removing a summary, we should reframe the parent details frame to
    8886             :       // ensure that another summary is used or the default summary is
    8887             :       // generated.
    8888           0 :       RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
    8889           0 :       return true;
    8890             :     }
    8891             :   }
    8892             : 
    8893             :   // Now check for possibly needing to reconstruct due to a pseudo parent
    8894             :   // For the case of ruby pseudo parent, effectively, only pseudo rb/rt frame
    8895             :   // need to be checked here, since all other types of parent will be catched
    8896             :   // by "Check ruby containers" section below.
    8897           0 :   if (IsTableOrRubyPseudo(parent)) {
    8898           0 :     if (FindFirstNonWhitespaceChild(parent) == inFlowFrame ||
    8899           0 :         !FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation()) ||
    8900             :         // If it is a whitespace, and is the only child of the parent, the
    8901             :         // pseudo parent was created for the space, and should now be removed.
    8902           0 :         (IsWhitespaceFrame(aFrame) &&
    8903           0 :          parent->PrincipalChildList().OnlyChild()) ||
    8904             :         // If we're a table-column-group, then the OnlyChild check above is
    8905             :         // not going to catch cases when we're the first child.
    8906           0 :         (inFlowFrame->IsTableColGroupFrame() &&
    8907           0 :          parent->GetChildList(nsIFrame::kColGroupList).FirstChild() == inFlowFrame) ||
    8908             :         // Similar if we're a table-caption.
    8909           0 :         (inFlowFrame->IsTableCaption() &&
    8910           0 :          parent->GetChildList(nsIFrame::kCaptionList).FirstChild() == inFlowFrame)) {
    8911           0 :       RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
    8912           0 :       return true;
    8913             :     }
    8914             :   }
    8915             : 
    8916             :   // Might need to reconstruct things if this frame's nextSibling is a table
    8917             :   // or ruby pseudo, since removal of this frame might mean that this pseudo
    8918             :   // needs to get merged with the frame's prevSibling if that's also a table
    8919             :   // or ruby pseudo.
    8920             :   nsIFrame* nextSibling =
    8921           0 :     FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation());
    8922           0 :   NS_ASSERTION(!IsTableOrRubyPseudo(inFlowFrame), "Shouldn't happen here");
    8923             :   // Effectively, for the ruby pseudo sibling case, only pseudo <ruby> frame
    8924             :   // need to be checked here, since all other types of such frames will have
    8925             :   // a ruby container parent, and be catched by "Check ruby containers" below.
    8926           1 :   if (nextSibling && IsTableOrRubyPseudo(nextSibling)) {
    8927           0 :     nsIFrame* prevSibling = FindPreviousNonWhitespaceSibling(inFlowFrame);
    8928           0 :     if (prevSibling && IsTableOrRubyPseudo(prevSibling)) {
    8929             : #ifdef DEBUG
    8930           0 :       if (gNoisyContentUpdates) {
    8931             :         printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    8932           0 :                "frame=");
    8933           0 :         nsFrame::ListTag(stdout, aFrame);
    8934             :         printf(" has a table pseudo next sibling of different type and a "
    8935             :                "table pseudo prevsibling\n");
    8936             :       }
    8937             : #endif
    8938             :       // Good enough to recreate frames for aFrame's parent's content; even if
    8939             :       // aFrame's parent is a pseudo, that'll be the right content node.
    8940           0 :       RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
    8941           0 :       return true;
    8942             :     }
    8943             :   }
    8944             : 
    8945             :   // Check ruby containers
    8946          16 :   LayoutFrameType parentType = parent->Type();
    8947          32 :   if (parentType == LayoutFrameType::Ruby ||
    8948          16 :       RubyUtils::IsRubyContainerBox(parentType)) {
    8949             :     // In ruby containers, pseudo frames may be created from
    8950             :     // whitespaces or even nothing. There are two cases we actually
    8951             :     // need to handle here, but hard to check exactly:
    8952             :     // 1. Status of spaces beside the frame may vary, and related
    8953             :     //    frames may be constructed or destroyed accordingly.
    8954             :     // 2. The type of the first child of a ruby frame determines
    8955             :     //    whether a pseudo ruby base container should exist.
    8956           0 :     RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
    8957           0 :     return true;
    8958             :   }
    8959             : 
    8960             :   // Might need to reconstruct things if the removed frame's nextSibling is an
    8961             :   // anonymous flex item.  The removed frame might've been what divided two
    8962             :   // runs of inline content into two anonymous flex items, which would now
    8963             :   // need to be merged.
    8964             :   // NOTE: It's fine that we've advanced nextSibling past whitespace (up above);
    8965             :   // we're only interested in anonymous flex items here, and those can never
    8966             :   // be adjacent to whitespace, since they absorb contiguous runs of inline
    8967             :   // non-replaced content (including whitespace).
    8968           1 :   if (nextSibling && IsAnonymousFlexOrGridItem(nextSibling)) {
    8969           0 :     AssertAnonymousFlexOrGridItemParent(nextSibling, parent);
    8970             : #ifdef DEBUG
    8971           0 :     if (gNoisyContentUpdates) {
    8972             :       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    8973           0 :              "frame=");
    8974           0 :       nsFrame::ListTag(stdout, aFrame);
    8975             :       printf(" has an anonymous flex item as its next sibling\n");
    8976             :     }
    8977             : #endif // DEBUG
    8978             :     // Recreate frames for the flex container (the removed frame's parent)
    8979           0 :     RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
    8980           0 :     return true;
    8981             :   }
    8982             : 
    8983             :   // Might need to reconstruct things if the removed frame's nextSibling is
    8984             :   // null and its parent is an anonymous flex item. (This might be the last
    8985             :   // remaining child of that anonymous flex item, which can then go away.)
    8986           1 :   if (!nextSibling && IsAnonymousFlexOrGridItem(parent)) {
    8987           0 :     AssertAnonymousFlexOrGridItemParent(parent, parent->GetParent());
    8988             : #ifdef DEBUG
    8989           0 :     if (gNoisyContentUpdates) {
    8990             :       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    8991           0 :              "frame=");
    8992           0 :       nsFrame::ListTag(stdout, aFrame);
    8993             :       printf(" has an anonymous flex item as its parent\n");
    8994             :     }
    8995             : #endif // DEBUG
    8996             :     // Recreate frames for the flex container (the removed frame's grandparent)
    8997           0 :     RecreateFramesForContent(parent->GetParent()->GetContent(),
    8998           0 :                              InsertionKind::Async);
    8999           0 :     return true;
    9000             :   }
    9001             : 
    9002             : #ifdef MOZ_XUL
    9003          16 :   if (aFrame->IsPopupSetFrame()) {
    9004           0 :     nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
    9005           0 :     if (rootBox && rootBox->GetPopupSetFrame() == aFrame) {
    9006           0 :       ReconstructDocElementHierarchy(InsertionKind::Async);
    9007           0 :       return true;
    9008             :     }
    9009             :   }
    9010             : #endif
    9011             : 
    9012             :   // Reconstruct if inflowFrame is parent's only child, and parent is, or has,
    9013             :   // a non-fluid continuation, i.e. it was split by bidi resolution
    9014          38 :   if (!inFlowFrame->GetPrevSibling() &&
    9015          20 :       !inFlowFrame->GetNextSibling() &&
    9016           8 :       ((parent->GetPrevContinuation() && !parent->GetPrevInFlow()) ||
    9017           4 :        (parent->GetNextContinuation() && !parent->GetNextInFlow()))) {
    9018           0 :     RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
    9019           0 :     return true;
    9020             :   }
    9021             : 
    9022             :   // We might still need to reconstruct things if the parent of inFlowFrame is
    9023             :   // ib-split, since in that case the removal of aFrame might affect the
    9024             :   // splitting of its parent.
    9025           0 :   if (!IsFramePartOfIBSplit(parent)) {
    9026             :     return false;
    9027             :   }
    9028             : 
    9029             :   // If inFlowFrame is not the only in-flow child of |parent|, then removing
    9030             :   // it will change nothing about the {ib} split.
    9031           0 :   if (inFlowFrame != parent->PrincipalChildList().FirstChild() ||
    9032           0 :       inFlowFrame->LastContinuation()->GetNextSibling()) {
    9033             :     return false;
    9034             :   }
    9035             : 
    9036             :   // If the parent is the first or last part of the {ib} split, then
    9037             :   // removing one of its kids will have no effect on the splitting.
    9038             :   // Get the first continuation up front so we don't have to do it twice.
    9039           0 :   nsIFrame* parentFirstContinuation = parent->FirstContinuation();
    9040           0 :   if (!GetIBSplitSibling(parentFirstContinuation) ||
    9041           0 :       !GetIBSplitPrevSibling(parentFirstContinuation)) {
    9042             :     return false;
    9043             :   }
    9044             : 
    9045             : #ifdef DEBUG
    9046           0 :   if (gNoisyContentUpdates) {
    9047             :     printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    9048           0 :            "frame=");
    9049           0 :     nsFrame::ListTag(stdout, parent);
    9050             :     printf(" is ib-split\n");
    9051             :   }
    9052             : #endif
    9053             : 
    9054           0 :   ReframeContainingBlock(parent);
    9055           0 :   return true;
    9056             : }
    9057             : 
    9058             : void
    9059           0 : nsCSSFrameConstructor::UpdateTableCellSpans(nsIContent* aContent)
    9060             : {
    9061           0 :   nsTableCellFrame* cellFrame = do_QueryFrame(aContent->GetPrimaryFrame());
    9062             : 
    9063             :   // It's possible that this warning could fire if some other style change
    9064             :   // simultaneously changes the 'display' of the element and makes it no
    9065             :   // longer be a table cell.
    9066           0 :   NS_WARNING_ASSERTION(cellFrame, "Hint should only be posted on table cells!");
    9067             : 
    9068           0 :   if (cellFrame) {
    9069           0 :     cellFrame->GetTableFrame()->RowOrColSpanChanged(cellFrame);
    9070             :   }
    9071           0 : }
    9072             : 
    9073             : static nsIContent*
    9074           0 : GetTopmostMathMLElement(nsIContent* aMathMLContent)
    9075             : {
    9076           0 :   MOZ_ASSERT(aMathMLContent->IsMathMLElement());
    9077           0 :   MOZ_ASSERT(aMathMLContent->GetPrimaryFrame());
    9078           0 :   MOZ_ASSERT(aMathMLContent->GetPrimaryFrame()->IsFrameOfType(nsIFrame::eMathML));
    9079           0 :   nsIContent* root = aMathMLContent;
    9080             : 
    9081           0 :   for (nsIContent* parent = aMathMLContent->GetFlattenedTreeParent();
    9082           0 :        parent;
    9083             :        parent = parent->GetFlattenedTreeParent()) {
    9084           0 :     nsIFrame* frame = parent->GetPrimaryFrame();
    9085           0 :     if (!frame || !frame->IsFrameOfType(nsIFrame::eMathML)) {
    9086             :       break;
    9087             :     }
    9088           0 :     root = parent;
    9089             :   }
    9090             : 
    9091           0 :   return root;
    9092             : }
    9093             : 
    9094             : void
    9095           7 : nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent,
    9096             :                                                 InsertionKind aInsertionKind)
    9097             : {
    9098           7 :   MOZ_ASSERT(aContent);
    9099             : 
    9100             :   // If there is no document, we don't want to recreate frames for it.  (You
    9101             :   // shouldn't generally be giving this method content without a document
    9102             :   // anyway).
    9103             :   // Rebuilding the frame tree can have bad effects, especially if it's the
    9104             :   // frame tree for chrome (see bug 157322).
    9105           7 :   if (NS_WARN_IF(!aContent->GetComposedDoc())) {
    9106             :     return;
    9107             :   }
    9108             : 
    9109             :   // Is the frame ib-split? If so, we need to reframe the containing
    9110             :   // block *here*, rather than trying to remove and re-insert the
    9111             :   // content (which would otherwise result in *two* nested reframe
    9112             :   // containing block from ContentRemoved() and ContentInserted(),
    9113             :   // below!).  We'd really like to optimize away one of those
    9114             :   // containing block reframes, hence the code here.
    9115             : 
    9116           7 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    9117           7 :   if (frame && frame->IsFrameOfType(nsIFrame::eMathML)) {
    9118             :     // Reframe the topmost MathML element to prevent exponential blowup
    9119             :     // (see bug 397518).
    9120           0 :     aContent = GetTopmostMathMLElement(aContent);
    9121           0 :     frame = aContent->GetPrimaryFrame();
    9122             :   }
    9123             : 
    9124           7 :   if (frame) {
    9125           0 :     nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(frame);
    9126           7 :     if (nonGeneratedAncestor->GetContent() != aContent) {
    9127           0 :       return RecreateFramesForContent(nonGeneratedAncestor->GetContent(),
    9128           0 :                                       InsertionKind::Async);
    9129             :     }
    9130             : 
    9131           0 :     if (frame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
    9132             :       // Recreate the frames for the entire nsIAnonymousContentCreator tree
    9133             :       // since |frame| or one of its descendants may need an ComputedStyle
    9134             :       // that associates it to a CSS pseudo-element, and only the
    9135             :       // nsIAnonymousContentCreator that created this content knows how to make
    9136             :       // that happen.
    9137           0 :       nsIAnonymousContentCreator* acc = nullptr;
    9138           0 :       nsIFrame* ancestor = nsLayoutUtils::GetParentOrPlaceholderFor(frame);
    9139           0 :       while (!(acc = do_QueryFrame(ancestor))) {
    9140           0 :         ancestor = nsLayoutUtils::GetParentOrPlaceholderFor(ancestor);
    9141             :       }
    9142             :       NS_ASSERTION(acc, "Where is the nsIAnonymousContentCreator? We may fail "
    9143             :                         "to recreate its content correctly");
    9144             :       // nsSVGUseFrame is special, and we know this is unnecessary for it.
    9145           0 :       if (!ancestor->IsSVGUseFrame()) {
    9146           0 :         NS_ASSERTION(aContent->IsInNativeAnonymousSubtree(),
    9147             :                      "Why is NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT set?");
    9148           0 :         return RecreateFramesForContent(ancestor->GetContent(),
    9149           0 :                                         InsertionKind::Async);
    9150             :       }
    9151             :     }
    9152             : 
    9153           7 :     nsIFrame* parent = frame->GetParent();
    9154           0 :     nsIContent* parentContent = parent ? parent->GetContent() : nullptr;
    9155             :     // If the parent frame is a leaf then the subsequent insert will fail to
    9156             :     // create a frame, so we need to recreate the parent content. This happens
    9157             :     // with native anonymous content from the editor.
    9158           0 :     if (parent && parent->IsLeaf() && parentContent &&
    9159             :         parentContent != aContent) {
    9160           0 :       return RecreateFramesForContent(parentContent, InsertionKind::Async);
    9161             :     }
    9162             :   }
    9163             : 
    9164           7 :   if (frame && MaybeRecreateContainerForFrameRemoval(frame)) {
    9165             :     return;
    9166             :   }
    9167             : 
    9168           7 :   MOZ_ASSERT(aContent->GetParentNode());
    9169             : 
    9170             :   // Before removing the frames associated with the content object,
    9171             :   // ask them to save their state onto a temporary state object.
    9172           0 :   CaptureStateForFramesOf(aContent, mTempFrameTreeState);
    9173             : 
    9174             :   // Remove the frames associated with the content object.
    9175           0 :   nsIContent* nextSibling = aContent->IsRootOfAnonymousSubtree() ?
    9176          11 :     nullptr : aContent->GetNextSibling();
    9177             :   bool didReconstruct =
    9178           7 :     ContentRemoved(aContent, nextSibling, REMOVE_FOR_RECONSTRUCTION);
    9179             : 
    9180           7 :   if (!didReconstruct) {
    9181           7 :     if (aInsertionKind == InsertionKind::Async && aContent->IsElement()) {
    9182             :       // FIXME(emilio, bug 1397239): There's nothing removing the frame state
    9183             :       // for elements that go away before we come back to the frame
    9184             :       // constructor.
    9185             :       //
    9186             :       // Also, it'd be nice to just use the `ContentRangeInserted` path for
    9187             :       // both elements and non-elements, but we need to make lazy frame
    9188             :       // construction to apply to all elements first.
    9189           0 :       RestyleManager()->PostRestyleEvent(aContent->AsElement(),
    9190             :                                          nsRestyleHint(0),
    9191           0 :                                          nsChangeHint_ReconstructFrame);
    9192             :     } else {
    9193             :       // Now, recreate the frames associated with this content object. If
    9194             :       // ContentRemoved triggered reconstruction, then we don't need to do this
    9195             :       // because the frames will already have been built.
    9196          14 :       ContentRangeInserted(aContent,
    9197             :                            aContent->GetNextSibling(),
    9198             :                            mTempFrameTreeState,
    9199           0 :                            aInsertionKind);
    9200             :     }
    9201             :   }
    9202             : }
    9203             : 
    9204             : bool
    9205           0 : nsCSSFrameConstructor::DestroyFramesFor(Element* aElement)
    9206             : {
    9207           0 :   MOZ_ASSERT(aElement && aElement->GetParentNode());
    9208             : 
    9209             :   nsIContent* nextSibling =
    9210           0 :     aElement->IsRootOfAnonymousSubtree() ? nullptr : aElement->GetNextSibling();
    9211             : 
    9212           0 :   CaptureStateForFramesOf(aElement, mTempFrameTreeState);
    9213             :   return ContentRemoved(aElement,
    9214             :                         nextSibling,
    9215           0 :                         REMOVE_FOR_RECONSTRUCTION);
    9216             : }
    9217             : 
    9218             : //////////////////////////////////////////////////////////////////////
    9219             : 
    9220             : // Block frame construction code
    9221             : 
    9222             : already_AddRefed<ComputedStyle>
    9223           0 : nsCSSFrameConstructor::GetFirstLetterStyle(nsIContent* aContent,
    9224             :                                            ComputedStyle* aComputedStyle)
    9225             : {
    9226           0 :   if (aContent) {
    9227           0 :     return mPresShell->StyleSet()->
    9228             :       ResolvePseudoElementStyle(aContent->AsElement(),
    9229             :                                 CSSPseudoElementType::firstLetter,
    9230             :                                 aComputedStyle,
    9231           0 :                                 nullptr);
    9232             :   }
    9233             :   return nullptr;
    9234             : }
    9235             : 
    9236             : already_AddRefed<ComputedStyle>
    9237           0 : nsCSSFrameConstructor::GetFirstLineStyle(nsIContent* aContent,
    9238             :                                          ComputedStyle* aComputedStyle)
    9239             : {
    9240           0 :   if (aContent) {
    9241           0 :     return mPresShell->StyleSet()->
    9242             :       ResolvePseudoElementStyle(aContent->AsElement(),
    9243             :                                 CSSPseudoElementType::firstLine,
    9244             :                                 aComputedStyle,
    9245           0 :                                 nullptr);
    9246             :   }
    9247             :   return nullptr;
    9248             : }
    9249             : 
    9250             : // Predicate to see if a given content (block element) has
    9251             : // first-letter style applied to it.
    9252             : bool
    9253          15 : nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(nsIContent* aContent,
    9254             :                                                   ComputedStyle* aComputedStyle)
    9255             : {
    9256           0 :   return nsLayoutUtils::HasPseudoStyle(aContent, aComputedStyle,
    9257             :                                        CSSPseudoElementType::firstLetter,
    9258           0 :                                        mPresShell->GetPresContext());
    9259             : }
    9260             : 
    9261             : bool
    9262           0 : nsCSSFrameConstructor::HasFirstLetterStyle(nsIFrame* aBlockFrame)
    9263             : {
    9264           8 :   MOZ_ASSERT(aBlockFrame, "Need a frame");
    9265           8 :   NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
    9266             :                "Not a block frame?");
    9267             : 
    9268          16 :   return (aBlockFrame->GetStateBits() & NS_BLOCK_HAS_FIRST_LETTER_STYLE) != 0;
    9269             : }
    9270             : 
    9271             : bool
    9272           0 : nsCSSFrameConstructor::ShouldHaveFirstLineStyle(nsIContent* aContent,
    9273             :                                                 ComputedStyle* aComputedStyle)
    9274             : {
    9275             :   bool hasFirstLine =
    9276          22 :     nsLayoutUtils::HasPseudoStyle(aContent, aComputedStyle,
    9277             :                                   CSSPseudoElementType::firstLine,
    9278          44 :                                   mPresShell->GetPresContext());
    9279          22 :   return hasFirstLine && !aContent->IsHTMLElement(nsGkAtoms::fieldset);
    9280             : }
    9281             : 
    9282             : void
    9283           0 : nsCSSFrameConstructor::ShouldHaveSpecialBlockStyle(nsIContent* aContent,
    9284             :                                                    ComputedStyle* aComputedStyle,
    9285             :                                                    bool* aHaveFirstLetterStyle,
    9286             :                                                    bool* aHaveFirstLineStyle)
    9287             : {
    9288          15 :   *aHaveFirstLetterStyle =
    9289          15 :     ShouldHaveFirstLetterStyle(aContent, aComputedStyle);
    9290          15 :   *aHaveFirstLineStyle =
    9291          15 :     ShouldHaveFirstLineStyle(aContent, aComputedStyle);
    9292          15 : }
    9293             : 
    9294             : /* static */
    9295             : const nsCSSFrameConstructor::PseudoParentData
    9296             : nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
    9297             :   { // Cell
    9298             :     FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
    9299             :                      FCDATA_USE_CHILD_ITEMS |
    9300             :                      FCDATA_IS_WRAPPER_ANON_BOX |
    9301             :                      FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
    9302             :                      &nsCSSFrameConstructor::ConstructTableCell),
    9303             :     &nsCSSAnonBoxes::tableCell
    9304             :   },
    9305             :   { // Row
    9306             :     FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
    9307             :                      FCDATA_USE_CHILD_ITEMS |
    9308             :                      FCDATA_IS_WRAPPER_ANON_BOX |
    9309             :                      FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
    9310             :                      &nsCSSFrameConstructor::ConstructTableRowOrRowGroup),
    9311             :     &nsCSSAnonBoxes::tableRow
    9312             :   },
    9313             :   { // Row group
    9314             :     FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
    9315             :                      FCDATA_USE_CHILD_ITEMS |
    9316             :                      FCDATA_IS_WRAPPER_ANON_BOX |
    9317             :                      FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    9318             :                      &nsCSSFrameConstructor::ConstructTableRowOrRowGroup),
    9319             :     &nsCSSAnonBoxes::tableRowGroup
    9320             :   },
    9321             :   { // Column group
    9322             :     FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
    9323             :                 FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
    9324             :                 FCDATA_SKIP_ABSPOS_PUSH |
    9325             :                 // Not FCDATA_IS_WRAPPER_ANON_BOX, because we don't need to
    9326             :                 // restyle these: they have non-inheriting styles.
    9327             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    9328             :                 NS_NewTableColGroupFrame),
    9329             :     &nsCSSAnonBoxes::tableColGroup
    9330             :   },
    9331             :   { // Table
    9332             :     FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS |
    9333             :                      FCDATA_IS_WRAPPER_ANON_BOX,
    9334             :                      &nsCSSFrameConstructor::ConstructTable),
    9335             :     &nsCSSAnonBoxes::table
    9336             :   },
    9337             :   { // Ruby
    9338             :     FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
    9339             :                 FCDATA_USE_CHILD_ITEMS |
    9340             :                 FCDATA_IS_WRAPPER_ANON_BOX |
    9341             :                 FCDATA_SKIP_FRAMESET,
    9342             :                 NS_NewRubyFrame),
    9343             :     &nsCSSAnonBoxes::ruby
    9344             :   },
    9345             :   { // Ruby Base
    9346             :     FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
    9347             :                 FCDATA_IS_LINE_PARTICIPANT |
    9348             :                 FCDATA_IS_WRAPPER_ANON_BOX |
    9349             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer) |
    9350             :                 FCDATA_SKIP_FRAMESET,
    9351             :                 NS_NewRubyBaseFrame),
    9352             :     &nsCSSAnonBoxes::rubyBase
    9353             :   },
    9354             :   { // Ruby Base Container
    9355             :     FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
    9356             :                 FCDATA_IS_LINE_PARTICIPANT |
    9357             :                 FCDATA_IS_WRAPPER_ANON_BOX |
    9358             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby) |
    9359             :                 FCDATA_SKIP_FRAMESET,
    9360             :                 NS_NewRubyBaseContainerFrame),
    9361             :     &nsCSSAnonBoxes::rubyBaseContainer
    9362             :   },
    9363             :   { // Ruby Text
    9364             :     FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
    9365             :                 FCDATA_IS_LINE_PARTICIPANT |
    9366             :                 FCDATA_IS_WRAPPER_ANON_BOX |
    9367             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer) |
    9368             :                 FCDATA_SKIP_FRAMESET,
    9369             :                 NS_NewRubyTextFrame),
    9370             :     &nsCSSAnonBoxes::rubyText
    9371             :   },
    9372             :   { // Ruby Text Container
    9373             :     FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
    9374             :                 FCDATA_IS_WRAPPER_ANON_BOX |
    9375             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby) |
    9376             :                 FCDATA_SKIP_FRAMESET,
    9377             :                 NS_NewRubyTextContainerFrame),
    9378             :     &nsCSSAnonBoxes::rubyTextContainer
    9379             :   }
    9380             : };
    9381             : 
    9382             : void
    9383           0 : nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
    9384             :   nsFrameConstructorState& aState,
    9385             :   FrameConstructionItemList& aItems,
    9386             :   nsIFrame* aParentFrame)
    9387             : {
    9388           0 :   if (aItems.IsEmpty() || !::IsFlexOrGridContainer(aParentFrame)) {
    9389         273 :     return;
    9390             :   }
    9391             : 
    9392           0 :   const bool isLegacyBox = IsFlexContainerForLegacyBox(aParentFrame);
    9393           0 :   FCItemIterator iter(aItems);
    9394           0 :   do {
    9395             :     // Advance iter past children that don't want to be wrapped
    9396           0 :     if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState, isLegacyBox)) {
    9397             :       // Hit the end of the items without finding any remaining children that
    9398             :       // need to be wrapped. We're finished!
    9399           0 :       return;
    9400             :     }
    9401             : 
    9402             :     // If our next potentially-wrappable child is whitespace, then see if
    9403             :     // there's anything wrappable immediately after it. If not, we just drop
    9404             :     // the whitespace and move on. (We're not supposed to create any anonymous
    9405             :     // flex/grid items that _only_ contain whitespace).
    9406             :     // (BUT if this is generated content, then we don't give whitespace nodes
    9407             :     // any special treatment, because they're probably not really whitespace --
    9408             :     // they're just temporarily empty, waiting for their generated text.)
    9409             :     // XXXdholbert If this node's generated text will *actually end up being
    9410             :     // entirely whitespace*, then we technically should still skip over it, per
    9411             :     // the CSS grid & flexbox specs. I'm not bothering with that at this point,
    9412             :     // since it's a pretty extreme edge case.
    9413           0 :     if (!aParentFrame->IsGeneratedContentFrame() &&
    9414           0 :         iter.item().IsWhitespace(aState)) {
    9415           0 :       FCItemIterator afterWhitespaceIter(iter);
    9416           0 :       bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
    9417             :       bool nextChildNeedsAnonItem =
    9418           0 :         !hitEnd &&
    9419           0 :         afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(aState, isLegacyBox);
    9420             : 
    9421           0 :       if (!nextChildNeedsAnonItem) {
    9422             :         // There's nothing after the whitespace that we need to wrap, so we
    9423             :         // just drop this run of whitespace.
    9424           0 :         iter.DeleteItemsTo(this, afterWhitespaceIter);
    9425           0 :         if (hitEnd) {
    9426             :           // Nothing left to do -- we're finished!
    9427           0 :           return;
    9428             :         }
    9429             :         // else, we have a next child and it does not want to be wrapped.  So,
    9430             :         // we jump back to the beginning of the loop to skip over that child
    9431             :         // (and anything else non-wrappable after it)
    9432           0 :         MOZ_ASSERT(!iter.IsDone() &&
    9433             :                    !iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyBox),
    9434             :                    "hitEnd and/or nextChildNeedsAnonItem lied");
    9435           0 :         continue;
    9436             :       }
    9437             :     }
    9438             : 
    9439             :     // Now |iter| points to the first child that needs to be wrapped in an
    9440             :     // anonymous flex/grid item. Now we see how many children after it also want
    9441             :     // to be wrapped in an anonymous flex/grid item.
    9442           0 :     FCItemIterator endIter(iter); // iterator to find the end of the group
    9443           0 :     endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isLegacyBox);
    9444             : 
    9445           0 :     NS_ASSERTION(iter != endIter,
    9446             :                  "Should've had at least one wrappable child to seek past");
    9447             : 
    9448             :     // Now, we create the anonymous flex or grid item to contain the children
    9449             :     // between |iter| and |endIter|.
    9450           0 :     nsAtom* pseudoType = (aParentFrame->IsFlexContainerFrame())
    9451             :                             ? nsCSSAnonBoxes::anonymousFlexItem
    9452           0 :                             : nsCSSAnonBoxes::anonymousGridItem;
    9453           0 :     ComputedStyle* parentStyle = aParentFrame->Style();
    9454           0 :     nsIContent* parentContent = aParentFrame->GetContent();
    9455             :     already_AddRefed<ComputedStyle> wrapperStyle =
    9456           0 :       mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(pseudoType,
    9457           0 :                                                                  parentStyle);
    9458             : 
    9459             :     static const FrameConstructionData sBlockFormattingContextFCData =
    9460             :       FCDATA_DECL(FCDATA_SKIP_FRAMESET |
    9461             :                   FCDATA_USE_CHILD_ITEMS |
    9462             :                   FCDATA_IS_WRAPPER_ANON_BOX,
    9463             :                   NS_NewBlockFormattingContext);
    9464             : 
    9465             :     FrameConstructionItem* newItem =
    9466             :       new (this) FrameConstructionItem(&sBlockFormattingContextFCData,
    9467             :                                 // Use the content of our parent frame
    9468             :                                 parentContent,
    9469             :                                 // no pending binding
    9470             :                                 nullptr,
    9471             :                                 wrapperStyle,
    9472           0 :                                 true, nullptr);
    9473             : 
    9474           0 :     newItem->mIsAllInline = newItem->mHasInlineEnds =
    9475           0 :       newItem->mComputedStyle->StyleDisplay()->IsInlineOutsideStyle();
    9476           0 :     newItem->mIsBlock = !newItem->mIsAllInline;
    9477             : 
    9478           0 :     MOZ_ASSERT(!newItem->mIsAllInline && newItem->mIsBlock,
    9479             :                "expecting anonymous flex/grid items to be block-level "
    9480             :                "(this will make a difference when we encounter "
    9481             :                "'align-items: baseline')");
    9482             : 
    9483             :     // Anonymous flex and grid items induce line boundaries around their
    9484             :     // contents.
    9485           0 :     newItem->mChildItems.SetLineBoundaryAtStart(true);
    9486           0 :     newItem->mChildItems.SetLineBoundaryAtEnd(true);
    9487             :     // The parent of the items in aItems is also the parent of the items
    9488             :     // in mChildItems
    9489           0 :     newItem->mChildItems.SetParentHasNoXBLChildren(
    9490           0 :       aItems.ParentHasNoXBLChildren());
    9491             : 
    9492             :     // Eat up all items between |iter| and |endIter| and put them in our
    9493             :     // wrapper. This advances |iter| to point to |endIter|.
    9494           0 :     iter.AppendItemsToList(this, endIter, newItem->mChildItems);
    9495             : 
    9496           0 :     iter.InsertItem(newItem);
    9497           0 :   } while (!iter.IsDone());
    9498             : }
    9499             : 
    9500             : /* static */ nsCSSFrameConstructor::RubyWhitespaceType
    9501           0 : nsCSSFrameConstructor::ComputeRubyWhitespaceType(StyleDisplay aPrevDisplay,
    9502             :                                                  StyleDisplay aNextDisplay)
    9503             : {
    9504           0 :   MOZ_ASSERT(nsStyleDisplay::IsRubyDisplayType(aPrevDisplay) &&
    9505             :              nsStyleDisplay::IsRubyDisplayType(aNextDisplay));
    9506           0 :   if (aPrevDisplay == aNextDisplay &&
    9507           0 :       (aPrevDisplay == StyleDisplay::RubyBase ||
    9508           0 :        aPrevDisplay == StyleDisplay::RubyText)) {
    9509             :     return eRubyInterLeafWhitespace;
    9510             :   }
    9511           0 :   if (aNextDisplay == StyleDisplay::RubyText ||
    9512             :       aNextDisplay == StyleDisplay::RubyTextContainer) {
    9513             :     return eRubyInterLevelWhitespace;
    9514             :   }
    9515           0 :   return eRubyInterSegmentWhitespace;
    9516             : }
    9517             : 
    9518             : /**
    9519             :  * This function checks the content from |aStartIter| to |aEndIter|,
    9520             :  * determines whether it contains only whitespace, and if yes,
    9521             :  * interprets the type of whitespace. This method does not change
    9522             :  * any of the iters.
    9523             :  */
    9524             : /* static */ nsCSSFrameConstructor::RubyWhitespaceType
    9525           0 : nsCSSFrameConstructor::InterpretRubyWhitespace(nsFrameConstructorState& aState,
    9526             :                                                const FCItemIterator& aStartIter,
    9527             :                                                const FCItemIterator& aEndIter)
    9528             : {
    9529           0 :   if (!aStartIter.item().IsWhitespace(aState)) {
    9530             :     return eRubyNotWhitespace;
    9531             :   }
    9532             : 
    9533           0 :   FCItemIterator spaceEndIter(aStartIter);
    9534           0 :   spaceEndIter.SkipWhitespace(aState);
    9535           0 :   if (spaceEndIter != aEndIter) {
    9536             :     return eRubyNotWhitespace;
    9537             :   }
    9538             : 
    9539             :   // Any leading or trailing whitespace in non-pseudo ruby box
    9540             :   // should have been trimmed, hence there should not be any
    9541             :   // whitespace at the start or the end.
    9542           0 :   MOZ_ASSERT(!aStartIter.AtStart() && !aEndIter.IsDone());
    9543           0 :   FCItemIterator prevIter(aStartIter);
    9544           0 :   prevIter.Prev();
    9545             :   return ComputeRubyWhitespaceType(
    9546           0 :       prevIter.item().mComputedStyle->StyleDisplay()->mDisplay,
    9547           0 :       aEndIter.item().mComputedStyle->StyleDisplay()->mDisplay);
    9548             : }
    9549             : 
    9550             : 
    9551             : /**
    9552             :  * This function eats up consecutive items which do not want the current
    9553             :  * parent into either a ruby base box or a ruby text box.  When it
    9554             :  * returns, |aIter| points to the first item it doesn't wrap.
    9555             :  */
    9556             : void
    9557           0 : nsCSSFrameConstructor::WrapItemsInPseudoRubyLeafBox(
    9558             :   FCItemIterator& aIter,
    9559             :   ComputedStyle* aParentStyle, nsIContent* aParentContent)
    9560             : {
    9561           0 :   StyleDisplay parentDisplay = aParentStyle->StyleDisplay()->mDisplay;
    9562             :   ParentType parentType, wrapperType;
    9563           0 :   if (parentDisplay == StyleDisplay::RubyTextContainer) {
    9564             :     parentType = eTypeRubyTextContainer;
    9565             :     wrapperType = eTypeRubyText;
    9566             :   } else {
    9567           0 :     MOZ_ASSERT(parentDisplay == StyleDisplay::RubyBaseContainer);
    9568             :     parentType = eTypeRubyBaseContainer;
    9569             :     wrapperType = eTypeRubyBase;
    9570             :   }
    9571             : 
    9572           0 :   MOZ_ASSERT(aIter.item().DesiredParentType() != parentType,
    9573             :              "Should point to something needs to be wrapped.");
    9574             : 
    9575           0 :   FCItemIterator endIter(aIter);
    9576           0 :   endIter.SkipItemsNotWantingParentType(parentType);
    9577             : 
    9578             :   WrapItemsInPseudoParent(aParentContent, aParentStyle,
    9579           0 :                           wrapperType, aIter, endIter);
    9580           0 : }
    9581             : 
    9582             : /**
    9583             :  * This function eats up consecutive items into a ruby level container.
    9584             :  * It may create zero or one level container. When it returns, |aIter|
    9585             :  * points to the first item it doesn't wrap.
    9586             :  */
    9587             : void
    9588           0 : nsCSSFrameConstructor::WrapItemsInPseudoRubyLevelContainer(
    9589             :   nsFrameConstructorState& aState, FCItemIterator& aIter,
    9590             :   ComputedStyle* aParentStyle, nsIContent* aParentContent)
    9591             : {
    9592           0 :   MOZ_ASSERT(aIter.item().DesiredParentType() != eTypeRuby,
    9593             :              "Pointing to a level container?");
    9594             : 
    9595           0 :   FrameConstructionItem& firstItem = aIter.item();
    9596           0 :   ParentType wrapperType = firstItem.DesiredParentType();
    9597           0 :   if (wrapperType != eTypeRubyTextContainer) {
    9598             :     // If the first item is not ruby text,
    9599             :     // it should be in a base container.
    9600           0 :     wrapperType = eTypeRubyBaseContainer;
    9601             :   }
    9602             : 
    9603             :   FCItemIterator endIter(aIter);
    9604           0 :   do {
    9605           0 :     if (endIter.SkipItemsWantingParentType(wrapperType) ||
    9606             :         // If the skipping above stops at some item which wants a
    9607             :         // different ruby parent, then we have finished.
    9608           0 :         IsRubyParentType(endIter.item().DesiredParentType())) {
    9609             :       // No more items need to be wrapped in this level container.
    9610             :       break;
    9611             :     }
    9612             : 
    9613           0 :     FCItemIterator contentEndIter(endIter);
    9614           0 :     contentEndIter.SkipItemsNotWantingRubyParent();
    9615             :     // endIter must be on something doesn't want a ruby parent.
    9616           0 :     MOZ_ASSERT(contentEndIter != endIter);
    9617             : 
    9618             :     // InterpretRubyWhitespace depends on the fact that any leading or
    9619             :     // trailing whitespace described in the spec have been trimmed at
    9620             :     // this point. With this precondition, it is safe not to check
    9621             :     // whether contentEndIter has been done.
    9622             :     RubyWhitespaceType whitespaceType =
    9623           0 :       InterpretRubyWhitespace(aState, endIter, contentEndIter);
    9624           0 :     if (whitespaceType == eRubyInterLevelWhitespace) {
    9625             :       // Remove inter-level whitespace.
    9626           0 :       bool atStart = (aIter == endIter);
    9627           0 :       endIter.DeleteItemsTo(this, contentEndIter);
    9628           0 :       if (atStart) {
    9629           0 :         aIter = endIter;
    9630             :       }
    9631           0 :     } else if (whitespaceType == eRubyInterSegmentWhitespace) {
    9632             :       // If this level container starts with inter-segment whitespaces,
    9633             :       // wrap them. Break at contentEndIter. Otherwise, leave it here.
    9634             :       // Break at endIter. They will be wrapped when we are here again.
    9635           0 :       if (aIter == endIter) {
    9636           0 :         MOZ_ASSERT(wrapperType == eTypeRubyBaseContainer,
    9637             :                    "Inter-segment whitespace should be wrapped in rbc");
    9638           0 :         endIter = contentEndIter;
    9639             :       }
    9640             :       break;
    9641           0 :     } else if (wrapperType == eTypeRubyTextContainer &&
    9642           0 :                whitespaceType != eRubyInterLeafWhitespace) {
    9643             :       // Misparented inline content that's not inter-annotation
    9644             :       // whitespace doesn't belong in a pseudo ruby text container.
    9645             :       // Break at endIter.
    9646             :       break;
    9647             :     } else {
    9648           0 :       endIter = contentEndIter;
    9649             :     }
    9650           0 :   } while (!endIter.IsDone());
    9651             : 
    9652             :   // It is possible that everything our parent wants us to wrap is
    9653             :   // simply an inter-level whitespace, which has been trimmed, or
    9654             :   // an inter-segment whitespace, which will be wrapped later.
    9655             :   // In those cases, don't create anything.
    9656           0 :   if (aIter != endIter) {
    9657             :     WrapItemsInPseudoParent(aParentContent, aParentStyle,
    9658           0 :                             wrapperType, aIter, endIter);
    9659             :   }
    9660           0 : }
    9661             : 
    9662             : /**
    9663             :  * This function trims leading and trailing whitespaces
    9664             :  * in the given item list.
    9665             :  */
    9666             : void
    9667           0 : nsCSSFrameConstructor::TrimLeadingAndTrailingWhitespaces(
    9668             :     nsFrameConstructorState& aState,
    9669             :     FrameConstructionItemList& aItems)
    9670             : {
    9671           0 :   FCItemIterator iter(aItems);
    9672           0 :   if (!iter.IsDone() &&
    9673           0 :       iter.item().IsWhitespace(aState)) {
    9674           0 :     FCItemIterator spaceEndIter(iter);
    9675           0 :     spaceEndIter.SkipWhitespace(aState);
    9676           0 :     iter.DeleteItemsTo(this, spaceEndIter);
    9677             :   }
    9678             : 
    9679           0 :   iter.SetToEnd();
    9680           0 :   if (!iter.AtStart()) {
    9681             :     FCItemIterator spaceEndIter(iter);
    9682           0 :     do {
    9683           0 :       iter.Prev();
    9684           0 :       if (iter.AtStart()) {
    9685             :         // It's fine to not check the first item, because we
    9686             :         // should have trimmed leading whitespaces above.
    9687             :         break;
    9688             :       }
    9689           0 :     } while (iter.item().IsWhitespace(aState));
    9690           0 :     iter.Next();
    9691           0 :     if (iter != spaceEndIter) {
    9692           0 :       iter.DeleteItemsTo(this, spaceEndIter);
    9693             :     }
    9694             :   }
    9695           0 : }
    9696             : 
    9697             : /**
    9698             :  * This function walks through the child list (aItems) and creates
    9699             :  * needed pseudo ruby boxes to wrap misparented children.
    9700             :  */
    9701             : void
    9702           0 : nsCSSFrameConstructor::CreateNeededPseudoInternalRubyBoxes(
    9703             :   nsFrameConstructorState& aState,
    9704             :   FrameConstructionItemList& aItems,
    9705             :   nsIFrame* aParentFrame)
    9706             : {
    9707           0 :   const ParentType ourParentType = GetParentType(aParentFrame);
    9708         273 :   if (!IsRubyParentType(ourParentType) ||
    9709           0 :       aItems.AllWantParentType(ourParentType)) {
    9710         273 :     return;
    9711             :   }
    9712             : 
    9713           0 :   if (!IsRubyPseudo(aParentFrame)) {
    9714             :     // Normally, ruby pseudo frames start from and end at some elements,
    9715             :     // which means they don't have leading and trailing whitespaces at
    9716             :     // all.  But there are two cases where they do actually have leading
    9717             :     // or trailing whitespaces:
    9718             :     // 1. It is an inter-segment whitespace which in an individual ruby
    9719             :     //    base container.
    9720             :     // 2. The pseudo frame starts from or ends at consecutive inline
    9721             :     //    content, which is not pure whitespace, but includes some.
    9722             :     // In either case, the whitespaces are not the leading or trailing
    9723             :     // whitespaces defined in the spec, and thus should not be trimmed.
    9724           0 :     TrimLeadingAndTrailingWhitespaces(aState, aItems);
    9725             :   }
    9726             : 
    9727           0 :   FCItemIterator iter(aItems);
    9728           0 :   nsIContent* parentContent = aParentFrame->GetContent();
    9729           0 :   ComputedStyle* parentStyle = aParentFrame->Style();
    9730           0 :   while (!iter.IsDone()) {
    9731           0 :     if (!iter.SkipItemsWantingParentType(ourParentType)) {
    9732           0 :       if (ourParentType == eTypeRuby) {
    9733             :         WrapItemsInPseudoRubyLevelContainer(aState, iter, parentStyle,
    9734           0 :                                             parentContent);
    9735             :       } else {
    9736           0 :         WrapItemsInPseudoRubyLeafBox(iter, parentStyle, parentContent);
    9737             :       }
    9738             :     }
    9739             :   }
    9740             : }
    9741             : 
    9742             : /*
    9743             :  * This function works as follows: we walk through the child list (aItems) and
    9744             :  * find items that cannot have aParentFrame as their parent.  We wrap
    9745             :  * continuous runs of such items into a FrameConstructionItem for a frame that
    9746             :  * gets them closer to their desired parents.  For example, a run of non-row
    9747             :  * children of a row-group will get wrapped in a row.  When we later construct
    9748             :  * the frame for this wrapper (in this case for the row), it'll be the correct
    9749             :  * parent for the cells in the set of items we wrapped or we'll wrap cells
    9750             :  * around everything else.  At the end of this method, aItems is guaranteed to
    9751             :  * contain only items for frames that can be direct kids of aParentFrame.
    9752             :  */
    9753             : void
    9754           0 : nsCSSFrameConstructor::CreateNeededPseudoContainers(
    9755             :     nsFrameConstructorState& aState,
    9756             :     FrameConstructionItemList& aItems,
    9757             :     nsIFrame* aParentFrame)
    9758             : {
    9759         273 :   ParentType ourParentType = GetParentType(aParentFrame);
    9760           0 :   if (IsRubyParentType(ourParentType) ||
    9761           0 :       aItems.AllWantParentType(ourParentType)) {
    9762             :     // Nothing to do here
    9763         273 :     return;
    9764             :   }
    9765             : 
    9766           0 :   FCItemIterator iter(aItems);
    9767           0 :   do {
    9768           0 :     if (iter.SkipItemsWantingParentType(ourParentType)) {
    9769             :       // Nothing else to do here; we're finished
    9770           0 :       return;
    9771             :     }
    9772             : 
    9773             :     // Now we're pointing to the first child that wants a different parent
    9774             :     // type.
    9775             : 
    9776             :     // Now try to figure out what kids we can group together.  We can generally
    9777             :     // group everything that has a different desired parent type from us.  Two
    9778             :     // exceptions to this:
    9779             :     // 1) If our parent type is table, we can't group columns with anything
    9780             :     //    else other than whitespace.
    9781             :     // 2) Whitespace that lies between two things we can group which both want
    9782             :     //    a non-block parent should be dropped, even if we can't group them
    9783             :     //    with each other and even if the whitespace wants a parent of
    9784             :     //    ourParentType.  Ends of the list count as things that don't want a
    9785             :     //    block parent (so that for example we'll drop a whitespace-only list).
    9786             : 
    9787           0 :     FCItemIterator endIter(iter); /* iterator to find the end of the group */
    9788           0 :     ParentType groupingParentType = endIter.item().DesiredParentType();
    9789           0 :     if (aItems.AllWantParentType(groupingParentType) &&
    9790             :         groupingParentType != eTypeBlock) {
    9791             :       // Just group them all and be done with it.  We need the check for
    9792             :       // eTypeBlock here to catch the "all the items are whitespace" case
    9793             :       // described above.
    9794           0 :       endIter.SetToEnd();
    9795             :     } else {
    9796             :       // Locate the end of the group.
    9797             : 
    9798             :       // Keep track of the type the previous item wanted, in case we have to
    9799             :       // deal with whitespace.  Start it off with ourParentType, since that's
    9800             :       // the last thing |iter| would have skipped over.
    9801             :       ParentType prevParentType = ourParentType;
    9802           0 :       do {
    9803             :         // Walk an iterator past any whitespace that we might be able to drop
    9804             :         // from the list
    9805           0 :         FCItemIterator spaceEndIter(endIter);
    9806           0 :         if (prevParentType != eTypeBlock &&
    9807           0 :             !aParentFrame->IsGeneratedContentFrame() &&
    9808           0 :             spaceEndIter.item().IsWhitespace(aState)) {
    9809           0 :           bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
    9810             : 
    9811             :           // We drop the whitespace in the following cases:
    9812             :           // 1) If these are not trailing spaces and the next item wants a table
    9813             :           //    or table-part parent
    9814             :           // 2) If these are trailing spaces and aParentFrame is a
    9815             :           //    tabular container according to rule 1.3 of CSS 2.1 Sec 17.2.1.
    9816             :           //    (Being a tabular container pretty much means ourParentType is
    9817             :           //    not eTypeBlock besides the eTypeColGroup case, which won't
    9818             :           //    reach here.)
    9819           0 :           if ((!trailingSpaces &&
    9820           0 :                IsTableParentType(spaceEndIter.item().DesiredParentType())) ||
    9821           0 :               (trailingSpaces && ourParentType != eTypeBlock)) {
    9822           0 :             bool updateStart = (iter == endIter);
    9823           0 :             endIter.DeleteItemsTo(this, spaceEndIter);
    9824           0 :             NS_ASSERTION(trailingSpaces == endIter.IsDone(),
    9825             :                          "These should match");
    9826             : 
    9827           0 :             if (updateStart) {
    9828           0 :               iter = endIter;
    9829             :             }
    9830             : 
    9831           0 :             if (trailingSpaces) {
    9832             :               break; /* Found group end */
    9833             :             }
    9834             : 
    9835           0 :             if (updateStart) {
    9836             :               // Update groupingParentType, since it might have been eTypeBlock
    9837             :               // just because of the whitespace.
    9838           0 :               groupingParentType = iter.item().DesiredParentType();
    9839             :             }
    9840             :           }
    9841             :         }
    9842             : 
    9843             :         // Now endIter points to a non-whitespace item or a non-droppable
    9844             :         // whitespace item. In the latter case, if this is the end of the group
    9845             :         // we'll traverse this whitespace again.  But it'll all just be quick
    9846             :         // DesiredParentType() checks which will match ourParentType (that's
    9847             :         // what it means that this is the group end), so it's OK.
    9848             :         // However, when we are grouping a ruby parent, and endIter points to
    9849             :         // a non-droppable whitespace, if the next non-whitespace item also
    9850             :         // wants a ruby parent, the whitespace should also be included into
    9851             :         // the current ruby container.
    9852           0 :         prevParentType = endIter.item().DesiredParentType();
    9853           0 :         if (prevParentType == ourParentType &&
    9854           0 :             (endIter == spaceEndIter ||
    9855           0 :              spaceEndIter.IsDone() ||
    9856           0 :              !IsRubyParentType(groupingParentType) ||
    9857           0 :              !IsRubyParentType(spaceEndIter.item().DesiredParentType()))) {
    9858             :           // End the group at endIter.
    9859             :           break;
    9860             :         }
    9861             : 
    9862           0 :         if (ourParentType == eTypeTable &&
    9863           0 :             (prevParentType == eTypeColGroup) !=
    9864             :             (groupingParentType == eTypeColGroup)) {
    9865             :           // Either we started with columns and now found something else, or vice
    9866             :           // versa.  In any case, end the grouping.
    9867             :           break;
    9868             :         }
    9869             : 
    9870             :         // If we have some whitespace that we were not able to drop and there is
    9871             :         // an item after the whitespace that is already properly parented, then
    9872             :         // make sure to include the spaces in our group but stop the group after
    9873             :         // that.
    9874           0 :         if (spaceEndIter != endIter &&
    9875           0 :             !spaceEndIter.IsDone() &&
    9876           0 :             ourParentType == spaceEndIter.item().DesiredParentType()) {
    9877           0 :             endIter = spaceEndIter;
    9878           0 :             break;
    9879             :         }
    9880             : 
    9881             :         // Include the whitespace we didn't drop (if any) in the group.
    9882           0 :         endIter = spaceEndIter;
    9883           0 :         prevParentType = endIter.item().DesiredParentType();
    9884             : 
    9885           0 :         endIter.Next();
    9886           0 :       } while (!endIter.IsDone());
    9887             :     }
    9888             : 
    9889           0 :     if (iter == endIter) {
    9890             :       // Nothing to wrap here; just skipped some whitespace
    9891           0 :       continue;
    9892             :     }
    9893             : 
    9894             :     // Now group together all the items between iter and endIter.  The right
    9895             :     // parent type to use depends on ourParentType.
    9896             :     ParentType wrapperType;
    9897           0 :     switch (ourParentType) {
    9898             :       case eTypeRow:
    9899             :         // The parent type for a cell is eTypeBlock, since that's what a cell
    9900             :         // looks like to its kids.
    9901             :         wrapperType = eTypeBlock;
    9902             :         break;
    9903             :       case eTypeRowGroup:
    9904           0 :         wrapperType = eTypeRow;
    9905           0 :         break;
    9906             :       case eTypeTable:
    9907             :         // Either colgroup or rowgroup, depending on what we're grouping.
    9908           0 :         wrapperType = groupingParentType == eTypeColGroup ?
    9909             :           eTypeColGroup : eTypeRowGroup;
    9910             :         break;
    9911             :       case eTypeColGroup:
    9912           0 :         MOZ_CRASH("Colgroups should be suppresing non-col child items");
    9913             :       default:
    9914           0 :         NS_ASSERTION(ourParentType == eTypeBlock, "Unrecognized parent type");
    9915           0 :         if (IsRubyParentType(groupingParentType)) {
    9916             :           wrapperType = eTypeRuby;
    9917             :         } else {
    9918           0 :           NS_ASSERTION(IsTableParentType(groupingParentType),
    9919             :                        "groupingParentType should be either Ruby or table");
    9920             :           wrapperType = eTypeTable;
    9921             :         }
    9922             :     }
    9923             : 
    9924           0 :     ComputedStyle* parentStyle = aParentFrame->Style();
    9925           0 :     WrapItemsInPseudoParent(aParentFrame->GetContent(), parentStyle,
    9926           0 :                             wrapperType, iter, endIter);
    9927             : 
    9928             :     // Now |iter| points to the item that was the first one we didn't wrap;
    9929             :     // loop and see whether we need to skip it or wrap it in something
    9930             :     // different.
    9931           0 :   } while (!iter.IsDone());
    9932             : }
    9933             : 
    9934             : /**
    9935             :  * This method wraps frame construction item from |aIter| to
    9936             :  * |aEndIter|. After it returns, aIter points to the first item
    9937             :  * after the wrapper.
    9938             :  */
    9939             : void
    9940           0 : nsCSSFrameConstructor::WrapItemsInPseudoParent(nsIContent* aParentContent,
    9941             :                                                ComputedStyle* aParentStyle,
    9942             :                                                ParentType aWrapperType,
    9943             :                                                FCItemIterator& aIter,
    9944             :                                                const FCItemIterator& aEndIter)
    9945             : {
    9946           0 :   const PseudoParentData& pseudoData = sPseudoParentData[aWrapperType];
    9947           0 :   nsAtom* pseudoType = *pseudoData.mPseudoType;
    9948           0 :   StyleDisplay parentDisplay = aParentStyle->StyleDisplay()->mDisplay;
    9949             : 
    9950           0 :   if (pseudoType == nsCSSAnonBoxes::table &&
    9951           0 :       (parentDisplay == StyleDisplay::Inline ||
    9952           0 :        parentDisplay == StyleDisplay::RubyBase ||
    9953             :        parentDisplay == StyleDisplay::RubyText)) {
    9954           0 :     pseudoType = nsCSSAnonBoxes::inlineTable;
    9955             :   }
    9956             : 
    9957           0 :   already_AddRefed<ComputedStyle> wrapperStyle;
    9958           0 :   if (pseudoData.mFCData.mBits & FCDATA_IS_WRAPPER_ANON_BOX) {
    9959             :     wrapperStyle =
    9960           0 :       mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(pseudoType,
    9961           0 :                                                                  aParentStyle);
    9962             :   } else {
    9963             :     wrapperStyle =
    9964           0 :       mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(pseudoType);
    9965             :   }
    9966             : 
    9967             :   FrameConstructionItem* newItem =
    9968             :     new (this) FrameConstructionItem(&pseudoData.mFCData,
    9969             :                               // Use the content of our parent frame
    9970             :                               aParentContent,
    9971             :                               // no pending binding
    9972             :                               nullptr,
    9973             :                               wrapperStyle,
    9974           0 :                               true, nullptr);
    9975             : 
    9976           0 :   const nsStyleDisplay* disp = newItem->mComputedStyle->StyleDisplay();
    9977             :   // Here we're cheating a tad... technically, table-internal items should be
    9978             :   // inline if aParentFrame is inline, but they'll get wrapped in an
    9979             :   // inline-table in the end, so it'll all work out.  In any case, arguably
    9980             :   // we don't need to maintain this state at this point... but it's better
    9981             :   // to, I guess.
    9982           0 :   newItem->mIsAllInline = newItem->mHasInlineEnds =
    9983             :     disp->IsInlineOutsideStyle();
    9984             : 
    9985           0 :   bool isRuby = disp->IsRubyDisplayType();
    9986             :   // All types of ruby frames need a block frame to provide line layout,
    9987             :   // hence they are always line participant.
    9988           0 :   newItem->mIsLineParticipant = isRuby;
    9989             : 
    9990           0 :   if (!isRuby) {
    9991             :     // Table pseudo frames always induce line boundaries around their
    9992             :     // contents.
    9993           0 :     newItem->mChildItems.SetLineBoundaryAtStart(true);
    9994           0 :     newItem->mChildItems.SetLineBoundaryAtEnd(true);
    9995             :   }
    9996             :   // The parent of the items in aItems is also the parent of the items
    9997             :   // in mChildItems
    9998           0 :   newItem->mChildItems.SetParentHasNoXBLChildren(
    9999           0 :       aIter.List()->ParentHasNoXBLChildren());
   10000             : 
   10001             :   // Eat up all items between |aIter| and |aEndIter| and put them in our
   10002             :   // wrapper Advances |aIter| to point to |aEndIter|.
   10003           0 :   aIter.AppendItemsToList(this, aEndIter, newItem->mChildItems);
   10004             : 
   10005           0 :   aIter.InsertItem(newItem);
   10006           0 : }
   10007             : 
   10008             : void
   10009           0 : nsCSSFrameConstructor::CreateNeededPseudoSiblings(
   10010             :     nsFrameConstructorState& aState,
   10011             :     FrameConstructionItemList& aItems,
   10012             :     nsIFrame* aParentFrame)
   10013             : {
   10014           0 :   if (aItems.IsEmpty() ||
   10015           0 :       GetParentType(aParentFrame) != eTypeRuby) {
   10016         273 :     return;
   10017             :   }
   10018             : 
   10019           0 :   FCItemIterator iter(aItems);
   10020           0 :   StyleDisplay firstDisplay = iter.item().mComputedStyle->StyleDisplay()->mDisplay;
   10021           0 :   if (firstDisplay == StyleDisplay::RubyBaseContainer) {
   10022             :     return;
   10023             :   }
   10024           0 :   NS_ASSERTION(firstDisplay == StyleDisplay::RubyTextContainer,
   10025             :                "Child of ruby frame should either a rbc or a rtc");
   10026             : 
   10027             :   const PseudoParentData& pseudoData =
   10028           0 :     sPseudoParentData[eTypeRubyBaseContainer];
   10029           0 :   already_AddRefed<ComputedStyle> pseudoStyle = mPresShell->StyleSet()->
   10030             :     ResolveInheritingAnonymousBoxStyle(*pseudoData.mPseudoType,
   10031           0 :                                        aParentFrame->Style());
   10032             :   FrameConstructionItem* newItem =
   10033             :     new (this) FrameConstructionItem(&pseudoData.mFCData,
   10034             :                                      // Use the content of the parent frame
   10035           0 :                                      aParentFrame->GetContent(),
   10036             :                                      // no pending binding
   10037             :                                      nullptr,
   10038             :                                      pseudoStyle,
   10039           0 :                                      true, nullptr);
   10040           0 :   newItem->mIsAllInline = true;
   10041           0 :   newItem->mChildItems.SetParentHasNoXBLChildren(true);
   10042           0 :   iter.InsertItem(newItem);
   10043             : }
   10044             : 
   10045             : #ifdef DEBUG
   10046             : /**
   10047             :  * Returns true iff aFrame should be wrapped in an anonymous flex/grid item,
   10048             :  * rather than being a direct child of aContainerFrame.
   10049             :  *
   10050             :  * NOTE: aContainerFrame must be a flex or grid container - this function is
   10051             :  * purely for sanity-checking the children of these container types.
   10052             :  * NOTE: See also NeedsAnonFlexOrGridItem(), for the non-debug version of this
   10053             :  * logic (which operates a bit earlier, on FCData instead of frames).
   10054             :  */
   10055             : static bool
   10056           0 : FrameWantsToBeInAnonymousItem(const nsIFrame* aContainerFrame,
   10057             :                               const nsIFrame* aFrame)
   10058             : {
   10059           0 :   MOZ_ASSERT(::IsFlexOrGridContainer(aContainerFrame));
   10060             : 
   10061             :   // Any line-participant frames (e.g. text) definitely want to be wrapped in
   10062             :   // an anonymous flex/grid item.
   10063           0 :   if (aFrame->IsFrameOfType(nsIFrame::eLineParticipant)) {
   10064             :     return true;
   10065             :   }
   10066             : 
   10067             :   // If the container is a -webkit-{inline-}box or -moz-{inline-}box container,
   10068             :   // then placeholders also need to be wrapped, for compatibility.
   10069           0 :   if (IsFlexContainerForLegacyBox(aContainerFrame) &&
   10070           0 :       aFrame->IsPlaceholderFrame()) {
   10071             :     return true;
   10072             :   }
   10073             : 
   10074           0 :   return false;
   10075             : }
   10076             : #endif
   10077             : 
   10078             : static void
   10079         273 : VerifyGridFlexContainerChildren(nsIFrame* aParentFrame,
   10080             :                                 const nsFrameList& aChildren)
   10081             : {
   10082             : #ifdef DEBUG
   10083           0 :   if (!::IsFlexOrGridContainer(aParentFrame)) {
   10084             :     return;
   10085             :   }
   10086             : 
   10087           0 :   bool prevChildWasAnonItem = false;
   10088           0 :   for (const nsIFrame* child : aChildren) {
   10089           0 :     MOZ_ASSERT(!FrameWantsToBeInAnonymousItem(aParentFrame, child),
   10090             :                "frame wants to be inside an anonymous item, but it isn't");
   10091           0 :     if (IsAnonymousFlexOrGridItem(child)) {
   10092           0 :       AssertAnonymousFlexOrGridItemParent(child, aParentFrame);
   10093           0 :       MOZ_ASSERT(!prevChildWasAnonItem, "two anon items in a row");
   10094           0 :       nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
   10095           0 :       MOZ_ASSERT(firstWrappedChild, "anonymous item shouldn't be empty");
   10096             :       prevChildWasAnonItem = true;
   10097             :     } else {
   10098             :       prevChildWasAnonItem = false;
   10099             :     }
   10100             :   }
   10101             : #endif
   10102             : }
   10103             : 
   10104             : inline void
   10105         273 : nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aState,
   10106             :                                                    FrameConstructionItemList& aItems,
   10107             :                                                    nsContainerFrame* aParentFrame,
   10108             :                                                    bool aParentIsWrapperAnonBox,
   10109             :                                                    nsFrameItems& aFrameItems)
   10110             : {
   10111             :   // Ensure aParentIsWrapperAnonBox is correct.  We _could_ compute it directly,
   10112             :   // but it would be a bit slow, which is why we pass it from callers, who have
   10113             :   // that information offhand in many cases.
   10114         273 :   MOZ_ASSERT(ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox);
   10115             : 
   10116           0 :   CreateNeededPseudoContainers(aState, aItems, aParentFrame);
   10117         273 :   CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
   10118           0 :   CreateNeededPseudoInternalRubyBoxes(aState, aItems, aParentFrame);
   10119         273 :   CreateNeededPseudoSiblings(aState, aItems, aParentFrame);
   10120             : 
   10121           0 :   for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
   10122           0 :     NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
   10123             :                  "Needed pseudos didn't get created; expect bad things");
   10124         272 :     ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
   10125             :   }
   10126             : 
   10127           0 :   VerifyGridFlexContainerChildren(aParentFrame, aFrameItems);
   10128         273 :   NS_ASSERTION(!aState.mHavePendingPopupgroup,
   10129             :                "Should have proccessed it by now");
   10130             : 
   10131         273 :   if (aParentIsWrapperAnonBox) {
   10132           0 :     for (nsIFrame* f : aFrameItems) {
   10133           0 :       f->SetParentIsWrapperAnonBox();
   10134             :     }
   10135             :   }
   10136         273 : }
   10137             : 
   10138             : void
   10139         237 : nsCSSFrameConstructor::AddFCItemsForAnonymousContent(
   10140             :             nsFrameConstructorState& aState,
   10141             :             nsContainerFrame* aFrame,
   10142             :             nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
   10143             :             FrameConstructionItemList& aItemsToConstruct,
   10144             :             uint32_t aExtraFlags)
   10145             : {
   10146         648 :   for (uint32_t i = 0; i < aAnonymousItems.Length(); ++i) {
   10147           0 :     nsIContent* content = aAnonymousItems[i].mContent;
   10148             :     // Gecko-styled nodes should have no pending restyle flags.
   10149             :     // Assert some things about this content
   10150          87 :     MOZ_ASSERT(!(content->GetFlags() &
   10151             :                  (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME)),
   10152             :                "Should not be marked as needing frames");
   10153          87 :     MOZ_ASSERT(!content->GetPrimaryFrame(),
   10154             :                "Should have no existing frame");
   10155          87 :     MOZ_ASSERT(!content->IsComment() && !content->IsProcessingInstruction(),
   10156             :                "Why is someone creating garbage anonymous content");
   10157             : 
   10158             :     // Make sure we eagerly performed the servo cascade when the anonymous
   10159             :     // nodes were created.
   10160           0 :     MOZ_ASSERT(!content->IsElement() || content->AsElement()->HasServoData());
   10161             : 
   10162         261 :     RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(content);
   10163             : 
   10164           0 :     nsTArray<nsIAnonymousContentCreator::ContentInfo>* anonChildren = nullptr;
   10165         261 :     if (!aAnonymousItems[i].mChildren.IsEmpty()) {
   10166           0 :       anonChildren = &aAnonymousItems[i].mChildren;
   10167             :     }
   10168             : 
   10169             :     uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK |
   10170           0 :                      ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT | aExtraFlags;
   10171             : 
   10172          87 :     AddFrameConstructionItemsInternal(aState, content, aFrame,
   10173             :                                       true, computedStyle, flags,
   10174          87 :                                       anonChildren, aItemsToConstruct);
   10175             :   }
   10176         237 : }
   10177             : 
   10178             : void
   10179         214 : nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
   10180             :                                        nsIContent*              aContent,
   10181             :                                        ComputedStyle*          aComputedStyle,
   10182             :                                        nsContainerFrame*        aFrame,
   10183             :                                        const bool               aCanHaveGeneratedContent,
   10184             :                                        nsFrameItems&            aFrameItems,
   10185             :                                        const bool               aAllowBlockStyles,
   10186             :                                        PendingBinding*          aPendingBinding,
   10187             :                                        nsIFrame*                aPossiblyLeafFrame)
   10188             : {
   10189         214 :   MOZ_ASSERT(aFrame, "Must have parent frame here");
   10190           0 :   MOZ_ASSERT(aFrame->GetContentInsertionFrame() == aFrame,
   10191             :              "Parent frame in ProcessChildren should be its own "
   10192             :              "content insertion frame");
   10193             : 
   10194         214 :   const uint32_t kMaxDepth = 2 * MAX_REFLOW_DEPTH;
   10195             :   static_assert(kMaxDepth <= UINT16_MAX, "mCurrentDepth type is too narrow");
   10196           0 :   AutoRestore<uint16_t> savedDepth(mCurrentDepth);
   10197         214 :   if (mCurrentDepth != UINT16_MAX) {
   10198         214 :     ++mCurrentDepth;
   10199             :   }
   10200             : 
   10201         214 :   if (!aPossiblyLeafFrame) {
   10202          29 :     aPossiblyLeafFrame = aFrame;
   10203             :   }
   10204             : 
   10205             :   // XXXbz ideally, this would do all the pushing of various
   10206             :   // containing blocks as needed, so callers don't have to do it...
   10207             : 
   10208             :   // Check that our parent frame is a block before allowing ::first-letter/line.
   10209             :   // E.g. <button style="display:grid"> should not allow it.
   10210         229 :   const bool allowFirstPseudos = aAllowBlockStyles &&
   10211         229 :                                  nsLayoutUtils::GetAsBlock(aFrame);
   10212           0 :   bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
   10213         214 :   if (allowFirstPseudos) {
   10214             :     ShouldHaveSpecialBlockStyle(aContent, aComputedStyle, &haveFirstLetterStyle,
   10215          15 :                                 &haveFirstLineStyle);
   10216             :   }
   10217             : 
   10218           0 :   const bool isFlexOrGridContainer = ::IsFlexOrGridContainer(aFrame);
   10219             :   // The logic here needs to match the logic in GetFloatContainingBlock()
   10220             :   // (Since we already have isFlexOrGridContainer, we check that eagerly instead
   10221             :   // of letting ShouldSuppressFloatingOfDescendants look it up redundantly.)
   10222         428 :   nsFrameConstructorSaveState floatSaveState;
   10223         428 :   if (isFlexOrGridContainer ||
   10224         214 :       ShouldSuppressFloatingOfDescendants(aFrame)) {
   10225           0 :     aState.PushFloatContainingBlock(nullptr, floatSaveState);
   10226          38 :   } else if (aFrame->IsFloatContainingBlock()) {
   10227           0 :     aState.PushFloatContainingBlock(aFrame, floatSaveState);
   10228             :   }
   10229             : 
   10230             :   nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
   10231           0 :                                                            aPendingBinding);
   10232             : 
   10233         428 :   AutoFrameConstructionItemList itemsToConstruct(this);
   10234             : 
   10235             :   // If we have first-letter or first-line style then frames can get
   10236             :   // moved around so don't set these flags.
   10237         214 :   if (allowFirstPseudos && !haveFirstLetterStyle && !haveFirstLineStyle) {
   10238          15 :     itemsToConstruct.SetLineBoundaryAtStart(true);
   10239             :     itemsToConstruct.SetLineBoundaryAtEnd(true);
   10240             :   }
   10241             : 
   10242             :   // Create any anonymous frames we need here.  This must happen before the
   10243             :   // non-anonymous children are processed to ensure that popups are never
   10244             :   // constructed before the popupset.
   10245         428 :   AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
   10246         214 :   GetAnonymousContent(aContent, aPossiblyLeafFrame, anonymousItems);
   10247             : #ifdef DEBUG
   10248           0 :   for (uint32_t i = 0; i < anonymousItems.Length(); ++i) {
   10249         108 :     MOZ_ASSERT(anonymousItems[i].mContent->IsRootOfAnonymousSubtree(),
   10250             :                "Content should know it's an anonymous subtree");
   10251             :   }
   10252             : #endif
   10253             :   AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
   10254         214 :                                 itemsToConstruct);
   10255             : 
   10256         214 :   if (!aPossiblyLeafFrame->IsLeaf()) {
   10257             :     // :before/:after content should have the same style parent as normal kids.
   10258             :     //
   10259             :     // Note that we don't use this style for looking up things like special
   10260             :     // block styles because in some cases involving table pseudo-frames it has
   10261             :     // nothing to do with the parent frame's desired behavior.
   10262             :     ComputedStyle* computedStyle;
   10263             : 
   10264           0 :     if (aCanHaveGeneratedContent) {
   10265             :       computedStyle =
   10266         342 :         nsFrame::CorrectStyleParentFrame(aFrame, nullptr)->Style();
   10267             :       // Probe for generated content before
   10268           0 :       CreateGeneratedContentItem(aState, aFrame, aContent->AsElement(),
   10269             :                                  computedStyle, CSSPseudoElementType::before,
   10270         171 :                                  itemsToConstruct);
   10271             :     }
   10272             : 
   10273           0 :     const bool addChildItems = MOZ_LIKELY(mCurrentDepth < kMaxDepth);
   10274           0 :     if (!addChildItems) {
   10275           0 :       NS_WARNING("ProcessChildren max depth exceeded");
   10276             :     }
   10277             : 
   10278         342 :     InsertionPoint insertion(aFrame, nullptr);
   10279         342 :     FlattenedChildIterator iter(aContent);
   10280           0 :     for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
   10281             :       // Get the parent of the content and check if it is a XBL children element
   10282             :       // (if the content is a children element then parent != aContent because the
   10283             :       // FlattenedChildIterator will transitively iterate through <xbl:children>
   10284             :       // for default content). Push the children element as an ancestor here because
   10285             :       // it does not have a frame and would not otherwise be pushed as an ancestor.
   10286           0 :       insertion.mContainer = aContent;
   10287             : 
   10288             : 
   10289             :       // FIXME(emilio): This code can go away, child->GetFlattenedTreeParent()
   10290             :       // is always aContent, wtf.
   10291         375 :       nsIContent* parent = child->GetParent();
   10292           0 :       MOZ_ASSERT(parent, "Parent must be non-null because we are iterating children.");
   10293           0 :       if (parent != aContent && parent->IsElement()) {
   10294           0 :         insertion.mContainer = child->GetFlattenedTreeParent();
   10295          13 :         MOZ_ASSERT(insertion.mContainer == GetInsertionPoint(child).mContainer);
   10296             :       }
   10297             : 
   10298         375 :       if (addChildItems) {
   10299           0 :         AddFrameConstructionItems(aState, child, iter.XBLInvolved(), insertion,
   10300         375 :                                   itemsToConstruct);
   10301             :       } else {
   10302           0 :         ClearLazyBits(child, child->GetNextSibling());
   10303             :       }
   10304             :     }
   10305           0 :     itemsToConstruct.SetParentHasNoXBLChildren(!iter.XBLInvolved());
   10306             : 
   10307         171 :     if (aCanHaveGeneratedContent) {
   10308             :       // Probe for generated content after
   10309         171 :       CreateGeneratedContentItem(aState, aFrame, aContent->AsElement(),
   10310             :                                  computedStyle, CSSPseudoElementType::after,
   10311         171 :                                  itemsToConstruct);
   10312             :     }
   10313             :   } else {
   10314          43 :     ClearLazyBits(aContent->GetFirstChild(), nullptr);
   10315             :   }
   10316             : 
   10317             :   ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
   10318             :                               /* aParentIsWrapperAnonBox = */ false,
   10319           0 :                               aFrameItems);
   10320             : 
   10321           0 :   NS_ASSERTION(!allowFirstPseudos || !aFrame->IsXULBoxFrame(),
   10322             :                "can't be both block and box");
   10323             : 
   10324         214 :   if (haveFirstLetterStyle) {
   10325           0 :     WrapFramesInFirstLetterFrame(aFrame, aFrameItems);
   10326             :   }
   10327         214 :   if (haveFirstLineStyle) {
   10328             :     WrapFramesInFirstLineFrame(aState, aContent, aFrame, nullptr,
   10329           0 :                                aFrameItems);
   10330             :   }
   10331             : 
   10332             :   // We might end up with first-line frames that change
   10333             :   // AnyKidsNeedBlockParent() without changing itemsToConstruct, but that
   10334             :   // should never happen for cases whan aFrame->IsXULBoxFrame().
   10335         214 :   NS_ASSERTION(!haveFirstLineStyle || !aFrame->IsXULBoxFrame(),
   10336             :                "Shouldn't have first-line style if we're a box");
   10337         390 :   NS_ASSERTION(!aFrame->IsXULBoxFrame() ||
   10338             :                itemsToConstruct.AnyItemsNeedBlockParent() ==
   10339             :                  (AnyKidsNeedBlockParent(aFrameItems.FirstChild()) != nullptr),
   10340             :                "Something went awry in our block parent calculations");
   10341             : 
   10342           0 :   if (aFrame->IsXULBoxFrame() && itemsToConstruct.AnyItemsNeedBlockParent()) {
   10343             :     // XXXbz we could do this on the FrameConstructionItemList level,
   10344             :     // no?  And if we cared we could look through the item list
   10345             :     // instead of groveling through the framelist here..
   10346           0 :     ComputedStyle *frameComputedStyle = aFrame->Style();
   10347             :     // Report a warning for non-GC frames, for chrome:
   10348           0 :     if (!aFrame->IsGeneratedContentFrame() &&
   10349           0 :         mPresShell->GetPresContext()->IsChrome()) {
   10350           0 :       nsIContent *badKid = AnyKidsNeedBlockParent(aFrameItems.FirstChild());
   10351           0 :       nsDependentAtomString parentTag(aContent->NodeInfo()->NameAtom()),
   10352           0 :                             kidTag(badKid->NodeInfo()->NameAtom());
   10353           0 :       const char16_t* params[] = { parentTag.get(), kidTag.get() };
   10354           0 :       const nsStyleDisplay *display = frameComputedStyle->StyleDisplay();
   10355             :       const char *message =
   10356           0 :         (display->mDisplay == StyleDisplay::MozInlineBox)
   10357           0 :           ? "NeededToWrapXULInlineBox" : "NeededToWrapXUL";
   10358           0 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
   10359           0 :                                       NS_LITERAL_CSTRING("Layout: FrameConstructor"),
   10360           0 :                                       mDocument,
   10361             :                                       nsContentUtils::eXUL_PROPERTIES,
   10362             :                                       message,
   10363           0 :                                       params, ArrayLength(params));
   10364             :     }
   10365             : 
   10366           3 :     RefPtr<ComputedStyle> blockSC = mPresShell->StyleSet()->
   10367           9 :       ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::mozXULAnonymousBlock,
   10368           0 :                                          frameComputedStyle);
   10369           3 :     nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
   10370             :     // We might, in theory, want to set NS_BLOCK_FLOAT_MGR and
   10371             :     // NS_BLOCK_MARGIN_ROOT, but I think it's a bad idea given that
   10372             :     // a real block placed here wouldn't get those set on it.
   10373             : 
   10374           0 :     InitAndRestoreFrame(aState, aContent, aFrame, blockFrame, false);
   10375             : 
   10376           0 :     NS_ASSERTION(!blockFrame->HasView(), "need to do view reparenting");
   10377           3 :     ReparentFrames(this, blockFrame, aFrameItems, false);
   10378             : 
   10379           0 :     blockFrame->SetInitialChildList(kPrincipalList, aFrameItems);
   10380           3 :     NS_ASSERTION(aFrameItems.IsEmpty(), "How did that happen?");
   10381           0 :     aFrameItems.Clear();
   10382           3 :     aFrameItems.AddChild(blockFrame);
   10383             : 
   10384           6 :     aFrame->AddStateBits(NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK);
   10385           3 :     MOZ_ASSERT(!aFrame->IsLeaf(),
   10386             :                "Why do we have an nsLeafBoxFrame here?");
   10387           6 :     aFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
   10388             :   }
   10389         214 : }
   10390             : 
   10391             : //----------------------------------------------------------------------
   10392             : 
   10393             : // Support for :first-line style
   10394             : 
   10395             : // Special routine to handle placing a list of frames into a block
   10396             : // frame that has first-line style. The routine ensures that the first
   10397             : // collection of inline frames end up in a first-line frame.
   10398             : // NOTE: aState may have containing block information related to a
   10399             : // different part of the frame tree than where the first line occurs.
   10400             : // In particular aState may be set up for where ContentInserted or
   10401             : // ContentAppended is inserting content, which may be some
   10402             : // non-first-in-flow continuation of the block to which the first-line
   10403             : // belongs. So this function needs to be careful about how it uses
   10404             : // aState.
   10405             : void
   10406           0 : nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
   10407             :   nsFrameConstructorState& aState,
   10408             :   nsIContent*              aBlockContent,
   10409             :   nsContainerFrame*        aBlockFrame,
   10410             :   nsFirstLineFrame*        aLineFrame,
   10411             :   nsFrameItems&            aFrameItems)
   10412             : {
   10413             :   // Find the part of aFrameItems that we want to put in the first-line
   10414           0 :   nsFrameList::FrameLinkEnumerator link(aFrameItems);
   10415           0 :   while (!link.AtEnd() && link.NextFrame()->IsInlineOutside()) {
   10416           0 :     link.Next();
   10417             :   }
   10418             : 
   10419           0 :   nsFrameList firstLineChildren = aFrameItems.ExtractHead(link);
   10420             : 
   10421           0 :   if (firstLineChildren.IsEmpty()) {
   10422             :     // Nothing is supposed to go into the first-line; nothing to do
   10423           0 :     return;
   10424             :   }
   10425             : 
   10426           0 :   if (!aLineFrame) {
   10427             :     // Create line frame
   10428             :     ComputedStyle* parentStyle =
   10429             :       nsFrame::CorrectStyleParentFrame(aBlockFrame,
   10430             :                                        nsCSSPseudoElements::firstLine)->
   10431           0 :         Style();
   10432           0 :     RefPtr<ComputedStyle> firstLineStyle = GetFirstLineStyle(aBlockContent,
   10433           0 :                                                                 parentStyle);
   10434             : 
   10435           0 :     aLineFrame = NS_NewFirstLineFrame(mPresShell, firstLineStyle);
   10436             : 
   10437             :     // Initialize the line frame
   10438           0 :     InitAndRestoreFrame(aState, aBlockContent, aBlockFrame, aLineFrame);
   10439             : 
   10440             :     // The lineFrame will be the block's first child; the rest of the
   10441             :     // frame list (after lastInlineFrame) will be the second and
   10442             :     // subsequent children; insert lineFrame into aFrameItems.
   10443           0 :     aFrameItems.InsertFrame(nullptr, nullptr, aLineFrame);
   10444             : 
   10445           0 :     NS_ASSERTION(aLineFrame->Style() == firstLineStyle,
   10446             :                  "Bogus style on line frame");
   10447             :   }
   10448             : 
   10449             :   // Give the inline frames to the lineFrame <b>after</b> reparenting them
   10450           0 :   ReparentFrames(this, aLineFrame, firstLineChildren, true);
   10451           0 :   if (aLineFrame->PrincipalChildList().IsEmpty() &&
   10452           0 :       (aLineFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
   10453           0 :     aLineFrame->SetInitialChildList(kPrincipalList, firstLineChildren);
   10454             :   } else {
   10455           0 :     AppendFrames(aLineFrame, kPrincipalList, firstLineChildren);
   10456             :   }
   10457             : }
   10458             : 
   10459             : // Special routine to handle appending a new frame to a block frame's
   10460             : // child list. Takes care of placing the new frame into the right
   10461             : // place when first-line style is present.
   10462             : void
   10463           0 : nsCSSFrameConstructor::AppendFirstLineFrames(
   10464             :   nsFrameConstructorState& aState,
   10465             :   nsIContent*              aBlockContent,
   10466             :   nsContainerFrame*        aBlockFrame,
   10467             :   nsFrameItems&            aFrameItems)
   10468             : {
   10469             :   // It's possible that aBlockFrame needs to have a first-line frame
   10470             :   // created because it doesn't currently have any children.
   10471           0 :   const nsFrameList& blockKids = aBlockFrame->PrincipalChildList();
   10472           0 :   if (blockKids.IsEmpty()) {
   10473             :     WrapFramesInFirstLineFrame(aState, aBlockContent,
   10474           0 :                                aBlockFrame, nullptr, aFrameItems);
   10475           0 :     return;
   10476             :   }
   10477             : 
   10478             :   // Examine the last block child - if it's a first-line frame then
   10479             :   // appended frames need special treatment.
   10480           0 :   nsIFrame* lastBlockKid = blockKids.LastChild();
   10481           0 :   if (!lastBlockKid->IsLineFrame()) {
   10482             :     // No first-line frame at the end of the list, therefore there is
   10483             :     // an intervening block between any first-line frame the frames
   10484             :     // we are appending. Therefore, we don't need any special
   10485             :     // treatment of the appended frames.
   10486             :     return;
   10487             :   }
   10488             : 
   10489           0 :   nsFirstLineFrame* lineFrame = static_cast<nsFirstLineFrame*>(lastBlockKid);
   10490             :   WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame,
   10491           0 :                              lineFrame, aFrameItems);
   10492             : }
   10493             : 
   10494             : void
   10495           0 : nsCSSFrameConstructor::CheckForFirstLineInsertion(nsIFrame* aParentFrame,
   10496             :                                                   nsFrameItems& aFrameItems)
   10497             : {
   10498           0 :   MOZ_ASSERT(aParentFrame->Style()->HasPseudoElementData(),
   10499             :              "Why were we called?");
   10500             : 
   10501           0 :   if (aFrameItems.IsEmpty()) {
   10502             :     // Happens often enough, with the caption stuff.  No need to do the ancestor
   10503             :     // walk here.
   10504             :     return;
   10505             :   }
   10506             : 
   10507           0 :   class RestyleManager* restyleManager = RestyleManager();
   10508             : 
   10509             :   // Check whether there's a ::first-line on the path up from aParentFrame.
   10510             :   // Note that we can't stop until we've run out of ancestors with
   10511             :   // pseudo-element data, because the first-letter might be somewhere way up the
   10512             :   // tree; in particular it might be past our containing block.
   10513           0 :   nsIFrame* ancestor = aParentFrame;
   10514           0 :   while (ancestor) {
   10515           0 :     if (!ancestor->Style()->HasPseudoElementData()) {
   10516             :       // We know we won't find a ::first-line now.
   10517             :       return;
   10518             :     }
   10519             : 
   10520           0 :     if (!ancestor->IsLineFrame()) {
   10521           0 :       ancestor = ancestor->GetParent();
   10522             :       continue;
   10523             :     }
   10524             : 
   10525           0 :     if (!ancestor->Style()->IsPseudoElement()) {
   10526             :       // This is a continuation lineframe, not the first line; no need to do
   10527             :       // anything to the styles.
   10528             :       return;
   10529             :     }
   10530             : 
   10531             :     // Fix up the styles of aFrameItems for ::first-line.
   10532           0 :     for (nsIFrame* f : aFrameItems) {
   10533           0 :       restyleManager->ReparentComputedStyleForFirstLine(f);
   10534             :     }
   10535           0 :     return;
   10536             :   }
   10537             : }
   10538             : 
   10539             : //----------------------------------------------------------------------
   10540             : 
   10541             : // First-letter support
   10542             : 
   10543             : // Determine how many characters in the text fragment apply to the
   10544             : // first letter
   10545             : static int32_t
   10546           0 : FirstLetterCount(const nsTextFragment* aFragment)
   10547             : {
   10548           0 :   int32_t count = 0;
   10549           0 :   int32_t firstLetterLength = 0;
   10550             : 
   10551           0 :   int32_t i, n = aFragment->GetLength();
   10552           0 :   for (i = 0; i < n; i++) {
   10553           0 :     char16_t ch = aFragment->CharAt(i);
   10554             :     // FIXME: take content language into account when deciding whitespace.
   10555           0 :     if (dom::IsSpaceCharacter(ch)) {
   10556           0 :       if (firstLetterLength) {
   10557             :         break;
   10558             :       }
   10559           0 :       count++;
   10560           0 :       continue;
   10561             :     }
   10562             :     // XXX I18n
   10563           0 :     if ((ch == '\'') || (ch == '\"')) {
   10564           0 :       if (firstLetterLength) {
   10565             :         break;
   10566             :       }
   10567             :       // keep looping
   10568             :       firstLetterLength = 1;
   10569             :     }
   10570             :     else {
   10571           0 :       count++;
   10572           0 :       break;
   10573             :     }
   10574             :   }
   10575             : 
   10576           0 :   return count;
   10577             : }
   10578             : 
   10579             : static bool
   10580           0 : NeedFirstLetterContinuation(nsIContent* aContent)
   10581             : {
   10582           0 :   MOZ_ASSERT(aContent, "null ptr");
   10583             : 
   10584           0 :   bool result = false;
   10585           0 :   if (aContent) {
   10586           0 :     const nsTextFragment* frag = aContent->GetText();
   10587           0 :     if (frag) {
   10588           0 :       int32_t flc = FirstLetterCount(frag);
   10589           0 :       int32_t tl = frag->GetLength();
   10590           0 :       if (flc < tl) {
   10591           0 :         result = true;
   10592             :       }
   10593             :     }
   10594             :   }
   10595           0 :   return result;
   10596             : }
   10597             : 
   10598           0 : static bool IsFirstLetterContent(nsIContent* aContent)
   10599             : {
   10600           0 :   return aContent->TextLength() &&
   10601           0 :          !aContent->TextIsOnlyWhitespace();
   10602             : }
   10603             : 
   10604             : /**
   10605             :  * Create a letter frame, only make it a floating frame.
   10606             :  */
   10607             : nsFirstLetterFrame*
   10608           0 : nsCSSFrameConstructor::CreateFloatingLetterFrame(
   10609             :   nsFrameConstructorState& aState,
   10610             :   nsIContent* aTextContent,
   10611             :   nsIFrame* aTextFrame,
   10612             :   nsContainerFrame* aParentFrame,
   10613             :   ComputedStyle* aParentComputedStyle,
   10614             :   ComputedStyle* aComputedStyle,
   10615             :   nsFrameItems& aResult)
   10616             : {
   10617           0 :   MOZ_ASSERT(aParentComputedStyle);
   10618             : 
   10619             :   nsFirstLetterFrame* letterFrame =
   10620           0 :     NS_NewFirstLetterFrame(mPresShell, aComputedStyle);
   10621             :   // We don't want to use a text content for a non-text frame (because we want
   10622             :   // its primary frame to be a text frame).
   10623           0 :   nsIContent* letterContent = aParentFrame->GetContent();
   10624           0 :   nsContainerFrame* containingBlock = aState.GetGeometricParent(
   10625           0 :     aComputedStyle->StyleDisplay(), aParentFrame);
   10626           0 :   InitAndRestoreFrame(aState, letterContent, containingBlock, letterFrame);
   10627             : 
   10628             :   // Init the text frame to refer to the letter frame.
   10629             :   //
   10630             :   // Make sure we get a proper style for it (the one passed in is for the letter
   10631             :   // frame and will have the float property set on it; the text frame shouldn't
   10632             :   // have that set).
   10633           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet();
   10634             :   RefPtr<ComputedStyle> textSC = styleSet->
   10635           0 :     ResolveStyleForText(aTextContent, aComputedStyle);
   10636           0 :   aTextFrame->SetComputedStyleWithoutNotification(textSC);
   10637           0 :   InitAndRestoreFrame(aState, aTextContent, letterFrame, aTextFrame);
   10638             : 
   10639             :   // And then give the text frame to the letter frame
   10640           0 :   SetInitialSingleChild(letterFrame, aTextFrame);
   10641             : 
   10642             :   // See if we will need to continue the text frame (does it contain
   10643             :   // more than just the first-letter text or not?) If it does, then we
   10644             :   // create (in advance) a continuation frame for it.
   10645           0 :   nsIFrame* nextTextFrame = nullptr;
   10646           0 :   if (NeedFirstLetterContinuation(aTextContent)) {
   10647             :     // Create continuation
   10648             :     nextTextFrame =
   10649           0 :       CreateContinuingFrame(aState.mPresContext, aTextFrame, aParentFrame);
   10650             :     RefPtr<ComputedStyle> newSC = styleSet->
   10651           0 :       ResolveStyleForText(aTextContent, aParentComputedStyle);
   10652           0 :     nextTextFrame->SetComputedStyle(newSC);
   10653             :   }
   10654             : 
   10655           0 :   NS_ASSERTION(aResult.IsEmpty(), "aResult should be an empty nsFrameItems!");
   10656             :   // Put the new float before any of the floats in the block we're doing
   10657             :   // first-letter for, that is, before any floats whose parent is
   10658             :   // containingBlock.
   10659           0 :   nsFrameList::FrameLinkEnumerator link(aState.mFloatedItems);
   10660           0 :   while (!link.AtEnd() && link.NextFrame()->GetParent() != containingBlock) {
   10661           0 :     link.Next();
   10662             :   }
   10663             : 
   10664           0 :   aState.AddChild(letterFrame, aResult, letterContent, aParentFrame,
   10665           0 :                   false, true, false, true, link.PrevFrame());
   10666             : 
   10667           0 :   if (nextTextFrame) {
   10668           0 :     aResult.AddChild(nextTextFrame);
   10669             :   }
   10670             : 
   10671           0 :   return letterFrame;
   10672             : }
   10673             : 
   10674             : /**
   10675             :  * Create a new letter frame for aTextFrame. The letter frame will be
   10676             :  * a child of aParentFrame.
   10677             :  */
   10678             : void
   10679           0 : nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame,
   10680             :                                          nsContainerFrame* aBlockContinuation,
   10681             :                                          nsIContent* aTextContent,
   10682             :                                          nsContainerFrame* aParentFrame,
   10683             :                                          nsFrameItems& aResult)
   10684             : {
   10685           0 :   MOZ_ASSERT(aTextContent->IsText(), "aTextContent isn't text");
   10686           0 :   NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
   10687             :                  "Not a block frame?");
   10688             : 
   10689             :   // Get a ComputedStyle for the first-letter-frame.
   10690             :   //
   10691             :   // Keep this in sync with nsBlockFrame::UpdatePseudoElementStyles.
   10692             :   nsIFrame* parentFrame =
   10693           0 :     nsFrame::CorrectStyleParentFrame(aParentFrame,
   10694           0 :                                      nsCSSPseudoElements::firstLetter);
   10695             : 
   10696           0 :   ComputedStyle* parentComputedStyle = parentFrame->Style();
   10697             : 
   10698             :   // Use content from containing block so that we can actually
   10699             :   // find a matching style rule.
   10700           0 :   nsIContent* blockContent = aBlockFrame->GetContent();
   10701             : 
   10702             :   // Create first-letter style rule
   10703             :   RefPtr<ComputedStyle> sc =
   10704           0 :     GetFirstLetterStyle(blockContent, parentComputedStyle);
   10705             : 
   10706           0 :   if (sc) {
   10707           0 :     if (parentFrame->IsLineFrame()) {
   10708             :       nsIFrame* parentIgnoringFirstLine =
   10709           0 :         nsFrame::CorrectStyleParentFrame(aBlockFrame,
   10710           0 :                                          nsCSSPseudoElements::firstLetter);
   10711             : 
   10712             :       sc =
   10713           0 :         mPresShell->StyleSet()->ReparentComputedStyle(
   10714             :           sc,
   10715             :           parentComputedStyle,
   10716             :           parentIgnoringFirstLine->Style(),
   10717             :           parentComputedStyle,
   10718           0 :           blockContent->AsElement());
   10719             :     }
   10720             : 
   10721           0 :     RefPtr<ComputedStyle> textSC = mPresShell->StyleSet()->
   10722           0 :       ResolveStyleForText(aTextContent, sc);
   10723             : 
   10724             :     // Create a new text frame (the original one will be discarded)
   10725             :     // pass a temporary stylecontext, the correct one will be set
   10726             :     // later.  Start off by unsetting the primary frame for
   10727             :     // aTextContent, so it's no longer pointing to the to-be-destroyed
   10728             :     // frame.
   10729             :     // XXXbz it would be really nice to destroy the old frame _first_,
   10730             :     // then create the new one, so we could avoid this hack.
   10731           0 :     aTextContent->SetPrimaryFrame(nullptr);
   10732           0 :     nsIFrame* textFrame = NS_NewTextFrame(mPresShell, textSC);
   10733             : 
   10734           0 :     NS_ASSERTION(aBlockContinuation == GetFloatContainingBlock(aParentFrame),
   10735             :                  "Containing block is confused");
   10736             :     nsFrameConstructorState state(mPresShell,
   10737             :                                   GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
   10738             :                                   GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
   10739           0 :                                   aBlockContinuation);
   10740             : 
   10741             :     // Create the right type of first-letter frame
   10742           0 :     const nsStyleDisplay* display = sc->StyleDisplay();
   10743             :     nsFirstLetterFrame* letterFrame;
   10744           0 :     if (display->IsFloatingStyle() &&
   10745           0 :         !nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
   10746             :       // Make a floating first-letter frame
   10747           0 :       letterFrame = CreateFloatingLetterFrame(state, aTextContent, textFrame,
   10748             :                                               aParentFrame, parentComputedStyle,
   10749           0 :                                               sc, aResult);
   10750             :     }
   10751             :     else {
   10752             :       // Make an inflow first-letter frame
   10753           0 :       letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
   10754             : 
   10755             :       // Initialize the first-letter-frame.  We don't want to use a text
   10756             :       // content for a non-text frame (because we want its primary frame to
   10757             :       // be a text frame).
   10758           0 :       nsIContent* letterContent = aParentFrame->GetContent();
   10759           0 :       letterFrame->Init(letterContent, aParentFrame, nullptr);
   10760             : 
   10761           0 :       InitAndRestoreFrame(state, aTextContent, letterFrame, textFrame);
   10762             : 
   10763           0 :       SetInitialSingleChild(letterFrame, textFrame);
   10764           0 :       aResult.Clear();
   10765           0 :       aResult.AddChild(letterFrame);
   10766           0 :       NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),
   10767             :                    "should have the first continuation here");
   10768           0 :       aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
   10769             :     }
   10770           0 :     MOZ_ASSERT(!aBlockFrame->GetPrevContinuation(),
   10771             :                "Setting up a first-letter frame on a non-first block continuation?");
   10772           0 :     auto parent = static_cast<nsContainerFrame*>(aParentFrame->FirstContinuation());
   10773           0 :     parent->SetHasFirstLetterChild();
   10774           0 :     aBlockFrame->SetProperty(nsContainerFrame::FirstLetterProperty(),
   10775           0 :                              letterFrame);
   10776           0 :     aTextContent->SetPrimaryFrame(textFrame);
   10777             :   }
   10778           0 : }
   10779             : 
   10780             : void
   10781           0 : nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
   10782             :   nsContainerFrame*        aBlockFrame,
   10783             :   nsFrameItems&            aBlockFrames)
   10784             : {
   10785           0 :   aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
   10786             : 
   10787           0 :   nsContainerFrame* parentFrame = nullptr;
   10788           0 :   nsIFrame* textFrame = nullptr;
   10789           0 :   nsIFrame* prevFrame = nullptr;
   10790           0 :   nsFrameItems letterFrames;
   10791           0 :   bool stopLooking = false;
   10792           0 :   WrapFramesInFirstLetterFrame(aBlockFrame, aBlockFrame, aBlockFrame,
   10793             :                                aBlockFrames.FirstChild(),
   10794             :                                &parentFrame, &textFrame, &prevFrame,
   10795           0 :                                letterFrames, &stopLooking);
   10796           0 :   if (parentFrame) {
   10797           0 :     if (parentFrame == aBlockFrame) {
   10798             :       // Take textFrame out of the block's frame list and substitute the
   10799             :       // letter frame(s) instead.
   10800           0 :       aBlockFrames.DestroyFrame(textFrame);
   10801           0 :       aBlockFrames.InsertFrames(nullptr, prevFrame, letterFrames);
   10802             :     }
   10803             :     else {
   10804             :       // Take the old textFrame out of the inline parent's child list
   10805           0 :       RemoveFrame(kPrincipalList, textFrame);
   10806             : 
   10807             :       // Insert in the letter frame(s)
   10808           0 :       parentFrame->InsertFrames(kPrincipalList, prevFrame, letterFrames);
   10809             :     }
   10810             :   }
   10811           0 : }
   10812             : 
   10813             : void
   10814           0 : nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
   10815             :   nsContainerFrame*        aBlockFrame,
   10816             :   nsContainerFrame*        aBlockContinuation,
   10817             :   nsContainerFrame*        aParentFrame,
   10818             :   nsIFrame*                aParentFrameList,
   10819             :   nsContainerFrame**       aModifiedParent,
   10820             :   nsIFrame**               aTextFrame,
   10821             :   nsIFrame**               aPrevFrame,
   10822             :   nsFrameItems&            aLetterFrames,
   10823             :   bool*                    aStopLooking)
   10824             : {
   10825           0 :   nsIFrame* prevFrame = nullptr;
   10826           0 :   nsIFrame* frame = aParentFrameList;
   10827             : 
   10828           0 :   while (frame) {
   10829           0 :     nsIFrame* nextFrame = frame->GetNextSibling();
   10830             : 
   10831           0 :     LayoutFrameType frameType = frame->Type();
   10832           0 :     if (LayoutFrameType::Text == frameType) {
   10833             :       // Wrap up first-letter content in a letter frame
   10834           0 :       nsIContent* textContent = frame->GetContent();
   10835           0 :       if (IsFirstLetterContent(textContent)) {
   10836             :         // Create letter frame to wrap up the text
   10837             :         CreateLetterFrame(aBlockFrame, aBlockContinuation, textContent,
   10838           0 :                           aParentFrame, aLetterFrames);
   10839             : 
   10840             :         // Provide adjustment information for parent
   10841           0 :         *aModifiedParent = aParentFrame;
   10842           0 :         *aTextFrame = frame;
   10843           0 :         *aPrevFrame = prevFrame;
   10844           0 :         *aStopLooking = true;
   10845           0 :         return;
   10846             :       }
   10847           0 :     } else if (IsInlineFrame(frame) && frameType != LayoutFrameType::Br) {
   10848           0 :       nsIFrame* kids = frame->PrincipalChildList().FirstChild();
   10849             :       WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation,
   10850             :                                    static_cast<nsContainerFrame*>(frame),
   10851             :                                    kids, aModifiedParent, aTextFrame,
   10852           0 :                                    aPrevFrame, aLetterFrames, aStopLooking);
   10853           0 :       if (*aStopLooking) {
   10854             :         return;
   10855             :       }
   10856             :     }
   10857             :     else {
   10858             :       // This will stop us looking to create more letter frames. For
   10859             :       // example, maybe the frame-type is "letterFrame" or
   10860             :       // "placeholderFrame". This keeps us from creating extra letter
   10861             :       // frames, and also prevents us from creating letter frames when
   10862             :       // the first real content child of a block is not text (e.g. an
   10863             :       // image, hr, etc.)
   10864           0 :       *aStopLooking = true;
   10865           0 :       break;
   10866             :     }
   10867             : 
   10868             :     prevFrame = frame;
   10869             :     frame = nextFrame;
   10870             :   }
   10871             : }
   10872             : 
   10873             : static nsIFrame*
   10874           0 : FindFirstLetterFrame(nsIFrame* aFrame, nsIFrame::ChildListID aListID)
   10875             : {
   10876           0 :   nsFrameList list = aFrame->GetChildList(aListID);
   10877           0 :   for (nsFrameList::Enumerator e(list); !e.AtEnd(); e.Next()) {
   10878           0 :     if (e.get()->IsLetterFrame()) {
   10879           0 :       return e.get();
   10880             :     }
   10881             :   }
   10882           0 :   return nullptr;
   10883             : }
   10884             : 
   10885             : void
   10886           0 : nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
   10887             :   nsIPresShell* aPresShell,
   10888             :   nsIFrame* aBlockFrame)
   10889             : {
   10890             :   // Look for the first letter frame on the kFloatList, then kPushedFloatsList.
   10891             :   nsIFrame* floatFrame =
   10892           0 :     ::FindFirstLetterFrame(aBlockFrame, nsIFrame::kFloatList);
   10893           0 :   if (!floatFrame) {
   10894             :     floatFrame =
   10895           0 :       ::FindFirstLetterFrame(aBlockFrame, nsIFrame::kPushedFloatsList);
   10896           0 :     if (!floatFrame) {
   10897           0 :       return;
   10898             :     }
   10899             :   }
   10900             : 
   10901             :   // Take the text frame away from the letter frame (so it isn't
   10902             :   // destroyed when we destroy the letter frame).
   10903           0 :   nsIFrame* textFrame = floatFrame->PrincipalChildList().FirstChild();
   10904           0 :   if (!textFrame) {
   10905             :     return;
   10906             :   }
   10907             : 
   10908             :   // Discover the placeholder frame for the letter frame
   10909           0 :   nsPlaceholderFrame* placeholderFrame = floatFrame->GetPlaceholderFrame();
   10910           0 :   if (!placeholderFrame) {
   10911             :     // Somethings really wrong
   10912             :     return;
   10913             :   }
   10914           0 :   nsContainerFrame* parentFrame = placeholderFrame->GetParent();
   10915           0 :   if (!parentFrame) {
   10916             :     // Somethings really wrong
   10917             :     return;
   10918             :   }
   10919           0 :   static_cast<nsContainerFrame*>(parentFrame->FirstContinuation())->
   10920           0 :     ClearHasFirstLetterChild();
   10921             : 
   10922             :   // Create a new text frame with the right style that maps all of the content
   10923             :   // that was previously part of the letter frame (and probably continued
   10924             :   // elsewhere).
   10925           0 :   ComputedStyle* parentSC = parentFrame->Style();
   10926           0 :   nsIContent* textContent = textFrame->GetContent();
   10927           0 :   if (!textContent) {
   10928             :     return;
   10929             :   }
   10930             :   RefPtr<ComputedStyle> newSC = aPresShell->StyleSet()->
   10931           0 :     ResolveStyleForText(textContent, parentSC);
   10932           0 :   nsIFrame* newTextFrame = NS_NewTextFrame(aPresShell, newSC);
   10933           0 :   newTextFrame->Init(textContent, parentFrame, nullptr);
   10934             : 
   10935             :   // Destroy the old text frame's continuations (the old text frame
   10936             :   // will be destroyed when its letter frame is destroyed).
   10937           0 :   nsIFrame* frameToDelete = textFrame->LastContinuation();
   10938           0 :   while (frameToDelete != textFrame) {
   10939           0 :     nsIFrame* nextFrameToDelete = frameToDelete->GetPrevContinuation();
   10940           0 :     RemoveFrame(kPrincipalList, frameToDelete);
   10941           0 :     frameToDelete = nextFrameToDelete;
   10942             :   }
   10943             : 
   10944           0 :   nsIFrame* prevSibling = placeholderFrame->GetPrevSibling();
   10945             : 
   10946             :   // Now that everything is set...
   10947             : #ifdef NOISY_FIRST_LETTER
   10948             :   printf("RemoveFloatingFirstLetterFrames: textContent=%p oldTextFrame=%p newTextFrame=%p\n",
   10949             :          textContent.get(), textFrame, newTextFrame);
   10950             : #endif
   10951             : 
   10952             :   // Remove placeholder frame and the float
   10953           0 :   RemoveFrame(kPrincipalList, placeholderFrame);
   10954             : 
   10955             :   // Now that the old frames are gone, we can start pointing to our
   10956             :   // new primary frame.
   10957           0 :   textContent->SetPrimaryFrame(newTextFrame);
   10958             : 
   10959             :   // Wallpaper bug 822910.
   10960           0 :   bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
   10961           0 :   if (offsetsNeedFixing) {
   10962             :     prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
   10963             :   }
   10964             : 
   10965             :   // Insert text frame in its place
   10966           0 :   nsFrameList textList(newTextFrame, newTextFrame);
   10967           0 :   InsertFrames(parentFrame, kPrincipalList, prevSibling, textList);
   10968             : 
   10969           0 :   if (offsetsNeedFixing) {
   10970             :     prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
   10971             :   }
   10972             : }
   10973             : 
   10974             : void
   10975           0 : nsCSSFrameConstructor::RemoveFirstLetterFrames(nsIPresShell* aPresShell,
   10976             :                                                nsContainerFrame* aFrame,
   10977             :                                                nsContainerFrame* aBlockFrame,
   10978             :                                                bool* aStopLooking)
   10979             : {
   10980           0 :   nsIFrame* prevSibling = nullptr;
   10981           0 :   nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
   10982             : 
   10983           0 :   while (kid) {
   10984           0 :     if (kid->IsLetterFrame()) {
   10985             :       // Bingo. Found it. First steal away the text frame.
   10986           0 :       static_cast<nsContainerFrame*>(aFrame->FirstContinuation())->
   10987           0 :         ClearHasFirstLetterChild();
   10988           0 :       nsIFrame* textFrame = kid->PrincipalChildList().FirstChild();
   10989           0 :       if (!textFrame) {
   10990             :         break;
   10991             :       }
   10992             : 
   10993             :       // Create a new textframe
   10994           0 :       ComputedStyle* parentSC = aFrame->Style();
   10995           0 :       if (!parentSC) {
   10996             :         break;
   10997             :       }
   10998           0 :       nsIContent* textContent = textFrame->GetContent();
   10999           0 :       if (!textContent) {
   11000             :         break;
   11001             :       }
   11002             :       RefPtr<ComputedStyle> newSC = aPresShell->StyleSet()->
   11003           0 :         ResolveStyleForText(textContent, parentSC);
   11004           0 :       textFrame = NS_NewTextFrame(aPresShell, newSC);
   11005           0 :       textFrame->Init(textContent, aFrame, nullptr);
   11006             : 
   11007             :       // Next rip out the kid and replace it with the text frame
   11008           0 :       RemoveFrame(kPrincipalList, kid);
   11009             : 
   11010             :       // Now that the old frames are gone, we can start pointing to our
   11011             :       // new primary frame.
   11012           0 :       textContent->SetPrimaryFrame(textFrame);
   11013             : 
   11014             :       // Wallpaper bug 822910.
   11015           0 :       bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
   11016           0 :       if (offsetsNeedFixing) {
   11017             :         prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
   11018             :       }
   11019             : 
   11020             :       // Insert text frame in its place
   11021           0 :       nsFrameList textList(textFrame, textFrame);
   11022           0 :       InsertFrames(aFrame, kPrincipalList, prevSibling, textList);
   11023             : 
   11024           0 :       if (offsetsNeedFixing) {
   11025             :         prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
   11026             :       }
   11027             : 
   11028           0 :       *aStopLooking = true;
   11029           0 :       NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),
   11030             :                    "should have the first continuation here");
   11031           0 :       aBlockFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
   11032             :       break;
   11033             :     }
   11034           0 :     else if (IsInlineFrame(kid)) {
   11035           0 :       nsContainerFrame* kidAsContainerFrame = do_QueryFrame(kid);
   11036           0 :       if (kidAsContainerFrame) {
   11037             :         // Look inside child inline frame for the letter frame.
   11038             :         RemoveFirstLetterFrames(aPresShell, kidAsContainerFrame,
   11039           0 :                                 aBlockFrame, aStopLooking);
   11040           0 :         if (*aStopLooking) {
   11041             :           break;
   11042             :         }
   11043             :       }
   11044             :     }
   11045           0 :     prevSibling = kid;
   11046           0 :     kid = kid->GetNextSibling();
   11047             :   }
   11048           0 : }
   11049             : 
   11050             : void
   11051           0 : nsCSSFrameConstructor::RemoveLetterFrames(nsIPresShell* aPresShell,
   11052             :                                           nsContainerFrame* aBlockFrame)
   11053             : {
   11054             :   aBlockFrame =
   11055           0 :     static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
   11056           0 :   aBlockFrame->RemoveProperty(nsContainerFrame::FirstLetterProperty());
   11057           0 :   nsContainerFrame* continuation = aBlockFrame;
   11058             : 
   11059           0 :   bool stopLooking = false;
   11060             :   do {
   11061           0 :     RemoveFloatingFirstLetterFrames(aPresShell, continuation);
   11062             :     RemoveFirstLetterFrames(aPresShell, continuation, aBlockFrame,
   11063           0 :                             &stopLooking);
   11064           0 :     if (stopLooking) {
   11065             :       break;
   11066             :     }
   11067             :     continuation =
   11068           0 :       static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
   11069           0 :   }  while (continuation);
   11070           0 : }
   11071             : 
   11072             : // Fixup the letter frame situation for the given block
   11073             : void
   11074           0 : nsCSSFrameConstructor::RecoverLetterFrames(nsContainerFrame* aBlockFrame)
   11075             : {
   11076             :   aBlockFrame =
   11077           0 :     static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
   11078           0 :   nsContainerFrame* continuation = aBlockFrame;
   11079             : 
   11080           0 :   nsContainerFrame* parentFrame = nullptr;
   11081           0 :   nsIFrame* textFrame = nullptr;
   11082           0 :   nsIFrame* prevFrame = nullptr;
   11083           0 :   nsFrameItems letterFrames;
   11084           0 :   bool stopLooking = false;
   11085             :   do {
   11086             :     // XXX shouldn't this bit be set already (bug 408493), assert instead?
   11087           0 :     continuation->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
   11088           0 :     WrapFramesInFirstLetterFrame(aBlockFrame, continuation, continuation,
   11089           0 :                                  continuation->PrincipalChildList().FirstChild(),
   11090             :                                  &parentFrame, &textFrame, &prevFrame,
   11091           0 :                                  letterFrames, &stopLooking);
   11092           0 :     if (stopLooking) {
   11093             :       break;
   11094             :     }
   11095             :     continuation =
   11096           0 :       static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
   11097           0 :   } while (continuation);
   11098             : 
   11099           0 :   if (parentFrame) {
   11100             :     // Take the old textFrame out of the parent's child list
   11101           0 :     RemoveFrame(kPrincipalList, textFrame);
   11102             : 
   11103             :     // Insert in the letter frame(s)
   11104           0 :     parentFrame->InsertFrames(kPrincipalList, prevFrame, letterFrames);
   11105             :   }
   11106           0 : }
   11107             : 
   11108             : //----------------------------------------------------------------------
   11109             : 
   11110             : // listbox Widget Routines
   11111             : 
   11112             : void
   11113           0 : nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame*      aParentFrame,
   11114             :                                             nsIFrame*              aPrevFrame,
   11115             :                                             nsIContent*            aChild,
   11116             :                                             nsIFrame**             aNewFrame,
   11117             :                                             bool                   aIsAppend)
   11118             : {
   11119             : #ifdef MOZ_XUL
   11120             :   // Construct a new frame
   11121           0 :   if (aParentFrame) {
   11122           0 :     nsFrameItems            frameItems;
   11123             :     nsFrameConstructorState state(mPresShell,
   11124             :                                   GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
   11125             :                                   GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
   11126             :                                   GetFloatContainingBlock(aParentFrame),
   11127           0 :                                   do_AddRef(mTempFrameTreeState));
   11128             : 
   11129           0 :     if (aChild->IsElement() && !aChild->AsElement()->HasServoData()) {
   11130           0 :       mPresShell->StyleSet()->StyleNewSubtree(aChild->AsElement());
   11131             :     }
   11132             : 
   11133           0 :     RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aChild);
   11134             : 
   11135             :     // Pre-check for display "none" - only if we find that, do we create
   11136             :     // any frame at all
   11137           0 :     const nsStyleDisplay* display = computedStyle->StyleDisplay();
   11138             : 
   11139           0 :     if (StyleDisplay::None == display->mDisplay) {
   11140           0 :       *aNewFrame = nullptr;
   11141           0 :       return;
   11142             :     }
   11143             : 
   11144           0 :     AutoFrameConstructionItemList items(this);
   11145           0 :     AddFrameConstructionItemsInternal(state, aChild, aParentFrame,
   11146             :                                       true, computedStyle,
   11147           0 :                                       ITEM_ALLOW_XBL_BASE, nullptr, items);
   11148             :     ConstructFramesFromItemList(state, items, aParentFrame,
   11149             :                                 /* aParentIsWrapperAnonBox = */ false,
   11150           0 :                                 frameItems);
   11151             : 
   11152           0 :     nsIFrame* newFrame = frameItems.FirstChild();
   11153           0 :     *aNewFrame = newFrame;
   11154             : 
   11155           0 :     if (newFrame) {
   11156             :       // Notify the parent frame
   11157           0 :       if (aIsAppend)
   11158           0 :         ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(frameItems);
   11159             :       else
   11160           0 :         ((nsListBoxBodyFrame*)aParentFrame)->ListBoxInsertFrames(aPrevFrame, frameItems);
   11161             :     }
   11162             : 
   11163             : #ifdef ACCESSIBILITY
   11164           0 :     if (newFrame) {
   11165           0 :       nsAccessibilityService* accService = nsIPresShell::AccService();
   11166           0 :       if (accService) {
   11167           0 :         accService->ContentRangeInserted(mPresShell,
   11168             :                                          aChild,
   11169           0 :                                          aChild->GetNextSibling());
   11170             :       }
   11171             :     }
   11172             : #endif
   11173             :   }
   11174             : #endif
   11175             : }
   11176             : 
   11177             : //----------------------------------------
   11178             : 
   11179             : void
   11180          15 : nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
   11181             :                                       nsIContent*              aContent,
   11182             :                                       nsContainerFrame*        aParentFrame,
   11183             :                                       nsContainerFrame*        aContentParentFrame,
   11184             :                                       ComputedStyle*          aComputedStyle,
   11185             :                                       nsContainerFrame**       aNewFrame,
   11186             :                                       nsFrameItems&            aFrameItems,
   11187             :                                       nsIFrame*                aPositionedFrameForAbsPosContainer,
   11188             :                                       PendingBinding*          aPendingBinding)
   11189             : {
   11190             :   // Create column wrapper if necessary
   11191          15 :   nsContainerFrame* blockFrame = *aNewFrame;
   11192           0 :   NS_ASSERTION((blockFrame->IsBlockFrame() || blockFrame->IsDetailsFrame()),
   11193             :                "not a block frame nor a details frame?");
   11194          15 :   nsContainerFrame* parent = aParentFrame;
   11195           0 :   RefPtr<ComputedStyle> blockStyle = aComputedStyle;
   11196           0 :   const nsStyleColumn* columns = aComputedStyle->StyleColumn();
   11197             : 
   11198           0 :   if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO
   11199           0 :       || columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
   11200             :     nsContainerFrame* columnSetFrame =
   11201           0 :       NS_NewColumnSetFrame(mPresShell, aComputedStyle,
   11202           0 :                            nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
   11203             : 
   11204           0 :     InitAndRestoreFrame(aState, aContent, aParentFrame, columnSetFrame);
   11205           0 :     blockStyle = mPresShell->StyleSet()->
   11206           0 :       ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::columnContent,
   11207           0 :                                          aComputedStyle);
   11208           0 :     parent = columnSetFrame;
   11209           0 :     *aNewFrame = columnSetFrame;
   11210           0 :     if (aPositionedFrameForAbsPosContainer == blockFrame) {
   11211           0 :       aPositionedFrameForAbsPosContainer = columnSetFrame;
   11212             :     }
   11213             : 
   11214           0 :     SetInitialSingleChild(columnSetFrame, blockFrame);
   11215             :   }
   11216             : 
   11217           0 :   blockFrame->SetComputedStyleWithoutNotification(blockStyle);
   11218          15 :   InitAndRestoreFrame(aState, aContent, parent, blockFrame);
   11219             : 
   11220           0 :   aState.AddChild(*aNewFrame, aFrameItems, aContent,
   11221             :                   aContentParentFrame ? aContentParentFrame :
   11222          15 :                                         aParentFrame);
   11223          15 :   if (!mRootElementFrame) {
   11224             :     // The frame we're constructing will be the root element frame.
   11225             :     // Set mRootElementFrame before processing children.
   11226           5 :     mRootElementFrame = *aNewFrame;
   11227             :   }
   11228             : 
   11229             :   // We should make the outer frame be the absolute containing block,
   11230             :   // if one is required. We have to do this because absolute
   11231             :   // positioning must be computed with respect to the CSS dimensions
   11232             :   // of the element, which are the dimensions of the outer block. But
   11233             :   // we can't really do that because only blocks can have absolute
   11234             :   // children. So use the block and try to compensate with hacks
   11235             :   // in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
   11236          30 :   nsFrameConstructorSaveState absoluteSaveState;
   11237          30 :   (*aNewFrame)->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
   11238           0 :   if (aPositionedFrameForAbsPosContainer) {
   11239             :     //    NS_ASSERTION(aRelPos, "should have made area frame for this");
   11240           0 :     aState.PushAbsoluteContainingBlock(*aNewFrame, aPositionedFrameForAbsPosContainer, absoluteSaveState);
   11241             :   }
   11242             : 
   11243             :   // Process the child content
   11244           0 :   nsFrameItems childItems;
   11245             :   ProcessChildren(aState, aContent, aComputedStyle, blockFrame, true,
   11246          15 :                   childItems, true, aPendingBinding);
   11247             : 
   11248             :   // Set the frame's initial child list
   11249          15 :   blockFrame->SetInitialChildList(kPrincipalList, childItems);
   11250          15 : }
   11251             : 
   11252             : nsIFrame*
   11253           0 : nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState,
   11254             :                                        FrameConstructionItem&   aItem,
   11255             :                                        nsContainerFrame*        aParentFrame,
   11256             :                                        const nsStyleDisplay*    aDisplay,
   11257             :                                        nsFrameItems&            aFrameItems)
   11258             : {
   11259             :   // If an inline frame has non-inline kids, then we chop up the child list
   11260             :   // into runs of blocks and runs of inlines, create anonymous block frames to
   11261             :   // contain the runs of blocks, inline frames with our style for the runs of
   11262             :   // inlines, and put all these frames, in order, into aFrameItems.
   11263             :   //
   11264             :   // We return the the first one.  The whole setup is called an {ib}
   11265             :   // split; in what follows "frames in the split" refers to the anonymous blocks
   11266             :   // and inlines that contain our children.
   11267             :   //
   11268             :   // {ib} splits maintain the following invariants:
   11269             :   // 1) All frames in the split have the NS_FRAME_PART_OF_IBSPLIT bit
   11270             :   //    set.
   11271             :   // 2) Each frame in the split has the nsIFrame::IBSplitSibling
   11272             :   //    property pointing to the next frame in the split, except for the last
   11273             :   //    one, which does not have it set.
   11274             :   // 3) Each frame in the split has the nsIFrame::IBSplitPrevSibling
   11275             :   //    property pointing to the previous frame in the split, except for the
   11276             :   //    first one, which does not have it set.
   11277             :   // 4) The first and last frame in the split are always inlines.
   11278             :   //
   11279             :   // An invariant that is NOT maintained is that the wrappers are actually
   11280             :   // linked via GetNextSibling linkage.  A simple example is an inline
   11281             :   // containing an inline that contains a block.  The three parts of the inner
   11282             :   // inline end up with three different parents.
   11283             :   //
   11284             :   // For example, this HTML:
   11285             :   // <span>
   11286             :   //   <div>a</div>
   11287             :   //   <span>
   11288             :   //     b
   11289             :   //     <div>c</div>
   11290             :   //   </span>
   11291             :   //   d
   11292             :   //   <div>e</div>
   11293             :   //   f
   11294             :   //  </span>
   11295             :   // Gives the following frame tree:
   11296             :   //
   11297             :   // Inline (outer span)
   11298             :   // Block (anonymous, outer span)
   11299             :   //   Block (div)
   11300             :   //     Text("a")
   11301             :   // Inline (outer span)
   11302             :   //   Inline (inner span)
   11303             :   //     Text("b")
   11304             :   // Block (anonymous, outer span)
   11305             :   //   Block (anonymous, inner span)
   11306             :   //     Block (div)
   11307             :   //       Text("c")
   11308             :   // Inline (outer span)
   11309             :   //   Inline (inner span)
   11310             :   //   Text("d")
   11311             :   // Block (anonymous, outer span)
   11312             :   //   Block (div)
   11313             :   //     Text("e")
   11314             :   // Inline (outer span)
   11315             :   //   Text("f")
   11316             : 
   11317           0 :   nsIContent* const content = aItem.mContent;
   11318           0 :   ComputedStyle* const computedStyle = aItem.mComputedStyle;
   11319             : 
   11320             :   bool positioned =
   11321           0 :     StyleDisplay::Inline == aDisplay->mDisplay &&
   11322           0 :     aDisplay->IsRelativelyPositionedStyle() &&
   11323           0 :     !nsSVGUtils::IsInSVGTextSubtree(aParentFrame);
   11324             : 
   11325           0 :   nsInlineFrame* newFrame = NS_NewInlineFrame(mPresShell, computedStyle);
   11326             : 
   11327             :   // Initialize the frame
   11328           0 :   InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
   11329             : 
   11330           0 :   nsFrameConstructorSaveState absoluteSaveState;  // definition cannot be inside next block
   11331             :                                                   // because the object's destructor is significant
   11332             :                                                   // this is part of the fix for bug 42372
   11333             : 
   11334           0 :   newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
   11335           0 :   if (positioned) {
   11336             :     // Relatively positioned frames becomes a container for child
   11337             :     // frames that are positioned
   11338           0 :     aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
   11339             :   }
   11340             : 
   11341             :   // Process the child content
   11342           0 :   nsFrameItems childItems;
   11343           0 :   ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
   11344             :                               /* aParentIsWrapperAnonBox = */ false,
   11345           0 :                               childItems);
   11346             : 
   11347           0 :   nsFrameList::FrameLinkEnumerator firstBlockEnumerator(childItems);
   11348           0 :   if (!aItem.mIsAllInline) {
   11349           0 :     FindFirstBlock(firstBlockEnumerator);
   11350             :   }
   11351             : 
   11352           0 :   if (aItem.mIsAllInline || firstBlockEnumerator.AtEnd()) {
   11353             :     // This part is easy.  We either already know we have no non-inline kids,
   11354             :     // or haven't found any when constructing actual frames (the latter can
   11355             :     // happen only if out-of-flows that we thought had no containing block
   11356             :     // acquired one when ancestor inline frames and {ib} splits got
   11357             :     // constructed).  Just put all the kids into the single inline frame and
   11358             :     // bail.
   11359           0 :     newFrame->SetInitialChildList(kPrincipalList, childItems);
   11360           0 :     aState.AddChild(newFrame, aFrameItems, content, aParentFrame);
   11361           0 :     return newFrame;
   11362             :   }
   11363             : 
   11364             :   // This inline frame contains several types of children. Therefore this frame
   11365             :   // has to be chopped into several pieces, as described above.
   11366             : 
   11367             :   // Grab the first inline's kids
   11368           0 :   nsFrameList firstInlineKids = childItems.ExtractHead(firstBlockEnumerator);
   11369           0 :   newFrame->SetInitialChildList(kPrincipalList, firstInlineKids);
   11370             : 
   11371           0 :   aFrameItems.AddChild(newFrame);
   11372             : 
   11373           0 :   newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
   11374           0 :   CreateIBSiblings(aState, newFrame, positioned, childItems, aFrameItems);
   11375             : 
   11376           0 :   return newFrame;
   11377             : }
   11378             : 
   11379             : void
   11380           0 : nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState,
   11381             :                                         nsContainerFrame* aInitialInline,
   11382             :                                         bool aIsPositioned,
   11383             :                                         nsFrameItems& aChildItems,
   11384             :                                         nsFrameItems& aSiblings)
   11385             : {
   11386           0 :   nsIContent* content = aInitialInline->GetContent();
   11387           0 :   ComputedStyle* computedStyle = aInitialInline->Style();
   11388           0 :   nsContainerFrame* parentFrame = aInitialInline->GetParent();
   11389             : 
   11390             :   // Resolve the right style for our anonymous blocks.
   11391             :   //
   11392             :   // The distinction in styles is needed because of CSS 2.1, section
   11393             :   // 9.2.1.1, which says:
   11394             :   //
   11395             :   //   When such an inline box is affected by relative positioning, any
   11396             :   //   resulting translation also affects the block-level box contained
   11397             :   //   in the inline box.
   11398           0 :   RefPtr<ComputedStyle> blockSC = mPresShell->StyleSet()->
   11399           0 :     ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::mozBlockInsideInlineWrapper,
   11400           0 :                                        computedStyle);
   11401             : 
   11402             :   nsContainerFrame* lastNewInline =
   11403           0 :     static_cast<nsContainerFrame*>(aInitialInline->FirstContinuation());
   11404           0 :   do {
   11405             :     // On entry to this loop aChildItems is not empty and the first frame in it
   11406             :     // is block-level.
   11407           0 :     MOZ_ASSERT(aChildItems.NotEmpty(), "Should have child items");
   11408           0 :     MOZ_ASSERT(!aChildItems.FirstChild()->IsInlineOutside(),
   11409             :                "Must have list starting with block");
   11410             : 
   11411             :     // The initial run of blocks belongs to an anonymous block that we create
   11412             :     // right now. The anonymous block will be the parent of these block
   11413             :     // children of the inline.
   11414           0 :     nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
   11415           0 :     InitAndRestoreFrame(aState, content, parentFrame, blockFrame, false);
   11416             : 
   11417             :     // Find the first non-block child which defines the end of our block kids
   11418             :     // and the start of our next inline's kids
   11419             :     nsFrameList::FrameLinkEnumerator firstNonBlock =
   11420           0 :       FindFirstNonBlock(aChildItems);
   11421           0 :     nsFrameList blockKids = aChildItems.ExtractHead(firstNonBlock);
   11422             : 
   11423           0 :     MoveChildrenTo(aInitialInline, blockFrame, blockKids);
   11424             : 
   11425           0 :     SetFrameIsIBSplit(lastNewInline, blockFrame);
   11426           0 :     aSiblings.AddChild(blockFrame);
   11427             : 
   11428             :     // Now grab the initial inlines in aChildItems and put them into an inline
   11429             :     // frame.
   11430           0 :     nsInlineFrame* inlineFrame = NS_NewInlineFrame(mPresShell, computedStyle);
   11431           0 :     InitAndRestoreFrame(aState, content, parentFrame, inlineFrame, false);
   11432           0 :     inlineFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
   11433           0 :     if (aIsPositioned) {
   11434           0 :       inlineFrame->MarkAsAbsoluteContainingBlock();
   11435             :     }
   11436             : 
   11437           0 :     if (aChildItems.NotEmpty()) {
   11438           0 :       nsFrameList::FrameLinkEnumerator firstBlock(aChildItems);
   11439           0 :       FindFirstBlock(firstBlock);
   11440           0 :       nsFrameList inlineKids = aChildItems.ExtractHead(firstBlock);
   11441             : 
   11442           0 :       MoveChildrenTo(aInitialInline, inlineFrame, inlineKids);
   11443             :     }
   11444             : 
   11445           0 :     SetFrameIsIBSplit(blockFrame, inlineFrame);
   11446           0 :     aSiblings.AddChild(inlineFrame);
   11447           0 :     lastNewInline = inlineFrame;
   11448           0 :   } while (aChildItems.NotEmpty());
   11449             : 
   11450           0 :   SetFrameIsIBSplit(lastNewInline, nullptr);
   11451           0 : }
   11452             : 
   11453             : void
   11454           0 : nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
   11455             :                                              FrameConstructionItem& aParentItem,
   11456             :                                              bool aItemIsWithinSVGText,
   11457             :                                              bool aItemAllowsTextPathChild)
   11458             : {
   11459             :   // XXXbz should we preallocate aParentItem.mChildItems to some sane
   11460             :   // length?  Maybe even to parentContent->GetChildCount()?
   11461             :   nsFrameConstructorState::PendingBindingAutoPusher
   11462           0 :     pusher(aState, aParentItem.mPendingBinding);
   11463             : 
   11464           0 :   ComputedStyle* const parentComputedStyle = aParentItem.mComputedStyle;
   11465           0 :   nsIContent* const parentContent = aParentItem.mContent;
   11466             : 
   11467           0 :   if (!aItemIsWithinSVGText) {
   11468             :     // Probe for generated content before
   11469           0 :     CreateGeneratedContentItem(aState, nullptr, parentContent->AsElement(),
   11470             :                                parentComputedStyle, CSSPseudoElementType::before,
   11471           0 :                                aParentItem.mChildItems);
   11472             :   }
   11473             : 
   11474           0 :   uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK;
   11475           0 :   if (aItemIsWithinSVGText) {
   11476           0 :     flags |= ITEM_IS_WITHIN_SVG_TEXT;
   11477             :   }
   11478           0 :   if (aItemAllowsTextPathChild && aParentItem.mIsForSVGAElement) {
   11479           0 :     flags |= ITEM_ALLOWS_TEXT_PATH_CHILD;
   11480             :   }
   11481             : 
   11482           0 :   if (!aParentItem.mAnonChildren.IsEmpty()) {
   11483             :     // Use the anon-children list instead of the content tree child list so that
   11484             :     // we use any special style that should be associated with the children, and
   11485             :     // so that we won't try to construct grandchildren frame constructor items
   11486             :     // before the frame is available for their parent.
   11487           0 :     AddFCItemsForAnonymousContent(aState, nullptr, aParentItem.mAnonChildren,
   11488           0 :                                   aParentItem.mChildItems, flags);
   11489             :   } else {
   11490             :     // Use the content tree child list:
   11491           0 :     FlattenedChildIterator iter(parentContent);
   11492           0 :     for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) {
   11493             :       // Manually check for comments/PIs, since we don't have a frame to pass to
   11494             :       // AddFrameConstructionItems.  We know our parent is a non-replaced inline,
   11495             :       // so there is no need to do the NeedFrameFor check.
   11496           0 :       content->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
   11497           0 :       if (content->IsComment() || content->IsProcessingInstruction()) {
   11498           0 :         continue;
   11499             :       }
   11500             : 
   11501           0 :       RefPtr<ComputedStyle> childContext = ResolveComputedStyle(content);
   11502           0 :       AddFrameConstructionItemsInternal(aState, content, nullptr,
   11503           0 :                                         iter.XBLInvolved(), childContext,
   11504             :                                         flags, nullptr,
   11505           0 :                                         aParentItem.mChildItems);
   11506             :     }
   11507             :   }
   11508             : 
   11509           0 :   if (!aItemIsWithinSVGText) {
   11510             :     // Probe for generated content after
   11511           0 :     CreateGeneratedContentItem(aState, nullptr, parentContent->AsElement(),
   11512             :                                parentComputedStyle,
   11513             :                                CSSPseudoElementType::after,
   11514           0 :                                aParentItem.mChildItems);
   11515             :   }
   11516             : 
   11517           0 :   aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
   11518           0 : }
   11519             : 
   11520             : // return whether it's ok to append (in the AppendFrames sense) to
   11521             : // aParentFrame if our nextSibling is aNextSibling.  aParentFrame must
   11522             : // be an ib-split inline.
   11523             : static bool
   11524           0 : IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame, nsIFrame* aNextSibling)
   11525             : {
   11526           0 :   MOZ_ASSERT(IsInlineFrame(aParentFrame), "Must have an inline parent here");
   11527             : 
   11528           0 :   do {
   11529           0 :     NS_ASSERTION(IsFramePartOfIBSplit(aParentFrame),
   11530             :                  "How is this not part of an ib-split?");
   11531           0 :     if (aNextSibling || aParentFrame->GetNextContinuation() ||
   11532           0 :         GetIBSplitSibling(aParentFrame)) {
   11533             :       return false;
   11534             :     }
   11535             : 
   11536           0 :     aNextSibling = aParentFrame->GetNextSibling();
   11537           0 :     aParentFrame = aParentFrame->GetParent();
   11538             :   } while (IsInlineFrame(aParentFrame));
   11539             : 
   11540             :   return true;
   11541             : }
   11542             : 
   11543             : bool
   11544          36 : nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
   11545             :                                            nsIFrame* aContainingBlock,
   11546             :                                            nsIFrame* aFrame,
   11547             :                                            FrameConstructionItemList& aItems,
   11548             :                                            bool aIsAppend,
   11549             :                                            nsIFrame* aPrevSibling)
   11550             : {
   11551          36 :   if (aItems.IsEmpty()) {
   11552             :     return false;
   11553             :   }
   11554             : 
   11555             :   // Before we go and append the frames, we must check for several
   11556             :   // special situations.
   11557             : 
   11558             :   // Situation #1 is a XUL frame that contains frames that are required
   11559             :   // to be wrapped in blocks.
   11560          51 :   if (aFrame->IsXULBoxFrame() &&
   11561           0 :       !(aFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
   11562          11 :       aItems.AnyItemsNeedBlockParent()) {
   11563           0 :     RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
   11564           0 :     return true;
   11565             :   }
   11566             : 
   11567           0 :   nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
   11568             : 
   11569             :   // Situation #2 is a flex or grid container frame into which we're inserting
   11570             :   // new inline non-replaced children, adjacent to an existing anonymous
   11571             :   // flex or grid item.
   11572          20 :   LayoutFrameType frameType = aFrame->Type();
   11573           0 :   if (frameType == LayoutFrameType::FlexContainer ||
   11574           0 :       frameType == LayoutFrameType::GridContainer) {
   11575           0 :     FCItemIterator iter(aItems);
   11576             : 
   11577             :     // Check if we're adding to-be-wrapped content right *after* an existing
   11578             :     // anonymous flex or grid item (which would need to absorb this content).
   11579           0 :     const bool isLegacyBox = IsFlexContainerForLegacyBox(aFrame);
   11580           0 :     if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
   11581           0 :         iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyBox)) {
   11582           0 :       RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
   11583           0 :       return true;
   11584             :     }
   11585             : 
   11586             :     // Check if we're adding to-be-wrapped content right *before* an existing
   11587             :     // anonymous flex or grid item (which would need to absorb this content).
   11588           0 :     if (nextSibling && IsAnonymousFlexOrGridItem(nextSibling)) {
   11589             :       // Jump to the last entry in the list
   11590           0 :       iter.SetToEnd();
   11591           0 :       iter.Prev();
   11592           0 :       if (iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyBox)) {
   11593           0 :         RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
   11594           0 :         return true;
   11595             :       }
   11596             :     }
   11597             :   }
   11598             : 
   11599             :   // Situation #3 is an anonymous flex or grid item that's getting new children
   11600             :   // who don't want to be wrapped.
   11601          20 :   if (IsAnonymousFlexOrGridItem(aFrame)) {
   11602           0 :     AssertAnonymousFlexOrGridItemParent(aFrame, aFrame->GetParent());
   11603             : 
   11604             :     // We need to push a null float containing block to be sure that
   11605             :     // "NeedsAnonFlexOrGridItem" will know we're not honoring floats for this
   11606             :     // inserted content. (In particular, this is necessary in order for
   11607             :     // its "GetGeometricParent" call to return the correct result.)
   11608             :     // We're not honoring floats on this content because it has the
   11609             :     // _flex/grid container_ as its parent in the content tree.
   11610           0 :     nsFrameConstructorSaveState floatSaveState;
   11611           0 :     aState.PushFloatContainingBlock(nullptr, floatSaveState);
   11612             : 
   11613           0 :     FCItemIterator iter(aItems);
   11614             :     // Skip over things that _do_ need an anonymous flex item, because
   11615             :     // they're perfectly happy to go here -- they won't cause a reframe.
   11616           0 :     nsIFrame* containerFrame = aFrame->GetParent();
   11617           0 :     const bool isLegacyBox = IsFlexContainerForLegacyBox(containerFrame);
   11618           0 :     if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isLegacyBox)) {
   11619             :       // We hit something that _doesn't_ need an anonymous flex item!
   11620             :       // Rebuild the flex container to bust it out.
   11621           0 :       RecreateFramesForContent(containerFrame->GetContent(), InsertionKind::Async);
   11622           0 :       return true;
   11623             :     }
   11624             : 
   11625             :     // If we get here, then everything in |aItems| needs to be wrapped in
   11626             :     // an anonymous flex or grid item.  That's where it's already going - good!
   11627             :   }
   11628             : 
   11629             :   // Situation #4 is a ruby-related frame that's getting new children.
   11630             :   // The situation for ruby is complex, especially when interacting with
   11631             :   // spaces. It containes these two special cases apart from tables:
   11632             :   // 1) There are effectively three types of white spaces in ruby frames
   11633             :   //    we handle differently: leading/tailing/inter-level space,
   11634             :   //    inter-base/inter-annotation space, and inter-segment space.
   11635             :   //    These three types of spaces can be converted to each other when
   11636             :   //    their sibling changes.
   11637             :   // 2) The first effective child of a ruby frame must always be a ruby
   11638             :   //    base container. It should be created or destroyed accordingly.
   11639           0 :   if (IsRubyPseudo(aFrame) || frameType == LayoutFrameType::Ruby ||
   11640          20 :       RubyUtils::IsRubyContainerBox(frameType)) {
   11641             :     // We want to optimize it better, and avoid reframing as much as
   11642             :     // possible. But given the cases above, and the fact that a ruby
   11643             :     // usually won't be very large, it should be fine to reframe it.
   11644           0 :     RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
   11645           0 :     return true;
   11646             :   }
   11647             : 
   11648             :   // Situation #5 is a case when table pseudo-frames don't work out right
   11649          20 :   ParentType parentType = GetParentType(aFrame);
   11650             :   // If all the kids want a parent of the type that aFrame is, then we're all
   11651             :   // set to go.  Indeed, there won't be any table pseudo-frames created between
   11652             :   // aFrame and the kids, so those won't need to be merged with any table
   11653             :   // pseudo-frames that might already be kids of aFrame.  If aFrame itself is a
   11654             :   // table pseudo-frame, then all the kids in this list would have wanted a
   11655             :   // frame of that type wrapping them anyway, so putting them inside it is ok.
   11656          20 :   if (!aItems.AllWantParentType(parentType)) {
   11657             :     // Don't give up yet.  If parentType is not eTypeBlock and the parent is
   11658             :     // not a generated content frame, then try filtering whitespace out of the
   11659             :     // list.
   11660           0 :     if (parentType != eTypeBlock && !aFrame->IsGeneratedContentFrame()) {
   11661             :       // For leading whitespace followed by a kid that wants our parent type,
   11662             :       // there are four cases:
   11663             :       // 1) We have a previous sibling which is not a table pseudo.  That means
   11664             :       //    that previous sibling wanted a (non-block) parent of the type we're
   11665             :       //    looking at.  Then the whitespace comes between two table-internal
   11666             :       //    elements, so should be collapsed out.
   11667             :       // 2) We have a previous sibling which is a table pseudo.  It might have
   11668             :       //    kids who want this whitespace, so we need to reframe.
   11669             :       // 3) We have no previous sibling and our parent frame is not a table
   11670             :       //    pseudo.  That means that we'll be at the beginning of our actual
   11671             :       //    non-block-type parent, and the whitespace is OK to collapse out.
   11672             :       //    If something is ever inserted before us, it'll find our own parent
   11673             :       //    as its parent and if it's something that would care about the
   11674             :       //    whitespace it'll want a block parent, so it'll trigger a reframe at
   11675             :       //    that point.
   11676             :       // 4) We have no previous sibling and our parent frame is a table pseudo.
   11677             :       //    Need to reframe.
   11678             :       // All that is predicated on finding the correct previous sibling.  We
   11679             :       // might have to walk backwards along continuations from aFrame to do so.
   11680             :       //
   11681             :       // It's always OK to drop whitespace between any two items that want a
   11682             :       // parent of type parentType.
   11683             :       //
   11684             :       // For trailing whitespace preceded by a kid that wants our parent type,
   11685             :       // there are four cases:
   11686             :       // 1) We have a next sibling which is not a table pseudo.  That means
   11687             :       //    that next sibling wanted a (non-block) parent of the type we're
   11688             :       //    looking at.  Then the whitespace comes between two table-internal
   11689             :       //    elements, so should be collapsed out.
   11690             :       // 2) We have a next sibling which is a table pseudo.  It might have
   11691             :       //    kids who want this whitespace, so we need to reframe.
   11692             :       // 3) We have no next sibling and our parent frame is not a table
   11693             :       //    pseudo.  That means that we'll be at the end of our actual
   11694             :       //    non-block-type parent, and the whitespace is OK to collapse out.
   11695             :       //    If something is ever inserted after us, it'll find our own parent
   11696             :       //    as its parent and if it's something that would care about the
   11697             :       //    whitespace it'll want a block parent, so it'll trigger a reframe at
   11698             :       //    that point.
   11699             :       // 4) We have no next sibling and our parent frame is a table pseudo.
   11700             :       //    Need to reframe.
   11701             :       // All that is predicated on finding the correct next sibling.  We might
   11702             :       // have to walk forward along continuations from aFrame to do so.  That
   11703             :       // said, in the case when nextSibling is null at this point and aIsAppend
   11704             :       // is true, we know we're in case 3.  Furthermore, in that case we don't
   11705             :       // even have to worry about the table pseudo situation; we know our
   11706             :       // parent is not a table pseudo there.
   11707           0 :       FCItemIterator iter(aItems);
   11708             :       FCItemIterator start(iter);
   11709           0 :       do {
   11710           0 :         if (iter.SkipItemsWantingParentType(parentType)) {
   11711             :           break;
   11712             :         }
   11713             : 
   11714             :         // iter points to an item that wants a different parent.  If it's not
   11715             :         // whitespace, we're done; no more point scanning the list.
   11716           0 :         if (!iter.item().IsWhitespace(aState)) {
   11717             :           break;
   11718             :         }
   11719             : 
   11720           0 :         if (iter == start) {
   11721             :           // Leading whitespace.  How to handle this depends on our
   11722             :           // previous sibling and aFrame.  See the long comment above.
   11723           0 :           nsIFrame* prevSibling = aPrevSibling;
   11724           0 :           if (!prevSibling) {
   11725             :             // Try to find one after all
   11726           0 :             nsIFrame* parentPrevCont = aFrame->GetPrevContinuation();
   11727           0 :             while (parentPrevCont) {
   11728           0 :               prevSibling = parentPrevCont->GetChildList(kPrincipalList).LastChild();
   11729           0 :               if (prevSibling) {
   11730             :                 break;
   11731             :               }
   11732           0 :               parentPrevCont = parentPrevCont->GetPrevContinuation();
   11733             :             }
   11734             :           };
   11735           0 :           if (prevSibling) {
   11736           0 :             if (IsTablePseudo(prevSibling)) {
   11737             :               // need to reframe
   11738             :               break;
   11739             :             }
   11740           0 :           } else if (IsTablePseudo(aFrame)) {
   11741             :             // need to reframe
   11742             :             break;
   11743             :           }
   11744             :         }
   11745             : 
   11746           0 :         FCItemIterator spaceEndIter(iter);
   11747             :         // Advance spaceEndIter past any whitespace
   11748           0 :         bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
   11749             : 
   11750             :         bool okToDrop;
   11751           0 :         if (trailingSpaces) {
   11752             :           // Trailing whitespace.  How to handle this depeds on aIsAppend, our
   11753             :           // next sibling and aFrame.  See the long comment above.
   11754           0 :           okToDrop = aIsAppend && !nextSibling;
   11755           0 :           if (!okToDrop) {
   11756           0 :             if (!nextSibling) {
   11757             :               // Try to find one after all
   11758           0 :               nsIFrame* parentNextCont = aFrame->GetNextContinuation();
   11759           0 :               while (parentNextCont) {
   11760           0 :                 nextSibling = parentNextCont->PrincipalChildList().FirstChild();
   11761           0 :                 if (nextSibling) {
   11762             :                   break;
   11763             :                 }
   11764           0 :                 parentNextCont = parentNextCont->GetNextContinuation();
   11765             :               }
   11766             :             }
   11767             : 
   11768           0 :             okToDrop = (nextSibling && !IsTablePseudo(nextSibling)) ||
   11769           0 :                        (!nextSibling && !IsTablePseudo(aFrame));
   11770             :           }
   11771             : #ifdef DEBUG
   11772             :           else {
   11773           0 :             NS_ASSERTION(!IsTablePseudo(aFrame), "How did that happen?");
   11774             :           }
   11775             : #endif
   11776             :         } else {
   11777           0 :           okToDrop = (spaceEndIter.item().DesiredParentType() == parentType);
   11778             :         }
   11779             : 
   11780           0 :         if (okToDrop) {
   11781           0 :           iter.DeleteItemsTo(this, spaceEndIter);
   11782             :         } else {
   11783             :           // We're done: we don't want to drop the whitespace, and it has the
   11784             :           // wrong parent type.
   11785             :           break;
   11786             :         }
   11787             : 
   11788             :         // Now loop, since |iter| points to item right after the whitespace we
   11789             :         // removed.
   11790           0 :       } while (!iter.IsDone());
   11791             :     }
   11792             : 
   11793             :     // We might be able to figure out some sort of optimizations here, but they
   11794             :     // would have to depend on having a correct aPrevSibling and a correct next
   11795             :     // sibling.  For example, we can probably avoid reframing if none of
   11796             :     // aFrame, aPrevSibling, and next sibling are table pseudo-frames.  But it
   11797             :     // doesn't seem worth it to worry about that for now, especially since we
   11798             :     // in fact do not have a reliable aPrevSibling, nor any next sibling, in
   11799             :     // this method.
   11800             : 
   11801             :     // aItems might have changed, so recheck the parent type thing.  In fact,
   11802             :     // it might be empty, so recheck that too.
   11803           0 :     if (aItems.IsEmpty()) {
   11804             :       return false;
   11805             :     }
   11806             : 
   11807           0 :     if (!aItems.AllWantParentType(parentType)) {
   11808             :       // Reframing aFrame->GetContent() is good enough, since the content of
   11809             :       // table pseudo-frames is the ancestor content.
   11810           0 :       RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
   11811           0 :       return true;
   11812             :     }
   11813             :   }
   11814             : 
   11815             :   // Now we have several cases involving {ib} splits.  Put them all in a
   11816             :   // do/while with breaks to take us to the "go and reconstruct" code.
   11817             :   do {
   11818           0 :     if (IsInlineFrame(aFrame)) {
   11819           0 :       if (aItems.AreAllItemsInline()) {
   11820             :         // We can just put the kids in.
   11821             :         return false;
   11822             :       }
   11823             : 
   11824           0 :       if (!IsFramePartOfIBSplit(aFrame)) {
   11825             :         // Need to go ahead and reconstruct.
   11826             :         break;
   11827             :       }
   11828             : 
   11829             :       // Now we're adding kids including some blocks to an inline part of an
   11830             :       // {ib} split.  If we plan to call AppendFrames, and don't have a next
   11831             :       // sibling for the new frames, and our parent is the last continuation of
   11832             :       // the last part of the {ib} split, and the same is true of all our
   11833             :       // ancestor inlines (they have no following continuations and they're the
   11834             :       // last part of their {ib} splits and we'd be adding to the end for all
   11835             :       // of them), then AppendFrames will handle things for us.  Bail out in
   11836             :       // that case.
   11837           0 :       if (aIsAppend && IsSafeToAppendToIBSplitInline(aFrame, nextSibling)) {
   11838             :         return false;
   11839             :       }
   11840             : 
   11841             :       // Need to reconstruct.
   11842             :       break;
   11843             :     }
   11844             : 
   11845             :     // Now we know we have a block parent.  If it's not part of an
   11846             :     // ib-split, we're all set.
   11847           0 :     if (!IsFramePartOfIBSplit(aFrame)) {
   11848             :       return false;
   11849             :     }
   11850             : 
   11851             :     // We're adding some kids to a block part of an {ib} split.  If all the
   11852             :     // kids are blocks, we don't need to reconstruct.
   11853           0 :     if (aItems.AreAllItemsBlock()) {
   11854             :       return false;
   11855             :     }
   11856             : 
   11857             :     // We might have some inline kids for this block.  Just fall out of the
   11858             :     // loop and reconstruct.
   11859             :   } while (0);
   11860             : 
   11861             :   // If we don't have a containing block, start with aFrame and look for one.
   11862           0 :   if (!aContainingBlock) {
   11863           0 :     aContainingBlock = aFrame;
   11864             :   }
   11865             : 
   11866             :   // To find the right block to reframe, just walk up the tree until we find a
   11867             :   // frame that is:
   11868             :   // 1)  Not part of an IB split
   11869             :   // 2)  Not a pseudo-frame
   11870             :   // 3)  Not an inline frame
   11871             :   // We're guaranteed to find one, since ComputedStyle::ApplyStyleFixups
   11872             :   // enforces that the root is display:none, display:table, or display:block.
   11873             :   // Note that walking up "too far" is OK in terms of correctness, even if it
   11874             :   // might be a little inefficient.  This is why we walk out of all
   11875             :   // pseudo-frames -- telling which ones are or are not OK to walk out of is
   11876             :   // too hard (and I suspect that we do in fact need to walk out of all of
   11877             :   // them).
   11878           0 :   while (IsFramePartOfIBSplit(aContainingBlock) ||
   11879           0 :          aContainingBlock->IsInlineOutside() ||
   11880           0 :          aContainingBlock->Style()->GetPseudo()) {
   11881           0 :     aContainingBlock = aContainingBlock->GetParent();
   11882           0 :     NS_ASSERTION(aContainingBlock,
   11883             :                  "Must have non-inline, non-ib-split, non-pseudo frame as "
   11884             :                  "root (or child of root, for a table root)!");
   11885             :   }
   11886             : 
   11887             :   // Tell parent of the containing block to reformulate the
   11888             :   // entire block. This is painful and definitely not optimal
   11889             :   // but it will *always* get the right answer.
   11890             : 
   11891           0 :   nsIContent* blockContent = aContainingBlock->GetContent();
   11892             : #ifdef DEBUG
   11893           0 :   if (gNoisyContentUpdates) {
   11894             :     printf("nsCSSFrameConstructor::WipeContainingBlock: blockContent=%p\n",
   11895             :            blockContent);
   11896             :   }
   11897             : #endif
   11898           0 :   RecreateFramesForContent(blockContent, InsertionKind::Async);
   11899           0 :   return true;
   11900             : }
   11901             : 
   11902             : void
   11903           0 : nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame)
   11904             : {
   11905             : 
   11906             : #ifdef DEBUG
   11907             :   // ReframeContainingBlock is a NASTY routine, it causes terrible performance problems
   11908             :   // so I want to see when it is happening!  Unfortunately, it is happening way to often because
   11909             :   // so much content on the web causes block-in-inline frame situations and we handle them
   11910             :   // very poorly
   11911           0 :   if (gNoisyContentUpdates) {
   11912             :     printf("nsCSSFrameConstructor::ReframeContainingBlock frame=%p\n",
   11913             :            aFrame);
   11914             :   }
   11915             : #endif
   11916             : 
   11917             :   // XXXbz how exactly would we get here while isReflowing anyway?  Should this
   11918             :   // whole test be ifdef DEBUG?
   11919           0 :   if (mPresShell->IsReflowLocked()) {
   11920             :     // don't ReframeContainingBlock, this will result in a crash
   11921             :     // if we remove a tree that's in reflow - see bug 121368 for testcase
   11922           0 :     NS_ERROR("Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a Reflow!!!");
   11923             :     return;
   11924             :   }
   11925             : 
   11926             :   // Get the first "normal" ancestor of the target frame.
   11927           0 :   nsIFrame* containingBlock = GetIBContainingBlockFor(aFrame);
   11928           0 :   if (containingBlock) {
   11929             :     // From here we look for the containing block in case the target
   11930             :     // frame is already a block (which can happen when an inline frame
   11931             :     // wraps some of its content in an anonymous block; see
   11932             :     // ConstructInline)
   11933             : 
   11934             :     // NOTE: We used to get the FloatContainingBlock here, but it was often wrong.
   11935             :     // GetIBContainingBlock works much better and provides the correct container in all cases
   11936             :     // so GetFloatContainingBlock(aFrame) has been removed
   11937             : 
   11938             :     // And get the containingBlock's content
   11939           0 :     if (nsIContent* blockContent = containingBlock->GetContent()) {
   11940             : #ifdef DEBUG
   11941           0 :       if (gNoisyContentUpdates) {
   11942             :         printf("  ==> blockContent=%p\n", blockContent);
   11943             :       }
   11944             : #endif
   11945           0 :       RecreateFramesForContent(blockContent->AsElement(), InsertionKind::Async);
   11946           0 :       return;
   11947             :     }
   11948             :   }
   11949             : 
   11950             :   // If we get here, we're screwed!
   11951           0 :   RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
   11952           0 :                            InsertionKind::Async);
   11953             : }
   11954             : 
   11955             : void
   11956           0 : nsCSSFrameConstructor::GenerateChildFrames(nsContainerFrame* aFrame)
   11957             : {
   11958             :   {
   11959           0 :     nsAutoScriptBlocker scriptBlocker;
   11960           0 :     nsFrameItems childItems;
   11961           0 :     nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
   11962             :     // We don't have a parent frame with a pending binding constructor here,
   11963             :     // so no need to worry about ordering of the kids' constructors with it.
   11964             :     // Pass null for the PendingBinding.
   11965           0 :     ProcessChildren(state, aFrame->GetContent(), aFrame->Style(),
   11966             :                     aFrame, false, childItems, false,
   11967           0 :                     nullptr);
   11968             : 
   11969           0 :     aFrame->SetInitialChildList(kPrincipalList, childItems);
   11970             :   }
   11971             : 
   11972             : #ifdef ACCESSIBILITY
   11973           0 :   if (nsAccessibilityService* accService = nsIPresShell::AccService()) {
   11974           0 :     if (nsIContent* child = aFrame->GetContent()->GetFirstChild()) {
   11975           0 :       accService->ContentRangeInserted(mPresShell, child, nullptr);
   11976             :     }
   11977             :   }
   11978             : #endif
   11979             : 
   11980             :   // call XBL constructors after the frames are created
   11981           0 :   mPresShell->GetDocument()->BindingManager()->ProcessAttachedQueue();
   11982           0 : }
   11983             : 
   11984             : //////////////////////////////////////////////////////////
   11985             : // nsCSSFrameConstructor::FrameConstructionItem methods //
   11986             : //////////////////////////////////////////////////////////
   11987             : bool
   11988           6 : nsCSSFrameConstructor::
   11989             : FrameConstructionItem::IsWhitespace(nsFrameConstructorState& aState) const
   11990             : {
   11991           0 :   MOZ_ASSERT(aState.mCreatingExtraFrames ||
   11992             :              !mContent->GetPrimaryFrame(), "How did that happen?");
   11993           6 :   if (!mIsText) {
   11994             :     return false;
   11995             :   }
   11996           6 :   mContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
   11997           6 :                      NS_REFRAME_IF_WHITESPACE);
   11998           6 :   return mContent->TextIsOnlyWhitespace();
   11999             : }
   12000             : 
   12001             : //////////////////////////////////////////////////////////////
   12002             : // nsCSSFrameConstructor::FrameConstructionItemList methods //
   12003             : //////////////////////////////////////////////////////////////
   12004             : void
   12005           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12006             : AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta)
   12007             : {
   12008           0 :   MOZ_ASSERT(aDelta == 1 || aDelta == -1, "Unexpected delta");
   12009           0 :   mItemCount += aDelta;
   12010           0 :   if (aItem->mIsAllInline) {
   12011           0 :     mInlineCount += aDelta;
   12012             :   }
   12013           0 :   if (aItem->mIsBlock) {
   12014           0 :     mBlockCount += aDelta;
   12015             :   }
   12016           0 :   if (aItem->mIsLineParticipant) {
   12017           0 :     mLineParticipantCount += aDelta;
   12018             :   }
   12019           0 :   mDesiredParentCounts[aItem->DesiredParentType()] += aDelta;
   12020           0 : }
   12021             : 
   12022             : ////////////////////////////////////////////////////////////////////////
   12023             : // nsCSSFrameConstructor::FrameConstructionItemList::Iterator methods //
   12024             : ////////////////////////////////////////////////////////////////////////
   12025             : inline bool
   12026           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12027             : Iterator::SkipItemsWantingParentType(ParentType aParentType)
   12028             : {
   12029           0 :   MOZ_ASSERT(!IsDone(), "Shouldn't be done yet");
   12030           0 :   while (item().DesiredParentType() == aParentType) {
   12031           0 :     Next();
   12032           0 :     if (IsDone()) {
   12033             :       return true;
   12034             :     }
   12035             :   }
   12036             :   return false;
   12037             : }
   12038             : 
   12039             : inline bool
   12040           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12041             : Iterator::SkipItemsNotWantingParentType(ParentType aParentType)
   12042             : {
   12043           0 :   MOZ_ASSERT(!IsDone(), "Shouldn't be done yet");
   12044           0 :   while (item().DesiredParentType() != aParentType) {
   12045           0 :     Next();
   12046           0 :     if (IsDone()) {
   12047             :       return true;
   12048             :     }
   12049             :   }
   12050             :   return false;
   12051             : }
   12052             : 
   12053             : // Note: we implement -webkit-{inline-}box (and optionally -moz-{inline-}box)
   12054             : // using nsFlexContainerFrame, but we use different rules for what gets wrapped
   12055             : // in an anonymous flex item.
   12056             : bool
   12057           0 : nsCSSFrameConstructor::FrameConstructionItem::
   12058             :   NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
   12059             :                           bool aIsLegacyBox)
   12060             : {
   12061           0 :   if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) {
   12062             :     // This will be an inline non-replaced box.
   12063             :     return true;
   12064             :   }
   12065             : 
   12066           0 :   if (aIsLegacyBox) {
   12067           0 :     if (mComputedStyle->StyleDisplay()->IsInlineOutsideStyle()) {
   12068             :       // In an emulated legacy box, all inline-level content gets wrapped in an
   12069             :       // anonymous flex item.
   12070             :       return true;
   12071             :     }
   12072           0 :     if (mIsPopup ||
   12073           0 :         (!(mFCData->mBits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
   12074           0 :          aState.GetGeometricParent(mComputedStyle->StyleDisplay(), nullptr))) {
   12075             :       // We're abspos or fixedpos (or a XUL popup), which means we'll spawn a
   12076             :       // placeholder which (because our container is an emulated legacy box)
   12077             :       // we'll need to wrap in an anonymous flex item.  So, we just treat
   12078             :       // _this_ frame as if _it_ needs to be wrapped in an anonymous flex item,
   12079             :       // and then when we spawn the placeholder, it'll end up in the right
   12080             :       // spot.
   12081             :       return true;
   12082             :     }
   12083             :   }
   12084             : 
   12085             :   return false;
   12086             : }
   12087             : 
   12088             : inline bool
   12089           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12090             : Iterator::SkipItemsThatNeedAnonFlexOrGridItem(
   12091             :   const nsFrameConstructorState& aState,
   12092             :   bool aIsLegacyBox)
   12093             : {
   12094           0 :   MOZ_ASSERT(!IsDone(), "Shouldn't be done yet");
   12095           0 :   while (item().NeedsAnonFlexOrGridItem(aState, aIsLegacyBox)) {
   12096           0 :     Next();
   12097           0 :     if (IsDone()) {
   12098             :       return true;
   12099             :     }
   12100             :   }
   12101             :   return false;
   12102             : }
   12103             : 
   12104             : inline bool
   12105           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12106             : Iterator::SkipItemsThatDontNeedAnonFlexOrGridItem(
   12107             :   const nsFrameConstructorState& aState,
   12108             :   bool aIsLegacyBox)
   12109             : {
   12110           0 :   MOZ_ASSERT(!IsDone(), "Shouldn't be done yet");
   12111           0 :   while (!(item().NeedsAnonFlexOrGridItem(aState, aIsLegacyBox))) {
   12112           0 :     Next();
   12113           0 :     if (IsDone()) {
   12114             :       return true;
   12115             :     }
   12116             :   }
   12117             :   return false;
   12118             : }
   12119             : 
   12120             : inline bool
   12121           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12122             : Iterator::SkipItemsNotWantingRubyParent()
   12123             : {
   12124           0 :   MOZ_ASSERT(!IsDone(), "Shouldn't be done yet");
   12125           0 :   while (!IsRubyParentType(item().DesiredParentType())) {
   12126           0 :     Next();
   12127           0 :     if (IsDone()) {
   12128             :       return true;
   12129             :     }
   12130             :   }
   12131             :   return false;
   12132             : }
   12133             : 
   12134             : inline bool
   12135           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12136             : Iterator::SkipWhitespace(nsFrameConstructorState& aState)
   12137             : {
   12138           0 :   MOZ_ASSERT(!IsDone(), "Shouldn't be done yet");
   12139           0 :   MOZ_ASSERT(item().IsWhitespace(aState), "Not pointing to whitespace?");
   12140           0 :   do {
   12141           0 :     Next();
   12142           0 :     if (IsDone()) {
   12143             :       return true;
   12144             :     }
   12145           0 :   } while (item().IsWhitespace(aState));
   12146             : 
   12147             :   return false;
   12148             : }
   12149             : 
   12150             : void
   12151           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12152             : Iterator::AppendItemToList(FrameConstructionItemList& aTargetList)
   12153             : {
   12154           0 :   NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
   12155           0 :   MOZ_ASSERT(!IsDone(), "should not be done");
   12156             : 
   12157           0 :   FrameConstructionItem* item = mCurrent;
   12158           0 :   Next();
   12159           0 :   item->remove();
   12160           0 :   aTargetList.mItems.insertBack(item);
   12161             : 
   12162           0 :   mList.AdjustCountsForItem(item, -1);
   12163           0 :   aTargetList.AdjustCountsForItem(item, 1);
   12164           0 : }
   12165             : 
   12166             : void
   12167           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12168             : Iterator::AppendItemsToList(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd,
   12169             :                             FrameConstructionItemList& aTargetList)
   12170             : {
   12171           0 :   NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
   12172           0 :   MOZ_ASSERT(&mList == &aEnd.mList, "End iterator for some other list?");
   12173             : 
   12174             :   // We can't just move our guts to the other list if it already has
   12175             :   // some information or if we're not moving our entire list.
   12176           0 :   if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty()) {
   12177           0 :     do {
   12178           0 :       AppendItemToList(aTargetList);
   12179             :     } while (*this != aEnd);
   12180             :     return;
   12181             :   }
   12182             : 
   12183             :   // Move our entire list of items into the empty target list.
   12184           0 :   aTargetList.mItems = std::move(mList.mItems);
   12185             : 
   12186             :   // Copy over the various counters
   12187           0 :   aTargetList.mInlineCount = mList.mInlineCount;
   12188           0 :   aTargetList.mBlockCount = mList.mBlockCount;
   12189           0 :   aTargetList.mLineParticipantCount = mList.mLineParticipantCount;
   12190           0 :   aTargetList.mItemCount = mList.mItemCount;
   12191           0 :   memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
   12192           0 :          sizeof(aTargetList.mDesiredParentCounts));
   12193             : 
   12194             :   // reset mList
   12195           0 :   mList.Reset(aFCtor);
   12196             : 
   12197             :   // Point ourselves to aEnd, as advertised
   12198           0 :   SetToEnd();
   12199           0 :   MOZ_ASSERT(*this == aEnd, "How did that happen?");
   12200             : }
   12201             : 
   12202             : void
   12203           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12204             : Iterator::InsertItem(FrameConstructionItem* aItem)
   12205             : {
   12206           0 :   if (IsDone()) {
   12207           0 :     mList.mItems.insertBack(aItem);
   12208             :   } else {
   12209             :     // Just insert the item before us.  There's no magic here.
   12210           0 :     mCurrent->setPrevious(aItem);
   12211             :   }
   12212           0 :   mList.AdjustCountsForItem(aItem, 1);
   12213             : 
   12214           0 :   MOZ_ASSERT(aItem->getNext() == mCurrent, "How did that happen?");
   12215           0 : }
   12216             : 
   12217             : void
   12218           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   12219             : Iterator::DeleteItemsTo(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd)
   12220             : {
   12221           0 :   MOZ_ASSERT(&mList == &aEnd.mList, "End iterator for some other list?");
   12222           0 :   MOZ_ASSERT(*this != aEnd, "Shouldn't be at aEnd yet");
   12223             : 
   12224           0 :   do {
   12225           0 :     NS_ASSERTION(!IsDone(), "Ran off end of list?");
   12226           0 :     FrameConstructionItem* item = mCurrent;
   12227           0 :     Next();
   12228           0 :     item->remove();
   12229           0 :     mList.AdjustCountsForItem(item, -1);
   12230           0 :     item->Delete(aFCtor);
   12231             :   } while (*this != aEnd);
   12232           0 : }
   12233             : 
   12234             : void
   12235           0 : nsCSSFrameConstructor::QuotesDirty()
   12236             : {
   12237           0 :   mQuotesDirty = true;
   12238           0 :   mPresShell->SetNeedLayoutFlush();
   12239           0 : }
   12240             : 
   12241             : void
   12242           0 : nsCSSFrameConstructor::CountersDirty()
   12243             : {
   12244           0 :   mCountersDirty = true;
   12245           0 :   mPresShell->SetNeedLayoutFlush();
   12246           0 : }
   12247             : 
   12248             : void*
   12249         285 : nsCSSFrameConstructor::AllocateFCItem()
   12250             : {
   12251             :   void* item;
   12252           0 :   if (mFirstFreeFCItem) {
   12253           0 :     item = mFirstFreeFCItem;
   12254         147 :     mFirstFreeFCItem = mFirstFreeFCItem->mNext;
   12255             :   } else {
   12256         138 :     item = mFCItemPool.Allocate(sizeof(FrameConstructionItem));
   12257             :   }
   12258         285 :   ++mFCItemsInUse;
   12259           0 :   return item;
   12260             : }
   12261             : 
   12262             : void
   12263           0 : nsCSSFrameConstructor::FreeFCItem(FrameConstructionItem* aItem)
   12264             : {
   12265         285 :   MOZ_ASSERT(mFCItemsInUse != 0);
   12266           0 :   if (--mFCItemsInUse == 0) {
   12267             :     // The arena is now unused - clear it but retain one chunk.
   12268           0 :     mFirstFreeFCItem = nullptr;
   12269          42 :     mFCItemPool.Clear();
   12270             :   } else {
   12271             :     // Prepend it to the list of free items.
   12272         243 :     FreeFCItemLink* item = reinterpret_cast<FreeFCItemLink*>(aItem);
   12273           0 :     item->mNext = mFirstFreeFCItem;
   12274         243 :     mFirstFreeFCItem = item;
   12275             :   }
   12276           0 : }
   12277             : 
   12278             : void
   12279          13 : nsCSSFrameConstructor::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const
   12280             : {
   12281          13 :   if (nsIFrame* rootFrame = GetRootFrame()) {
   12282           0 :     rootFrame->AddSizeOfExcludingThisForTree(aSizes);
   12283             :   }
   12284             : 
   12285             :   // This must be done after measuring from the frame tree, since frame
   12286             :   // manager will measure sizes of staled computed values and style
   12287             :   // structs, which only make sense after we know what are being used.
   12288          13 :   nsFrameManager::AddSizeOfIncludingThis(aSizes);
   12289             : 
   12290             :   // Measurement of the following members may be added later if DMD finds it
   12291             :   // is worthwhile:
   12292             :   // - mFCItemPool
   12293             :   // - mQuoteList
   12294             :   // - mCounterManager
   12295             : }

Generated by: LCOV version 1.13-14-ga5dd952