LCOV - code coverage report
Current view: top level - layout/base - nsCSSFrameConstructor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 2130 4971 42.8 %
Date: 2017-07-14 16:53:18 Functions: 154 257 59.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : // vim:cindent:ts=2:et:sw=2:
       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/DebugOnly.h"
      16             : #include "mozilla/ErrorResult.h"
      17             : #include "mozilla/dom/HTMLDetailsElement.h"
      18             : #include "mozilla/dom/HTMLSelectElement.h"
      19             : #include "mozilla/dom/HTMLSummaryElement.h"
      20             : #include "mozilla/EventStates.h"
      21             : #include "mozilla/Likely.h"
      22             : #include "mozilla/LinkedList.h"
      23             : #include "mozilla/PresShell.h"
      24             : #include "mozilla/ServoBindings.h"
      25             : #include "nsAbsoluteContainingBlock.h"
      26             : #include "nsCSSPseudoElements.h"
      27             : #include "nsIAtom.h"
      28             : #include "nsIFrameInlines.h"
      29             : #include "nsGkAtoms.h"
      30             : #include "nsPresContext.h"
      31             : #include "nsIDocument.h"
      32             : #include "nsTableFrame.h"
      33             : #include "nsTableColFrame.h"
      34             : #include "nsTableRowFrame.h"
      35             : #include "nsTableCellFrame.h"
      36             : #include "nsIDOMHTMLDocument.h"
      37             : #include "nsHTMLParts.h"
      38             : #include "nsIPresShell.h"
      39             : #include "nsUnicharUtils.h"
      40             : #include "mozilla/StyleSetHandle.h"
      41             : #include "mozilla/StyleSetHandleInlines.h"
      42             : #include "nsViewManager.h"
      43             : #include "nsStyleConsts.h"
      44             : #ifdef MOZ_XUL
      45             : #include "nsXULElement.h"
      46             : #include "mozilla/dom/BoxObject.h"
      47             : #endif // MOZ_XUL
      48             : #include "nsContainerFrame.h"
      49             : #include "nsNameSpaceManager.h"
      50             : #include "nsIComboboxControlFrame.h"
      51             : #include "nsComboboxControlFrame.h"
      52             : #include "nsIListControlFrame.h"
      53             : #include "nsIDOMCharacterData.h"
      54             : #include "nsPlaceholderFrame.h"
      55             : #include "nsTableRowGroupFrame.h"
      56             : #include "nsIFormControl.h"
      57             : #include "nsCSSAnonBoxes.h"
      58             : #include "nsTextFragment.h"
      59             : #include "nsIAnonymousContentCreator.h"
      60             : #include "nsBindingManager.h"
      61             : #include "nsXBLBinding.h"
      62             : #include "nsContentUtils.h"
      63             : #include "nsIScriptError.h"
      64             : #ifdef XP_MACOSX
      65             : #include "nsIDocShell.h"
      66             : #endif
      67             : #include "ChildIterator.h"
      68             : #include "nsError.h"
      69             : #include "nsLayoutUtils.h"
      70             : #include "nsAutoPtr.h"
      71             : #include "nsBoxFrame.h"
      72             : #include "nsBoxLayout.h"
      73             : #include "nsFlexContainerFrame.h"
      74             : #include "nsGridContainerFrame.h"
      75             : #include "RubyUtils.h"
      76             : #include "nsRubyFrame.h"
      77             : #include "nsRubyBaseFrame.h"
      78             : #include "nsRubyBaseContainerFrame.h"
      79             : #include "nsRubyTextFrame.h"
      80             : #include "nsRubyTextContainerFrame.h"
      81             : #include "nsImageFrame.h"
      82             : #include "nsIObjectLoadingContent.h"
      83             : #include "nsTArray.h"
      84             : #include "nsGenericDOMDataNode.h"
      85             : #include "mozilla/dom/Element.h"
      86             : #include "mozilla/dom/ElementInlines.h"
      87             : #include "nsAutoLayoutPhase.h"
      88             : #include "nsStyleStructInlines.h"
      89             : #include "nsPageContentFrame.h"
      90             : #include "mozilla/GeckoStyleContext.h"
      91             : #include "mozilla/RestyleManager.h"
      92             : #include "mozilla/RestyleManagerInlines.h"
      93             : #include "StickyScrollContainer.h"
      94             : #include "nsFieldSetFrame.h"
      95             : #include "nsInlineFrame.h"
      96             : #include "nsBlockFrame.h"
      97             : #include "nsCanvasFrame.h"
      98             : #include "nsFirstLetterFrame.h"
      99             : #include "nsGfxScrollFrame.h"
     100             : #include "nsPageFrame.h"
     101             : #include "nsSimplePageSequenceFrame.h"
     102             : #include "nsTableWrapperFrame.h"
     103             : #include "nsIScrollableFrame.h"
     104             : #include "nsBackdropFrame.h"
     105             : #include "nsTransitionManager.h"
     106             : #include "DetailsFrame.h"
     107             : #include "nsThemeConstants.h"
     108             : 
     109             : #ifdef MOZ_XUL
     110             : #include "nsIRootBox.h"
     111             : #endif
     112             : #ifdef ACCESSIBILITY
     113             : #include "nsAccessibilityService.h"
     114             : #endif
     115             : 
     116             : #include "nsXBLService.h"
     117             : 
     118             : #undef NOISY_FIRST_LETTER
     119             : 
     120             : #include "nsMathMLParts.h"
     121             : #include "mozilla/dom/SVGTests.h"
     122             : #include "nsSVGUtils.h"
     123             : 
     124             : #include "nsRefreshDriver.h"
     125             : #include "nsRuleProcessorData.h"
     126             : #include "nsTextNode.h"
     127             : #include "ActiveLayerTracker.h"
     128             : #include "nsIPresShellInlines.h"
     129             : 
     130             : using namespace mozilla;
     131             : using namespace mozilla::dom;
     132             : 
     133             : // An alias for convenience.
     134             : static const nsIFrame::ChildListID kPrincipalList = nsIFrame::kPrincipalList;
     135             : 
     136             : nsIFrame*
     137             : NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     138             : 
     139             : nsIFrame*
     140             : NS_NewHTMLVideoFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     141             : 
     142             : nsContainerFrame*
     143             : NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     144             : nsContainerFrame*
     145             : NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     146             : nsIFrame*
     147             : NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     148             : nsIFrame*
     149             : NS_NewSVGGeometryFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     150             : nsIFrame*
     151             : NS_NewSVGGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     152             : nsIFrame*
     153             : NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     154             : nsContainerFrame*
     155             : NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     156             : nsIFrame*
     157             : NS_NewSVGAFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     158             : nsIFrame*
     159             : NS_NewSVGSwitchFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     160             : nsIFrame*
     161             : NS_NewSVGSymbolFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     162             : nsIFrame*
     163             : NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     164             : nsIFrame*
     165             : NS_NewSVGContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     166             : nsIFrame*
     167             : NS_NewSVGUseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     168             : nsIFrame*
     169             : NS_NewSVGViewFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     170             : extern nsIFrame*
     171             : NS_NewSVGLinearGradientFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     172             : extern nsIFrame*
     173             : NS_NewSVGRadialGradientFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     174             : extern nsIFrame*
     175             : NS_NewSVGStopFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     176             : nsContainerFrame*
     177             : NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     178             : nsContainerFrame*
     179             : NS_NewSVGMarkerAnonChildFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     180             : extern nsIFrame*
     181             : NS_NewSVGImageFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     182             : nsIFrame*
     183             : NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     184             : nsIFrame*
     185             : NS_NewSVGFilterFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     186             : nsIFrame*
     187             : NS_NewSVGPatternFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     188             : nsIFrame*
     189             : NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     190             : nsIFrame*
     191             : NS_NewSVGFEContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     192             : nsIFrame*
     193             : NS_NewSVGFELeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     194             : nsIFrame*
     195             : NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     196             : nsIFrame*
     197             : NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     198             : 
     199             : #include "mozilla/dom/NodeInfo.h"
     200             : #include "prenv.h"
     201             : #include "nsNodeInfoManager.h"
     202             : #include "nsContentCreatorFunctions.h"
     203             : 
     204             : #ifdef DEBUG
     205             : // Set the environment variable GECKO_FRAMECTOR_DEBUG_FLAGS to one or
     206             : // more of the following flags (comma separated) for handy debug
     207             : // output.
     208             : static bool gNoisyContentUpdates = false;
     209             : static bool gReallyNoisyContentUpdates = false;
     210             : static bool gNoisyInlineConstruction = false;
     211             : 
     212             : struct FrameCtorDebugFlags {
     213             :   const char* name;
     214             :   bool* on;
     215             : };
     216             : 
     217             : static FrameCtorDebugFlags gFlags[] = {
     218             :   { "content-updates",              &gNoisyContentUpdates },
     219             :   { "really-noisy-content-updates", &gReallyNoisyContentUpdates },
     220             :   { "noisy-inline",                 &gNoisyInlineConstruction }
     221             : };
     222             : 
     223             : #define NUM_DEBUG_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
     224             : #endif
     225             : 
     226             : 
     227             : #ifdef MOZ_XUL
     228             : #include "nsMenuFrame.h"
     229             : #include "nsPopupSetFrame.h"
     230             : #include "nsTreeColFrame.h"
     231             : #include "nsIBoxObject.h"
     232             : #include "nsPIListBoxObject.h"
     233             : #include "nsListBoxBodyFrame.h"
     234             : #include "nsListItemFrame.h"
     235             : #include "nsXULLabelFrame.h"
     236             : 
     237             : //------------------------------------------------------------------
     238             : 
     239             : nsIFrame*
     240             : NS_NewAutoRepeatBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     241             : 
     242             : nsContainerFrame*
     243             : NS_NewRootBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     244             : 
     245             : nsContainerFrame*
     246             : NS_NewDocElementBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     247             : 
     248             : nsIFrame*
     249             : NS_NewDeckFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     250             : 
     251             : nsIFrame*
     252             : NS_NewLeafBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     253             : 
     254             : nsIFrame*
     255             : NS_NewStackFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     256             : 
     257             : nsIFrame*
     258             : NS_NewProgressMeterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     259             : 
     260             : nsIFrame*
     261             : NS_NewRangeFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     262             : 
     263             : nsIFrame*
     264             : NS_NewImageBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     265             : 
     266             : nsIFrame*
     267             : NS_NewTextBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     268             : 
     269             : nsIFrame*
     270             : NS_NewGroupBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     271             : 
     272             : nsIFrame*
     273             : NS_NewButtonBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     274             : 
     275             : nsIFrame*
     276             : NS_NewSplitterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     277             : 
     278             : nsIFrame*
     279             : NS_NewMenuPopupFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     280             : 
     281             : nsIFrame*
     282             : NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     283             : 
     284             : nsIFrame*
     285             : NS_NewMenuFrame (nsIPresShell* aPresShell, nsStyleContext* aContext, uint32_t aFlags);
     286             : 
     287             : nsIFrame*
     288             : NS_NewMenuBarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     289             : 
     290             : nsIFrame*
     291             : NS_NewTreeBodyFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     292             : 
     293             : // grid
     294             : nsresult
     295             : NS_NewGridLayout2 ( nsIPresShell* aPresShell, nsBoxLayout** aNewLayout );
     296             : nsIFrame*
     297             : NS_NewGridRowLeafFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     298             : nsIFrame*
     299             : NS_NewGridRowGroupFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     300             : 
     301             : // end grid
     302             : 
     303             : nsIFrame*
     304             : NS_NewTitleBarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     305             : 
     306             : nsIFrame*
     307             : NS_NewResizerFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     308             : 
     309             : 
     310             : #endif
     311             : 
     312             : nsHTMLScrollFrame*
     313             : NS_NewHTMLScrollFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot);
     314             : 
     315             : nsXULScrollFrame*
     316             : NS_NewXULScrollFrame(nsIPresShell* aPresShell, nsStyleContext* aContext,
     317             :                      bool aIsRoot, bool aClipAllDescendants);
     318             : 
     319             : nsIFrame*
     320             : NS_NewSliderFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     321             : 
     322             : nsIFrame*
     323             : NS_NewScrollbarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     324             : 
     325             : nsIFrame*
     326             : NS_NewScrollbarButtonFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     327             : 
     328             : 
     329             : #ifdef NOISY_FINDFRAME
     330             : static int32_t FFWC_totalCount=0;
     331             : static int32_t FFWC_doLoop=0;
     332             : static int32_t FFWC_doSibling=0;
     333             : static int32_t FFWC_recursions=0;
     334             : static int32_t FFWC_nextInFlows=0;
     335             : #endif
     336             : 
     337             : // Wrapper class to handle stack-construction a TreeMatchContext only if we're
     338             : // using the Gecko style system.
     339          48 : class MOZ_STACK_CLASS TreeMatchContextHolder
     340             : {
     341             : public:
     342          48 :   explicit TreeMatchContextHolder(nsIDocument* aDocument)
     343          48 :   {
     344          48 :     if (!aDocument->IsStyledByServo()) {
     345          96 :       mMaybeTreeMatchContext.emplace(aDocument,
     346          48 :                                      TreeMatchContext::ForFrameConstruction);
     347             :     }
     348          48 :   }
     349             : 
     350          24 :   bool Exists() const { return mMaybeTreeMatchContext.isSome(); }
     351          48 :   operator TreeMatchContext*() { return mMaybeTreeMatchContext.ptrOr(nullptr); }
     352             : 
     353          24 :   TreeMatchContext* operator ->()
     354             :   {
     355          24 :     MOZ_ASSERT(mMaybeTreeMatchContext.isSome());
     356          24 :     return mMaybeTreeMatchContext.ptr();
     357             :   }
     358             : 
     359             : private:
     360             :   Maybe<TreeMatchContext> mMaybeTreeMatchContext;
     361             : };
     362             : 
     363             : // Returns true if aFrame is an anonymous flex/grid item.
     364             : static inline bool
     365          77 : IsAnonymousFlexOrGridItem(const nsIFrame* aFrame)
     366             : {
     367          77 :   const nsIAtom* pseudoType = aFrame->StyleContext()->GetPseudo();
     368         154 :   return pseudoType == nsCSSAnonBoxes::anonymousFlexItem ||
     369         154 :          pseudoType == nsCSSAnonBoxes::anonymousGridItem;
     370             : }
     371             : 
     372             : // Returns true if aFrame is a flex/grid container.
     373             : static inline bool
     374         606 : IsFlexOrGridContainer(const nsIFrame* aFrame)
     375             : {
     376         606 :   const LayoutFrameType t = aFrame->Type();
     377         606 :   return t == LayoutFrameType::FlexContainer ||
     378         606 :          t == LayoutFrameType::GridContainer;
     379             : }
     380             : 
     381             : // Returns true IFF the given nsIFrame is a nsFlexContainerFrame and
     382             : // represents a -webkit-{inline-}box container.
     383             : static inline bool
     384           0 : IsFlexContainerForLegacyBox(const nsIFrame* aFrame)
     385             : {
     386           0 :   return aFrame->IsFlexContainerFrame() &&
     387           0 :          aFrame->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX);
     388             : }
     389             : 
     390             : #if DEBUG
     391             : static void
     392           0 : AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
     393             :                                     const nsIFrame* aParent)
     394             : {
     395           0 :   MOZ_ASSERT(IsAnonymousFlexOrGridItem(aChild),
     396             :              "expected an anonymous flex or grid item child frame");
     397           0 :   MOZ_ASSERT(aParent, "expected a parent frame");
     398           0 :   const nsIAtom* pseudoType = aChild->StyleContext()->GetPseudo();
     399           0 :   if (pseudoType == nsCSSAnonBoxes::anonymousFlexItem) {
     400           0 :     MOZ_ASSERT(aParent->IsFlexContainerFrame(),
     401             :                "anonymous flex items should only exist as children "
     402             :                "of flex container frames");
     403             :   } else {
     404           0 :     MOZ_ASSERT(aParent->IsGridContainerFrame(),
     405             :                "anonymous grid items should only exist as children "
     406             :                "of grid container frames");
     407             :   }
     408           0 : }
     409             : #else
     410             : #define AssertAnonymousFlexOrGridItemParent(x, y) do { /* nothing */ } while(0)
     411             : #endif
     412             : 
     413             : static inline nsContainerFrame*
     414           0 : GetFieldSetBlockFrame(nsIFrame* aFieldsetFrame)
     415             : {
     416             :   // Depends on the fieldset child frame order - see ConstructFieldSetFrame() below.
     417           0 :   nsIFrame* firstChild = aFieldsetFrame->PrincipalChildList().FirstChild();
     418           0 :   nsIFrame* inner = firstChild && firstChild->GetNextSibling() ? firstChild->GetNextSibling() : firstChild;
     419           0 :   return inner ? inner->GetContentInsertionFrame() : nullptr;
     420             : }
     421             : 
     422             : #define FCDATA_DECL(_flags, _func)                            \
     423             :   { _flags, { (FrameCreationFunc)_func }, nullptr, nullptr }
     424             : #define FCDATA_WITH_WRAPPING_BLOCK(_flags, _func, _anon_box)  \
     425             :   { _flags | FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS,        \
     426             :       { (FrameCreationFunc)_func }, nullptr, &_anon_box }
     427             : 
     428             : #define UNREACHABLE_FCDATA()                                  \
     429             :   { 0, { (FrameCreationFunc)nullptr }, nullptr, nullptr }
     430             : //----------------------------------------------------------------------
     431             : 
     432             : /**
     433             :  * True if aFrame is an actual inline frame in the sense of non-replaced
     434             :  * display:inline CSS boxes.  In other words, it can be affected by {ib}
     435             :  * splitting and can contain first-letter frames.  Basically, this is either an
     436             :  * inline frame (positioned or otherwise) or an line frame (this last because
     437             :  * it can contain first-letter and because inserting blocks in the middle of it
     438             :  * needs to terminate it).
     439             :  */
     440             : static bool
     441          44 : IsInlineFrame(const nsIFrame* aFrame)
     442             : {
     443          44 :   return aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
     444             : }
     445             : 
     446             : /**
     447             :  * True if aFrame is an instance of an SVG frame class or is an inline/block
     448             :  * frame being used for SVG text.
     449             :  */
     450             : static bool
     451         527 : IsFrameForSVG(const nsIFrame* aFrame)
     452             : {
     453         896 :   return aFrame->IsFrameOfType(nsIFrame::eSVG) ||
     454         896 :          nsSVGUtils::IsInSVGTextSubtree(aFrame);
     455             : }
     456             : 
     457             : /**
     458             :  * Returns true iff aFrame explicitly prevents its descendants from floating
     459             :  * (at least, down to the level of descendants which themselves are
     460             :  * float-containing blocks -- those will manage the floating status of any
     461             :  * lower-level descendents inside them, of course).
     462             :  */
     463             : static bool
     464         540 : ShouldSuppressFloatingOfDescendants(nsIFrame* aFrame)
     465             : {
     466        1080 :   return aFrame->IsFrameOfType(nsIFrame::eMathML) ||
     467         818 :     aFrame->IsXULBoxFrame() ||
     468         818 :     ::IsFlexOrGridContainer(aFrame);
     469             : }
     470             : 
     471             : /**
     472             :  * If any children require a block parent, return the first such child.
     473             :  * Otherwise return null.
     474             :  */
     475             : static nsIContent*
     476         223 : AnyKidsNeedBlockParent(nsIFrame *aFrameList)
     477             : {
     478         519 :   for (nsIFrame *k = aFrameList; k; k = k->GetNextSibling()) {
     479             :     // Line participants, such as text and inline frames, can't be
     480             :     // directly inside a XUL box; they must be wrapped in an
     481             :     // intermediate block.
     482         301 :     if (k->IsFrameOfType(nsIFrame::eLineParticipant)) {
     483           5 :       return k->GetContent();
     484             :     }
     485             :   }
     486         218 :   return nullptr;
     487             : }
     488             : 
     489             : // Reparent a frame into a wrapper frame that is a child of its old parent.
     490             : static void
     491           5 : ReparentFrame(RestyleManager* aRestyleManager,
     492             :               nsContainerFrame* aNewParentFrame,
     493             :               nsIFrame* aFrame)
     494             : {
     495           5 :   aFrame->SetParent(aNewParentFrame);
     496           5 :   aRestyleManager->ReparentStyleContext(aFrame);
     497           5 : }
     498             : 
     499             : static void
     500           5 : ReparentFrames(nsCSSFrameConstructor* aFrameConstructor,
     501             :                nsContainerFrame* aNewParentFrame,
     502             :                const nsFrameList& aFrameList)
     503             : {
     504           5 :   RestyleManager* restyleManager = aFrameConstructor->RestyleManager();
     505          10 :   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
     506           5 :     ReparentFrame(restyleManager, aNewParentFrame, e.get());
     507             :   }
     508           5 : }
     509             : 
     510             : //----------------------------------------------------------------------
     511             : //
     512             : // When inline frames get weird and have block frames in them, we
     513             : // annotate them to help us respond to incremental content changes
     514             : // more easily.
     515             : 
     516             : static inline bool
     517         287 : IsFramePartOfIBSplit(nsIFrame* aFrame)
     518             : {
     519         287 :   bool result = (aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) != 0;
     520         287 :   MOZ_ASSERT(!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) ||
     521             :                         static_cast<nsInlineFrame*>(do_QueryFrame(aFrame)),
     522             :              "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT");
     523         287 :   return result;
     524             : }
     525             : 
     526           0 : static nsContainerFrame* GetIBSplitSibling(nsIFrame* aFrame)
     527             : {
     528           0 :   NS_PRECONDITION(IsFramePartOfIBSplit(aFrame), "Shouldn't call this");
     529             : 
     530             :   // We only store the "ib-split sibling" annotation with the first
     531             :   // frame in the continuation chain. Walk back to find that frame now.
     532           0 :   return aFrame->FirstContinuation()->
     533           0 :            GetProperty(nsIFrame::IBSplitSibling());
     534             : }
     535             : 
     536           0 : static nsContainerFrame* GetIBSplitPrevSibling(nsIFrame* aFrame)
     537             : {
     538           0 :   NS_PRECONDITION(IsFramePartOfIBSplit(aFrame), "Shouldn't call this");
     539             : 
     540             :   // We only store the ib-split sibling annotation with the first
     541             :   // frame in the continuation chain. Walk back to find that frame now.
     542           0 :   return aFrame->FirstContinuation()->
     543           0 :            GetProperty(nsIFrame::IBSplitPrevSibling());
     544             : }
     545             : 
     546             : static nsContainerFrame*
     547           0 : GetLastIBSplitSibling(nsIFrame* aFrame, bool aReturnEmptyTrailingInline)
     548             : {
     549           0 :   for (nsIFrame *frame = aFrame, *next; ; frame = next) {
     550           0 :     next = GetIBSplitSibling(frame);
     551           0 :     if (!next ||
     552           0 :         (!aReturnEmptyTrailingInline && !next->PrincipalChildList().FirstChild() &&
     553           0 :          !GetIBSplitSibling(next))) {
     554           0 :       NS_ASSERTION(!next || !frame->IsInlineOutside(),
     555             :                    "Should have a block here!");
     556           0 :       return static_cast<nsContainerFrame*>(frame);
     557             :     }
     558             :   }
     559             :   NS_NOTREACHED("unreachable code");
     560             :   return nullptr;
     561             : }
     562             : 
     563             : static void
     564           0 : SetFrameIsIBSplit(nsContainerFrame* aFrame, nsContainerFrame* aIBSplitSibling)
     565             : {
     566           0 :   NS_PRECONDITION(aFrame, "bad args!");
     567             : 
     568             :   // We should be the only continuation
     569           0 :   NS_ASSERTION(!aFrame->GetPrevContinuation(),
     570             :                "assigning ib-split sibling to other than first continuation!");
     571           0 :   NS_ASSERTION(!aFrame->GetNextContinuation() ||
     572             :                IsFramePartOfIBSplit(aFrame->GetNextContinuation()),
     573             :                "should have no non-ib-split continuations here");
     574             : 
     575             :   // Mark the frame as ib-split.
     576           0 :   aFrame->AddStateBits(NS_FRAME_PART_OF_IBSPLIT);
     577             : 
     578           0 :   if (aIBSplitSibling) {
     579           0 :     NS_ASSERTION(!aIBSplitSibling->GetPrevContinuation(),
     580             :                  "assigning something other than the first continuation as the "
     581             :                  "ib-split sibling");
     582             : 
     583             :     // Store the ib-split sibling (if we were given one) with the
     584             :     // first frame in the flow.
     585           0 :     aFrame->SetProperty(nsIFrame::IBSplitSibling(), aIBSplitSibling);
     586           0 :     aIBSplitSibling->SetProperty(nsIFrame::IBSplitPrevSibling(), aFrame);
     587             :   }
     588           0 : }
     589             : 
     590             : static nsIFrame*
     591           0 : GetIBContainingBlockFor(nsIFrame* aFrame)
     592             : {
     593           0 :   NS_PRECONDITION(IsFramePartOfIBSplit(aFrame),
     594             :                   "GetIBContainingBlockFor() should only be called on known IB frames");
     595             : 
     596             :   // Get the first "normal" ancestor of the target frame.
     597             :   nsIFrame* parentFrame;
     598             :   do {
     599           0 :     parentFrame = aFrame->GetParent();
     600             : 
     601           0 :     if (! parentFrame) {
     602           0 :       NS_ERROR("no unsplit block frame in IB hierarchy");
     603           0 :       return aFrame;
     604             :     }
     605             : 
     606             :     // Note that we ignore non-ib-split frames which have a pseudo on their
     607             :     // style context -- they're not the frames we're looking for!  In
     608             :     // particular, they may be hiding a real parent that _is_ in an ib-split.
     609           0 :     if (!IsFramePartOfIBSplit(parentFrame) &&
     610           0 :         !parentFrame->StyleContext()->GetPseudo())
     611           0 :       break;
     612             : 
     613           0 :     aFrame = parentFrame;
     614             :   } while (1);
     615             : 
     616             :   // post-conditions
     617           0 :   NS_ASSERTION(parentFrame, "no normal ancestor found for ib-split frame "
     618             :                             "in GetIBContainingBlockFor");
     619           0 :   NS_ASSERTION(parentFrame != aFrame, "parentFrame is actually the child frame - bogus reslt");
     620             : 
     621           0 :   return parentFrame;
     622             : }
     623             : 
     624             : //----------------------------------------------------------------------
     625             : 
     626             : // Block/inline frame construction logic. We maintain a few invariants here:
     627             : //
     628             : // 1. Block frames contain block and inline frames.
     629             : //
     630             : // 2. Inline frames only contain inline frames. If an inline parent has a block
     631             : // child then the block child is migrated upward until it lands in a block
     632             : // parent (the inline frames containing block is where it will end up).
     633             : 
     634             : // After this function returns, aLink is pointing to the first link at or
     635             : // after its starting position for which the next frame is a block.  If there
     636             : // is no such link, it points to the end of the list.
     637             : static void
     638           0 : FindFirstBlock(nsFrameList::FrameLinkEnumerator& aLink)
     639             : {
     640           0 :   for ( ; !aLink.AtEnd(); aLink.Next()) {
     641           0 :     if (!aLink.NextFrame()->IsInlineOutside()) {
     642           0 :       return;
     643             :     }
     644             :   }
     645             : }
     646             : 
     647             : // This function returns a frame link enumerator pointing to the first link in
     648             : // the list for which the next frame is not block.  If there is no such link,
     649             : // it points to the end of the list.
     650             : static nsFrameList::FrameLinkEnumerator
     651           0 : FindFirstNonBlock(const nsFrameList& aList)
     652             : {
     653           0 :   nsFrameList::FrameLinkEnumerator link(aList);
     654           0 :   for (; !link.AtEnd(); link.Next()) {
     655           0 :     if (link.NextFrame()->IsInlineOutside()) {
     656           0 :       break;
     657             :     }
     658             :   }
     659           0 :   return link;
     660             : }
     661             : 
     662             : inline void
     663          72 : SetInitialSingleChild(nsContainerFrame* aParent, nsIFrame* aFrame)
     664             : {
     665          72 :   NS_PRECONDITION(!aFrame->GetNextSibling(), "Should be using a frame list");
     666          72 :   nsFrameList temp(aFrame, aFrame);
     667          72 :   aParent->SetInitialChildList(kPrincipalList, temp);
     668          72 : }
     669             : 
     670             : // -----------------------------------------------------------
     671             : 
     672             : // Structure used when constructing formatting object trees.
     673        2851 : struct nsFrameItems : public nsFrameList
     674             : {
     675             :   // Appends the frame to the end of the list
     676             :   void AddChild(nsIFrame* aChild);
     677             : };
     678             : 
     679             : void
     680         562 : nsFrameItems::AddChild(nsIFrame* aChild)
     681             : {
     682         562 :   NS_PRECONDITION(aChild, "nsFrameItems::AddChild");
     683             : 
     684             :   // It'd be really nice if we could just AppendFrames(kPrincipalList, aChild) here,
     685             :   // but some of our callers put frames that have different
     686             :   // parents (caption, I'm looking at you) on the same framelist, and
     687             :   // nsFrameList asserts if you try to do that.
     688         562 :   if (IsEmpty()) {
     689         336 :     SetFrames(aChild);
     690             :   }
     691             :   else {
     692         226 :     NS_ASSERTION(aChild != mLastChild,
     693             :                  "Same frame being added to frame list twice?");
     694         226 :     mLastChild->SetNextSibling(aChild);
     695         226 :     mLastChild = nsLayoutUtils::GetLastSibling(aChild);
     696             :   }
     697         562 : }
     698             : 
     699             : // -----------------------------------------------------------
     700             : 
     701             : // Structure used when constructing formatting object trees. Contains
     702             : // state information needed for absolutely positioned elements
     703             : struct nsAbsoluteItems : nsFrameItems {
     704             :   // containing block for absolutely positioned elements
     705             :   nsContainerFrame* containingBlock;
     706             : 
     707             :   explicit nsAbsoluteItems(nsContainerFrame* aContainingBlock);
     708             : #ifdef DEBUG
     709             :   // XXXbz Does this need a debug-only assignment operator that nulls out the
     710             :   // childList in the nsAbsoluteItems we're copying?  Introducing a difference
     711             :   // between debug and non-debug behavior seems bad, so I guess not...
     712        4604 :   ~nsAbsoluteItems() {
     713        2302 :     NS_ASSERTION(!FirstChild(),
     714             :                  "Dangling child list.  Someone forgot to insert it?");
     715        2302 :   }
     716             : #endif
     717             : 
     718             :   // Appends the frame to the end of the list
     719             :   void AddChild(nsIFrame* aChild);
     720             : };
     721             : 
     722        2302 : nsAbsoluteItems::nsAbsoluteItems(nsContainerFrame* aContainingBlock)
     723        2302 :   : containingBlock(aContainingBlock)
     724             : {
     725        2302 : }
     726             : 
     727             : // Additional behavior is that it sets the frame's NS_FRAME_OUT_OF_FLOW flag
     728             : void
     729           0 : nsAbsoluteItems::AddChild(nsIFrame* aChild)
     730             : {
     731           0 :   aChild->AddStateBits(NS_FRAME_OUT_OF_FLOW);
     732           0 :   NS_ASSERTION(aChild->GetPlaceholderFrame(),
     733             :                "Child without placeholder being added to nsAbsoluteItems?");
     734           0 :   nsFrameItems::AddChild(aChild);
     735           0 : }
     736             : 
     737             : // -----------------------------------------------------------
     738             : 
     739             : // Structure for saving the existing state when pushing/poping containing
     740             : // blocks. The destructor restores the state to its previous state
     741             : class MOZ_STACK_CLASS nsFrameConstructorSaveState {
     742             : public:
     743             :   typedef nsIFrame::ChildListID ChildListID;
     744             :   nsFrameConstructorSaveState();
     745             :   ~nsFrameConstructorSaveState();
     746             : 
     747             : private:
     748             :   nsAbsoluteItems* mItems;      // pointer to struct whose data we save/restore
     749             :   nsAbsoluteItems  mSavedItems; // copy of original data
     750             : 
     751             :   // The name of the child list in which our frames would belong
     752             :   ChildListID mChildListID;
     753             :   nsFrameConstructorState* mState;
     754             : 
     755             :   // State used only when we're saving the abs-pos state for a transformed
     756             :   // element.
     757             :   nsAbsoluteItems mSavedFixedItems;
     758             : 
     759             :   bool mSavedFixedPosIsAbsPos;
     760             : 
     761             :   friend class nsFrameConstructorState;
     762             : };
     763             : 
     764             : // Structure used to keep track of a list of bindings we need to call
     765             : // AddToAttachedQueue on.  These should be in post-order depth-first
     766             : // flattened tree traversal order.
     767             : struct PendingBinding : public LinkedListElement<PendingBinding>
     768             : {
     769             : #ifdef NS_BUILD_REFCNT_LOGGING
     770         332 :   PendingBinding() {
     771         332 :     MOZ_COUNT_CTOR(PendingBinding);
     772         332 :   }
     773         664 :   ~PendingBinding() {
     774         332 :     MOZ_COUNT_DTOR(PendingBinding);
     775         332 :   }
     776             : #endif
     777             : 
     778             :   RefPtr<nsXBLBinding> mBinding;
     779             : };
     780             : 
     781             : // Structure used for maintaining state information during the
     782             : // frame construction process
     783             : class MOZ_STACK_CLASS nsFrameConstructorState {
     784             : public:
     785             :   typedef nsIFrame::ChildListID ChildListID;
     786             : 
     787             :   nsPresContext            *mPresContext;
     788             :   nsIPresShell             *mPresShell;
     789             :   nsFrameManager           *mFrameManager;
     790             : 
     791             : #ifdef MOZ_XUL
     792             :   // Frames destined for the kPopupList.
     793             :   nsAbsoluteItems           mPopupItems;
     794             : #endif
     795             : 
     796             :   // Containing block information for out-of-flow frames.
     797             :   nsAbsoluteItems           mFixedItems;
     798             :   nsAbsoluteItems           mAbsoluteItems;
     799             :   nsAbsoluteItems           mFloatedItems;
     800             :   // The containing block of a frame in the top layer is defined by the
     801             :   // spec: fixed-positioned frames are children of the viewport frame,
     802             :   // and absolutely-positioned frames are children of the initial
     803             :   // containing block. They would not be caught by any other containing
     804             :   // block, e.g. frames with transform or filter.
     805             :   nsAbsoluteItems           mTopLayerFixedItems;
     806             :   nsAbsoluteItems           mTopLayerAbsoluteItems;
     807             : 
     808             :   nsCOMPtr<nsILayoutHistoryState> mFrameState;
     809             :   // These bits will be added to the state bits of any frame we construct
     810             :   // using this state.
     811             :   nsFrameState              mAdditionalStateBits;
     812             : 
     813             :   // When working with the transform and filter properties, we want to hook
     814             :   // the abs-pos and fixed-pos lists together, since such
     815             :   // elements are fixed-pos containing blocks.  This flag determines
     816             :   // whether or not we want to wire the fixed-pos and abs-pos lists
     817             :   // together.
     818             :   bool                      mFixedPosIsAbsPos;
     819             : 
     820             :   // A boolean to indicate whether we have a "pending" popupgroup.  That is, we
     821             :   // have already created the FrameConstructionItem for the root popupgroup but
     822             :   // we have not yet created the relevant frame.
     823             :   bool                      mHavePendingPopupgroup;
     824             : 
     825             :   // If false (which is the default) then call SetPrimaryFrame() as needed
     826             :   // during frame construction.  If true, don't make any SetPrimaryFrame()
     827             :   // calls, except for generated content which doesn't have a primary frame
     828             :   // yet.  The mCreatingExtraFrames == true mode is meant to be used for
     829             :   // construction of random "extra" frames for elements via normal frame
     830             :   // construction APIs (e.g. replication of things across pages in paginated
     831             :   // mode).
     832             :   bool                      mCreatingExtraFrames;
     833             : 
     834             :   nsCOMArray<nsIContent>    mGeneratedTextNodesWithInitializer;
     835             : 
     836             :   // Selector matching context for. This is null when we're using the Servo style
     837             :   // system.
     838             :   TreeMatchContext*         mTreeMatchContext;
     839             : 
     840             :   // Constructor
     841             :   // Use the passed-in history state.
     842             :   //
     843             :   // aTreeMatchContext is null when we're using the Servo style system.
     844             :   nsFrameConstructorState(
     845             :     nsIPresShell* aPresShell,
     846             :     TreeMatchContext* aTreeMatchContext,
     847             :     nsContainerFrame* aFixedContainingBlock,
     848             :     nsContainerFrame* aAbsoluteContainingBlock,
     849             :     nsContainerFrame* aFloatContainingBlock,
     850             :     already_AddRefed<nsILayoutHistoryState> aHistoryState);
     851             :   // Get the history state from the pres context's pres shell.
     852             :   nsFrameConstructorState(nsIPresShell* aPresShell,
     853             :                           TreeMatchContext* aTreeMatchContext,
     854             :                           nsContainerFrame* aFixedContainingBlock,
     855             :                           nsContainerFrame* aAbsoluteContainingBlock,
     856             :                           nsContainerFrame* aFloatContainingBlock);
     857             : 
     858             :   ~nsFrameConstructorState();
     859             : 
     860         491 :   bool HasAncestorFilter()
     861             :   {
     862         491 :     return mTreeMatchContext && mTreeMatchContext->mAncestorFilter.HasFilter();
     863             :   }
     864             : 
     865             :   // Function to push the existing absolute containing block state and
     866             :   // create a new scope. Code that uses this function should get matching
     867             :   // logic in GetAbsoluteContainingBlock.
     868             :   // Also makes aNewAbsoluteContainingBlock the containing block for
     869             :   // fixed-pos elements if necessary.
     870             :   // aPositionedFrame is the frame whose style actually makes
     871             :   // aNewAbsoluteContainingBlock a containing block. E.g. for a scrollable element
     872             :   // aPositionedFrame is the element's primary frame and
     873             :   // aNewAbsoluteContainingBlock is the scrolled frame.
     874             :   void PushAbsoluteContainingBlock(nsContainerFrame* aNewAbsoluteContainingBlock,
     875             :                                    nsIFrame* aPositionedFrame,
     876             :                                    nsFrameConstructorSaveState& aSaveState);
     877             : 
     878             :   // Function to push the existing float containing block state and
     879             :   // create a new scope. Code that uses this function should get matching
     880             :   // logic in GetFloatContainingBlock.
     881             :   // Pushing a null float containing block forbids any frames from being
     882             :   // floated until a new float containing block is pushed.
     883             :   // XXX we should get rid of null float containing blocks and teach the
     884             :   // various frame classes to deal with floats instead.
     885             :   void PushFloatContainingBlock(nsContainerFrame* aNewFloatContainingBlock,
     886             :                                 nsFrameConstructorSaveState& aSaveState);
     887             : 
     888             :   // Function to return the proper geometric parent for a frame with display
     889             :   // struct given by aStyleDisplay and parent's frame given by
     890             :   // aContentParentFrame.
     891             :   nsContainerFrame* GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
     892             :                                        nsContainerFrame* aContentParentFrame) const;
     893             : 
     894             :   /**
     895             :    * Function to add a new frame to the right frame list.  This MUST be called
     896             :    * on frames before their children have been processed if the frames might
     897             :    * conceivably be out-of-flow; otherwise cleanup in error cases won't work
     898             :    * right.  Also, this MUST be called on frames after they have been
     899             :    * initialized.
     900             :    * @param aNewFrame the frame to add
     901             :    * @param aFrameItems the list to add in-flow frames to
     902             :    * @param aContent the content pointer for aNewFrame
     903             :    * @param aStyleContext the style context resolved for aContent
     904             :    * @param aParentFrame the parent frame for the content if it were in-flow
     905             :    * @param aCanBePositioned pass false if the frame isn't allowed to be
     906             :    *        positioned
     907             :    * @param aCanBeFloated pass false if the frame isn't allowed to be
     908             :    *        floated
     909             :    * @param aIsOutOfFlowPopup pass true if the frame is an out-of-flow popup
     910             :    *        (XUL-only)
     911             :    */
     912             :   void AddChild(nsIFrame* aNewFrame,
     913             :                 nsFrameItems& aFrameItems,
     914             :                 nsIContent* aContent,
     915             :                 nsStyleContext* aStyleContext,
     916             :                 nsContainerFrame* aParentFrame,
     917             :                 bool aCanBePositioned = true,
     918             :                 bool aCanBeFloated = true,
     919             :                 bool aIsOutOfFlowPopup = false,
     920             :                 bool aInsertAfter = false,
     921             :                 nsIFrame* aInsertAfterFrame = nullptr);
     922             : 
     923             :   /**
     924             :    * Function to return the fixed-pos element list.  Normally this will just hand back the
     925             :    * fixed-pos element list, but in case we're dealing with a transformed element that's
     926             :    * acting as an abs-pos and fixed-pos container, we'll hand back the abs-pos list.  Callers should
     927             :    * use this function if they want to get the list acting as the fixed-pos item parent.
     928             :    */
     929           6 :   nsAbsoluteItems& GetFixedItems()
     930             :   {
     931           6 :     return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
     932             :   }
     933          24 :   const nsAbsoluteItems& GetFixedItems() const
     934             :   {
     935          24 :     return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
     936             :   }
     937             : 
     938             : 
     939             :   /**
     940             :    * class to automatically push and pop a pending binding in the frame
     941             :    * constructor state.  See nsCSSFrameConstructor::FrameConstructionItem
     942             :    * mPendingBinding documentation.
     943             :    */
     944             :   class PendingBindingAutoPusher;
     945             :   friend class PendingBindingAutoPusher;
     946             :   class MOZ_STACK_CLASS PendingBindingAutoPusher {
     947             :   public:
     948         328 :     PendingBindingAutoPusher(nsFrameConstructorState& aState,
     949         328 :                              PendingBinding* aPendingBinding) :
     950             :       mState(aState),
     951         328 :       mPendingBinding(aState.mCurrentPendingBindingInsertionPoint)
     952             :         {
     953         328 :           if (aPendingBinding) {
     954         113 :             aState.mCurrentPendingBindingInsertionPoint = aPendingBinding;
     955             :           }
     956         328 :         }
     957             : 
     958         328 :     ~PendingBindingAutoPusher()
     959         328 :       {
     960         328 :         mState.mCurrentPendingBindingInsertionPoint = mPendingBinding;
     961         328 :       }
     962             : 
     963             :   private:
     964             :     nsFrameConstructorState& mState;
     965             :     PendingBinding* mPendingBinding;
     966             :   };
     967             : 
     968             :   /**
     969             :    * Add a new pending binding to the list
     970             :    */
     971         237 :   void AddPendingBinding(PendingBinding* aPendingBinding) {
     972         237 :     if (mCurrentPendingBindingInsertionPoint) {
     973         167 :       mCurrentPendingBindingInsertionPoint->setPrevious(aPendingBinding);
     974             :     } else {
     975          70 :       mPendingBindings.insertBack(aPendingBinding);
     976             :     }
     977         237 :   }
     978             : 
     979             : protected:
     980             :   friend class nsFrameConstructorSaveState;
     981             : 
     982             :   /**
     983             :    * ProcessFrameInsertions takes the frames in aFrameItems and adds them as
     984             :    * kids to the aChildListID child list of |aFrameItems.containingBlock|.
     985             :    */
     986             :   void ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
     987             :                               ChildListID aChildListID);
     988             : 
     989             :   /**
     990             :    * GetOutOfFlowFrameItems selects the out-of-flow frame list the new
     991             :    * frame should be added to. If the frame shouldn't be added to any
     992             :    * out-of-flow list, it returns nullptr. The corresponding type of
     993             :    * placeholder is also returned via the aPlaceholderType parameter
     994             :    * if this method doesn't return nullptr. The caller should check
     995             :    * whether the returned list really has a containing block.
     996             :    */
     997             :   nsAbsoluteItems* GetOutOfFlowFrameItems(nsIFrame* aNewFrame,
     998             :                                           bool aCanBePositioned,
     999             :                                           bool aCanBeFloated,
    1000             :                                           bool aIsOutOfFlowPopup,
    1001             :                                           nsFrameState* aPlaceholderType);
    1002             : 
    1003             :   void ConstructBackdropFrameFor(nsIContent* aContent, nsIFrame* aFrame);
    1004             : 
    1005             :   // Our list of all pending bindings.  When we're done, we need to call
    1006             :   // AddToAttachedQueue on all of them, in order.
    1007             :   LinkedList<PendingBinding> mPendingBindings;
    1008             : 
    1009             :   PendingBinding* mCurrentPendingBindingInsertionPoint;
    1010             : };
    1011             : 
    1012         108 : nsFrameConstructorState::nsFrameConstructorState(
    1013             :   nsIPresShell* aPresShell,
    1014             :   TreeMatchContext* aTreeMatchContext,
    1015             :   nsContainerFrame* aFixedContainingBlock,
    1016             :   nsContainerFrame* aAbsoluteContainingBlock,
    1017             :   nsContainerFrame* aFloatContainingBlock,
    1018         108 :   already_AddRefed<nsILayoutHistoryState> aHistoryState)
    1019         108 :   : mPresContext(aPresShell->GetPresContext()),
    1020             :     mPresShell(aPresShell),
    1021         108 :     mFrameManager(aPresShell->FrameManager()),
    1022             : #ifdef MOZ_XUL
    1023             :     mPopupItems(nullptr),
    1024             : #endif
    1025             :     mFixedItems(aFixedContainingBlock),
    1026             :     mAbsoluteItems(aAbsoluteContainingBlock),
    1027             :     mFloatedItems(aFloatContainingBlock),
    1028             :     mTopLayerFixedItems(
    1029         108 :       static_cast<nsContainerFrame*>(mFrameManager->GetRootFrame())),
    1030             :     mTopLayerAbsoluteItems(
    1031             :       aPresShell->FrameConstructor()->GetDocElementContainingBlock()),
    1032             :     // See PushAbsoluteContaningBlock below
    1033             :     mFrameState(aHistoryState),
    1034             :     mAdditionalStateBits(nsFrameState(0)),
    1035             :     // If the fixed-pos containing block is equal to the abs-pos containing
    1036             :     // block, use the abs-pos containing block's abs-pos list for fixed-pos
    1037             :     // frames.
    1038         108 :     mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
    1039             :     mHavePendingPopupgroup(false),
    1040             :     mCreatingExtraFrames(false),
    1041             :     mTreeMatchContext(aTreeMatchContext),
    1042         432 :     mCurrentPendingBindingInsertionPoint(nullptr)
    1043             : {
    1044             : #ifdef MOZ_XUL
    1045         108 :   nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
    1046         108 :   if (rootBox) {
    1047          34 :     mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
    1048             :   }
    1049             : #endif
    1050         108 :   MOZ_COUNT_CTOR(nsFrameConstructorState);
    1051         108 : }
    1052             : 
    1053          60 : nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
    1054             :                                                  TreeMatchContext* aTreeMatchContext,
    1055             :                                                  nsContainerFrame* aFixedContainingBlock,
    1056             :                                                  nsContainerFrame* aAbsoluteContainingBlock,
    1057          60 :                                                  nsContainerFrame* aFloatContainingBlock)
    1058             :   : nsFrameConstructorState(aPresShell,
    1059             :                             aTreeMatchContext,
    1060             :                             aFixedContainingBlock,
    1061             :                             aAbsoluteContainingBlock,
    1062             :                             aFloatContainingBlock,
    1063          60 :                             aPresShell->GetDocument()->GetLayoutHistoryState())
    1064             : {
    1065          60 : }
    1066             : 
    1067         216 : nsFrameConstructorState::~nsFrameConstructorState()
    1068             : {
    1069         108 :   MOZ_COUNT_DTOR(nsFrameConstructorState);
    1070         108 :   ProcessFrameInsertions(mTopLayerFixedItems, nsIFrame::kFixedList);
    1071         108 :   ProcessFrameInsertions(mTopLayerAbsoluteItems, nsIFrame::kAbsoluteList);
    1072         108 :   ProcessFrameInsertions(mFloatedItems, nsIFrame::kFloatList);
    1073         108 :   ProcessFrameInsertions(mAbsoluteItems, nsIFrame::kAbsoluteList);
    1074         108 :   ProcessFrameInsertions(mFixedItems, nsIFrame::kFixedList);
    1075             : #ifdef MOZ_XUL
    1076         108 :   ProcessFrameInsertions(mPopupItems, nsIFrame::kPopupList);
    1077             : #endif
    1078         108 :   for (int32_t i = mGeneratedTextNodesWithInitializer.Count() - 1; i >= 0; --i) {
    1079           0 :     mGeneratedTextNodesWithInitializer[i]->
    1080           0 :       DeleteProperty(nsGkAtoms::genConInitializerProperty);
    1081             :   }
    1082         108 :   if (!mPendingBindings.isEmpty()) {
    1083          16 :     nsBindingManager* bindingManager = mPresShell->GetDocument()->BindingManager();
    1084         237 :     do {
    1085         474 :       nsAutoPtr<PendingBinding> pendingBinding;
    1086         237 :       pendingBinding = mPendingBindings.popFirst();
    1087         237 :       bindingManager->AddToAttachedQueue(pendingBinding->mBinding);
    1088         237 :     } while (!mPendingBindings.isEmpty());
    1089          16 :     mCurrentPendingBindingInsertionPoint = nullptr;
    1090             :   }
    1091         108 : }
    1092             : 
    1093             : static nsContainerFrame*
    1094          40 : AdjustAbsoluteContainingBlock(nsContainerFrame* aContainingBlockIn)
    1095             : {
    1096          40 :   if (!aContainingBlockIn) {
    1097           0 :     return nullptr;
    1098             :   }
    1099             : 
    1100             :   // Always use the container's first continuation. (Inline frames can have
    1101             :   // non-fluid bidi continuations...)
    1102          40 :   return static_cast<nsContainerFrame*>(aContainingBlockIn->FirstContinuation());
    1103             : }
    1104             : 
    1105             : void
    1106          40 : nsFrameConstructorState::PushAbsoluteContainingBlock(nsContainerFrame* aNewAbsoluteContainingBlock,
    1107             :                                                      nsIFrame* aPositionedFrame,
    1108             :                                                      nsFrameConstructorSaveState& aSaveState)
    1109             : {
    1110          40 :   aSaveState.mItems = &mAbsoluteItems;
    1111          40 :   aSaveState.mSavedItems = mAbsoluteItems;
    1112          40 :   aSaveState.mChildListID = nsIFrame::kAbsoluteList;
    1113          40 :   aSaveState.mState = this;
    1114          40 :   aSaveState.mSavedFixedPosIsAbsPos = mFixedPosIsAbsPos;
    1115             : 
    1116          40 :   if (mFixedPosIsAbsPos) {
    1117             :     // Since we're going to replace mAbsoluteItems, we need to save it into
    1118             :     // mFixedItems now (and save the current value of mFixedItems).
    1119           0 :     aSaveState.mSavedFixedItems = mFixedItems;
    1120           0 :     mFixedItems = mAbsoluteItems;
    1121             :   }
    1122             : 
    1123          40 :   mAbsoluteItems =
    1124          80 :     nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock));
    1125             : 
    1126             :   /* See if we're wiring the fixed-pos and abs-pos lists together.  This happens iff
    1127             :    * we're a transformed element.
    1128             :    */
    1129          80 :   mFixedPosIsAbsPos = aPositionedFrame &&
    1130          40 :       aPositionedFrame->IsFixedPosContainingBlock();
    1131             : 
    1132          40 :   if (aNewAbsoluteContainingBlock) {
    1133          40 :     aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
    1134             :   }
    1135          40 : }
    1136             : 
    1137             : void
    1138         252 : nsFrameConstructorState::PushFloatContainingBlock(nsContainerFrame* aNewFloatContainingBlock,
    1139             :                                                   nsFrameConstructorSaveState& aSaveState)
    1140             : {
    1141         252 :   NS_PRECONDITION(!aNewFloatContainingBlock ||
    1142             :                   aNewFloatContainingBlock->IsFloatContainingBlock(),
    1143             :                   "Please push a real float containing block!");
    1144         252 :   NS_ASSERTION(!aNewFloatContainingBlock ||
    1145             :                !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock),
    1146             :                "We should not push a frame that is supposed to _suppress_ "
    1147             :                "floats as a float containing block!");
    1148         252 :   aSaveState.mItems = &mFloatedItems;
    1149         252 :   aSaveState.mSavedItems = mFloatedItems;
    1150         252 :   aSaveState.mChildListID = nsIFrame::kFloatList;
    1151         252 :   aSaveState.mState = this;
    1152         252 :   mFloatedItems = nsAbsoluteItems(aNewFloatContainingBlock);
    1153         252 : }
    1154             : 
    1155             : nsContainerFrame*
    1156          87 : nsFrameConstructorState::GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
    1157             :                                             nsContainerFrame* aContentParentFrame) const
    1158             : {
    1159          87 :   NS_PRECONDITION(aStyleDisplay, "Must have display struct!");
    1160             : 
    1161             :   // If there is no container for a fixed, absolute, or floating root
    1162             :   // frame, we will ignore the positioning.  This hack is originally
    1163             :   // brought to you by the letter T: tables, since other roots don't
    1164             :   // even call into this code.  See bug 178855.
    1165             :   //
    1166             :   // XXX Disabling positioning in this case is a hack.  If one was so inclined,
    1167             :   // one could support this either by (1) inserting a dummy block between the
    1168             :   // table and the canvas or (2) teaching the canvas how to reflow positioned
    1169             :   // elements. (1) has the usual problems when multiple frames share the same
    1170             :   // content (notice all the special cases in this file dealing with inner
    1171             :   // tables and table wrappers which share the same content). (2) requires some
    1172             :   // work and possible factoring.
    1173             :   //
    1174             :   // XXXbz couldn't we just force position to "static" on roots and
    1175             :   // float to "none"?  That's OK per CSS 2.1, as far as I can tell.
    1176             : 
    1177         137 :   if (aContentParentFrame &&
    1178          50 :       nsSVGUtils::IsInSVGTextSubtree(aContentParentFrame)) {
    1179           0 :     return aContentParentFrame;
    1180             :   }
    1181             : 
    1182          87 :   if (aStyleDisplay->IsFloatingStyle() && mFloatedItems.containingBlock) {
    1183           0 :     NS_ASSERTION(!aStyleDisplay->IsAbsolutelyPositionedStyle(),
    1184             :                  "Absolutely positioned _and_ floating?");
    1185           0 :     return mFloatedItems.containingBlock;
    1186             :   }
    1187             : 
    1188          87 :   if (aStyleDisplay->mTopLayer != NS_STYLE_TOP_LAYER_NONE) {
    1189           0 :     MOZ_ASSERT(aStyleDisplay->mTopLayer == NS_STYLE_TOP_LAYER_TOP,
    1190             :                "-moz-top-layer should be either none or top");
    1191           0 :     MOZ_ASSERT(aStyleDisplay->IsAbsolutelyPositionedStyle(),
    1192             :                "Top layer items should always be absolutely positioned");
    1193           0 :     if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED) {
    1194           0 :       MOZ_ASSERT(mTopLayerFixedItems.containingBlock, "No root frame?");
    1195           0 :       return mTopLayerFixedItems.containingBlock;
    1196             :     }
    1197           0 :     MOZ_ASSERT(aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE);
    1198           0 :     MOZ_ASSERT(mTopLayerAbsoluteItems.containingBlock);
    1199           0 :     return mTopLayerAbsoluteItems.containingBlock;
    1200             :   }
    1201             : 
    1202          89 :   if (aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
    1203           2 :       mAbsoluteItems.containingBlock) {
    1204           0 :     return mAbsoluteItems.containingBlock;
    1205             :   }
    1206             : 
    1207          99 :   if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
    1208          12 :       GetFixedItems().containingBlock) {
    1209          12 :     return GetFixedItems().containingBlock;
    1210             :   }
    1211             : 
    1212          75 :   return aContentParentFrame;
    1213             : }
    1214             : 
    1215             : nsAbsoluteItems*
    1216         504 : nsFrameConstructorState::GetOutOfFlowFrameItems(nsIFrame* aNewFrame,
    1217             :                                                 bool aCanBePositioned,
    1218             :                                                 bool aCanBeFloated,
    1219             :                                                 bool aIsOutOfFlowPopup,
    1220             :                                                 nsFrameState* aPlaceholderType)
    1221             : {
    1222             : #ifdef MOZ_XUL
    1223         504 :   if (MOZ_UNLIKELY(aIsOutOfFlowPopup)) {
    1224          29 :     MOZ_ASSERT(mPopupItems.containingBlock, "Must have a popup set frame!");
    1225          29 :     *aPlaceholderType = PLACEHOLDER_FOR_POPUP;
    1226          29 :     return &mPopupItems;
    1227             :   }
    1228             : #endif // MOZ_XUL
    1229         475 :   if (aCanBeFloated && aNewFrame->IsFloating()) {
    1230           0 :     *aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
    1231           0 :     return &mFloatedItems;
    1232             :   }
    1233             : 
    1234         475 :   if (aCanBePositioned) {
    1235          62 :     const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
    1236          62 :     if (disp->mTopLayer != NS_STYLE_TOP_LAYER_NONE) {
    1237           0 :       *aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
    1238           0 :       if (disp->mPosition == NS_STYLE_POSITION_FIXED) {
    1239           0 :         return &mTopLayerFixedItems;
    1240             :       }
    1241           0 :       return &mTopLayerAbsoluteItems;
    1242             :     }
    1243          62 :     if (disp->mPosition == NS_STYLE_POSITION_ABSOLUTE) {
    1244           1 :       *aPlaceholderType = PLACEHOLDER_FOR_ABSPOS;
    1245           1 :       return &mAbsoluteItems;
    1246             :     }
    1247          61 :     if (disp->mPosition == NS_STYLE_POSITION_FIXED) {
    1248           6 :       *aPlaceholderType = PLACEHOLDER_FOR_FIXEDPOS;
    1249           6 :       return &GetFixedItems();
    1250             :     }
    1251             :   }
    1252         468 :   return nullptr;
    1253             : }
    1254             : 
    1255             : void
    1256           0 : nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
    1257             :                                                    nsIFrame* aFrame)
    1258             : {
    1259           0 :   MOZ_ASSERT(aFrame->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
    1260           0 :   nsContainerFrame* frame = do_QueryFrame(aFrame);
    1261           0 :   if (!frame) {
    1262           0 :     NS_WARNING("Cannot create backdrop frame for non-container frame");
    1263           0 :     return;
    1264             :   }
    1265             : 
    1266           0 :   RefPtr<nsStyleContext> style = mPresShell->StyleSet()->
    1267           0 :     ResolvePseudoElementStyle(aContent->AsElement(),
    1268             :                               CSSPseudoElementType::backdrop,
    1269             :                               /* aParentStyleContext */ nullptr,
    1270           0 :                               /* aPseudoElement */ nullptr);
    1271           0 :   MOZ_ASSERT(style->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
    1272             :   nsContainerFrame* parentFrame =
    1273           0 :     GetGeometricParent(style->StyleDisplay(), nullptr);
    1274             : 
    1275           0 :   nsBackdropFrame* backdropFrame = new (mPresShell) nsBackdropFrame(style);
    1276           0 :   backdropFrame->Init(aContent, parentFrame, nullptr);
    1277             : 
    1278             :   nsFrameState placeholderType;
    1279             :   nsAbsoluteItems* frameItems = GetOutOfFlowFrameItems(backdropFrame,
    1280             :                                                        true, true, false,
    1281           0 :                                                        &placeholderType);
    1282           0 :   MOZ_ASSERT(placeholderType == PLACEHOLDER_FOR_TOPLAYER);
    1283             : 
    1284             :   nsIFrame* placeholder = nsCSSFrameConstructor::
    1285           0 :     CreatePlaceholderFrameFor(mPresShell, aContent, backdropFrame,
    1286           0 :                               frame, nullptr, PLACEHOLDER_FOR_TOPLAYER);
    1287           0 :   nsFrameList temp(placeholder, placeholder);
    1288           0 :   frame->SetInitialChildList(nsIFrame::kBackdropList, temp);
    1289             : 
    1290           0 :   frameItems->AddChild(backdropFrame);
    1291             : }
    1292             : 
    1293             : void
    1294         504 : nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
    1295             :                                   nsFrameItems& aFrameItems,
    1296             :                                   nsIContent* aContent,
    1297             :                                   nsStyleContext* aStyleContext,
    1298             :                                   nsContainerFrame* aParentFrame,
    1299             :                                   bool aCanBePositioned,
    1300             :                                   bool aCanBeFloated,
    1301             :                                   bool aIsOutOfFlowPopup,
    1302             :                                   bool aInsertAfter,
    1303             :                                   nsIFrame* aInsertAfterFrame)
    1304             : {
    1305         504 :   NS_PRECONDITION(!aNewFrame->GetNextSibling(), "Shouldn't happen");
    1306             : 
    1307             :   nsFrameState placeholderType;
    1308             :   nsAbsoluteItems* outOfFlowFrameItems =
    1309         504 :     GetOutOfFlowFrameItems(aNewFrame, aCanBePositioned, aCanBeFloated,
    1310         504 :                            aIsOutOfFlowPopup, &placeholderType);
    1311             : 
    1312             :   // The comments in GetGeometricParent regarding root table frames
    1313             :   // all apply here, unfortunately. Thus, we need to check whether
    1314             :   // the returned frame items really has containing block.
    1315             :   nsFrameItems* frameItems;
    1316         504 :   if (outOfFlowFrameItems && outOfFlowFrameItems->containingBlock) {
    1317          35 :     MOZ_ASSERT(aNewFrame->GetParent() == outOfFlowFrameItems->containingBlock,
    1318             :                "Parent of the frame is not the containing block?");
    1319          35 :     frameItems = outOfFlowFrameItems;
    1320             :   } else {
    1321         469 :     frameItems = &aFrameItems;
    1322         469 :     placeholderType = nsFrameState(0);
    1323             :   }
    1324             : 
    1325         504 :   if (placeholderType) {
    1326          35 :     NS_ASSERTION(frameItems != &aFrameItems,
    1327             :                  "Putting frame in-flow _and_ want a placeholder?");
    1328             :     nsIFrame* placeholderFrame =
    1329          35 :       nsCSSFrameConstructor::CreatePlaceholderFrameFor(mPresShell,
    1330             :                                                        aContent,
    1331             :                                                        aNewFrame,
    1332             :                                                        aParentFrame,
    1333             :                                                        nullptr,
    1334          35 :                                                        placeholderType);
    1335             : 
    1336          35 :     placeholderFrame->AddStateBits(mAdditionalStateBits);
    1337             :     // Add the placeholder frame to the flow
    1338          35 :     aFrameItems.AddChild(placeholderFrame);
    1339             : 
    1340          35 :     if (placeholderType == PLACEHOLDER_FOR_TOPLAYER) {
    1341           0 :       ConstructBackdropFrameFor(aContent, aNewFrame);
    1342             :     }
    1343             :   }
    1344             : #ifdef DEBUG
    1345             :   else {
    1346         469 :     NS_ASSERTION(aNewFrame->GetParent() == aParentFrame,
    1347             :                  "In-flow frame has wrong parent");
    1348             :   }
    1349             : #endif
    1350             : 
    1351         504 :   if (aInsertAfter) {
    1352           0 :     frameItems->InsertFrame(nullptr, aInsertAfterFrame, aNewFrame);
    1353             :   } else {
    1354         504 :     frameItems->AddChild(aNewFrame);
    1355             :   }
    1356         504 : }
    1357             : 
    1358             : void
    1359         940 : nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
    1360             :                                                 ChildListID aChildListID)
    1361             : {
    1362             : #define NS_NONXUL_LIST_TEST (&aFrameItems == &mFloatedItems &&            \
    1363             :                              aChildListID == nsIFrame::kFloatList)    ||  \
    1364             :                             ((&aFrameItems == &mAbsoluteItems ||          \
    1365             :                               &aFrameItems == &mTopLayerAbsoluteItems) && \
    1366             :                              aChildListID == nsIFrame::kAbsoluteList) ||  \
    1367             :                             ((&aFrameItems == &mFixedItems ||             \
    1368             :                               &aFrameItems == &mTopLayerFixedItems) &&    \
    1369             :                              aChildListID == nsIFrame::kFixedList)
    1370             : #ifdef MOZ_XUL
    1371         940 :   NS_PRECONDITION(NS_NONXUL_LIST_TEST ||
    1372             :                   (&aFrameItems == &mPopupItems &&
    1373             :                    aChildListID == nsIFrame::kPopupList),
    1374             :                   "Unexpected aFrameItems/aChildListID combination");
    1375             : #else
    1376             :   NS_PRECONDITION(NS_NONXUL_LIST_TEST,
    1377             :                   "Unexpected aFrameItems/aChildListID combination");
    1378             : #endif
    1379             : 
    1380         940 :   if (aFrameItems.IsEmpty()) {
    1381         930 :     return;
    1382             :   }
    1383             : 
    1384          10 :   nsContainerFrame* containingBlock = aFrameItems.containingBlock;
    1385             : 
    1386          10 :   NS_ASSERTION(containingBlock,
    1387             :                "Child list without containing block?");
    1388             : 
    1389          10 :   if (aChildListID == nsIFrame::kFixedList) {
    1390             :     // Put this frame on the transformed-frame's abs-pos list instead, if
    1391             :     // it has abs-pos children instead of fixed-pos children.
    1392           3 :     aChildListID = containingBlock->GetAbsoluteListID();
    1393             :   }
    1394             : 
    1395             :   // Insert the frames hanging out in aItems.  We can use SetInitialChildList()
    1396             :   // if the containing block hasn't been reflowed yet (so NS_FRAME_FIRST_REFLOW
    1397             :   // is set) and doesn't have any frames in the aChildListID child list yet.
    1398          10 :   const nsFrameList& childList = containingBlock->GetChildList(aChildListID);
    1399          12 :   if (childList.IsEmpty() &&
    1400           2 :       (containingBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    1401             :     // If we're injecting absolutely positioned frames, inject them on the
    1402             :     // absolute containing block
    1403           2 :     if (aChildListID == containingBlock->GetAbsoluteListID()) {
    1404             :       containingBlock->GetAbsoluteContainingBlock()->
    1405           1 :         SetInitialChildList(containingBlock, aChildListID, aFrameItems);
    1406             :     } else {
    1407           1 :       containingBlock->SetInitialChildList(aChildListID, aFrameItems);
    1408             :     }
    1409           8 :   } else if (aChildListID == nsIFrame::kFixedList ||
    1410             :              aChildListID == nsIFrame::kAbsoluteList) {
    1411             :     // The order is not important for abs-pos/fixed-pos frame list, just
    1412             :     // append the frame items to the list directly.
    1413           2 :     mFrameManager->AppendFrames(containingBlock, aChildListID, aFrameItems);
    1414             :   } else {
    1415             :     // Note that whether the frame construction context is doing an append or
    1416             :     // not is not helpful here, since it could be appending to some frame in
    1417             :     // the middle of the document, which means we're not necessarily
    1418             :     // appending to the children of the containing block.
    1419             :     //
    1420             :     // We need to make sure the 'append to the end of document' case is fast.
    1421             :     // So first test the last child of the containing block
    1422           6 :     nsIFrame* lastChild = childList.LastChild();
    1423             : 
    1424             :     // CompareTreePosition uses placeholder hierarchy for out of flow frames,
    1425             :     // so this will make out-of-flows respect the ordering of placeholders,
    1426             :     // which is great because it takes care of anonymous content.
    1427           6 :     nsIFrame* firstNewFrame = aFrameItems.FirstChild();
    1428             : 
    1429             :     // Cache the ancestor chain so that we can reuse it if needed.
    1430          12 :     AutoTArray<nsIFrame*, 20> firstNewFrameAncestors;
    1431           6 :     nsIFrame* notCommonAncestor = nullptr;
    1432           6 :     if (lastChild) {
    1433             :       notCommonAncestor = nsLayoutUtils::FillAncestors(firstNewFrame,
    1434             :                                                        containingBlock,
    1435           6 :                                                        &firstNewFrameAncestors);
    1436             :     }
    1437             : 
    1438          12 :     if (!lastChild ||
    1439           6 :         nsLayoutUtils::CompareTreePosition(lastChild, firstNewFrame,
    1440             :                                            firstNewFrameAncestors,
    1441             :                                            notCommonAncestor ?
    1442             :                                              containingBlock : nullptr) < 0) {
    1443             :       // no lastChild, or lastChild comes before the new children, so just append
    1444           6 :       mFrameManager->AppendFrames(containingBlock, aChildListID, aFrameItems);
    1445             :     } else {
    1446             :       // Try the other children. First collect them to an array so that a
    1447             :       // reasonable fast binary search can be used to find the insertion point.
    1448           0 :       AutoTArray<nsIFrame*, 128> children;
    1449           0 :       for (nsIFrame* f = childList.FirstChild(); f != lastChild;
    1450           0 :            f = f->GetNextSibling()) {
    1451           0 :         children.AppendElement(f);
    1452             :       }
    1453             : 
    1454           0 :       nsIFrame* insertionPoint = nullptr;
    1455           0 :       int32_t imin = 0;
    1456           0 :       int32_t max = children.Length();
    1457           0 :       while (max > imin) {
    1458           0 :         int32_t imid = imin + ((max - imin) / 2);
    1459           0 :         nsIFrame* f = children[imid];
    1460             :         int32_t compare =
    1461           0 :           nsLayoutUtils::CompareTreePosition(f, firstNewFrame, firstNewFrameAncestors,
    1462           0 :                                              notCommonAncestor ? containingBlock : nullptr);
    1463           0 :         if (compare > 0) {
    1464             :           // f is after the new frame.
    1465           0 :           max = imid;
    1466           0 :           insertionPoint = imid > 0 ? children[imid - 1] : nullptr;
    1467           0 :         } else if (compare < 0) {
    1468             :           // f is before the new frame.
    1469           0 :           imin = imid + 1;
    1470           0 :           insertionPoint = f;
    1471             :         } else {
    1472             :           // This is for the old behavior. Should be removed once it is
    1473             :           // guaranteed that CompareTreePosition can't return 0!
    1474             :           // See bug 928645.
    1475           0 :           NS_WARNING("Something odd happening???");
    1476           0 :           insertionPoint = nullptr;
    1477           0 :           for (uint32_t i = 0; i < children.Length(); ++i) {
    1478           0 :             nsIFrame* f = children[i];
    1479           0 :             if (nsLayoutUtils::CompareTreePosition(f, firstNewFrame,
    1480             :                                                    firstNewFrameAncestors,
    1481             :                                                    notCommonAncestor ?
    1482             :                                                      containingBlock : nullptr) > 0) {
    1483           0 :               break;
    1484             :             }
    1485           0 :             insertionPoint = f;
    1486             :           }
    1487           0 :           break;
    1488             :         }
    1489             :       }
    1490           0 :       mFrameManager->InsertFrames(containingBlock, aChildListID,
    1491           0 :                                   insertionPoint, aFrameItems);
    1492             :     }
    1493             :   }
    1494             : 
    1495          10 :   NS_POSTCONDITION(aFrameItems.IsEmpty(), "How did that happen?");
    1496             : }
    1497             : 
    1498             : 
    1499         681 : nsFrameConstructorSaveState::nsFrameConstructorSaveState()
    1500             :   : mItems(nullptr),
    1501             :     mSavedItems(nullptr),
    1502             :     mChildListID(kPrincipalList),
    1503             :     mState(nullptr),
    1504             :     mSavedFixedItems(nullptr),
    1505         681 :     mSavedFixedPosIsAbsPos(false)
    1506             : {
    1507         681 : }
    1508             : 
    1509        1362 : nsFrameConstructorSaveState::~nsFrameConstructorSaveState()
    1510             : {
    1511             :   // Restore the state
    1512         681 :   if (mItems) {
    1513         292 :     NS_ASSERTION(mState, "Can't have mItems set without having a state!");
    1514         292 :     mState->ProcessFrameInsertions(*mItems, mChildListID);
    1515         292 :     *mItems = mSavedItems;
    1516             : #ifdef DEBUG
    1517             :     // We've transferred the child list, so drop the pointer we held to it.
    1518             :     // Note that this only matters for the assert in ~nsAbsoluteItems.
    1519         292 :     mSavedItems.Clear();
    1520             : #endif
    1521         292 :     if (mItems == &mState->mAbsoluteItems) {
    1522          40 :       mState->mFixedPosIsAbsPos = mSavedFixedPosIsAbsPos;
    1523          40 :       if (mSavedFixedPosIsAbsPos) {
    1524             :         // mAbsoluteItems was moved to mFixedItems, so move mFixedItems back
    1525             :         // and repair the old mFixedItems now.
    1526           0 :         mState->mAbsoluteItems = mState->mFixedItems;
    1527           0 :         mState->mFixedItems = mSavedFixedItems;
    1528             : #ifdef DEBUG
    1529           0 :         mSavedFixedItems.Clear();
    1530             : #endif
    1531             :       }
    1532             :     }
    1533         292 :     NS_ASSERTION(!mItems->LastChild() || !mItems->LastChild()->GetNextSibling(),
    1534             :                  "Something corrupted our list");
    1535             :   }
    1536         681 : }
    1537             : 
    1538             : /**
    1539             :  * Moves aFrameList from aOldParent to aNewParent.  This updates the parent
    1540             :  * pointer of the frames in the list, and reparents their views as needed.
    1541             :  * nsFrame::SetParent sets the NS_FRAME_HAS_VIEW bit on aNewParent and its
    1542             :  * ancestors as needed. Then it sets the list as the initial child list
    1543             :  * on aNewParent, unless aNewParent either already has kids or has been
    1544             :  * reflowed; in that case it appends the new frames.  Note that this
    1545             :  * method differs from ReparentFrames in that it doesn't change the kids'
    1546             :  * style contexts.
    1547             :  */
    1548             : // XXXbz Since this is only used for {ib} splits, could we just copy the view
    1549             : // bits from aOldParent to aNewParent and then use the
    1550             : // nsFrameList::ApplySetParent?  That would still leave us doing two passes
    1551             : // over the list, of course; if we really wanted to we could factor out the
    1552             : // relevant part of ReparentFrameViewList, I suppose...  Or just get rid of
    1553             : // views, which would make most of this function go away.
    1554             : static void
    1555           0 : MoveChildrenTo(nsIFrame* aOldParent,
    1556             :                nsContainerFrame* aNewParent,
    1557             :                nsFrameList& aFrameList)
    1558             : {
    1559           0 :   bool sameGrandParent = aOldParent->GetParent() == aNewParent->GetParent();
    1560             : 
    1561           0 :   if (aNewParent->HasView() || aOldParent->HasView() || !sameGrandParent) {
    1562             :     // Move the frames into the new view
    1563           0 :     nsContainerFrame::ReparentFrameViewList(aFrameList, aOldParent, aNewParent);
    1564             :   }
    1565             : 
    1566           0 :   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
    1567           0 :     e.get()->SetParent(aNewParent);
    1568             :   }
    1569             : 
    1570           0 :   if (aNewParent->PrincipalChildList().IsEmpty() &&
    1571           0 :       (aNewParent->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    1572           0 :     aNewParent->SetInitialChildList(kPrincipalList, aFrameList);
    1573             :   } else {
    1574           0 :     aNewParent->AppendFrames(kPrincipalList, aFrameList);
    1575             :   }
    1576           0 : }
    1577             : 
    1578             : //----------------------------------------------------------------------
    1579             : 
    1580          28 : nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument* aDocument,
    1581          28 :                                              nsIPresShell* aPresShell)
    1582             :   : nsFrameManager(aPresShell)
    1583             :   , mDocument(aDocument)
    1584             :   , mRootElementFrame(nullptr)
    1585             :   , mRootElementStyleFrame(nullptr)
    1586             :   , mDocElementContainingBlock(nullptr)
    1587             :   , mPageSequenceFrame(nullptr)
    1588             :   , mCurrentDepth(0)
    1589             : #ifdef DEBUG
    1590             :   , mUpdateCount(0)
    1591             : #endif
    1592             :   , mQuotesDirty(false)
    1593             :   , mCountersDirty(false)
    1594             :   , mIsDestroyingFrameTree(false)
    1595             :   , mHasRootAbsPosContainingBlock(false)
    1596          28 :   , mAlwaysCreateFramesForIgnorableWhitespace(false)
    1597             : {
    1598             : #ifdef DEBUG
    1599             :   static bool gFirstTime = true;
    1600          28 :   if (gFirstTime) {
    1601           2 :     gFirstTime = false;
    1602           2 :     char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
    1603           2 :     if (flags) {
    1604           0 :       bool error = false;
    1605             :       for (;;) {
    1606           0 :         char* comma = PL_strchr(flags, ',');
    1607           0 :         if (comma)
    1608           0 :           *comma = '\0';
    1609             : 
    1610           0 :         bool found = false;
    1611           0 :         FrameCtorDebugFlags* flag = gFlags;
    1612           0 :         FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
    1613           0 :         while (flag < limit) {
    1614           0 :           if (PL_strcasecmp(flag->name, flags) == 0) {
    1615           0 :             *(flag->on) = true;
    1616           0 :             printf("nsCSSFrameConstructor: setting %s debug flag on\n", flag->name);
    1617           0 :             found = true;
    1618           0 :             break;
    1619             :           }
    1620           0 :           ++flag;
    1621             :         }
    1622             : 
    1623           0 :         if (! found)
    1624           0 :           error = true;
    1625             : 
    1626           0 :         if (! comma)
    1627           0 :           break;
    1628             : 
    1629           0 :         *comma = ',';
    1630           0 :         flags = comma + 1;
    1631           0 :       }
    1632             : 
    1633           0 :       if (error) {
    1634           0 :         printf("Here are the available GECKO_FRAMECTOR_DEBUG_FLAGS:\n");
    1635           0 :         FrameCtorDebugFlags* flag = gFlags;
    1636           0 :         FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
    1637           0 :         while (flag < limit) {
    1638           0 :           printf("  %s\n", flag->name);
    1639           0 :           ++flag;
    1640             :         }
    1641           0 :         printf("Note: GECKO_FRAMECTOR_DEBUG_FLAGS is a comma separated list of flag\n");
    1642           0 :         printf("names (no whitespace)\n");
    1643             :       }
    1644             :     }
    1645             :   }
    1646             : #endif
    1647          28 : }
    1648             : 
    1649             : void
    1650         126 : nsCSSFrameConstructor::NotifyDestroyingFrame(nsIFrame* aFrame)
    1651             : {
    1652         126 :   NS_PRECONDITION(mUpdateCount != 0,
    1653             :                   "Should be in an update while destroying frames");
    1654             : 
    1655         126 :   if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
    1656           0 :     if (mQuoteList.DestroyNodesFor(aFrame))
    1657           0 :       QuotesDirty();
    1658             :   }
    1659             : 
    1660         126 :   if (aFrame->HasAnyStateBits(NS_FRAME_HAS_CSS_COUNTER_STYLE) &&
    1661           0 :       mCounterManager.DestroyNodesFor(aFrame)) {
    1662             :     // Technically we don't need to update anything if we destroyed only
    1663             :     // USE nodes.  However, this is unlikely to happen in the real world
    1664             :     // since USE nodes generally go along with INCREMENT nodes.
    1665           0 :     CountersDirty();
    1666             :   }
    1667             : 
    1668         126 :   RestyleManager()->NotifyDestroyingFrame(aFrame);
    1669             : 
    1670         126 :   nsFrameManager::NotifyDestroyingFrame(aFrame);
    1671         126 : }
    1672             : 
    1673           0 : struct nsGenConInitializer {
    1674             :   nsAutoPtr<nsGenConNode> mNode;
    1675             :   nsGenConList*           mList;
    1676             :   void (nsCSSFrameConstructor::*mDirtyAll)();
    1677             : 
    1678           0 :   nsGenConInitializer(nsGenConNode* aNode, nsGenConList* aList,
    1679             :                       void (nsCSSFrameConstructor::*aDirtyAll)())
    1680           0 :     : mNode(aNode), mList(aList), mDirtyAll(aDirtyAll) {}
    1681             : };
    1682             : 
    1683             : already_AddRefed<nsIContent>
    1684           6 : nsCSSFrameConstructor::CreateGenConTextNode(nsFrameConstructorState& aState,
    1685             :                                             const nsString& aString,
    1686             :                                             RefPtr<nsTextNode>* aText,
    1687             :                                             nsGenConInitializer* aInitializer)
    1688             : {
    1689          18 :   RefPtr<nsTextNode> content = new nsTextNode(mDocument->NodeInfoManager());
    1690           6 :   content->SetText(aString, false);
    1691           6 :   if (aText) {
    1692           0 :     *aText = content;
    1693             :   }
    1694           6 :   if (aInitializer) {
    1695           0 :     content->SetProperty(nsGkAtoms::genConInitializerProperty, aInitializer,
    1696           0 :                          nsINode::DeleteProperty<nsGenConInitializer>);
    1697           0 :     aState.mGeneratedTextNodesWithInitializer.AppendObject(content);
    1698             :   }
    1699          12 :   return content.forget();
    1700             : }
    1701             : 
    1702             : already_AddRefed<nsIContent>
    1703           6 : nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
    1704             :                                               nsIContent*     aParentContent,
    1705             :                                               nsStyleContext* aStyleContext,
    1706             :                                               uint32_t        aContentIndex)
    1707             : {
    1708             :   // Get the content value
    1709             :   const nsStyleContentData &data =
    1710           6 :     aStyleContext->StyleContent()->ContentAt(aContentIndex);
    1711           6 :   nsStyleContentType type = data.GetType();
    1712             : 
    1713           6 :   switch (type) {
    1714             :     case eStyleContentType_Image: {
    1715           0 :       imgRequestProxy* image = data.GetImage();
    1716           0 :       if (!image) {
    1717             :         // CSS had something specified that couldn't be converted to an
    1718             :         // image object
    1719           0 :         return nullptr;
    1720             :       }
    1721             : 
    1722             :       // Create an image content object and pass it the image request.
    1723             :       // XXX Check if it's an image type we can handle...
    1724             : 
    1725           0 :       RefPtr<NodeInfo> nodeInfo;
    1726           0 :       nodeInfo = mDocument->NodeInfoManager()->
    1727           0 :         GetNodeInfo(nsGkAtoms::mozgeneratedcontentimage, nullptr,
    1728           0 :                     kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
    1729             : 
    1730           0 :       nsCOMPtr<nsIContent> content;
    1731           0 :       NS_NewGenConImageContent(getter_AddRefs(content), nodeInfo.forget(),
    1732           0 :                                image);
    1733           0 :       return content.forget();
    1734             :     }
    1735             : 
    1736             :     case eStyleContentType_String:
    1737             :       return CreateGenConTextNode(aState,
    1738          12 :                                   nsDependentString(data.GetString()),
    1739           6 :                                   nullptr, nullptr);
    1740             : 
    1741             :     case eStyleContentType_Attr: {
    1742           0 :       nsCOMPtr<nsIAtom> attrName;
    1743           0 :       int32_t attrNameSpace = kNameSpaceID_None;
    1744           0 :       nsAutoString contentString(data.GetString());
    1745             : 
    1746           0 :       int32_t barIndex = contentString.FindChar('|'); // CSS namespace delimiter
    1747           0 :       if (-1 != barIndex) {
    1748           0 :         nsAutoString  nameSpaceVal;
    1749           0 :         contentString.Left(nameSpaceVal, barIndex);
    1750             :         nsresult error;
    1751           0 :         attrNameSpace = nameSpaceVal.ToInteger(&error);
    1752           0 :         contentString.Cut(0, barIndex + 1);
    1753           0 :         if (contentString.Length()) {
    1754           0 :           if (mDocument->IsHTMLDocument() && aParentContent->IsHTMLElement()) {
    1755           0 :             ToLowerCase(contentString);
    1756             :           }
    1757           0 :           attrName = NS_Atomize(contentString);
    1758             :         }
    1759             :       }
    1760             :       else {
    1761           0 :         if (mDocument->IsHTMLDocument() && aParentContent->IsHTMLElement()) {
    1762           0 :           ToLowerCase(contentString);
    1763             :         }
    1764           0 :         attrName = NS_Atomize(contentString);
    1765             :       }
    1766             : 
    1767           0 :       if (!attrName) {
    1768           0 :         return nullptr;
    1769             :       }
    1770             : 
    1771           0 :       nsCOMPtr<nsIContent> content;
    1772           0 :       NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1773           0 :                              attrNameSpace, attrName, getter_AddRefs(content));
    1774           0 :       return content.forget();
    1775             :     }
    1776             : 
    1777             :     case eStyleContentType_Counter:
    1778             :     case eStyleContentType_Counters: {
    1779           0 :       nsStyleContentData::CounterFunction* counters = data.GetCounters();
    1780             :       nsCounterList* counterList =
    1781           0 :         mCounterManager.CounterListFor(counters->mIdent);
    1782             : 
    1783             :       nsCounterUseNode* node =
    1784             :         new nsCounterUseNode(counters, aContentIndex,
    1785           0 :                              type == eStyleContentType_Counters);
    1786             : 
    1787             :       nsGenConInitializer* initializer =
    1788             :         new nsGenConInitializer(node, counterList,
    1789           0 :                                 &nsCSSFrameConstructor::CountersDirty);
    1790             :       return CreateGenConTextNode(aState, EmptyString(), &node->mText,
    1791           0 :                                   initializer);
    1792             :     }
    1793             : 
    1794             :     case eStyleContentType_OpenQuote:
    1795             :     case eStyleContentType_CloseQuote:
    1796             :     case eStyleContentType_NoOpenQuote:
    1797             :     case eStyleContentType_NoCloseQuote: {
    1798             :       nsQuoteNode* node =
    1799           0 :         new nsQuoteNode(type, aContentIndex);
    1800             : 
    1801             :       nsGenConInitializer* initializer =
    1802             :         new nsGenConInitializer(node, &mQuoteList,
    1803           0 :                                 &nsCSSFrameConstructor::QuotesDirty);
    1804             :       return CreateGenConTextNode(aState, EmptyString(), &node->mText,
    1805           0 :                                   initializer);
    1806             :     }
    1807             : 
    1808             :     case eStyleContentType_AltContent: {
    1809             :       // Use the "alt" attribute; if that fails and the node is an HTML
    1810             :       // <input>, try the value attribute and then fall back to some default
    1811             :       // localized text we have.
    1812             :       // XXX what if the 'alt' attribute is added later, how will we
    1813             :       // detect that and do the right thing here?
    1814           0 :       if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::alt)) {
    1815           0 :         nsCOMPtr<nsIContent> content;
    1816           0 :         NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1817           0 :                                kNameSpaceID_None, nsGkAtoms::alt, getter_AddRefs(content));
    1818           0 :         return content.forget();
    1819             :       }
    1820             : 
    1821           0 :       if (aParentContent->IsHTMLElement() &&
    1822           0 :           aParentContent->NodeInfo()->Equals(nsGkAtoms::input)) {
    1823           0 :         if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    1824           0 :           nsCOMPtr<nsIContent> content;
    1825           0 :           NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1826           0 :                                  kNameSpaceID_None, nsGkAtoms::value, getter_AddRefs(content));
    1827           0 :           return content.forget();
    1828             :         }
    1829             : 
    1830           0 :         nsXPIDLString temp;
    1831             :         nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
    1832           0 :                                            "Submit", temp);
    1833           0 :         return CreateGenConTextNode(aState, temp, nullptr, nullptr);
    1834             :       }
    1835             : 
    1836           0 :       break;
    1837             :     }
    1838             : 
    1839             :     case eStyleContentType_Uninitialized:
    1840           0 :       NS_NOTREACHED("uninitialized content type");
    1841           0 :       return nullptr;
    1842             :   }
    1843             : 
    1844           0 :   return nullptr;
    1845             : }
    1846             : 
    1847             : /*
    1848             :  * aParentFrame - the frame that should be the parent of the generated
    1849             :  *   content.  This is the frame for the corresponding content node,
    1850             :  *   which must not be a leaf frame.
    1851             :  *
    1852             :  * Any items created are added to aItems.
    1853             :  *
    1854             :  * We create an XML element (tag _moz_generated_content_before or
    1855             :  * _moz_generated_content_after) representing the pseudoelement. We
    1856             :  * create a DOM node for each 'content' item and make those nodes the
    1857             :  * children of the XML element. Then we create a frame subtree for
    1858             :  * the XML element as if it were a regular child of
    1859             :  * aParentFrame/aParentContent, giving the XML element the ::before or
    1860             :  * ::after style.
    1861             :  */
    1862             : void
    1863         460 : nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aState,
    1864             :                                                   nsContainerFrame* aParentFrame,
    1865             :                                                   nsIContent*      aParentContent,
    1866             :                                                   nsStyleContext*  aStyleContext,
    1867             :                                                   CSSPseudoElementType aPseudoElement,
    1868             :                                                   FrameConstructionItemList& aItems)
    1869             : {
    1870         460 :   MOZ_ASSERT(aPseudoElement == CSSPseudoElementType::before ||
    1871             :              aPseudoElement == CSSPseudoElementType::after,
    1872             :              "unexpected aPseudoElement");
    1873             : 
    1874         460 :   MOZ_ASSERT(aParentContent->IsElement());
    1875             : 
    1876         460 :   StyleSetHandle styleSet = mPresShell->StyleSet();
    1877             : 
    1878             :   // Probe for the existence of the pseudo-element
    1879         466 :   RefPtr<nsStyleContext> pseudoStyleContext;
    1880             :   pseudoStyleContext =
    1881         920 :     styleSet->ProbePseudoElementStyle(aParentContent->AsElement(),
    1882             :                                       aPseudoElement,
    1883             :                                       aStyleContext,
    1884         460 :                                       aState.mTreeMatchContext);
    1885         460 :   if (!pseudoStyleContext)
    1886         454 :     return;
    1887             : 
    1888           6 :   bool isBefore = aPseudoElement == CSSPseudoElementType::before;
    1889             : 
    1890             :   // |ProbePseudoStyleFor| checked the 'display' property and the
    1891             :   // |ContentCount()| of the 'content' property for us.
    1892          12 :   RefPtr<NodeInfo> nodeInfo;
    1893           6 :   nsIAtom* elemName = isBefore ?
    1894           6 :     nsGkAtoms::mozgeneratedcontentbefore : nsGkAtoms::mozgeneratedcontentafter;
    1895          12 :   nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(elemName, nullptr,
    1896             :                                                        kNameSpaceID_None,
    1897           6 :                                                        nsIDOMNode::ELEMENT_NODE);
    1898          12 :   nsCOMPtr<Element> container;
    1899           6 :   nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
    1900           6 :   if (NS_FAILED(rv))
    1901           0 :     return;
    1902             : 
    1903             :   // Cleared when the pseudo is unbound from the tree, so no need to store a
    1904             :   // strong reference, nor a destructor.
    1905             :   nsIAtom* property = isBefore
    1906           6 :     ? nsGkAtoms::beforePseudoProperty : nsGkAtoms::afterPseudoProperty;
    1907           6 :   aParentContent->SetProperty(property, container.get());
    1908             : 
    1909           6 :   container->SetIsNativeAnonymousRoot();
    1910           6 :   container->SetPseudoElementType(aPseudoElement);
    1911             : 
    1912             :   // If the parent is in a shadow tree, make sure we don't
    1913             :   // bind with a document because shadow roots and its descendants
    1914             :   // are not in document.
    1915             :   nsIDocument* bindDocument =
    1916           6 :     aParentContent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
    1917           6 :   rv = container->BindToTree(bindDocument, aParentContent, aParentContent, true);
    1918           6 :   if (NS_FAILED(rv)) {
    1919           0 :     container->UnbindFromTree();
    1920           0 :     return;
    1921             :   }
    1922             : 
    1923             :   // Servo has already eagerly computed the style for the container, so we can
    1924             :   // just stick the style on the element and avoid an additional traversal.
    1925             :   //
    1926             :   // We don't do this for pseudos that may trigger animations or transitions,
    1927             :   // since those need to be kicked off by the traversal machinery.
    1928           6 :   bool isServo = pseudoStyleContext->IsServo();
    1929           6 :   bool hasServoAnimations = false;
    1930           6 :   if (isServo) {
    1931           0 :     ServoComputedValues* servoStyle = pseudoStyleContext->ComputedValues();
    1932           0 :     hasServoAnimations = Servo_ComputedValues_SpecifiesAnimationsOrTransitions(servoStyle);
    1933           0 :     if (!hasServoAnimations) {
    1934           0 :       Servo_SetExplicitStyle(container, servoStyle);
    1935             :     }
    1936             :   }
    1937             : 
    1938             :   // stylo: ServoRestyleManager does not handle transitions yet, and when it
    1939             :   // does it probably won't need to track reframed style contexts to start
    1940             :   // transitions correctly.
    1941           6 :   if (mozilla::GeckoRestyleManager* geckoRM = RestyleManager()->GetAsGecko()) {
    1942             :     GeckoRestyleManager::ReframingStyleContexts* rsc =
    1943           6 :       geckoRM->GetReframingStyleContexts();
    1944           6 :     if (rsc) {
    1945           0 :       nsStyleContext* oldStyleContext = rsc->Get(container, aPseudoElement);
    1946           0 :       if (oldStyleContext) {
    1947           0 :         GeckoRestyleManager::TryInitiatingTransition(aState.mPresContext,
    1948             :                                                      container,
    1949             :                                                      oldStyleContext,
    1950           0 :                                                      &pseudoStyleContext);
    1951             :       } else {
    1952           0 :         aState.mPresContext->TransitionManager()->
    1953           0 :           PruneCompletedTransitions(aParentContent->AsElement(),
    1954           0 :                                     aPseudoElement, pseudoStyleContext);
    1955             :       }
    1956             :     }
    1957             :   }
    1958             : 
    1959           6 :   uint32_t contentCount = pseudoStyleContext->StyleContent()->ContentCount();
    1960           6 :   bool createdChildElement = false;
    1961          12 :   for (uint32_t contentIndex = 0; contentIndex < contentCount; contentIndex++) {
    1962             :     nsCOMPtr<nsIContent> content =
    1963          12 :       CreateGeneratedContent(aState, aParentContent, pseudoStyleContext,
    1964          12 :                              contentIndex);
    1965           6 :     if (content) {
    1966           6 :       container->AppendChildTo(content, false);
    1967           6 :       if (content->IsElement()) {
    1968           0 :         createdChildElement = true;
    1969             :       }
    1970             :     }
    1971             :   }
    1972             : 
    1973             :   // We may need to do a synchronous servo traversal in various uncommon cases.
    1974           6 :   if (isServo) {
    1975           0 :     if (hasServoAnimations) {
    1976             :       // If animations are involved, we avoid the SetExplicitStyle optimization
    1977             :       // above.
    1978           0 :       mPresShell->StyleSet()->AsServo()->StyleNewSubtree(container);
    1979           0 :     } else if (createdChildElement) {
    1980             :       // If we created any children elements, Servo needs to traverse them, but
    1981             :       // the root is already set up.
    1982           0 :       mPresShell->StyleSet()->AsServo()->StyleNewChildren(container);
    1983             :     }
    1984             :   }
    1985             : 
    1986           6 :   AddFrameConstructionItemsInternal(aState, container, aParentFrame, elemName,
    1987             :                                     kNameSpaceID_None, true,
    1988             :                                     pseudoStyleContext,
    1989             :                                     ITEM_IS_GENERATED_CONTENT, nullptr,
    1990           6 :                                     aItems);
    1991             : }
    1992             : 
    1993             : /****************************************************
    1994             :  **  BEGIN TABLE SECTION
    1995             :  ****************************************************/
    1996             : 
    1997             : // The term pseudo frame is being used instead of anonymous frame, since anonymous
    1998             : // frame has been used elsewhere to refer to frames that have generated content
    1999             : 
    2000             : // Return whether the given frame is a table pseudo-frame. Note that
    2001             : // cell-content and table-outer frames have pseudo-types, but are always
    2002             : // created, even for non-anonymous cells and tables respectively.  So for those
    2003             : // we have to examine the cell or table frame to see whether it's a pseudo
    2004             : // frame. In particular, a lone table caption will have a table wrapper as its
    2005             : // parent, but will also trigger construction of an empty inner table, which
    2006             : // will be the one we can examine to see whether the wrapper was a pseudo-frame.
    2007             : static bool
    2008          84 : IsTablePseudo(nsIFrame* aFrame)
    2009             : {
    2010          84 :   nsIAtom* pseudoType = aFrame->StyleContext()->GetPseudo();
    2011          96 :   return pseudoType &&
    2012          24 :     (pseudoType == nsCSSAnonBoxes::table ||
    2013          24 :      pseudoType == nsCSSAnonBoxes::inlineTable ||
    2014          24 :      pseudoType == nsCSSAnonBoxes::tableColGroup ||
    2015          24 :      pseudoType == nsCSSAnonBoxes::tableRowGroup ||
    2016          24 :      pseudoType == nsCSSAnonBoxes::tableRow ||
    2017          24 :      pseudoType == nsCSSAnonBoxes::tableCell ||
    2018          12 :      (pseudoType == nsCSSAnonBoxes::cellContent &&
    2019           0 :       aFrame->GetParent()->StyleContext()->GetPseudo() ==
    2020          12 :         nsCSSAnonBoxes::tableCell) ||
    2021          12 :      (pseudoType == nsCSSAnonBoxes::tableWrapper &&
    2022           0 :       (aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo() ==
    2023           0 :          nsCSSAnonBoxes::table ||
    2024           0 :        aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo() ==
    2025          84 :          nsCSSAnonBoxes::inlineTable)));
    2026             : }
    2027             : 
    2028             : static bool
    2029         128 : IsRubyPseudo(nsIFrame* aFrame)
    2030             : {
    2031         128 :   return RubyUtils::IsRubyPseudo(aFrame->StyleContext()->GetPseudo());
    2032             : }
    2033             : 
    2034             : static bool
    2035          84 : IsTableOrRubyPseudo(nsIFrame* aFrame)
    2036             : {
    2037          84 :   return IsTablePseudo(aFrame) || IsRubyPseudo(aFrame);
    2038             : }
    2039             : 
    2040             : /* static */
    2041             : nsCSSFrameConstructor::ParentType
    2042        1702 : nsCSSFrameConstructor::GetParentType(LayoutFrameType aFrameType)
    2043             : {
    2044        1702 :   if (aFrameType == LayoutFrameType::Table) {
    2045           0 :     return eTypeTable;
    2046             :   }
    2047        1702 :   if (aFrameType == LayoutFrameType::TableRowGroup) {
    2048           0 :     return eTypeRowGroup;
    2049             :   }
    2050        1702 :   if (aFrameType == LayoutFrameType::TableRow) {
    2051           0 :     return eTypeRow;
    2052             :   }
    2053        1702 :   if (aFrameType == LayoutFrameType::TableColGroup) {
    2054           0 :     return eTypeColGroup;
    2055             :   }
    2056        1702 :   if (aFrameType == LayoutFrameType::RubyBaseContainer) {
    2057           0 :     return eTypeRubyBaseContainer;
    2058             :   }
    2059        1702 :   if (aFrameType == LayoutFrameType::RubyTextContainer) {
    2060           0 :     return eTypeRubyTextContainer;
    2061             :   }
    2062        1702 :   if (aFrameType == LayoutFrameType::Ruby) {
    2063           0 :     return eTypeRuby;
    2064             :   }
    2065             : 
    2066        1702 :   return eTypeBlock;
    2067             : }
    2068             : 
    2069             : static nsContainerFrame*
    2070           0 : AdjustCaptionParentFrame(nsContainerFrame* aParentFrame)
    2071             : {
    2072           0 :   if (aParentFrame->IsTableFrame()) {
    2073           0 :     return aParentFrame->GetParent();
    2074             :   }
    2075           0 :   return aParentFrame;
    2076             : }
    2077             : 
    2078             : /**
    2079             :  * If the parent frame is a |tableFrame| and the child is a
    2080             :  * |captionFrame|, then we want to insert the frames beneath the
    2081             :  * |tableFrame|'s parent frame. Returns |true| if the parent frame
    2082             :  * needed to be fixed up.
    2083             :  */
    2084             : static bool
    2085           0 : GetCaptionAdjustedParent(nsContainerFrame*  aParentFrame,
    2086             :                          const nsIFrame*    aChildFrame,
    2087             :                          nsContainerFrame** aAdjParentFrame)
    2088             : {
    2089           0 :   *aAdjParentFrame = aParentFrame;
    2090           0 :   bool haveCaption = false;
    2091             : 
    2092           0 :   if (aChildFrame->IsTableCaption()) {
    2093           0 :     haveCaption = true;
    2094           0 :     *aAdjParentFrame = ::AdjustCaptionParentFrame(aParentFrame);
    2095             :   }
    2096           0 :   return haveCaption;
    2097             : }
    2098             : 
    2099             : void
    2100         492 : nsCSSFrameConstructor::AdjustParentFrame(nsContainerFrame**           aParentFrame,
    2101             :                                          const FrameConstructionData* aFCData,
    2102             :                                          nsStyleContext*              aStyleContext)
    2103             : {
    2104         492 :   NS_PRECONDITION(aStyleContext, "Must have child's style context");
    2105         492 :   NS_PRECONDITION(aFCData, "Must have frame construction data");
    2106             : 
    2107         492 :   bool tablePart = ((aFCData->mBits & FCDATA_IS_TABLE_PART) != 0);
    2108             : 
    2109         492 :   if (tablePart && aStyleContext->StyleDisplay()->mDisplay ==
    2110             :       StyleDisplay::TableCaption) {
    2111           0 :     *aParentFrame = ::AdjustCaptionParentFrame(*aParentFrame);
    2112             :   }
    2113         492 : }
    2114             : 
    2115             : // Pull all the captions present in aItems out  into aCaptions
    2116             : static void
    2117           0 : PullOutCaptionFrames(nsFrameItems& aItems, nsFrameItems& aCaptions)
    2118             : {
    2119           0 :   nsIFrame* child = aItems.FirstChild();
    2120           0 :   while (child) {
    2121           0 :     nsIFrame* nextSibling = child->GetNextSibling();
    2122           0 :     if (child->IsTableCaption()) {
    2123           0 :       aItems.RemoveFrame(child);
    2124           0 :       aCaptions.AddChild(child);
    2125             :     }
    2126           0 :     child = nextSibling;
    2127             :   }
    2128           0 : }
    2129             : 
    2130             : 
    2131             : // Construct the outer, inner table frames and the children frames for the table.
    2132             : // XXX Page break frames for pseudo table frames are not constructed to avoid the risk
    2133             : // associated with revising the pseudo frame mechanism. The long term solution
    2134             : // of having frames handle page-break-before/after will solve the problem.
    2135             : nsIFrame*
    2136           0 : nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
    2137             :                                       FrameConstructionItem&   aItem,
    2138             :                                       nsContainerFrame*        aParentFrame,
    2139             :                                       const nsStyleDisplay*    aDisplay,
    2140             :                                       nsFrameItems&            aFrameItems)
    2141             : {
    2142           0 :   NS_PRECONDITION(aDisplay->mDisplay == StyleDisplay::Table ||
    2143             :                   aDisplay->mDisplay == StyleDisplay::InlineTable,
    2144             :                   "Unexpected call");
    2145             : 
    2146           0 :   nsIContent* const content = aItem.mContent;
    2147           0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    2148           0 :   const uint32_t nameSpaceID = aItem.mNameSpaceID;
    2149             : 
    2150             :   // create the pseudo SC for the table wrapper as a child of the inner SC
    2151           0 :   RefPtr<nsStyleContext> outerStyleContext;
    2152           0 :   outerStyleContext = mPresShell->StyleSet()->
    2153           0 :     ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::tableWrapper,
    2154           0 :                                        styleContext);
    2155             : 
    2156             :   // Create the table wrapper frame which holds the caption and inner table frame
    2157             :   nsContainerFrame* newFrame;
    2158           0 :   if (kNameSpaceID_MathML == nameSpaceID)
    2159           0 :     newFrame = NS_NewMathMLmtableOuterFrame(mPresShell, outerStyleContext);
    2160             :   else
    2161           0 :     newFrame = NS_NewTableWrapperFrame(mPresShell, outerStyleContext);
    2162             : 
    2163             :   nsContainerFrame* geometricParent =
    2164           0 :     aState.GetGeometricParent(outerStyleContext->StyleDisplay(),
    2165           0 :                               aParentFrame);
    2166             : 
    2167             :   // Init the table wrapper frame
    2168           0 :   InitAndRestoreFrame(aState, content, geometricParent, newFrame);
    2169             : 
    2170             :   // Create the inner table frame
    2171             :   nsContainerFrame* innerFrame;
    2172           0 :   if (kNameSpaceID_MathML == nameSpaceID)
    2173           0 :     innerFrame = NS_NewMathMLmtableFrame(mPresShell, styleContext);
    2174             :   else
    2175           0 :     innerFrame = NS_NewTableFrame(mPresShell, styleContext);
    2176             : 
    2177           0 :   InitAndRestoreFrame(aState, content, newFrame, innerFrame);
    2178           0 :   innerFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2179             : 
    2180             :   // Put the newly created frames into the right child list
    2181           0 :   SetInitialSingleChild(newFrame, innerFrame);
    2182             : 
    2183           0 :   aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame);
    2184             : 
    2185           0 :   if (!mRootElementFrame) {
    2186             :     // The frame we're constructing will be the root element frame.
    2187             :     // Set mRootElementFrame before processing children.
    2188           0 :     mRootElementFrame = newFrame;
    2189             :   }
    2190             : 
    2191           0 :   nsFrameItems childItems;
    2192             : 
    2193             :   // Process children
    2194           0 :   nsFrameConstructorSaveState absoluteSaveState;
    2195           0 :   const nsStyleDisplay* display = outerStyleContext->StyleDisplay();
    2196             : 
    2197             :   // Mark the table frame as an absolute container if needed
    2198           0 :   newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2199           0 :   if (display->IsAbsPosContainingBlock(newFrame)) {
    2200           0 :     aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
    2201             :   }
    2202           0 :   NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
    2203             :                "nsIAnonymousContentCreator::CreateAnonymousContent "
    2204             :                "implementations for table frames are not currently expected "
    2205             :                "to output a list where the items have their own children");
    2206           0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    2207           0 :     ConstructFramesFromItemList(aState, aItem.mChildItems,
    2208           0 :                                 innerFrame, childItems);
    2209             :   } else {
    2210           0 :     ProcessChildren(aState, content, styleContext, innerFrame,
    2211           0 :                     true, childItems, false, aItem.mPendingBinding);
    2212             :   }
    2213             : 
    2214           0 :   nsFrameItems captionItems;
    2215           0 :   PullOutCaptionFrames(childItems, captionItems);
    2216             : 
    2217             :   // Set the inner table frame's initial primary list
    2218           0 :   innerFrame->SetInitialChildList(kPrincipalList, childItems);
    2219             : 
    2220             :   // Set the table wrapper frame's secondary childlist lists
    2221           0 :   if (captionItems.NotEmpty()) {
    2222           0 :     newFrame->SetInitialChildList(nsIFrame::kCaptionList, captionItems);
    2223             :   }
    2224             : 
    2225           0 :   return newFrame;
    2226             : }
    2227             : 
    2228             : static void
    2229           0 : MakeTablePartAbsoluteContainingBlockIfNeeded(nsFrameConstructorState&     aState,
    2230             :                                              const nsStyleDisplay*        aDisplay,
    2231             :                                              nsFrameConstructorSaveState& aAbsSaveState,
    2232             :                                              nsContainerFrame*            aFrame)
    2233             : {
    2234             :   // If we're positioned, then we need to become an absolute containing block
    2235             :   // for any absolutely positioned children and register for post-reflow fixup.
    2236             :   //
    2237             :   // Note that usually if a frame type can be an absolute containing block, we
    2238             :   // always set NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN, whether it actually is or not.
    2239             :   // However, in this case flag serves the additional purpose of indicating that
    2240             :   // the frame was registered with its table frame. This allows us to avoid the
    2241             :   // overhead of unregistering the frame in most cases.
    2242           0 :   if (aDisplay->IsAbsPosContainingBlock(aFrame)) {
    2243           0 :     aFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2244           0 :     aState.PushAbsoluteContainingBlock(aFrame, aFrame, aAbsSaveState);
    2245           0 :     nsTableFrame::RegisterPositionedTablePart(aFrame);
    2246             :   }
    2247           0 : }
    2248             : 
    2249             : nsIFrame*
    2250           0 : nsCSSFrameConstructor::ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
    2251             :                                                    FrameConstructionItem&   aItem,
    2252             :                                                    nsContainerFrame*        aParentFrame,
    2253             :                                                    const nsStyleDisplay*    aDisplay,
    2254             :                                                    nsFrameItems&            aFrameItems)
    2255             : {
    2256           0 :   MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::TableRow ||
    2257             :              aDisplay->mDisplay == StyleDisplay::TableRowGroup ||
    2258             :              aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
    2259             :              aDisplay->mDisplay == StyleDisplay::TableHeaderGroup,
    2260             :              "Not a row or row group");
    2261           0 :   MOZ_ASSERT(aItem.mStyleContext->StyleDisplay() == aDisplay,
    2262             :              "Display style doesn't match style context");
    2263           0 :   nsIContent* const content = aItem.mContent;
    2264           0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    2265           0 :   const uint32_t nameSpaceID = aItem.mNameSpaceID;
    2266             : 
    2267             :   nsContainerFrame* newFrame;
    2268           0 :   if (aDisplay->mDisplay == StyleDisplay::TableRow) {
    2269           0 :     if (kNameSpaceID_MathML == nameSpaceID)
    2270           0 :       newFrame = NS_NewMathMLmtrFrame(mPresShell, styleContext);
    2271             :     else
    2272           0 :       newFrame = NS_NewTableRowFrame(mPresShell, styleContext);
    2273             :   } else {
    2274           0 :     newFrame = NS_NewTableRowGroupFrame(mPresShell, styleContext);
    2275             :   }
    2276             : 
    2277           0 :   InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
    2278             : 
    2279           0 :   nsFrameConstructorSaveState absoluteSaveState;
    2280             :   MakeTablePartAbsoluteContainingBlockIfNeeded(aState, aDisplay,
    2281             :                                                absoluteSaveState,
    2282           0 :                                                newFrame);
    2283             : 
    2284           0 :   nsFrameItems childItems;
    2285           0 :   NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
    2286             :                "nsIAnonymousContentCreator::CreateAnonymousContent "
    2287             :                "implementations for table frames are not currently expected "
    2288             :                "to output a list where the items have their own children");
    2289           0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    2290           0 :     ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
    2291           0 :                                 childItems);
    2292             :   } else {
    2293           0 :     ProcessChildren(aState, content, styleContext, newFrame,
    2294           0 :                     true, childItems, false, aItem.mPendingBinding);
    2295             :   }
    2296             : 
    2297           0 :   newFrame->SetInitialChildList(kPrincipalList, childItems);
    2298           0 :   aFrameItems.AddChild(newFrame);
    2299           0 :   return newFrame;
    2300             : }
    2301             : 
    2302             : nsIFrame*
    2303           0 : nsCSSFrameConstructor::ConstructTableCol(nsFrameConstructorState& aState,
    2304             :                                          FrameConstructionItem&   aItem,
    2305             :                                          nsContainerFrame*        aParentFrame,
    2306             :                                          const nsStyleDisplay*    aStyleDisplay,
    2307             :                                          nsFrameItems&            aFrameItems)
    2308             : {
    2309           0 :   nsIContent* const content = aItem.mContent;
    2310           0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    2311             : 
    2312           0 :   nsTableColFrame* colFrame = NS_NewTableColFrame(mPresShell, styleContext);
    2313           0 :   InitAndRestoreFrame(aState, content, aParentFrame, colFrame);
    2314             : 
    2315           0 :   NS_ASSERTION(colFrame->StyleContext() == styleContext,
    2316             :                "Unexpected style context");
    2317             : 
    2318           0 :   aFrameItems.AddChild(colFrame);
    2319             : 
    2320             :   // construct additional col frames if the col frame has a span > 1
    2321           0 :   int32_t span = colFrame->GetSpan();
    2322           0 :   for (int32_t spanX = 1; spanX < span; spanX++) {
    2323           0 :     nsTableColFrame* newCol = NS_NewTableColFrame(mPresShell, styleContext);
    2324           0 :     InitAndRestoreFrame(aState, content, aParentFrame, newCol, false);
    2325           0 :     aFrameItems.LastChild()->SetNextContinuation(newCol);
    2326           0 :     newCol->SetPrevContinuation(aFrameItems.LastChild());
    2327           0 :     aFrameItems.AddChild(newCol);
    2328           0 :     newCol->SetColType(eColAnonymousCol);
    2329             :   }
    2330             : 
    2331           0 :   return colFrame;
    2332             : }
    2333             : 
    2334             : nsIFrame*
    2335           0 : nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState,
    2336             :                                           FrameConstructionItem&   aItem,
    2337             :                                           nsContainerFrame*        aParentFrame,
    2338             :                                           const nsStyleDisplay*    aDisplay,
    2339             :                                           nsFrameItems&            aFrameItems)
    2340             : {
    2341           0 :   MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::TableCell,
    2342             :              "Unexpected call");
    2343             : 
    2344           0 :   nsIContent* const content = aItem.mContent;
    2345           0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    2346           0 :   const uint32_t nameSpaceID = aItem.mNameSpaceID;
    2347             : 
    2348             :   nsTableFrame* tableFrame =
    2349           0 :     static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
    2350             :   nsContainerFrame* newFrame;
    2351             :   // <mtable> is border separate in mathml.css and the MathML code doesn't implement
    2352             :   // border collapse. For those users who style <mtable> with border collapse,
    2353             :   // give them the default non-MathML table frames that understand border collapse.
    2354             :   // This won't break us because MathML table frames are all subclasses of the default
    2355             :   // table code, and so we can freely mix <mtable> with <mtr> or <tr>, <mtd> or <td>.
    2356             :   // What will happen is just that non-MathML frames won't understand MathML attributes
    2357             :   // and will therefore miss the special handling that the MathML code does.
    2358           0 :   if (kNameSpaceID_MathML == nameSpaceID && !tableFrame->IsBorderCollapse()) {
    2359           0 :     newFrame = NS_NewMathMLmtdFrame(mPresShell, styleContext, tableFrame);
    2360             :   } else {
    2361             :     // Warning: If you change this and add a wrapper frame around table cell
    2362             :     // frames, make sure Bug 368554 doesn't regress!
    2363             :     // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
    2364           0 :     newFrame = NS_NewTableCellFrame(mPresShell, styleContext, tableFrame);
    2365             :   }
    2366             : 
    2367             :   // Initialize the table cell frame
    2368           0 :   InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
    2369           0 :   newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2370             : 
    2371             :   // Resolve pseudo style and initialize the body cell frame
    2372           0 :   RefPtr<nsStyleContext> innerPseudoStyle;
    2373           0 :   innerPseudoStyle = mPresShell->StyleSet()->
    2374           0 :     ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::cellContent,
    2375           0 :                                        styleContext);
    2376             : 
    2377             :   // Create a block frame that will format the cell's content
    2378             :   bool isBlock;
    2379             :   nsContainerFrame* cellInnerFrame;
    2380           0 :   if (kNameSpaceID_MathML == nameSpaceID) {
    2381           0 :     cellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
    2382           0 :     isBlock = false;
    2383             :   } else {
    2384           0 :     cellInnerFrame = NS_NewBlockFormattingContext(mPresShell, innerPseudoStyle);
    2385           0 :     isBlock = true;
    2386             :   }
    2387             : 
    2388           0 :   InitAndRestoreFrame(aState, content, newFrame, cellInnerFrame);
    2389             : 
    2390           0 :   nsFrameConstructorSaveState absoluteSaveState;
    2391             :   MakeTablePartAbsoluteContainingBlockIfNeeded(aState, aDisplay,
    2392             :                                                absoluteSaveState,
    2393           0 :                                                newFrame);
    2394             : 
    2395           0 :   nsFrameItems childItems;
    2396           0 :   NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
    2397             :                "nsIAnonymousContentCreator::CreateAnonymousContent "
    2398             :                "implementations for table frames are not currently expected "
    2399             :                "to output a list where the items have their own children");
    2400           0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    2401             :     // Need to push ourselves as a float containing block.
    2402             :     // XXXbz it might be nice to work on getting the parent
    2403             :     // FrameConstructionItem down into ProcessChildren and just making use of
    2404             :     // the push there, but that's a bit of work.
    2405           0 :     nsFrameConstructorSaveState floatSaveState;
    2406           0 :     if (!isBlock) { /* MathML case */
    2407           0 :       aState.PushFloatContainingBlock(nullptr, floatSaveState);
    2408             :     } else {
    2409           0 :       aState.PushFloatContainingBlock(cellInnerFrame, floatSaveState);
    2410             :     }
    2411             : 
    2412           0 :     ConstructFramesFromItemList(aState, aItem.mChildItems, cellInnerFrame,
    2413           0 :                                 childItems);
    2414             :   } else {
    2415             :     // Process the child content
    2416           0 :     ProcessChildren(aState, content, styleContext, cellInnerFrame,
    2417           0 :                     true, childItems, isBlock, aItem.mPendingBinding);
    2418             :   }
    2419             : 
    2420           0 :   cellInnerFrame->SetInitialChildList(kPrincipalList, childItems);
    2421           0 :   SetInitialSingleChild(newFrame, cellInnerFrame);
    2422           0 :   aFrameItems.AddChild(newFrame);
    2423           0 :   return newFrame;
    2424             : }
    2425             : 
    2426             : static inline bool
    2427         884 : NeedFrameFor(const nsFrameConstructorState& aState,
    2428             :              nsIFrame*   aParentFrame,
    2429             :              nsIContent* aChildContent)
    2430             : {
    2431             :   // XXX the GetContent() != aChildContent check is needed due to bug 135040.
    2432             :   // Remove it once that's fixed.
    2433         884 :   NS_PRECONDITION(!aChildContent->GetPrimaryFrame() ||
    2434             :                   aState.mCreatingExtraFrames ||
    2435             :                   aChildContent->GetPrimaryFrame()->GetContent() != aChildContent,
    2436             :                   "Why did we get called?");
    2437             : 
    2438             :   // don't create a whitespace frame if aParentFrame doesn't want it.
    2439             :   // always create frames for children in generated content. counter(),
    2440             :   // quotes, and attr() content can easily change dynamically and we don't
    2441             :   // want to be reconstructing frames. It's not even clear that these
    2442             :   // should be considered ignorable just because they evaluate to
    2443             :   // whitespace.
    2444             : 
    2445             :   // We could handle all this in CreateNeededPseudoContainers or some other
    2446             :   // place after we build our frame construction items, but that would involve
    2447             :   // creating frame construction items for whitespace kids of
    2448             :   // eExcludesIgnorableWhitespace frames, where we know we'll be dropping them
    2449             :   // all anyway, and involve an extra walk down the frame construction item
    2450             :   // list.
    2451        1768 :   if ((aParentFrame &&
    2452        1464 :        (!aParentFrame->IsFrameOfType(nsIFrame::eExcludesIgnorableWhitespace) ||
    2453        2039 :         aParentFrame->IsGeneratedContentFrame())) ||
    2454         575 :       !aChildContent->IsNodeOfType(nsINode::eTEXT)) {
    2455         884 :     return true;
    2456             :   }
    2457             : 
    2458           0 :   aChildContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
    2459           0 :                           NS_REFRAME_IF_WHITESPACE);
    2460           0 :   return !aChildContent->TextIsOnlyWhitespace();
    2461             : }
    2462             : 
    2463             : /***********************************************
    2464             :  * END TABLE SECTION
    2465             :  ***********************************************/
    2466             : 
    2467             : nsIFrame*
    2468          24 : nsCSSFrameConstructor::ConstructDocElementFrame(Element*                 aDocElement,
    2469             :                                                 nsILayoutHistoryState*   aFrameState)
    2470             : {
    2471          24 :   MOZ_ASSERT(GetRootFrame(),
    2472             :              "No viewport?  Someone forgot to call ConstructRootFrame!");
    2473          24 :   MOZ_ASSERT(!mDocElementContainingBlock,
    2474             :              "Shouldn't have a doc element containing block here");
    2475             : 
    2476             :   // Resolve a new style context for the viewport since it may be affected
    2477             :   // by a new root element style (e.g. a propagated 'direction').
    2478             :   // @see nsStyleContext::ApplyStyleFixups
    2479             :   {
    2480          48 :     RefPtr<nsStyleContext> sc = mPresShell->StyleSet()->
    2481          72 :       ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::viewport, nullptr);
    2482          24 :     GetRootFrame()->SetStyleContextWithoutNotification(sc);
    2483             :   }
    2484             : 
    2485             :   // Make sure to call UpdateViewportScrollbarStylesOverride before
    2486             :   // SetUpDocElementContainingBlock, since it sets up our scrollbar state
    2487             :   // properly.
    2488          48 :   DebugOnly<nsIContent*> propagatedScrollFrom;
    2489          24 :   if (nsPresContext* presContext = mPresShell->GetPresContext()) {
    2490          24 :     propagatedScrollFrom = presContext->UpdateViewportScrollbarStylesOverride();
    2491             :   }
    2492             : 
    2493          24 :   SetUpDocElementContainingBlock(aDocElement);
    2494             : 
    2495          24 :   NS_ASSERTION(mDocElementContainingBlock, "Should have parent by now");
    2496             : 
    2497          48 :   TreeMatchContextHolder matchContext(mDocument);
    2498             :   // Initialize the ancestor filter with null for now; we'll push
    2499             :   // aDocElement once we finish resolving style for it.
    2500          24 :   if (matchContext.Exists()) {
    2501          24 :     matchContext->InitAncestors(nullptr);
    2502             :   }
    2503             :   nsFrameConstructorState state(mPresShell,
    2504             :                                 matchContext,
    2505          24 :                                 GetAbsoluteContainingBlock(mDocElementContainingBlock, FIXED_POS),
    2506             :                                 nullptr,
    2507          72 :                                 nullptr, do_AddRef(aFrameState));
    2508             : 
    2509             :   // XXXbz why, exactly?
    2510          24 :   if (!mTempFrameTreeState)
    2511          24 :     state.mPresShell->CaptureHistoryState(getter_AddRefs(mTempFrameTreeState));
    2512             : 
    2513             :   // Make sure that we'll handle restyles for this document element in
    2514             :   // the future.  We need this, because the document element might
    2515             :   // have stale restyle bits from a previous frame constructor for
    2516             :   // this document.  Unlike in AddFrameConstructionItems, it's safe to
    2517             :   // unset all element restyle flags, since we don't have any
    2518             :   // siblings.
    2519          24 :   aDocElement->UnsetRestyleFlagsIfGecko();
    2520             : 
    2521             :   // --------- CREATE AREA OR BOX FRAME -------
    2522          24 :   if (ServoStyleSet* set = mPresShell->StyleSet()->GetAsServo()) {
    2523             :     // NOTE(emilio): If the root has a non-null binding, we'll stop at the
    2524             :     // document element and won't process any children, loading the bindings (or
    2525             :     // failing to do so) will take care of the rest.
    2526           0 :     set->StyleDocument(TraversalRestyleBehavior::Normal);
    2527             :   }
    2528             : 
    2529             :   // FIXME: Should this use ResolveStyleContext?  (The calls in this
    2530             :   // function are the only case in nsCSSFrameConstructor where we don't
    2531             :   // do so for the construction of a style context for an element.)
    2532             :   RefPtr<nsStyleContext> styleContext =
    2533          48 :     mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
    2534             :                                             nullptr,
    2535          48 :                                             LazyComputeBehavior::Assert);
    2536             : 
    2537          24 :   const nsStyleDisplay* display = styleContext->StyleDisplay();
    2538             : 
    2539             :   // Ensure that our XBL bindings are installed.
    2540          24 :   if (display->mBinding) {
    2541             :     // Get the XBL loader.
    2542             :     nsresult rv;
    2543             :     bool resolveStyle;
    2544             : 
    2545           1 :     nsXBLService* xblService = nsXBLService::GetInstance();
    2546           1 :     if (!xblService) {
    2547           0 :       return nullptr;
    2548             :     }
    2549             : 
    2550           2 :     RefPtr<nsXBLBinding> binding;
    2551           2 :     rv = xblService->LoadBindings(aDocElement, display->mBinding->GetURI(),
    2552           1 :                                   display->mBinding->mExtraData->GetPrincipal(),
    2553           2 :                                   getter_AddRefs(binding), &resolveStyle);
    2554           1 :     if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED) {
    2555             :       // Binding will load asynchronously.
    2556           0 :       if (aDocElement->IsStyledByServo()) {
    2557           0 :         ServoRestyleManager::ClearServoDataFromSubtree(aDocElement);
    2558             :       }
    2559           0 :       return nullptr;
    2560             :     }
    2561             : 
    2562           1 :     if (binding) {
    2563             :       // For backwards compat, keep firing the root's constructor
    2564             :       // after all of its kids' constructors.  So tell the binding
    2565             :       // manager about it right now.
    2566           1 :       mDocument->BindingManager()->AddToAttachedQueue(binding);
    2567             :     }
    2568             : 
    2569           1 :     if (resolveStyle) {
    2570             :       // FIXME: Should this use ResolveStyleContext?  (The calls in this
    2571             :       // function are the only case in nsCSSFrameConstructor where we
    2572             :       // don't do so for the construction of a style context for an
    2573             :       // element.)
    2574             :       //
    2575             :       // FIXME(emilio): This looks fishy. It really wants to fully re-resolve
    2576             :       // the style, but it wont if the element is already styled afaict... It
    2577             :       // seems we handle it on a subsequent restyle?
    2578           0 :       styleContext = mPresShell->StyleSet()->ResolveStyleFor(
    2579           0 :           aDocElement, nullptr, LazyComputeBehavior::Assert);
    2580           0 :       display = styleContext->StyleDisplay();
    2581             :     }
    2582          23 :   } else if (display->mBinding.ForceGet() && aDocElement->IsStyledByServo()) {
    2583             :     // See the comment in AddFrameConstructionItemsInternal for why this is
    2584             :     // needed.
    2585           0 :     mPresShell->StyleSet()->AsServo()->StyleNewChildren(aDocElement);
    2586             :   }
    2587             : 
    2588             :   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
    2589             : 
    2590          24 :   NS_ASSERTION(!display->IsScrollableOverflow() ||
    2591             :                state.mPresContext->IsPaginated() ||
    2592             :                propagatedScrollFrom == aDocElement,
    2593             :                "Scrollbars should have been propagated to the viewport");
    2594             : 
    2595          24 :   if (MOZ_UNLIKELY(display->mDisplay == StyleDisplay::None)) {
    2596           0 :     SetUndisplayedContent(aDocElement, styleContext);
    2597           0 :     return nullptr;
    2598             :   }
    2599             : 
    2600          48 :   TreeMatchContext::AutoAncestorPusher ancestorPusher(state.mTreeMatchContext);
    2601          24 :   ancestorPusher.PushAncestorAndStyleScope(aDocElement);
    2602             : 
    2603             :   // Make sure to start any background image loads for the root element now.
    2604          24 :   styleContext->StartBackgroundImageLoads();
    2605             : 
    2606          48 :   nsFrameConstructorSaveState docElementContainingBlockAbsoluteSaveState;
    2607          24 :   if (mHasRootAbsPosContainingBlock) {
    2608             :     // Push the absolute containing block now so we can absolutely position
    2609             :     // the root element
    2610          23 :     mDocElementContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2611          23 :     state.PushAbsoluteContainingBlock(mDocElementContainingBlock,
    2612          23 :                                       mDocElementContainingBlock,
    2613          23 :                                       docElementContainingBlockAbsoluteSaveState);
    2614             :   }
    2615             : 
    2616             :   // The rules from CSS 2.1, section 9.2.4, have already been applied
    2617             :   // by the style system, so we can assume that display->mDisplay is
    2618             :   // either NONE, BLOCK, or TABLE.
    2619             : 
    2620             :   // contentFrame is the primary frame for the root element. newFrame
    2621             :   // is the frame that will be the child of the initial containing block.
    2622             :   // These are usually the same frame but they can be different, in
    2623             :   // particular if the root frame is positioned, in which case
    2624             :   // contentFrame is the out-of-flow frame and newFrame is the
    2625             :   // placeholder.
    2626             :   nsContainerFrame* contentFrame;
    2627             :   nsIFrame* newFrame;
    2628          24 :   bool processChildren = false;
    2629             : 
    2630          48 :   nsFrameConstructorSaveState absoluteSaveState;
    2631             : 
    2632             :   // Check whether we need to build a XUL box or SVG root frame
    2633             : #ifdef MOZ_XUL
    2634          24 :   if (aDocElement->IsXULElement()) {
    2635           1 :     contentFrame = NS_NewDocElementBoxFrame(mPresShell, styleContext);
    2636           1 :     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
    2637           1 :                         contentFrame);
    2638           1 :     newFrame = contentFrame;
    2639           1 :     processChildren = true;
    2640             :   }
    2641             :   else
    2642             : #endif
    2643          23 :   if (aDocElement->IsSVGElement()) {
    2644          21 :     if (!aDocElement->IsSVGElement(nsGkAtoms::svg)) {
    2645           0 :       return nullptr;
    2646             :     }
    2647             :     // We're going to call the right function ourselves, so no need to give a
    2648             :     // function to this FrameConstructionData.
    2649             : 
    2650             :     // XXXbz on the other hand, if we converted this whole function to
    2651             :     // FrameConstructionData/Item, then we'd need the right function
    2652             :     // here... but would probably be able to get away with less code in this
    2653             :     // function in general.
    2654             :     // Use a null PendingBinding, since our binding is not in fact pending.
    2655             :     static const FrameConstructionData rootSVGData = FCDATA_DECL(0, nullptr);
    2656             :     already_AddRefed<nsStyleContext> extraRef =
    2657          42 :       RefPtr<nsStyleContext>(styleContext).forget();
    2658             :     FrameConstructionItem item(&rootSVGData, aDocElement,
    2659             :                                aDocElement->NodeInfo()->NameAtom(),
    2660             :                                kNameSpaceID_SVG, nullptr, extraRef, true,
    2661          42 :                                nullptr);
    2662             : 
    2663          21 :     nsFrameItems frameItems;
    2664          21 :     contentFrame = static_cast<nsContainerFrame*>(
    2665          21 :       ConstructOuterSVG(state, item, mDocElementContainingBlock,
    2666             :                         styleContext->StyleDisplay(),
    2667             :                         frameItems));
    2668          21 :     newFrame = frameItems.FirstChild();
    2669          21 :     NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
    2670           4 :   } else if (display->mDisplay == StyleDisplay::Flex ||
    2671           2 :              display->mDisplay == StyleDisplay::WebkitBox) {
    2672           0 :     contentFrame = NS_NewFlexContainerFrame(mPresShell, styleContext);
    2673           0 :     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
    2674           0 :                         contentFrame);
    2675           0 :     newFrame = contentFrame;
    2676           0 :     processChildren = true;
    2677             : 
    2678           0 :     newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2679           0 :     if (display->IsAbsPosContainingBlock(newFrame)) {
    2680             :       state.PushAbsoluteContainingBlock(contentFrame, newFrame,
    2681           0 :                                         absoluteSaveState);
    2682             :     }
    2683             : 
    2684           2 :   } else if (display->mDisplay == StyleDisplay::Grid) {
    2685           0 :     contentFrame = NS_NewGridContainerFrame(mPresShell, styleContext);
    2686           0 :     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
    2687           0 :                         contentFrame);
    2688           0 :     newFrame = contentFrame;
    2689           0 :     processChildren = true;
    2690             : 
    2691           0 :     newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2692           0 :     if (display->IsAbsPosContainingBlock(newFrame)) {
    2693             :       state.PushAbsoluteContainingBlock(contentFrame, newFrame,
    2694           0 :                                         absoluteSaveState);
    2695             :     }
    2696           2 :   } else if (display->mDisplay == StyleDisplay::Table) {
    2697             :     // We're going to call the right function ourselves, so no need to give a
    2698             :     // function to this FrameConstructionData.
    2699             : 
    2700             :     // XXXbz on the other hand, if we converted this whole function to
    2701             :     // FrameConstructionData/Item, then we'd need the right function
    2702             :     // here... but would probably be able to get away with less code in this
    2703             :     // function in general.
    2704             :     // Use a null PendingBinding, since our binding is not in fact pending.
    2705             :     static const FrameConstructionData rootTableData = FCDATA_DECL(0, nullptr);
    2706             :     already_AddRefed<nsStyleContext> extraRef =
    2707           0 :       RefPtr<nsStyleContext>(styleContext).forget();
    2708             :     FrameConstructionItem item(&rootTableData, aDocElement,
    2709             :                                aDocElement->NodeInfo()->NameAtom(),
    2710             :                                kNameSpaceID_None, nullptr, extraRef, true,
    2711           0 :                                nullptr);
    2712             : 
    2713           0 :     nsFrameItems frameItems;
    2714             :     // if the document is a table then just populate it.
    2715           0 :     contentFrame = static_cast<nsContainerFrame*>(
    2716           0 :       ConstructTable(state, item, mDocElementContainingBlock,
    2717             :                      styleContext->StyleDisplay(),
    2718             :                      frameItems));
    2719           0 :     newFrame = frameItems.FirstChild();
    2720           0 :     NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
    2721             :   } else {
    2722           2 :     MOZ_ASSERT(display->mDisplay == StyleDisplay::Block ||
    2723             :                display->mDisplay == StyleDisplay::FlowRoot,
    2724             :                "Unhandled display type for root element");
    2725           2 :     contentFrame = NS_NewBlockFormattingContext(mPresShell, styleContext);
    2726           2 :     nsFrameItems frameItems;
    2727             :     // Use a null PendingBinding, since our binding is not in fact pending.
    2728           2 :     ConstructBlock(state, aDocElement,
    2729             :                    state.GetGeometricParent(display,
    2730             :                                             mDocElementContainingBlock),
    2731             :                    mDocElementContainingBlock, styleContext,
    2732             :                    &contentFrame, frameItems,
    2733           2 :                    display->IsAbsPosContainingBlock(contentFrame) ? contentFrame : nullptr,
    2734           2 :                    nullptr);
    2735           2 :     newFrame = frameItems.FirstChild();
    2736           2 :     NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
    2737             :   }
    2738             : 
    2739          24 :   MOZ_ASSERT(newFrame);
    2740          24 :   MOZ_ASSERT(contentFrame);
    2741             : 
    2742          24 :   NS_ASSERTION(processChildren ? !mRootElementFrame :
    2743             :                  mRootElementFrame == contentFrame,
    2744             :                "unexpected mRootElementFrame");
    2745          24 :   mRootElementFrame = contentFrame;
    2746             : 
    2747             :   // Figure out which frame has the main style for the document element,
    2748             :   // assigning it to mRootElementStyleFrame.
    2749             :   // Backgrounds should be propagated from that frame to the viewport.
    2750          24 :   contentFrame->GetParentStyleContext(&mRootElementStyleFrame);
    2751          24 :   bool isChild = mRootElementStyleFrame &&
    2752          24 :                  mRootElementStyleFrame->GetParent() == contentFrame;
    2753          24 :   if (!isChild) {
    2754          24 :     mRootElementStyleFrame = mRootElementFrame;
    2755             :   }
    2756             : 
    2757          24 :   if (processChildren) {
    2758             :     // Still need to process the child content
    2759           1 :     nsFrameItems childItems;
    2760             : 
    2761           1 :     NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame) &&
    2762             :                  !contentFrame->IsFrameOfType(nsIFrame::eSVG),
    2763             :                  "Only XUL frames should reach here");
    2764             :     // Use a null PendingBinding, since our binding is not in fact pending.
    2765           1 :     ProcessChildren(state, aDocElement, styleContext, contentFrame, true,
    2766           2 :                     childItems, false, nullptr);
    2767             : 
    2768             :     // Set the initial child lists
    2769           1 :     contentFrame->SetInitialChildList(kPrincipalList, childItems);
    2770             :   }
    2771             : 
    2772             :   // set the primary frame
    2773          24 :   aDocElement->SetPrimaryFrame(contentFrame);
    2774             : 
    2775          24 :   SetInitialSingleChild(mDocElementContainingBlock, newFrame);
    2776             : 
    2777             :   // Create frames for anonymous contents if there is a canvas frame.
    2778          24 :   if (mDocElementContainingBlock->IsCanvasFrame()) {
    2779          23 :     ConstructAnonymousContentForCanvas(state, mDocElementContainingBlock,
    2780          23 :                                        aDocElement);
    2781             :   }
    2782             : 
    2783          24 :   return newFrame;
    2784             : }
    2785             : 
    2786             : 
    2787             : nsIFrame*
    2788          24 : nsCSSFrameConstructor::ConstructRootFrame()
    2789             : {
    2790          48 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    2791             : 
    2792          24 :   StyleSetHandle styleSet = mPresShell->StyleSet();
    2793             : 
    2794             :   // --------- BUILD VIEWPORT -----------
    2795             :   RefPtr<nsStyleContext> viewportPseudoStyle =
    2796          48 :     styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::viewport,
    2797          48 :                                                  nullptr);
    2798             :   ViewportFrame* viewportFrame =
    2799          24 :     NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
    2800             : 
    2801             :   // XXXbz do we _have_ to pass a null content pointer to that frame?
    2802             :   // Would it really kill us to pass in the root element or something?
    2803             :   // What would that break?
    2804          24 :   viewportFrame->Init(nullptr, nullptr, nullptr);
    2805             : 
    2806          24 :   viewportFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2807             : 
    2808             :   // Bind the viewport frame to the root view
    2809          24 :   nsView* rootView = mPresShell->GetViewManager()->GetRootView();
    2810          24 :   viewportFrame->SetView(rootView);
    2811             : 
    2812          24 :   viewportFrame->SyncFrameViewProperties(rootView);
    2813          24 :   nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
    2814          24 :                                          rootView, nullptr, nsContainerFrame::SET_ASYNC);
    2815             : 
    2816             :   // Make it an absolute container for fixed-pos elements
    2817          24 :   viewportFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    2818          24 :   viewportFrame->MarkAsAbsoluteContainingBlock();
    2819             : 
    2820          48 :   return viewportFrame;
    2821             : }
    2822             : 
    2823             : void
    2824          24 : nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
    2825             : {
    2826          24 :   NS_PRECONDITION(aDocElement, "No element?");
    2827          24 :   NS_PRECONDITION(!aDocElement->GetParent(), "Not root content?");
    2828          24 :   NS_PRECONDITION(aDocElement->GetUncomposedDoc(), "Not in a document?");
    2829          24 :   NS_PRECONDITION(aDocElement->GetUncomposedDoc()->GetRootElement() ==
    2830             :                   aDocElement, "Not the root of the document?");
    2831             : 
    2832             :   /*
    2833             :     how the root frame hierarchy should look
    2834             : 
    2835             :   Galley presentation, non-XUL, with scrolling:
    2836             : 
    2837             :       ViewportFrame [fixed-cb]
    2838             :         nsHTMLScrollFrame
    2839             :           nsCanvasFrame [abs-cb]
    2840             :             root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2841             :                                 nsTableWrapperFrame, nsPlaceholderFrame)
    2842             : 
    2843             :   Galley presentation, XUL
    2844             : 
    2845             :       ViewportFrame [fixed-cb]
    2846             :         nsRootBoxFrame
    2847             :           root element frame (nsDocElementBoxFrame)
    2848             : 
    2849             :   Print presentation, non-XUL
    2850             : 
    2851             :       ViewportFrame
    2852             :         nsSimplePageSequenceFrame
    2853             :           nsPageFrame
    2854             :             nsPageContentFrame [fixed-cb]
    2855             :               nsCanvasFrame [abs-cb]
    2856             :                 root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2857             :                                     nsTableWrapperFrame, nsPlaceholderFrame)
    2858             : 
    2859             :   Print-preview presentation, non-XUL
    2860             : 
    2861             :       ViewportFrame
    2862             :         nsHTMLScrollFrame
    2863             :           nsSimplePageSequenceFrame
    2864             :             nsPageFrame
    2865             :               nsPageContentFrame [fixed-cb]
    2866             :                 nsCanvasFrame [abs-cb]
    2867             :                   root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2868             :                                       nsTableWrapperFrame, nsPlaceholderFrame)
    2869             : 
    2870             :   Print/print preview of XUL is not supported.
    2871             :   [fixed-cb]: the default containing block for fixed-pos content
    2872             :   [abs-cb]: the default containing block for abs-pos content
    2873             : 
    2874             :   Meaning of nsCSSFrameConstructor fields:
    2875             :     mRootElementFrame is "root element frame".  This is the primary frame for
    2876             :       the root element.
    2877             :     mDocElementContainingBlock is the parent of mRootElementFrame
    2878             :       (i.e. nsCanvasFrame or nsRootBoxFrame)
    2879             : 
    2880             :     mPageSequenceFrame is the nsSimplePageSequenceFrame, or null if there isn't one
    2881             :   */
    2882             : 
    2883             :   // --------- CREATE ROOT FRAME -------
    2884             : 
    2885             : 
    2886             :   // Create the root frame. The document element's frame is a child of the
    2887             :   // root frame.
    2888             :   //
    2889             :   // The root frame serves two purposes:
    2890             :   // - reserves space for any margins needed for the document element's frame
    2891             :   // - renders the document element's background. This ensures the background covers
    2892             :   //   the entire canvas as specified by the CSS2 spec
    2893             : 
    2894          24 :   nsPresContext* presContext = mPresShell->GetPresContext();
    2895          24 :   bool isPaginated = presContext->IsRootPaginatedDocument();
    2896          24 :   nsContainerFrame* viewportFrame = static_cast<nsContainerFrame*>(GetRootFrame());
    2897          24 :   nsStyleContext* viewportPseudoStyle = viewportFrame->StyleContext();
    2898             : 
    2899          24 :   nsContainerFrame* rootFrame = nullptr;
    2900             :   nsIAtom* rootPseudo;
    2901             : 
    2902          24 :   if (!isPaginated) {
    2903             : #ifdef MOZ_XUL
    2904          24 :     if (aDocElement->IsXULElement())
    2905             :     {
    2906             :       // pass a temporary stylecontext, the correct one will be set later
    2907           1 :       rootFrame = NS_NewRootBoxFrame(mPresShell, viewportPseudoStyle);
    2908             :     } else
    2909             : #endif
    2910             :     {
    2911             :       // pass a temporary stylecontext, the correct one will be set later
    2912          23 :       rootFrame = NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
    2913          23 :       mHasRootAbsPosContainingBlock = true;
    2914             :     }
    2915             : 
    2916          24 :     rootPseudo = nsCSSAnonBoxes::canvas;
    2917          24 :     mDocElementContainingBlock = rootFrame;
    2918             :   } else {
    2919             :     // Create a page sequence frame
    2920           0 :     rootFrame = NS_NewSimplePageSequenceFrame(mPresShell, viewportPseudoStyle);
    2921           0 :     mPageSequenceFrame = rootFrame;
    2922           0 :     rootPseudo = nsCSSAnonBoxes::pageSequence;
    2923           0 :     rootFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    2924             :   }
    2925             : 
    2926             : 
    2927             :   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
    2928             : 
    2929             :   // If the device supports scrolling (e.g., in galley mode on the screen and
    2930             :   // for print-preview, but not when printing), then create a scroll frame that
    2931             :   // will act as the scrolling mechanism for the viewport.
    2932             :   // XXX Do we even need a viewport when printing to a printer?
    2933             : 
    2934          24 :   bool isHTML = aDocElement->IsHTMLElement();
    2935          24 :   bool isXUL = false;
    2936             : 
    2937          24 :   if (!isHTML) {
    2938          22 :     isXUL = aDocElement->IsXULElement();
    2939             :   }
    2940             : 
    2941             :   // Never create scrollbars for XUL documents
    2942          24 :   bool isScrollable = isPaginated ? presContext->HasPaginatedScrolling() : !isXUL;
    2943             : 
    2944             :   // We no longer need to do overflow propagation here. It's taken care of
    2945             :   // when we construct frames for the element whose overflow might be
    2946             :   // propagated
    2947          24 :   NS_ASSERTION(!isScrollable || !isXUL,
    2948             :                "XUL documents should never be scrollable - see above");
    2949             : 
    2950          24 :   nsContainerFrame* newFrame = rootFrame;
    2951          48 :   RefPtr<nsStyleContext> rootPseudoStyle;
    2952             :   // we must create a state because if the scrollbars are GFX it needs the
    2953             :   // state to build the scrollbar frames.
    2954          48 :   TreeMatchContextHolder matchContext(mDocument);
    2955          48 :   nsFrameConstructorState state(mPresShell, matchContext, nullptr, nullptr, nullptr);
    2956             : 
    2957             :   // Start off with the viewport as parent; we'll adjust it as needed.
    2958          24 :   nsContainerFrame* parentFrame = viewportFrame;
    2959             : 
    2960          24 :   StyleSetHandle styleSet = mPresShell->StyleSet();
    2961             :   // If paginated, make sure we don't put scrollbars in
    2962          24 :   if (!isScrollable) {
    2963             :     rootPseudoStyle =
    2964           2 :       styleSet->ResolveInheritingAnonymousBoxStyle(rootPseudo,
    2965           1 :                                                    viewportPseudoStyle);
    2966             :   } else {
    2967          23 :       if (rootPseudo == nsCSSAnonBoxes::canvas) {
    2968          23 :         rootPseudo = nsCSSAnonBoxes::scrolledCanvas;
    2969             :       } else {
    2970           0 :         NS_ASSERTION(rootPseudo == nsCSSAnonBoxes::pageSequence,
    2971             :                      "Unknown root pseudo");
    2972           0 :         rootPseudo = nsCSSAnonBoxes::scrolledPageSequence;
    2973             :       }
    2974             : 
    2975             :       // Build the frame. We give it the content we are wrapping which is the
    2976             :       // document element, the root frame, the parent view port frame, and we
    2977             :       // should get back the new frame and the scrollable view if one was
    2978             :       // created.
    2979             : 
    2980             :       // resolve a context for the scrollframe
    2981          46 :       RefPtr<nsStyleContext>  styleContext;
    2982             :       styleContext =
    2983          46 :         styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::viewportScroll,
    2984          23 :                                                      viewportPseudoStyle);
    2985             : 
    2986             :       // Note that the viewport scrollframe is always built with
    2987             :       // overflow:auto style. This forces the scroll frame to create
    2988             :       // anonymous content for both scrollbars. This is necessary even
    2989             :       // if the HTML or BODY elements are overriding the viewport
    2990             :       // scroll style to 'hidden' --- dynamic style changes might put
    2991             :       // scrollbars back on the viewport and we don't want to have to
    2992             :       // reframe the viewport to create the scrollbar content.
    2993          23 :       newFrame = nullptr;
    2994          46 :       rootPseudoStyle = BeginBuildingScrollFrame( state,
    2995             :                                                   aDocElement,
    2996             :                                                   styleContext,
    2997             :                                                   viewportFrame,
    2998             :                                                   rootPseudo,
    2999             :                                                   true,
    3000          23 :                                                   newFrame);
    3001          23 :       parentFrame = newFrame;
    3002             :   }
    3003             : 
    3004          24 :   rootFrame->SetStyleContextWithoutNotification(rootPseudoStyle);
    3005          24 :   rootFrame->Init(aDocElement, parentFrame, nullptr);
    3006             : 
    3007          24 :   if (isScrollable) {
    3008          23 :     FinishBuildingScrollFrame(parentFrame, rootFrame);
    3009             :   }
    3010             : 
    3011          24 :   if (isPaginated) {
    3012             :     // Create the first page
    3013             :     // Set the initial child lists
    3014             :     nsContainerFrame* canvasFrame;
    3015             :     nsContainerFrame* pageFrame =
    3016           0 :       ConstructPageFrame(mPresShell, rootFrame, nullptr, canvasFrame);
    3017           0 :     pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    3018           0 :     SetInitialSingleChild(rootFrame, pageFrame);
    3019             : 
    3020             :     // The eventual parent of the document element frame.
    3021             :     // XXX should this be set for every new page (in ConstructPageFrame)?
    3022           0 :     mDocElementContainingBlock = canvasFrame;
    3023           0 :     mHasRootAbsPosContainingBlock = true;
    3024             :   }
    3025             : 
    3026          24 :   if (viewportFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
    3027          24 :     SetInitialSingleChild(viewportFrame, newFrame);
    3028             :   } else {
    3029           0 :     nsFrameList newFrameList(newFrame, newFrame);
    3030           0 :     viewportFrame->AppendFrames(kPrincipalList, newFrameList);
    3031             :   }
    3032          24 : }
    3033             : 
    3034             : void
    3035          23 : nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
    3036             :                                                           nsIFrame* aFrame,
    3037             :                                                           nsIContent* aDocElement)
    3038             : {
    3039          23 :   NS_ASSERTION(aFrame->IsCanvasFrame(), "aFrame should be canvas frame!");
    3040             : 
    3041          46 :   AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
    3042          23 :   GetAnonymousContent(aDocElement, aFrame, anonymousItems);
    3043          23 :   if (anonymousItems.IsEmpty()) {
    3044           0 :     return;
    3045             :   }
    3046             : 
    3047          46 :   FrameConstructionItemList itemsToConstruct;
    3048          23 :   nsContainerFrame* frameAsContainer = do_QueryFrame(aFrame);
    3049          23 :   AddFCItemsForAnonymousContent(aState, frameAsContainer, anonymousItems, itemsToConstruct);
    3050             : 
    3051          23 :   nsFrameItems frameItems;
    3052          23 :   ConstructFramesFromItemList(aState, itemsToConstruct, frameAsContainer, frameItems);
    3053          23 :   frameAsContainer->AppendFrames(kPrincipalList, frameItems);
    3054             : }
    3055             : 
    3056             : nsContainerFrame*
    3057           0 : nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell*  aPresShell,
    3058             :                                           nsContainerFrame* aParentFrame,
    3059             :                                           nsIFrame*      aPrevPageFrame,
    3060             :                                           nsContainerFrame*& aCanvasFrame)
    3061             : {
    3062           0 :   nsStyleContext* parentStyleContext = aParentFrame->StyleContext();
    3063           0 :   StyleSetHandle styleSet = aPresShell->StyleSet();
    3064             : 
    3065           0 :   RefPtr<nsStyleContext> pagePseudoStyle;
    3066             :   pagePseudoStyle =
    3067           0 :     styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::page,
    3068           0 :                                                  parentStyleContext);
    3069             : 
    3070           0 :   nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
    3071             : 
    3072             :   // Initialize the page frame and force it to have a view. This makes printing of
    3073             :   // the pages easier and faster.
    3074           0 :   pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
    3075             : 
    3076           0 :   RefPtr<nsStyleContext> pageContentPseudoStyle;
    3077             :   pageContentPseudoStyle =
    3078           0 :     styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::pageContent,
    3079           0 :                                                  pagePseudoStyle);
    3080             : 
    3081             :   nsContainerFrame* pageContentFrame =
    3082           0 :     NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
    3083             : 
    3084             :   // Initialize the page content frame and force it to have a view. Also make it the
    3085             :   // containing block for fixed elements which are repeated on every page.
    3086           0 :   nsIFrame* prevPageContentFrame = nullptr;
    3087           0 :   if (aPrevPageFrame) {
    3088           0 :     prevPageContentFrame = aPrevPageFrame->PrincipalChildList().FirstChild();
    3089           0 :     NS_ASSERTION(prevPageContentFrame, "missing page content frame");
    3090             :   }
    3091           0 :   pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
    3092           0 :   if (!prevPageContentFrame) {
    3093           0 :     pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    3094             :   }
    3095           0 :   SetInitialSingleChild(pageFrame, pageContentFrame);
    3096             :   // Make it an absolute container for fixed-pos elements
    3097           0 :   pageContentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    3098           0 :   pageContentFrame->MarkAsAbsoluteContainingBlock();
    3099             : 
    3100           0 :   RefPtr<nsStyleContext> canvasPseudoStyle;
    3101             :   canvasPseudoStyle =
    3102           0 :     styleSet->ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::canvas,
    3103           0 :                                                  pageContentPseudoStyle);
    3104             : 
    3105           0 :   aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
    3106             : 
    3107           0 :   nsIFrame* prevCanvasFrame = nullptr;
    3108           0 :   if (prevPageContentFrame) {
    3109           0 :     prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
    3110           0 :     NS_ASSERTION(prevCanvasFrame, "missing canvas frame");
    3111             :   }
    3112           0 :   aCanvasFrame->Init(nullptr, pageContentFrame, prevCanvasFrame);
    3113           0 :   SetInitialSingleChild(pageContentFrame, aCanvasFrame);
    3114           0 :   return pageFrame;
    3115             : }
    3116             : 
    3117             : /* static */
    3118             : nsIFrame*
    3119          35 : nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell*     aPresShell,
    3120             :                                                  nsIContent*       aContent,
    3121             :                                                  nsIFrame*         aFrame,
    3122             :                                                  nsContainerFrame* aParentFrame,
    3123             :                                                  nsIFrame*         aPrevInFlow,
    3124             :                                                  nsFrameState      aTypeBit)
    3125             : {
    3126          70 :   RefPtr<nsStyleContext> placeholderStyle = aPresShell->StyleSet()->
    3127          70 :     ResolveStyleForPlaceholder();
    3128             : 
    3129             :   // The placeholder frame gets a pseudo style context
    3130             :   nsPlaceholderFrame* placeholderFrame =
    3131          35 :     (nsPlaceholderFrame*)NS_NewPlaceholderFrame(aPresShell, placeholderStyle,
    3132          35 :                                                 aTypeBit);
    3133             : 
    3134          35 :   placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow);
    3135             : 
    3136             :   // Associate the placeholder/out-of-flow with each other.
    3137          35 :   placeholderFrame->SetOutOfFlowFrame(aFrame);
    3138          35 :   aFrame->SetProperty(nsIFrame::PlaceholderFrameProperty(), placeholderFrame);
    3139             : 
    3140          35 :   aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
    3141             : 
    3142          70 :   return placeholderFrame;
    3143             : }
    3144             : 
    3145             : // Clears any lazy bits set in the range [aStartContent, aEndContent).  If
    3146             : // aEndContent is null, that means to clear bits in all siblings starting with
    3147             : // aStartContent.  aStartContent must not be null unless aEndContent is also
    3148             : // null.  We do this so that when new children are inserted under elements whose
    3149             : // frame is a leaf the new children don't cause us to try to construct frames
    3150             : // for the existing children again.
    3151             : static inline void
    3152          74 : ClearLazyBits(nsIContent* aStartContent, nsIContent* aEndContent)
    3153             : {
    3154          74 :   NS_PRECONDITION(aStartContent || !aEndContent,
    3155             :                   "Must have start child if we have an end child");
    3156         405 :   for (nsIContent* cur = aStartContent; cur != aEndContent;
    3157         331 :        cur = cur->GetNextSibling()) {
    3158         331 :     cur->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
    3159             :   }
    3160          74 : }
    3161             : 
    3162             : nsIFrame*
    3163           0 : nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
    3164             :                                             FrameConstructionItem&   aItem,
    3165             :                                             nsContainerFrame*        aParentFrame,
    3166             :                                             const nsStyleDisplay*    aStyleDisplay,
    3167             :                                             nsFrameItems&            aFrameItems)
    3168             : {
    3169           0 :   nsIContent* const content = aItem.mContent;
    3170           0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    3171             : 
    3172             :   // Construct a frame-based listbox or combobox
    3173           0 :   dom::HTMLSelectElement* sel = dom::HTMLSelectElement::FromContent(content);
    3174           0 :   MOZ_ASSERT(sel);
    3175           0 :   if (sel->IsCombobox()) {
    3176             :     // Construct a frame-based combo box.
    3177             :     // The frame-based combo box is built out of three parts. A display area, a button and
    3178             :     // a dropdown list. The display area and button are created through anonymous content.
    3179             :     // The drop-down list's frame is created explicitly. The combobox frame shares its content
    3180             :     // with the drop-down list.
    3181           0 :     nsFrameState flags = NS_BLOCK_FLOAT_MGR;
    3182             :     nsComboboxControlFrame* comboboxFrame =
    3183           0 :       NS_NewComboboxControlFrame(mPresShell, styleContext, flags);
    3184             : 
    3185             :     // Save the history state so we don't restore during construction
    3186             :     // since the complete tree is required before we restore.
    3187           0 :     nsILayoutHistoryState *historyState = aState.mFrameState;
    3188           0 :     aState.mFrameState = nullptr;
    3189             :     // Initialize the combobox frame
    3190           0 :     InitAndRestoreFrame(aState, content,
    3191             :                         aState.GetGeometricParent(aStyleDisplay, aParentFrame),
    3192           0 :                         comboboxFrame);
    3193             : 
    3194           0 :     comboboxFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    3195             : 
    3196             :     aState.AddChild(comboboxFrame, aFrameItems, content, styleContext,
    3197           0 :                     aParentFrame);
    3198             : 
    3199             :     // Resolve pseudo element style for the dropdown list
    3200           0 :     RefPtr<nsStyleContext> listStyle;
    3201           0 :     listStyle = mPresShell->StyleSet()->
    3202           0 :       ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::dropDownList,
    3203           0 :                                          styleContext);
    3204             : 
    3205             :     // Create a listbox
    3206           0 :     nsContainerFrame* listFrame = NS_NewListControlFrame(mPresShell, listStyle);
    3207             : 
    3208             :     // Notify the listbox that it is being used as a dropdown list.
    3209           0 :     nsIListControlFrame * listControlFrame = do_QueryFrame(listFrame);
    3210           0 :     if (listControlFrame) {
    3211           0 :       listControlFrame->SetComboboxFrame(comboboxFrame);
    3212             :     }
    3213             :     // Notify combobox that it should use the listbox as it's popup
    3214           0 :     comboboxFrame->SetDropDown(listFrame);
    3215             : 
    3216           0 :     NS_ASSERTION(!listFrame->IsAbsPosContainingBlock(),
    3217             :                  "Ended up with positioned dropdown list somehow.");
    3218           0 :     NS_ASSERTION(!listFrame->IsFloating(),
    3219             :                  "Ended up with floating dropdown list somehow.");
    3220             : 
    3221             :     // Initialize the scroll frame positioned. Note that it is NOT
    3222             :     // initialized as absolutely positioned.
    3223             :     nsContainerFrame* scrolledFrame =
    3224           0 :       NS_NewSelectsAreaFrame(mPresShell, styleContext, flags);
    3225             : 
    3226           0 :     InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
    3227             :                           comboboxFrame, listStyle, true,
    3228           0 :                           aItem.mPendingBinding, aFrameItems);
    3229             : 
    3230           0 :     NS_ASSERTION(listFrame->GetView(), "ListFrame's view is nullptr");
    3231             : 
    3232             :     // Create display and button frames from the combobox's anonymous content.
    3233             :     // The anonymous content is appended to existing anonymous content for this
    3234             :     // element (the scrollbars).
    3235           0 :     nsFrameItems childItems;
    3236             : 
    3237             :     // nsComboboxControlFrame needs special frame creation behavior for its first
    3238             :     // piece of anonymous content, which means that we can't take the normal
    3239             :     // ProcessChildren path.
    3240           0 :     AutoTArray<nsIAnonymousContentCreator::ContentInfo, 2> newAnonymousItems;
    3241           0 :     DebugOnly<nsresult> rv = GetAnonymousContent(content, comboboxFrame, newAnonymousItems);
    3242           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3243           0 :     MOZ_ASSERT(newAnonymousItems.Length() == 2);
    3244             : 
    3245             :     // Manually create a frame for the special NAC.
    3246           0 :     MOZ_ASSERT(newAnonymousItems[0].mContent == comboboxFrame->GetDisplayNode());
    3247           0 :     newAnonymousItems.RemoveElementAt(0);
    3248           0 :     nsIFrame* customFrame = comboboxFrame->CreateFrameForDisplayNode();
    3249           0 :     MOZ_ASSERT(customFrame);
    3250           0 :     customFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
    3251           0 :     childItems.AddChild(customFrame);
    3252             : 
    3253             :     // The other piece of NAC can take the normal path.
    3254           0 :     FrameConstructionItemList fcItems;
    3255             :     AddFCItemsForAnonymousContent(aState, comboboxFrame, newAnonymousItems,
    3256           0 :                                   fcItems);
    3257           0 :     ConstructFramesFromItemList(aState, fcItems, comboboxFrame, childItems);
    3258             : 
    3259           0 :     comboboxFrame->SetInitialChildList(kPrincipalList, childItems);
    3260             : 
    3261             :     // Initialize the additional popup child list which contains the
    3262             :     // dropdown list frame.
    3263           0 :     nsFrameItems popupItems;
    3264           0 :     popupItems.AddChild(listFrame);
    3265             :     comboboxFrame->SetInitialChildList(nsIFrame::kSelectPopupList,
    3266           0 :                                        popupItems);
    3267             : 
    3268           0 :     aState.mFrameState = historyState;
    3269           0 :     if (aState.mFrameState) {
    3270             :       // Restore frame state for the entire subtree of |comboboxFrame|.
    3271           0 :       RestoreFrameState(comboboxFrame, aState.mFrameState);
    3272             :     }
    3273           0 :     return comboboxFrame;
    3274             :   }
    3275             : 
    3276             :   // Listbox, not combobox
    3277           0 :   nsContainerFrame* listFrame = NS_NewListControlFrame(mPresShell, styleContext);
    3278             : 
    3279           0 :   nsContainerFrame* scrolledFrame = NS_NewSelectsAreaFrame(
    3280           0 :       mPresShell, styleContext, NS_BLOCK_FLOAT_MGR);
    3281             : 
    3282             :   // ******* this code stolen from Initialze ScrollFrame ********
    3283             :   // please adjust this code to use BuildScrollFrame.
    3284             : 
    3285           0 :   InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
    3286             :                         aParentFrame, styleContext, false,
    3287           0 :                         aItem.mPendingBinding, aFrameItems);
    3288             : 
    3289           0 :   return listFrame;
    3290             : }
    3291             : 
    3292             : /**
    3293             :  * Used to be InitializeScrollFrame but now it's only used for the select tag
    3294             :  * But the select tag should really be fixed to use GFX scrollbars that can
    3295             :  * be create with BuildScrollFrame.
    3296             :  */
    3297             : void
    3298           0 : nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
    3299             :                                              nsContainerFrame*        scrollFrame,
    3300             :                                              nsContainerFrame*        scrolledFrame,
    3301             :                                              nsIContent*              aContent,
    3302             :                                              nsContainerFrame*        aParentFrame,
    3303             :                                              nsStyleContext*          aStyleContext,
    3304             :                                              bool                     aBuildCombobox,
    3305             :                                              PendingBinding*          aPendingBinding,
    3306             :                                              nsFrameItems&            aFrameItems)
    3307             : {
    3308             :   // Initialize it
    3309             :   nsContainerFrame* geometricParent =
    3310           0 :     aState.GetGeometricParent(aStyleContext->StyleDisplay(), aParentFrame);
    3311             : 
    3312             :   // We don't call InitAndRestoreFrame for scrollFrame because we can only
    3313             :   // restore the frame state after its parts have been created (in particular,
    3314             :   // the scrollable view). So we have to split Init and Restore.
    3315             : 
    3316           0 :   scrollFrame->Init(aContent, geometricParent, nullptr);
    3317             : 
    3318           0 :   if (!aBuildCombobox) {
    3319           0 :     aState.AddChild(scrollFrame, aFrameItems, aContent,
    3320           0 :                     aStyleContext, aParentFrame);
    3321             :   }
    3322             : 
    3323             :   BuildScrollFrame(aState, aContent, aStyleContext, scrolledFrame,
    3324           0 :                    geometricParent, scrollFrame);
    3325             : 
    3326           0 :   if (aState.mFrameState) {
    3327             :     // Restore frame state for the scroll frame
    3328           0 :     RestoreFrameStateFor(scrollFrame, aState.mFrameState);
    3329             :   }
    3330             : 
    3331             :   // Process children
    3332           0 :   nsFrameItems                childItems;
    3333             : 
    3334             :   ProcessChildren(aState, aContent, aStyleContext, scrolledFrame, false,
    3335           0 :                   childItems, false, aPendingBinding);
    3336             : 
    3337             :   // Set the scrolled frame's initial child lists
    3338           0 :   scrolledFrame->SetInitialChildList(kPrincipalList, childItems);
    3339           0 : }
    3340             : 
    3341             : nsIFrame*
    3342           0 : nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
    3343             :                                               FrameConstructionItem&   aItem,
    3344             :                                               nsContainerFrame*        aParentFrame,
    3345             :                                               const nsStyleDisplay*    aStyleDisplay,
    3346             :                                               nsFrameItems&            aFrameItems)
    3347             : {
    3348           0 :   nsIContent* const content = aItem.mContent;
    3349           0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    3350             : 
    3351           0 :   nsContainerFrame* fieldsetFrame = NS_NewFieldSetFrame(mPresShell, styleContext);
    3352             : 
    3353             :   // Initialize it
    3354           0 :   InitAndRestoreFrame(aState, content,
    3355             :                       aState.GetGeometricParent(aStyleDisplay, aParentFrame),
    3356           0 :                       fieldsetFrame);
    3357             : 
    3358           0 :   fieldsetFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    3359             : 
    3360             :   // Resolve style and initialize the frame
    3361           0 :   RefPtr<nsStyleContext> fieldsetContentStyle;
    3362           0 :   fieldsetContentStyle = mPresShell->StyleSet()->
    3363           0 :     ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::fieldsetContent,
    3364           0 :                                        styleContext);
    3365             : 
    3366           0 :   const nsStyleDisplay* fieldsetContentDisplay = fieldsetContentStyle->StyleDisplay();
    3367           0 :   bool isScrollable = fieldsetContentDisplay->IsScrollableOverflow();
    3368           0 :   nsContainerFrame* scrollFrame = nullptr;
    3369           0 :   if (isScrollable) {
    3370             :     fieldsetContentStyle =
    3371           0 :       BeginBuildingScrollFrame(aState, content, fieldsetContentStyle,
    3372             :                                fieldsetFrame, nsCSSAnonBoxes::scrolledContent,
    3373           0 :                                false, scrollFrame);
    3374             :   }
    3375             : 
    3376           0 :   nsContainerFrame* absPosContainer = nullptr;
    3377           0 :   if (fieldsetFrame->IsAbsPosContainingBlock()) {
    3378           0 :     absPosContainer = fieldsetFrame;
    3379             :   }
    3380             : 
    3381             :   // Create the inner ::-moz-fieldset-content frame.
    3382             :   nsContainerFrame* contentFrameTop;
    3383             :   nsContainerFrame* contentFrame;
    3384           0 :   auto parent = scrollFrame ? scrollFrame : fieldsetFrame;
    3385           0 :   switch (fieldsetContentDisplay->mDisplay) {
    3386             :     case StyleDisplay::Flex:
    3387           0 :       contentFrame = NS_NewFlexContainerFrame(mPresShell, fieldsetContentStyle);
    3388           0 :       InitAndRestoreFrame(aState, content, parent, contentFrame);
    3389           0 :       contentFrameTop = contentFrame;
    3390           0 :       break;
    3391             :     case StyleDisplay::Grid:
    3392           0 :       contentFrame = NS_NewGridContainerFrame(mPresShell, fieldsetContentStyle);
    3393           0 :       InitAndRestoreFrame(aState, content, parent, contentFrame);
    3394           0 :       contentFrameTop = contentFrame;
    3395           0 :       break;
    3396             :     default: {
    3397           0 :       MOZ_ASSERT(fieldsetContentDisplay->mDisplay == StyleDisplay::Block,
    3398             :                  "bug in nsRuleNode::ComputeDisplayData?");
    3399             : 
    3400           0 :       nsContainerFrame* columnSetFrame = nullptr;
    3401           0 :       RefPtr<nsStyleContext> innerSC = fieldsetContentStyle;
    3402           0 :       const nsStyleColumn* columns = fieldsetContentStyle->StyleColumn();
    3403           0 :       if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
    3404           0 :           columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
    3405             :         columnSetFrame =
    3406           0 :           NS_NewColumnSetFrame(mPresShell, fieldsetContentStyle,
    3407           0 :                                nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
    3408           0 :         InitAndRestoreFrame(aState, content, parent, columnSetFrame);
    3409           0 :         innerSC = mPresShell->StyleSet()->
    3410           0 :           ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::columnContent,
    3411           0 :                                              fieldsetContentStyle);
    3412           0 :         if (absPosContainer) {
    3413           0 :           absPosContainer = columnSetFrame;
    3414             :         }
    3415             :       }
    3416           0 :       contentFrame = NS_NewBlockFormattingContext(mPresShell, innerSC);
    3417           0 :       if (columnSetFrame) {
    3418           0 :         InitAndRestoreFrame(aState, content, columnSetFrame, contentFrame);
    3419           0 :         SetInitialSingleChild(columnSetFrame, contentFrame);
    3420           0 :         contentFrameTop = columnSetFrame;
    3421             :       } else {
    3422           0 :         InitAndRestoreFrame(aState, content, parent, contentFrame);
    3423           0 :         contentFrameTop = contentFrame;
    3424             :       }
    3425           0 :       break;
    3426             :     }
    3427             :   }
    3428             : 
    3429           0 :   aState.AddChild(fieldsetFrame, aFrameItems, content, styleContext, aParentFrame);
    3430             : 
    3431             :   // Process children
    3432           0 :   nsFrameConstructorSaveState absoluteSaveState;
    3433           0 :   nsFrameItems                childItems;
    3434             : 
    3435           0 :   contentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    3436           0 :   if (absPosContainer) {
    3437           0 :     aState.PushAbsoluteContainingBlock(contentFrame, absPosContainer, absoluteSaveState);
    3438             :   }
    3439             : 
    3440           0 :   ProcessChildren(aState, content, styleContext, contentFrame, true,
    3441           0 :                   childItems, true, aItem.mPendingBinding);
    3442             : 
    3443           0 :   nsFrameItems fieldsetKids;
    3444           0 :   fieldsetKids.AddChild(scrollFrame ? scrollFrame : contentFrameTop);
    3445             : 
    3446           0 :   for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
    3447           0 :     nsIFrame* child = e.get();
    3448           0 :     nsContainerFrame* cif = child->GetContentInsertionFrame();
    3449           0 :     if (cif && cif->IsLegendFrame()) {
    3450             :       // We want the legend to be the first frame in the fieldset child list.
    3451             :       // That way the EventStateManager will do the right thing when tabbing
    3452             :       // from a selection point within the legend (bug 236071), which is
    3453             :       // used for implementing legend access keys (bug 81481).
    3454             :       // GetAdjustedParentFrame() below depends on this frame order.
    3455           0 :       childItems.RemoveFrame(child);
    3456             :       // Make sure to reparent the legend so it has the fieldset as the parent.
    3457           0 :       fieldsetKids.InsertFrame(fieldsetFrame, nullptr, child);
    3458           0 :       if (scrollFrame) {
    3459             :         StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary(
    3460           0 :             child, contentFrame);
    3461             :       }
    3462           0 :       break;
    3463             :     }
    3464             :   }
    3465             : 
    3466           0 :   if (isScrollable) {
    3467           0 :     FinishBuildingScrollFrame(scrollFrame, contentFrameTop);
    3468             :   }
    3469             : 
    3470             :   // Set the inner frame's initial child lists
    3471           0 :   contentFrame->SetInitialChildList(kPrincipalList, childItems);
    3472             : 
    3473             :   // Set the outer frame's initial child list
    3474           0 :   fieldsetFrame->SetInitialChildList(kPrincipalList, fieldsetKids);
    3475             : 
    3476           0 :   fieldsetFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
    3477             : 
    3478             :   // Our new frame returned is the outer frame, which is the fieldset frame.
    3479           0 :   return fieldsetFrame;
    3480             : }
    3481             : 
    3482             : nsIFrame*
    3483           0 : nsCSSFrameConstructor::ConstructDetailsFrame(nsFrameConstructorState& aState,
    3484             :                                              FrameConstructionItem& aItem,
    3485             :                                              nsContainerFrame* aParentFrame,
    3486             :                                              const nsStyleDisplay* aStyleDisplay,
    3487             :                                              nsFrameItems& aFrameItems)
    3488             : {
    3489           0 :   if (!aStyleDisplay->IsScrollableOverflow()) {
    3490             :     return ConstructNonScrollableBlockWithConstructor(aState, aItem, aParentFrame,
    3491             :                                                       aStyleDisplay, aFrameItems,
    3492           0 :                                                       NS_NewDetailsFrame);
    3493             :   }
    3494             : 
    3495             :   // Build a scroll frame to wrap details frame if necessary.
    3496             :   return ConstructScrollableBlockWithConstructor(aState, aItem, aParentFrame,
    3497             :                                                  aStyleDisplay, aFrameItems,
    3498           0 :                                                  NS_NewDetailsFrame);
    3499             : }
    3500             : 
    3501             : static nsIFrame*
    3502           0 : FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame)
    3503             : {
    3504           0 :   for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) {
    3505           0 :     NS_ASSERTION(f->IsGeneratedContentFrame(),
    3506             :                  "should not have exited generated content");
    3507           0 :     nsIAtom* pseudo = f->StyleContext()->GetPseudo();
    3508           0 :     if (pseudo == nsCSSPseudoElements::before ||
    3509           0 :         pseudo == nsCSSPseudoElements::after)
    3510           0 :       return f;
    3511             :   }
    3512           0 :   return nullptr;
    3513             : }
    3514             : 
    3515             : #define SIMPLE_FCDATA(_func) FCDATA_DECL(0, _func)
    3516             : #define FULL_CTOR_FCDATA(_flags, _func)                             \
    3517             :   { _flags | FCDATA_FUNC_IS_FULL_CTOR, { nullptr }, _func, nullptr }
    3518             : 
    3519             : /* static */
    3520             : const nsCSSFrameConstructor::FrameConstructionData*
    3521         181 : nsCSSFrameConstructor::FindTextData(nsIFrame* aParentFrame)
    3522             : {
    3523         181 :   if (aParentFrame && IsFrameForSVG(aParentFrame)) {
    3524             :     nsIFrame *ancestorFrame =
    3525         158 :       nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
    3526         158 :     if (ancestorFrame) {
    3527             :       static const FrameConstructionData sSVGTextData =
    3528             :         FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | FCDATA_IS_SVG_TEXT,
    3529             :                     NS_NewTextFrame);
    3530         158 :       if (nsSVGUtils::IsInSVGTextSubtree(ancestorFrame)) {
    3531           0 :         return &sSVGTextData;
    3532             :       }
    3533             :     }
    3534         158 :     return nullptr;
    3535             :   }
    3536             : 
    3537             :   static const FrameConstructionData sTextData =
    3538             :     FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT, NS_NewTextFrame);
    3539          23 :   return &sTextData;
    3540             : }
    3541             : 
    3542             : void
    3543          18 : nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
    3544             :                                           nsFrameConstructorState& aState,
    3545             :                                           nsIContent*              aContent,
    3546             :                                           nsContainerFrame*        aParentFrame,
    3547             :                                           nsStyleContext*          aStyleContext,
    3548             :                                           nsFrameItems&            aFrameItems)
    3549             : {
    3550          18 :   NS_PRECONDITION(aData, "Must have frame construction data");
    3551             : 
    3552          18 :   nsIFrame* newFrame = (*aData->mFunc.mCreationFunc)(mPresShell, aStyleContext);
    3553             : 
    3554          18 :   InitAndRestoreFrame(aState, aContent, aParentFrame, newFrame);
    3555             : 
    3556             :   // We never need to create a view for a text frame.
    3557             : 
    3558          18 :   if (newFrame->IsGeneratedContentFrame()) {
    3559          12 :     nsAutoPtr<nsGenConInitializer> initializer;
    3560             :     initializer =
    3561             :       static_cast<nsGenConInitializer*>(
    3562           6 :         aContent->UnsetProperty(nsGkAtoms::genConInitializerProperty));
    3563           6 :     if (initializer) {
    3564           0 :       if (initializer->mNode->InitTextFrame(initializer->mList,
    3565           0 :               FindAncestorWithGeneratedContentPseudo(newFrame), newFrame)) {
    3566           0 :         (this->*(initializer->mDirtyAll))();
    3567             :       }
    3568           0 :       initializer->mNode.forget();
    3569             :     }
    3570             :   }
    3571             : 
    3572             :   // Add the newly constructed frame to the flow
    3573          18 :   aFrameItems.AddChild(newFrame);
    3574             : 
    3575          18 :   if (!aState.mCreatingExtraFrames)
    3576          18 :     aContent->SetPrimaryFrame(newFrame);
    3577          18 : }
    3578             : 
    3579             : /* static */
    3580             : const nsCSSFrameConstructor::FrameConstructionData*
    3581           4 : nsCSSFrameConstructor::FindDataByInt(int32_t aInt,
    3582             :                                      Element* aElement,
    3583             :                                      nsStyleContext* aStyleContext,
    3584             :                                      const FrameConstructionDataByInt* aDataPtr,
    3585             :                                      uint32_t aDataLength)
    3586             : {
    3587          26 :   for (const FrameConstructionDataByInt *curData = aDataPtr,
    3588           4 :          *endData = aDataPtr + aDataLength;
    3589          26 :        curData != endData;
    3590             :        ++curData) {
    3591          26 :     if (curData->mInt == aInt) {
    3592           4 :       const FrameConstructionData* data = &curData->mData;
    3593           4 :       if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) {
    3594           0 :         return data->mFunc.mDataGetter(aElement, aStyleContext);
    3595             :       }
    3596             : 
    3597           4 :       return data;
    3598             :     }
    3599             :   }
    3600             : 
    3601           0 :   return nullptr;
    3602             : }
    3603             : 
    3604             : /* static */
    3605             : const nsCSSFrameConstructor::FrameConstructionData*
    3606         462 : nsCSSFrameConstructor::FindDataByTag(nsIAtom* aTag,
    3607             :                                      Element* aElement,
    3608             :                                      nsStyleContext* aStyleContext,
    3609             :                                      const FrameConstructionDataByTag* aDataPtr,
    3610             :                                      uint32_t aDataLength)
    3611             : {
    3612        8094 :   for (const FrameConstructionDataByTag *curData = aDataPtr,
    3613         462 :          *endData = aDataPtr + aDataLength;
    3614        8094 :        curData != endData;
    3615             :        ++curData) {
    3616        7916 :     if (*curData->mTag == aTag) {
    3617         284 :       const FrameConstructionData* data = &curData->mData;
    3618         284 :       if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) {
    3619          21 :         return data->mFunc.mDataGetter(aElement, aStyleContext);
    3620             :       }
    3621             : 
    3622         263 :       return data;
    3623             :     }
    3624             :   }
    3625             : 
    3626         178 :   return nullptr;
    3627             : }
    3628             : 
    3629             : #define SUPPRESS_FCDATA() FCDATA_DECL(FCDATA_SUPPRESS_FRAME, nullptr)
    3630             : #define SIMPLE_INT_CREATE(_int, _func) { _int, SIMPLE_FCDATA(_func) }
    3631             : #define SIMPLE_INT_CHAIN(_int, _func)                       \
    3632             :   { _int, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER, _func) }
    3633             : #define COMPLEX_INT_CREATE(_int, _func)         \
    3634             :   { _int, FULL_CTOR_FCDATA(0, _func) }
    3635             : 
    3636             : #define SIMPLE_TAG_CREATE(_tag, _func)          \
    3637             :   { &nsGkAtoms::_tag, SIMPLE_FCDATA(_func) }
    3638             : #define SIMPLE_TAG_CHAIN(_tag, _func)                                   \
    3639             :   { &nsGkAtoms::_tag, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER,  _func) }
    3640             : #define COMPLEX_TAG_CREATE(_tag, _func)             \
    3641             :   { &nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
    3642             : 
    3643             : static bool
    3644          47 : IsFrameForFieldSet(nsIFrame* aFrame)
    3645             : {
    3646          47 :   nsIAtom* pseudo = aFrame->StyleContext()->GetPseudo();
    3647          94 :   if (pseudo == nsCSSAnonBoxes::fieldsetContent ||
    3648          90 :       pseudo == nsCSSAnonBoxes::scrolledContent ||
    3649          43 :       pseudo == nsCSSAnonBoxes::columnContent) {
    3650           4 :     return IsFrameForFieldSet(aFrame->GetParent());
    3651             :   }
    3652          43 :   return aFrame->IsFieldSetFrame();
    3653             : }
    3654             : 
    3655             : /* static */
    3656             : const nsCSSFrameConstructor::FrameConstructionData*
    3657         469 : nsCSSFrameConstructor::FindHTMLData(Element* aElement,
    3658             :                                     nsIAtom* aTag,
    3659             :                                     int32_t aNameSpaceID,
    3660             :                                     nsIFrame* aParentFrame,
    3661             :                                     nsStyleContext* aStyleContext)
    3662             : {
    3663             :   // Ignore the tag if it's not HTML content and if it doesn't extend (via XBL)
    3664             :   // a valid HTML namespace.  This check must match the one in
    3665             :   // ShouldHaveFirstLineStyle.
    3666         469 :   if (aNameSpaceID != kNameSpaceID_XHTML) {
    3667         451 :     return nullptr;
    3668             :   }
    3669             : 
    3670          18 :   NS_ASSERTION(!aParentFrame ||
    3671             :                aParentFrame->StyleContext()->GetPseudo() !=
    3672             :                  nsCSSAnonBoxes::fieldsetContent ||
    3673             :                aParentFrame->GetParent()->IsFieldSetFrame(),
    3674             :                "Unexpected parent for fieldset content anon box");
    3675          18 :   if (aTag == nsGkAtoms::legend &&
    3676           0 :       (!aParentFrame || !IsFrameForFieldSet(aParentFrame) ||
    3677           0 :        aStyleContext->StyleDisplay()->IsFloatingStyle() ||
    3678           0 :        aStyleContext->StyleDisplay()->IsAbsolutelyPositionedStyle())) {
    3679             :     // <legend> is only special inside fieldset, we only check the frame tree
    3680             :     // parent because the content tree parent may not be a <fieldset> due to
    3681             :     // display:contents, Shadow DOM, or XBL. For floated or absolutely
    3682             :     // positioned legends we want to construct by display type and
    3683             :     // not do special legend stuff.
    3684           0 :     return nullptr;
    3685             :   }
    3686             : 
    3687             :   static const FrameConstructionDataByTag sHTMLData[] = {
    3688             :     SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData),
    3689             :     SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,
    3690             :                      nsCSSFrameConstructor::FindImgData),
    3691             :     { &nsGkAtoms::br,
    3692             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | FCDATA_IS_LINE_BREAK,
    3693             :                   NS_NewBRFrame) },
    3694             :     SIMPLE_TAG_CREATE(wbr, NS_NewWBRFrame),
    3695             :     SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData),
    3696             :     SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame),
    3697             :     COMPLEX_TAG_CREATE(select, &nsCSSFrameConstructor::ConstructSelectFrame),
    3698             :     SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData),
    3699             :     SIMPLE_TAG_CHAIN(applet, nsCSSFrameConstructor::FindObjectData),
    3700             :     SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
    3701             :     COMPLEX_TAG_CREATE(fieldset,
    3702             :                        &nsCSSFrameConstructor::ConstructFieldSetFrame),
    3703             :     { &nsGkAtoms::legend,
    3704             :       FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES | FCDATA_MAY_NEED_SCROLLFRAME,
    3705             :                   NS_NewLegendFrame) },
    3706             :     SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
    3707             :     SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
    3708             :     { &nsGkAtoms::button,
    3709             :       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_ALLOW_BLOCK_STYLES |
    3710             :                                  FCDATA_ALLOW_GRID_FLEX_COLUMNSET,
    3711             :                                  NS_NewHTMLButtonControlFrame,
    3712             :                                  nsCSSAnonBoxes::buttonContent) },
    3713             :     SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
    3714             :     SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
    3715             :     SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
    3716             :     SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame),
    3717             :     SIMPLE_TAG_CREATE(meter, NS_NewMeterFrame),
    3718             :     COMPLEX_TAG_CREATE(details, &nsCSSFrameConstructor::ConstructDetailsFrame)
    3719             :   };
    3720             : 
    3721          18 :   return FindDataByTag(aTag, aElement, aStyleContext, sHTMLData,
    3722          36 :                        ArrayLength(sHTMLData));
    3723             : }
    3724             : 
    3725             : /* static */
    3726             : const nsCSSFrameConstructor::FrameConstructionData*
    3727           0 : nsCSSFrameConstructor::FindImgData(Element* aElement,
    3728             :                                    nsStyleContext* aStyleContext)
    3729             : {
    3730           0 :   if (!nsImageFrame::ShouldCreateImageFrameFor(aElement, aStyleContext)) {
    3731           0 :     return nullptr;
    3732             :   }
    3733             : 
    3734             :   static const FrameConstructionData sImgData = SIMPLE_FCDATA(NS_NewImageFrame);
    3735           0 :   return &sImgData;
    3736             : }
    3737             : 
    3738             : /* static */
    3739             : const nsCSSFrameConstructor::FrameConstructionData*
    3740           0 : nsCSSFrameConstructor::FindImgControlData(Element* aElement,
    3741             :                                           nsStyleContext* aStyleContext)
    3742             : {
    3743           0 :   if (!nsImageFrame::ShouldCreateImageFrameFor(aElement, aStyleContext)) {
    3744           0 :     return nullptr;
    3745             :   }
    3746             : 
    3747             :   static const FrameConstructionData sImgControlData =
    3748             :     SIMPLE_FCDATA(NS_NewImageControlFrame);
    3749           0 :   return &sImgControlData;
    3750             : }
    3751             : 
    3752             : /* static */
    3753             : const nsCSSFrameConstructor::FrameConstructionData*
    3754           4 : nsCSSFrameConstructor::FindInputData(Element* aElement,
    3755             :                                      nsStyleContext* aStyleContext)
    3756             : {
    3757             :   static const FrameConstructionDataByInt sInputData[] = {
    3758             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_CHECKBOX, NS_NewGfxCheckboxControlFrame),
    3759             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_RADIO, NS_NewGfxRadioControlFrame),
    3760             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_FILE, NS_NewFileControlFrame),
    3761             :     SIMPLE_INT_CHAIN(NS_FORM_INPUT_IMAGE,
    3762             :                      nsCSSFrameConstructor::FindImgControlData),
    3763             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_EMAIL, NS_NewTextControlFrame),
    3764             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_SEARCH, NS_NewTextControlFrame),
    3765             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TEXT, NS_NewTextControlFrame),
    3766             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TEL, NS_NewTextControlFrame),
    3767             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_URL, NS_NewTextControlFrame),
    3768             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_RANGE, NS_NewRangeFrame),
    3769             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_PASSWORD, NS_NewTextControlFrame),
    3770             :     { NS_FORM_INPUT_COLOR,
    3771             :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewColorControlFrame,
    3772             :                                  nsCSSAnonBoxes::buttonContent) },
    3773             :     // TODO: this is temporary until a frame is written: bug 635240.
    3774             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_NUMBER, NS_NewNumberControlFrame),
    3775             : #if defined(MOZ_WIDGET_ANDROID)
    3776             :     // On Android, date/time input appears as a normal text box.
    3777             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewTextControlFrame),
    3778             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame),
    3779             : #else
    3780             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewDateTimeControlFrame),
    3781             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewDateTimeControlFrame),
    3782             : #endif
    3783             :     // TODO: this is temporary until a frame is written: bug 888320
    3784             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_MONTH, NS_NewTextControlFrame),
    3785             :     // TODO: this is temporary until a frame is written: bug 888320
    3786             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_WEEK, NS_NewTextControlFrame),
    3787             :     // TODO: this is temporary until a frame is written: bug 888320
    3788             :     SIMPLE_INT_CREATE(NS_FORM_INPUT_DATETIME_LOCAL, NS_NewTextControlFrame),
    3789             :     { NS_FORM_INPUT_SUBMIT,
    3790             :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3791             :                                  nsCSSAnonBoxes::buttonContent) },
    3792             :     { NS_FORM_INPUT_RESET,
    3793             :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3794             :                                  nsCSSAnonBoxes::buttonContent) },
    3795             :     { NS_FORM_INPUT_BUTTON,
    3796             :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3797             :                                  nsCSSAnonBoxes::buttonContent) }
    3798             :     // Keeping hidden inputs out of here on purpose for so they get frames by
    3799             :     // display (in practice, none).
    3800             :   };
    3801             : 
    3802           8 :   nsCOMPtr<nsIFormControl> control = do_QueryInterface(aElement);
    3803           4 :   NS_ASSERTION(control, "input doesn't implement nsIFormControl?");
    3804             : 
    3805           4 :   auto controlType = control->ControlType();
    3806             : 
    3807             :   // Note that Android widgets don't have theming support and thus
    3808             :   // appearance:none is the same as any other appearance value.
    3809             :   // So this chunk doesn't apply there:
    3810             : #if !defined(MOZ_WIDGET_ANDROID)
    3811             :   // radio and checkbox inputs with appearance:none should be constructed
    3812             :   // by display type.  (Note that we're not checking that appearance is
    3813             :   // not (respectively) NS_THEME_RADIO and NS_THEME_CHECKBOX.)
    3814           8 :   if ((controlType == NS_FORM_INPUT_CHECKBOX ||
    3815           4 :        controlType == NS_FORM_INPUT_RADIO) &&
    3816           0 :       aStyleContext->StyleDisplay()->mAppearance == NS_THEME_NONE) {
    3817           0 :     return nullptr;
    3818             :   }
    3819             : #endif
    3820             : 
    3821           4 :   return FindDataByInt(controlType, aElement, aStyleContext,
    3822           8 :                        sInputData, ArrayLength(sInputData));
    3823             : }
    3824             : 
    3825             : /* static */
    3826             : const nsCSSFrameConstructor::FrameConstructionData*
    3827           0 : nsCSSFrameConstructor::FindObjectData(Element* aElement,
    3828             :                                       nsStyleContext* aStyleContext)
    3829             : {
    3830             :   // GetDisplayedType isn't necessarily nsIObjectLoadingContent::TYPE_NULL for
    3831             :   // cases when the object is broken/suppressed/etc (e.g. a broken image), but
    3832             :   // we want to treat those cases as TYPE_NULL
    3833             :   uint32_t type;
    3834           0 :   if (aElement->State().HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
    3835           0 :                                               NS_EVENT_STATE_USERDISABLED |
    3836           0 :                                               NS_EVENT_STATE_SUPPRESSED)) {
    3837           0 :     type = nsIObjectLoadingContent::TYPE_NULL;
    3838             :   } else {
    3839           0 :     nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(aElement));
    3840           0 :     NS_ASSERTION(objContent,
    3841             :                  "applet, embed and object must implement "
    3842             :                  "nsIObjectLoadingContent!");
    3843             : 
    3844           0 :     objContent->GetDisplayedType(&type);
    3845             :   }
    3846             : 
    3847             :   static const FrameConstructionDataByInt sObjectData[] = {
    3848             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_LOADING,
    3849             :                       NS_NewEmptyFrame),
    3850             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_PLUGIN,
    3851             :                       NS_NewObjectFrame),
    3852             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_IMAGE,
    3853             :                       NS_NewImageFrame),
    3854             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_DOCUMENT,
    3855             :                       NS_NewSubDocumentFrame),
    3856             :     // Fake plugin handlers load as documents
    3857             :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_FAKE_PLUGIN,
    3858             :                       NS_NewSubDocumentFrame)
    3859             :     // Nothing for TYPE_NULL so we'll construct frames by display there
    3860             :   };
    3861             : 
    3862           0 :   return FindDataByInt((int32_t)type, aElement, aStyleContext,
    3863           0 :                        sObjectData, ArrayLength(sObjectData));
    3864             : }
    3865             : 
    3866             : /* static */
    3867             : const nsCSSFrameConstructor::FrameConstructionData*
    3868           0 : nsCSSFrameConstructor::FindCanvasData(Element* aElement,
    3869             :                                       nsStyleContext* aStyleContext)
    3870             : {
    3871             :   // We want to check whether script is enabled on the document that
    3872             :   // could be painting to the canvas.  That's the owner document of
    3873             :   // the canvas, except when the owner document is a static document,
    3874             :   // in which case it's the original document it was cloned from.
    3875           0 :   nsIDocument* doc = aElement->OwnerDoc();
    3876           0 :   if (doc->IsStaticDocument()) {
    3877           0 :     doc = doc->GetOriginalDocument();
    3878             :   }
    3879           0 :   if (!doc->IsScriptEnabled()) {
    3880           0 :     return nullptr;
    3881             :   }
    3882             : 
    3883             :   static const FrameConstructionData sCanvasData =
    3884             :     FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewHTMLCanvasFrame,
    3885             :                                nsCSSAnonBoxes::htmlCanvasContent);
    3886           0 :   return &sCanvasData;
    3887             : }
    3888             : 
    3889             : void
    3890         469 : nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
    3891             :                                                       nsFrameConstructorState& aState,
    3892             :                                                       nsContainerFrame* aParentFrame,
    3893             :                                                       nsFrameItems& aFrameItems)
    3894             : {
    3895         469 :   const FrameConstructionData* data = aItem.mFCData;
    3896         469 :   NS_ASSERTION(data, "Must have frame construction data");
    3897             : 
    3898         469 :   uint32_t bits = data->mBits;
    3899             : 
    3900         469 :   NS_ASSERTION(!(bits & FCDATA_FUNC_IS_DATA_GETTER),
    3901             :                "Should have dealt with this inside the data finder");
    3902             : 
    3903             :   // Some sets of bits are not compatible with each other
    3904             : #define CHECK_ONLY_ONE_BIT(_bit1, _bit2)               \
    3905             :   NS_ASSERTION(!(bits & _bit1) || !(bits & _bit2),     \
    3906             :                "Only one of these bits should be set")
    3907         469 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_FORCE_NULL_ABSPOS_CONTAINER);
    3908         469 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_WRAP_KIDS_IN_BLOCKS);
    3909         469 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_MAY_NEED_SCROLLFRAME);
    3910         469 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_IS_POPUP);
    3911         469 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_SKIP_ABSPOS_PUSH);
    3912         469 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
    3913             :                      FCDATA_DISALLOW_GENERATED_CONTENT);
    3914         469 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_ALLOW_BLOCK_STYLES);
    3915         469 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
    3916             :                      FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
    3917         469 :   CHECK_ONLY_ONE_BIT(FCDATA_WRAP_KIDS_IN_BLOCKS,
    3918             :                      FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
    3919             : #undef CHECK_ONLY_ONE_BIT
    3920         469 :   NS_ASSERTION(!(bits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) ||
    3921             :                ((bits & FCDATA_FUNC_IS_FULL_CTOR) &&
    3922             :                 data->mFullConstructor ==
    3923             :                   &nsCSSFrameConstructor::ConstructNonScrollableBlock),
    3924             :                "Unexpected FCDATA_FORCED_NON_SCROLLABLE_BLOCK flag");
    3925             : 
    3926             :   // Don't create a subdocument frame for iframes if we're creating extra frames
    3927         469 :   if (aState.mCreatingExtraFrames &&
    3928           0 :       aItem.mContent->IsHTMLElement(nsGkAtoms::iframe))
    3929             :   {
    3930           0 :     return;
    3931             :   }
    3932             : 
    3933         469 :   nsIContent* const content = aItem.mContent;
    3934         469 :   nsIContent* parent = content->GetParent();
    3935             : 
    3936             :   // Push display:contents ancestors.
    3937         938 :   Maybe<AutoDisplayContentsAncestorPusher> adcp;
    3938         469 :   if (aState.mTreeMatchContext) {
    3939         469 :     adcp.emplace(*aState.mTreeMatchContext, aState.mPresContext, parent);
    3940             :   } else {
    3941           0 :     MOZ_ASSERT(content->IsStyledByServo());
    3942             :   }
    3943             : 
    3944             :   // Get the parent of the content and check if it is a XBL children element.
    3945             :   // Push the children element as an ancestor here because it does
    3946             :   // not have a frame and would not otherwise be pushed as an ancestor. It is
    3947             :   // necessary to do so in order to correctly handle style resolution on
    3948             :   // descendants.  (If !adcp.IsEmpty() then it was already pushed by
    3949             :   // AutoDisplayContentsAncestorPusher above.)
    3950             :   TreeMatchContext::AutoAncestorPusher
    3951         938 :     insertionPointPusher(aState.mTreeMatchContext);
    3952         938 :   if (adcp.isSome() && adcp->IsEmpty() && parent &&
    3953         469 :       nsContentUtils::IsContentInsertionPoint(parent)) {
    3954           0 :     if (aState.mTreeMatchContext->mAncestorFilter.HasFilter()) {
    3955           0 :       insertionPointPusher.PushAncestorAndStyleScope(parent);
    3956             :     } else {
    3957           0 :       insertionPointPusher.PushStyleScope(parent);
    3958             :     }
    3959             :   }
    3960             : 
    3961             :   // Push the content as a style ancestor now, so we don't have to do
    3962             :   // it in our various full-constructor functions.  In particular,
    3963             :   // since a number of full-constructor functions don't actually call
    3964             :   // ProcessChildren in some cases (e.g. for CSS anonymous table boxes
    3965             :   // or for situations where only anonymouse children are having
    3966             :   // frames constructed), this is the best place to bottleneck the
    3967             :   // pushing of the content instead of having to do it in multiple
    3968             :   // places.
    3969             :   TreeMatchContext::AutoAncestorPusher
    3970         938 :     ancestorPusher(aState.mTreeMatchContext);
    3971         469 :   if (aState.HasAncestorFilter()) {
    3972         455 :     ancestorPusher.PushAncestorAndStyleScope(content);
    3973             :   } else {
    3974          14 :     ancestorPusher.PushStyleScope(content);
    3975             :   }
    3976             : 
    3977             :   nsIFrame* newFrame;
    3978             :   nsIFrame* primaryFrame;
    3979         469 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    3980         469 :   const nsStyleDisplay* display = styleContext->StyleDisplay();
    3981         469 :   if (bits & FCDATA_FUNC_IS_FULL_CTOR) {
    3982             :     newFrame =
    3983          21 :       (this->*(data->mFullConstructor))(aState, aItem, aParentFrame,
    3984          42 :                                         display, aFrameItems);
    3985          21 :     MOZ_ASSERT(newFrame, "Full constructor failed");
    3986          21 :     primaryFrame = newFrame;
    3987             :   } else {
    3988             :     newFrame =
    3989         448 :       (*data->mFunc.mCreationFunc)(mPresShell, styleContext);
    3990             : 
    3991         448 :     bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW);
    3992         448 :     bool isPopup = aItem.mIsPopup;
    3993         448 :     NS_ASSERTION(!isPopup ||
    3994             :                  (aState.mPopupItems.containingBlock &&
    3995             :                   aState.mPopupItems.containingBlock->IsPopupSetFrame()),
    3996             :                  "Should have a containing block here!");
    3997             : 
    3998             :     nsContainerFrame* geometricParent =
    3999         867 :       isPopup ? aState.mPopupItems.containingBlock :
    4000         419 :       (allowOutOfFlow ? aState.GetGeometricParent(display, aParentFrame)
    4001         448 :                       : aParentFrame);
    4002             : 
    4003             :     // Must init frameToAddToList to null, since it's inout
    4004         448 :     nsIFrame* frameToAddToList = nullptr;
    4005         596 :     if ((bits & FCDATA_MAY_NEED_SCROLLFRAME) &&
    4006         148 :         display->IsScrollableOverflow()) {
    4007           8 :       nsContainerFrame* scrollframe = nullptr;
    4008             :       BuildScrollFrame(aState, content, styleContext, newFrame,
    4009           8 :                        geometricParent, scrollframe);
    4010           8 :       frameToAddToList = scrollframe;
    4011             :     } else {
    4012         440 :       InitAndRestoreFrame(aState, content, geometricParent, newFrame);
    4013         440 :       frameToAddToList = newFrame;
    4014             :     }
    4015             : 
    4016             :     // Use frameToAddToList as the primary frame.  In the non-scrollframe case
    4017             :     // they're equal, but in the scrollframe case newFrame is the scrolled
    4018             :     // frame, while frameToAddToList is the scrollframe (and should be the
    4019             :     // primary frame).
    4020         448 :     primaryFrame = frameToAddToList;
    4021             : 
    4022             :     // If we need to create a block formatting context to wrap our
    4023             :     // kids, do it now.
    4024         448 :     const nsStyleDisplay* maybeAbsoluteContainingBlockDisplay = display;
    4025         448 :     nsIFrame* maybeAbsoluteContainingBlockStyleFrame = primaryFrame;
    4026         448 :     nsIFrame* maybeAbsoluteContainingBlock = newFrame;
    4027         448 :     nsIFrame* possiblyLeafFrame = newFrame;
    4028         448 :     if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS) {
    4029           4 :       RefPtr<nsStyleContext> outerSC = mPresShell->StyleSet()->
    4030           6 :         ResolveInheritingAnonymousBoxStyle(*data->mAnonBoxPseudo,
    4031           4 :                                            styleContext);
    4032             : #ifdef DEBUG
    4033           2 :       nsContainerFrame* containerFrame = do_QueryFrame(newFrame);
    4034           2 :       MOZ_ASSERT(containerFrame);
    4035             : #endif
    4036           2 :       nsContainerFrame* container = static_cast<nsContainerFrame*>(newFrame);
    4037             :       nsContainerFrame* outerFrame;
    4038             :       nsContainerFrame* innerFrame;
    4039           2 :       if (bits & FCDATA_ALLOW_GRID_FLEX_COLUMNSET) {
    4040           0 :         switch (display->mDisplay) {
    4041             :           case StyleDisplay::Flex:
    4042             :           case StyleDisplay::InlineFlex:
    4043           0 :             outerFrame = NS_NewFlexContainerFrame(mPresShell, outerSC);
    4044           0 :             InitAndRestoreFrame(aState, content, container, outerFrame);
    4045           0 :             innerFrame = outerFrame;
    4046           0 :             break;
    4047             :           case StyleDisplay::Grid:
    4048             :           case StyleDisplay::InlineGrid:
    4049           0 :             outerFrame = NS_NewGridContainerFrame(mPresShell, outerSC);
    4050           0 :             InitAndRestoreFrame(aState, content, container, outerFrame);
    4051           0 :             innerFrame = outerFrame;
    4052           0 :             break;
    4053             :           default: {
    4054           0 :             nsContainerFrame* columnSetFrame = nullptr;
    4055           0 :             RefPtr<nsStyleContext> innerSC = outerSC;
    4056           0 :             const nsStyleColumn* columns = outerSC->StyleColumn();
    4057           0 :             if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
    4058           0 :                 columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
    4059             :               columnSetFrame =
    4060           0 :                 NS_NewColumnSetFrame(mPresShell, outerSC,
    4061           0 :                                      nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
    4062           0 :               InitAndRestoreFrame(aState, content, container, columnSetFrame);
    4063           0 :               innerSC = mPresShell->StyleSet()->
    4064           0 :                 ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::columnContent,
    4065           0 :                                                    outerSC);
    4066             :             }
    4067           0 :             innerFrame = NS_NewBlockFormattingContext(mPresShell, innerSC);
    4068           0 :             if (columnSetFrame) {
    4069           0 :               InitAndRestoreFrame(aState, content, columnSetFrame, innerFrame);
    4070           0 :               SetInitialSingleChild(columnSetFrame, innerFrame);
    4071           0 :               outerFrame = columnSetFrame;
    4072             :             } else {
    4073           0 :               InitAndRestoreFrame(aState, content, container, innerFrame);
    4074           0 :               outerFrame = innerFrame;
    4075             :             }
    4076           0 :             break;
    4077             :           }
    4078             :         }
    4079             :       } else {
    4080           2 :         innerFrame = NS_NewBlockFormattingContext(mPresShell, outerSC);
    4081           2 :         InitAndRestoreFrame(aState, content, container, innerFrame);
    4082           2 :         outerFrame = innerFrame;
    4083             :       }
    4084             : 
    4085           2 :       SetInitialSingleChild(container, outerFrame);
    4086             : 
    4087           2 :       container->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    4088             : 
    4089             :       // Now figure out whether newFrame or outerFrame should be the
    4090             :       // absolute container.
    4091           2 :       auto outerDisplay = outerSC->StyleDisplay();
    4092           2 :       if (outerDisplay->IsAbsPosContainingBlock(outerFrame)) {
    4093           2 :         maybeAbsoluteContainingBlockDisplay = outerDisplay;
    4094           2 :         maybeAbsoluteContainingBlock = outerFrame;
    4095           2 :         maybeAbsoluteContainingBlockStyleFrame = outerFrame;
    4096           2 :         innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    4097             :       }
    4098             : 
    4099             :       // Our kids should go into the innerFrame.
    4100           2 :       newFrame = innerFrame;
    4101             :     }
    4102             : 
    4103         448 :     aState.AddChild(frameToAddToList, aFrameItems, content, styleContext,
    4104         448 :                     aParentFrame, allowOutOfFlow, allowOutOfFlow, isPopup);
    4105             : 
    4106         448 :     nsContainerFrame* newFrameAsContainer = do_QueryFrame(newFrame);
    4107         448 :     if (newFrameAsContainer) {
    4108             : #ifdef MOZ_XUL
    4109             :       // Icky XUL stuff, sadly
    4110             : 
    4111         283 :       if (aItem.mIsRootPopupgroup) {
    4112           1 :         NS_ASSERTION(nsIRootBox::GetRootBox(mPresShell) &&
    4113             :                      nsIRootBox::GetRootBox(mPresShell)->GetPopupSetFrame() ==
    4114             :                      newFrame,
    4115             :                      "Unexpected PopupSetFrame");
    4116           1 :         aState.mPopupItems.containingBlock = newFrameAsContainer;
    4117           1 :         aState.mHavePendingPopupgroup = false;
    4118             :       }
    4119             : #endif /* MOZ_XUL */
    4120             : 
    4121             :       // Process the child content if requested
    4122         283 :       nsFrameItems childItems;
    4123         566 :       nsFrameConstructorSaveState absoluteSaveState;
    4124             : 
    4125         283 :       if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER) {
    4126           0 :         aState.PushAbsoluteContainingBlock(nullptr, nullptr, absoluteSaveState);
    4127         283 :       } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH)) {
    4128         111 :         maybeAbsoluteContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
    4129             :         // This check is identical to nsStyleDisplay::IsAbsPosContainingBlock
    4130             :         // except without the assertion that the style display and frame match.
    4131             :         // When constructing scroll frames we intentionally use the style
    4132             :         // display for the outer, but make the inner the containing block.
    4133         333 :         if ((maybeAbsoluteContainingBlockDisplay->IsAbsolutelyPositionedStyle() ||
    4134         214 :              maybeAbsoluteContainingBlockDisplay->IsRelativelyPositionedStyle() ||
    4135         103 :              maybeAbsoluteContainingBlockDisplay->IsFixedPosContainingBlock(
    4136         121 :                  maybeAbsoluteContainingBlockStyleFrame)) &&
    4137          10 :             !nsSVGUtils::IsInSVGTextSubtree(maybeAbsoluteContainingBlockStyleFrame)) {
    4138             :           nsContainerFrame* cf = static_cast<nsContainerFrame*>(
    4139          10 :               maybeAbsoluteContainingBlock);
    4140          10 :           aState.PushAbsoluteContainingBlock(cf, cf, absoluteSaveState);
    4141             :         }
    4142             :       }
    4143             : 
    4144         283 :       if (!aItem.mAnonChildren.IsEmpty()) {
    4145           0 :         NS_ASSERTION(!(bits & FCDATA_USE_CHILD_ITEMS),
    4146             :                      "We should not have both anonymous and non-anonymous "
    4147             :                      "children in a given FrameConstructorItem");
    4148           0 :         AddFCItemsForAnonymousContent(aState, newFrameAsContainer, aItem.mAnonChildren,
    4149           0 :                                       aItem.mChildItems);
    4150           0 :         bits |= FCDATA_USE_CHILD_ITEMS;
    4151             :       }
    4152             : 
    4153         283 :       if (bits & FCDATA_USE_CHILD_ITEMS) {
    4154           0 :         nsFrameConstructorSaveState floatSaveState;
    4155             : 
    4156           0 :         if (ShouldSuppressFloatingOfDescendants(newFrame)) {
    4157           0 :           aState.PushFloatContainingBlock(nullptr, floatSaveState);
    4158           0 :         } else if (newFrame->IsFloatContainingBlock()) {
    4159           0 :           aState.PushFloatContainingBlock(newFrameAsContainer, floatSaveState);
    4160             :         }
    4161           0 :         ConstructFramesFromItemList(aState, aItem.mChildItems, newFrameAsContainer,
    4162           0 :                                     childItems);
    4163             :       } else {
    4164             :         // Process the child frames.
    4165         849 :         ProcessChildren(aState, content, styleContext, newFrameAsContainer,
    4166         283 :                         !(bits & FCDATA_DISALLOW_GENERATED_CONTENT),
    4167             :                         childItems,
    4168         283 :                         (bits & FCDATA_ALLOW_BLOCK_STYLES) != 0,
    4169         283 :                         aItem.mPendingBinding, possiblyLeafFrame);
    4170             :       }
    4171             : 
    4172         283 :       if (bits & FCDATA_WRAP_KIDS_IN_BLOCKS) {
    4173           0 :         nsFrameItems newItems;
    4174           0 :         nsFrameItems currentBlockItems;
    4175             :         nsIFrame* f;
    4176           0 :         while ((f = childItems.FirstChild()) != nullptr) {
    4177           0 :           bool wrapFrame = IsInlineFrame(f) || IsFramePartOfIBSplit(f);
    4178           0 :           if (!wrapFrame) {
    4179             :             FlushAccumulatedBlock(aState, content, newFrameAsContainer,
    4180           0 :                                   currentBlockItems, newItems);
    4181             :           }
    4182             : 
    4183           0 :           childItems.RemoveFrame(f);
    4184           0 :           if (wrapFrame) {
    4185           0 :             currentBlockItems.AddChild(f);
    4186             :           } else {
    4187           0 :             newItems.AddChild(f);
    4188             :           }
    4189             :         }
    4190             :         FlushAccumulatedBlock(aState, content, newFrameAsContainer,
    4191           0 :                               currentBlockItems, newItems);
    4192             : 
    4193           0 :         if (childItems.NotEmpty()) {
    4194             :           // an error must have occurred, delete unprocessed frames
    4195           0 :           childItems.DestroyFrames();
    4196             :         }
    4197             : 
    4198           0 :         childItems = newItems;
    4199             :       }
    4200             : 
    4201             :       // Set the frame's initial child list
    4202             :       // Note that MathML depends on this being called even if
    4203             :       // childItems is empty!
    4204         283 :       newFrameAsContainer->SetInitialChildList(kPrincipalList, childItems);
    4205             :     }
    4206             :   }
    4207             : 
    4208             : #ifdef MOZ_XUL
    4209             :   // More icky XUL stuff
    4210         840 :   if (aItem.mNameSpaceID == kNameSpaceID_XUL &&
    4211         644 :       (aItem.mTag == nsGkAtoms::treechildren || // trees always need titletips
    4212         623 :        content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext) ||
    4213         301 :        content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltip))) {
    4214          49 :     nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
    4215          49 :     if (rootBox) {
    4216          49 :       rootBox->AddTooltipSupport(content);
    4217             :     }
    4218             :   }
    4219             : #endif
    4220             : 
    4221         469 :   NS_ASSERTION(newFrame->IsFrameOfType(nsIFrame::eLineParticipant) ==
    4222             :                ((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),
    4223             :                "Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits");
    4224             : 
    4225         469 :   if (aItem.mIsAnonymousContentCreatorContent) {
    4226          39 :     primaryFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
    4227             :   }
    4228             : 
    4229             :   // Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
    4230             :   // generated content that doesn't have one yet.  Note that we have to examine
    4231             :   // the frame bit, because by this point mIsGeneratedContent has been cleared
    4232             :   // on aItem.
    4233         938 :   if ((!aState.mCreatingExtraFrames ||
    4234           0 :        (primaryFrame->HasAnyStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT |
    4235           0 :                                       NS_FRAME_GENERATED_CONTENT) &&
    4236         938 :         !aItem.mContent->GetPrimaryFrame())) &&
    4237         469 :        !(bits & FCDATA_SKIP_FRAMESET)) {
    4238         469 :     aItem.mContent->SetPrimaryFrame(primaryFrame);
    4239         469 :     ActiveLayerTracker::TransferActivityToFrame(aItem.mContent, primaryFrame);
    4240             :   }
    4241             : }
    4242             : 
    4243             : static void
    4244           8 : SetFlagsOnSubtree(nsIContent *aNode, uintptr_t aFlagsToSet)
    4245             : {
    4246             : #ifdef DEBUG
    4247             :   // Make sure that the node passed to us doesn't have any XBL children
    4248             :   {
    4249          16 :     FlattenedChildIterator iter(aNode);
    4250           8 :     NS_ASSERTION(!iter.XBLInvolved() || !iter.GetNextChild(),
    4251             :                  "The node should not have any XBL children");
    4252             :   }
    4253             : #endif
    4254             : 
    4255             :   // Set the flag on the node itself
    4256           8 :   aNode->SetFlags(aFlagsToSet);
    4257             : 
    4258             :   // Set the flag on all of its children recursively
    4259             :   uint32_t count;
    4260           8 :   nsIContent * const *children = aNode->GetChildArray(&count);
    4261             : 
    4262          12 :   for (uint32_t index = 0; index < count; ++index) {
    4263           4 :     SetFlagsOnSubtree(children[index], aFlagsToSet);
    4264             :   }
    4265           8 : }
    4266             : 
    4267             : /**
    4268             :  * This function takes a tree of nsIAnonymousContentCreator::ContentInfo
    4269             :  * objects where the nsIContent nodes have just been created, and appends the
    4270             :  * nsIContent children in the tree to their parent. The leaf nsIContent objects
    4271             :  * are appended first to minimize the number of notifications that are sent
    4272             :  * out (i.e. by appending as many descendants as posible while their parent is
    4273             :  * not yet in the document tree).
    4274             :  *
    4275             :  * This function is used simply as a convenience so that implementations of
    4276             :  * nsIAnonymousContentCreator::CreateAnonymousContent don't all have to have
    4277             :  * their own code to connect the elements that they create.
    4278             :  */
    4279             : static void
    4280          62 : ConnectAnonymousTreeDescendants(nsIContent* aParent,
    4281             :                                 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
    4282             : {
    4283          62 :   uint32_t count = aContent.Length();
    4284          62 :   for (uint32_t i=0; i < count; i++) {
    4285           0 :     nsIContent* content = aContent[i].mContent;
    4286           0 :     NS_ASSERTION(content, "null anonymous content?");
    4287             : 
    4288           0 :     ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
    4289             : 
    4290           0 :     aParent->AppendChildTo(content, false);
    4291             :   }
    4292          62 : }
    4293             : 
    4294             : static void
    4295          16 : SetNativeAnonymousBitOnDescendants(nsIContent* aRoot)
    4296             : {
    4297          40 :   for (nsIContent* curr = aRoot; curr; curr = curr->GetNextNode(aRoot)) {
    4298          24 :     curr->SetFlags(NODE_IS_NATIVE_ANONYMOUS);
    4299             :   }
    4300          16 : }
    4301             : 
    4302             : nsresult
    4303         394 : nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
    4304             :                                            nsIFrame* aParentFrame,
    4305             :                                            nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
    4306             : {
    4307         394 :   nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
    4308         394 :   if (!creator)
    4309         300 :     return NS_OK;
    4310             : 
    4311          94 :   nsresult rv = creator->CreateAnonymousContent(aContent);
    4312          94 :   if (NS_FAILED(rv)) {
    4313             :     // CreateAnonymousContent failed, e.g. because the page has a <use> loop.
    4314           0 :     return rv;
    4315             :   }
    4316             : 
    4317          94 :   uint32_t count = aContent.Length();
    4318         156 :   for (uint32_t i=0; i < count; i++) {
    4319             :     // get our child's content and set its parent to our content
    4320          62 :     nsIContent* content = aContent[i].mContent;
    4321          62 :     NS_ASSERTION(content, "null anonymous content?");
    4322             : 
    4323          62 :     ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
    4324             : 
    4325          62 :     LayoutFrameType parentFrameType = aParentFrame->Type();
    4326          62 :     if (parentFrameType == LayoutFrameType::SVGUse) {
    4327             :       // least-surprise CSS binding until we do the SVG specified
    4328             :       // cascading rules for <svg:use> - bug 265894
    4329          23 :       content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
    4330             :     } else {
    4331          39 :       content->SetIsNativeAnonymousRoot();
    4332             :       // Don't mark descendants of the custom content container
    4333             :       // as native anonymous.  When canvas custom content is initially
    4334             :       // created and appended to the custom content container, in
    4335             :       // nsIDocument::InsertAnonymousContent, it is not considered native
    4336             :       // anonymous content.  But if we end up reframing the root element,
    4337             :       // we will re-create the nsCanvasFrame, and we would end up in here,
    4338             :       // marking it as NAC.  Existing uses of canvas custom content would
    4339             :       // break if it becomes NAC (since each element starts inheriting
    4340             :       // styles from its closest non-NAC ancestor, rather than from its
    4341             :       // parent).
    4342          62 :       if (!(parentFrameType == LayoutFrameType::Canvas &&
    4343             :             content == static_cast<nsCanvasFrame*>(aParentFrame)
    4344          23 :                          ->GetCustomContentContainer())) {
    4345          16 :         SetNativeAnonymousBitOnDescendants(content);
    4346             :       }
    4347             :     }
    4348             : 
    4349          62 :     bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
    4350             : 
    4351             :     // If the parent is in a shadow tree, make sure we don't
    4352             :     // bind with a document because shadow roots and its descendants
    4353             :     // are not in document.
    4354             :     nsIDocument* bindDocument =
    4355          62 :       aParent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
    4356          62 :     rv = content->BindToTree(bindDocument, aParent, aParent, true);
    4357             :     // If the anonymous content creator requested that the content should be
    4358             :     // editable, honor its request.
    4359             :     // We need to set the flag on the whole subtree, because existing
    4360             :     // children's flags have already been set as part of the BindToTree operation.
    4361          62 :     if (anonContentIsEditable) {
    4362           4 :       NS_ASSERTION(aParentFrame->IsTextInputFrame(),
    4363             :                    "We only expect this for anonymous content under a text control frame");
    4364           4 :       SetFlagsOnSubtree(content, NODE_IS_EDITABLE);
    4365             :     }
    4366          62 :     if (NS_FAILED(rv)) {
    4367           0 :       content->UnbindFromTree();
    4368           0 :       return rv;
    4369             :     }
    4370             :   }
    4371             : 
    4372          94 :   if (ServoStyleSet* styleSet = mPresShell->StyleSet()->GetAsServo()) {
    4373             :     // Eagerly compute styles for the anonymous content tree.
    4374           0 :     for (auto& info : aContent) {
    4375           0 :       if (info.mContent->IsElement()) {
    4376           0 :         styleSet->StyleNewSubtree(info.mContent->AsElement());
    4377             :       }
    4378             :     }
    4379             :   }
    4380             : 
    4381          94 :   return NS_OK;
    4382             : }
    4383             : 
    4384             : static
    4385          43 : bool IsXULDisplayType(const nsStyleDisplay* aDisplay)
    4386             : {
    4387          86 :   return (aDisplay->mDisplay == StyleDisplay::MozInlineBox ||
    4388             : #ifdef MOZ_XUL
    4389          86 :           aDisplay->mDisplay == StyleDisplay::MozInlineGrid ||
    4390          86 :           aDisplay->mDisplay == StyleDisplay::MozInlineStack ||
    4391             : #endif
    4392          43 :           aDisplay->mDisplay == StyleDisplay::MozBox
    4393             : #ifdef MOZ_XUL
    4394          70 :           || aDisplay->mDisplay == StyleDisplay::MozGrid ||
    4395          70 :           aDisplay->mDisplay == StyleDisplay::MozStack ||
    4396          70 :           aDisplay->mDisplay == StyleDisplay::MozGridGroup ||
    4397          70 :           aDisplay->mDisplay == StyleDisplay::MozGridLine ||
    4398          70 :           aDisplay->mDisplay == StyleDisplay::MozDeck ||
    4399         113 :           aDisplay->mDisplay == StyleDisplay::MozPopup ||
    4400          35 :           aDisplay->mDisplay == StyleDisplay::MozGroupbox
    4401             : #endif
    4402          43 :           );
    4403             : }
    4404             : 
    4405             : 
    4406             : // XUL frames are not allowed to be out of flow.
    4407             : #define SIMPLE_XUL_FCDATA(_func)                                        \
    4408             :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH,    \
    4409             :               _func)
    4410             : #define SCROLLABLE_XUL_FCDATA(_func)                                    \
    4411             :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |   \
    4412             :               FCDATA_MAY_NEED_SCROLLFRAME, _func)
    4413             : // .. but we allow some XUL frames to be _containers_ for out-of-flow content
    4414             : // (This is the same as SCROLLABLE_XUL_FCDATA, but w/o FCDATA_SKIP_ABSPOS_PUSH)
    4415             : #define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func)                   \
    4416             :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
    4417             :               FCDATA_MAY_NEED_SCROLLFRAME, _func)
    4418             : 
    4419             : #define SIMPLE_XUL_CREATE(_tag, _func)            \
    4420             :   { &nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func) }
    4421             : #define SCROLLABLE_XUL_CREATE(_tag, _func)            \
    4422             :   { &nsGkAtoms::_tag, SCROLLABLE_XUL_FCDATA(_func) }
    4423             : #define SIMPLE_XUL_DISPLAY_CREATE(_display, _func)      \
    4424             :   FCDATA_FOR_DISPLAY(_display, SIMPLE_XUL_FCDATA(_func))
    4425             : #define SCROLLABLE_XUL_DISPLAY_CREATE(_display, _func)                          \
    4426             :   FCDATA_FOR_DISPLAY(_display, SCROLLABLE_XUL_FCDATA(_func))
    4427             : #define SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(_display, _func)         \
    4428             :   FCDATA_FOR_DISPLAY(_display, SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func))
    4429             : 
    4430             : static
    4431           0 : nsIFrame* NS_NewGridBoxFrame(nsIPresShell* aPresShell,
    4432             :                              nsStyleContext* aStyleContext)
    4433             : {
    4434           0 :   nsCOMPtr<nsBoxLayout> layout;
    4435           0 :   NS_NewGridLayout2(aPresShell, getter_AddRefs(layout));
    4436           0 :   return NS_NewBoxFrame(aPresShell, aStyleContext, false, layout);
    4437             : }
    4438             : 
    4439             : /* static */
    4440             : const nsCSSFrameConstructor::FrameConstructionData*
    4441         463 : nsCSSFrameConstructor::FindXULTagData(Element* aElement,
    4442             :                                       nsIAtom* aTag,
    4443             :                                       int32_t aNameSpaceID,
    4444             :                                       nsStyleContext* aStyleContext)
    4445             : {
    4446         463 :   if (aNameSpaceID != kNameSpaceID_XUL) {
    4447         141 :     return nullptr;
    4448             :   }
    4449             : 
    4450             :   static const FrameConstructionDataByTag sXULTagData[] = {
    4451             : #ifdef MOZ_XUL
    4452             :     SCROLLABLE_XUL_CREATE(button, NS_NewButtonBoxFrame),
    4453             :     SCROLLABLE_XUL_CREATE(checkbox, NS_NewButtonBoxFrame),
    4454             :     SCROLLABLE_XUL_CREATE(radio, NS_NewButtonBoxFrame),
    4455             :     SCROLLABLE_XUL_CREATE(autorepeatbutton, NS_NewAutoRepeatBoxFrame),
    4456             :     SCROLLABLE_XUL_CREATE(titlebar, NS_NewTitleBarFrame),
    4457             :     SCROLLABLE_XUL_CREATE(resizer, NS_NewResizerFrame),
    4458             :     SIMPLE_XUL_CREATE(image, NS_NewImageBoxFrame),
    4459             :     SIMPLE_XUL_CREATE(spring, NS_NewLeafBoxFrame),
    4460             :     SIMPLE_XUL_CREATE(spacer, NS_NewLeafBoxFrame),
    4461             :     SIMPLE_XUL_CREATE(treechildren, NS_NewTreeBodyFrame),
    4462             :     SIMPLE_XUL_CREATE(treecol, NS_NewTreeColFrame),
    4463             :     SIMPLE_XUL_CREATE(text, NS_NewTextBoxFrame),
    4464             :     SIMPLE_TAG_CHAIN(label, nsCSSFrameConstructor::FindXULLabelData),
    4465             :     SIMPLE_TAG_CHAIN(description, nsCSSFrameConstructor::FindXULDescriptionData),
    4466             :     SIMPLE_XUL_CREATE(menu, NS_NewMenuFrame),
    4467             :     SIMPLE_XUL_CREATE(menubutton, NS_NewMenuFrame),
    4468             :     SIMPLE_XUL_CREATE(menuitem, NS_NewMenuItemFrame),
    4469             : #ifdef XP_MACOSX
    4470             :     SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData),
    4471             : #else
    4472             :     SIMPLE_XUL_CREATE(menubar, NS_NewMenuBarFrame),
    4473             : #endif /* XP_MACOSX */
    4474             :     SIMPLE_TAG_CHAIN(popupgroup, nsCSSFrameConstructor::FindPopupGroupData),
    4475             :     SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame),
    4476             :     SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame),
    4477             :     SIMPLE_XUL_CREATE(browser, NS_NewSubDocumentFrame),
    4478             :     SIMPLE_XUL_CREATE(progressmeter, NS_NewProgressMeterFrame),
    4479             :     SIMPLE_XUL_CREATE(splitter, NS_NewSplitterFrame),
    4480             :     SIMPLE_TAG_CHAIN(listboxbody,
    4481             :                      nsCSSFrameConstructor::FindXULListBoxBodyData),
    4482             :     SIMPLE_TAG_CHAIN(listitem, nsCSSFrameConstructor::FindXULListItemData),
    4483             : #endif /* MOZ_XUL */
    4484             :     SIMPLE_XUL_CREATE(slider, NS_NewSliderFrame),
    4485             :     SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame),
    4486             :     SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame)
    4487             : };
    4488             : 
    4489         322 :   return FindDataByTag(aTag, aElement, aStyleContext, sXULTagData,
    4490         644 :                        ArrayLength(sXULTagData));
    4491             : }
    4492             : 
    4493             : #ifdef MOZ_XUL
    4494             : /* static */
    4495             : const nsCSSFrameConstructor::FrameConstructionData*
    4496           1 : nsCSSFrameConstructor::FindPopupGroupData(Element* aElement,
    4497             :                                           nsStyleContext* /* unused */)
    4498             : {
    4499           1 :   if (!aElement->IsRootOfNativeAnonymousSubtree()) {
    4500           0 :     return nullptr;
    4501             :   }
    4502             : 
    4503             :   static const FrameConstructionData sPopupSetData =
    4504             :     SIMPLE_XUL_FCDATA(NS_NewPopupSetFrame);
    4505           1 :   return &sPopupSetData;
    4506             : }
    4507             : 
    4508             : /* static */
    4509             : const nsCSSFrameConstructor::FrameConstructionData
    4510             : nsCSSFrameConstructor::sXULTextBoxData = SIMPLE_XUL_FCDATA(NS_NewTextBoxFrame);
    4511             : 
    4512             : /* static */
    4513             : const nsCSSFrameConstructor::FrameConstructionData*
    4514          16 : nsCSSFrameConstructor::FindXULLabelData(Element* aElement,
    4515             :                                         nsStyleContext* /* unused */)
    4516             : {
    4517          16 :   if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    4518          11 :     return &sXULTextBoxData;
    4519             :   }
    4520             : 
    4521             :   static const FrameConstructionData sLabelData =
    4522             :     SIMPLE_XUL_FCDATA(NS_NewXULLabelFrame);
    4523           5 :   return &sLabelData;
    4524             : }
    4525             : 
    4526             : static nsIFrame*
    4527           0 : NS_NewXULDescriptionFrame(nsIPresShell* aPresShell, nsStyleContext *aContext)
    4528             : {
    4529             :   // XXXbz do we really need to set up the block formatting context root? If the
    4530             :   // parent is not a block we'll get it anyway, and if it is, do we want it?
    4531           0 :   return NS_NewBlockFormattingContext(aPresShell, aContext);
    4532             : }
    4533             : 
    4534             : /* static */
    4535             : const nsCSSFrameConstructor::FrameConstructionData*
    4536           0 : nsCSSFrameConstructor::FindXULDescriptionData(Element* aElement,
    4537             :                                               nsStyleContext* /* unused */)
    4538             : {
    4539           0 :   if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    4540           0 :     return &sXULTextBoxData;
    4541             :   }
    4542             : 
    4543             :   static const FrameConstructionData sDescriptionData =
    4544             :     SIMPLE_XUL_FCDATA(NS_NewXULDescriptionFrame);
    4545           0 :   return &sDescriptionData;
    4546             : }
    4547             : 
    4548             : #ifdef XP_MACOSX
    4549             : /* static */
    4550             : const nsCSSFrameConstructor::FrameConstructionData*
    4551             : nsCSSFrameConstructor::FindXULMenubarData(Element* aElement,
    4552             :                                           nsStyleContext* aStyleContext)
    4553             : {
    4554             :   nsCOMPtr<nsIDocShell> treeItem =
    4555             :     aStyleContext->PresContext()->GetDocShell();
    4556             :   if (treeItem && nsIDocShellTreeItem::typeChrome == treeItem->ItemType()) {
    4557             :     nsCOMPtr<nsIDocShellTreeItem> parent;
    4558             :     treeItem->GetParent(getter_AddRefs(parent));
    4559             :     if (!parent) {
    4560             :       // This is the root.  Suppress the menubar, since on Mac
    4561             :       // window menus are not attached to the window.
    4562             :       static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
    4563             :       return &sSuppressData;
    4564             :     }
    4565             :   }
    4566             : 
    4567             :   static const FrameConstructionData sMenubarData =
    4568             :     SIMPLE_XUL_FCDATA(NS_NewMenuBarFrame);
    4569             :   return &sMenubarData;
    4570             : }
    4571             : #endif /* XP_MACOSX */
    4572             : 
    4573             : /* static */
    4574             : const nsCSSFrameConstructor::FrameConstructionData*
    4575           0 : nsCSSFrameConstructor::FindXULListBoxBodyData(Element* aElement,
    4576             :                                               nsStyleContext* aStyleContext)
    4577             : {
    4578           0 :   if (aStyleContext->StyleDisplay()->mDisplay !=
    4579             :         StyleDisplay::MozGridGroup) {
    4580           0 :     return nullptr;
    4581             :   }
    4582             : 
    4583             :   static const FrameConstructionData sListBoxBodyData =
    4584             :     SCROLLABLE_XUL_FCDATA(NS_NewListBoxBodyFrame);
    4585           0 :   return &sListBoxBodyData;
    4586             : }
    4587             : 
    4588             : /* static */
    4589             : const nsCSSFrameConstructor::FrameConstructionData*
    4590           0 : nsCSSFrameConstructor::FindXULListItemData(Element* aElement,
    4591             :                                            nsStyleContext* aStyleContext)
    4592             : {
    4593           0 :   if (aStyleContext->StyleDisplay()->mDisplay != StyleDisplay::MozGridLine) {
    4594           0 :     return nullptr;
    4595             :   }
    4596             : 
    4597             :   static const FrameConstructionData sListItemData =
    4598             :     SCROLLABLE_XUL_FCDATA(NS_NewListItemFrame);
    4599           0 :   return &sListItemData;
    4600             : }
    4601             : 
    4602             : #endif /* MOZ_XUL */
    4603             : 
    4604             : /* static */
    4605             : const nsCSSFrameConstructor::FrameConstructionData*
    4606         184 : nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay,
    4607             :                                           Element* aElement,
    4608             :                                           nsStyleContext* aStyleContext)
    4609             : {
    4610             :   static const FrameConstructionDataByDisplay sXULDisplayData[] = {
    4611             :     SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::MozBox,
    4612             :                                                    NS_NewBoxFrame),
    4613             :     SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineBox,
    4614             :                                                    NS_NewBoxFrame),
    4615             : #ifdef MOZ_XUL
    4616             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGrid, NS_NewGridBoxFrame),
    4617             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineGrid, NS_NewGridBoxFrame),
    4618             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGridGroup,
    4619             :                                   NS_NewGridRowGroupFrame),
    4620             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGridLine,
    4621             :                                   NS_NewGridRowLeafFrame),
    4622             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozStack, NS_NewStackFrame),
    4623             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineStack, NS_NewStackFrame),
    4624             :     SIMPLE_XUL_DISPLAY_CREATE(StyleDisplay::MozDeck, NS_NewDeckFrame),
    4625             :     SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGroupbox, NS_NewGroupBoxFrame),
    4626             :     FCDATA_FOR_DISPLAY(StyleDisplay::MozPopup,
    4627             :       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
    4628             :                   FCDATA_SKIP_ABSPOS_PUSH, NS_NewMenuPopupFrame))
    4629             : #endif /* MOZ_XUL */
    4630             :   };
    4631             : 
    4632         184 :   if (aDisplay->mDisplay < StyleDisplay::MozBox) {
    4633          20 :     return nullptr;
    4634             :   }
    4635             : 
    4636         164 :   MOZ_ASSERT(aDisplay->mDisplay <= StyleDisplay::MozPopup,
    4637             :              "Someone added a new display value?");
    4638             : 
    4639             :   const FrameConstructionDataByDisplay& data =
    4640         164 :     sXULDisplayData[size_t(aDisplay->mDisplay) - size_t(StyleDisplay::MozBox)];
    4641         164 :   MOZ_ASSERT(aDisplay->mDisplay == data.mDisplay,
    4642             :              "Did someone mess with the order?");
    4643             : 
    4644         164 :   return &data.mData;
    4645             : }
    4646             : 
    4647             : already_AddRefed<nsStyleContext>
    4648          43 : nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
    4649             :                                                 nsIContent*              aContent,
    4650             :                                                 nsStyleContext*          aContentStyle,
    4651             :                                                 nsContainerFrame*        aParentFrame,
    4652             :                                                 nsIAtom*                 aScrolledPseudo,
    4653             :                                                 bool                     aIsRoot,
    4654             :                                                 nsContainerFrame*&       aNewFrame)
    4655             : {
    4656          43 :   nsContainerFrame* gfxScrollFrame = aNewFrame;
    4657             : 
    4658          43 :   nsFrameItems anonymousItems;
    4659             : 
    4660          86 :   RefPtr<nsStyleContext> contentStyle = aContentStyle;
    4661             : 
    4662          43 :   if (!gfxScrollFrame) {
    4663             :     // Build a XULScrollFrame when the child is a box, otherwise an
    4664             :     // HTMLScrollFrame
    4665             :     // XXXbz this is the lone remaining consumer of IsXULDisplayType.
    4666             :     // I wonder whether we can eliminate that somehow.
    4667          43 :     const nsStyleDisplay* displayStyle = aContentStyle->StyleDisplay();
    4668          43 :     if (IsXULDisplayType(displayStyle)) {
    4669           8 :       gfxScrollFrame = NS_NewXULScrollFrame(mPresShell, contentStyle, aIsRoot,
    4670          16 :           displayStyle->mDisplay == StyleDisplay::MozStack ||
    4671          16 :           displayStyle->mDisplay == StyleDisplay::MozInlineStack);
    4672             :     } else {
    4673          35 :       gfxScrollFrame = NS_NewHTMLScrollFrame(mPresShell, contentStyle, aIsRoot);
    4674             :     }
    4675             : 
    4676          43 :     InitAndRestoreFrame(aState, aContent, aParentFrame, gfxScrollFrame);
    4677             :   }
    4678             : 
    4679             :   // if there are any anonymous children for the scroll frame, create
    4680             :   // frames for them.
    4681             :   //
    4682             :   // We can't take the normal ProcessChildren path, because the NAC needs to
    4683             :   // be parented to the scrollframe, and everything else needs to be parented
    4684             :   // to the scrolledframe.
    4685          86 :   AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> scrollNAC;
    4686          86 :   DebugOnly<nsresult> rv = GetAnonymousContent(aContent, gfxScrollFrame, scrollNAC);
    4687          43 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    4688          43 :   if (scrollNAC.Length() > 0) {
    4689           4 :     TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
    4690           2 :     if (aState.HasAncestorFilter()) {
    4691           0 :       ancestorPusher.PushAncestorAndStyleScope(aContent->AsElement());
    4692             :     } else {
    4693           2 :       ancestorPusher.PushStyleScope(aContent->AsElement());
    4694             :     }
    4695             : 
    4696           4 :     FrameConstructionItemList items;
    4697           2 :     AddFCItemsForAnonymousContent(aState, gfxScrollFrame, scrollNAC, items);
    4698           2 :     ConstructFramesFromItemList(aState, items, gfxScrollFrame, anonymousItems);
    4699             :   }
    4700             : 
    4701          43 :   aNewFrame = gfxScrollFrame;
    4702          43 :   gfxScrollFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    4703             : 
    4704             :   // we used the style that was passed in. So resolve another one.
    4705          43 :   StyleSetHandle styleSet = mPresShell->StyleSet();
    4706             :   RefPtr<nsStyleContext> scrolledChildStyle =
    4707          86 :     styleSet->ResolveInheritingAnonymousBoxStyle(aScrolledPseudo, contentStyle);
    4708             : 
    4709          43 :   if (gfxScrollFrame) {
    4710          43 :      gfxScrollFrame->SetInitialChildList(kPrincipalList, anonymousItems);
    4711             :   }
    4712             : 
    4713          86 :   return scrolledChildStyle.forget();
    4714             : }
    4715             : 
    4716             : void
    4717          43 : nsCSSFrameConstructor::FinishBuildingScrollFrame(nsContainerFrame* aScrollFrame,
    4718             :                                                  nsIFrame* aScrolledFrame)
    4719             : {
    4720          43 :   nsFrameList scrolled(aScrolledFrame, aScrolledFrame);
    4721          43 :   aScrollFrame->AppendFrames(kPrincipalList, scrolled);
    4722          43 : }
    4723             : 
    4724             : /**
    4725             :  * Called to wrap a gfx scrollframe around a frame. The hierarchy will look like this
    4726             :  *
    4727             :  * ------- for gfx scrollbars ------
    4728             :  *
    4729             :  *
    4730             :  *            ScrollFrame
    4731             :  *                 ^
    4732             :  *                 |
    4733             :  *               Frame (scrolled frame you passed in)
    4734             :  *
    4735             :  *
    4736             :  *-----------------------------------
    4737             :  * LEGEND:
    4738             :  *
    4739             :  * ScrollFrame: This is a frame that manages gfx cross platform frame based scrollbars.
    4740             :  *
    4741             :  * @param aContent the content node of the child to wrap.
    4742             :  * @param aScrolledFrame The frame of the content to wrap. This should not be
    4743             :  *                    Initialized. This method will initialize it with a scrolled pseudo
    4744             :  *                    and no nsIContent. The content will be attached to the scrollframe
    4745             :  *                    returned.
    4746             :  * @param aContentStyle the style context that has already been resolved for the content being passed in.
    4747             :  *
    4748             :  * @param aParentFrame The parent to attach the scroll frame to
    4749             :  *
    4750             :  * @param aNewFrame The new scrollframe or gfx scrollframe that we create. It will contain the
    4751             :  *                  scrolled frame you passed in. (returned)
    4752             :  *                  If this is not null, we'll just use it
    4753             :  * @param aScrolledContentStyle the style that was resolved for the scrolled frame. (returned)
    4754             :  */
    4755             : void
    4756           8 : nsCSSFrameConstructor::BuildScrollFrame(nsFrameConstructorState& aState,
    4757             :                                         nsIContent*              aContent,
    4758             :                                         nsStyleContext*          aContentStyle,
    4759             :                                         nsIFrame*                aScrolledFrame,
    4760             :                                         nsContainerFrame*        aParentFrame,
    4761             :                                         nsContainerFrame*&       aNewFrame)
    4762             : {
    4763             :   RefPtr<nsStyleContext> scrolledContentStyle =
    4764          16 :     BeginBuildingScrollFrame(aState, aContent, aContentStyle, aParentFrame,
    4765             :                              nsCSSAnonBoxes::scrolledContent,
    4766          16 :                              false, aNewFrame);
    4767             : 
    4768           8 :   aScrolledFrame->SetStyleContextWithoutNotification(scrolledContentStyle);
    4769           8 :   InitAndRestoreFrame(aState, aContent, aNewFrame, aScrolledFrame);
    4770             : 
    4771           8 :   FinishBuildingScrollFrame(aNewFrame, aScrolledFrame);
    4772           8 : }
    4773             : 
    4774             : const nsCSSFrameConstructor::FrameConstructionData*
    4775          20 : nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
    4776             :                                        Element* aElement,
    4777             :                                        nsStyleContext* aStyleContext)
    4778             : {
    4779             :   static_assert(eParentTypeCount < (1 << (32 - FCDATA_PARENT_TYPE_OFFSET)),
    4780             :                 "Check eParentTypeCount should not overflow");
    4781             : 
    4782             :   // The style system ensures that floated and positioned frames are
    4783             :   // block-level.
    4784          20 :   NS_ASSERTION(!(aDisplay->IsFloatingStyle() ||
    4785             :                  aDisplay->IsAbsolutelyPositionedStyle()) ||
    4786             :                aDisplay->IsBlockOutsideStyle() ||
    4787             :                aDisplay->mDisplay == StyleDisplay::Contents,
    4788             :                "Style system did not apply CSS2.1 section 9.7 fixups");
    4789             : 
    4790             :   // If this is "body", try propagating its scroll style to the viewport
    4791             :   // Note that we need to do this even if the body is NOT scrollable;
    4792             :   // it might have dynamically changed from scrollable to not scrollable,
    4793             :   // and that might need to be propagated.
    4794             :   // XXXbz is this the right place to do this?  If this code moves,
    4795             :   // make this function static.
    4796          20 :   bool propagatedScrollToViewport = false;
    4797          20 :   if (aElement->IsHTMLElement(nsGkAtoms::body)) {
    4798           2 :     if (nsPresContext* presContext = mPresShell->GetPresContext()) {
    4799           2 :       propagatedScrollToViewport =
    4800           2 :         presContext->UpdateViewportScrollbarStylesOverride() == aElement;
    4801             :     }
    4802             :   }
    4803             : 
    4804          20 :   NS_ASSERTION(!propagatedScrollToViewport ||
    4805             :                !mPresShell->GetPresContext()->IsPaginated(),
    4806             :                "Shouldn't propagate scroll in paginated contexts");
    4807             : 
    4808          20 :   if (aDisplay->IsBlockInsideStyle()) {
    4809             :     // If the frame is a block-level frame and is scrollable, then wrap it in a
    4810             :     // scroll frame.  Except we don't want to do that for paginated contexts for
    4811             :     // frames that are block-outside and aren't frames for native anonymous stuff.
    4812             :     // XXX Ignore tables for the time being (except caption)
    4813             :     const uint32_t kCaptionCtorFlags =
    4814          20 :       FCDATA_IS_TABLE_PART | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable);
    4815          20 :     bool caption = aDisplay->mDisplay == StyleDisplay::TableCaption;
    4816          20 :     bool suppressScrollFrame = false;
    4817          32 :     bool needScrollFrame = aDisplay->IsScrollableOverflow() &&
    4818          32 :                            !propagatedScrollToViewport;
    4819          20 :     if (needScrollFrame) {
    4820          24 :       suppressScrollFrame = mPresShell->GetPresContext()->IsPaginated() &&
    4821          12 :                             aDisplay->IsBlockOutsideStyle() &&
    4822           0 :                             !aElement->IsInNativeAnonymousSubtree();
    4823          12 :       if (!suppressScrollFrame) {
    4824             :         static const FrameConstructionData sScrollableBlockData[2] =
    4825             :           { FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructScrollableBlock),
    4826             :             FULL_CTOR_FCDATA(kCaptionCtorFlags,
    4827             :                              &nsCSSFrameConstructor::ConstructScrollableBlock) };
    4828          12 :         return &sScrollableBlockData[caption];
    4829             :       }
    4830             : 
    4831             :       // If the scrollable frame would have propagated its scrolling to the
    4832             :       // viewport, we still want to construct a regular block rather than a
    4833             :       // scrollframe so that it paginates correctly, but we don't want to set
    4834             :       // the bit on the block that tells it to clip at paint time.
    4835           0 :       if (mPresShell->GetPresContext()->
    4836           0 :             ElementWouldPropagateScrollbarStyles(aElement)) {
    4837           0 :         suppressScrollFrame = false;
    4838             :       }
    4839             :     }
    4840             : 
    4841             :     // Handle various non-scrollable blocks.
    4842             :     static const FrameConstructionData sNonScrollableBlockData[2][2] = {
    4843             :       { FULL_CTOR_FCDATA(0,
    4844             :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock),
    4845             :         FULL_CTOR_FCDATA(kCaptionCtorFlags,
    4846             :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock) },
    4847             :       { FULL_CTOR_FCDATA(FCDATA_FORCED_NON_SCROLLABLE_BLOCK,
    4848             :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock),
    4849             :         FULL_CTOR_FCDATA(FCDATA_FORCED_NON_SCROLLABLE_BLOCK | kCaptionCtorFlags,
    4850             :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock) }
    4851             :     };
    4852           8 :     return &sNonScrollableBlockData[suppressScrollFrame][caption];
    4853             :   }
    4854             : 
    4855             :   // If this is for a <body> node and we've propagated the scroll-frame to the
    4856             :   // viewport, we need to make sure not to add another layer of scrollbars, so
    4857             :   // we use a different FCData struct without FCDATA_MAY_NEED_SCROLLFRAME.
    4858           0 :   if (propagatedScrollToViewport && aDisplay->IsScrollableOverflow()) {
    4859           0 :     if (aDisplay->mDisplay == StyleDisplay::Flex ||
    4860           0 :         aDisplay->mDisplay == StyleDisplay::WebkitBox) {
    4861             :       static const FrameConstructionData sNonScrollableFlexData =
    4862             :         FCDATA_DECL(0, NS_NewFlexContainerFrame);
    4863           0 :       return &sNonScrollableFlexData;
    4864             :     }
    4865           0 :     if (aDisplay->mDisplay == StyleDisplay::Grid) {
    4866             :       static const FrameConstructionData sNonScrollableGridData =
    4867             :         FCDATA_DECL(0, NS_NewGridContainerFrame);
    4868           0 :       return &sNonScrollableGridData;
    4869             :     }
    4870             :   }
    4871             : 
    4872             :   // NOTE: Make sure to keep this up to date with the StyleDisplay definition!
    4873             :   static const FrameConstructionDataByDisplay sDisplayData[] = {
    4874             :     FCDATA_FOR_DISPLAY(StyleDisplay::None, UNREACHABLE_FCDATA()),
    4875             :     FCDATA_FOR_DISPLAY(StyleDisplay::Block, UNREACHABLE_FCDATA()),
    4876             :     FCDATA_FOR_DISPLAY(StyleDisplay::FlowRoot, UNREACHABLE_FCDATA()),
    4877             :     // To keep the hash table small don't add inline frames (they're
    4878             :     // typically things like FONT and B), because we can quickly
    4879             :     // find them if we need to.
    4880             :     // XXXbz the "quickly" part is a bald-faced lie!
    4881             :     FCDATA_FOR_DISPLAY(StyleDisplay::Inline,
    4882             :       FULL_CTOR_FCDATA(FCDATA_IS_INLINE | FCDATA_IS_LINE_PARTICIPANT,
    4883             :                        &nsCSSFrameConstructor::ConstructInline)),
    4884             :     FCDATA_FOR_DISPLAY(StyleDisplay::InlineBlock, UNREACHABLE_FCDATA()),
    4885             :     FCDATA_FOR_DISPLAY(StyleDisplay::ListItem, UNREACHABLE_FCDATA()),
    4886             :     FCDATA_FOR_DISPLAY(StyleDisplay::Table,
    4887             :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable)),
    4888             :     FCDATA_FOR_DISPLAY(StyleDisplay::InlineTable,
    4889             :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable)),
    4890             :     // NOTE: In the unlikely event that we add another table-part here that has
    4891             :     // a desired-parent-type (& hence triggers table fixup), we'll need to also
    4892             :     // update the flexbox chunk in nsStyleContext::ApplyStyleFixups().
    4893             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableRowGroup,
    4894             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4895             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4896             :                        &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
    4897             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableColumn,
    4898             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4899             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup),
    4900             :                        &nsCSSFrameConstructor::ConstructTableCol)),
    4901             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableColumnGroup,
    4902             :       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
    4903             :                   FCDATA_SKIP_ABSPOS_PUSH |
    4904             :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4905             :                   NS_NewTableColGroupFrame)),
    4906             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableHeaderGroup,
    4907             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4908             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4909             :                        &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
    4910             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableFooterGroup,
    4911             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4912             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4913             :                        &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
    4914             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableRow,
    4915             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4916             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
    4917             :                        &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
    4918             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableCell,
    4919             :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4920             :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
    4921             :                        &nsCSSFrameConstructor::ConstructTableCell)),
    4922             :     FCDATA_FOR_DISPLAY(StyleDisplay::TableCaption, UNREACHABLE_FCDATA()),
    4923             :     FCDATA_FOR_DISPLAY(StyleDisplay::Flex,
    4924             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4925             :     FCDATA_FOR_DISPLAY(StyleDisplay::InlineFlex,
    4926             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4927             :     FCDATA_FOR_DISPLAY(StyleDisplay::Grid,
    4928             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame)),
    4929             :     FCDATA_FOR_DISPLAY(StyleDisplay::InlineGrid,
    4930             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame)),
    4931             :     FCDATA_FOR_DISPLAY(StyleDisplay::Ruby,
    4932             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT, NS_NewRubyFrame)),
    4933             :     FCDATA_FOR_DISPLAY(StyleDisplay::RubyBase,
    4934             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
    4935             :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer),
    4936             :                   NS_NewRubyBaseFrame)),
    4937             :     FCDATA_FOR_DISPLAY(StyleDisplay::RubyBaseContainer,
    4938             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
    4939             :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
    4940             :                   NS_NewRubyBaseContainerFrame)),
    4941             :     FCDATA_FOR_DISPLAY(StyleDisplay::RubyText,
    4942             :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
    4943             :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer),
    4944             :                   NS_NewRubyTextFrame)),
    4945             :     FCDATA_FOR_DISPLAY(StyleDisplay::RubyTextContainer,
    4946             :       FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
    4947             :                   NS_NewRubyTextContainerFrame)),
    4948             :     FCDATA_FOR_DISPLAY(StyleDisplay::Contents,
    4949             :       FULL_CTOR_FCDATA(FCDATA_IS_CONTENTS, nullptr/*never called*/)),
    4950             :     FCDATA_FOR_DISPLAY(StyleDisplay::WebkitBox,
    4951             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4952             :     FCDATA_FOR_DISPLAY(StyleDisplay::WebkitInlineBox,
    4953             :       FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
    4954             :   };
    4955             :   static_assert(ArrayLength(sDisplayData) == size_t(StyleDisplay::WebkitInlineBox) + 1,
    4956             :                 "Be sure to update sDisplayData if you touch StyleDisplay");
    4957             : 
    4958           0 :   MOZ_ASSERT(size_t(aDisplay->mDisplay) < ArrayLength(sDisplayData),
    4959             :              "XUL display data should have already been handled");
    4960             : 
    4961             :   // See the mDisplay fixup code in nsRuleNode::ComputeDisplayData.
    4962           0 :   MOZ_ASSERT(aDisplay->mDisplay != StyleDisplay::Contents ||
    4963             :              !aElement->IsRootOfNativeAnonymousSubtree(),
    4964             :              "display:contents on anonymous content is unsupported");
    4965             : 
    4966             :   const FrameConstructionDataByDisplay& data =
    4967           0 :     sDisplayData[size_t(aDisplay->mDisplay)];
    4968             : 
    4969           0 :   MOZ_ASSERT(data.mDisplay == aDisplay->mDisplay,
    4970             :              "Someone messed up the order in the display values");
    4971             : 
    4972           0 :   return &data.mData;
    4973             : }
    4974             : 
    4975             : nsIFrame*
    4976          12 : nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
    4977             :                                                 FrameConstructionItem&   aItem,
    4978             :                                                 nsContainerFrame*        aParentFrame,
    4979             :                                                 const nsStyleDisplay*    aDisplay,
    4980             :                                                 nsFrameItems&            aFrameItems)
    4981             : {
    4982             :   return ConstructScrollableBlockWithConstructor(aState, aItem, aParentFrame,
    4983             :                                                  aDisplay, aFrameItems,
    4984          12 :                                                  NS_NewBlockFormattingContext);
    4985             : }
    4986             : 
    4987             : nsIFrame*
    4988          12 : nsCSSFrameConstructor::ConstructScrollableBlockWithConstructor(
    4989             :   nsFrameConstructorState& aState,
    4990             :   FrameConstructionItem& aItem,
    4991             :   nsContainerFrame* aParentFrame,
    4992             :   const nsStyleDisplay* aDisplay,
    4993             :   nsFrameItems& aFrameItems,
    4994             :   BlockFrameCreationFunc aConstructor)
    4995             : {
    4996          12 :   nsIContent* const content = aItem.mContent;
    4997          12 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    4998             : 
    4999          12 :   nsContainerFrame* newFrame = nullptr;
    5000             :   RefPtr<nsStyleContext> scrolledContentStyle
    5001          24 :     = BeginBuildingScrollFrame(aState, content, styleContext,
    5002             :                                aState.GetGeometricParent(aDisplay, aParentFrame),
    5003             :                                nsCSSAnonBoxes::scrolledContent,
    5004          24 :                                false, newFrame);
    5005             : 
    5006             :   // Create our block frame
    5007             :   // pass a temporary stylecontext, the correct one will be set later
    5008          12 :   nsContainerFrame* scrolledFrame = aConstructor(mPresShell, styleContext);
    5009             : 
    5010             :   // Make sure to AddChild before we call ConstructBlock so that we
    5011             :   // end up before our descendants in fixed-pos lists as needed.
    5012          12 :   aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame);
    5013             : 
    5014          12 :   nsFrameItems blockItem;
    5015          24 :   ConstructBlock(aState, content, newFrame, newFrame, scrolledContentStyle,
    5016             :                  &scrolledFrame, blockItem,
    5017          12 :                  aDisplay->IsAbsPosContainingBlock(newFrame) ? newFrame : nullptr,
    5018          12 :                  aItem.mPendingBinding);
    5019             : 
    5020          12 :   MOZ_ASSERT(blockItem.OnlyChild() == scrolledFrame,
    5021             :              "Scrollframe's frameItems should be exactly the scrolled frame!");
    5022          12 :   FinishBuildingScrollFrame(newFrame, scrolledFrame);
    5023             : 
    5024          24 :   return newFrame;
    5025             : }
    5026             : 
    5027             : nsIFrame*
    5028           8 : nsCSSFrameConstructor::ConstructNonScrollableBlock(nsFrameConstructorState& aState,
    5029             :                                                    FrameConstructionItem&   aItem,
    5030             :                                                    nsContainerFrame*        aParentFrame,
    5031             :                                                    const nsStyleDisplay*    aDisplay,
    5032             :                                                    nsFrameItems&            aFrameItems)
    5033             : {
    5034             :   return ConstructNonScrollableBlockWithConstructor(aState, aItem, aParentFrame,
    5035             :                                                     aDisplay, aFrameItems,
    5036           8 :                                                     NS_NewBlockFrame);
    5037             : }
    5038             : 
    5039             : nsIFrame*
    5040           8 : nsCSSFrameConstructor::ConstructNonScrollableBlockWithConstructor(
    5041             :   nsFrameConstructorState& aState,
    5042             :   FrameConstructionItem& aItem,
    5043             :   nsContainerFrame* aParentFrame,
    5044             :   const nsStyleDisplay* aDisplay,
    5045             :   nsFrameItems& aFrameItems,
    5046             :   BlockFrameCreationFunc aConstructor)
    5047             : {
    5048           8 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    5049             : 
    5050             :   // We want a block formatting context root in paginated contexts for
    5051             :   // every block that would be scrollable in a non-paginated context.
    5052             :   // We mark our blocks with a bit here if this condition is true, so
    5053             :   // we can check it later in nsFrame::ApplyPaginatedOverflowClipping.
    5054             :   bool clipPaginatedOverflow =
    5055           8 :     (aItem.mFCData->mBits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) != 0;
    5056           8 :   nsFrameState flags = nsFrameState(0);
    5057          21 :   if ((aDisplay->IsAbsolutelyPositionedStyle() ||
    5058          10 :        aDisplay->IsFloatingStyle() ||
    5059          10 :        StyleDisplay::InlineBlock == aDisplay->mDisplay ||
    5060          11 :        clipPaginatedOverflow) &&
    5061           3 :       !nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
    5062           3 :     flags = NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS;
    5063           3 :     if (clipPaginatedOverflow) {
    5064           0 :       flags |= NS_BLOCK_CLIP_PAGINATED_OVERFLOW;
    5065             :     }
    5066             :   }
    5067             : 
    5068           8 :   nsContainerFrame* newFrame = aConstructor(mPresShell, styleContext);
    5069           8 :   newFrame->AddStateBits(flags);
    5070          16 :   ConstructBlock(aState, aItem.mContent,
    5071             :                  aState.GetGeometricParent(aDisplay, aParentFrame),
    5072             :                  aParentFrame, styleContext, &newFrame,
    5073             :                  aFrameItems,
    5074           8 :                  aDisplay->IsAbsPosContainingBlock(newFrame) ? newFrame : nullptr,
    5075           8 :                  aItem.mPendingBinding);
    5076           8 :   return newFrame;
    5077             : }
    5078             : 
    5079             : 
    5080             : void
    5081         583 : nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
    5082             :                                            nsIContent*              aContent,
    5083             :                                            nsContainerFrame*        aParentFrame,
    5084             :                                            nsIFrame*                aNewFrame,
    5085             :                                            bool                     aAllowCounters)
    5086             : {
    5087         583 :   NS_PRECONDITION(mUpdateCount != 0,
    5088             :                   "Should be in an update while creating frames");
    5089             : 
    5090         583 :   MOZ_ASSERT(aNewFrame, "Null frame cannot be initialized");
    5091             : 
    5092             :   // Initialize the frame
    5093         583 :   aNewFrame->Init(aContent, aParentFrame, nullptr);
    5094         583 :   aNewFrame->AddStateBits(aState.mAdditionalStateBits);
    5095             : 
    5096         583 :   if (aState.mFrameState) {
    5097             :     // Restore frame state for just the newly created frame.
    5098         120 :     RestoreFrameStateFor(aNewFrame, aState.mFrameState);
    5099             :   }
    5100             : 
    5101        1161 :   if (aAllowCounters &&
    5102         578 :       mCounterManager.AddCounterResetsAndIncrements(aNewFrame)) {
    5103           0 :     CountersDirty();
    5104             :   }
    5105         583 : }
    5106             : 
    5107             : already_AddRefed<nsStyleContext>
    5108         876 : nsCSSFrameConstructor::ResolveStyleContext(nsIFrame*         aParentFrame,
    5109             :                                            nsIContent*       aContainer,
    5110             :                                            nsIContent*       aChild,
    5111             :                                            nsFrameConstructorState* aState)
    5112             : {
    5113         876 :   MOZ_ASSERT(aContainer, "Must have parent here");
    5114             :   // XXX uncomment when bug 1089223 is fixed:
    5115             :   // MOZ_ASSERT(aContainer == aChild->GetFlattenedTreeParent());
    5116         876 :   nsStyleContext* parentStyleContext = GetDisplayContentsStyleFor(aContainer);
    5117         876 :   if (MOZ_LIKELY(!parentStyleContext)) {
    5118         876 :     aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nullptr);
    5119         876 :     if (aParentFrame) {
    5120         876 :       MOZ_ASSERT(aParentFrame->GetContent() == aContainer);
    5121             :       // Resolve the style context based on the content object and the parent
    5122             :       // style context
    5123         876 :       parentStyleContext = aParentFrame->StyleContext();
    5124             :     } else {
    5125             :       // Perhaps aParentFrame is a canvasFrame and we're replicating
    5126             :       // fixed-pos frames.
    5127             :       // XXX should we create a way to tell ConstructFrame which style
    5128             :       // context to use, and pass it the style context for the
    5129             :       // previous page's fixed-pos frame?
    5130             :     }
    5131             :   }
    5132             : 
    5133         876 :   return ResolveStyleContext(parentStyleContext, aChild, aState);
    5134             : }
    5135             : 
    5136             : already_AddRefed<nsStyleContext>
    5137           0 : nsCSSFrameConstructor::ResolveStyleContext(nsIFrame*          aParentFrame,
    5138             :                                            nsIContent*              aChild,
    5139             :                                            nsFrameConstructorState* aState)
    5140             : {
    5141           0 :   return ResolveStyleContext(aParentFrame, aChild->GetFlattenedTreeParent(), aChild, aState);
    5142             : }
    5143             : 
    5144             : already_AddRefed<nsStyleContext>
    5145         876 : nsCSSFrameConstructor::ResolveStyleContext(const InsertionPoint&    aInsertion,
    5146             :                                            nsIContent*              aChild,
    5147             :                                            nsFrameConstructorState* aState)
    5148             : {
    5149         876 :   return ResolveStyleContext(aInsertion.mParentFrame, aInsertion.mContainer,
    5150         876 :                              aChild, aState);
    5151             : }
    5152             : 
    5153             : already_AddRefed<nsStyleContext>
    5154        1063 : nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
    5155             :                                            nsIContent* aContent,
    5156             :                                            nsFrameConstructorState* aState,
    5157             :                                            Element* aOriginatingElementOrNull)
    5158             : {
    5159        1063 :   StyleSetHandle styleSet = mPresShell->StyleSet();
    5160        1063 :   aContent->OwnerDoc()->FlushPendingLinkUpdates();
    5161             : 
    5162        2126 :   RefPtr<nsStyleContext> result;
    5163        1063 :   if (aContent->IsElement()) {
    5164         882 :     auto pseudoType = aContent->AsElement()->GetPseudoElementType();
    5165         882 :     if (pseudoType == CSSPseudoElementType::NotPseudo) {
    5166         878 :       MOZ_ASSERT(!aOriginatingElementOrNull);
    5167         878 :       if (aState) {
    5168        1756 :         result = styleSet->ResolveStyleFor(aContent->AsElement(),
    5169             :                                            aParentStyleContext,
    5170             :                                            LazyComputeBehavior::Assert,
    5171         878 :                                            aState->mTreeMatchContext);
    5172             :       } else {
    5173           0 :         result = styleSet->ResolveStyleFor(aContent->AsElement(),
    5174             :                                            aParentStyleContext,
    5175           0 :                                            LazyComputeBehavior::Assert);
    5176             :       }
    5177             :     } else {
    5178           4 :       MOZ_ASSERT(aContent->IsInNativeAnonymousSubtree());
    5179           4 :       if (!aOriginatingElementOrNull) {
    5180             :         // For pseudo-implementing NAC created by JS using the ChromeOnly
    5181             :         // document.createElement(..., { pseudo: ... }) API, we find the
    5182             :         // originating element by lookup the tree until we find a non-NAC
    5183             :         // ancestor.  (These are the correct semantics for C++-generated pseudo-
    5184             :         // implementing NAC as well, but for those cases we already have a
    5185             :         // correct originating element passed in.)
    5186           0 :         MOZ_ASSERT(nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(pseudoType));
    5187             :         aOriginatingElementOrNull =
    5188           0 :           nsContentUtils::GetClosestNonNativeAnonymousAncestor(aContent->AsElement());
    5189             :       }
    5190           4 :       MOZ_ASSERT(aOriginatingElementOrNull);
    5191           8 :       result = styleSet->ResolvePseudoElementStyle(aOriginatingElementOrNull,
    5192             :                                                    pseudoType,
    5193             :                                                    aParentStyleContext,
    5194           4 :                                                    aContent->AsElement());
    5195             :     }
    5196             :   } else {
    5197         181 :     MOZ_ASSERT(!aOriginatingElementOrNull);
    5198         181 :     NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
    5199             :                  "shouldn't waste time creating style contexts for "
    5200             :                  "comments and processing instructions");
    5201         181 :     result = styleSet->ResolveStyleForText(aContent, aParentStyleContext);
    5202             :   }
    5203             : 
    5204             :   // ServoRestyleManager does not handle transitions yet, and when it does
    5205             :   // it probably won't need to track reframed style contexts to start
    5206             :   // transitions correctly.
    5207        1063 :   if (mozilla::GeckoRestyleManager* geckoRM = RestyleManager()->GetAsGecko()) {
    5208             :     GeckoRestyleManager::ReframingStyleContexts* rsc =
    5209        1063 :       geckoRM->GetReframingStyleContexts();
    5210        1063 :     if (rsc) {
    5211             :       nsStyleContext* oldStyleContext =
    5212         190 :         rsc->Get(aContent, CSSPseudoElementType::NotPseudo);
    5213         190 :       nsPresContext* presContext = mPresShell->GetPresContext();
    5214         190 :       if (oldStyleContext) {
    5215             :         GeckoRestyleManager::TryInitiatingTransition(presContext, aContent,
    5216          99 :                                                      oldStyleContext, &result);
    5217          91 :       } else if (aContent->IsElement()) {
    5218             :         presContext->TransitionManager()->
    5219          87 :           PruneCompletedTransitions(aContent->AsElement(),
    5220          87 :             CSSPseudoElementType::NotPseudo, result);
    5221             :       }
    5222             :     }
    5223             :   }
    5224             : 
    5225        2126 :   return result.forget();
    5226             : }
    5227             : 
    5228             : // MathML Mod - RBS
    5229             : void
    5230           0 : nsCSSFrameConstructor::FlushAccumulatedBlock(nsFrameConstructorState& aState,
    5231             :                                              nsIContent* aContent,
    5232             :                                              nsContainerFrame* aParentFrame,
    5233             :                                              nsFrameItems& aBlockItems,
    5234             :                                              nsFrameItems& aNewItems)
    5235             : {
    5236           0 :   if (aBlockItems.IsEmpty()) {
    5237             :     // Nothing to do
    5238           0 :     return;
    5239             :   }
    5240             : 
    5241           0 :   nsIAtom* anonPseudo = nsCSSAnonBoxes::mozMathMLAnonymousBlock;
    5242             : 
    5243             :   nsStyleContext* parentContext =
    5244             :     nsFrame::CorrectStyleParentFrame(aParentFrame,
    5245           0 :                                      anonPseudo)->StyleContext();
    5246           0 :   StyleSetHandle styleSet = mPresShell->StyleSet();
    5247           0 :   RefPtr<nsStyleContext> blockContext;
    5248             :   blockContext = styleSet->
    5249           0 :     ResolveInheritingAnonymousBoxStyle(anonPseudo, parentContext);
    5250             : 
    5251             :   // then, create a block frame that will wrap the child frames. Make it a
    5252             :   // MathML frame so that Get(Absolute/Float)ContainingBlockFor know that this
    5253             :   // is not a suitable block.
    5254             :   nsContainerFrame* blockFrame =
    5255           0 :     NS_NewMathMLmathBlockFrame(mPresShell, blockContext);
    5256           0 :   blockFrame->AddStateBits(NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS);
    5257             : 
    5258           0 :   InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
    5259           0 :   ReparentFrames(this, blockFrame, aBlockItems);
    5260             :   // abs-pos and floats are disabled in MathML children so we don't have to
    5261             :   // worry about messing up those.
    5262           0 :   blockFrame->SetInitialChildList(kPrincipalList, aBlockItems);
    5263           0 :   NS_ASSERTION(aBlockItems.IsEmpty(), "What happened?");
    5264           0 :   aBlockItems.Clear();
    5265           0 :   aNewItems.AddChild(blockFrame);
    5266             : }
    5267             : 
    5268             : // Only <math> elements can be floated or positioned.  All other MathML
    5269             : // should be in-flow.
    5270             : #define SIMPLE_MATHML_CREATE(_tag, _func)                               \
    5271             :   { &nsGkAtoms::_tag,                                                   \
    5272             :       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                         \
    5273             :                   FCDATA_FORCE_NULL_ABSPOS_CONTAINER |                  \
    5274             :                   FCDATA_WRAP_KIDS_IN_BLOCKS, _func) }
    5275             : 
    5276             : /* static */
    5277             : const nsCSSFrameConstructor::FrameConstructionData*
    5278         307 : nsCSSFrameConstructor::FindMathMLData(Element* aElement,
    5279             :                                       nsIAtom* aTag,
    5280             :                                       int32_t aNameSpaceID,
    5281             :                                       nsStyleContext* aStyleContext)
    5282             : {
    5283             :   // Make sure that we remain confined in the MathML world
    5284         307 :   if (aNameSpaceID != kNameSpaceID_MathML)
    5285         307 :     return nullptr;
    5286             : 
    5287             :   // Handle <math> specially, because it sometimes produces inlines
    5288           0 :   if (aTag == nsGkAtoms::math) {
    5289             :     // This needs to match the test in EnsureBlockDisplay in
    5290             :     // nsRuleNode.cpp.  Though the behavior here for the display:table
    5291             :     // case is pretty weird...
    5292           0 :     if (aStyleContext->StyleDisplay()->IsBlockOutsideStyle()) {
    5293             :       static const FrameConstructionData sBlockMathData =
    5294             :         FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
    5295             :                     FCDATA_WRAP_KIDS_IN_BLOCKS,
    5296             :                     NS_NewMathMLmathBlockFrame);
    5297           0 :       return &sBlockMathData;
    5298             :     }
    5299             : 
    5300             :     static const FrameConstructionData sInlineMathData =
    5301             :       FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
    5302             :                   FCDATA_IS_LINE_PARTICIPANT |
    5303             :                   FCDATA_WRAP_KIDS_IN_BLOCKS,
    5304             :                   NS_NewMathMLmathInlineFrame);
    5305           0 :     return &sInlineMathData;
    5306             :   }
    5307             : 
    5308             : 
    5309             :   static const FrameConstructionDataByTag sMathMLData[] = {
    5310             :     SIMPLE_MATHML_CREATE(annotation_, NS_NewMathMLTokenFrame),
    5311             :     SIMPLE_MATHML_CREATE(annotation_xml_, NS_NewMathMLmrowFrame),
    5312             :     SIMPLE_MATHML_CREATE(mi_, NS_NewMathMLTokenFrame),
    5313             :     SIMPLE_MATHML_CREATE(mn_, NS_NewMathMLTokenFrame),
    5314             :     SIMPLE_MATHML_CREATE(ms_, NS_NewMathMLTokenFrame),
    5315             :     SIMPLE_MATHML_CREATE(mtext_, NS_NewMathMLTokenFrame),
    5316             :     SIMPLE_MATHML_CREATE(mo_, NS_NewMathMLmoFrame),
    5317             :     SIMPLE_MATHML_CREATE(mfrac_, NS_NewMathMLmfracFrame),
    5318             :     SIMPLE_MATHML_CREATE(msup_, NS_NewMathMLmmultiscriptsFrame),
    5319             :     SIMPLE_MATHML_CREATE(msub_, NS_NewMathMLmmultiscriptsFrame),
    5320             :     SIMPLE_MATHML_CREATE(msubsup_, NS_NewMathMLmmultiscriptsFrame),
    5321             :     SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderoverFrame),
    5322             :     SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmunderoverFrame),
    5323             :     SIMPLE_MATHML_CREATE(munderover_, NS_NewMathMLmunderoverFrame),
    5324             :     SIMPLE_MATHML_CREATE(mphantom_, NS_NewMathMLmrowFrame),
    5325             :     SIMPLE_MATHML_CREATE(mpadded_, NS_NewMathMLmpaddedFrame),
    5326             :     SIMPLE_MATHML_CREATE(mspace_, NS_NewMathMLmspaceFrame),
    5327             :     SIMPLE_MATHML_CREATE(none, NS_NewMathMLmspaceFrame),
    5328             :     SIMPLE_MATHML_CREATE(mprescripts_, NS_NewMathMLmspaceFrame),
    5329             :     SIMPLE_MATHML_CREATE(mfenced_, NS_NewMathMLmfencedFrame),
    5330             :     SIMPLE_MATHML_CREATE(mmultiscripts_, NS_NewMathMLmmultiscriptsFrame),
    5331             :     SIMPLE_MATHML_CREATE(mstyle_, NS_NewMathMLmrowFrame),
    5332             :     SIMPLE_MATHML_CREATE(msqrt_, NS_NewMathMLmsqrtFrame),
    5333             :     SIMPLE_MATHML_CREATE(mroot_, NS_NewMathMLmrootFrame),
    5334             :     SIMPLE_MATHML_CREATE(maction_, NS_NewMathMLmactionFrame),
    5335             :     SIMPLE_MATHML_CREATE(mrow_, NS_NewMathMLmrowFrame),
    5336             :     SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame),
    5337             :     SIMPLE_MATHML_CREATE(menclose_, NS_NewMathMLmencloseFrame),
    5338             :     SIMPLE_MATHML_CREATE(semantics_, NS_NewMathMLsemanticsFrame)
    5339             :   };
    5340             : 
    5341           0 :   return FindDataByTag(aTag, aElement, aStyleContext, sMathMLData,
    5342           0 :                        ArrayLength(sMathMLData));
    5343             : }
    5344             : 
    5345             : 
    5346             : nsContainerFrame*
    5347          22 : nsCSSFrameConstructor::ConstructFrameWithAnonymousChild(
    5348             :                                    nsFrameConstructorState& aState,
    5349             :                                    FrameConstructionItem&   aItem,
    5350             :                                    nsContainerFrame*        aParentFrame,
    5351             :                                    nsFrameItems&            aFrameItems,
    5352             :                                    ContainerFrameCreationFunc aConstructor,
    5353             :                                    ContainerFrameCreationFunc aInnerConstructor,
    5354             :                                    nsICSSAnonBoxPseudo*     aInnerPseudo,
    5355             :                                    bool                     aCandidateRootFrame)
    5356             : {
    5357          22 :   nsIContent* const content = aItem.mContent;
    5358          22 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    5359             : 
    5360             :   // Create the outer frame:
    5361          22 :   nsContainerFrame* newFrame = aConstructor(mPresShell, styleContext);
    5362             : 
    5363          44 :   InitAndRestoreFrame(aState, content,
    5364             :                       aCandidateRootFrame ?
    5365          22 :                         aState.GetGeometricParent(styleContext->StyleDisplay(),
    5366             :                                                   aParentFrame) :
    5367             :                         aParentFrame,
    5368          22 :                       newFrame);
    5369          22 :   newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
    5370             : 
    5371             :   // Create the pseudo SC for the anonymous wrapper child as a child of the SC:
    5372          44 :   RefPtr<nsStyleContext> scForAnon;
    5373          44 :   scForAnon = mPresShell->StyleSet()->
    5374          22 :     ResolveInheritingAnonymousBoxStyle(aInnerPseudo, styleContext);
    5375             : 
    5376             :   // Create the anonymous inner wrapper frame
    5377          22 :   nsContainerFrame* innerFrame = aInnerConstructor(mPresShell, scForAnon);
    5378             : 
    5379          22 :   InitAndRestoreFrame(aState, content, newFrame, innerFrame);
    5380             : 
    5381             :   // Put the newly created frames into the right child list
    5382          22 :   SetInitialSingleChild(newFrame, innerFrame);
    5383             : 
    5384          22 :   aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame,
    5385          22 :                   aCandidateRootFrame, aCandidateRootFrame);
    5386             : 
    5387          22 :   if (!mRootElementFrame && aCandidateRootFrame) {
    5388             :     // The frame we're constructing will be the root element frame.
    5389             :     // Set mRootElementFrame before processing children.
    5390          21 :     mRootElementFrame = newFrame;
    5391             :   }
    5392             : 
    5393          22 :   nsFrameItems childItems;
    5394             : 
    5395             :   // Process children
    5396          22 :   NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
    5397             :                "nsIAnonymousContentCreator::CreateAnonymousContent should not "
    5398             :                "be implemented for frames for which we explicitly create an "
    5399             :                "anonymous child to wrap its child frames");
    5400          22 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    5401           0 :     ConstructFramesFromItemList(aState, aItem.mChildItems,
    5402           0 :                                 innerFrame, childItems);
    5403             :   } else {
    5404          22 :     ProcessChildren(aState, content, styleContext, innerFrame,
    5405          22 :                     true, childItems, false, aItem.mPendingBinding);
    5406             :   }
    5407             : 
    5408             :   // Set the inner wrapper frame's initial primary list
    5409          22 :   innerFrame->SetInitialChildList(kPrincipalList, childItems);
    5410             : 
    5411          44 :   return newFrame;
    5412             : }
    5413             : 
    5414             : nsIFrame*
    5415          22 : nsCSSFrameConstructor::ConstructOuterSVG(nsFrameConstructorState& aState,
    5416             :                                          FrameConstructionItem&   aItem,
    5417             :                                          nsContainerFrame*        aParentFrame,
    5418             :                                          const nsStyleDisplay*    aDisplay,
    5419             :                                          nsFrameItems&            aFrameItems)
    5420             : {
    5421          22 :   return ConstructFrameWithAnonymousChild(
    5422             :       aState, aItem, aParentFrame, aFrameItems,
    5423             :       NS_NewSVGOuterSVGFrame, NS_NewSVGOuterSVGAnonChildFrame,
    5424          22 :       nsCSSAnonBoxes::mozSVGOuterSVGAnonChild, true);
    5425             : }
    5426             : 
    5427             : nsIFrame*
    5428           0 : nsCSSFrameConstructor::ConstructMarker(nsFrameConstructorState& aState,
    5429             :                                        FrameConstructionItem&   aItem,
    5430             :                                        nsContainerFrame*        aParentFrame,
    5431             :                                        const nsStyleDisplay*    aDisplay,
    5432             :                                        nsFrameItems&            aFrameItems)
    5433             : {
    5434           0 :   return ConstructFrameWithAnonymousChild(
    5435             :       aState, aItem, aParentFrame, aFrameItems,
    5436             :       NS_NewSVGMarkerFrame, NS_NewSVGMarkerAnonChildFrame,
    5437           0 :       nsCSSAnonBoxes::mozSVGMarkerAnonChild, false);
    5438             : }
    5439             : 
    5440             : // Only outer <svg> elements can be floated or positioned.  All other SVG
    5441             : // should be in-flow.
    5442             : #define SIMPLE_SVG_FCDATA(_func)                                        \
    5443             :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
    5444             :               FCDATA_SKIP_ABSPOS_PUSH |                                 \
    5445             :               FCDATA_DISALLOW_GENERATED_CONTENT,  _func)
    5446             : #define SIMPLE_SVG_CREATE(_tag, _func)            \
    5447             :   { &nsGkAtoms::_tag, SIMPLE_SVG_FCDATA(_func) }
    5448             : 
    5449             : static bool
    5450         122 : IsFilterPrimitiveChildTag(const nsIAtom* aTag)
    5451             : {
    5452         244 :   return aTag == nsGkAtoms::feDistantLight ||
    5453         244 :          aTag == nsGkAtoms::fePointLight ||
    5454         244 :          aTag == nsGkAtoms::feSpotLight ||
    5455         244 :          aTag == nsGkAtoms::feFuncR ||
    5456         244 :          aTag == nsGkAtoms::feFuncG ||
    5457         244 :          aTag == nsGkAtoms::feFuncB ||
    5458         366 :          aTag == nsGkAtoms::feFuncA ||
    5459         244 :          aTag == nsGkAtoms::feMergeNode;
    5460             : }
    5461             : 
    5462             : /* static */
    5463             : const nsCSSFrameConstructor::FrameConstructionData*
    5464         307 : nsCSSFrameConstructor::FindSVGData(Element* aElement,
    5465             :                                    nsIAtom* aTag,
    5466             :                                    int32_t aNameSpaceID,
    5467             :                                    nsIFrame* aParentFrame,
    5468             :                                    bool aIsWithinSVGText,
    5469             :                                    bool aAllowsTextPathChild,
    5470             :                                    nsStyleContext* aStyleContext)
    5471             : {
    5472         307 :   if (aNameSpaceID != kNameSpaceID_SVG) {
    5473         184 :     return nullptr;
    5474             :   }
    5475             : 
    5476             :   static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
    5477             :   static const FrameConstructionData sContainerData =
    5478             :     SIMPLE_SVG_FCDATA(NS_NewSVGContainerFrame);
    5479             : 
    5480         123 :   bool parentIsSVG = aIsWithinSVGText;
    5481             :   nsIContent* parentContent =
    5482         123 :     aParentFrame ? aParentFrame->GetContent() : nullptr;
    5483             :   // XXXbz should this really be based on the XBL-resolved tag of the parent
    5484             :   // frame's content?  Should it not be based on the type of the parent frame
    5485             :   // (e.g. whether it's an SVG frame)?
    5486         123 :   if (parentContent) {
    5487             :     int32_t parentNSID;
    5488             :     nsIAtom* parentTag =
    5489             :       parentContent->OwnerDoc()->BindingManager()->
    5490         123 :         ResolveTag(parentContent, &parentNSID);
    5491             : 
    5492             :     // It's not clear whether the SVG spec intends to allow any SVG
    5493             :     // content within svg:foreignObject at all (SVG 1.1, section
    5494             :     // 23.2), but if it does, it better be svg:svg.  So given that
    5495             :     // we're allowing it, treat it as a non-SVG parent.
    5496         245 :     parentIsSVG = parentNSID == kNameSpaceID_SVG &&
    5497         122 :                   parentTag != nsGkAtoms::foreignObject;
    5498             :   }
    5499             : 
    5500         246 :   if ((aTag != nsGkAtoms::svg && !parentIsSVG) ||
    5501         369 :       (aTag == nsGkAtoms::desc || aTag == nsGkAtoms::title ||
    5502         123 :        aTag == nsGkAtoms::metadata)) {
    5503             :     // Sections 5.1 and G.4 of SVG 1.1 say that SVG elements other than
    5504             :     // svg:svg not contained within svg:svg are incorrect, although they
    5505             :     // don't seem to specify error handling.  Ignore them, since many of
    5506             :     // our frame classes can't deal.  It *may* be that the document
    5507             :     // should at that point be considered in error according to F.2, but
    5508             :     // it's hard to tell.
    5509             :     //
    5510             :     // Style mutation can't change this situation, so don't bother
    5511             :     // adding to the undisplayed content map.
    5512             :     //
    5513             :     // We don't currently handle any UI for desc/title/metadata
    5514           0 :     return &sSuppressData;
    5515             :   }
    5516             : 
    5517             :   // We don't need frames for animation elements
    5518         123 :   if (aElement->IsNodeOfType(nsINode::eANIMATION)) {
    5519           0 :     return &sSuppressData;
    5520             :   }
    5521             : 
    5522         123 :   if (aTag == nsGkAtoms::svg && !parentIsSVG) {
    5523             :     // We need outer <svg> elements to have an nsSVGOuterSVGFrame regardless
    5524             :     // of whether they fail conditional processing attributes, since various
    5525             :     // SVG frames assume that one exists.  We handle the non-rendering
    5526             :     // of failing outer <svg> element contents like <switch> statements,
    5527             :     // and do the PassesConditionalProcessingTests call in
    5528             :     // nsSVGOuterSVGFrame::Init.
    5529             :     static const FrameConstructionData sOuterSVGData =
    5530             :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructOuterSVG);
    5531           1 :     return &sOuterSVGData;
    5532             :   }
    5533             : 
    5534         122 :   if (aTag == nsGkAtoms::marker) {
    5535             :     static const FrameConstructionData sMarkerSVGData =
    5536             :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructMarker);
    5537           0 :     return &sMarkerSVGData;
    5538             :   }
    5539             : 
    5540         244 :   nsCOMPtr<SVGTests> tests(do_QueryInterface(aElement));
    5541         122 :   if (tests && !tests->PassesConditionalProcessingTests()) {
    5542             :     // Elements with failing conditional processing attributes never get
    5543             :     // rendered.  Note that this is not where we select which frame in a
    5544             :     // <switch> to render!  That happens in nsSVGSwitchFrame::PaintSVG.
    5545           0 :     if (aIsWithinSVGText) {
    5546             :       // SVGTextFrame doesn't handle conditional processing attributes,
    5547             :       // so don't create frames for descendants of <text> with failing
    5548             :       // attributes.  We need frames not to be created so that text layout
    5549             :       // is correct.
    5550           0 :       return &sSuppressData;
    5551             :     }
    5552             :     // If we're not inside <text>, create an nsSVGContainerFrame (which is a
    5553             :     // frame that doesn't render) so that paint servers can still be referenced,
    5554             :     // even if they live inside an element with failing conditional processing
    5555             :     // attributes.
    5556           0 :     return &sContainerData;
    5557             :   }
    5558             : 
    5559             :   // Ensure that a stop frame is a child of a gradient and that gradients
    5560             :   // can only have stop children.
    5561             :   bool parentIsGradient =
    5562         244 :     aParentFrame && (aParentFrame->IsSVGLinearGradientFrame() ||
    5563         244 :                      aParentFrame->IsSVGRadialGradientFrame());
    5564         122 :   bool stop = (aTag == nsGkAtoms::stop);
    5565         244 :   if ((parentIsGradient && !stop) ||
    5566         244 :       (!parentIsGradient && stop)) {
    5567           0 :     return &sSuppressData;
    5568             :   }
    5569             : 
    5570             :   // Prevent bad frame types being children of filters or parents of filter
    5571             :   // primitives.  If aParentFrame is null, we know that the frame that will
    5572             :   // be created will be an nsInlineFrame, so it can never be a filter.
    5573         122 :   bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
    5574         122 :   bool filterPrimitive = aElement->IsNodeOfType(nsINode::eFILTER);
    5575         244 :   if ((parentIsFilter && !filterPrimitive) ||
    5576         244 :       (!parentIsFilter && filterPrimitive)) {
    5577           0 :     return &sSuppressData;
    5578             :   }
    5579             : 
    5580             :   // Prevent bad frame types being children of filter primitives or parents of
    5581             :   // filter primitive children.  If aParentFrame is null, we know that the frame
    5582             :   // that will be created will be an nsInlineFrame, so it can never be a filter
    5583             :   // primitive.
    5584             :   bool parentIsFEContainerFrame =
    5585         122 :     aParentFrame && aParentFrame->IsSVGFEContainerFrame();
    5586         244 :   if ((parentIsFEContainerFrame && !IsFilterPrimitiveChildTag(aTag)) ||
    5587         244 :       (!parentIsFEContainerFrame && IsFilterPrimitiveChildTag(aTag))) {
    5588           0 :     return &sSuppressData;
    5589             :   }
    5590             : 
    5591             :   // Special cases for text/tspan/textPath, because the kind of frame
    5592             :   // they get depends on the parent frame.  We ignore 'a' elements when
    5593             :   // determining the parent, however.
    5594         122 :   if (aIsWithinSVGText) {
    5595             :     // If aIsWithinSVGText is true, then we know that the "SVG text uses
    5596             :     // CSS frames" pref was true when this SVG fragment was first constructed.
    5597             : 
    5598             :     // We don't use ConstructInline because we want different behavior
    5599             :     // for generated content.
    5600             :     static const FrameConstructionData sTSpanData =
    5601             :       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |
    5602             :                   FCDATA_SKIP_ABSPOS_PUSH |
    5603             :                   FCDATA_DISALLOW_GENERATED_CONTENT |
    5604             :                   FCDATA_IS_LINE_PARTICIPANT |
    5605             :                   FCDATA_IS_INLINE |
    5606             :                   FCDATA_USE_CHILD_ITEMS,
    5607             :                   NS_NewInlineFrame);
    5608           0 :     if (aTag == nsGkAtoms::textPath) {
    5609           0 :       if (aAllowsTextPathChild) {
    5610           0 :         return &sTSpanData;
    5611             :       }
    5612           0 :     } else if (aTag == nsGkAtoms::tspan ||
    5613           0 :                aTag == nsGkAtoms::a) {
    5614           0 :       return &sTSpanData;
    5615             :     }
    5616           0 :     return &sSuppressData;
    5617         122 :   } else if (aTag == nsGkAtoms::text) {
    5618             :     static const FrameConstructionData sTextData =
    5619             :       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_DISALLOW_OUT_OF_FLOW |
    5620             :                                  FCDATA_ALLOW_BLOCK_STYLES,
    5621             :                                  NS_NewSVGTextFrame,
    5622             :                                  nsCSSAnonBoxes::mozSVGText);
    5623           0 :     return &sTextData;
    5624         244 :   } else if (aTag == nsGkAtoms::tspan ||
    5625         122 :              aTag == nsGkAtoms::textPath) {
    5626           0 :     return &sSuppressData;
    5627             :   }
    5628             : 
    5629             :   static const FrameConstructionDataByTag sSVGData[] = {
    5630             :     SIMPLE_SVG_CREATE(svg, NS_NewSVGInnerSVGFrame),
    5631             :     SIMPLE_SVG_CREATE(g, NS_NewSVGGFrame),
    5632             :     SIMPLE_SVG_CREATE(svgSwitch, NS_NewSVGSwitchFrame),
    5633             :     SIMPLE_SVG_CREATE(symbol, NS_NewSVGSymbolFrame),
    5634             :     SIMPLE_SVG_CREATE(polygon, NS_NewSVGGeometryFrame),
    5635             :     SIMPLE_SVG_CREATE(polyline, NS_NewSVGGeometryFrame),
    5636             :     SIMPLE_SVG_CREATE(circle, NS_NewSVGGeometryFrame),
    5637             :     SIMPLE_SVG_CREATE(ellipse, NS_NewSVGGeometryFrame),
    5638             :     SIMPLE_SVG_CREATE(line, NS_NewSVGGeometryFrame),
    5639             :     SIMPLE_SVG_CREATE(rect, NS_NewSVGGeometryFrame),
    5640             :     SIMPLE_SVG_CREATE(path, NS_NewSVGGeometryFrame),
    5641             :     SIMPLE_SVG_CREATE(defs, NS_NewSVGContainerFrame),
    5642             :     SIMPLE_SVG_CREATE(generic_, NS_NewSVGGenericContainerFrame),
    5643             :     { &nsGkAtoms::foreignObject,
    5644             :       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_DISALLOW_OUT_OF_FLOW,
    5645             :                                  NS_NewSVGForeignObjectFrame,
    5646             :                                  nsCSSAnonBoxes::mozSVGForeignContent) },
    5647             :     SIMPLE_SVG_CREATE(a, NS_NewSVGAFrame),
    5648             :     SIMPLE_SVG_CREATE(linearGradient, NS_NewSVGLinearGradientFrame),
    5649             :     SIMPLE_SVG_CREATE(radialGradient, NS_NewSVGRadialGradientFrame),
    5650             :     SIMPLE_SVG_CREATE(stop, NS_NewSVGStopFrame),
    5651             :     SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame),
    5652             :     SIMPLE_SVG_CREATE(view, NS_NewSVGViewFrame),
    5653             :     SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame),
    5654             :     SIMPLE_SVG_CREATE(clipPath, NS_NewSVGClipPathFrame),
    5655             :     SIMPLE_SVG_CREATE(filter, NS_NewSVGFilterFrame),
    5656             :     SIMPLE_SVG_CREATE(pattern, NS_NewSVGPatternFrame),
    5657             :     SIMPLE_SVG_CREATE(mask, NS_NewSVGMaskFrame),
    5658             :     SIMPLE_SVG_CREATE(feDistantLight, NS_NewSVGFEUnstyledLeafFrame),
    5659             :     SIMPLE_SVG_CREATE(fePointLight, NS_NewSVGFEUnstyledLeafFrame),
    5660             :     SIMPLE_SVG_CREATE(feSpotLight, NS_NewSVGFEUnstyledLeafFrame),
    5661             :     SIMPLE_SVG_CREATE(feBlend, NS_NewSVGFELeafFrame),
    5662             :     SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGFELeafFrame),
    5663             :     SIMPLE_SVG_CREATE(feFuncR, NS_NewSVGFEUnstyledLeafFrame),
    5664             :     SIMPLE_SVG_CREATE(feFuncG, NS_NewSVGFEUnstyledLeafFrame),
    5665             :     SIMPLE_SVG_CREATE(feFuncB, NS_NewSVGFEUnstyledLeafFrame),
    5666             :     SIMPLE_SVG_CREATE(feFuncA, NS_NewSVGFEUnstyledLeafFrame),
    5667             :     SIMPLE_SVG_CREATE(feComposite, NS_NewSVGFELeafFrame),
    5668             :     SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGFEContainerFrame),
    5669             :     SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGFELeafFrame),
    5670             :     SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGFEContainerFrame),
    5671             :     SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGFELeafFrame),
    5672             :     SIMPLE_SVG_CREATE(feDropShadow, NS_NewSVGFELeafFrame),
    5673             :     SIMPLE_SVG_CREATE(feFlood, NS_NewSVGFELeafFrame),
    5674             :     SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGFELeafFrame),
    5675             :     SIMPLE_SVG_CREATE(feImage, NS_NewSVGFEImageFrame),
    5676             :     SIMPLE_SVG_CREATE(feMerge, NS_NewSVGFEContainerFrame),
    5677             :     SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGFEUnstyledLeafFrame),
    5678             :     SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGFELeafFrame),
    5679             :     SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame),
    5680             :     SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame),
    5681             :     SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame),
    5682             :     SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame)
    5683             :   };
    5684             : 
    5685             :   const FrameConstructionData* data =
    5686         122 :     FindDataByTag(aTag, aElement, aStyleContext, sSVGData,
    5687         244 :                   ArrayLength(sSVGData));
    5688             : 
    5689         122 :   if (!data) {
    5690           0 :     data = &sContainerData;
    5691             :   }
    5692             : 
    5693         122 :   return data;
    5694             : }
    5695             : 
    5696             : void
    5697           0 : nsCSSFrameConstructor::AddPageBreakItem(nsIContent* aContent,
    5698             :                                         FrameConstructionItemList& aItems)
    5699             : {
    5700             :   RefPtr<nsStyleContext> pseudoStyle =
    5701           0 :     mPresShell->StyleSet()->
    5702           0 :       ResolveNonInheritingAnonymousBoxStyle(nsCSSAnonBoxes::pageBreak);
    5703             : 
    5704           0 :   MOZ_ASSERT(pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block,
    5705             :              "Unexpected display");
    5706             : 
    5707             :   static const FrameConstructionData sPageBreakData =
    5708             :     FCDATA_DECL(FCDATA_SKIP_FRAMESET, NS_NewPageBreakFrame);
    5709             : 
    5710             :   // Lie about the tag and namespace so we don't trigger anything
    5711             :   // interesting during frame construction.
    5712           0 :   aItems.AppendItem(&sPageBreakData, aContent, nsCSSAnonBoxes::pageBreak,
    5713           0 :                     kNameSpaceID_None, nullptr, pseudoStyle.forget(),
    5714           0 :                     true, nullptr);
    5715           0 : }
    5716             : 
    5717             : bool
    5718         884 : nsCSSFrameConstructor::ShouldCreateItemsForChild(nsFrameConstructorState& aState,
    5719             :                                                  nsIContent* aContent,
    5720             :                                                  nsContainerFrame* aParentFrame)
    5721             : {
    5722         884 :   aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
    5723         884 :   if (aContent->IsElement() && !aContent->IsStyledByServo()) {
    5724             :     // We can't just remove our pending restyle flags, since we may
    5725             :     // have restyle-later-siblings set on us.  But we _can_ remove the
    5726             :     // "is possible restyle root" flags, and need to.  Otherwise we can
    5727             :     // end up with stale such flags (e.g. if we used to have a
    5728             :     // display:none parent when our last restyle was posted and
    5729             :     // processed and now no longer do).
    5730         695 :     aContent->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS &
    5731         695 :                          ~ELEMENT_PENDING_RESTYLE_FLAGS);
    5732             :   }
    5733             : 
    5734             :   // XXX the GetContent() != aContent check is needed due to bug 135040.
    5735             :   // Remove it once that's fixed.
    5736        1768 :   if (aContent->GetPrimaryFrame() &&
    5737         884 :       aContent->GetPrimaryFrame()->GetContent() == aContent &&
    5738           0 :       !aState.mCreatingExtraFrames) {
    5739           0 :     NS_ERROR("asked to create frame construction item for a node that already "
    5740             :              "has a frame");
    5741           0 :     return false;
    5742             :   }
    5743             : 
    5744             :   // don't create a whitespace frame if aParent doesn't want it
    5745         884 :   if (!NeedFrameFor(aState, aParentFrame, aContent)) {
    5746           0 :     return false;
    5747             :   }
    5748             : 
    5749             :   // never create frames for comments or PIs
    5750        1760 :   if (aContent->IsNodeOfType(nsINode::eCOMMENT) ||
    5751         876 :       aContent->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
    5752           8 :     return false;
    5753             :   }
    5754             : 
    5755         876 :   return true;
    5756             : }
    5757             : 
    5758             : void
    5759         876 : nsCSSFrameConstructor::DoAddFrameConstructionItems(nsFrameConstructorState& aState,
    5760             :                                                    nsIContent* aContent,
    5761             :                                                    nsStyleContext* aStyleContext,
    5762             :                                                    bool aSuppressWhiteSpaceOptimizations,
    5763             :                                                    nsContainerFrame* aParentFrame,
    5764             :                                                    nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
    5765             :                                                    FrameConstructionItemList& aItems)
    5766             : {
    5767         876 :   uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK;
    5768         876 :   if (aParentFrame) {
    5769         876 :     if (nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
    5770           0 :       flags |= ITEM_IS_WITHIN_SVG_TEXT;
    5771             :     }
    5772         909 :     if (aParentFrame->IsBlockFrame() && aParentFrame->GetParent() &&
    5773          33 :         aParentFrame->GetParent()->IsSVGTextFrame()) {
    5774           0 :       flags |= ITEM_ALLOWS_TEXT_PATH_CHILD;
    5775             :     }
    5776             :   }
    5777         876 :   AddFrameConstructionItemsInternal(aState, aContent, aParentFrame,
    5778             :                                     aContent->NodeInfo()->NameAtom(),
    5779             :                                     aContent->GetNameSpaceID(),
    5780             :                                     aSuppressWhiteSpaceOptimizations,
    5781             :                                     aStyleContext,
    5782             :                                     flags, aAnonChildren,
    5783         876 :                                     aItems);
    5784         876 : }
    5785             : 
    5786             : void
    5787         884 : nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState,
    5788             :                                                  nsIContent* aContent,
    5789             :                                                  bool aSuppressWhiteSpaceOptimizations,
    5790             :                                                  const InsertionPoint& aInsertion,
    5791             :                                                  FrameConstructionItemList& aItems)
    5792             : {
    5793         884 :   nsContainerFrame* parentFrame = aInsertion.mParentFrame;
    5794         884 :   if (!ShouldCreateItemsForChild(aState, aContent, parentFrame)) {
    5795           8 :     return;
    5796             :   }
    5797             :   RefPtr<nsStyleContext> styleContext =
    5798        1752 :     ResolveStyleContext(aInsertion, aContent, &aState);
    5799         876 :   DoAddFrameConstructionItems(aState, aContent, styleContext,
    5800             :                               aSuppressWhiteSpaceOptimizations, parentFrame,
    5801         876 :                               nullptr, aItems);
    5802             : }
    5803             : 
    5804             : void
    5805         294 : nsCSSFrameConstructor::SetAsUndisplayedContent(nsFrameConstructorState& aState,
    5806             :                                                FrameConstructionItemList& aList,
    5807             :                                                nsIContent* aContent,
    5808             :                                                nsStyleContext* aStyleContext,
    5809             :                                                bool aIsGeneratedContent)
    5810             : {
    5811         294 :   if (aStyleContext->GetPseudo()) {
    5812           0 :     if (aIsGeneratedContent) {
    5813           0 :       aContent->UnbindFromTree();
    5814             :     }
    5815           0 :     return;
    5816             :   }
    5817         294 :   NS_ASSERTION(!aIsGeneratedContent, "Should have had pseudo type");
    5818             : 
    5819         294 :   if (aState.mCreatingExtraFrames) {
    5820           0 :     MOZ_ASSERT(GetUndisplayedContent(aContent),
    5821             :                "should have called SetUndisplayedContent earlier");
    5822           0 :     return;
    5823             :   }
    5824         294 :   aList.AppendUndisplayedItem(aContent, aStyleContext);
    5825             : }
    5826             : 
    5827             : void
    5828         944 : nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
    5829             :                                                          nsIContent* aContent,
    5830             :                                                          nsContainerFrame* aParentFrame,
    5831             :                                                          nsIAtom* aTag,
    5832             :                                                          int32_t aNameSpaceID,
    5833             :                                                          bool aSuppressWhiteSpaceOptimizations,
    5834             :                                                          nsStyleContext* aStyleContext,
    5835             :                                                          uint32_t aFlags,
    5836             :                                                          nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
    5837             :                                                          FrameConstructionItemList& aItems)
    5838             : {
    5839         944 :   NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT) ||
    5840             :                   aContent->IsElement(),
    5841             :                   "Shouldn't get anything else here!");
    5842         944 :   MOZ_ASSERT(!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames ||
    5843             :              aContent->NodeInfo()->NameAtom() == nsGkAtoms::area);
    5844             : 
    5845             :   // The following code allows the user to specify the base tag
    5846             :   // of an element using XBL.  XUL and HTML objects (like boxes, menus, etc.)
    5847             :   // can then be extended arbitrarily.
    5848         944 :   const nsStyleDisplay* display = aStyleContext->StyleDisplay();
    5849        1436 :   RefPtr<nsStyleContext> styleContext(aStyleContext);
    5850         944 :   PendingBinding* pendingBinding = nullptr;
    5851         944 :   if (aFlags & ITEM_ALLOW_XBL_BASE) {
    5852         938 :     if (display->mBinding) {
    5853             :       // Ensure that our XBL bindings are installed.
    5854             : 
    5855         332 :       nsXBLService* xblService = nsXBLService::GetInstance();
    5856         332 :       if (!xblService)
    5857           0 :         return;
    5858             : 
    5859             :       bool resolveStyle;
    5860             : 
    5861         664 :       nsAutoPtr<PendingBinding> newPendingBinding(new PendingBinding());
    5862             : 
    5863         996 :       nsresult rv = xblService->LoadBindings(
    5864         332 :         aContent, display->mBinding->GetURI(),
    5865         332 :         display->mBinding->mExtraData->GetPrincipal(),
    5866         664 :         getter_AddRefs(newPendingBinding->mBinding), &resolveStyle);
    5867         332 :       if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED)
    5868           0 :         return;
    5869             : 
    5870         332 :       if (newPendingBinding->mBinding) {
    5871         237 :         pendingBinding = newPendingBinding;
    5872             :         // aState takes over owning newPendingBinding
    5873         237 :         aState.AddPendingBinding(newPendingBinding.forget());
    5874             :       }
    5875             : 
    5876         332 :       if (resolveStyle) {
    5877         125 :         if (aContent->IsStyledByServo()) {
    5878           0 :           Element* element = aContent->AsElement();
    5879           0 :           ServoStyleSet* styleSet = mPresShell->StyleSet()->AsServo();
    5880             : 
    5881             :           // XXX: We should have a better way to restyle ourselves.
    5882           0 :           ServoRestyleManager::ClearServoDataFromSubtree(element);
    5883           0 :           styleSet->StyleNewSubtree(element);
    5884             : 
    5885             :           // Servo's should_traverse_children() in traversal.rs skips
    5886             :           // styling descendants of elements with a -moz-binding the
    5887             :           // first time. Thus call StyleNewChildren() again.
    5888           0 :           styleSet->StyleNewChildren(element);
    5889             :           styleContext =
    5890           0 :             styleSet->ResolveStyleFor(element, nullptr, LazyComputeBehavior::Assert);
    5891             :         } else {
    5892             :           styleContext =
    5893         125 :             ResolveStyleContext(styleContext->GetParent(), aContent, &aState);
    5894             :         }
    5895             : 
    5896         125 :         display = styleContext->StyleDisplay();
    5897         125 :         aStyleContext = styleContext;
    5898             :       }
    5899             : 
    5900         332 :       aTag = mDocument->BindingManager()->ResolveTag(aContent, &aNameSpaceID);
    5901         606 :     } else if (display->mBinding.ForceGet()) {
    5902           0 :       if (aContent->IsStyledByServo()) {
    5903             :         // Servo's should_traverse_children skips styling descendants of
    5904             :         // elements with a -moz-binding value.  For -moz-binding URLs that can
    5905             :         // be resolved, we will load the binding above, which will style the
    5906             :         // children after they have been rearranged in the flattened tree.
    5907             :         // If the URL couldn't be resolved, we still need to style the children,
    5908             :         // so we do that here.
    5909           0 :         mPresShell->StyleSet()->AsServo()->StyleNewChildren(aContent->AsElement());
    5910             :       }
    5911             :     }
    5912             :   }
    5913             : 
    5914         944 :   const bool isGeneratedContent = !!(aFlags & ITEM_IS_GENERATED_CONTENT);
    5915             : 
    5916             :   // Pre-check for display "none" - if we find that, don't create
    5917             :   // any frame at all
    5918         944 :   if (StyleDisplay::None == display->mDisplay) {
    5919         294 :     SetAsUndisplayedContent(aState, aItems, aContent, styleContext, isGeneratedContent);
    5920         294 :     return;
    5921             :   }
    5922             : 
    5923         650 :   bool isText = !aContent->IsElement();
    5924             : 
    5925             :   // never create frames for non-option/optgroup kids of <select> and
    5926             :   // non-option kids of <optgroup> inside a <select>.
    5927             :   // XXXbz it's not clear how this should best work with XBL.
    5928         650 :   nsIContent *parent = aContent->GetParent();
    5929         650 :   if (parent) {
    5930             :     // Check tag first, since that check will usually fail
    5931        1300 :     if (parent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup) &&
    5932             :         // <option> is ok no matter what
    5933           0 :         !aContent->IsHTMLElement(nsGkAtoms::option) &&
    5934             :         // <optgroup> is OK in <select> but not in <optgroup>
    5935           0 :         (!aContent->IsHTMLElement(nsGkAtoms::optgroup) ||
    5936         650 :          !parent->IsHTMLElement(nsGkAtoms::select)) &&
    5937             :         // Allow native anonymous content no matter what
    5938           0 :         !aContent->IsRootOfNativeAnonymousSubtree()) {
    5939             :       // No frame for aContent
    5940           0 :       if (!isText) {
    5941           0 :         SetAsUndisplayedContent(aState, aItems, aContent, styleContext,
    5942           0 :                                 isGeneratedContent);
    5943             :       }
    5944           0 :       return;
    5945             :     }
    5946             :   }
    5947             : 
    5948             :   // When constructing a child of a non-open <details>, create only the frame
    5949             :   // for the main <summary> element, and skip other elements.  This only applies
    5950             :   // to things that are not roots of native anonymous subtrees (except for
    5951             :   // ::before and ::after); we always want to create "internal" anonymous
    5952             :   // content.
    5953         650 :   auto* details = HTMLDetailsElement::FromContentOrNull(parent);
    5954         650 :   if (details && !details->Open() &&
    5955           0 :       (!aContent->IsRootOfNativeAnonymousSubtree() ||
    5956           0 :        aContent->IsGeneratedContentContainerForBefore() ||
    5957           0 :        aContent->IsGeneratedContentContainerForAfter())) {
    5958           0 :     auto* summary = HTMLSummaryElement::FromContentOrNull(aContent);
    5959           0 :     if (!summary || !summary->IsMainSummary()) {
    5960           0 :       SetAsUndisplayedContent(aState, aItems, aContent, styleContext,
    5961           0 :                               isGeneratedContent);
    5962           0 :       return;
    5963             :     }
    5964             :   }
    5965             : 
    5966         650 :   bool isPopup = false;
    5967             :   // Try to find frame construction data for this content
    5968             :   const FrameConstructionData* data;
    5969         650 :   if (isText) {
    5970         181 :     data = FindTextData(aParentFrame);
    5971         181 :     if (!data) {
    5972             :       // Nothing to do here; suppressed text inside SVG
    5973         158 :       return;
    5974             :     }
    5975             :   } else {
    5976         469 :     Element* element = aContent->AsElement();
    5977             : 
    5978             :     // Don't create frames for non-SVG element children of SVG elements.
    5979         469 :     if (aNameSpaceID != kNameSpaceID_SVG &&
    5980         346 :         ((aParentFrame &&
    5981         346 :           IsFrameForSVG(aParentFrame) &&
    5982         346 :           !aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)) ||
    5983         346 :          (aFlags & ITEM_IS_WITHIN_SVG_TEXT))) {
    5984           0 :       SetAsUndisplayedContent(aState, aItems, element, styleContext,
    5985           0 :                               isGeneratedContent);
    5986           0 :       return;
    5987             :     }
    5988             : 
    5989         469 :     data = FindHTMLData(element, aTag, aNameSpaceID, aParentFrame,
    5990         469 :                         styleContext);
    5991         469 :     if (!data) {
    5992         463 :       data = FindXULTagData(element, aTag, aNameSpaceID, styleContext);
    5993             :     }
    5994         469 :     if (!data) {
    5995         307 :       data = FindMathMLData(element, aTag, aNameSpaceID, styleContext);
    5996             :     }
    5997         469 :     if (!data) {
    5998         921 :       data = FindSVGData(element, aTag, aNameSpaceID, aParentFrame,
    5999         307 :                          aFlags & ITEM_IS_WITHIN_SVG_TEXT,
    6000         307 :                          aFlags & ITEM_ALLOWS_TEXT_PATH_CHILD,
    6001         307 :                          styleContext);
    6002             :     }
    6003             : 
    6004             :     // Now check for XUL display types
    6005         469 :     if (!data) {
    6006         184 :       data = FindXULDisplayData(display, element, styleContext);
    6007             :     }
    6008             : 
    6009             :     // And general display types
    6010         469 :     if (!data) {
    6011          20 :       data = FindDisplayData(display, element, styleContext);
    6012             :     }
    6013             : 
    6014         469 :     NS_ASSERTION(data, "Should have frame construction data now");
    6015             : 
    6016         469 :     if (data->mBits & FCDATA_SUPPRESS_FRAME) {
    6017           0 :       SetAsUndisplayedContent(aState, aItems, element, styleContext, isGeneratedContent);
    6018           0 :       return;
    6019             :     }
    6020             : 
    6021             : #ifdef MOZ_XUL
    6022         498 :     if ((data->mBits & FCDATA_IS_POPUP) &&
    6023          44 :         (!aParentFrame || // Parent is inline
    6024          44 :          !aParentFrame->IsMenuFrame())) {
    6025          30 :       if (!aState.mPopupItems.containingBlock &&
    6026           1 :           !aState.mHavePendingPopupgroup) {
    6027           0 :         SetAsUndisplayedContent(aState, aItems, element, styleContext,
    6028           0 :                                 isGeneratedContent);
    6029           0 :         return;
    6030             :       }
    6031             : 
    6032          29 :       isPopup = true;
    6033             :     }
    6034             : #endif /* MOZ_XUL */
    6035             :   }
    6036             : 
    6037         492 :   uint32_t bits = data->mBits;
    6038             : 
    6039             :   // Inside colgroups, suppress everything except columns.
    6040         492 :   if (aParentFrame && aParentFrame->IsTableColGroupFrame() &&
    6041           0 :       (!(bits & FCDATA_IS_TABLE_PART) ||
    6042           0 :        display->mDisplay != StyleDisplay::TableColumn)) {
    6043           0 :     SetAsUndisplayedContent(aState, aItems, aContent, styleContext, isGeneratedContent);
    6044           0 :     return;
    6045             :   }
    6046             : 
    6047             :   bool canHavePageBreak =
    6048         978 :     (aFlags & ITEM_ALLOW_PAGE_BREAK) && aState.mPresContext->IsPaginated() &&
    6049           0 :     !display->IsAbsolutelyPositionedStyle() &&
    6050           0 :     !(aParentFrame && aParentFrame->IsGridContainerFrame()) &&
    6051         492 :     !(bits & FCDATA_IS_TABLE_PART) && !(bits & FCDATA_IS_SVG_TEXT);
    6052             : 
    6053         492 :   if (canHavePageBreak && display->mBreakBefore) {
    6054           0 :     AddPageBreakItem(aContent, aItems);
    6055             :   }
    6056             : 
    6057         492 :   if (MOZ_UNLIKELY(bits & FCDATA_IS_CONTENTS)) {
    6058           0 :     if (!GetDisplayContentsStyleFor(aContent)) {
    6059           0 :       MOZ_ASSERT(styleContext->GetPseudo() || !isGeneratedContent,
    6060             :                  "Should have had pseudo type");
    6061           0 :       aState.mFrameManager->SetDisplayContents(aContent, styleContext);
    6062             :     } else {
    6063           0 :       aState.mFrameManager->ChangeDisplayContents(aContent, styleContext);
    6064             :     }
    6065             : 
    6066           0 :     TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
    6067           0 :     if (aState.HasAncestorFilter()) {
    6068           0 :       ancestorPusher.PushAncestorAndStyleScope(aContent->AsElement());
    6069             :     } else {
    6070           0 :       ancestorPusher.PushStyleScope(aContent->AsElement());
    6071             :     }
    6072             : 
    6073           0 :     if (aParentFrame) {
    6074           0 :       aParentFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
    6075             :     }
    6076           0 :     CreateGeneratedContentItem(aState, aParentFrame, aContent, styleContext,
    6077           0 :                                CSSPseudoElementType::before, aItems);
    6078             : 
    6079           0 :     FlattenedChildIterator iter(aContent);
    6080           0 :     for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
    6081           0 :       if (!ShouldCreateItemsForChild(aState, child, aParentFrame)) {
    6082           0 :         continue;
    6083             :       }
    6084             : 
    6085             :       // Get the parent of the content and check if it is a XBL children element
    6086             :       // (if the content is a children element then parent != aContent because the
    6087             :       // FlattenedChildIterator will transitively iterate through <xbl:children>
    6088             :       // for default content). Push the children element as an ancestor here because
    6089             :       // it does not have a frame and would not otherwise be pushed as an ancestor.
    6090           0 :       nsIContent* parent = child->GetParent();
    6091           0 :       MOZ_ASSERT(parent, "Parent must be non-null because we are iterating children.");
    6092           0 :       TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
    6093           0 :       if (parent != aContent && parent->IsElement()) {
    6094           0 :         if (aState.HasAncestorFilter()) {
    6095           0 :           ancestorPusher.PushAncestorAndStyleScope(parent->AsElement());
    6096             :         } else {
    6097           0 :           ancestorPusher.PushStyleScope(parent->AsElement());
    6098             :         }
    6099             :       }
    6100             : 
    6101             :       RefPtr<nsStyleContext> childContext =
    6102           0 :         ResolveStyleContext(styleContext, child, &aState);
    6103           0 :       DoAddFrameConstructionItems(aState, child, childContext,
    6104             :                                   aSuppressWhiteSpaceOptimizations,
    6105           0 :                                   aParentFrame, aAnonChildren, aItems);
    6106             :     }
    6107           0 :     aItems.SetParentHasNoXBLChildren(!iter.XBLInvolved());
    6108             : 
    6109           0 :     CreateGeneratedContentItem(aState, aParentFrame, aContent, styleContext,
    6110           0 :                                CSSPseudoElementType::after, aItems);
    6111           0 :     if (canHavePageBreak && display->mBreakAfter) {
    6112           0 :       AddPageBreakItem(aContent, aItems);
    6113             :     }
    6114           0 :     return;
    6115             :   }
    6116             : 
    6117         492 :   FrameConstructionItem* item = nullptr;
    6118         492 :   if (details && details->Open()) {
    6119           0 :     auto* summary = HTMLSummaryElement::FromContentOrNull(aContent);
    6120           0 :     if (summary && summary->IsMainSummary()) {
    6121             :       // If details is open, the main summary needs to be rendered as if it is
    6122             :       // the first child, so add the item to the front of the item list.
    6123           0 :       item = aItems.PrependItem(data, aContent, aTag, aNameSpaceID,
    6124           0 :                                 pendingBinding, styleContext.forget(),
    6125           0 :                                 aSuppressWhiteSpaceOptimizations, aAnonChildren);
    6126             :     }
    6127             :   }
    6128             : 
    6129         492 :   if (!item) {
    6130         984 :     item = aItems.AppendItem(data, aContent, aTag, aNameSpaceID,
    6131         984 :                              pendingBinding, styleContext.forget(),
    6132         492 :                              aSuppressWhiteSpaceOptimizations, aAnonChildren);
    6133             :   }
    6134         492 :   item->mIsText = isText;
    6135         492 :   item->mIsGeneratedContent = isGeneratedContent;
    6136         492 :   item->mIsAnonymousContentCreatorContent =
    6137         492 :     aFlags & ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT;
    6138         492 :   if (isGeneratedContent) {
    6139           6 :     NS_ADDREF(item->mContent);
    6140             :   }
    6141         492 :   item->mIsRootPopupgroup =
    6142         493 :     aNameSpaceID == kNameSpaceID_XUL && aTag == nsGkAtoms::popupgroup &&
    6143           1 :     aContent->IsRootOfNativeAnonymousSubtree();
    6144         492 :   if (item->mIsRootPopupgroup) {
    6145           1 :     aState.mHavePendingPopupgroup = true;
    6146             :   }
    6147         492 :   item->mIsPopup = isPopup;
    6148         615 :   item->mIsForSVGAElement = aNameSpaceID == kNameSpaceID_SVG &&
    6149         123 :                             aTag == nsGkAtoms::a;
    6150             : 
    6151         492 :   if (canHavePageBreak && display->mBreakAfter) {
    6152           0 :     AddPageBreakItem(aContent, aItems);
    6153             :   }
    6154             : 
    6155         492 :   if (bits & FCDATA_IS_INLINE) {
    6156             :     // To correctly set item->mIsAllInline we need to build up our child items
    6157             :     // right now.
    6158           0 :     BuildInlineChildItems(aState, *item,
    6159           0 :                           aFlags & ITEM_IS_WITHIN_SVG_TEXT,
    6160           0 :                           aFlags & ITEM_ALLOWS_TEXT_PATH_CHILD);
    6161           0 :     item->mHasInlineEnds = true;
    6162           0 :     item->mIsBlock = false;
    6163             :   } else {
    6164             :     // Compute a boolean isInline which is guaranteed to be false for blocks
    6165             :     // (but may also be false for some inlines).
    6166             :     bool isInline =
    6167             :       // Table-internal things are inline-outside if and only if they're kids of
    6168             :       // inlines, since they'll trigger construction of inline-table
    6169             :       // pseudos.
    6170         492 :       ((bits & FCDATA_IS_TABLE_PART) &&
    6171           0 :        (!aParentFrame || // No aParentFrame means inline
    6172         492 :         aParentFrame->StyleDisplay()->mDisplay == StyleDisplay::Inline)) ||
    6173             :       // Things that are inline-outside but aren't inline frames are inline
    6174        1313 :       display->IsInlineOutsideStyle() ||
    6175             :       // Popups that are certainly out of flow.
    6176         492 :       isPopup;
    6177             : 
    6178             :     // Set mIsAllInline conservatively.  It just might be that even an inline
    6179             :     // that has mIsAllInline false doesn't need an {ib} split.  So this is just
    6180             :     // an optimization to keep from doing too much work in cases when we can
    6181             :     // show that mIsAllInline is true..
    6182         990 :     item->mIsAllInline = item->mHasInlineEnds = isInline ||
    6183             :       // Figure out whether we're guaranteed this item will be out of flow.
    6184             :       // This is not a precise test, since one of our ancestor inlines might add
    6185             :       // an absolute containing block (if it's relatively positioned) when there
    6186             :       // wasn't such a containing block before.  But it's conservative in the
    6187             :       // sense that anything that will really end up as an in-flow non-inline
    6188             :       // will test false here.  In other words, if this test is true we're
    6189             :       // guaranteed to be inline; if it's false we don't know what we'll end up
    6190             :       // as.
    6191             :       //
    6192             :       // If we make this test precise, we can remove some of the code dealing
    6193             :       // with the imprecision in ConstructInline and adjust the comments on
    6194             :       // mIsAllInline and mIsBlock in the header.  And probably remove mIsBlock
    6195             :       // altogether, since then it will always be equal to !mHasInlineEnds.
    6196         312 :       (!(bits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
    6197          12 :        aState.GetGeometricParent(display, nullptr));
    6198             : 
    6199             :     // Set mIsBlock conservatively.  It's OK to set it false for some real
    6200             :     // blocks, but not OK to set it true for things that aren't blocks.  Since
    6201             :     // isOutOfFlow might be false even in cases when the frame will end up
    6202             :     // out-of-flow, we can't use it here.  But we _can_ say that the frame will
    6203             :     // for sure end up in-flow if it's not floated or absolutely positioned.
    6204        1284 :     item->mIsBlock = !isInline &&
    6205         593 :                      !display->IsAbsolutelyPositionedStyle() &&
    6206        1078 :                      !display->IsFloatingStyle() &&
    6207         293 :                      !(bits & FCDATA_IS_SVG_TEXT);
    6208             :   }
    6209             : 
    6210         492 :   if (item->mIsAllInline) {
    6211         198 :     aItems.InlineItemAdded();
    6212         294 :   } else if (item->mIsBlock) {
    6213         293 :     aItems.BlockItemAdded();
    6214             :   }
    6215             : 
    6216             :   // Our item should be treated as a line participant if we have the relevant
    6217             :   // bit and are going to be in-flow.  Note that this really only matters if
    6218             :   // our ancestor is a box or some such, so the fact that we might have an
    6219             :   // inline ancestor that might become a containing block is not relevant here.
    6220         542 :   if ((bits & FCDATA_IS_LINE_PARTICIPANT) &&
    6221          50 :       ((bits & FCDATA_DISALLOW_OUT_OF_FLOW) ||
    6222          25 :        !aState.GetGeometricParent(display, nullptr))) {
    6223          25 :     item->mIsLineParticipant = true;
    6224          25 :     aItems.LineParticipantItemAdded();
    6225             :   }
    6226             : }
    6227             : 
    6228             : static void
    6229           6 : AddGenConPseudoToFrame(nsIFrame* aOwnerFrame, nsIContent* aContent)
    6230             : {
    6231           6 :   NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aOwnerFrame),
    6232             :                "property should only be set on first continuation/ib-sibling");
    6233             : 
    6234             :   // FIXME(emilio): Remove this property, and use the frame of the generated
    6235             :   // content itself to tear the content down? It should be quite simpler.
    6236             : 
    6237             :   nsIFrame::ContentArray* value =
    6238           6 :     aOwnerFrame->GetProperty(nsIFrame::GenConProperty());
    6239           6 :   if (!value) {
    6240           4 :     value = new nsIFrame::ContentArray;
    6241           4 :     aOwnerFrame->AddProperty(nsIFrame::GenConProperty(), value);
    6242             :   }
    6243           6 :   value->AppendElement(aContent);
    6244           6 : }
    6245             : 
    6246             : /**
    6247             :  * Return true if the frame construction item pointed to by aIter will
    6248             :  * create a frame adjacent to a line boundary in the frame tree, and that
    6249             :  * line boundary is induced by a content node adjacent to the frame's
    6250             :  * content node in the content tree. The latter condition is necessary so
    6251             :  * that ContentAppended/ContentInserted/ContentRemoved can easily find any
    6252             :  * text nodes that were suppressed here.
    6253             :  */
    6254             : bool
    6255          23 : nsCSSFrameConstructor::AtLineBoundary(FCItemIterator& aIter)
    6256             : {
    6257          23 :   if (aIter.item().mSuppressWhiteSpaceOptimizations) {
    6258           0 :     return false;
    6259             :   }
    6260             : 
    6261          23 :   if (aIter.AtStart()) {
    6262          35 :     if (aIter.List()->HasLineBoundaryAtStart() &&
    6263          14 :         !aIter.item().mContent->GetPreviousSibling())
    6264          14 :       return true;
    6265             :   } else {
    6266           2 :     FCItemIterator prev = aIter;
    6267           2 :     prev.Prev();
    6268           6 :     if (prev.item().IsLineBoundary() &&
    6269           4 :         !prev.item().mSuppressWhiteSpaceOptimizations &&
    6270           2 :         aIter.item().mContent->GetPreviousSibling() == prev.item().mContent)
    6271           2 :       return true;
    6272             :   }
    6273             : 
    6274           7 :   FCItemIterator next = aIter;
    6275           7 :   next.Next();
    6276           7 :   if (next.IsDone()) {
    6277           5 :     if (aIter.List()->HasLineBoundaryAtEnd() &&
    6278           0 :         !aIter.item().mContent->GetNextSibling())
    6279           0 :       return true;
    6280             :   } else {
    6281           6 :     if (next.item().IsLineBoundary() &&
    6282           4 :         !next.item().mSuppressWhiteSpaceOptimizations &&
    6283           2 :         aIter.item().mContent->GetNextSibling() == next.item().mContent)
    6284           2 :       return true;
    6285             :   }
    6286             : 
    6287           5 :   return false;
    6288             : }
    6289             : 
    6290             : void
    6291         492 : nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState& aState,
    6292             :                                                FCItemIterator& aIter,
    6293             :                                                nsContainerFrame* aParentFrame,
    6294             :                                                nsFrameItems& aFrameItems)
    6295             : {
    6296         492 :   nsContainerFrame* adjParentFrame = aParentFrame;
    6297         492 :   FrameConstructionItem& item = aIter.item();
    6298         492 :   nsStyleContext* styleContext = item.mStyleContext;
    6299         492 :   AdjustParentFrame(&adjParentFrame, item.mFCData, styleContext);
    6300             : 
    6301         492 :   if (item.mIsText) {
    6302             :     // If this is collapsible whitespace next to a line boundary,
    6303             :     // don't create a frame. item.IsWhitespace() also sets the
    6304             :     // NS_CREATE_FRAME_IF_NON_WHITESPACE flag in the text node. (If we
    6305             :     // end up creating a frame, nsTextFrame::Init will clear the flag.)
    6306             :     // We don't do this for generated content, because some generated
    6307             :     // text content is empty text nodes that are about to be initialized.
    6308             :     // (We check mAdditionalStateBits because only the generated content
    6309             :     // container's frame construction item is marked with
    6310             :     // mIsGeneratedContent, and we might not have an aParentFrame.)
    6311             :     // We don't do it for content that may have XBL anonymous siblings,
    6312             :     // because they make it difficult to correctly create the frame
    6313             :     // due to dynamic changes.
    6314             :     // We don't do it for SVG text, since we might need to position and
    6315             :     // measure the white space glyphs due to x/y/dx/dy attributes.
    6316          64 :     if (AtLineBoundary(aIter) &&
    6317          27 :         !styleContext->StyleText()->WhiteSpaceOrNewlineIsSignificant() &&
    6318          18 :         aIter.List()->ParentHasNoXBLChildren() &&
    6319          17 :         !(aState.mAdditionalStateBits & NS_FRAME_GENERATED_CONTENT) &&
    6320          16 :         (item.mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) &&
    6321          16 :         !(item.mFCData->mBits & FCDATA_IS_SVG_TEXT) &&
    6322          39 :         !mAlwaysCreateFramesForIgnorableWhitespace &&
    6323           8 :         item.IsWhitespace(aState))
    6324          28 :       return;
    6325             : 
    6326          18 :     ConstructTextFrame(item.mFCData, aState, item.mContent,
    6327             :                        adjParentFrame, styleContext,
    6328          36 :                        aFrameItems);
    6329          18 :     return;
    6330             :   }
    6331             : 
    6332             :   // Start background loads during frame construction so that we're
    6333             :   // guaranteed that they will be started before onload fires.
    6334         469 :   styleContext->StartBackgroundImageLoads();
    6335             : 
    6336         469 :   nsFrameState savedStateBits = aState.mAdditionalStateBits;
    6337         469 :   if (item.mIsGeneratedContent) {
    6338             :     // Ensure that frames created here are all tagged with
    6339             :     // NS_FRAME_GENERATED_CONTENT.
    6340           6 :     aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
    6341             : 
    6342             :     // Note that we're not necessarily setting this property on the primary
    6343             :     // frame for the content for which this is generated content.  We might be
    6344             :     // setting it on a table pseudo-frame inserted under that instead.  That's
    6345             :     // OK, though; we just need to do the property set so that the content will
    6346             :     // get cleaned up when the frame is destroyed.
    6347           6 :     ::AddGenConPseudoToFrame(aParentFrame, item.mContent);
    6348             : 
    6349             :     // Now that we've passed ownership of item.mContent to the frame, unset
    6350             :     // our generated content flag so we don't release or unbind it ourselves.
    6351           6 :     item.mIsGeneratedContent = false;
    6352             :   }
    6353             : 
    6354             :   // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
    6355         469 :   ConstructFrameFromItemInternal(item, aState, adjParentFrame, aFrameItems);
    6356             : 
    6357         469 :   aState.mAdditionalStateBits = savedStateBits;
    6358             : }
    6359             : 
    6360             : 
    6361             : inline bool
    6362             : IsRootBoxFrame(nsIFrame *aFrame)
    6363             : {
    6364             :   return (aFrame->IsRootFrame());
    6365             : }
    6366             : 
    6367             : void
    6368           0 : nsCSSFrameConstructor::ReconstructDocElementHierarchy()
    6369             : {
    6370           0 :   Element* rootElement = mDocument->GetRootElement();
    6371           0 :   if (!rootElement) {
    6372             :     /* nothing to do */
    6373           0 :     return;
    6374             :   }
    6375             :   RecreateFramesForContent(rootElement, false, REMOVE_FOR_RECONSTRUCTION,
    6376           0 :                            nullptr);
    6377             : }
    6378             : 
    6379             : nsContainerFrame*
    6380         144 : nsCSSFrameConstructor::GetAbsoluteContainingBlock(nsIFrame* aFrame,
    6381             :                                                   ContainingBlockType aType)
    6382             : {
    6383             :   // Starting with aFrame, look for a frame that is absolutely positioned or
    6384             :   // relatively positioned (and transformed, if aType is FIXED)
    6385         928 :   for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
    6386         889 :     if (frame->IsFrameOfType(nsIFrame::eMathML)) {
    6387             :       // If it's mathml, bail out -- no absolute positioning out from inside
    6388             :       // mathml frames.  Note that we don't make this part of the loop
    6389             :       // condition because of the stuff at the end of this method...
    6390           0 :       return nullptr;
    6391             :     }
    6392             : 
    6393             :     // Look for the ICB.
    6394         889 :     if (aType == FIXED_POS) {
    6395         553 :       LayoutFrameType t = frame->Type();
    6396         553 :       if (t == LayoutFrameType::Viewport || t == LayoutFrameType::PageContent) {
    6397          84 :         return static_cast<nsContainerFrame*>(frame);
    6398             :       }
    6399             :     }
    6400             : 
    6401             :     // If the frame is positioned, we will probably return it as the containing
    6402             :     // block (see the exceptions below).  Otherwise, we'll start looking at the
    6403             :     // parent frame, unless we're dealing with a scrollframe.
    6404             :     // Scrollframes are special since they're not positioned, but their
    6405             :     // scrolledframe might be.  So, we need to check this special case to return
    6406             :     // the correct containing block (the scrolledframe) in that case.
    6407             :     // If we're looking for a fixed-pos containing block and the frame is
    6408             :     // not transformed, skip it.
    6409        1588 :     if (!frame->IsAbsPosContainingBlock() ||
    6410          28 :         (aType == FIXED_POS &&
    6411          28 :          !frame->IsFixedPosContainingBlock())) {
    6412         783 :       continue;
    6413             :     }
    6414          22 :     nsIFrame* absPosCBCandidate = frame;
    6415          22 :     LayoutFrameType type = absPosCBCandidate->Type();
    6416          22 :     if (type == LayoutFrameType::FieldSet) {
    6417           0 :       absPosCBCandidate = static_cast<nsFieldSetFrame*>(absPosCBCandidate)->GetInner();
    6418           0 :       if (!absPosCBCandidate) {
    6419           0 :         continue;
    6420             :       }
    6421           0 :       type = absPosCBCandidate->Type();
    6422             :     }
    6423          22 :     if (type == LayoutFrameType::Scroll) {
    6424           2 :       nsIScrollableFrame* scrollFrame = do_QueryFrame(absPosCBCandidate);
    6425           2 :       absPosCBCandidate = scrollFrame->GetScrolledFrame();
    6426           2 :       if (!absPosCBCandidate) {
    6427           0 :         continue;
    6428             :       }
    6429           2 :       type = absPosCBCandidate->Type();
    6430             :     }
    6431             :     // Only first continuations can be containing blocks.
    6432          22 :     absPosCBCandidate = absPosCBCandidate->FirstContinuation();
    6433             :     // Is the frame really an absolute container?
    6434          22 :     if (!absPosCBCandidate->IsAbsoluteContainer()) {
    6435           1 :       continue;
    6436             :     }
    6437             : 
    6438             :     // For tables, skip the inner frame and consider the table wrapper frame.
    6439          21 :     if (type == LayoutFrameType::Table) {
    6440           0 :       continue;
    6441             :     }
    6442             :     // For table wrapper frames, we can just return absPosCBCandidate.
    6443          21 :     MOZ_ASSERT((nsContainerFrame*)do_QueryFrame(absPosCBCandidate),
    6444             :                "abs.pos. containing block must be nsContainerFrame sub-class");
    6445          21 :     return static_cast<nsContainerFrame*>(absPosCBCandidate);
    6446             :   }
    6447             : 
    6448          39 :   MOZ_ASSERT(aType != FIXED_POS, "no ICB in this frame tree?");
    6449             : 
    6450             :   // It is possible for the search for the containing block to fail, because
    6451             :   // no absolute container can be found in the parent chain.  In those cases,
    6452             :   // we fall back to the document element's containing block.
    6453          39 :   return mHasRootAbsPosContainingBlock ? mDocElementContainingBlock : nullptr;
    6454             : }
    6455             : 
    6456             : nsContainerFrame*
    6457          79 : nsCSSFrameConstructor::GetFloatContainingBlock(nsIFrame* aFrame)
    6458             : {
    6459             :   // Starting with aFrame, look for a frame that is a float containing block.
    6460             :   // IF we hit a mathml frame, bail out; we don't allow floating out of mathml
    6461             :   // frames, because they don't seem to be able to deal.
    6462             :   // The logic here needs to match the logic in ProcessChildren()
    6463         416 :   for (nsIFrame* containingBlock = aFrame;
    6464         391 :        containingBlock &&
    6465         183 :          !ShouldSuppressFloatingOfDescendants(containingBlock);
    6466             :        containingBlock = containingBlock->GetParent()) {
    6467         144 :     if (containingBlock->IsFloatContainingBlock()) {
    6468          15 :       MOZ_ASSERT((nsContainerFrame*)do_QueryFrame(containingBlock),
    6469             :                  "float containing block must be nsContainerFrame sub-class");
    6470          15 :       return static_cast<nsContainerFrame*>(containingBlock);
    6471             :     }
    6472             :   }
    6473             : 
    6474             :   // If we didn't find a containing block, then there just isn't
    6475             :   // one.... return null
    6476          64 :   return nullptr;
    6477             : }
    6478             : 
    6479             : /**
    6480             :  * This function will check whether aContainer has :after generated content.
    6481             :  * If so, appending to it should actually insert.  The return value is the
    6482             :  * parent to use for newly-appended content.  *aAfterFrame points to the :after
    6483             :  * frame before which appended content should go, if there is one.
    6484             :  */
    6485             : static nsContainerFrame*
    6486          41 : AdjustAppendParentForAfterContent(nsFrameManager* aFrameManager,
    6487             :                                   nsIContent* aContainer,
    6488             :                                   nsContainerFrame* aParentFrame,
    6489             :                                   nsIContent* aChild,
    6490             :                                   nsIFrame** aAfterFrame)
    6491             : {
    6492             :   // If the parent frame has any pseudo-elements or aContainer is a
    6493             :   // display:contents node then we need to walk through the child
    6494             :   // frames to find the first one that is either a ::after frame for an
    6495             :   // ancestor of aChild or a frame that is for a node later in the
    6496             :   // document than aChild and return that in aAfterFrame.
    6497         123 :   if (aParentFrame->GetProperty(nsIFrame::GenConProperty()) ||
    6498          41 :       nsLayoutUtils::HasPseudoStyle(aContainer, aParentFrame->StyleContext(),
    6499             :                                     CSSPseudoElementType::after,
    6500          82 :                                     aParentFrame->PresContext()) ||
    6501          41 :       aFrameManager->GetDisplayContentsStyleFor(aContainer)) {
    6502           0 :     nsIFrame* afterFrame = nullptr;
    6503             :     nsContainerFrame* parent =
    6504           0 :       static_cast<nsContainerFrame*>(aParentFrame->LastContinuation());
    6505           0 :     bool done = false;
    6506           0 :     while (!done && parent) {
    6507             :       // Ensure that all normal flow children are on the principal child list.
    6508           0 :       parent->DrainSelfOverflowList();
    6509             : 
    6510           0 :       nsIFrame* child = parent->GetChildList(nsIFrame::kPrincipalList).LastChild();
    6511           0 :       if (child && child->IsPseudoFrame(aContainer) &&
    6512           0 :           !child->IsGeneratedContentFrame()) {
    6513             :         // Drill down into non-generated pseudo frames of aContainer.
    6514           0 :         nsContainerFrame* childAsContainer = do_QueryFrame(child);
    6515           0 :         if (childAsContainer) {
    6516           0 :           parent = nsLayoutUtils::LastContinuationWithChild(childAsContainer);
    6517           0 :           continue;
    6518             :         }
    6519             :       }
    6520             : 
    6521           0 :       for (; child; child = child->GetPrevSibling()) {
    6522           0 :         nsIContent* c = child->GetContent();
    6523           0 :         if (child->IsGeneratedContentFrame()) {
    6524           0 :           nsIContent* p = c->GetParent();
    6525           0 :           if (c->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter) {
    6526           0 :             if (!nsContentUtils::ContentIsDescendantOf(aChild, p) &&
    6527           0 :                 p != aContainer &&
    6528           0 :                 nsContentUtils::PositionIsBefore(p, aChild)) {
    6529             :               // ::after generated content for content earlier in the doc and not
    6530             :               // for an ancestor.  "p != aContainer" may seem redundant but it
    6531             :               // checks if the ::after belongs to the XBL insertion point we're
    6532             :               // inserting aChild into (in which case ContentIsDescendantOf is
    6533             :               // false even though p == aContainer).
    6534             :               // See layout/reftests/bugs/482592-1a.xhtml for an example of that.
    6535           0 :               done = true;
    6536           0 :               break;
    6537             :             }
    6538           0 :           } else if (nsContentUtils::PositionIsBefore(p, aChild)) {
    6539             :             // Non-::after generated content for content earlier in the doc.
    6540           0 :             done = true;
    6541           0 :             break;
    6542             :           }
    6543           0 :         } else if (nsContentUtils::PositionIsBefore(c, aChild)) {
    6544             :           // Content is before aChild.
    6545           0 :           done = true;
    6546           0 :           break;
    6547             :         }
    6548           0 :         afterFrame = child;
    6549             :       }
    6550             : 
    6551           0 :       parent = static_cast<nsContainerFrame*>(parent->GetPrevContinuation());
    6552             :     }
    6553           0 :     if (afterFrame) {
    6554           0 :       *aAfterFrame = afterFrame;
    6555           0 :       return afterFrame->GetParent();
    6556             :     }
    6557             :   }
    6558             : 
    6559          41 :   *aAfterFrame = nullptr;
    6560             : 
    6561          41 :   if (IsFramePartOfIBSplit(aParentFrame)) {
    6562             :     // We might be in a situation where the last part of the {ib} split was
    6563             :     // empty.  Since we have no ::after pseudo-element, we do in fact want to be
    6564             :     // appending to that last part, so advance to it if needed.  Note that here
    6565             :     // aParentFrame is the result of a GetLastIBSplitSibling call, so must be
    6566             :     // either the last or next to last ib-split sibling.
    6567           0 :     nsContainerFrame* trailingInline = GetIBSplitSibling(aParentFrame);
    6568           0 :     if (trailingInline) {
    6569           0 :       aParentFrame = trailingInline;
    6570             :     }
    6571             : 
    6572             :     // Always make sure to look at the last continuation of the frame
    6573             :     // for the {ib} case, even if that continuation is empty.  We
    6574             :     // don't do this for the non-ib-split-frame case, since in the
    6575             :     // other cases appending to the last nonempty continuation is fine
    6576             :     // and in fact not doing that can confuse code that doesn't know
    6577             :     // to pull kids from continuations other than its next one.
    6578             :     aParentFrame =
    6579           0 :       static_cast<nsContainerFrame*>(aParentFrame->LastContinuation());
    6580             :   }
    6581             : 
    6582          41 :   return aParentFrame;
    6583             : }
    6584             : 
    6585             : /**
    6586             :  * This function will get the previous sibling to use for an append operation.
    6587             :  * it takes a parent frame (must not be null) and its :after frame (may be
    6588             :  * null).
    6589             :  */
    6590             : static nsIFrame*
    6591          41 : FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aAfterFrame)
    6592             : {
    6593          41 :   if (aAfterFrame) {
    6594           0 :     NS_ASSERTION(aAfterFrame->GetParent() == aParentFrame, "Wrong parent");
    6595           0 :     NS_ASSERTION(aAfterFrame->GetPrevSibling() ||
    6596             :                  aParentFrame->PrincipalChildList().FirstChild() == aAfterFrame,
    6597             :                  ":after frame must be on the principal child list here");
    6598           0 :     return aAfterFrame->GetPrevSibling();
    6599             :   }
    6600             : 
    6601          41 :   aParentFrame->DrainSelfOverflowList();
    6602             : 
    6603          41 :   return aParentFrame->GetChildList(kPrincipalList).LastChild();
    6604             : }
    6605             : 
    6606             : /**
    6607             :  * This function will get the next sibling for a frame insert operation given
    6608             :  * the parent and previous sibling.  aPrevSibling may be null.
    6609             :  */
    6610             : static nsIFrame*
    6611          72 : GetInsertNextSibling(nsIFrame* aParentFrame, nsIFrame* aPrevSibling)
    6612             : {
    6613          72 :   if (aPrevSibling) {
    6614          29 :     return aPrevSibling->GetNextSibling();
    6615             :   }
    6616             : 
    6617          43 :   return aParentFrame->PrincipalChildList().FirstChild();
    6618             : }
    6619             : 
    6620             : /**
    6621             :  * This function is called by ContentAppended() and ContentInserted() when
    6622             :  * appending flowed frames to a parent's principal child list. It handles the
    6623             :  * case where the parent is the trailing inline of an {ib} split.
    6624             :  */
    6625             : void
    6626          28 : nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&       aState,
    6627             :                                             nsContainerFrame*              aParentFrame,
    6628             :                                             nsFrameItems&                  aFrameList,
    6629             :                                             nsIFrame*                      aPrevSibling,
    6630             :                                             bool                           aIsRecursiveCall)
    6631             : {
    6632          28 :   NS_PRECONDITION(!IsFramePartOfIBSplit(aParentFrame) ||
    6633             :                   !GetIBSplitSibling(aParentFrame) ||
    6634             :                   !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild(),
    6635             :                   "aParentFrame has a ib-split sibling with kids?");
    6636          28 :   NS_PRECONDITION(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame,
    6637             :                   "Parent and prevsibling don't match");
    6638             : 
    6639          28 :   nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
    6640             : 
    6641          28 :   NS_ASSERTION(nextSibling ||
    6642             :                !aParentFrame->GetNextContinuation() ||
    6643             :                !aParentFrame->GetNextContinuation()->PrincipalChildList().FirstChild() ||
    6644             :                aIsRecursiveCall,
    6645             :                "aParentFrame has later continuations with kids?");
    6646          28 :   NS_ASSERTION(nextSibling ||
    6647             :                !IsFramePartOfIBSplit(aParentFrame) ||
    6648             :                (IsInlineFrame(aParentFrame) &&
    6649             :                 !GetIBSplitSibling(aParentFrame) &&
    6650             :                 !aParentFrame->GetNextContinuation()) ||
    6651             :                aIsRecursiveCall,
    6652             :                "aParentFrame is not last?");
    6653             : 
    6654             :   // If we're inserting a list of frames at the end of the trailing inline
    6655             :   // of an {ib} split, we may need to create additional {ib} siblings to parent
    6656             :   // them.
    6657          28 :   if (!nextSibling && IsFramePartOfIBSplit(aParentFrame)) {
    6658             :     // When we get here, our frame list might start with a block.  If it does
    6659             :     // so, and aParentFrame is an inline, and it and all its previous
    6660             :     // continuations have no siblings, then put the initial blocks from the
    6661             :     // frame list into the previous block of the {ib} split.  Note that we
    6662             :     // didn't want to stop at the block part of the split when figuring out
    6663             :     // initial parent, because that could screw up float parenting; it's easier
    6664             :     // to do this little fixup here instead.
    6665           0 :     if (aFrameList.NotEmpty() && !aFrameList.FirstChild()->IsInlineOutside()) {
    6666             :       // See whether our trailing inline is empty
    6667           0 :       nsIFrame* firstContinuation = aParentFrame->FirstContinuation();
    6668           0 :       if (firstContinuation->PrincipalChildList().IsEmpty()) {
    6669             :         // Our trailing inline is empty.  Collect our starting blocks from
    6670             :         // aFrameList, get the right parent frame for them, and put them in.
    6671             :         nsFrameList::FrameLinkEnumerator firstNonBlockEnumerator =
    6672           0 :           FindFirstNonBlock(aFrameList);
    6673           0 :         nsFrameList blockKids = aFrameList.ExtractHead(firstNonBlockEnumerator);
    6674           0 :         NS_ASSERTION(blockKids.NotEmpty(), "No blocks?");
    6675             : 
    6676           0 :         nsContainerFrame* prevBlock = GetIBSplitPrevSibling(firstContinuation);
    6677           0 :         prevBlock = static_cast<nsContainerFrame*>(prevBlock->LastContinuation());
    6678           0 :         NS_ASSERTION(prevBlock, "Should have previous block here");
    6679             : 
    6680           0 :         MoveChildrenTo(aParentFrame, prevBlock, blockKids);
    6681             :       }
    6682             :     }
    6683             : 
    6684             :     // We want to put some of the frames into this inline frame.
    6685           0 :     nsFrameList::FrameLinkEnumerator firstBlockEnumerator(aFrameList);
    6686           0 :     FindFirstBlock(firstBlockEnumerator);
    6687             : 
    6688           0 :     nsFrameList inlineKids = aFrameList.ExtractHead(firstBlockEnumerator);
    6689           0 :     if (!inlineKids.IsEmpty()) {
    6690           0 :       AppendFrames(aParentFrame, kPrincipalList, inlineKids);
    6691             :     }
    6692             : 
    6693           0 :     if (!aFrameList.IsEmpty()) {
    6694           0 :       bool positioned = aParentFrame->IsRelativelyPositioned();
    6695           0 :       nsFrameItems ibSiblings;
    6696           0 :       CreateIBSiblings(aState, aParentFrame, positioned, aFrameList,
    6697           0 :                        ibSiblings);
    6698             : 
    6699             :       // Make sure to trigger reflow of the inline that used to be our
    6700             :       // last one and now isn't anymore, since its GetSkipSides() has
    6701             :       // changed.
    6702           0 :       mPresShell->FrameNeedsReflow(aParentFrame,
    6703             :                                    nsIPresShell::eTreeChange,
    6704           0 :                                    NS_FRAME_HAS_DIRTY_CHILDREN);
    6705             : 
    6706             :       // Recurse so we create new ib siblings as needed for aParentFrame's parent
    6707           0 :       return AppendFramesToParent(aState, aParentFrame->GetParent(), ibSiblings,
    6708           0 :                                    aParentFrame, true);
    6709             :     }
    6710           0 :     return;
    6711             :   }
    6712             : 
    6713             :   // Insert the frames after our aPrevSibling
    6714          28 :   InsertFrames(aParentFrame, kPrincipalList, aPrevSibling, aFrameList);
    6715             : }
    6716             : 
    6717             : #define UNSET_DISPLAY static_cast<StyleDisplay>(255)
    6718             : 
    6719             : // This gets called to see if the frames corresponding to aSibling and aContent
    6720             : // should be siblings in the frame tree. Although (1) rows and cols, (2) row
    6721             : // groups and col groups, (3) row groups and captions, (4) legends and content
    6722             : // inside fieldsets, (5) popups and other kids of the menu are siblings from a
    6723             : // content perspective, they are not considered siblings in the frame tree.
    6724             : bool
    6725          19 : nsCSSFrameConstructor::IsValidSibling(nsIFrame*              aSibling,
    6726             :                                       nsIContent*            aContent,
    6727             :                                       StyleDisplay&          aDisplay)
    6728             : {
    6729          19 :   nsIFrame* parentFrame = aSibling->GetParent();
    6730          19 :   LayoutFrameType parentType = parentFrame->Type();
    6731             : 
    6732          19 :   StyleDisplay siblingDisplay = aSibling->GetDisplay();
    6733          19 :   if (StyleDisplay::TableColumnGroup == siblingDisplay ||
    6734          19 :       StyleDisplay::TableColumn      == siblingDisplay ||
    6735          19 :       StyleDisplay::TableCaption     == siblingDisplay ||
    6736          19 :       StyleDisplay::TableHeaderGroup == siblingDisplay ||
    6737          19 :       StyleDisplay::TableRowGroup    == siblingDisplay ||
    6738          19 :       StyleDisplay::TableFooterGroup == siblingDisplay ||
    6739             :       LayoutFrameType::Menu == parentType) {
    6740             :     // if we haven't already, construct a style context to find the display type of aContent
    6741           0 :     if (UNSET_DISPLAY == aDisplay) {
    6742             :       nsIFrame* styleParent;
    6743           0 :       aSibling->GetParentStyleContext(&styleParent);
    6744           0 :       if (!styleParent) {
    6745           0 :         styleParent = aSibling->GetParent();
    6746             :       }
    6747           0 :       if (!styleParent) {
    6748           0 :         NS_NOTREACHED("Shouldn't happen");
    6749           0 :         return false;
    6750             :       }
    6751           0 :       if (aContent->IsNodeOfType(nsINode::eCOMMENT) ||
    6752           0 :           aContent->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
    6753             :         // Comments and processing instructions never have frames, so we
    6754             :         // should not try to generate style contexts for them.
    6755           0 :         return false;
    6756             :       }
    6757             :       // XXXbz when this code is killed, the state argument to
    6758             :       // ResolveStyleContext can be made non-optional.
    6759             :       RefPtr<nsStyleContext> styleContext =
    6760           0 :         ResolveStyleContext(styleParent, aContent, nullptr);
    6761           0 :       const nsStyleDisplay* display = styleContext->StyleDisplay();
    6762           0 :       aDisplay = display->mDisplay;
    6763             :     }
    6764           0 :     if (LayoutFrameType::Menu == parentType) {
    6765             :       return
    6766           0 :         (StyleDisplay::MozPopup == aDisplay) ==
    6767           0 :         (StyleDisplay::MozPopup == siblingDisplay);
    6768             :     }
    6769             :     // To have decent performance we want to return false in cases in which
    6770             :     // reordering the two siblings has no effect on display.  To ensure
    6771             :     // correctness, we MUST return false in cases where the two siblings have
    6772             :     // the same desired parent type and live on different display lists.
    6773             :     // Specificaly, columns and column groups should only consider columns and
    6774             :     // column groups as valid siblings.  Captions should only consider other
    6775             :     // captions.  All other things should consider each other as valid
    6776             :     // siblings.  The restriction in the |if| above on siblingDisplay is ok,
    6777             :     // because for correctness the only part that really needs to happen is to
    6778             :     // not consider captions, column groups, and row/header/footer groups
    6779             :     // siblings of each other.  Treating a column or colgroup as a valid
    6780             :     // sibling of a non-table-related frame will just mean we end up reframing.
    6781           0 :     if ((siblingDisplay == StyleDisplay::TableCaption) !=
    6782           0 :         (aDisplay == StyleDisplay::TableCaption)) {
    6783             :       // One's a caption and the other is not.  Not valid siblings.
    6784           0 :       return false;
    6785             :     }
    6786             : 
    6787           0 :     if ((siblingDisplay == StyleDisplay::TableColumnGroup ||
    6788           0 :          siblingDisplay == StyleDisplay::TableColumn) !=
    6789           0 :         (aDisplay == StyleDisplay::TableColumnGroup ||
    6790           0 :          aDisplay == StyleDisplay::TableColumn)) {
    6791             :       // One's a column or column group and the other is not.  Not valid
    6792             :       // siblings.
    6793           0 :       return false;
    6794             :     }
    6795             :     // Fall through; it's possible that the display type was overridden and
    6796             :     // a different sort of frame was constructed, so we may need to return false
    6797             :     // below.
    6798             :   }
    6799             : 
    6800          19 :   if (IsFrameForFieldSet(parentFrame)) {
    6801             :     // Legends can be sibling of legends but not of other content in the fieldset
    6802           0 :     if (nsContainerFrame* cif = aSibling->GetContentInsertionFrame()) {
    6803           0 :       aSibling = cif;
    6804             :     }
    6805           0 :     LayoutFrameType sibType = aSibling->Type();
    6806           0 :     bool legendContent = aContent->IsHTMLElement(nsGkAtoms::legend);
    6807             : 
    6808           0 :     if ((legendContent && (LayoutFrameType::Legend != sibType)) ||
    6809           0 :         (!legendContent && (LayoutFrameType::Legend == sibType)))
    6810           0 :       return false;
    6811             :   }
    6812             : 
    6813          19 :   return true;
    6814             : }
    6815             : 
    6816             : nsIFrame*
    6817          34 : nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent,
    6818             :                                                   nsIContent* aTargetContent,
    6819             :                                                   StyleDisplay& aTargetContentDisplay,
    6820             :                                                   nsContainerFrame* aParentFrame,
    6821             :                                                   bool aPrevSibling)
    6822             : {
    6823          34 :   nsIFrame* sibling = aContent->GetPrimaryFrame();
    6824          34 :   if (!sibling && GetDisplayContentsStyleFor(aContent)) {
    6825             :     // A display:contents node - check if it has a ::before / ::after frame...
    6826           0 :     sibling = aPrevSibling ? nsLayoutUtils::GetAfterFrame(aContent)
    6827             :                            : nsLayoutUtils::GetBeforeFrame(aContent);
    6828           0 :     if (!sibling) {
    6829             :       // ... then recurse into children ...
    6830           0 :       const bool forward = !aPrevSibling;
    6831           0 :       FlattenedChildIterator iter(aContent, forward);
    6832           0 :       sibling = aPrevSibling ?
    6833           0 :         FindPreviousSibling(iter, aTargetContent, aTargetContentDisplay, aParentFrame) :
    6834           0 :         FindNextSibling(iter, aTargetContent, aTargetContentDisplay, aParentFrame);
    6835             :     }
    6836           0 :     if (!sibling) {
    6837             :       // ... then ::after / ::before on the opposite end.
    6838           0 :       sibling = aPrevSibling ? nsLayoutUtils::GetAfterFrame(aContent)
    6839             :                              : nsLayoutUtils::GetBeforeFrame(aContent);
    6840             :     }
    6841           0 :     if (!sibling) {
    6842           0 :       return nullptr;
    6843             :     }
    6844          34 :   } else if (!sibling || sibling->GetContent() != aContent) {
    6845             :     // XXX the GetContent() != aContent check is needed due to bug 135040.
    6846             :     // Remove it once that's fixed.
    6847          15 :     return nullptr;
    6848             :   }
    6849             : 
    6850             :   // If the frame is out-of-flow, GetPrimaryFrame() will have returned the
    6851             :   // out-of-flow frame; we want the placeholder.
    6852          19 :   if (sibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    6853           0 :     nsIFrame* placeholderFrame = sibling->GetPlaceholderFrame();
    6854           0 :     NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame");
    6855           0 :     sibling = placeholderFrame;
    6856             :   }
    6857             : 
    6858             :   // The frame we have now should never be a continuation
    6859          19 :   NS_ASSERTION(!sibling->GetPrevContinuation(), "How did that happen?");
    6860             : 
    6861          19 :   if (aPrevSibling) {
    6862             :     // The frame may be a ib-split frame (a split inline frame that
    6863             :     // contains a block).  Get the last part of that split.
    6864          11 :     if (IsFramePartOfIBSplit(sibling)) {
    6865           0 :       sibling = GetLastIBSplitSibling(sibling, true);
    6866             :     }
    6867             : 
    6868             :     // The frame may have a continuation. If so, we want the last
    6869             :     // non-overflow-container continuation as our previous sibling.
    6870          11 :     sibling = sibling->GetTailContinuation();
    6871             :   }
    6872             : 
    6873          38 :   if (aTargetContent &&
    6874          19 :       !IsValidSibling(sibling, aTargetContent, aTargetContentDisplay)) {
    6875           0 :     sibling = nullptr;
    6876             :   }
    6877             : 
    6878          19 :   return sibling;
    6879             : }
    6880             : 
    6881             : nsIFrame*
    6882          33 : nsCSSFrameConstructor::FindPreviousSibling(FlattenedChildIterator aIter,
    6883             :                                            nsIContent* aTargetContent,
    6884             :                                            StyleDisplay& aTargetContentDisplay,
    6885             :                                            nsContainerFrame* aParentFrame)
    6886             : {
    6887             :   // Note: not all content objects are associated with a frame (e.g., if it's
    6888             :   // `display: none') so keep looking until we find a previous frame.
    6889          33 :   while (nsIContent* sibling = aIter.GetPreviousChild()) {
    6890          20 :     MOZ_ASSERT(sibling != aTargetContent);
    6891             :     nsIFrame* prevSibling =
    6892             :       FindFrameForContentSibling(sibling, aTargetContent, aTargetContentDisplay,
    6893          20 :                                  aParentFrame, true);
    6894          20 :     if (prevSibling) {
    6895             :       // Found a previous sibling, we're done!
    6896          11 :       return prevSibling;
    6897             :     }
    6898           9 :   }
    6899             : 
    6900          13 :   return nullptr;
    6901             : }
    6902             : 
    6903             : nsIFrame*
    6904          19 : nsCSSFrameConstructor::FindNextSibling(FlattenedChildIterator aIter,
    6905             :                                        nsIContent* aTargetContent,
    6906             :                                        StyleDisplay& aTargetContentDisplay,
    6907             :                                        nsContainerFrame* aParentFrame)
    6908             : {
    6909          19 :   while (nsIContent* sibling = aIter.GetNextChild()) {
    6910          14 :     MOZ_ASSERT(sibling != aTargetContent);
    6911             :     nsIFrame* nextSibling =
    6912             :       FindFrameForContentSibling(sibling, aTargetContent, aTargetContentDisplay,
    6913          14 :                                  aParentFrame, false);
    6914             : 
    6915          14 :     if (nextSibling) {
    6916             :       // We found a next sibling, we're done!
    6917           8 :       return nextSibling;
    6918             :     }
    6919           6 :   }
    6920             : 
    6921           5 :   return nullptr;
    6922             : }
    6923             : 
    6924             : // For fieldsets, returns the area frame, if the child is not a legend.
    6925             : static nsContainerFrame*
    6926           5 : GetAdjustedParentFrame(nsContainerFrame* aParentFrame,
    6927             :                        nsIContent* aChildContent)
    6928             : {
    6929           5 :   NS_PRECONDITION(!aParentFrame->IsTableWrapperFrame(),
    6930             :                   "Shouldn't be happening!");
    6931             : 
    6932           5 :   nsContainerFrame* newParent = nullptr;
    6933             : 
    6934           5 :   if (aParentFrame->IsFieldSetFrame()) {
    6935             :     // If the parent is a fieldSet, use the fieldSet's area frame as the
    6936             :     // parent unless the new content is a legend.
    6937           0 :     if (!aChildContent->IsHTMLElement(nsGkAtoms::legend)) {
    6938           0 :       newParent = GetFieldSetBlockFrame(aParentFrame);
    6939             :     }
    6940             :   }
    6941           5 :   return newParent ? newParent : aParentFrame;
    6942             : }
    6943             : 
    6944             : nsIFrame*
    6945          24 : nsCSSFrameConstructor::GetInsertionPrevSibling(InsertionPoint* aInsertion,
    6946             :                                                nsIContent* aChild,
    6947             :                                                bool*       aIsAppend,
    6948             :                                                bool*       aIsRangeInsertSafe,
    6949             :                                                nsIContent* aStartSkipChild,
    6950             :                                                nsIContent* aEndSkipChild)
    6951             : {
    6952          24 :   NS_PRECONDITION(aInsertion->mParentFrame, "Must have parent frame to start with");
    6953             : 
    6954          24 :   *aIsAppend = false;
    6955             : 
    6956             :   // Find the frame that precedes the insertion point. Walk backwards
    6957             :   // from the parent frame to get the parent content, because if an
    6958             :   // XBL insertion point is involved, we'll need to use _that_ to find
    6959             :   // the preceding frame.
    6960          48 :   FlattenedChildIterator iter(aInsertion->mContainer);
    6961          39 :   bool xblCase = iter.XBLInvolved() ||
    6962          39 :          aInsertion->mParentFrame->GetContent() != aInsertion->mContainer;
    6963          24 :   if (xblCase || !aChild->IsRootOfAnonymousSubtree()) {
    6964             :     // The check for IsRootOfAnonymousSubtree() is because editor is
    6965             :     // severely broken and calls us directly for native anonymous
    6966             :     // nodes that it creates.
    6967          24 :     if (aStartSkipChild) {
    6968           0 :       iter.Seek(aStartSkipChild);
    6969             :     } else {
    6970          24 :       iter.Seek(aChild);
    6971             :     }
    6972             :   } else {
    6973             :     // Prime the iterator for the call to FindPreviousSibling.
    6974           0 :     iter.GetNextChild();
    6975           0 :     MOZ_ASSERT(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode),
    6976             :                "Someone passed native anonymous content directly into frame "
    6977             :                "construction.  Stop doing that!");
    6978             :   }
    6979             : 
    6980             :   // Note that FindPreviousSibling is passed the iterator by value, so that
    6981             :   // the later usage of the iterator starts from the same place.
    6982          24 :   StyleDisplay childDisplay = UNSET_DISPLAY;
    6983             :   nsIFrame* prevSibling =
    6984          24 :     FindPreviousSibling(iter, iter.Get(), childDisplay, aInsertion->mParentFrame);
    6985             : 
    6986             :   // Now, find the geometric parent so that we can handle
    6987             :   // continuations properly. Use the prev sibling if we have it;
    6988             :   // otherwise use the next sibling.
    6989          24 :   if (prevSibling) {
    6990          11 :     aInsertion->mParentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
    6991             :   } else {
    6992             :     // If there is no previous sibling, then find the frame that follows
    6993          13 :     if (aEndSkipChild) {
    6994           0 :       iter.Seek(aEndSkipChild);
    6995           0 :       iter.GetPreviousChild();
    6996             :     }
    6997             :     nsIFrame* nextSibling =
    6998          13 :       FindNextSibling(iter, iter.Get(), childDisplay, aInsertion->mParentFrame);
    6999          13 :     if (GetDisplayContentsStyleFor(aInsertion->mContainer)) {
    7000           0 :       if (!nextSibling) {
    7001             :         // Our siblings (if any) does not have a frame to guide us.
    7002             :         // The frame for aChild should be inserted whereever a frame for
    7003             :         // the container would be inserted.  This is needed when inserting
    7004             :         // into nested display:contents nodes.
    7005           0 :         nsIContent* child = aInsertion->mContainer;
    7006           0 :         nsIContent* parent = child->GetParent();
    7007           0 :         aInsertion->mParentFrame =
    7008           0 :           ::GetAdjustedParentFrame(aInsertion->mParentFrame, parent);
    7009           0 :         InsertionPoint fakeInsertion(aInsertion->mParentFrame, parent);
    7010             :         nsIFrame* result = GetInsertionPrevSibling(&fakeInsertion, child, aIsAppend,
    7011           0 :                                                    aIsRangeInsertSafe, nullptr, nullptr);
    7012           0 :         MOZ_ASSERT(aInsertion->mParentFrame->GetContent() ==
    7013             :                    fakeInsertion.mParentFrame->GetContent());
    7014             :         // fakeInsertion.mParentFrame may now be a continuation of the frame
    7015             :         // we started with in the ctor above.
    7016           0 :         aInsertion->mParentFrame = fakeInsertion.mParentFrame;
    7017           0 :         return result;
    7018             :       }
    7019             : 
    7020           0 :       prevSibling = nextSibling->GetPrevSibling();
    7021             :     }
    7022             : 
    7023          13 :     if (nextSibling) {
    7024           8 :       aInsertion->mParentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
    7025             :     } else {
    7026             :       // No previous or next sibling, so treat this like an appended frame.
    7027           5 :       *aIsAppend = true;
    7028           5 :       if (IsFramePartOfIBSplit(aInsertion->mParentFrame)) {
    7029             :         // Since we're appending, we'll walk to the last anonymous frame
    7030             :         // that was created for the broken inline frame.  But don't walk
    7031             :         // to the trailing inline if it's empty; stop at the block.
    7032           0 :         aInsertion->mParentFrame =
    7033           0 :           GetLastIBSplitSibling(aInsertion->mParentFrame, false);
    7034             :       }
    7035             :       // Get continuation that parents the last child.  This MUST be done
    7036             :       // before the AdjustAppendParentForAfterContent call.
    7037           5 :       aInsertion->mParentFrame =
    7038           5 :         nsLayoutUtils::LastContinuationWithChild(aInsertion->mParentFrame);
    7039             :       // Deal with fieldsets
    7040           5 :       aInsertion->mParentFrame =
    7041           5 :         ::GetAdjustedParentFrame(aInsertion->mParentFrame, aChild);
    7042             :       nsIFrame* appendAfterFrame;
    7043           5 :       aInsertion->mParentFrame =
    7044           5 :         ::AdjustAppendParentForAfterContent(this, aInsertion->mContainer,
    7045             :                                             aInsertion->mParentFrame,
    7046             :                                             aChild, &appendAfterFrame);
    7047           5 :       prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, appendAfterFrame);
    7048             :     }
    7049             :   }
    7050             : 
    7051          24 :   *aIsRangeInsertSafe = (childDisplay == UNSET_DISPLAY);
    7052          24 :   return prevSibling;
    7053             : }
    7054             : 
    7055             : nsContainerFrame*
    7056         210 : nsCSSFrameConstructor::GetContentInsertionFrameFor(nsIContent* aContent)
    7057             : {
    7058             :   // Get the primary frame associated with the content
    7059         210 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    7060             : 
    7061         210 :   if (!frame) {
    7062          45 :     if (GetDisplayContentsStyleFor(aContent)) {
    7063           0 :       nsIContent* parent = aContent->GetParent();
    7064           0 :       if (parent && parent == aContent->GetContainingShadow()) {
    7065           0 :         parent = parent->GetBindingParent();
    7066             :       }
    7067           0 :       frame = parent ? GetContentInsertionFrameFor(parent) : nullptr;
    7068             :     }
    7069          45 :     if (!frame) {
    7070          45 :       return nullptr;
    7071             :     }
    7072             :   } else {
    7073             :     // If the content of the frame is not the desired content then this is not
    7074             :     // really a frame for the desired content.
    7075             :     // XXX This check is needed due to bug 135040. Remove it once that's fixed.
    7076         165 :     if (frame->GetContent() != aContent) {
    7077           0 :       return nullptr;
    7078             :     }
    7079             :   }
    7080             : 
    7081         165 :   nsContainerFrame* insertionFrame = frame->GetContentInsertionFrame();
    7082             : 
    7083         165 :   NS_ASSERTION(!insertionFrame || insertionFrame == frame || !frame->IsLeaf(),
    7084             :     "The insertion frame is the primary frame or the primary frame isn't a leaf");
    7085             : 
    7086         165 :   return insertionFrame;
    7087             : }
    7088             : 
    7089             : static bool
    7090           0 : IsSpecialFramesetChild(nsIContent* aContent)
    7091             : {
    7092             :   // IMPORTANT: This must match the conditions in nsHTMLFramesetFrame::Init.
    7093           0 :   return aContent->IsAnyOfHTMLElements(nsGkAtoms::frameset, nsGkAtoms::frame);
    7094             : }
    7095             : 
    7096             : static void
    7097             : InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node);
    7098             : 
    7099             : #ifdef MOZ_XUL
    7100             : 
    7101             : static
    7102             : bool
    7103          69 : IsXULListBox(nsIContent* aContainer)
    7104             : {
    7105          69 :   return (aContainer->IsXULElement(nsGkAtoms::listbox));
    7106             : }
    7107             : 
    7108             : static
    7109             : nsListBoxBodyFrame*
    7110          28 : MaybeGetListBoxBodyFrame(nsIContent* aContainer, nsIContent* aChild)
    7111             : {
    7112          28 :   if (!aContainer)
    7113           0 :     return nullptr;
    7114             : 
    7115          28 :   if (IsXULListBox(aContainer) &&
    7116           0 :       aChild->IsXULElement(nsGkAtoms::listitem)) {
    7117           0 :     RefPtr<nsXULElement> xulElement = nsXULElement::FromContent(aContainer);
    7118           0 :     IgnoredErrorResult ignored;
    7119           0 :     nsCOMPtr<nsIBoxObject> boxObject = xulElement->GetBoxObject(ignored);
    7120           0 :     nsCOMPtr<nsPIListBoxObject> listBoxObject = do_QueryInterface(boxObject);
    7121           0 :     if (listBoxObject) {
    7122           0 :       return listBoxObject->GetListBoxBody(false);
    7123             :     }
    7124             :   }
    7125             : 
    7126          28 :   return nullptr;
    7127             : }
    7128             : #endif // MOZ_XUL
    7129             : 
    7130             : void
    7131          43 : nsCSSFrameConstructor::AddTextItemIfNeeded(nsFrameConstructorState& aState,
    7132             :                                            const InsertionPoint& aInsertion,
    7133             :                                            nsIContent* aPossibleTextContent,
    7134             :                                            FrameConstructionItemList& aItems)
    7135             : {
    7136          43 :   NS_PRECONDITION(aPossibleTextContent, "Must have node");
    7137          43 :   if (!aPossibleTextContent->IsNodeOfType(nsINode::eTEXT) ||
    7138           0 :       !aPossibleTextContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
    7139             :     // Not text, or not suppressed due to being all-whitespace (if it
    7140             :     // were being suppressed, it would have the
    7141             :     // NS_CREATE_FRAME_IF_NON_WHITESPACE flag)
    7142          43 :     return;
    7143             :   }
    7144           0 :   NS_ASSERTION(!aPossibleTextContent->GetPrimaryFrame(),
    7145             :                "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
    7146             :   AddFrameConstructionItems(aState, aPossibleTextContent, false,
    7147           0 :                             aInsertion, aItems);
    7148             : }
    7149             : 
    7150             : void
    7151           0 : nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aParentContent,
    7152             :                                            nsIContent* aContent)
    7153             : {
    7154           0 :   if (!aContent->IsNodeOfType(nsINode::eTEXT) ||
    7155           0 :       !aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
    7156             :     // Not text, or not suppressed due to being all-whitespace (if it
    7157             :     // were being suppressed, it would have the
    7158             :     // NS_CREATE_FRAME_IF_NON_WHITESPACE flag)
    7159           0 :     return;
    7160             :   }
    7161           0 :   NS_ASSERTION(!aContent->GetPrimaryFrame(),
    7162             :                "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
    7163           0 :   ContentInserted(aParentContent, aContent, nullptr, false);
    7164             : }
    7165             : 
    7166             : // For inserts aChild should be valid, for appends it should be null.
    7167             : // Returns true if this operation can be lazy, false if not.
    7168             : bool
    7169          61 : nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
    7170             :                                             nsIContent* aContainer,
    7171             :                                             nsIContent* aChild)
    7172             : {
    7173             :   // XXXmats no lazy frames for display:contents direct descendants yet
    7174             :   // (bug 979782).
    7175         190 :   if (mPresShell->GetPresContext()->IsChrome() || !aContainer ||
    7176         163 :       aContainer->IsInNativeAnonymousSubtree() || aContainer->IsXULElement() ||
    7177          34 :       GetDisplayContentsStyleFor(aContainer)) {
    7178          27 :     return false;
    7179             :   }
    7180             : 
    7181          34 :   if (aOperation == CONTENTINSERT) {
    7182           0 :     if (aChild->IsRootOfAnonymousSubtree() ||
    7183           0 :         (aChild->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
    7184           0 :          !aChild->IsInNativeAnonymousSubtree()) ||
    7185           0 :         aChild->IsEditable() || aChild->IsXULElement()) {
    7186           0 :       return false;
    7187             :     }
    7188             :   } else { // CONTENTAPPEND
    7189          34 :     NS_ASSERTION(aOperation == CONTENTAPPEND,
    7190             :                  "operation should be either insert or append");
    7191         146 :     for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
    7192         112 :       NS_ASSERTION(!child->IsRootOfAnonymousSubtree(),
    7193             :                    "Should be coming through the CONTENTAPPEND case");
    7194         112 :       if (child->IsXULElement() || child->IsEditable()) {
    7195           0 :         return false;
    7196             :       }
    7197             :     }
    7198             :   }
    7199             : 
    7200             :   // We can construct lazily; just need to set suitable bits in the content
    7201             :   // tree.
    7202             : 
    7203             :   // Walk up the tree setting the NODE_DESCENDANTS_NEED_FRAMES bit as we go.
    7204          34 :   nsIContent* content = aContainer;
    7205             : 
    7206             : #ifdef DEBUG
    7207             :   // If we hit a node with no primary frame, or the NODE_NEEDS_FRAME bit set
    7208             :   // we want to assert, but leaf frames that process their own children and may
    7209             :   // ignore anonymous children (eg framesets) make this complicated. So we set
    7210             :   // these two booleans if we encounter these situations and unset them if we
    7211             :   // hit a node with a leaf frame.
    7212             :   //
    7213             :   // Also, it's fine if one of the nodes without primary frame is a display:
    7214             :   // contents node except if it's the direct ancestor of the children we're
    7215             :   // recreating frames for.
    7216          34 :   bool noPrimaryFrame = false;
    7217          34 :   bool needsFrameBitSet = false;
    7218             : #endif
    7219         132 :   while (content &&
    7220          40 :          !content->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
    7221             : #ifdef DEBUG
    7222          29 :     if (content->GetPrimaryFrame() && content->GetPrimaryFrame()->IsLeaf()) {
    7223           0 :       noPrimaryFrame = needsFrameBitSet = false;
    7224             :     }
    7225          29 :     if (!noPrimaryFrame && !content->GetPrimaryFrame() &&
    7226           0 :         !GetDisplayContentsStyleFor(content)) {
    7227           0 :       noPrimaryFrame = true;
    7228             :     }
    7229          29 :     if (!needsFrameBitSet && content->HasFlag(NODE_NEEDS_FRAME)) {
    7230           0 :       needsFrameBitSet = true;
    7231             :     }
    7232             : #endif
    7233          29 :     content->SetFlags(NODE_DESCENDANTS_NEED_FRAMES);
    7234          29 :     content = content->GetFlattenedTreeParent();
    7235             :   }
    7236             : #ifdef DEBUG
    7237          45 :   if (content && content->GetPrimaryFrame() &&
    7238          11 :       content->GetPrimaryFrame()->IsLeaf()) {
    7239           0 :     noPrimaryFrame = needsFrameBitSet = false;
    7240             :   }
    7241          34 :   NS_ASSERTION(!noPrimaryFrame, "Ancestors of nodes with frames to be "
    7242             :     "constructed lazily should have frames");
    7243          34 :   NS_ASSERTION(!needsFrameBitSet, "Ancestors of nodes with frames to be "
    7244             :     "constructed lazily should not have NEEDS_FRAME bit set");
    7245             : #endif
    7246             : 
    7247             :   // Set NODE_NEEDS_FRAME on the new nodes.
    7248          34 :   if (aOperation == CONTENTINSERT) {
    7249           0 :     NS_ASSERTION(!aChild->GetPrimaryFrame() ||
    7250             :                  aChild->GetPrimaryFrame()->GetContent() != aChild,
    7251             :                  //XXX the aChild->GetPrimaryFrame()->GetContent() != aChild
    7252             :                  // check is needed due to bug 135040. Remove it once that's
    7253             :                  // fixed.
    7254             :                  "setting NEEDS_FRAME on a node that already has a frame?");
    7255           0 :     aChild->SetFlags(NODE_NEEDS_FRAME);
    7256             :   } else { // CONTENTAPPEND
    7257         146 :     for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
    7258         112 :       NS_ASSERTION(!child->GetPrimaryFrame() ||
    7259             :                    child->GetPrimaryFrame()->GetContent() != child,
    7260             :                    //XXX the child->GetPrimaryFrame()->GetContent() != child
    7261             :                    // check is needed due to bug 135040. Remove it once that's
    7262             :                    // fixed.
    7263             :                    "setting NEEDS_FRAME on a node that already has a frame?");
    7264         112 :       child->SetFlags(NODE_NEEDS_FRAME);
    7265             :     }
    7266             :   }
    7267             : 
    7268          34 :   if (mozilla::GeckoRestyleManager* geckoRM = RestyleManager()->GetAsGecko()) {
    7269          34 :     geckoRM->PostRestyleEventForLazyConstruction();
    7270             :   }
    7271             : 
    7272          34 :   return true;
    7273             : }
    7274             : 
    7275             : void
    7276          29 : nsCSSFrameConstructor::CreateNeededFrames(
    7277             :     nsIContent* aContent,
    7278             :     TreeMatchContext& aTreeMatchContext)
    7279             : {
    7280          29 :   MOZ_ASSERT(!aContent->IsStyledByServo());
    7281          29 :   NS_ASSERTION(!aContent->HasFlag(NODE_NEEDS_FRAME),
    7282             :     "shouldn't get here with a content node that has needs frame bit set");
    7283          29 :   NS_ASSERTION(aContent->HasFlag(NODE_DESCENDANTS_NEED_FRAMES),
    7284             :     "should only get here with a content node that has descendants needing frames");
    7285          29 :   MOZ_ASSERT(aTreeMatchContext.mAncestorFilter.HasFilter(),
    7286             :              "The whole point of having the tree match context is optimizing "
    7287             :              "the ancestor filter usage!");
    7288             : 
    7289          29 :   aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
    7290             : 
    7291             :   // We could either descend first (on nodes that don't have NODE_NEEDS_FRAME
    7292             :   // set) or issue content notifications for our kids first. In absence of
    7293             :   // anything definitive either way we'll go with the latter.
    7294             : 
    7295             :   // It might be better to use GetChildArray and scan it completely first and
    7296             :   // then issue all notifications. (We have to scan it completely first because
    7297             :   // constructing frames can set attributes, which can change the storage of
    7298             :   // child lists).
    7299             : 
    7300             :   // Scan the children of aContent to see what operations (if any) we need to
    7301             :   // perform.
    7302          29 :   uint32_t childCount = aContent->GetChildCount();
    7303          29 :   bool inRun = false;
    7304          29 :   nsIContent* firstChildInRun = nullptr;
    7305         186 :   for (uint32_t i = 0; i < childCount; i++) {
    7306         157 :     nsIContent* child = aContent->GetChildAt(i);
    7307         157 :     if (child->HasFlag(NODE_NEEDS_FRAME)) {
    7308         111 :       NS_ASSERTION(!child->GetPrimaryFrame() ||
    7309             :                    child->GetPrimaryFrame()->GetContent() != child,
    7310             :                    //XXX the child->GetPrimaryFrame()->GetContent() != child
    7311             :                    // check is needed due to bug 135040. Remove it once that's
    7312             :                    // fixed.
    7313             :                    "NEEDS_FRAME set on a node that already has a frame?");
    7314         111 :       if (!inRun) {
    7315          27 :         inRun = true;
    7316          27 :         firstChildInRun = child;
    7317             :       }
    7318             :     } else {
    7319          46 :       if (inRun) {
    7320           0 :         inRun = false;
    7321             :         // generate a ContentRangeInserted for [startOfRun,i)
    7322             :         ContentRangeInserted(aContent, firstChildInRun, child, nullptr,
    7323             :                              false, // aAllowLazyConstruction
    7324             :                              true,  // aForReconstruction
    7325           0 :                              &aTreeMatchContext);
    7326             :       }
    7327             :     }
    7328             :   }
    7329             : 
    7330          29 :   if (inRun) {
    7331             :     ContentAppended(aContent, firstChildInRun,
    7332             :                     false, // aAllowLazyConstruction
    7333             :                     true,  // aForReconstruction
    7334          27 :                     &aTreeMatchContext);
    7335             :   }
    7336             : 
    7337             :   // Now descend.
    7338          58 :   FlattenedChildIterator iter(aContent);
    7339         186 :   for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
    7340         157 :     if (child->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
    7341             :       TreeMatchContext::AutoAncestorPusher insertionPointPusher(
    7342          12 :           &aTreeMatchContext);
    7343             : 
    7344             :       // Handle stuff like xbl:children.
    7345           6 :       if (child->GetParent() != aContent && child->GetParent()->IsElement()) {
    7346           0 :         insertionPointPusher.PushAncestorAndStyleScope(
    7347           0 :             child->GetParent()->AsElement());
    7348             :       }
    7349             : 
    7350          12 :       TreeMatchContext::AutoAncestorPusher pusher(&aTreeMatchContext);
    7351           6 :       pusher.PushAncestorAndStyleScope(child);
    7352             : 
    7353           6 :       CreateNeededFrames(child, aTreeMatchContext);
    7354             :     }
    7355             :   }
    7356          29 : }
    7357             : 
    7358             : void
    7359         291 : nsCSSFrameConstructor::CreateNeededFrames()
    7360             : {
    7361         291 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
    7362             :                "Someone forgot a script blocker");
    7363             : 
    7364         291 :   Element* rootElement = mDocument->GetRootElement();
    7365         291 :   NS_ASSERTION(!rootElement || !rootElement->HasFlag(NODE_NEEDS_FRAME),
    7366             :     "root element should not have frame created lazily");
    7367         291 :   if (rootElement && rootElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
    7368          23 :     BeginUpdate();
    7369             :     TreeMatchContext treeMatchContext(
    7370          46 :         mDocument, TreeMatchContext::ForFrameConstruction);
    7371          23 :     treeMatchContext.InitAncestors(rootElement);
    7372          23 :     CreateNeededFrames(rootElement, treeMatchContext);
    7373          23 :     EndUpdate();
    7374             :   }
    7375         291 : }
    7376             : 
    7377             : void
    7378           5 : nsCSSFrameConstructor::IssueSingleInsertNofications(nsIContent* aContainer,
    7379             :                                                     nsIContent* aStartChild,
    7380             :                                                     nsIContent* aEndChild,
    7381             :                                                     bool aAllowLazyConstruction,
    7382             :                                                     bool aForReconstruction)
    7383             : {
    7384          10 :   for (nsIContent* child = aStartChild;
    7385          10 :        child != aEndChild;
    7386           5 :        child = child->GetNextSibling()) {
    7387          20 :     if ((child->GetPrimaryFrame() || GetUndisplayedContent(child) ||
    7388           5 :          GetDisplayContentsStyleFor(child))
    7389             : #ifdef MOZ_XUL
    7390             :         //  Except listboxes suck, so do NOT skip anything here if
    7391             :         //  we plan to notify a listbox.
    7392           5 :         && !MaybeGetListBoxBodyFrame(aContainer, child)
    7393             : #endif
    7394             :         ) {
    7395             :       // Already have a frame or undisplayed entry for this content; a
    7396             :       // previous ContentRangeInserted in this loop must have reconstructed
    7397             :       // its insertion parent.  Skip it.
    7398           0 :       continue;
    7399             :     }
    7400             :     // Call ContentRangeInserted with this node.
    7401           5 :     ContentRangeInserted(aContainer, child, child->GetNextSibling(),
    7402             :                          mTempFrameTreeState, aAllowLazyConstruction,
    7403           5 :                          aForReconstruction, nullptr);
    7404             :   }
    7405           5 : }
    7406             : 
    7407             : nsCSSFrameConstructor::InsertionPoint
    7408          41 : nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aContainer,
    7409             :                                               nsIContent* aStartChild,
    7410             :                                               nsIContent* aEndChild,
    7411             :                                               bool aAllowLazyConstruction,
    7412             :                                               bool aForReconstruction)
    7413             : {
    7414             :   // See if we have an XBL insertion point. If so, then that's our
    7415             :   // real parent frame; if not, then the frame hasn't been built yet
    7416             :   // and we just bail.
    7417          41 :   InsertionPoint insertionPoint = GetInsertionPoint(aContainer, nullptr);
    7418          41 :   if (!insertionPoint.mParentFrame && !insertionPoint.mMultiple) {
    7419           0 :     return insertionPoint; // Don't build the frames.
    7420             :   }
    7421             : 
    7422          41 :   bool hasInsertion = false;
    7423          41 :   if (!insertionPoint.mMultiple) {
    7424             :     // XXXbz XBL2/sXBL issue
    7425          37 :     nsIDocument* document = aStartChild->GetComposedDoc();
    7426             :     // XXXbz how would |document| be null here?
    7427          37 :     if (document && aStartChild->GetXBLInsertionParent()) {
    7428           1 :       hasInsertion = true;
    7429             :     }
    7430             :   }
    7431             : 
    7432          41 :   if (insertionPoint.mMultiple || hasInsertion) {
    7433             :     // We have an insertion point.  There are some additional tests we need to do
    7434             :     // in order to ensure that an append is a safe operation.
    7435           5 :     uint32_t childCount = 0;
    7436             : 
    7437           5 :     if (!insertionPoint.mMultiple) {
    7438             :       // We may need to make multiple ContentInserted calls instead.  A
    7439             :       // reasonable heuristic to employ (in order to maintain good performance)
    7440             :       // is to find out if the insertion point's content node contains any
    7441             :       // explicit children.  If it does not, then it is highly likely that
    7442             :       // an append is occurring.  (Note it is not definite, and there are insane
    7443             :       // cases we will not deal with by employing this heuristic, but it beats
    7444             :       // always falling back to multiple ContentInserted calls).
    7445             :       //
    7446             :       // In the multiple insertion point case, we know we're going to need to do
    7447             :       // multiple ContentInserted calls anyway.
    7448             :       // XXXndeakin This test doesn't work in the new world. Or rather, it works, but
    7449             :       // it's slow
    7450           1 :       childCount = insertionPoint.mParentFrame->GetContent()->GetChildCount();
    7451             :     }
    7452             : 
    7453             :     // If we have multiple insertion points or if we have an insertion point
    7454             :     // and the operation is not a true append or if the insertion point already
    7455             :     // has explicit children, then we must fall back.
    7456           5 :     if (insertionPoint.mMultiple || aEndChild != nullptr || childCount > 0) {
    7457             :       // Now comes the fun part.  For each inserted child, make a
    7458             :       // ContentInserted call as if it had just gotten inserted and
    7459             :       // let ContentInserted handle the mess.
    7460           5 :       IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
    7461           5 :                                    aAllowLazyConstruction, aForReconstruction);
    7462           5 :       insertionPoint.mParentFrame = nullptr;
    7463             :     }
    7464             :   }
    7465             : 
    7466          41 :   return insertionPoint;
    7467             : }
    7468             : 
    7469             : bool
    7470          60 : nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
    7471             :                                                 nsIContent* aStartChild,
    7472             :                                                 nsIContent* aEndChild)
    7473             : {
    7474          60 :   if (aParentFrame->IsFrameSetFrame()) {
    7475             :     // Check whether we have any kids we care about.
    7476           0 :     for (nsIContent* cur = aStartChild;
    7477           0 :          cur != aEndChild;
    7478           0 :          cur = cur->GetNextSibling()) {
    7479           0 :       if (IsSpecialFramesetChild(cur)) {
    7480             :         // Just reframe the parent, since framesets are weird like that.
    7481           0 :         RecreateFramesForContent(aParentFrame->GetContent(), false,
    7482           0 :                                  REMOVE_FOR_RECONSTRUCTION, nullptr);
    7483           0 :         return true;
    7484             :       }
    7485             :     }
    7486             :   }
    7487          60 :   return false;
    7488             : }
    7489             : 
    7490             : void
    7491           0 : nsCSSFrameConstructor::LazilyStyleNewChildRange(nsIContent* aStartChild,
    7492             :                                                 nsIContent* aEndChild)
    7493             : {
    7494           0 :   for (nsIContent* child = aStartChild; child != aEndChild;
    7495           0 :        child = child->GetNextSibling()) {
    7496           0 :     nsINode* parent = child->GetFlattenedTreeParent();
    7497           0 :     if (MOZ_LIKELY(parent) && parent->IsElement()) {
    7498           0 :       parent->AsElement()->NoteDirtyDescendantsForServo();
    7499             :     }
    7500             :   }
    7501           0 : }
    7502             : 
    7503             : void
    7504           0 : nsCSSFrameConstructor::StyleNewChildRange(nsIContent* aStartChild,
    7505             :                                           nsIContent* aEndChild)
    7506             : {
    7507           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet()->AsServo();
    7508             : 
    7509           0 :   for (nsIContent* child = aStartChild; child != aEndChild;
    7510           0 :        child = child->GetNextSibling()) {
    7511             :     // Calling StyleNewChildren on one child will end up styling another child,
    7512             :     // if they share the same flattened tree parent.  So we check HasServoData()
    7513             :     // to avoid a wasteful call to GetFlattenedTreeParent (on the child) and
    7514             :     // StyleNewChildren (on the flattened tree parent) when we detect we've
    7515             :     // already handled that parent.  In the common case of inserting elements
    7516             :     // into a container that does not have an XBL binding or shadow tree with
    7517             :     // distributed children, this boils down to a single call to
    7518             :     // GetFlattenedTreeParent/StyleNewChildren, and traversing the list of
    7519             :     // children checking HasServoData (which is fast).
    7520           0 :     if (child->IsElement() && !child->AsElement()->HasServoData()) {
    7521           0 :       Element* parent = child->AsElement()->GetFlattenedTreeParentElement();
    7522             :       // NB: Parent may be null if the content is appended to a shadow root, and
    7523             :       // isn't assigned to any insertion point.
    7524           0 :       if (MOZ_LIKELY(parent) && parent->HasServoData()) {
    7525           0 :         styleSet->StyleNewChildren(parent);
    7526             :       }
    7527             :     }
    7528             :   }
    7529           0 : }
    7530             : 
    7531             : void
    7532           0 : nsCSSFrameConstructor::StyleChildRangeForReconstruct(nsIContent* aStartChild,
    7533             :                                                      nsIContent* aEndChild)
    7534             : {
    7535           0 :   ServoStyleSet* styleSet = mPresShell->StyleSet()->AsServo();
    7536             : 
    7537             :   // We take a parallelism hit here, since we don't have a great API to pass
    7538             :   // a range of elements to style to Servo.
    7539           0 :   for (nsIContent* child = aStartChild; child != aEndChild;
    7540           0 :        child = child->GetNextSibling()) {
    7541           0 :     if (child->IsElement()) {
    7542           0 :       styleSet->StyleSubtreeForReconstruct(child->AsElement());
    7543             :     }
    7544             :   }
    7545           0 : }
    7546             : 
    7547             : void
    7548          83 : nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
    7549             :                                        nsIContent* aFirstNewContent,
    7550             :                                        bool aAllowLazyConstruction,
    7551             :                                        bool aForReconstruction,
    7552             :                                        TreeMatchContext* aProvidedTreeMatchContext)
    7553             : {
    7554          83 :   MOZ_ASSERT(!aProvidedTreeMatchContext || !aAllowLazyConstruction);
    7555          83 :   MOZ_ASSERT(!aAllowLazyConstruction || !RestyleManager()->IsInStyleRefresh());
    7556             : 
    7557         119 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    7558          83 :   NS_PRECONDITION(mUpdateCount != 0,
    7559             :                   "Should be in an update while creating frames");
    7560             : 
    7561             : #ifdef DEBUG
    7562          83 :   if (gNoisyContentUpdates) {
    7563           0 :     printf("nsCSSFrameConstructor::ContentAppended container=%p "
    7564             :            "first-child=%p lazy=%d\n",
    7565             :            static_cast<void*>(aContainer), aFirstNewContent,
    7566           0 :            aAllowLazyConstruction);
    7567           0 :     if (gReallyNoisyContentUpdates && aContainer) {
    7568           0 :       aContainer->List(stdout, 0);
    7569             :     }
    7570             :   }
    7571             : #endif
    7572             : 
    7573             : #ifdef DEBUG
    7574         351 :   for (nsIContent* child = aFirstNewContent;
    7575         351 :        child;
    7576         268 :        child = child->GetNextSibling()) {
    7577             :     // XXX the GetContent() != child check is needed due to bug 135040.
    7578             :     // Remove it once that's fixed.
    7579         268 :     NS_ASSERTION(!child->GetPrimaryFrame() ||
    7580             :                  child->GetPrimaryFrame()->GetContent() != child,
    7581             :                  "asked to construct a frame for a node that already has a frame");
    7582             :   }
    7583             : #endif
    7584             : 
    7585             : #ifdef MOZ_XUL
    7586          83 :   if (aContainer) {
    7587             :     int32_t namespaceID;
    7588             :     nsIAtom* tag =
    7589          83 :       mDocument->BindingManager()->ResolveTag(aContainer, &namespaceID);
    7590             : 
    7591             :     // Just ignore tree tags, anyway we don't create any frames for them.
    7592         166 :     if (tag == nsGkAtoms::treechildren ||
    7593         166 :         tag == nsGkAtoms::treeitem ||
    7594          83 :         tag == nsGkAtoms::treerow)
    7595           0 :       return;
    7596             :   }
    7597             : #endif // MOZ_XUL
    7598             : 
    7599             :   // The frame constructor uses this codepath both for bonafide newly-added
    7600             :   // content and for RestyleManager-driven frame construction (RECONSTRUCT_FRAME
    7601             :   // and lazy frame construction). If we're using the Servo style system, we
    7602             :   // want to ensure that styles get resolved in the first case, whereas for the
    7603             :   // second case they should have already been resolved if needed.
    7604          83 :   bool isNewlyAddedContentForServo = aContainer->IsStyledByServo() &&
    7605          83 :                                      !aForReconstruction;
    7606             : 
    7607             :   bool isNewShadowTreeContent =
    7608          83 :     aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
    7609          83 :     !aContainer->IsInNativeAnonymousSubtree() &&
    7610          83 :     !aFirstNewContent->IsInNativeAnonymousSubtree();
    7611             : 
    7612          83 :   if (!isNewShadowTreeContent) {
    7613             :     // See comment in ContentRangeInserted for why this is necessary.
    7614          91 :     if (!GetContentInsertionFrameFor(aContainer) &&
    7615           8 :         !aContainer->IsActiveChildrenElement()) {
    7616             :       // We're punting on frame construction because there's no container frame.
    7617             :       // The Servo-backed style system handles this case like the lazy frame
    7618             :       // construction case.
    7619           8 :       if (isNewlyAddedContentForServo) {
    7620           0 :         LazilyStyleNewChildRange(aFirstNewContent, nullptr);
    7621             :       }
    7622           8 :       return;
    7623             :     }
    7624             : 
    7625         123 :     if (aAllowLazyConstruction &&
    7626          48 :         MaybeConstructLazily(CONTENTAPPEND, aContainer, aFirstNewContent)) {
    7627          34 :       if (isNewlyAddedContentForServo) {
    7628           0 :         LazilyStyleNewChildRange(aFirstNewContent, nullptr);
    7629             :       }
    7630          34 :       return;
    7631             :     }
    7632             :   }
    7633             : 
    7634             :   // We couldn't construct lazily. Make Servo eagerly traverse the new content.
    7635          41 :   if (aContainer->IsStyledByServo()) {
    7636           0 :     if (aForReconstruction) {
    7637           0 :       StyleChildRangeForReconstruct(aFirstNewContent, nullptr);
    7638             :     } else {
    7639           0 :       StyleNewChildRange(aFirstNewContent, nullptr);
    7640             :     }
    7641             :   }
    7642             : 
    7643          41 :   if (isNewShadowTreeContent) {
    7644             :     // Recreate frames if content is appended into a ShadowRoot
    7645             :     // because children of ShadowRoot are rendered in place of children
    7646             :     // of the host.
    7647             :     //XXXsmaug This is super unefficient!
    7648           0 :     nsIContent* bindingParent = aContainer->GetBindingParent();
    7649           0 :     LAYOUT_PHASE_TEMP_EXIT();
    7650             :     RecreateFramesForContent(bindingParent, false,
    7651           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
    7652           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7653           0 :     return;
    7654             :   }
    7655             : 
    7656          41 :   LAYOUT_PHASE_TEMP_EXIT();
    7657             :   InsertionPoint insertion =
    7658             :     GetRangeInsertionPoint(aContainer, aFirstNewContent, nullptr,
    7659          41 :                            aAllowLazyConstruction, aForReconstruction);
    7660          41 :   nsContainerFrame*& parentFrame = insertion.mParentFrame;
    7661          41 :   LAYOUT_PHASE_TEMP_REENTER();
    7662          41 :   if (!parentFrame) {
    7663           5 :     return;
    7664             :   }
    7665             : 
    7666          36 :   LAYOUT_PHASE_TEMP_EXIT();
    7667          36 :   if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) {
    7668           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7669           0 :     return;
    7670             :   }
    7671          36 :   LAYOUT_PHASE_TEMP_REENTER();
    7672             : 
    7673          36 :   if (parentFrame->IsLeaf()) {
    7674             :     // Nothing to do here; we shouldn't be constructing kids of leaves
    7675             :     // Clear lazy bits so we don't try to construct again.
    7676           0 :     ClearLazyBits(aFirstNewContent, nullptr);
    7677           0 :     return;
    7678             :   }
    7679             : 
    7680          36 :   if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) {
    7681           0 :     LAYOUT_PHASE_TEMP_EXIT();
    7682           0 :     RecreateFramesForContent(parentFrame->GetContent(), false,
    7683           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
    7684           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7685           0 :     return;
    7686             :   }
    7687             : 
    7688             :   // If the frame we are manipulating is a ib-split frame (that is, one
    7689             :   // that's been created as a result of a block-in-inline situation) then we
    7690             :   // need to append to the last ib-split sibling, not to the frame itself.
    7691          36 :   bool parentIBSplit = IsFramePartOfIBSplit(parentFrame);
    7692          36 :   if (parentIBSplit) {
    7693             : #ifdef DEBUG
    7694           0 :     if (gNoisyContentUpdates) {
    7695           0 :       printf("nsCSSFrameConstructor::ContentAppended: parentFrame=");
    7696           0 :       nsFrame::ListTag(stdout, parentFrame);
    7697           0 :       printf(" is ib-split\n");
    7698             :     }
    7699             : #endif
    7700             : 
    7701             :     // Since we're appending, we'll walk to the last anonymous frame
    7702             :     // that was created for the broken inline frame.  But don't walk
    7703             :     // to the trailing inline if it's empty; stop at the block.
    7704           0 :     parentFrame = GetLastIBSplitSibling(parentFrame, false);
    7705             :   }
    7706             : 
    7707             :   // Get continuation that parents the last child.  This MUST be done
    7708             :   // before the AdjustAppendParentForAfterContent call.
    7709          36 :   parentFrame = nsLayoutUtils::LastContinuationWithChild(parentFrame);
    7710             : 
    7711             :   // We should never get here with fieldsets or details, since they have
    7712             :   // multiple insertion points.
    7713          36 :   MOZ_ASSERT(!parentFrame->IsFieldSetFrame() && !parentFrame->IsDetailsFrame(),
    7714             :              "Parent frame should not be fieldset or details!");
    7715             : 
    7716             :   // Deal with possible :after generated content on the parent
    7717             :   nsIFrame* parentAfterFrame;
    7718          36 :   parentFrame =
    7719          36 :     ::AdjustAppendParentForAfterContent(this, insertion.mContainer, parentFrame,
    7720             :                                         aFirstNewContent, &parentAfterFrame);
    7721             : 
    7722             :   // Create some new frames
    7723             :   //
    7724             :   // We use the provided tree match context, or create a new one on the fly
    7725             :   // otherwise.
    7726          72 :   Maybe<TreeMatchContext> matchContext;
    7727          36 :   if (!aProvidedTreeMatchContext && !aContainer->IsStyledByServo()) {
    7728           9 :     matchContext.emplace(mDocument, TreeMatchContext::ForFrameConstruction);
    7729           9 :     matchContext->InitAncestors(aContainer->AsElement());
    7730             :   }
    7731             :   nsFrameConstructorState state(mPresShell,
    7732             :                                 matchContext.ptrOr(aProvidedTreeMatchContext),
    7733             :                                 GetAbsoluteContainingBlock(parentFrame, FIXED_POS),
    7734             :                                 GetAbsoluteContainingBlock(parentFrame, ABS_POS),
    7735          72 :                                 GetFloatContainingBlock(parentFrame));
    7736             : 
    7737             :   // See if the containing block has :first-letter style applied.
    7738          36 :   bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
    7739          36 :   nsContainerFrame* containingBlock = state.mFloatedItems.containingBlock;
    7740          36 :   if (containingBlock) {
    7741           7 :     haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
    7742             :     haveFirstLineStyle =
    7743           7 :       ShouldHaveFirstLineStyle(containingBlock->GetContent(),
    7744           7 :                                containingBlock->StyleContext());
    7745             :   }
    7746             : 
    7747          36 :   if (haveFirstLetterStyle) {
    7748             :     // Before we get going, remove the current letter frames
    7749           0 :     RemoveLetterFrames(state.mPresShell, containingBlock);
    7750             :   }
    7751             : 
    7752          36 :   LayoutFrameType frameType = parentFrame->Type();
    7753             : 
    7754          72 :   FlattenedChildIterator iter(aContainer);
    7755          36 :   bool haveNoXBLChildren = (!iter.XBLInvolved() || !iter.GetNextChild());
    7756          72 :   FrameConstructionItemList items;
    7757          96 :   if (aFirstNewContent->GetPreviousSibling() &&
    7758          60 :       GetParentType(frameType) == eTypeBlock &&
    7759             :       haveNoXBLChildren) {
    7760             :     // If there's a text node in the normal content list just before the new
    7761             :     // items, and it has no frame, make a frame construction item for it. If it
    7762             :     // doesn't need a frame, ConstructFramesFromItemList below won't give it
    7763             :     // one.  No need to do all this if our parent type is not block, though,
    7764             :     // since WipeContainingBlock already handles that situation.
    7765             :     //
    7766             :     // Because we're appending, we don't need to worry about any text
    7767             :     // after the appended content; there can only be XBL anonymous content
    7768             :     // (text in an XBL binding is not suppressed) or generated content
    7769             :     // (and bare text nodes are not generated). Native anonymous content
    7770             :     // generated by frames never participates in inline layout.
    7771          24 :     AddTextItemIfNeeded(state, insertion,
    7772          24 :                         aFirstNewContent->GetPreviousSibling(), items);
    7773             :   }
    7774         156 :   for (nsIContent* child = aFirstNewContent;
    7775         156 :        child;
    7776         120 :        child = child->GetNextSibling()) {
    7777         120 :     AddFrameConstructionItems(state, child, false, insertion, items);
    7778             :   }
    7779             : 
    7780          36 :   nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, parentAfterFrame);
    7781             : 
    7782             :   // Perform special check for diddling around with the frames in
    7783             :   // a ib-split inline frame.
    7784             :   // If we're appending before :after content, then we're not really
    7785             :   // appending, so let WipeContainingBlock know that.
    7786          36 :   LAYOUT_PHASE_TEMP_EXIT();
    7787          36 :   if (WipeContainingBlock(state, containingBlock, parentFrame, items,
    7788             :                           true, prevSibling)) {
    7789           0 :     LAYOUT_PHASE_TEMP_REENTER();
    7790           0 :     return;
    7791             :   }
    7792          36 :   LAYOUT_PHASE_TEMP_REENTER();
    7793             : 
    7794             :   // If the parent is a block frame, and we're not in a special case
    7795             :   // where frames can be moved around, determine if the list is for the
    7796             :   // start or end of the block.
    7797          86 :   if (nsLayoutUtils::GetAsBlock(parentFrame) && !haveFirstLetterStyle &&
    7798          50 :       !haveFirstLineStyle && !parentIBSplit) {
    7799           7 :     items.SetLineBoundaryAtStart(!prevSibling ||
    7800           7 :                                  !prevSibling->IsInlineOutside() ||
    7801           7 :                                  prevSibling->IsBrFrame());
    7802             :     // :after content can't be <br> so no need to check it
    7803           7 :     items.SetLineBoundaryAtEnd(!parentAfterFrame ||
    7804           7 :         !parentAfterFrame->IsInlineOutside());
    7805             :   }
    7806             :   // To suppress whitespace-only text frames, we have to verify that
    7807             :   // our container's DOM child list matches its flattened tree child list.
    7808          36 :   items.SetParentHasNoXBLChildren(haveNoXBLChildren);
    7809             : 
    7810          36 :   nsFrameItems frameItems;
    7811          36 :   ConstructFramesFromItemList(state, items, parentFrame, frameItems);
    7812             : 
    7813         156 :   for (nsIContent* child = aFirstNewContent;
    7814         156 :        child;
    7815         120 :        child = child->GetNextSibling()) {
    7816             :     // Invalidate now instead of before the WipeContainingBlock call, just in
    7817             :     // case we do wipe; in that case we don't need to do this walk at all.
    7818             :     // XXXbz does that matter?  Would it make more sense to save some virtual
    7819             :     // GetChildAt calls instead and do this during construction of our
    7820             :     // FrameConstructionItemList?
    7821         120 :     InvalidateCanvasIfNeeded(mPresShell, child);
    7822             :   }
    7823             : 
    7824             :   // If the container is a table and a caption was appended, it needs to be put
    7825             :   // in the table wrapper frame's additional child list.
    7826          36 :   nsFrameItems captionItems;
    7827          36 :   if (LayoutFrameType::Table == frameType) {
    7828             :     // Pull out the captions.  Note that we don't want to do that as we go,
    7829             :     // because processing a single caption can add a whole bunch of things to
    7830             :     // the frame items due to pseudoframe processing.  So we'd have to pull
    7831             :     // captions from a list anyway; might as well do that here.
    7832             :     // XXXbz this is no longer true; we could pull captions directly out of the
    7833             :     // FrameConstructionItemList now.
    7834           0 :     PullOutCaptionFrames(frameItems, captionItems);
    7835             :   }
    7836             : 
    7837          36 :   if (haveFirstLineStyle && parentFrame == containingBlock) {
    7838             :     // It's possible that some of the new frames go into a
    7839             :     // first-line frame. Look at them and see...
    7840           0 :     AppendFirstLineFrames(state, containingBlock->GetContent(),
    7841           0 :                           containingBlock, frameItems);
    7842             :   }
    7843             : 
    7844             :   // Notify the parent frame passing it the list of new frames
    7845             :   // Append the flowed frames to the principal child list; captions
    7846             :   // need special treatment
    7847          36 :   if (captionItems.NotEmpty()) { // append the caption to the table wrapper
    7848           0 :     NS_ASSERTION(LayoutFrameType::Table == frameType, "how did that happen?");
    7849           0 :     nsContainerFrame* outerTable = parentFrame->GetParent();
    7850           0 :     AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
    7851             :   }
    7852             : 
    7853          36 :   if (frameItems.NotEmpty()) { // append the in-flow kids
    7854          23 :     AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
    7855             :   }
    7856             : 
    7857             :   // Recover first-letter frames
    7858          36 :   if (haveFirstLetterStyle) {
    7859           0 :     RecoverLetterFrames(containingBlock);
    7860             :   }
    7861             : 
    7862             : #ifdef DEBUG
    7863          36 :   if (gReallyNoisyContentUpdates) {
    7864           0 :     printf("nsCSSFrameConstructor::ContentAppended: resulting frame model:\n");
    7865           0 :     parentFrame->List(stdout, 0);
    7866             :   }
    7867             : #endif
    7868             : 
    7869             : #ifdef ACCESSIBILITY
    7870          36 :   nsAccessibilityService* accService = nsIPresShell::AccService();
    7871          36 :   if (accService) {
    7872           0 :     accService->ContentRangeInserted(mPresShell, aContainer,
    7873           0 :                                      aFirstNewContent, nullptr);
    7874             :   }
    7875             : #endif
    7876             : }
    7877             : 
    7878             : #ifdef MOZ_XUL
    7879             : 
    7880             : enum content_operation
    7881             : {
    7882             :     CONTENT_INSERTED,
    7883             :     CONTENT_REMOVED
    7884             : };
    7885             : 
    7886             : // Helper function to lookup the listbox body frame and send a notification
    7887             : // for insertion or removal of content
    7888             : static
    7889          28 : bool NotifyListBoxBody(nsPresContext*    aPresContext,
    7890             :                          nsIContent*        aContainer,
    7891             :                          nsIContent*        aChild,
    7892             :                          // Only used for the removed notification
    7893             :                          nsIContent*        aOldNextSibling,
    7894             :                          nsIFrame*          aChildFrame,
    7895             :                          content_operation  aOperation)
    7896             : {
    7897             :   nsListBoxBodyFrame* listBoxBodyFrame =
    7898          28 :     MaybeGetListBoxBodyFrame(aContainer, aChild);
    7899          28 :   if (listBoxBodyFrame) {
    7900           0 :     if (aOperation == CONTENT_REMOVED) {
    7901             :       // Except if we have an aChildFrame and its parent is not the right
    7902             :       // thing, then we don't do this.  Pseudo frames are so much fun....
    7903           0 :       if (!aChildFrame || aChildFrame->GetParent() == listBoxBodyFrame) {
    7904             :         listBoxBodyFrame->OnContentRemoved(aPresContext, aContainer,
    7905           0 :                                            aChildFrame, aOldNextSibling);
    7906           0 :         return true;
    7907             :       }
    7908             :     } else {
    7909           0 :       listBoxBodyFrame->OnContentInserted(aChild);
    7910           0 :       return true;
    7911             :     }
    7912             :   }
    7913             : 
    7914          28 :   return false;
    7915             : }
    7916             : #endif // MOZ_XUL
    7917             : 
    7918             : void
    7919          43 : nsCSSFrameConstructor::ContentInserted(nsIContent*            aContainer,
    7920             :                                        nsIContent*            aChild,
    7921             :                                        nsILayoutHistoryState* aFrameState,
    7922             :                                        bool                   aAllowLazyConstruction)
    7923             : {
    7924          43 :   ContentRangeInserted(aContainer,
    7925             :                        aChild,
    7926             :                        aChild->GetNextSibling(),
    7927             :                        aFrameState,
    7928          43 :                        aAllowLazyConstruction);
    7929          43 : }
    7930             : 
    7931             : // ContentRangeInserted handles creating frames for a range of nodes that
    7932             : // aren't at the end of their childlist. ContentRangeInserted isn't a real
    7933             : // content notification, but rather it handles regular ContentInserted calls
    7934             : // for a single node as well as the lazy construction of frames for a range of
    7935             : // nodes when called from CreateNeededFrames. For a range of nodes to be
    7936             : // suitable to have its frames constructed all at once they must meet the same
    7937             : // conditions that ContentAppended imposes (GetRangeInsertionPoint checks
    7938             : // these), plus more. Namely when finding the insertion prevsibling we must not
    7939             : // need to consult something specific to any one node in the range, so that the
    7940             : // insertion prevsibling would be the same for each node in the range. So we
    7941             : // pass the first node in the range to GetInsertionPrevSibling, and if
    7942             : // IsValidSibling (the only place GetInsertionPrevSibling might look at the
    7943             : // passed in node itself) needs to resolve style on the node we record this and
    7944             : // return that this range needs to be split up and inserted separately. Table
    7945             : // captions need extra attention as we need to determine where to insert them
    7946             : // in the caption list, while skipping any nodes in the range being inserted
    7947             : // (because when we treat the caption frames the other nodes have had their
    7948             : // frames constructed but not yet inserted into the frame tree).
    7949             : void
    7950          65 : nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
    7951             :                                             nsIContent* aStartChild,
    7952             :                                             nsIContent* aEndChild,
    7953             :                                             nsILayoutHistoryState* aFrameState,
    7954             :                                             bool aAllowLazyConstruction,
    7955             :                                             bool aForReconstruction,
    7956             :                                             TreeMatchContext* aProvidedTreeMatchContext)
    7957             : {
    7958          65 :   MOZ_ASSERT(!aProvidedTreeMatchContext || !aAllowLazyConstruction);
    7959          65 :   MOZ_ASSERT(!aAllowLazyConstruction || !RestyleManager()->IsInStyleRefresh());
    7960             : 
    7961          89 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    7962          65 :   NS_PRECONDITION(mUpdateCount != 0,
    7963             :                   "Should be in an update while creating frames");
    7964             : 
    7965          65 :   NS_PRECONDITION(aStartChild, "must always pass a child");
    7966             : 
    7967             : #ifdef DEBUG
    7968          65 :   if (gNoisyContentUpdates) {
    7969           0 :     printf("nsCSSFrameConstructor::ContentRangeInserted container=%p "
    7970             :            "start-child=%p end-child=%p lazy=%d\n",
    7971             :            static_cast<void*>(aContainer),
    7972             :            static_cast<void*>(aStartChild), static_cast<void*>(aEndChild),
    7973           0 :            aAllowLazyConstruction);
    7974           0 :     if (gReallyNoisyContentUpdates) {
    7975           0 :       if (aContainer) {
    7976           0 :         aContainer->List(stdout,0);
    7977             :       } else {
    7978           0 :         aStartChild->List(stdout, 0);
    7979             :       }
    7980             :     }
    7981             :   }
    7982             : 
    7983         130 :   for (nsIContent* child = aStartChild;
    7984         130 :        child != aEndChild;
    7985          65 :        child = child->GetNextSibling()) {
    7986             :     // XXX the GetContent() != child check is needed due to bug 135040.
    7987             :     // Remove it once that's fixed.
    7988          65 :     NS_ASSERTION(!child->GetPrimaryFrame() ||
    7989             :                  child->GetPrimaryFrame()->GetContent() != child,
    7990             :                  "asked to construct a frame for a node that already has a frame");
    7991             :   }
    7992             : #endif
    7993             : 
    7994          65 :   bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
    7995          65 :   NS_ASSERTION(isSingleInsert || !aAllowLazyConstruction,
    7996             :                "range insert shouldn't be lazy");
    7997          65 :   NS_ASSERTION(isSingleInsert || aEndChild,
    7998             :                "range should not include all nodes after aStartChild");
    7999             : 
    8000             : #ifdef MOZ_XUL
    8001          65 :   if (aContainer && IsXULListBox(aContainer)) {
    8002           0 :     if (isSingleInsert) {
    8003           0 :       if (NotifyListBoxBody(mPresShell->GetPresContext(), aContainer,
    8004             :                             // The insert case in NotifyListBoxBody
    8005             :                             // doesn't use "old next sibling".
    8006             :                             aStartChild, nullptr, nullptr, CONTENT_INSERTED)) {
    8007           0 :         return;
    8008             :       }
    8009             :     } else {
    8010             :       // We don't handle a range insert to a listbox parent, issue single
    8011             :       // ContertInserted calls for each node inserted.
    8012           0 :       LAYOUT_PHASE_TEMP_EXIT();
    8013           0 :       IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
    8014           0 :                                    aAllowLazyConstruction, aForReconstruction);
    8015           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8016           0 :       return;
    8017             :     }
    8018             :   }
    8019             : #endif // MOZ_XUL
    8020             : 
    8021             :   // If we have a null parent, then this must be the document element being
    8022             :   // inserted, or some other child of the document in the DOM (might be a PI,
    8023             :   // say).
    8024          65 :   if (!aContainer) {
    8025          24 :     NS_ASSERTION(isSingleInsert,
    8026             :                  "root node insertion should be a single insertion");
    8027          24 :     Element* docElement = mDocument->GetRootElement();
    8028             : 
    8029          24 :     if (aStartChild != docElement) {
    8030             :       // Not the root element; just bail out
    8031           0 :       return;
    8032             :     }
    8033             : 
    8034          24 :     NS_PRECONDITION(!mRootElementFrame, "root element frame already created");
    8035             : 
    8036             :     // Create frames for the document element and its child elements
    8037          24 :     if (ConstructDocElementFrame(docElement, aFrameState)) {
    8038          24 :       InvalidateCanvasIfNeeded(mPresShell, aStartChild);
    8039             : #ifdef DEBUG
    8040          24 :       if (gReallyNoisyContentUpdates) {
    8041             :         printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
    8042           0 :                "model:\n");
    8043           0 :         mRootElementFrame->List(stdout, 0);
    8044             :       }
    8045             : #endif
    8046             :     }
    8047             : 
    8048          24 :     if (aFrameState) {
    8049             :       // Restore frame state for the root scroll frame if there is one
    8050           0 :       if (nsIFrame* rootScrollFrame = mPresShell->GetRootScrollFrame()) {
    8051           0 :         RestoreFrameStateFor(rootScrollFrame, aFrameState);
    8052             :       }
    8053             :     }
    8054             : 
    8055             : #ifdef ACCESSIBILITY
    8056          24 :     if (nsAccessibilityService* accService = nsIPresShell::AccService()) {
    8057           0 :       accService->ContentRangeInserted(mPresShell, aContainer,
    8058           0 :                                        aStartChild, aEndChild);
    8059             :     }
    8060             : #endif
    8061             : 
    8062          24 :     return;
    8063             :   }
    8064             : 
    8065             :   // The frame constructor uses this codepath both for bonafide newly-added
    8066             :   // content and for RestyleManager-driven frame construction (RECONSTRUCT_FRAME
    8067             :   // and lazy frame construction). If we're using the Servo style system, we
    8068             :   // want to ensure that styles get resolved in the first case, whereas for the
    8069             :   // second case they should have already been resolved if needed.
    8070          41 :   bool isNewlyAddedContentForServo = aContainer->IsStyledByServo() &&
    8071          41 :                                      !aForReconstruction;
    8072             : 
    8073             :   bool isNewShadowTreeContent =
    8074          41 :     aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
    8075           0 :     !aContainer->IsInNativeAnonymousSubtree() &&
    8076          41 :     (!aStartChild || !aStartChild->IsInNativeAnonymousSubtree()) &&
    8077          41 :     (!aEndChild || !aEndChild->IsInNativeAnonymousSubtree());
    8078             : 
    8079          41 :   if (!isNewShadowTreeContent) {
    8080          41 :     nsContainerFrame* parentFrame = GetContentInsertionFrameFor(aContainer);
    8081             :     // The xbl:children element won't have a frame, but default content can have the children as
    8082             :     // a parent. While its uncommon to change the structure of the default content itself, a label,
    8083             :     // for example, can be reframed by having its value attribute set or removed.
    8084          41 :     if (!parentFrame && !aContainer->IsActiveChildrenElement()) {
    8085             :       // We're punting on frame construction because there's no container frame.
    8086             :       // The Servo-backed style system handles this case like the lazy frame
    8087             :       // construction case.
    8088          12 :       if (isNewlyAddedContentForServo) {
    8089           0 :         LazilyStyleNewChildRange(aStartChild, aEndChild);
    8090             :       }
    8091          12 :       return;
    8092             :     }
    8093             : 
    8094             :     // Otherwise, we've got parent content. Find its frame.
    8095          29 :     NS_ASSERTION(!parentFrame || parentFrame->GetContent() == aContainer ||
    8096             :                  GetDisplayContentsStyleFor(aContainer), "New XBL code is possibly wrong!");
    8097             : 
    8098          42 :     if (aAllowLazyConstruction &&
    8099          13 :         MaybeConstructLazily(CONTENTINSERT, aContainer, aStartChild)) {
    8100           0 :       if (isNewlyAddedContentForServo) {
    8101           0 :         LazilyStyleNewChildRange(aStartChild, aEndChild);
    8102             :       }
    8103           0 :       return;
    8104             :     }
    8105             :   }
    8106             : 
    8107             :   // We couldn't construct lazily. Make Servo eagerly traverse the new content.
    8108          29 :   if (aContainer->IsStyledByServo()) {
    8109           0 :     if (aForReconstruction) {
    8110           0 :       StyleChildRangeForReconstruct(aStartChild, aEndChild);
    8111             :     } else {
    8112           0 :       StyleNewChildRange(aStartChild, aEndChild);
    8113             :     }
    8114             :   }
    8115             : 
    8116          29 :   if (isNewShadowTreeContent) {
    8117             :     // Recreate frames if content is inserted into a ShadowRoot
    8118             :     // because children of ShadowRoot are rendered in place of
    8119             :     // the children of the host.
    8120             :     //XXXsmaug This is super unefficient!
    8121           0 :     nsIContent* bindingParent = aContainer->GetBindingParent();
    8122           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8123             :     RecreateFramesForContent(bindingParent, false,
    8124           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
    8125           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8126           0 :     return;
    8127             :   }
    8128             : 
    8129          29 :   InsertionPoint insertion;
    8130          29 :   if (isSingleInsert) {
    8131             :     // See if we have an XBL insertion point. If so, then that's our
    8132             :     // real parent frame; if not, then the frame hasn't been built yet
    8133             :     // and we just bail.
    8134          29 :     insertion = GetInsertionPoint(aContainer, aStartChild);
    8135             :   } else {
    8136             :     // Get our insertion point. If we need to issue single ContentInserted's
    8137             :     // GetRangeInsertionPoint will take care of that for us.
    8138           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8139           0 :     insertion = GetRangeInsertionPoint(aContainer, aStartChild, aEndChild,
    8140             :                                        aAllowLazyConstruction,
    8141           0 :                                        aForReconstruction);
    8142           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8143             :   }
    8144             : 
    8145          29 :   if (!insertion.mParentFrame) {
    8146           5 :     return;
    8147             :   }
    8148             : 
    8149             :   bool isAppend, isRangeInsertSafe;
    8150             :   nsIFrame* prevSibling = GetInsertionPrevSibling(&insertion, aStartChild,
    8151          24 :                                                   &isAppend, &isRangeInsertSafe);
    8152             : 
    8153             :   // check if range insert is safe
    8154          24 :   if (!isSingleInsert && !isRangeInsertSafe) {
    8155             :     // must fall back to a single ContertInserted for each child in the range
    8156           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8157           0 :     IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
    8158           0 :                                  aAllowLazyConstruction, aForReconstruction);
    8159           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8160           0 :     return;
    8161             :   }
    8162             : 
    8163          24 :   nsIContent* container = insertion.mParentFrame->GetContent();
    8164             : 
    8165          24 :   LayoutFrameType frameType = insertion.mParentFrame->Type();
    8166          24 :   LAYOUT_PHASE_TEMP_EXIT();
    8167          24 :   if (MaybeRecreateForFrameset(insertion.mParentFrame, aStartChild, aEndChild)) {
    8168           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8169           0 :     return;
    8170             :   }
    8171          24 :   LAYOUT_PHASE_TEMP_REENTER();
    8172             : 
    8173             :   // We should only get here with fieldsets when doing a single insert, because
    8174             :   // fieldsets have multiple insertion points.
    8175          24 :   NS_ASSERTION(isSingleInsert || frameType != LayoutFrameType::FieldSet,
    8176             :                "Unexpected parent");
    8177          24 :   if (IsFrameForFieldSet(insertion.mParentFrame) &&
    8178           0 :       aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
    8179             :     // Just reframe the parent, since figuring out whether this
    8180             :     // should be the new legend and then handling it is too complex.
    8181             :     // We could do a little better here --- check if the fieldset already
    8182             :     // has a legend which occurs earlier in its child list than this node,
    8183             :     // and if so, proceed. But we'd have to extend nsFieldSetFrame
    8184             :     // to locate this legend in the inserted frames and extract it.
    8185           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8186           0 :     RecreateFramesForContent(insertion.mParentFrame->GetContent(), false,
    8187           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
    8188           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8189           0 :     return;
    8190             :   }
    8191             : 
    8192             :   // We should only get here with details when doing a single insertion because
    8193             :   // we treat details frame as if it has multiple insertion points.
    8194          24 :   MOZ_ASSERT(isSingleInsert || frameType != LayoutFrameType::Details);
    8195          24 :   if (frameType == LayoutFrameType::Details) {
    8196             :     // When inserting an element into <details>, just reframe the details frame
    8197             :     // and let it figure out where the element should be laid out. It might seem
    8198             :     // expensive to recreate the entire details frame, but it's the simplest way
    8199             :     // to handle the insertion.
    8200           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8201           0 :     RecreateFramesForContent(insertion.mParentFrame->GetContent(), false,
    8202           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
    8203           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8204           0 :     return;
    8205             :   }
    8206             : 
    8207             :   // Don't construct kids of leaves
    8208          24 :   if (insertion.mParentFrame->IsLeaf()) {
    8209             :     // Clear lazy bits so we don't try to construct again.
    8210           0 :     ClearLazyBits(aStartChild, aEndChild);
    8211           0 :     return;
    8212             :   }
    8213             : 
    8214          24 :   if (insertion.mParentFrame->IsFrameOfType(nsIFrame::eMathML)) {
    8215           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8216           0 :     RecreateFramesForContent(insertion.mParentFrame->GetContent(), false,
    8217           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
    8218           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8219           0 :     return;
    8220             :   }
    8221             : 
    8222          48 :   Maybe<TreeMatchContext> matchContext;
    8223          24 :   if (!aProvidedTreeMatchContext && !aContainer->IsStyledByServo()) {
    8224          24 :     matchContext.emplace(mDocument, TreeMatchContext::ForFrameConstruction);
    8225          24 :     matchContext->InitAncestors(aContainer ? aContainer->AsElement() : nullptr);
    8226             :   }
    8227             :   nsFrameConstructorState state(mPresShell,
    8228             :                                 matchContext.ptrOr(aProvidedTreeMatchContext),
    8229          24 :                                 GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS),
    8230          24 :                                 GetAbsoluteContainingBlock(insertion.mParentFrame, ABS_POS),
    8231          24 :                                 GetFloatContainingBlock(insertion.mParentFrame),
    8232         120 :                                 do_AddRef(aFrameState));
    8233             : 
    8234             :   // Recover state for the containing block - we need to know if
    8235             :   // it has :first-letter or :first-line style applied to it. The
    8236             :   // reason we care is that the internal structure in these cases
    8237             :   // is not the normal structure and requires custom updating
    8238             :   // logic.
    8239          24 :   nsContainerFrame* containingBlock = state.mFloatedItems.containingBlock;
    8240          24 :   bool haveFirstLetterStyle = false;
    8241          24 :   bool haveFirstLineStyle = false;
    8242             : 
    8243             :   // In order to shave off some cycles, we only dig up the
    8244             :   // containing block haveFirst* flags if the parent frame where
    8245             :   // the insertion/append is occurring is an inline or block
    8246             :   // container. For other types of containers this isn't relevant.
    8247          24 :   StyleDisplay parentDisplay = insertion.mParentFrame->GetDisplay();
    8248             : 
    8249             :   // Examine the insertion.mParentFrame where the insertion is taking
    8250             :   // place. If it's a certain kind of container then some special
    8251             :   // processing is done.
    8252          24 :   if ((StyleDisplay::Block == parentDisplay) ||
    8253          19 :       (StyleDisplay::ListItem == parentDisplay) ||
    8254          19 :       (StyleDisplay::Inline == parentDisplay) ||
    8255             :       (StyleDisplay::InlineBlock == parentDisplay)) {
    8256             :     // Recover the special style flags for the containing block
    8257           5 :     if (containingBlock) {
    8258           2 :       haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
    8259             :       haveFirstLineStyle =
    8260           2 :         ShouldHaveFirstLineStyle(containingBlock->GetContent(),
    8261           2 :                                  containingBlock->StyleContext());
    8262             :     }
    8263             : 
    8264           5 :     if (haveFirstLetterStyle) {
    8265             :       // If our current insertion.mParentFrame is a Letter frame, use its parent as our
    8266             :       // new parent hint
    8267           0 :       if (insertion.mParentFrame->IsLetterFrame()) {
    8268             :         // If insertion.mParentFrame is out of flow, then we actually want the parent of
    8269             :         // the placeholder frame.
    8270           0 :         if (insertion.mParentFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    8271             :           nsPlaceholderFrame* placeholderFrame =
    8272           0 :             insertion.mParentFrame->GetPlaceholderFrame();
    8273           0 :           NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?");
    8274           0 :           insertion.mParentFrame = placeholderFrame->GetParent();
    8275             :         } else {
    8276           0 :           insertion.mParentFrame = insertion.mParentFrame->GetParent();
    8277             :         }
    8278             :       }
    8279             : 
    8280             :       // Remove the old letter frames before doing the insertion
    8281           0 :       RemoveLetterFrames(mPresShell, state.mFloatedItems.containingBlock);
    8282             : 
    8283             :       // Removing the letterframes messes around with the frame tree, removing
    8284             :       // and creating frames.  We need to reget our prevsibling, parent frame,
    8285             :       // etc.
    8286             :       prevSibling = GetInsertionPrevSibling(&insertion, aStartChild, &isAppend,
    8287           0 :                                             &isRangeInsertSafe);
    8288             : 
    8289             :       // Need check whether a range insert is still safe.
    8290           0 :       if (!isSingleInsert && !isRangeInsertSafe) {
    8291             :         // Need to recover the letter frames first.
    8292           0 :         RecoverLetterFrames(state.mFloatedItems.containingBlock);
    8293             : 
    8294             :         // must fall back to a single ContertInserted for each child in the range
    8295           0 :         LAYOUT_PHASE_TEMP_EXIT();
    8296           0 :         IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
    8297           0 :                                      aAllowLazyConstruction, aForReconstruction);
    8298           0 :         LAYOUT_PHASE_TEMP_REENTER();
    8299           0 :         return;
    8300             :       }
    8301             : 
    8302           0 :       container = insertion.mParentFrame->GetContent();
    8303           0 :       frameType = insertion.mParentFrame->Type();
    8304             :     }
    8305             :   }
    8306             : 
    8307          24 :   if (!prevSibling) {
    8308             :     // We're inserting the new frames as the first child. See if the
    8309             :     // parent has a :before pseudo-element
    8310          13 :     nsIFrame* firstChild = insertion.mParentFrame->PrincipalChildList().FirstChild();
    8311             : 
    8312          21 :     if (firstChild &&
    8313           8 :         nsLayoutUtils::IsGeneratedContentFor(container, firstChild,
    8314             :                                              nsCSSPseudoElements::before)) {
    8315             :       // Insert the new frames after the last continuation of the :before
    8316           0 :       prevSibling = firstChild->GetTailContinuation();
    8317           0 :       insertion.mParentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
    8318             :       // Don't change isAppend here; we'll can call AppendFrames as needed, and
    8319             :       // the change to our prevSibling doesn't affect that.
    8320             :     }
    8321             :   }
    8322             : 
    8323          48 :   FrameConstructionItemList items;
    8324          24 :   ParentType parentType = GetParentType(frameType);
    8325          48 :   FlattenedChildIterator iter(aContainer);
    8326          24 :   bool haveNoXBLChildren = (!iter.XBLInvolved() || !iter.GetNextChild());
    8327          60 :   if (aStartChild->GetPreviousSibling() &&
    8328          36 :       parentType == eTypeBlock && haveNoXBLChildren) {
    8329             :     // If there's a text node in the normal content list just before the
    8330             :     // new nodes, and it has no frame, make a frame construction item for
    8331             :     // it, because it might need a frame now.  No need to do this if our
    8332             :     // parent type is not block, though, since WipeContainingBlock
    8333             :     // already handles that sitation.
    8334           8 :     AddTextItemIfNeeded(state, insertion, aStartChild->GetPreviousSibling(),
    8335           8 :                         items);
    8336             :   }
    8337             : 
    8338          24 :   if (isSingleInsert) {
    8339          24 :     AddFrameConstructionItems(state, aStartChild,
    8340          24 :                               aStartChild->IsRootOfAnonymousSubtree(),
    8341          24 :                               insertion, items);
    8342             :   } else {
    8343           0 :     for (nsIContent* child = aStartChild;
    8344           0 :          child != aEndChild;
    8345           0 :          child = child->GetNextSibling()){
    8346           0 :       AddFrameConstructionItems(state, child, false, insertion, items);
    8347             :     }
    8348             :   }
    8349             : 
    8350          24 :   if (aEndChild && parentType == eTypeBlock && haveNoXBLChildren) {
    8351             :     // If there's a text node in the normal content list just after the
    8352             :     // new nodes, and it has no frame, make a frame construction item for
    8353             :     // it, because it might need a frame now.  No need to do this if our
    8354             :     // parent type is not block, though, since WipeContainingBlock
    8355             :     // already handles that sitation.
    8356          11 :     AddTextItemIfNeeded(state, insertion, aEndChild, items);
    8357             :   }
    8358             : 
    8359             :   // Perform special check for diddling around with the frames in
    8360             :   // a special inline frame.
    8361             :   // If we're appending before :after content, then we're not really
    8362             :   // appending, so let WipeContainingBlock know that.
    8363          24 :   LAYOUT_PHASE_TEMP_EXIT();
    8364          24 :   if (WipeContainingBlock(state, containingBlock, insertion.mParentFrame, items,
    8365             :                           isAppend, prevSibling)) {
    8366           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8367           0 :     return;
    8368             :   }
    8369          24 :   LAYOUT_PHASE_TEMP_REENTER();
    8370             : 
    8371             :   // If the container is a table and a caption will be appended, it needs to be
    8372             :   // put in the table wrapper frame's additional child list.
    8373             :   // We make no attempt here to set flags to indicate whether the list
    8374             :   // will be at the start or end of a block. It doesn't seem worthwhile.
    8375          24 :   nsFrameItems frameItems, captionItems;
    8376          24 :   ConstructFramesFromItemList(state, items, insertion.mParentFrame, frameItems);
    8377             : 
    8378          24 :   if (frameItems.NotEmpty()) {
    8379          40 :     for (nsIContent* child = aStartChild;
    8380          40 :          child != aEndChild;
    8381          20 :          child = child->GetNextSibling()){
    8382          20 :       InvalidateCanvasIfNeeded(mPresShell, child);
    8383             :     }
    8384             : 
    8385          20 :     if (LayoutFrameType::Table == frameType ||
    8386             :         LayoutFrameType::TableWrapper == frameType) {
    8387           0 :       PullOutCaptionFrames(frameItems, captionItems);
    8388             :     }
    8389             :   }
    8390             : 
    8391             :   // If the parent of our current prevSibling is different from the frame we'll
    8392             :   // actually use as the parent, then the calculated insertion point is now
    8393             :   // invalid and as it is unknown where to insert correctly we append instead
    8394             :   // (bug 341858).
    8395             :   // This can affect our prevSibling and isAppend, but should not have any
    8396             :   // effect on the WipeContainingBlock above, since this should only happen
    8397             :   // when neither parent is a ib-split frame and should not affect whitespace
    8398             :   // handling inside table-related frames (and in fact, can only happen when
    8399             :   // one of the parents is a table wrapper and one is an inner table or when the
    8400             :   // parent is a fieldset or fieldset content frame).  So it won't affect the
    8401             :   // {ib} or XUL box cases in WipeContainingBlock(), and the table pseudo
    8402             :   // handling will only be affected by us maybe thinking we're not inserting
    8403             :   // at the beginning, whereas we really are.  That would have made us reframe
    8404             :   // unnecessarily, but that's ok.
    8405             :   // XXXbz we should push our frame construction item code up higher, so we
    8406             :   // know what our items are by the time we start figuring out previous
    8407             :   // siblings
    8408          33 :   if (prevSibling && frameItems.NotEmpty() &&
    8409           9 :       frameItems.FirstChild()->GetParent() != prevSibling->GetParent()) {
    8410             : #ifdef DEBUG
    8411           0 :     nsIFrame* frame1 = frameItems.FirstChild()->GetParent();
    8412           0 :     nsIFrame* frame2 = prevSibling->GetParent();
    8413           0 :     NS_ASSERTION(!IsFramePartOfIBSplit(frame1) &&
    8414             :                  !IsFramePartOfIBSplit(frame2),
    8415             :                  "Neither should be ib-split");
    8416           0 :     NS_ASSERTION((frame1->IsTableFrame() &&
    8417             :                   frame2->IsTableWrapperFrame()) ||
    8418             :                  (frame1->IsTableWrapperFrame() &&
    8419             :                   frame2->IsTableFrame()) ||
    8420             :                  frame1->IsFieldSetFrame() ||
    8421             :                  (frame1->GetParent() &&
    8422             :                   frame1->GetParent()->IsFieldSetFrame()),
    8423             :                  "Unexpected frame types");
    8424             : #endif
    8425           0 :     isAppend = true;
    8426             :     nsIFrame* appendAfterFrame;
    8427           0 :     insertion.mParentFrame =
    8428           0 :       ::AdjustAppendParentForAfterContent(this, container,
    8429             :                                           frameItems.FirstChild()->GetParent(),
    8430             :                                           aStartChild, &appendAfterFrame);
    8431           0 :     prevSibling = ::FindAppendPrevSibling(insertion.mParentFrame, appendAfterFrame);
    8432             :   }
    8433             : 
    8434          24 :   if (haveFirstLineStyle && insertion.mParentFrame == containingBlock) {
    8435             :     // It's possible that the new frame goes into a first-line
    8436             :     // frame. Look at it and see...
    8437           0 :     if (isAppend) {
    8438             :       // Use append logic when appending
    8439           0 :       AppendFirstLineFrames(state, containingBlock->GetContent(),
    8440           0 :                             containingBlock, frameItems);
    8441             :     }
    8442             :     else {
    8443             :       // Use more complicated insert logic when inserting
    8444             :       // XXXbz this method is a no-op, so it's easy for the args being passed
    8445             :       // here to make no sense without anyone noticing...  If it ever stops
    8446             :       // being a no-op, vet them carefully!
    8447             :       InsertFirstLineFrames(state, container, containingBlock, &insertion.mParentFrame,
    8448           0 :                             prevSibling, frameItems);
    8449             :     }
    8450             :   }
    8451             : 
    8452             :   // We might have captions; put them into the caption list of the
    8453             :   // table wrapper frame.
    8454          24 :   if (captionItems.NotEmpty()) {
    8455           0 :     NS_ASSERTION(LayoutFrameType::Table == frameType ||
    8456             :                  LayoutFrameType::TableWrapper == frameType,
    8457             :                  "parent for caption is not table?");
    8458             :     // We need to determine where to put the caption items; start with the
    8459             :     // the parent frame that has already been determined and get the insertion
    8460             :     // prevsibling of the first caption item.
    8461             :     bool captionIsAppend;
    8462           0 :     nsIFrame* captionPrevSibling = nullptr;
    8463             : 
    8464             :     // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
    8465             :     bool ignored;
    8466           0 :     InsertionPoint captionInsertion(insertion.mParentFrame, insertion.mContainer);
    8467           0 :     if (isSingleInsert) {
    8468             :       captionPrevSibling =
    8469             :         GetInsertionPrevSibling(&captionInsertion, aStartChild,
    8470           0 :                                 &captionIsAppend, &ignored);
    8471             :     } else {
    8472           0 :       nsIContent* firstCaption = captionItems.FirstChild()->GetContent();
    8473             :       // It is very important here that we skip the children in
    8474             :       // [aStartChild,aEndChild) when looking for a
    8475             :       // prevsibling.
    8476             :       captionPrevSibling =
    8477             :         GetInsertionPrevSibling(&captionInsertion, firstCaption,
    8478             :                                 &captionIsAppend, &ignored,
    8479           0 :                                 aStartChild, aEndChild);
    8480             :     }
    8481             : 
    8482           0 :     nsContainerFrame* outerTable = nullptr;
    8483           0 :     if (GetCaptionAdjustedParent(captionInsertion.mParentFrame,
    8484           0 :                                  captionItems.FirstChild(),
    8485             :                                  &outerTable)) {
    8486             :       // If the parent is not a table wrapper frame we will try to add frames
    8487             :       // to a named child list that the parent does not honor and the frames
    8488             :       // will get lost.
    8489           0 :       NS_ASSERTION(outerTable->IsTableWrapperFrame(),
    8490             :                    "Pseudo frame construction failure; "
    8491             :                    "a caption can be only a child of a table wrapper frame");
    8492             : 
    8493             :       // If the parent of our current prevSibling is different from the frame
    8494             :       // we'll actually use as the parent, then the calculated insertion
    8495             :       // point is now invalid (bug 341382).
    8496           0 :       if (captionPrevSibling &&
    8497           0 :           captionPrevSibling->GetParent() != outerTable) {
    8498           0 :           captionPrevSibling = nullptr;
    8499             :       }
    8500           0 :       if (captionIsAppend) {
    8501           0 :         AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
    8502             :       } else {
    8503           0 :         InsertFrames(outerTable, nsIFrame::kCaptionList,
    8504           0 :                      captionPrevSibling, captionItems);
    8505             :       }
    8506             :     }
    8507             :   }
    8508             : 
    8509          24 :   if (frameItems.NotEmpty()) {
    8510             :     // Notify the parent frame
    8511          20 :     if (isAppend) {
    8512           5 :       AppendFramesToParent(state, insertion.mParentFrame, frameItems, prevSibling);
    8513             :     } else {
    8514          15 :       InsertFrames(insertion.mParentFrame, kPrincipalList, prevSibling, frameItems);
    8515             :     }
    8516             :   }
    8517             : 
    8518          24 :   if (haveFirstLetterStyle) {
    8519             :     // Recover the letter frames for the containing block when
    8520             :     // it has first-letter style.
    8521           0 :     RecoverLetterFrames(state.mFloatedItems.containingBlock);
    8522             :   }
    8523             : 
    8524             : #ifdef DEBUG
    8525          24 :   if (gReallyNoisyContentUpdates && insertion.mParentFrame) {
    8526           0 :     printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame model:\n");
    8527           0 :     insertion.mParentFrame->List(stdout, 0);
    8528             :   }
    8529             : #endif
    8530             : 
    8531             : #ifdef ACCESSIBILITY
    8532          24 :   nsAccessibilityService* accService = nsIPresShell::AccService();
    8533          24 :   if (accService) {
    8534           0 :     accService->ContentRangeInserted(mPresShell, aContainer,
    8535           0 :                                      aStartChild, aEndChild);
    8536             :   }
    8537             : #endif
    8538             : }
    8539             : 
    8540             : void
    8541          28 : nsCSSFrameConstructor::ContentRemoved(nsIContent*  aContainer,
    8542             :                                       nsIContent*  aChild,
    8543             :                                       nsIContent*  aOldNextSibling,
    8544             :                                       RemoveFlags  aFlags,
    8545             :                                       bool*        aDidReconstruct,
    8546             :                                       nsIContent** aDestroyedFramesFor)
    8547             : {
    8548          56 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    8549          28 :   NS_PRECONDITION(mUpdateCount != 0,
    8550             :                   "Should be in an update while destroying frames");
    8551             : 
    8552          28 :   *aDidReconstruct = false;
    8553          28 :   if (aDestroyedFramesFor) {
    8554           0 :     *aDestroyedFramesFor = aChild;
    8555             :   }
    8556             : 
    8557             :   // We're destroying our frame(s). This normally happens either when the
    8558             :   // content is being removed from the DOM (in which case we'll drop all Servo
    8559             :   // data in UnbindFromTree), or when we're recreating frames (usually in
    8560             :   // response to having retrieved a ReconstructFrame change hint after
    8561             :   // restyling). In both of those cases, there are no pending restyles we need
    8562             :   // to worry about.
    8563             :   //
    8564             :   // However, there is also the (rare) DestroyFramesFor path, in which we tear
    8565             :   // down (and usually recreate) the frames for a subtree. In this case, leaving
    8566             :   // the style data on the elements is problematic for our invariants, because
    8567             :   // there might be pending restyles in the subtree. If we simply leave them
    8568             :   // as-is, the subsequent traversal when recreating frames will generate a
    8569             :   // bunch of bogus change hints to update frames that no longer exist.
    8570             :   //
    8571             :   // So the two obvious options are to (1) process all pending restyles and take
    8572             :   // all the change hints before destroying the frames, or (2) drop all the
    8573             :   // style data.  We chose the latter, since that matches the performance
    8574             :   // characteristics of the old Gecko style system.
    8575             :   //
    8576             :   // That said, it's almost certainly possible to optimize this if it turns out
    8577             :   // to be hot. It's just not a priority at the moment.
    8578             :   //
    8579             :   // FIXME(emilio): This really really feels like a hack, and it's only for the
    8580             :   // XBL/Shadow DOM path, so we should do this there instead.
    8581          28 :   if (aFlags == REMOVE_DESTROY_FRAMES && aChild->IsElement() &&
    8582           0 :       aChild->IsStyledByServo()) {
    8583           0 :     ServoRestyleManager::ClearServoDataFromSubtree(aChild->AsElement());
    8584             :   }
    8585             : 
    8586          28 :   nsPresContext* presContext = mPresShell->GetPresContext();
    8587          28 :   MOZ_ASSERT(presContext, "Our presShell should have a valid presContext");
    8588             : 
    8589          28 :   if (aChild->IsHTMLElement(nsGkAtoms::body) ||
    8590           0 :       (!aContainer && aChild->IsElement())) {
    8591             :     // We might be removing the element that we propagated viewport scrollbar
    8592             :     // styles from.  Recompute those. (This clause covers two of the three
    8593             :     // possible scrollbar-propagation sources: the <body> [as aChild or a
    8594             :     // descendant] and the root node. The other possible scrollbar-propagation
    8595             :     // source is a fullscreen element, and we have code elsewhere to update
    8596             :     // scrollbars after fullscreen elements are removed -- specifically, it's
    8597             :     // part of the fullscreen cleanup code called by Element::UnbindFromTree.)
    8598           0 :     presContext->UpdateViewportScrollbarStylesOverride();
    8599             :   }
    8600             : 
    8601             : #ifdef DEBUG
    8602          28 :   if (gNoisyContentUpdates) {
    8603             :     printf("nsCSSFrameConstructor::ContentRemoved container=%p child=%p "
    8604             :            "old-next-sibling=%p\n",
    8605             :            static_cast<void*>(aContainer),
    8606             :            static_cast<void*>(aChild),
    8607           0 :            static_cast<void*>(aOldNextSibling));
    8608           0 :     if (gReallyNoisyContentUpdates) {
    8609           0 :       aContainer->List(stdout, 0);
    8610             :     }
    8611             :   }
    8612             : #endif
    8613             : 
    8614          28 :   nsIFrame* childFrame = aChild->GetPrimaryFrame();
    8615          28 :   if (!childFrame || childFrame->GetContent() != aChild) {
    8616             :     // XXXbz the GetContent() != aChild check is needed due to bug 135040.
    8617             :     // Remove it once that's fixed.
    8618           9 :     ClearUndisplayedContentIn(aChild, aContainer);
    8619             :   }
    8620          28 :   MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild),
    8621             :              "display:contents nodes shouldn't have a frame");
    8622          28 :   if (!childFrame && GetDisplayContentsStyleFor(aChild)) {
    8623           0 :     nsIContent* ancestor = aContainer;
    8624           0 :     MOZ_ASSERT(ancestor, "display: contents on the root?");
    8625           0 :     while (!ancestor->GetPrimaryFrame()) {
    8626             :       // FIXME(emilio): Should this use the flattened tree parent instead?
    8627           0 :       ancestor = ancestor->GetParent();
    8628           0 :       MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!");
    8629             :     }
    8630             : 
    8631           0 :     nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame();
    8632           0 :     if (ancestorFrame->GetProperty(nsIFrame::GenConProperty())) {
    8633           0 :       *aDidReconstruct = true;
    8634           0 :       LAYOUT_PHASE_TEMP_EXIT();
    8635             : 
    8636             :       // XXXmats Can we recreate frames only for the ::after/::before content?
    8637             :       // XXX Perhaps even only those that belong to the aChild sub-tree?
    8638           0 :       RecreateFramesForContent(ancestor, false, aFlags, aDestroyedFramesFor);
    8639           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8640           0 :       return;
    8641             :     }
    8642             : 
    8643           0 :     FlattenedChildIterator iter(aChild);
    8644           0 :     for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
    8645           0 :       if (c->GetPrimaryFrame() || GetDisplayContentsStyleFor(c)) {
    8646           0 :         LAYOUT_PHASE_TEMP_EXIT();
    8647           0 :         ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct, aDestroyedFramesFor);
    8648           0 :         LAYOUT_PHASE_TEMP_REENTER();
    8649           0 :         if (aFlags != REMOVE_DESTROY_FRAMES && *aDidReconstruct) {
    8650           0 :           return;
    8651             :         }
    8652             :       }
    8653             :     }
    8654           0 :     ClearDisplayContentsIn(aChild, aContainer);
    8655             :   }
    8656             : 
    8657             : #ifdef MOZ_XUL
    8658          28 :   if (NotifyListBoxBody(presContext, aContainer, aChild, aOldNextSibling,
    8659             :                         childFrame, CONTENT_REMOVED)) {
    8660           0 :     if (aFlags == REMOVE_DESTROY_FRAMES) {
    8661           0 :       CaptureStateForFramesOf(aChild, mTempFrameTreeState);
    8662             :     }
    8663           0 :     return;
    8664             :   }
    8665             : #endif // MOZ_XUL
    8666             : 
    8667             :   // If we're removing the root, then make sure to remove things starting at
    8668             :   // the viewport's child instead of the primary frame (which might even be
    8669             :   // null if the root had an XBL binding or display:none, even though the
    8670             :   // frames above it got created).  We do the adjustment after the childFrame
    8671             :   // check above, because we do want to clear any undisplayed content we might
    8672             :   // have for the root.  Detecting removal of a root is a little exciting; in
    8673             :   // particular, having a null aContainer is necessary but NOT sufficient.  Due
    8674             :   // to how we process reframes, the content node might not even be in our
    8675             :   // document by now.  So explicitly check whether the viewport's first kid's
    8676             :   // content node is aChild.
    8677          28 :   bool isRoot = false;
    8678          28 :   if (!aContainer) {
    8679           0 :     nsIFrame* viewport = GetRootFrame();
    8680           0 :     if (viewport) {
    8681           0 :       nsIFrame* firstChild = viewport->PrincipalChildList().FirstChild();
    8682           0 :       if (firstChild && firstChild->GetContent() == aChild) {
    8683           0 :         isRoot = true;
    8684           0 :         childFrame = firstChild;
    8685           0 :         NS_ASSERTION(!childFrame->GetNextSibling(), "How did that happen?");
    8686             :       }
    8687             :     }
    8688             :   }
    8689             : 
    8690          56 :   if (aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE) &&
    8691          28 :       !aContainer->IsInNativeAnonymousSubtree() &&
    8692           0 :       !aChild->IsInNativeAnonymousSubtree()) {
    8693             :     // Recreate frames if content is removed from a ShadowRoot because it may
    8694             :     // contain an insertion point which can change how the host is rendered.
    8695             :     //
    8696             :     // XXXsmaug This is super unefficient!
    8697           0 :     nsIContent* bindingParent = aContainer->GetBindingParent();
    8698           0 :     *aDidReconstruct = true;
    8699           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8700           0 :     RecreateFramesForContent(bindingParent, false, aFlags, aDestroyedFramesFor);
    8701           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8702           0 :     return;
    8703             :   }
    8704             : 
    8705          28 :   if (aFlags == REMOVE_DESTROY_FRAMES) {
    8706           0 :     CaptureStateForFramesOf(aChild, mTempFrameTreeState);
    8707             :   }
    8708             : 
    8709          28 :   if (childFrame) {
    8710          19 :     InvalidateCanvasIfNeeded(mPresShell, aChild);
    8711             : 
    8712             :     // See whether we need to remove more than just childFrame
    8713          19 :     LAYOUT_PHASE_TEMP_EXIT();
    8714             :     nsIContent* container;
    8715          19 :     if (MaybeRecreateContainerForFrameRemoval(childFrame, aFlags, &container)) {
    8716           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8717           0 :       MOZ_ASSERT(container);
    8718           0 :       *aDidReconstruct = true;
    8719           0 :       if (aDestroyedFramesFor) {
    8720           0 :         *aDestroyedFramesFor = container;
    8721             :       }
    8722           0 :       return;
    8723             :     }
    8724          19 :     LAYOUT_PHASE_TEMP_REENTER();
    8725             : 
    8726             :     // Get the childFrame's parent frame
    8727          19 :     nsIFrame* parentFrame = childFrame->GetParent();
    8728          19 :     LayoutFrameType parentType = parentFrame->Type();
    8729             : 
    8730          19 :     if (parentType == LayoutFrameType::FrameSet &&
    8731           0 :         IsSpecialFramesetChild(aChild)) {
    8732             :       // Just reframe the parent, since framesets are weird like that.
    8733           0 :       *aDidReconstruct = true;
    8734           0 :       LAYOUT_PHASE_TEMP_EXIT();
    8735           0 :       RecreateFramesForContent(parentFrame->GetContent(), false,
    8736           0 :                                aFlags, aDestroyedFramesFor);
    8737           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8738           0 :       return;
    8739             :     }
    8740             : 
    8741             :     // If we're a child of MathML, then we should reframe the MathML content.
    8742             :     // If we're non-MathML, then we would be wrapped in a block so we need to
    8743             :     // check our grandparent in that case.
    8744             :     nsIFrame* possibleMathMLAncestor = parentType == LayoutFrameType::Block
    8745          19 :                                          ? parentFrame->GetParent()
    8746          19 :                                          : parentFrame;
    8747          19 :     if (possibleMathMLAncestor->IsFrameOfType(nsIFrame::eMathML)) {
    8748           0 :       *aDidReconstruct = true;
    8749           0 :       LAYOUT_PHASE_TEMP_EXIT();
    8750           0 :       RecreateFramesForContent(possibleMathMLAncestor->GetContent(),
    8751           0 :                                false, aFlags, aDestroyedFramesFor);
    8752           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8753           0 :       return;
    8754             :     }
    8755             : 
    8756             :     // Undo XUL wrapping if it's no longer needed.
    8757             :     // (If we're in the XUL block-wrapping situation, parentFrame is the
    8758             :     // wrapper frame.)
    8759          19 :     nsIFrame* grandparentFrame = parentFrame->GetParent();
    8760          50 :     if (grandparentFrame && grandparentFrame->IsXULBoxFrame() &&
    8761          12 :         (grandparentFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
    8762             :         // check if this frame is the only one needing wrapping
    8763          19 :         aChild == AnyKidsNeedBlockParent(parentFrame->PrincipalChildList().FirstChild()) &&
    8764           0 :         !AnyKidsNeedBlockParent(childFrame->GetNextSibling())) {
    8765           0 :       *aDidReconstruct = true;
    8766           0 :       LAYOUT_PHASE_TEMP_EXIT();
    8767           0 :       RecreateFramesForContent(grandparentFrame->GetContent(), true,
    8768           0 :                                aFlags, aDestroyedFramesFor);
    8769           0 :       LAYOUT_PHASE_TEMP_REENTER();
    8770           0 :       return;
    8771             :     }
    8772             : 
    8773             : #ifdef ACCESSIBILITY
    8774          19 :     nsAccessibilityService* accService = nsIPresShell::AccService();
    8775          19 :     if (accService) {
    8776           0 :       accService->ContentRemoved(mPresShell, aChild);
    8777             :     }
    8778             : #endif
    8779             : 
    8780             :     // Examine the containing-block for the removed content and see if
    8781             :     // :first-letter style applies.
    8782          19 :     nsIFrame* inflowChild = childFrame;
    8783          19 :     if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    8784           0 :       inflowChild = childFrame->GetPlaceholderFrame();
    8785           0 :       NS_ASSERTION(inflowChild, "No placeholder for out-of-flow?");
    8786             :     }
    8787             :     nsContainerFrame* containingBlock =
    8788          19 :       GetFloatContainingBlock(inflowChild->GetParent());
    8789          19 :     bool haveFLS = containingBlock && HasFirstLetterStyle(containingBlock);
    8790          19 :     if (haveFLS) {
    8791             :       // Trap out to special routine that handles adjusting a blocks
    8792             :       // frame tree when first-letter style is present.
    8793             : #ifdef NOISY_FIRST_LETTER
    8794             :       printf("ContentRemoved: containingBlock=");
    8795             :       nsFrame::ListTag(stdout, containingBlock);
    8796             :       printf(" parentFrame=");
    8797             :       nsFrame::ListTag(stdout, parentFrame);
    8798             :       printf(" childFrame=");
    8799             :       nsFrame::ListTag(stdout, childFrame);
    8800             :       printf("\n");
    8801             : #endif
    8802             : 
    8803             :       // First update the containing blocks structure by removing the
    8804             :       // existing letter frames. This makes the subsequent logic
    8805             :       // simpler.
    8806           0 :       RemoveLetterFrames(mPresShell, containingBlock);
    8807             : 
    8808             :       // Recover childFrame and parentFrame
    8809           0 :       childFrame = aChild->GetPrimaryFrame();
    8810           0 :       if (!childFrame || childFrame->GetContent() != aChild) {
    8811             :         // XXXbz the GetContent() != aChild check is needed due to bug 135040.
    8812             :         // Remove it once that's fixed.
    8813           0 :         ClearUndisplayedContentIn(aChild, aContainer);
    8814           0 :         return;
    8815             :       }
    8816           0 :       parentFrame = childFrame->GetParent();
    8817           0 :       parentType = parentFrame->Type();
    8818             : 
    8819             : #ifdef NOISY_FIRST_LETTER
    8820             :       printf("  ==> revised parentFrame=");
    8821             :       nsFrame::ListTag(stdout, parentFrame);
    8822             :       printf(" childFrame=");
    8823             :       nsFrame::ListTag(stdout, childFrame);
    8824             :       printf("\n");
    8825             : #endif
    8826             :     }
    8827             : 
    8828             : #ifdef DEBUG
    8829          19 :     if (gReallyNoisyContentUpdates) {
    8830           0 :       printf("nsCSSFrameConstructor::ContentRemoved: childFrame=");
    8831           0 :       nsFrame::ListTag(stdout, childFrame);
    8832           0 :       putchar('\n');
    8833           0 :       parentFrame->List(stdout, 0);
    8834             :     }
    8835             : #endif
    8836             : 
    8837             : 
    8838             :     // Notify the parent frame that it should delete the frame
    8839          19 :     if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    8840           0 :       childFrame = childFrame->GetPlaceholderFrame();
    8841           0 :       NS_ASSERTION(childFrame, "Missing placeholder frame for out of flow.");
    8842           0 :       parentFrame = childFrame->GetParent();
    8843             :     }
    8844          19 :     RemoveFrame(nsLayoutUtils::GetChildListNameFor(childFrame), childFrame);
    8845             : 
    8846          19 :     if (isRoot) {
    8847           0 :       mRootElementFrame = nullptr;
    8848           0 :       mRootElementStyleFrame = nullptr;
    8849           0 :       mDocElementContainingBlock = nullptr;
    8850           0 :       mPageSequenceFrame = nullptr;
    8851           0 :       mHasRootAbsPosContainingBlock = false;
    8852             :     }
    8853             : 
    8854          19 :     if (haveFLS && mRootElementFrame) {
    8855           0 :       RecoverLetterFrames(containingBlock);
    8856             :     }
    8857             : 
    8858             :     // If we're just reconstructing frames for the element, then the
    8859             :     // following ContentInserted notification on the element will
    8860             :     // take care of fixing up any adjacent text nodes.  We don't need
    8861             :     // to do this if the table parent type of our parent type is not
    8862             :     // eTypeBlock, though, because in that case the whitespace isn't
    8863             :     // being suppressed due to us anyway.
    8864          38 :     if (aContainer && !aChild->IsRootOfAnonymousSubtree() &&
    8865          24 :         aFlags == REMOVE_CONTENT &&
    8866           5 :         GetParentType(parentType) == eTypeBlock) {
    8867             :       // Adjacent whitespace-only text nodes might have been suppressed if
    8868             :       // this node does not have inline ends. Create frames for them now
    8869             :       // if necessary.
    8870             :       // Reframe any text node just before the node being removed, if there is
    8871             :       // one, and if it's not the last child or the first child. If a whitespace
    8872             :       // textframe was being suppressed and it's now the last child or first
    8873             :       // child then it can stay suppressed since the parent must be a block
    8874             :       // and hence it's adjacent to a block end.
    8875             :       // If aOldNextSibling is null, then the text node before the node being
    8876             :       // removed is the last node, and we don't need to worry about it.
    8877           5 :       if (aOldNextSibling) {
    8878           0 :         nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
    8879           0 :         if (prevSibling && prevSibling->GetPreviousSibling()) {
    8880           0 :           LAYOUT_PHASE_TEMP_EXIT();
    8881           0 :           ReframeTextIfNeeded(aContainer, prevSibling);
    8882           0 :           LAYOUT_PHASE_TEMP_REENTER();
    8883             :         }
    8884             :       }
    8885             :       // Reframe any text node just after the node being removed, if there is
    8886             :       // one, and if it's not the last child or the first child.
    8887           5 :       if (aOldNextSibling && aOldNextSibling->GetNextSibling() &&
    8888           0 :           aOldNextSibling->GetPreviousSibling()) {
    8889           0 :         LAYOUT_PHASE_TEMP_EXIT();
    8890           0 :         ReframeTextIfNeeded(aContainer, aOldNextSibling);
    8891           0 :         LAYOUT_PHASE_TEMP_REENTER();
    8892             :       }
    8893             :     }
    8894             : 
    8895             : #ifdef DEBUG
    8896          19 :     if (gReallyNoisyContentUpdates && parentFrame) {
    8897           0 :       printf("nsCSSFrameConstructor::ContentRemoved: resulting frame model:\n");
    8898           0 :       parentFrame->List(stdout, 0);
    8899             :     }
    8900             : #endif
    8901             :   }
    8902             : }
    8903             : 
    8904             : /**
    8905             :  * This method invalidates the canvas when frames are removed or added for a
    8906             :  * node that might have its background propagated to the canvas, i.e., a
    8907             :  * document root node or an HTML BODY which is a child of the root node.
    8908             :  *
    8909             :  * @param aFrame a frame for a content node about to be removed or a frame that
    8910             :  *               was just created for a content node that was inserted.
    8911             :  */
    8912             : static void
    8913         183 : InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node)
    8914             : {
    8915         183 :   NS_PRECONDITION(presShell->GetRootFrame(), "What happened here?");
    8916         183 :   NS_PRECONDITION(presShell->GetPresContext(), "Say what?");
    8917             : 
    8918             :   //  Note that both in ContentRemoved and ContentInserted the content node
    8919             :   //  will still have the right parent pointer, so looking at that is ok.
    8920             : 
    8921         183 :   nsIContent* parent = node->GetParent();
    8922         183 :   if (parent) {
    8923             :     // Has a parent; might not be what we want
    8924         159 :     nsIContent* grandParent = parent->GetParent();
    8925         159 :     if (grandParent) {
    8926             :       // Has a grandparent, so not what we want
    8927          82 :       return;
    8928             :     }
    8929             : 
    8930             :     // Check whether it's an HTML body
    8931          77 :     if (!node->IsHTMLElement(nsGkAtoms::body)) {
    8932          77 :       return;
    8933             :     }
    8934             :   }
    8935             : 
    8936             :   // At this point the node has no parent or it's an HTML <body> child of the
    8937             :   // root.  We might not need to invalidate in this case (eg we might be in
    8938             :   // XHTML or something), but chances are we want to.  Play it safe.
    8939             :   // Invalidate the viewport.
    8940             : 
    8941          24 :   nsIFrame* rootFrame = presShell->GetRootFrame();
    8942          24 :   rootFrame->InvalidateFrameSubtree();
    8943             : }
    8944             : 
    8945             : nsIFrame*
    8946           0 : nsCSSFrameConstructor::EnsureFrameForTextNode(nsGenericDOMDataNode* aContent)
    8947             : {
    8948           0 :   if (aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
    8949           0 :       !mAlwaysCreateFramesForIgnorableWhitespace) {
    8950             :     // Text frame may have been suppressed. Disable suppression and signal
    8951             :     // that a flush should be performed. We do this on a document-wide
    8952             :     // basis so that pages that repeatedly query metrics for
    8953             :     // collapsed-whitespace text nodes don't trigger pathological behavior.
    8954           0 :     mAlwaysCreateFramesForIgnorableWhitespace = true;
    8955           0 :     nsAutoScriptBlocker blocker;
    8956           0 :     BeginUpdate();
    8957           0 :     ReconstructDocElementHierarchy();
    8958           0 :     EndUpdate();
    8959             :   }
    8960           0 :   return aContent->GetPrimaryFrame();
    8961             : }
    8962             : 
    8963             : void
    8964           1 : nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
    8965             :                                             CharacterDataChangeInfo* aInfo)
    8966             : {
    8967           2 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    8968             : 
    8969           2 :   if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
    8970           2 :        !aContent->TextIsOnlyWhitespace()) ||
    8971           1 :       (aContent->HasFlag(NS_REFRAME_IF_WHITESPACE) &&
    8972           0 :        aContent->TextIsOnlyWhitespace())) {
    8973             : #ifdef DEBUG
    8974           0 :     nsIFrame* frame = aContent->GetPrimaryFrame();
    8975           0 :     NS_ASSERTION(!frame || !frame->IsGeneratedContentFrame(),
    8976             :                  "Bit should never be set on generated content");
    8977             : #endif
    8978           0 :     LAYOUT_PHASE_TEMP_EXIT();
    8979             :     RecreateFramesForContent(aContent, false,
    8980           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
    8981           0 :     LAYOUT_PHASE_TEMP_REENTER();
    8982           0 :     return;
    8983             :   }
    8984             : 
    8985             :   // Find the child frame
    8986           1 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    8987             : 
    8988             :   // Notify the first frame that maps the content. It will generate a reflow
    8989             :   // command
    8990             : 
    8991             :   // It's possible the frame whose content changed isn't inserted into the
    8992             :   // frame hierarchy yet, or that there is no frame that maps the content
    8993           1 :   if (nullptr != frame) {
    8994             : #if 0
    8995             :     NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
    8996             :        ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p",
    8997             :         aContent, ContentTag(aContent, 0),
    8998             :         aSubContent, frame));
    8999             : #endif
    9000             : 
    9001             :     // Special check for text content that is a child of a letter frame.  If
    9002             :     // this happens, we should remove the letter frame, do whatever we're
    9003             :     // planning to do with this notification, then put the letter frame back.
    9004             :     // Note that this is basically what RecreateFramesForContent ends up doing;
    9005             :     // the reason we dont' want to call that here is that our text content
    9006             :     // could be native anonymous, in which case RecreateFramesForContent would
    9007             :     // completely barf on it.  And recreating the non-anonymous ancestor would
    9008             :     // just lead us to come back into this notification (e.g. if quotes or
    9009             :     // counters are involved), leading to a loop.
    9010           0 :     nsContainerFrame* block = GetFloatContainingBlock(frame);
    9011           0 :     bool haveFirstLetterStyle = false;
    9012           0 :     if (block) {
    9013             :       // See if the block has first-letter style applied to it.
    9014           0 :       haveFirstLetterStyle = HasFirstLetterStyle(block);
    9015           0 :       if (haveFirstLetterStyle) {
    9016           0 :         RemoveLetterFrames(mPresShell, block);
    9017             :         // Reget |frame|, since we might have killed it.
    9018             :         // Do we really need to call CharacterDataChanged in this case, though?
    9019           0 :         frame = aContent->GetPrimaryFrame();
    9020           0 :         NS_ASSERTION(frame, "Should have frame here!");
    9021             :       }
    9022             :     }
    9023             : 
    9024           0 :     frame->CharacterDataChanged(aInfo);
    9025             : 
    9026           0 :     if (haveFirstLetterStyle) {
    9027           0 :       RecoverLetterFrames(block);
    9028             :     }
    9029             :   }
    9030             : }
    9031             : 
    9032             : void
    9033         835 : nsCSSFrameConstructor::BeginUpdate() {
    9034         835 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
    9035             :                "Someone forgot a script blocker");
    9036             : 
    9037             :   nsRootPresContext* rootPresContext =
    9038         835 :     mPresShell->GetPresContext()->GetRootPresContext();
    9039         835 :   if (rootPresContext) {
    9040         835 :     rootPresContext->IncrementDOMGeneration();
    9041             :   }
    9042             : 
    9043             : #ifdef DEBUG
    9044         835 :   ++mUpdateCount;
    9045             : #endif
    9046         835 : }
    9047             : 
    9048             : void
    9049         835 : nsCSSFrameConstructor::EndUpdate()
    9050             : {
    9051             : #ifdef DEBUG
    9052         835 :   NS_ASSERTION(mUpdateCount, "Negative mUpdateCount!");
    9053         835 :   --mUpdateCount;
    9054             : #endif
    9055         835 : }
    9056             : 
    9057             : void
    9058         105 : nsCSSFrameConstructor::RecalcQuotesAndCounters()
    9059             : {
    9060         210 :   nsAutoScriptBlocker scriptBlocker;
    9061             : 
    9062         105 :   if (mQuotesDirty) {
    9063           0 :     mQuotesDirty = false;
    9064           0 :     mQuoteList.RecalcAll();
    9065             :   }
    9066             : 
    9067         105 :   if (mCountersDirty) {
    9068           0 :     mCountersDirty = false;
    9069           0 :     mCounterManager.RecalcAll();
    9070             :   }
    9071             : 
    9072         105 :   NS_ASSERTION(!mQuotesDirty, "Quotes updates will be lost");
    9073         105 :   NS_ASSERTION(!mCountersDirty, "Counter updates will be lost");
    9074         105 : }
    9075             : 
    9076             : void
    9077           0 : nsCSSFrameConstructor::NotifyCounterStylesAreDirty()
    9078             : {
    9079           0 :   NS_PRECONDITION(mUpdateCount != 0, "Should be in an update");
    9080           0 :   mCounterManager.SetAllDirty();
    9081           0 :   CountersDirty();
    9082           0 : }
    9083             : 
    9084             : void
    9085           4 : nsCSSFrameConstructor::WillDestroyFrameTree()
    9086             : {
    9087             : #if defined(DEBUG_dbaron_off)
    9088             :   mCounterManager.Dump();
    9089             : #endif
    9090             : 
    9091           4 :   mIsDestroyingFrameTree = true;
    9092             : 
    9093             :   // Prevent frame tree destruction from being O(N^2)
    9094           4 :   mQuoteList.Clear();
    9095           4 :   mCounterManager.Clear();
    9096             : 
    9097             :   // Remove our presshell as a style flush observer.  But leave
    9098             :   // RestyleManager::mObservingRefreshDriver true so we don't readd to
    9099             :   // it even if someone tries to post restyle events on us from this
    9100             :   // point on for some reason.
    9101           4 :   mPresShell->GetPresContext()->RefreshDriver()->
    9102           8 :     RemoveStyleFlushObserver(mPresShell);
    9103             : 
    9104           4 :   nsFrameManager::Destroy();
    9105           4 : }
    9106             : 
    9107             : //STATIC
    9108             : 
    9109             : // XXXbz I'd really like this method to go away. Once we have inline-block and
    9110             : // I can just use that for sized broken images, that can happen, maybe.
    9111             : void
    9112           0 : nsCSSFrameConstructor::GetAlternateTextFor(nsIContent*    aContent,
    9113             :                                            nsIAtom*       aTag,
    9114             :                                            nsXPIDLString& aAltText)
    9115             : {
    9116             :   // The "alt" attribute specifies alternate text that is rendered
    9117             :   // when the image can not be displayed.
    9118           0 :   if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aAltText)) {
    9119           0 :     return;
    9120             :   }
    9121             : 
    9122           0 :   if (nsGkAtoms::input == aTag) {
    9123             :     // If there's no "alt" attribute, and aContent is an input element, then use
    9124             :     // the value of the "value" attribute
    9125           0 :     if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aAltText)) {
    9126           0 :       return;
    9127             :     }
    9128             : 
    9129             :     // If there's no "value" attribute either, then use the localized string for
    9130             :     // "Submit" as the alternate text.
    9131             :     nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
    9132           0 :                                        "Submit", aAltText);
    9133             :   }
    9134             : }
    9135             : 
    9136             : nsIFrame*
    9137           0 : nsCSSFrameConstructor::CreateContinuingOuterTableFrame(nsIPresShell*     aPresShell,
    9138             :                                                        nsPresContext*    aPresContext,
    9139             :                                                        nsIFrame*         aFrame,
    9140             :                                                        nsContainerFrame* aParentFrame,
    9141             :                                                        nsIContent*       aContent,
    9142             :                                                        nsStyleContext*   aStyleContext)
    9143             : {
    9144           0 :   nsTableWrapperFrame* newFrame = NS_NewTableWrapperFrame(aPresShell, aStyleContext);
    9145             : 
    9146           0 :   newFrame->Init(aContent, aParentFrame, aFrame);
    9147             : 
    9148             :   // Create a continuing inner table frame, and if there's a caption then
    9149             :   // replicate the caption
    9150           0 :   nsFrameItems  newChildFrames;
    9151             : 
    9152           0 :   nsIFrame* childFrame = aFrame->PrincipalChildList().FirstChild();
    9153           0 :   if (childFrame) {
    9154             :     nsIFrame* continuingTableFrame =
    9155           0 :       CreateContinuingFrame(aPresContext, childFrame, newFrame);
    9156           0 :     newChildFrames.AddChild(continuingTableFrame);
    9157             : 
    9158           0 :     NS_ASSERTION(!childFrame->GetNextSibling(),"there can be only one inner table frame");
    9159             :   }
    9160             : 
    9161             :   // Set the table wrapper's initial child list
    9162           0 :   newFrame->SetInitialChildList(kPrincipalList, newChildFrames);
    9163             : 
    9164           0 :   return newFrame;
    9165             : }
    9166             : 
    9167             : nsIFrame*
    9168           0 : nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell*     aPresShell,
    9169             :                                                   nsIFrame*         aFrame,
    9170             :                                                   nsContainerFrame* aParentFrame,
    9171             :                                                   nsIContent*       aContent,
    9172             :                                                   nsStyleContext*   aStyleContext)
    9173             : {
    9174           0 :   nsTableFrame* newFrame = NS_NewTableFrame(aPresShell, aStyleContext);
    9175             : 
    9176           0 :   newFrame->Init(aContent, aParentFrame, aFrame);
    9177             : 
    9178             :   // Replicate any header/footer frames
    9179           0 :   nsFrameItems  childFrames;
    9180           0 :   for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
    9181             :     // See if it's a header/footer, possibly wrapped in a scroll frame.
    9182             :     nsTableRowGroupFrame* rowGroupFrame =
    9183           0 :       static_cast<nsTableRowGroupFrame*>(childFrame);
    9184             :     // If the row group was continued, then don't replicate it.
    9185           0 :     nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
    9186           0 :     if (rgNextInFlow) {
    9187           0 :       rowGroupFrame->SetRepeatable(false);
    9188             :     }
    9189           0 :     else if (rowGroupFrame->IsRepeatable()) {
    9190             :       // Replicate the header/footer frame.
    9191             :       nsTableRowGroupFrame*   headerFooterFrame;
    9192           0 :       nsFrameItems            childItems;
    9193             : 
    9194           0 :       TreeMatchContextHolder matchContext(mDocument);
    9195             :       nsFrameConstructorState state(mPresShell,
    9196             :                                     matchContext,
    9197             :                                     GetAbsoluteContainingBlock(newFrame, FIXED_POS),
    9198             :                                     GetAbsoluteContainingBlock(newFrame, ABS_POS),
    9199           0 :                                     nullptr);
    9200           0 :       state.mCreatingExtraFrames = true;
    9201             : 
    9202           0 :       nsStyleContext* const headerFooterStyleContext = rowGroupFrame->StyleContext();
    9203             :       headerFooterFrame = static_cast<nsTableRowGroupFrame*>
    9204           0 :                                      (NS_NewTableRowGroupFrame(aPresShell, headerFooterStyleContext));
    9205             : 
    9206           0 :       nsIContent* headerFooter = rowGroupFrame->GetContent();
    9207           0 :       headerFooterFrame->Init(headerFooter, newFrame, nullptr);
    9208             : 
    9209           0 :       nsFrameConstructorSaveState absoluteSaveState;
    9210           0 :       MakeTablePartAbsoluteContainingBlockIfNeeded(state,
    9211             :                                                    headerFooterStyleContext->StyleDisplay(),
    9212             :                                                    absoluteSaveState,
    9213           0 :                                                    headerFooterFrame);
    9214             : 
    9215           0 :       ProcessChildren(state, headerFooter, rowGroupFrame->StyleContext(),
    9216             :                       headerFooterFrame, true, childItems, false,
    9217           0 :                       nullptr);
    9218           0 :       NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
    9219           0 :       headerFooterFrame->SetInitialChildList(kPrincipalList, childItems);
    9220           0 :       headerFooterFrame->SetRepeatable(true);
    9221             : 
    9222             :       // Table specific initialization
    9223           0 :       headerFooterFrame->InitRepeatedFrame(rowGroupFrame);
    9224             : 
    9225             :       // XXX Deal with absolute and fixed frames...
    9226           0 :       childFrames.AddChild(headerFooterFrame);
    9227             :     }
    9228             :   }
    9229             : 
    9230             :   // Set the table frame's initial child list
    9231           0 :   newFrame->SetInitialChildList(kPrincipalList, childFrames);
    9232             : 
    9233           0 :   return newFrame;
    9234             : }
    9235             : 
    9236             : nsIFrame*
    9237           0 : nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext*    aPresContext,
    9238             :                                              nsIFrame*         aFrame,
    9239             :                                              nsContainerFrame* aParentFrame,
    9240             :                                              bool              aIsFluid)
    9241             : {
    9242           0 :   nsIPresShell*              shell = aPresContext->PresShell();
    9243           0 :   nsStyleContext*            styleContext = aFrame->StyleContext();
    9244           0 :   nsIFrame*                  newFrame = nullptr;
    9245           0 :   nsIFrame*                  nextContinuation = aFrame->GetNextContinuation();
    9246           0 :   nsIFrame*                  nextInFlow = aFrame->GetNextInFlow();
    9247             : 
    9248             :   // Use the frame type to determine what type of frame to create
    9249           0 :   LayoutFrameType frameType = aFrame->Type();
    9250           0 :   nsIContent* content = aFrame->GetContent();
    9251             : 
    9252           0 :   NS_ASSERTION(aFrame->GetSplittableType() != NS_FRAME_NOT_SPLITTABLE,
    9253             :                "why CreateContinuingFrame for a non-splittable frame?");
    9254             : 
    9255           0 :   if (LayoutFrameType::Text == frameType) {
    9256           0 :     newFrame = NS_NewContinuingTextFrame(shell, styleContext);
    9257           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9258           0 :   } else if (LayoutFrameType::Inline == frameType) {
    9259           0 :     newFrame = NS_NewInlineFrame(shell, styleContext);
    9260           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9261           0 :   } else if (LayoutFrameType::Block == frameType) {
    9262           0 :     MOZ_ASSERT(!aFrame->IsTableCaption(),
    9263             :                "no support for fragmenting table captions yet");
    9264           0 :     newFrame = NS_NewBlockFrame(shell, styleContext);
    9265           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9266             : #ifdef MOZ_XUL
    9267           0 :   } else if (LayoutFrameType::XULLabel == frameType) {
    9268           0 :     newFrame = NS_NewXULLabelFrame(shell, styleContext);
    9269           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9270             : #endif
    9271           0 :   } else if (LayoutFrameType::ColumnSet == frameType) {
    9272           0 :     MOZ_ASSERT(!aFrame->IsTableCaption(),
    9273             :                "no support for fragmenting table captions yet");
    9274           0 :     newFrame = NS_NewColumnSetFrame(shell, styleContext, nsFrameState(0));
    9275           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9276           0 :   } else if (LayoutFrameType::Page == frameType) {
    9277             :     nsContainerFrame* canvasFrame;
    9278           0 :     newFrame = ConstructPageFrame(shell, aParentFrame, aFrame, canvasFrame);
    9279           0 :   } else if (LayoutFrameType::TableWrapper == frameType) {
    9280             :     newFrame =
    9281             :       CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
    9282           0 :                                       content, styleContext);
    9283             : 
    9284           0 :   } else if (LayoutFrameType::Table == frameType) {
    9285             :     newFrame =
    9286             :       CreateContinuingTableFrame(shell, aFrame, aParentFrame,
    9287           0 :                                  content, styleContext);
    9288             : 
    9289           0 :   } else if (LayoutFrameType::TableRowGroup == frameType) {
    9290           0 :     newFrame = NS_NewTableRowGroupFrame(shell, styleContext);
    9291           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9292           0 :     if (newFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
    9293           0 :       nsTableFrame::RegisterPositionedTablePart(newFrame);
    9294             :     }
    9295           0 :   } else if (LayoutFrameType::TableRow == frameType) {
    9296           0 :     nsTableRowFrame* rowFrame = NS_NewTableRowFrame(shell, styleContext);
    9297             : 
    9298           0 :     rowFrame->Init(content, aParentFrame, aFrame);
    9299           0 :     if (rowFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
    9300           0 :       nsTableFrame::RegisterPositionedTablePart(rowFrame);
    9301             :     }
    9302             : 
    9303             :     // Create a continuing frame for each table cell frame
    9304           0 :     nsFrameItems  newChildList;
    9305           0 :     nsIFrame* cellFrame = aFrame->PrincipalChildList().FirstChild();
    9306           0 :     while (cellFrame) {
    9307             :       // See if it's a table cell frame
    9308           0 :       if (IS_TABLE_CELL(cellFrame->Type())) {
    9309             :         nsIFrame* continuingCellFrame =
    9310           0 :           CreateContinuingFrame(aPresContext, cellFrame, rowFrame);
    9311           0 :         newChildList.AddChild(continuingCellFrame);
    9312             :       }
    9313           0 :       cellFrame = cellFrame->GetNextSibling();
    9314             :     }
    9315             : 
    9316           0 :     rowFrame->SetInitialChildList(kPrincipalList, newChildList);
    9317           0 :     newFrame = rowFrame;
    9318             : 
    9319           0 :   } else if (IS_TABLE_CELL(frameType)) {
    9320             :     // Warning: If you change this and add a wrapper frame around table cell
    9321             :     // frames, make sure Bug 368554 doesn't regress!
    9322             :     // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
    9323             :     nsTableFrame* tableFrame =
    9324           0 :       static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
    9325             :     nsTableCellFrame* cellFrame =
    9326           0 :       NS_NewTableCellFrame(shell, styleContext, tableFrame);
    9327             : 
    9328           0 :     cellFrame->Init(content, aParentFrame, aFrame);
    9329           0 :     if (cellFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
    9330           0 :       nsTableFrame::RegisterPositionedTablePart(cellFrame);
    9331             :     }
    9332             : 
    9333             :     // Create a continuing area frame
    9334           0 :     nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
    9335             :     nsIFrame* continuingBlockFrame =
    9336             :       CreateContinuingFrame(aPresContext, blockFrame,
    9337           0 :                             static_cast<nsContainerFrame*>(cellFrame));
    9338             : 
    9339           0 :     SetInitialSingleChild(cellFrame, continuingBlockFrame);
    9340           0 :     newFrame = cellFrame;
    9341           0 :   } else if (LayoutFrameType::Line == frameType) {
    9342           0 :     newFrame = NS_NewFirstLineFrame(shell, styleContext);
    9343           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9344           0 :   } else if (LayoutFrameType::Letter == frameType) {
    9345           0 :     newFrame = NS_NewFirstLetterFrame(shell, styleContext);
    9346           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9347           0 :   } else if (LayoutFrameType::Image == frameType) {
    9348           0 :     newFrame = NS_NewImageFrame(shell, styleContext);
    9349           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9350           0 :   } else if (LayoutFrameType::ImageControl == frameType) {
    9351           0 :     newFrame = NS_NewImageControlFrame(shell, styleContext);
    9352           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9353           0 :   } else if (LayoutFrameType::Placeholder == frameType) {
    9354             :     // create a continuing out of flow frame
    9355           0 :     nsIFrame* oofFrame = nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
    9356             :     nsIFrame* oofContFrame =
    9357           0 :       CreateContinuingFrame(aPresContext, oofFrame, aParentFrame);
    9358             :     newFrame =
    9359           0 :       CreatePlaceholderFrameFor(shell, content, oofContFrame,
    9360             :                                 aParentFrame, aFrame,
    9361           0 :                                 aFrame->GetStateBits() & PLACEHOLDER_TYPE_MASK);
    9362           0 :   } else if (LayoutFrameType::FieldSet == frameType) {
    9363           0 :     nsContainerFrame* fieldset = NS_NewFieldSetFrame(shell, styleContext);
    9364             : 
    9365           0 :     fieldset->Init(content, aParentFrame, aFrame);
    9366             : 
    9367             :     // Create a continuing area frame
    9368             :     // XXXbz we really shouldn't have to do this by hand!
    9369           0 :     nsContainerFrame* blockFrame = GetFieldSetBlockFrame(aFrame);
    9370           0 :     if (blockFrame) {
    9371             :       nsIFrame* continuingBlockFrame =
    9372           0 :         CreateContinuingFrame(aPresContext, blockFrame, fieldset);
    9373             :       // Set the fieldset's initial child list
    9374           0 :       SetInitialSingleChild(fieldset, continuingBlockFrame);
    9375             :     } else {
    9376           0 :       MOZ_ASSERT(aFrame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
    9377             :                  "FieldSet block may only be null for overflow containers");
    9378             :     }
    9379           0 :     newFrame = fieldset;
    9380           0 :   } else if (LayoutFrameType::Legend == frameType) {
    9381           0 :     newFrame = NS_NewLegendFrame(shell, styleContext);
    9382           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9383           0 :   } else if (LayoutFrameType::FlexContainer == frameType) {
    9384           0 :     newFrame = NS_NewFlexContainerFrame(shell, styleContext);
    9385           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9386           0 :   } else if (LayoutFrameType::GridContainer == frameType) {
    9387           0 :     newFrame = NS_NewGridContainerFrame(shell, styleContext);
    9388           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9389           0 :   } else if (LayoutFrameType::Ruby == frameType) {
    9390           0 :     newFrame = NS_NewRubyFrame(shell, styleContext);
    9391           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9392           0 :   } else if (LayoutFrameType::RubyBaseContainer == frameType) {
    9393           0 :     newFrame = NS_NewRubyBaseContainerFrame(shell, styleContext);
    9394           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9395           0 :   } else if (LayoutFrameType::RubyTextContainer == frameType) {
    9396           0 :     newFrame = NS_NewRubyTextContainerFrame(shell, styleContext);
    9397           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9398           0 :   } else if (LayoutFrameType::Details == frameType) {
    9399           0 :     newFrame = NS_NewDetailsFrame(shell, styleContext);
    9400           0 :     newFrame->Init(content, aParentFrame, aFrame);
    9401             :   } else {
    9402           0 :     MOZ_CRASH("unexpected frame type");
    9403             :   }
    9404             : 
    9405             :   // Init() set newFrame to be a fluid continuation of aFrame.
    9406             :   // If we want a non-fluid continuation, we need to call SetPrevContinuation()
    9407             :   // to reset NS_FRAME_IS_FLUID_CONTINUATION.
    9408           0 :   if (!aIsFluid) {
    9409           0 :     newFrame->SetPrevContinuation(aFrame);
    9410             :   }
    9411             : 
    9412             :   // A continuation of generated content is also generated content
    9413           0 :   if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
    9414           0 :     newFrame->AddStateBits(NS_FRAME_GENERATED_CONTENT);
    9415             :   }
    9416             : 
    9417             :   // A continuation of nsIAnonymousContentCreator content is also
    9418             :   // nsIAnonymousContentCreator created content
    9419           0 :   if (aFrame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
    9420           0 :     newFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
    9421             :   }
    9422             : 
    9423             :   // A continuation of an out-of-flow is also an out-of-flow
    9424           0 :   if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    9425           0 :     newFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
    9426             :   }
    9427             : 
    9428           0 :   if (nextInFlow) {
    9429           0 :     nextInFlow->SetPrevInFlow(newFrame);
    9430           0 :     newFrame->SetNextInFlow(nextInFlow);
    9431           0 :   } else if (nextContinuation) {
    9432           0 :     nextContinuation->SetPrevContinuation(newFrame);
    9433           0 :     newFrame->SetNextContinuation(nextContinuation);
    9434             :   }
    9435             : 
    9436           0 :   NS_POSTCONDITION(!newFrame->GetNextSibling(), "unexpected sibling");
    9437           0 :   return newFrame;
    9438             : }
    9439             : 
    9440             : nsresult
    9441           0 : nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
    9442             : {
    9443             :   // Now deal with fixed-pos things....  They should appear on all pages,
    9444             :   // so we want to move over the placeholders when processing the child
    9445             :   // of the pageContentFrame.
    9446             : 
    9447           0 :   nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
    9448           0 :   if (!prevPageContentFrame) {
    9449           0 :     return NS_OK;
    9450             :   }
    9451             :   nsContainerFrame* canvasFrame =
    9452           0 :     do_QueryFrame(aParentFrame->PrincipalChildList().FirstChild());
    9453           0 :   nsIFrame* prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
    9454           0 :   if (!canvasFrame || !prevCanvasFrame) {
    9455             :     // document's root element frame missing
    9456           0 :     return NS_ERROR_UNEXPECTED;
    9457             :   }
    9458             : 
    9459           0 :   nsFrameItems fixedPlaceholders;
    9460           0 :   nsIFrame* firstFixed = prevPageContentFrame->GetChildList(nsIFrame::kFixedList).FirstChild();
    9461           0 :   if (!firstFixed) {
    9462           0 :     return NS_OK;
    9463             :   }
    9464             : 
    9465             :   // Don't allow abs-pos descendants of the fixed content to escape the content.
    9466             :   // This should not normally be possible (because fixed-pos elements should
    9467             :   // be absolute containers) but fixed-pos tables currently aren't abs-pos
    9468             :   // containers.
    9469           0 :   TreeMatchContextHolder matchContext(mDocument);
    9470             :   nsFrameConstructorState state(mPresShell,
    9471             :                                 matchContext,
    9472             :                                 aParentFrame,
    9473             :                                 nullptr,
    9474           0 :                                 mRootElementFrame);
    9475           0 :   state.mCreatingExtraFrames = true;
    9476             : 
    9477             :   // We can't use an ancestor filter here, because we're not going to
    9478             :   // be usefully recurring down the tree.  This means that other
    9479             :   // places in frame construction can't assume a filter is
    9480             :   // initialized!
    9481             : 
    9482             :   // Iterate across fixed frames and replicate each whose placeholder is a
    9483             :   // descendant of aFrame. (We don't want to explicitly copy placeholders that
    9484             :   // are within fixed frames, because that would cause duplicates on the new
    9485             :   // page - bug 389619)
    9486           0 :   for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
    9487           0 :     nsIFrame* prevPlaceholder = fixed->GetPlaceholderFrame();
    9488           0 :     if (prevPlaceholder &&
    9489           0 :         nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) {
    9490             :       // We want to use the same style as the primary style frame for
    9491             :       // our content
    9492           0 :       nsIContent* content = fixed->GetContent();
    9493             :       nsStyleContext* styleContext =
    9494           0 :         nsLayoutUtils::GetStyleFrame(content)->StyleContext();
    9495           0 :       FrameConstructionItemList items;
    9496           0 :       AddFrameConstructionItemsInternal(state, content, canvasFrame,
    9497             :                                         content->NodeInfo()->NameAtom(),
    9498             :                                         content->GetNameSpaceID(),
    9499             :                                         true,
    9500             :                                         styleContext,
    9501             :                                         ITEM_ALLOW_XBL_BASE |
    9502             :                                           ITEM_ALLOW_PAGE_BREAK,
    9503           0 :                                         nullptr, items);
    9504           0 :       ConstructFramesFromItemList(state, items, canvasFrame, fixedPlaceholders);
    9505             :     }
    9506             :   }
    9507             : 
    9508             :   // Add the placeholders to our primary child list.
    9509             :   // XXXbz this is a little screwed up, since the fixed frames will have
    9510             :   // broken auto-positioning. Oh, well.
    9511           0 :   NS_ASSERTION(!canvasFrame->PrincipalChildList().FirstChild(),
    9512             :                "leaking frames; doc root continuation must be empty");
    9513           0 :   canvasFrame->SetInitialChildList(kPrincipalList, fixedPlaceholders);
    9514           0 :   return NS_OK;
    9515             : }
    9516             : 
    9517             : nsCSSFrameConstructor::InsertionPoint
    9518          90 : nsCSSFrameConstructor::GetInsertionPoint(nsIContent* aContainer,
    9519             :                                          nsIContent* aChild)
    9520             : {
    9521          90 :   nsBindingManager* bindingManager = mDocument->BindingManager();
    9522             : 
    9523             :   nsIContent* insertionElement;
    9524          90 :   if (aChild) {
    9525             :     // We've got an explicit insertion child. Check to see if it's
    9526             :     // anonymous.
    9527          49 :     if (aChild->GetBindingParent() == aContainer) {
    9528             :       // This child content is anonymous. Don't use the insertion
    9529             :       // point, since that's only for the explicit kids.
    9530           3 :       return InsertionPoint(GetContentInsertionFrameFor(aContainer), aContainer);
    9531             :     }
    9532             : 
    9533          46 :     if (nsContentUtils::HasDistributedChildren(aContainer)) {
    9534             :       // The container distributes nodes, use the frame of the flattened tree parent.
    9535             :       // It may be the case that the node is distributed but not matched to any
    9536             :       // insertion points, so there is no flattened parent.
    9537           0 :       nsIContent* flattenedParent = aChild->GetFlattenedTreeParent();
    9538           0 :       if (flattenedParent) {
    9539             :         return InsertionPoint(GetContentInsertionFrameFor(flattenedParent),
    9540           0 :                               flattenedParent);
    9541             :       }
    9542           0 :       return InsertionPoint();
    9543             :     }
    9544             : 
    9545          46 :     insertionElement = bindingManager->FindNestedInsertionPoint(aContainer, aChild);
    9546             :   } else {
    9547          41 :     if (nsContentUtils::HasDistributedChildren(aContainer)) {
    9548             :       // The container distributes nodes to shadow DOM insertion points.
    9549             :       // Return with aMultiple set to true to induce callers to insert children
    9550             :       // individually into the node's flattened tree parent.
    9551           4 :       return InsertionPoint(nullptr, nullptr, true);
    9552             :     }
    9553             : 
    9554             :     bool multiple;
    9555          41 :     insertionElement = bindingManager->FindNestedSingleInsertionPoint(aContainer, &multiple);
    9556          41 :     if (multiple) {
    9557           4 :       return InsertionPoint(nullptr, nullptr, true);
    9558             :     }
    9559             :   }
    9560             : 
    9561          83 :   if (!insertionElement) {
    9562             :     // The FindNested{,Single}InsertionPoint methods return null in the case
    9563             :     // that there is a binding with anonymous content but no insertion point.
    9564             :     // In that case the element doesn't belong in the flattened tree, and we
    9565             :     // don't want to render it.
    9566           0 :     return InsertionPoint();
    9567             :   }
    9568             : 
    9569             :   InsertionPoint insertion(GetContentInsertionFrameFor(insertionElement),
    9570          83 :                            insertionElement);
    9571             : 
    9572             :   // Fieldset frames have multiple normal flow child frame lists so handle it
    9573             :   // the same as if it had multiple content insertion points.
    9574          83 :   if (insertion.mParentFrame && insertion.mParentFrame->IsFieldSetFrame()) {
    9575           0 :     insertion.mMultiple = true;
    9576             :   }
    9577             : 
    9578             :   // A details frame moves the first summary frame to be its first child, so we
    9579             :   // treat it as if it has multiple content insertion points.
    9580          83 :   if (insertion.mParentFrame && insertion.mParentFrame->IsDetailsFrame()) {
    9581           0 :     insertion.mMultiple = true;
    9582             :   }
    9583             : 
    9584          83 :   return insertion;
    9585             : }
    9586             : 
    9587             : // Capture state for the frame tree rooted at the frame associated with the
    9588             : // content object, aContent
    9589             : void
    9590          17 : nsCSSFrameConstructor::CaptureStateForFramesOf(nsIContent* aContent,
    9591             :                                                nsILayoutHistoryState* aHistoryState)
    9592             : {
    9593          17 :   if (!aHistoryState) {
    9594           0 :     return;
    9595             :   }
    9596          17 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    9597          17 :   if (frame == mRootElementFrame) {
    9598           0 :     frame = mRootElementFrame ?
    9599           0 :       GetAbsoluteContainingBlock(mRootElementFrame, FIXED_POS) :
    9600           0 :       GetRootFrame();
    9601             :   }
    9602          45 :   for ( ; frame;
    9603             :         frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
    9604          14 :     CaptureFrameState(frame, aHistoryState);
    9605             :   }
    9606             : }
    9607             : 
    9608             : static bool
    9609           6 : DefinitelyEqualURIsAndPrincipal(mozilla::css::URLValue* aURI1,
    9610             :                                 mozilla::css::URLValue* aURI2)
    9611             : {
    9612          12 :   return aURI1 == aURI2 ||
    9613           6 :          (aURI1 && aURI2 && aURI1->DefinitelyEqualURIsAndPrincipal(*aURI2));
    9614             : }
    9615             : 
    9616             : nsStyleContext*
    9617          50 : nsCSSFrameConstructor::MaybeRecreateFramesForElement(Element* aElement)
    9618             : {
    9619         100 :   RefPtr<nsStyleContext> oldContext = GetUndisplayedContent(aElement);
    9620          50 :   StyleDisplay oldDisplay = StyleDisplay::None;
    9621          50 :   if (!oldContext) {
    9622          42 :     oldContext = GetDisplayContentsStyleFor(aElement);
    9623          42 :     if (!oldContext) {
    9624          42 :       return nullptr;
    9625             :     }
    9626           0 :     oldDisplay = StyleDisplay::Contents;
    9627             :   }
    9628             : 
    9629             :   // The parent has a frame, so try resolving a new context.
    9630          16 :   RefPtr<nsStyleContext> newContext = mPresShell->StyleSet()->
    9631          24 :     ResolveStyleFor(aElement, oldContext->GetParent(),
    9632          16 :                     LazyComputeBehavior::Assert);
    9633             : 
    9634           8 :   if (oldDisplay == StyleDisplay::None) {
    9635           8 :     ChangeUndisplayedContent(aElement, newContext);
    9636             :   } else {
    9637           0 :     ChangeDisplayContents(aElement, newContext);
    9638             :   }
    9639             : 
    9640           8 :   const nsStyleDisplay* disp = newContext->StyleDisplay();
    9641           8 :   if (oldDisplay == disp->mDisplay) {
    9642             :     // We can skip trying to recreate frames here, but only if our style
    9643             :     // context does not have a binding URI that differs from our old one.
    9644             :     // Otherwise, we should try to recreate, because we may want to apply the
    9645             :     // new binding
    9646           6 :     if (!disp->mBinding) {
    9647           0 :       return newContext;
    9648             :     }
    9649           6 :     const nsStyleDisplay* oldDisp = oldContext->PeekStyleDisplay();
    9650          12 :     if (oldDisp &&
    9651           6 :         DefinitelyEqualURIsAndPrincipal(disp->mBinding, oldDisp->mBinding)) {
    9652           6 :       return newContext;
    9653             :     }
    9654             :   }
    9655             : 
    9656           2 :   RecreateFramesForContent(aElement, false, REMOVE_FOR_RECONSTRUCTION, nullptr);
    9657           2 :   return nullptr;
    9658             : }
    9659             : 
    9660             : static bool
    9661          18 : IsWhitespaceFrame(nsIFrame* aFrame)
    9662             : {
    9663          18 :   MOZ_ASSERT(aFrame, "invalid argument");
    9664          18 :   return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
    9665             : }
    9666             : 
    9667             : static nsIFrame*
    9668           0 : FindFirstNonWhitespaceChild(nsIFrame* aParentFrame)
    9669             : {
    9670           0 :   nsIFrame* f = aParentFrame->PrincipalChildList().FirstChild();
    9671           0 :   while (f && IsWhitespaceFrame(f)) {
    9672           0 :     f = f->GetNextSibling();
    9673             :   }
    9674           0 :   return f;
    9675             : }
    9676             : 
    9677             : static nsIFrame*
    9678          33 : FindNextNonWhitespaceSibling(nsIFrame* aFrame)
    9679             : {
    9680          33 :   nsIFrame* f = aFrame;
    9681          33 :   do {
    9682          33 :     f = f->GetNextSibling();
    9683          33 :   } while (f && IsWhitespaceFrame(f));
    9684          33 :   return f;
    9685             : }
    9686             : 
    9687             : static nsIFrame*
    9688           0 : FindPreviousNonWhitespaceSibling(nsIFrame* aFrame)
    9689             : {
    9690           0 :   nsIFrame* f = aFrame;
    9691           0 :   do {
    9692           0 :     f = f->GetPrevSibling();
    9693           0 :   } while (f && IsWhitespaceFrame(f));
    9694           0 :   return f;
    9695             : }
    9696             : 
    9697             : bool
    9698          33 : nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
    9699             :                                                              RemoveFlags aFlags,
    9700             :                                                              nsIContent** aDestroyedFramesFor)
    9701             : {
    9702          33 :   NS_PRECONDITION(aFrame, "Must have a frame");
    9703          33 :   NS_PRECONDITION(aFrame->GetParent(), "Frame shouldn't be root");
    9704          33 :   NS_PRECONDITION(aFrame == aFrame->FirstContinuation(),
    9705             :                   "aFrame not the result of GetPrimaryFrame()?");
    9706             : 
    9707          33 :   *aDestroyedFramesFor = nullptr;
    9708             : 
    9709          33 :   if (IsFramePartOfIBSplit(aFrame)) {
    9710             :     // The removal functions can't handle removal of an {ib} split directly; we
    9711             :     // need to rebuild the containing block.
    9712             : #ifdef DEBUG
    9713           0 :     if (gNoisyContentUpdates) {
    9714             :       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    9715           0 :              "frame=");
    9716           0 :       nsFrame::ListTag(stdout, aFrame);
    9717           0 :       printf(" is ib-split\n");
    9718             :     }
    9719             : #endif
    9720             : 
    9721           0 :     ReframeContainingBlock(aFrame, aFlags, aDestroyedFramesFor);
    9722           0 :     return true;
    9723             :   }
    9724             : 
    9725          33 :   nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame();
    9726          33 :   if (insertionFrame && insertionFrame->IsLegendFrame() &&
    9727           0 :       aFrame->GetParent()->IsFieldSetFrame()) {
    9728             :     // When we remove the legend for a fieldset, we should reframe
    9729             :     // the fieldset to ensure another legend is used, if there is one
    9730           0 :     RecreateFramesForContent(aFrame->GetParent()->GetContent(), false,
    9731           0 :                              aFlags, aDestroyedFramesFor);
    9732           0 :     return true;
    9733             :   }
    9734             : 
    9735             :   nsIFrame* inFlowFrame =
    9736          33 :     (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) ?
    9737          33 :       aFrame->GetPlaceholderFrame() : aFrame;
    9738          33 :   MOZ_ASSERT(inFlowFrame, "How did that happen?");
    9739          33 :   MOZ_ASSERT(inFlowFrame == inFlowFrame->FirstContinuation(),
    9740             :              "placeholder for primary frame has previous continuations?");
    9741          33 :   nsIFrame* parent = inFlowFrame->GetParent();
    9742             : 
    9743          33 :   if (parent && parent->IsDetailsFrame()) {
    9744             :     HTMLSummaryElement* summary =
    9745           0 :       HTMLSummaryElement::FromContent(aFrame->GetContent());
    9746           0 :     DetailsFrame* detailsFrame = static_cast<DetailsFrame*>(parent);
    9747             : 
    9748             :     // Unlike adding summary element cases, we need to check children of the
    9749             :     // parent details frame since at this moment the summary element has been
    9750             :     // already removed from the parent details element's child list.
    9751           0 :     if (summary && detailsFrame->HasMainSummaryFrame(aFrame)) {
    9752             :       // When removing a summary, we should reframe the parent details frame to
    9753             :       // ensure that another summary is used or the default summary is
    9754             :       // generated.
    9755           0 :       RecreateFramesForContent(parent->GetContent(),
    9756             :                                false, REMOVE_FOR_RECONSTRUCTION,
    9757           0 :                                aDestroyedFramesFor);
    9758           0 :       return true;
    9759             :     }
    9760             :   }
    9761             : 
    9762             :   // Now check for possibly needing to reconstruct due to a pseudo parent
    9763             :   // For the case of ruby pseudo parent, effectively, only pseudo rb/rt frame
    9764             :   // need to be checked here, since all other types of parent will be catched
    9765             :   // by "Check ruby containers" section below.
    9766          33 :   if (IsTableOrRubyPseudo(parent)) {
    9767           0 :     if (FindFirstNonWhitespaceChild(parent) == inFlowFrame ||
    9768           0 :         !FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation()) ||
    9769             :         // If it is a whitespace, and is the only child of the parent, the
    9770             :         // pseudo parent was created for the space, and should now be removed.
    9771           0 :         (IsWhitespaceFrame(aFrame) &&
    9772           0 :          parent->PrincipalChildList().OnlyChild()) ||
    9773             :         // If we're a table-column-group, then the OnlyChild check above is
    9774             :         // not going to catch cases when we're the first child.
    9775           0 :         (inFlowFrame->IsTableColGroupFrame() &&
    9776           0 :          parent->GetChildList(nsIFrame::kColGroupList).FirstChild() == inFlowFrame) ||
    9777             :         // Similar if we're a table-caption.
    9778           0 :         (inFlowFrame->IsTableCaption() &&
    9779           0 :          parent->GetChildList(nsIFrame::kCaptionList).FirstChild() == inFlowFrame)) {
    9780             :       // We're the first or last frame in the pseudo.  Need to reframe.
    9781             :       // Good enough to recreate frames for |parent|'s content
    9782           0 :       RecreateFramesForContent(parent->GetContent(), true, aFlags,
    9783           0 :                                aDestroyedFramesFor);
    9784           0 :       return true;
    9785             :     }
    9786             :   }
    9787             : 
    9788             :   // Might need to reconstruct things if this frame's nextSibling is a table
    9789             :   // or ruby pseudo, since removal of this frame might mean that this pseudo
    9790             :   // needs to get merged with the frame's prevSibling if that's also a table
    9791             :   // or ruby pseudo.
    9792             :   nsIFrame* nextSibling =
    9793          33 :     FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation());
    9794          33 :   NS_ASSERTION(!IsTableOrRubyPseudo(inFlowFrame), "Shouldn't happen here");
    9795             :   // Effectively, for the ruby pseudo sibling case, only pseudo <ruby> frame
    9796             :   // need to be checked here, since all other types of such frames will have
    9797             :   // a ruby container parent, and be catched by "Check ruby containers" below.
    9798          33 :   if (nextSibling && IsTableOrRubyPseudo(nextSibling)) {
    9799           0 :     nsIFrame* prevSibling = FindPreviousNonWhitespaceSibling(inFlowFrame);
    9800           0 :     if (prevSibling && IsTableOrRubyPseudo(prevSibling)) {
    9801             : #ifdef DEBUG
    9802           0 :       if (gNoisyContentUpdates) {
    9803             :         printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    9804           0 :                "frame=");
    9805           0 :         nsFrame::ListTag(stdout, aFrame);
    9806             :         printf(" has a table pseudo next sibling of different type and a "
    9807           0 :                "table pseudo prevsibling\n");
    9808             :       }
    9809             : #endif
    9810             :       // Good enough to recreate frames for aFrame's parent's content; even if
    9811             :       // aFrame's parent is a pseudo, that'll be the right content node.
    9812           0 :       RecreateFramesForContent(parent->GetContent(), true, aFlags,
    9813           0 :                                aDestroyedFramesFor);
    9814           0 :       return true;
    9815             :     }
    9816             :   }
    9817             : 
    9818             :   // Check ruby containers
    9819          33 :   LayoutFrameType parentType = parent->Type();
    9820          66 :   if (parentType == LayoutFrameType::Ruby ||
    9821          33 :       RubyUtils::IsRubyContainerBox(parentType)) {
    9822             :     // In ruby containers, pseudo frames may be created from
    9823             :     // whitespaces or even nothing. There are two cases we actually
    9824             :     // need to handle here, but hard to check exactly:
    9825             :     // 1. Status of spaces beside the frame may vary, and related
    9826             :     //    frames may be constructed or destroyed accordingly.
    9827             :     // 2. The type of the first child of a ruby frame determines
    9828             :     //    whether a pseudo ruby base container should exist.
    9829           0 :     RecreateFramesForContent(parent->GetContent(), true, aFlags,
    9830           0 :                              aDestroyedFramesFor);
    9831           0 :     return true;
    9832             :   }
    9833             : 
    9834             :   // Might need to reconstruct things if the removed frame's nextSibling is an
    9835             :   // anonymous flex item.  The removed frame might've been what divided two
    9836             :   // runs of inline content into two anonymous flex items, which would now
    9837             :   // need to be merged.
    9838             :   // NOTE: It's fine that we've advanced nextSibling past whitespace (up above);
    9839             :   // we're only interested in anonymous flex items here, and those can never
    9840             :   // be adjacent to whitespace, since they absorb contiguous runs of inline
    9841             :   // non-replaced content (including whitespace).
    9842          33 :   if (nextSibling && IsAnonymousFlexOrGridItem(nextSibling)) {
    9843           0 :     AssertAnonymousFlexOrGridItemParent(nextSibling, parent);
    9844             : #ifdef DEBUG
    9845           0 :     if (gNoisyContentUpdates) {
    9846             :       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    9847           0 :              "frame=");
    9848           0 :       nsFrame::ListTag(stdout, aFrame);
    9849           0 :       printf(" has an anonymous flex item as its next sibling\n");
    9850             :     }
    9851             : #endif // DEBUG
    9852             :     // Recreate frames for the flex container (the removed frame's parent)
    9853           0 :     RecreateFramesForContent(parent->GetContent(), true, aFlags,
    9854           0 :                              aDestroyedFramesFor);
    9855           0 :     return true;
    9856             :   }
    9857             : 
    9858             :   // Might need to reconstruct things if the removed frame's nextSibling is
    9859             :   // null and its parent is an anonymous flex item. (This might be the last
    9860             :   // remaining child of that anonymous flex item, which can then go away.)
    9861          33 :   if (!nextSibling && IsAnonymousFlexOrGridItem(parent)) {
    9862           0 :     AssertAnonymousFlexOrGridItemParent(parent, parent->GetParent());
    9863             : #ifdef DEBUG
    9864           0 :     if (gNoisyContentUpdates) {
    9865             :       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    9866           0 :              "frame=");
    9867           0 :       nsFrame::ListTag(stdout, aFrame);
    9868           0 :       printf(" has an anonymous flex item as its parent\n");
    9869             :     }
    9870             : #endif // DEBUG
    9871             :     // Recreate frames for the flex container (the removed frame's grandparent)
    9872           0 :     RecreateFramesForContent(parent->GetParent()->GetContent(), true,
    9873           0 :                              aFlags, aDestroyedFramesFor);
    9874           0 :     return true;
    9875             :   }
    9876             : 
    9877             : #ifdef MOZ_XUL
    9878          33 :   if (aFrame->IsPopupSetFrame()) {
    9879           0 :     nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
    9880           0 :     if (rootBox && rootBox->GetPopupSetFrame() == aFrame) {
    9881           0 :       ReconstructDocElementHierarchy();
    9882           0 :       return true;
    9883             :     }
    9884             :   }
    9885             : #endif
    9886             : 
    9887             :   // Reconstruct if inflowFrame is parent's only child, and parent is, or has,
    9888             :   // a non-fluid continuation, i.e. it was split by bidi resolution
    9889          87 :   if (!inFlowFrame->GetPrevSibling() &&
    9890          48 :       !inFlowFrame->GetNextSibling() &&
    9891          30 :       ((parent->GetPrevContinuation() && !parent->GetPrevInFlow()) ||
    9892          15 :        (parent->GetNextContinuation() && !parent->GetNextInFlow()))) {
    9893           0 :     RecreateFramesForContent(parent->GetContent(), true, aFlags,
    9894           0 :                              aDestroyedFramesFor);
    9895           0 :     return true;
    9896             :   }
    9897             : 
    9898             :   // We might still need to reconstruct things if the parent of inFlowFrame is
    9899             :   // ib-split, since in that case the removal of aFrame might affect the
    9900             :   // splitting of its parent.
    9901          33 :   if (!IsFramePartOfIBSplit(parent)) {
    9902          33 :     return false;
    9903             :   }
    9904             : 
    9905             :   // If inFlowFrame is not the only in-flow child of |parent|, then removing
    9906             :   // it will change nothing about the {ib} split.
    9907           0 :   if (inFlowFrame != parent->PrincipalChildList().FirstChild() ||
    9908           0 :       inFlowFrame->LastContinuation()->GetNextSibling()) {
    9909           0 :     return false;
    9910             :   }
    9911             : 
    9912             :   // If the parent is the first or last part of the {ib} split, then
    9913             :   // removing one of its kids will have no effect on the splitting.
    9914             :   // Get the first continuation up front so we don't have to do it twice.
    9915           0 :   nsIFrame* parentFirstContinuation = parent->FirstContinuation();
    9916           0 :   if (!GetIBSplitSibling(parentFirstContinuation) ||
    9917           0 :       !GetIBSplitPrevSibling(parentFirstContinuation)) {
    9918           0 :     return false;
    9919             :   }
    9920             : 
    9921             : #ifdef DEBUG
    9922           0 :   if (gNoisyContentUpdates) {
    9923             :     printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    9924           0 :            "frame=");
    9925           0 :     nsFrame::ListTag(stdout, parent);
    9926           0 :     printf(" is ib-split\n");
    9927             :   }
    9928             : #endif
    9929             : 
    9930           0 :   ReframeContainingBlock(parent, aFlags, aDestroyedFramesFor);
    9931           0 :   return true;
    9932             : }
    9933             : 
    9934             : void
    9935          17 : nsCSSFrameConstructor::RecreateFramesForContent(nsIContent*  aContent,
    9936             :                                                 bool         aAsyncInsert,
    9937             :                                                 RemoveFlags  aFlags,
    9938             :                                                 nsIContent** aDestroyedFramesFor)
    9939             : {
    9940          17 :   NS_PRECONDITION(!aAsyncInsert || aContent->IsElement(),
    9941             :                   "Can only insert elements async");
    9942             :   // If there is no document, we don't want to recreate frames for it.  (You
    9943             :   // shouldn't generally be giving this method content without a document
    9944             :   // anyway).
    9945             :   // Rebuilding the frame tree can have bad effects, especially if it's the
    9946             :   // frame tree for chrome (see bug 157322).
    9947          17 :   if (NS_WARN_IF(!aContent->GetComposedDoc())) {
    9948           0 :     return;
    9949             :   }
    9950             : 
    9951             :   // Is the frame ib-split? If so, we need to reframe the containing
    9952             :   // block *here*, rather than trying to remove and re-insert the
    9953             :   // content (which would otherwise result in *two* nested reframe
    9954             :   // containing block from ContentRemoved() and ContentInserted(),
    9955             :   // below!).  We'd really like to optimize away one of those
    9956             :   // containing block reframes, hence the code here.
    9957             : 
    9958          17 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    9959          17 :   if (frame && frame->IsFrameOfType(nsIFrame::eMathML)) {
    9960             :     // Reframe the topmost MathML element to prevent exponential blowup
    9961             :     // (see bug 397518)
    9962             :     while (true) {
    9963           0 :       nsIContent* parentContent = aContent->GetParent();
    9964           0 :       nsIFrame* parentContentFrame = parentContent->GetPrimaryFrame();
    9965           0 :       if (!parentContentFrame || !parentContentFrame->IsFrameOfType(nsIFrame::eMathML))
    9966           0 :         break;
    9967           0 :       aContent = parentContent;
    9968           0 :       frame = parentContentFrame;
    9969           0 :     }
    9970             :   }
    9971             : 
    9972          17 :   if (frame) {
    9973          14 :     nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(frame);
    9974          14 :     if (nonGeneratedAncestor->GetContent() != aContent) {
    9975           0 :       return RecreateFramesForContent(nonGeneratedAncestor->GetContent(), aAsyncInsert,
    9976           0 :                                       aFlags, aDestroyedFramesFor);
    9977             :     }
    9978             : 
    9979          14 :     if (frame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
    9980             :       // Recreate the frames for the entire nsIAnonymousContentCreator tree
    9981             :       // since |frame| or one of its descendants may need an nsStyleContext
    9982             :       // that associates it to a CSS pseudo-element, and only the
    9983             :       // nsIAnonymousContentCreator that created this content knows how to make
    9984             :       // that happen.
    9985           0 :       nsIAnonymousContentCreator* acc = nullptr;
    9986           0 :       nsIFrame* ancestor = nsLayoutUtils::GetParentOrPlaceholderFor(frame);
    9987           0 :       while (!(acc = do_QueryFrame(ancestor))) {
    9988           0 :         ancestor = nsLayoutUtils::GetParentOrPlaceholderFor(ancestor);
    9989             :       }
    9990           0 :       NS_ASSERTION(acc, "Where is the nsIAnonymousContentCreator? We may fail "
    9991             :                         "to recreate its content correctly");
    9992             :       // nsSVGUseFrame is special, and we know this is unnecessary for it.
    9993           0 :       if (!ancestor->IsSVGUseFrame()) {
    9994           0 :         NS_ASSERTION(aContent->IsInNativeAnonymousSubtree(),
    9995             :                      "Why is NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT set?");
    9996           0 :         return RecreateFramesForContent(ancestor->GetContent(), aAsyncInsert,
    9997           0 :                                         aFlags, aDestroyedFramesFor);
    9998             :       }
    9999             :     }
   10000             : 
   10001          14 :     nsIFrame* parent = frame->GetParent();
   10002          14 :     nsIContent* parentContent = parent ? parent->GetContent() : nullptr;
   10003             :     // If the parent frame is a leaf then the subsequent insert will fail to
   10004             :     // create a frame, so we need to recreate the parent content. This happens
   10005             :     // with native anonymous content from the editor.
   10006          14 :     if (parent && parent->IsLeaf() && parentContent &&
   10007             :         parentContent != aContent) {
   10008           0 :       return RecreateFramesForContent(parentContent, aAsyncInsert, aFlags,
   10009           0 :                                       aDestroyedFramesFor);
   10010             :     }
   10011             :   }
   10012             : 
   10013             :   nsIContent* container;
   10014          17 :   if (frame && MaybeRecreateContainerForFrameRemoval(frame, aFlags,
   10015             :                                                      &container)) {
   10016           0 :     MOZ_ASSERT(container);
   10017           0 :     if (aDestroyedFramesFor) {
   10018           0 :       *aDestroyedFramesFor = container;
   10019             :     }
   10020           0 :     return;
   10021             :   }
   10022             : 
   10023          17 :   nsINode* containerNode = aContent->GetParentNode();
   10024             :   // XXXbz how can containerNode be null here?
   10025          17 :   if (containerNode) {
   10026             :     // Before removing the frames associated with the content object,
   10027             :     // ask them to save their state onto a temporary state object.
   10028          17 :     CaptureStateForFramesOf(aContent, mTempFrameTreeState);
   10029             : 
   10030             :     // Need the nsIContent parent, which might be null here, since we need to
   10031             :     // pass it to ContentInserted and ContentRemoved.
   10032          34 :     nsCOMPtr<nsIContent> container = aContent->GetParent();
   10033             : 
   10034             :     // Remove the frames associated with the content object.
   10035             :     bool didReconstruct;
   10036          30 :     nsIContent* nextSibling = aContent->IsRootOfAnonymousSubtree() ?
   10037          30 :       nullptr : aContent->GetNextSibling();
   10038          17 :     const bool reconstruct = aFlags != REMOVE_DESTROY_FRAMES;
   10039          17 :     RemoveFlags flags = reconstruct ? REMOVE_FOR_RECONSTRUCTION : aFlags;
   10040          17 :     ContentRemoved(container, aContent, nextSibling, flags,
   10041          17 :                    &didReconstruct, aDestroyedFramesFor);
   10042          17 :     if (reconstruct && !didReconstruct) {
   10043             :       // Now, recreate the frames associated with this content object. If
   10044             :       // ContentRemoved triggered reconstruction, then we don't need to do this
   10045             :       // because the frames will already have been built.
   10046          17 :       if (aAsyncInsert) {
   10047             :         // XXXmats doesn't frame state need to be restored in this case too?
   10048           0 :         RestyleManager()->PostRestyleEvent(
   10049           0 :           aContent->AsElement(), nsRestyleHint(0), nsChangeHint_ReconstructFrame);
   10050             :       } else {
   10051          17 :         ContentRangeInserted(container, aContent, aContent->GetNextSibling(),
   10052             :                              mTempFrameTreeState,
   10053             :                              false, // aAllowLazyConstruction
   10054             :                              true,  // aForReconstruction
   10055          17 :                              nullptr);
   10056             :       }
   10057             :     }
   10058             :   }
   10059             : }
   10060             : 
   10061             : void
   10062           0 : nsCSSFrameConstructor::DestroyFramesFor(nsIContent*  aContent,
   10063             :                                         nsIContent** aDestroyedFramesFor)
   10064             : {
   10065           0 :   MOZ_ASSERT(aContent && aContent->GetParentNode());
   10066             : 
   10067             :   bool didReconstruct;
   10068             :   nsIContent* nextSibling =
   10069           0 :     aContent->IsRootOfAnonymousSubtree() ? nullptr : aContent->GetNextSibling();
   10070           0 :   ContentRemoved(aContent->GetParent(), aContent, nextSibling,
   10071           0 :                  REMOVE_DESTROY_FRAMES, &didReconstruct, aDestroyedFramesFor);
   10072           0 : }
   10073             : 
   10074             : //////////////////////////////////////////////////////////////////////
   10075             : 
   10076             : // Block frame construction code
   10077             : 
   10078             : already_AddRefed<nsStyleContext>
   10079           0 : nsCSSFrameConstructor::GetFirstLetterStyle(nsIContent* aContent,
   10080             :                                            nsStyleContext* aStyleContext)
   10081             : {
   10082           0 :   if (aContent) {
   10083           0 :     return mPresShell->StyleSet()->
   10084             :       ResolvePseudoElementStyle(aContent->AsElement(),
   10085             :                                 CSSPseudoElementType::firstLetter,
   10086             :                                 aStyleContext,
   10087           0 :                                 nullptr);
   10088             :   }
   10089           0 :   return nullptr;
   10090             : }
   10091             : 
   10092             : already_AddRefed<nsStyleContext>
   10093           0 : nsCSSFrameConstructor::GetFirstLineStyle(nsIContent* aContent,
   10094             :                                          nsStyleContext* aStyleContext)
   10095             : {
   10096           0 :   if (aContent) {
   10097           0 :     return mPresShell->StyleSet()->
   10098             :       ResolvePseudoElementStyle(aContent->AsElement(),
   10099             :                                 CSSPseudoElementType::firstLine,
   10100             :                                 aStyleContext,
   10101           0 :                                 nullptr);
   10102             :   }
   10103           0 :   return nullptr;
   10104             : }
   10105             : 
   10106             : // Predicate to see if a given content (block element) has
   10107             : // first-letter style applied to it.
   10108             : bool
   10109          22 : nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(nsIContent* aContent,
   10110             :                                                   nsStyleContext* aStyleContext)
   10111             : {
   10112          22 :   return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
   10113             :                                        CSSPseudoElementType::firstLetter,
   10114          44 :                                        mPresShell->GetPresContext());
   10115             : }
   10116             : 
   10117             : bool
   10118          15 : nsCSSFrameConstructor::HasFirstLetterStyle(nsIFrame* aBlockFrame)
   10119             : {
   10120          15 :   NS_PRECONDITION(aBlockFrame, "Need a frame");
   10121          15 :   NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
   10122             :                "Not a block frame?");
   10123             : 
   10124          15 :   return (aBlockFrame->GetStateBits() & NS_BLOCK_HAS_FIRST_LETTER_STYLE) != 0;
   10125             : }
   10126             : 
   10127             : bool
   10128          31 : nsCSSFrameConstructor::ShouldHaveFirstLineStyle(nsIContent* aContent,
   10129             :                                                 nsStyleContext* aStyleContext)
   10130             : {
   10131             :   bool hasFirstLine =
   10132          31 :     nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
   10133             :                                   CSSPseudoElementType::firstLine,
   10134          62 :                                   mPresShell->GetPresContext());
   10135          31 :   if (hasFirstLine) {
   10136             :     // But disable for fieldsets
   10137             :     int32_t namespaceID;
   10138           0 :     nsIAtom* tag = mDocument->BindingManager()->ResolveTag(aContent,
   10139           0 :                                                            &namespaceID);
   10140             :     // This check must match the one in FindHTMLData.
   10141           0 :     hasFirstLine = tag != nsGkAtoms::fieldset ||
   10142           0 :       namespaceID != kNameSpaceID_XHTML;
   10143             :   }
   10144             : 
   10145          31 :   return hasFirstLine;
   10146             : }
   10147             : 
   10148             : void
   10149          22 : nsCSSFrameConstructor::ShouldHaveSpecialBlockStyle(nsIContent* aContent,
   10150             :                                                    nsStyleContext* aStyleContext,
   10151             :                                                    bool* aHaveFirstLetterStyle,
   10152             :                                                    bool* aHaveFirstLineStyle)
   10153             : {
   10154          22 :   *aHaveFirstLetterStyle =
   10155          22 :     ShouldHaveFirstLetterStyle(aContent, aStyleContext);
   10156          22 :   *aHaveFirstLineStyle =
   10157          22 :     ShouldHaveFirstLineStyle(aContent, aStyleContext);
   10158          22 : }
   10159             : 
   10160             : /* static */
   10161             : const nsCSSFrameConstructor::PseudoParentData
   10162             : nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
   10163             :   { // Cell
   10164             :     FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
   10165             :                      FCDATA_USE_CHILD_ITEMS |
   10166             :                      FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
   10167             :                      &nsCSSFrameConstructor::ConstructTableCell),
   10168             :     &nsCSSAnonBoxes::tableCell
   10169             :   },
   10170             :   { // Row
   10171             :     FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
   10172             :                      FCDATA_USE_CHILD_ITEMS |
   10173             :                      FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
   10174             :                      &nsCSSFrameConstructor::ConstructTableRowOrRowGroup),
   10175             :     &nsCSSAnonBoxes::tableRow
   10176             :   },
   10177             :   { // Row group
   10178             :     FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
   10179             :                      FCDATA_USE_CHILD_ITEMS |
   10180             :                      FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
   10181             :                      &nsCSSFrameConstructor::ConstructTableRowOrRowGroup),
   10182             :     &nsCSSAnonBoxes::tableRowGroup
   10183             :   },
   10184             :   { // Column group
   10185             :     FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
   10186             :                 FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
   10187             :                 FCDATA_SKIP_ABSPOS_PUSH |
   10188             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
   10189             :                 NS_NewTableColGroupFrame),
   10190             :     &nsCSSAnonBoxes::tableColGroup
   10191             :   },
   10192             :   { // Table
   10193             :     FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS,
   10194             :                      &nsCSSFrameConstructor::ConstructTable),
   10195             :     &nsCSSAnonBoxes::table
   10196             :   },
   10197             :   { // Ruby
   10198             :     FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
   10199             :                 FCDATA_USE_CHILD_ITEMS |
   10200             :                 FCDATA_SKIP_FRAMESET,
   10201             :                 NS_NewRubyFrame),
   10202             :     &nsCSSAnonBoxes::ruby
   10203             :   },
   10204             :   { // Ruby Base
   10205             :     FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
   10206             :                 FCDATA_IS_LINE_PARTICIPANT |
   10207             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer) |
   10208             :                 FCDATA_SKIP_FRAMESET,
   10209             :                 NS_NewRubyBaseFrame),
   10210             :     &nsCSSAnonBoxes::rubyBase
   10211             :   },
   10212             :   { // Ruby Base Container
   10213             :     FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
   10214             :                 FCDATA_IS_LINE_PARTICIPANT |
   10215             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby) |
   10216             :                 FCDATA_SKIP_FRAMESET,
   10217             :                 NS_NewRubyBaseContainerFrame),
   10218             :     &nsCSSAnonBoxes::rubyBaseContainer
   10219             :   },
   10220             :   { // Ruby Text
   10221             :     FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
   10222             :                 FCDATA_IS_LINE_PARTICIPANT |
   10223             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer) |
   10224             :                 FCDATA_SKIP_FRAMESET,
   10225             :                 NS_NewRubyTextFrame),
   10226             :     &nsCSSAnonBoxes::rubyText
   10227             :   },
   10228             :   { // Ruby Text Container
   10229             :     FCDATA_DECL(FCDATA_USE_CHILD_ITEMS |
   10230             :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby) |
   10231             :                 FCDATA_SKIP_FRAMESET,
   10232             :                 NS_NewRubyTextContainerFrame),
   10233             :     &nsCSSAnonBoxes::rubyTextContainer
   10234             :   }
   10235             : };
   10236             : 
   10237             : void
   10238         413 : nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
   10239             :   nsFrameConstructorState& aState,
   10240             :   FrameConstructionItemList& aItems,
   10241             :   nsIFrame* aParentFrame)
   10242             : {
   10243         413 :   if (aItems.IsEmpty()) {
   10244         539 :     return;
   10245             :   }
   10246         287 :   const LayoutFrameType parentType = aParentFrame->Type();
   10247         287 :   if (parentType != LayoutFrameType::FlexContainer &&
   10248             :       parentType != LayoutFrameType::GridContainer) {
   10249         287 :     return;
   10250             :   }
   10251             : 
   10252           0 :   const bool isWebkitBox = IsFlexContainerForLegacyBox(aParentFrame);
   10253           0 :   FCItemIterator iter(aItems);
   10254           0 :   do {
   10255             :     // Advance iter past children that don't want to be wrapped
   10256           0 :     if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState, isWebkitBox)) {
   10257             :       // Hit the end of the items without finding any remaining children that
   10258             :       // need to be wrapped. We're finished!
   10259           0 :       return;
   10260             :     }
   10261             : 
   10262             :     // If our next potentially-wrappable child is whitespace, then see if
   10263             :     // there's anything wrappable immediately after it. If not, we just drop
   10264             :     // the whitespace and move on. (We're not supposed to create any anonymous
   10265             :     // flex/grid items that _only_ contain whitespace).
   10266             :     // (BUT if this is generated content, then we don't give whitespace nodes
   10267             :     // any special treatment, because they're probably not really whitespace --
   10268             :     // they're just temporarily empty, waiting for their generated text.)
   10269             :     // XXXdholbert If this node's generated text will *actually end up being
   10270             :     // entirely whitespace*, then we technically should still skip over it, per
   10271             :     // the CSS grid & flexbox specs. I'm not bothering with that at this point,
   10272             :     // since it's a pretty extreme edge case.
   10273           0 :     if (!aParentFrame->IsGeneratedContentFrame() &&
   10274           0 :         iter.item().IsWhitespace(aState)) {
   10275           0 :       FCItemIterator afterWhitespaceIter(iter);
   10276           0 :       bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
   10277             :       bool nextChildNeedsAnonItem =
   10278           0 :         !hitEnd &&
   10279           0 :         afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox);
   10280             : 
   10281           0 :       if (!nextChildNeedsAnonItem) {
   10282             :         // There's nothing after the whitespace that we need to wrap, so we
   10283             :         // just drop this run of whitespace.
   10284           0 :         iter.DeleteItemsTo(afterWhitespaceIter);
   10285           0 :         if (hitEnd) {
   10286             :           // Nothing left to do -- we're finished!
   10287           0 :           return;
   10288             :         }
   10289             :         // else, we have a next child and it does not want to be wrapped.  So,
   10290             :         // we jump back to the beginning of the loop to skip over that child
   10291             :         // (and anything else non-wrappable after it)
   10292           0 :         MOZ_ASSERT(!iter.IsDone() &&
   10293             :                    !iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox),
   10294             :                    "hitEnd and/or nextChildNeedsAnonItem lied");
   10295           0 :         continue;
   10296             :       }
   10297             :     }
   10298             : 
   10299             :     // Now |iter| points to the first child that needs to be wrapped in an
   10300             :     // anonymous flex/grid item. Now we see how many children after it also want
   10301             :     // to be wrapped in an anonymous flex/grid item.
   10302           0 :     FCItemIterator endIter(iter); // iterator to find the end of the group
   10303           0 :     endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isWebkitBox);
   10304             : 
   10305           0 :     NS_ASSERTION(iter != endIter,
   10306             :                  "Should've had at least one wrappable child to seek past");
   10307             : 
   10308             :     // Now, we create the anonymous flex or grid item to contain the children
   10309             :     // between |iter| and |endIter|.
   10310           0 :     nsIAtom* pseudoType = (aParentFrame->IsFlexContainerFrame())
   10311             :                             ? nsCSSAnonBoxes::anonymousFlexItem
   10312           0 :                             : nsCSSAnonBoxes::anonymousGridItem;
   10313           0 :     nsStyleContext* parentStyle = aParentFrame->StyleContext();
   10314           0 :     nsIContent* parentContent = aParentFrame->GetContent();
   10315             :     already_AddRefed<nsStyleContext> wrapperStyle =
   10316           0 :       mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(pseudoType,
   10317           0 :                                                                  parentStyle);
   10318             : 
   10319             :     static const FrameConstructionData sBlockFormattingContextFCData =
   10320             :       FCDATA_DECL(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS,
   10321             :                   NS_NewBlockFormattingContext);
   10322             : 
   10323             :     FrameConstructionItem* newItem =
   10324             :       new FrameConstructionItem(&sBlockFormattingContextFCData,
   10325             :                                 // Use the content of our parent frame
   10326             :                                 parentContent,
   10327             :                                 // Lie about the tag; it doesn't matter anyway
   10328             :                                 pseudoType,
   10329           0 :                                 iter.item().mNameSpaceID,
   10330             :                                 // no pending binding
   10331             :                                 nullptr,
   10332             :                                 wrapperStyle,
   10333           0 :                                 true, nullptr);
   10334             : 
   10335           0 :     newItem->mIsAllInline = newItem->mHasInlineEnds =
   10336           0 :       newItem->mStyleContext->StyleDisplay()->IsInlineOutsideStyle();
   10337           0 :     newItem->mIsBlock = !newItem->mIsAllInline;
   10338             : 
   10339           0 :     MOZ_ASSERT(!newItem->mIsAllInline && newItem->mIsBlock,
   10340             :                "expecting anonymous flex/grid items to be block-level "
   10341             :                "(this will make a difference when we encounter "
   10342             :                "'align-items: baseline')");
   10343             : 
   10344             :     // Anonymous flex and grid items induce line boundaries around their
   10345             :     // contents.
   10346           0 :     newItem->mChildItems.SetLineBoundaryAtStart(true);
   10347           0 :     newItem->mChildItems.SetLineBoundaryAtEnd(true);
   10348             :     // The parent of the items in aItems is also the parent of the items
   10349             :     // in mChildItems
   10350           0 :     newItem->mChildItems.SetParentHasNoXBLChildren(
   10351           0 :       aItems.ParentHasNoXBLChildren());
   10352             : 
   10353             :     // Eat up all items between |iter| and |endIter| and put them in our
   10354             :     // wrapper. This advances |iter| to point to |endIter|.
   10355           0 :     iter.AppendItemsToList(endIter, newItem->mChildItems);
   10356             : 
   10357           0 :     iter.InsertItem(newItem);
   10358           0 :   } while (!iter.IsDone());
   10359             : }
   10360             : 
   10361             : /* static */ nsCSSFrameConstructor::RubyWhitespaceType
   10362           0 : nsCSSFrameConstructor::ComputeRubyWhitespaceType(StyleDisplay aPrevDisplay,
   10363             :                                                  StyleDisplay aNextDisplay)
   10364             : {
   10365           0 :   MOZ_ASSERT(nsStyleDisplay::IsRubyDisplayType(aPrevDisplay) &&
   10366             :              nsStyleDisplay::IsRubyDisplayType(aNextDisplay));
   10367           0 :   if (aPrevDisplay == aNextDisplay &&
   10368           0 :       (aPrevDisplay == StyleDisplay::RubyBase ||
   10369             :        aPrevDisplay == StyleDisplay::RubyText)) {
   10370           0 :     return eRubyInterLeafWhitespace;
   10371             :   }
   10372           0 :   if (aNextDisplay == StyleDisplay::RubyText ||
   10373             :       aNextDisplay == StyleDisplay::RubyTextContainer) {
   10374           0 :     return eRubyInterLevelWhitespace;
   10375             :   }
   10376           0 :   return eRubyInterSegmentWhitespace;
   10377             : }
   10378             : 
   10379             : /**
   10380             :  * This function checks the content from |aStartIter| to |aEndIter|,
   10381             :  * determines whether it contains only whitespace, and if yes,
   10382             :  * interprets the type of whitespace. This method does not change
   10383             :  * any of the iters.
   10384             :  */
   10385             : /* static */ nsCSSFrameConstructor::RubyWhitespaceType
   10386           0 : nsCSSFrameConstructor::InterpretRubyWhitespace(nsFrameConstructorState& aState,
   10387             :                                                const FCItemIterator& aStartIter,
   10388             :                                                const FCItemIterator& aEndIter)
   10389             : {
   10390           0 :   if (!aStartIter.item().IsWhitespace(aState)) {
   10391           0 :     return eRubyNotWhitespace;
   10392             :   }
   10393             : 
   10394           0 :   FCItemIterator spaceEndIter(aStartIter);
   10395           0 :   spaceEndIter.SkipWhitespace(aState);
   10396           0 :   if (spaceEndIter != aEndIter) {
   10397           0 :     return eRubyNotWhitespace;
   10398             :   }
   10399             : 
   10400             :   // Any leading or trailing whitespace in non-pseudo ruby box
   10401             :   // should have been trimmed, hence there should not be any
   10402             :   // whitespace at the start or the end.
   10403           0 :   MOZ_ASSERT(!aStartIter.AtStart() && !aEndIter.IsDone());
   10404           0 :   FCItemIterator prevIter(aStartIter);
   10405           0 :   prevIter.Prev();
   10406             :   return ComputeRubyWhitespaceType(
   10407           0 :       prevIter.item().mStyleContext->StyleDisplay()->mDisplay,
   10408           0 :       aEndIter.item().mStyleContext->StyleDisplay()->mDisplay);
   10409             : }
   10410             : 
   10411             : 
   10412             : /**
   10413             :  * This function eats up consecutive items which do not want the current
   10414             :  * parent into either a ruby base box or a ruby text box.  When it
   10415             :  * returns, |aIter| points to the first item it doesn't wrap.
   10416             :  */
   10417             : void
   10418           0 : nsCSSFrameConstructor::WrapItemsInPseudoRubyLeafBox(
   10419             :   FCItemIterator& aIter,
   10420             :   nsStyleContext* aParentStyle, nsIContent* aParentContent)
   10421             : {
   10422           0 :   StyleDisplay parentDisplay = aParentStyle->StyleDisplay()->mDisplay;
   10423             :   ParentType parentType, wrapperType;
   10424           0 :   if (parentDisplay == StyleDisplay::RubyTextContainer) {
   10425           0 :     parentType = eTypeRubyTextContainer;
   10426           0 :     wrapperType = eTypeRubyText;
   10427             :   } else {
   10428           0 :     MOZ_ASSERT(parentDisplay == StyleDisplay::RubyBaseContainer);
   10429           0 :     parentType = eTypeRubyBaseContainer;
   10430           0 :     wrapperType = eTypeRubyBase;
   10431             :   }
   10432             : 
   10433           0 :   MOZ_ASSERT(aIter.item().DesiredParentType() != parentType,
   10434             :              "Should point to something needs to be wrapped.");
   10435             : 
   10436           0 :   FCItemIterator endIter(aIter);
   10437           0 :   endIter.SkipItemsNotWantingParentType(parentType);
   10438             : 
   10439             :   WrapItemsInPseudoParent(aParentContent, aParentStyle,
   10440           0 :                           wrapperType, aIter, endIter);
   10441           0 : }
   10442             : 
   10443             : /**
   10444             :  * This function eats up consecutive items into a ruby level container.
   10445             :  * It may create zero or one level container. When it returns, |aIter|
   10446             :  * points to the first item it doesn't wrap.
   10447             :  */
   10448             : void
   10449           0 : nsCSSFrameConstructor::WrapItemsInPseudoRubyLevelContainer(
   10450             :   nsFrameConstructorState& aState, FCItemIterator& aIter,
   10451             :   nsStyleContext* aParentStyle, nsIContent* aParentContent)
   10452             : {
   10453           0 :   MOZ_ASSERT(aIter.item().DesiredParentType() != eTypeRuby,
   10454             :              "Pointing to a level container?");
   10455             : 
   10456           0 :   FrameConstructionItem& firstItem = aIter.item();
   10457           0 :   ParentType wrapperType = firstItem.DesiredParentType();
   10458           0 :   if (wrapperType != eTypeRubyTextContainer) {
   10459             :     // If the first item is not ruby text,
   10460             :     // it should be in a base container.
   10461           0 :     wrapperType = eTypeRubyBaseContainer;
   10462             :   }
   10463             : 
   10464           0 :   FCItemIterator endIter(aIter);
   10465           0 :   do {
   10466           0 :     if (endIter.SkipItemsWantingParentType(wrapperType) ||
   10467             :         // If the skipping above stops at some item which wants a
   10468             :         // different ruby parent, then we have finished.
   10469           0 :         IsRubyParentType(endIter.item().DesiredParentType())) {
   10470             :       // No more items need to be wrapped in this level container.
   10471           0 :       break;
   10472             :     }
   10473             : 
   10474           0 :     FCItemIterator contentEndIter(endIter);
   10475           0 :     contentEndIter.SkipItemsNotWantingRubyParent();
   10476             :     // endIter must be on something doesn't want a ruby parent.
   10477           0 :     MOZ_ASSERT(contentEndIter != endIter);
   10478             : 
   10479             :     // InterpretRubyWhitespace depends on the fact that any leading or
   10480             :     // trailing whitespace described in the spec have been trimmed at
   10481             :     // this point. With this precondition, it is safe not to check
   10482             :     // whether contentEndIter has been done.
   10483             :     RubyWhitespaceType whitespaceType =
   10484           0 :       InterpretRubyWhitespace(aState, endIter, contentEndIter);
   10485           0 :     if (whitespaceType == eRubyInterLevelWhitespace) {
   10486             :       // Remove inter-level whitespace.
   10487           0 :       bool atStart = (aIter == endIter);
   10488           0 :       endIter.DeleteItemsTo(contentEndIter);
   10489           0 :       if (atStart) {
   10490           0 :         aIter = endIter;
   10491             :       }
   10492           0 :     } else if (whitespaceType == eRubyInterSegmentWhitespace) {
   10493             :       // If this level container starts with inter-segment whitespaces,
   10494             :       // wrap them. Break at contentEndIter. Otherwise, leave it here.
   10495             :       // Break at endIter. They will be wrapped when we are here again.
   10496           0 :       if (aIter == endIter) {
   10497           0 :         MOZ_ASSERT(wrapperType == eTypeRubyBaseContainer,
   10498             :                    "Inter-segment whitespace should be wrapped in rbc");
   10499           0 :         endIter = contentEndIter;
   10500             :       }
   10501           0 :       break;
   10502           0 :     } else if (wrapperType == eTypeRubyTextContainer &&
   10503             :                whitespaceType != eRubyInterLeafWhitespace) {
   10504             :       // Misparented inline content that's not inter-annotation
   10505             :       // whitespace doesn't belong in a pseudo ruby text container.
   10506             :       // Break at endIter.
   10507             :       break;
   10508             :     } else {
   10509           0 :       endIter = contentEndIter;
   10510             :     }
   10511           0 :   } while (!endIter.IsDone());
   10512             : 
   10513             :   // It is possible that everything our parent wants us to wrap is
   10514             :   // simply an inter-level whitespace, which has been trimmed, or
   10515             :   // an inter-segment whitespace, which will be wrapped later.
   10516             :   // In those cases, don't create anything.
   10517           0 :   if (aIter != endIter) {
   10518             :     WrapItemsInPseudoParent(aParentContent, aParentStyle,
   10519           0 :                             wrapperType, aIter, endIter);
   10520             :   }
   10521           0 : }
   10522             : 
   10523             : /**
   10524             :  * This function trims leading and trailing whitespaces
   10525             :  * in the given item list.
   10526             :  */
   10527             : void
   10528           0 : nsCSSFrameConstructor::TrimLeadingAndTrailingWhitespaces(
   10529             :     nsFrameConstructorState& aState,
   10530             :     FrameConstructionItemList& aItems)
   10531             : {
   10532           0 :   FCItemIterator iter(aItems);
   10533           0 :   if (!iter.IsDone() &&
   10534           0 :       iter.item().IsWhitespace(aState)) {
   10535           0 :     FCItemIterator spaceEndIter(iter);
   10536           0 :     spaceEndIter.SkipWhitespace(aState);
   10537           0 :     iter.DeleteItemsTo(spaceEndIter);
   10538             :   }
   10539             : 
   10540           0 :   iter.SetToEnd();
   10541           0 :   if (!iter.AtStart()) {
   10542           0 :     FCItemIterator spaceEndIter(iter);
   10543           0 :     do {
   10544           0 :       iter.Prev();
   10545           0 :       if (iter.AtStart()) {
   10546             :         // It's fine to not check the first item, because we
   10547             :         // should have trimmed leading whitespaces above.
   10548           0 :         break;
   10549             :       }
   10550           0 :     } while (iter.item().IsWhitespace(aState));
   10551           0 :     iter.Next();
   10552           0 :     if (iter != spaceEndIter) {
   10553           0 :       iter.DeleteItemsTo(spaceEndIter);
   10554             :     }
   10555             :   }
   10556           0 : }
   10557             : 
   10558             : /**
   10559             :  * This function walks through the child list (aItems) and creates
   10560             :  * needed pseudo ruby boxes to wrap misparented children.
   10561             :  */
   10562             : void
   10563         413 : nsCSSFrameConstructor::CreateNeededPseudoInternalRubyBoxes(
   10564             :   nsFrameConstructorState& aState,
   10565             :   FrameConstructionItemList& aItems,
   10566             :   nsIFrame* aParentFrame)
   10567             : {
   10568         413 :   const ParentType ourParentType = GetParentType(aParentFrame);
   10569         413 :   if (!IsRubyParentType(ourParentType) ||
   10570           0 :       aItems.AllWantParentType(ourParentType)) {
   10571         413 :     return;
   10572             :   }
   10573             : 
   10574           0 :   if (!IsRubyPseudo(aParentFrame)) {
   10575             :     // Normally, ruby pseudo frames start from and end at some elements,
   10576             :     // which means they don't have leading and trailing whitespaces at
   10577             :     // all.  But there are two cases where they do actually have leading
   10578             :     // or trailing whitespaces:
   10579             :     // 1. It is an inter-segment whitespace which in an individual ruby
   10580             :     //    base container.
   10581             :     // 2. The pseudo frame starts from or ends at consecutive inline
   10582             :     //    content, which is not pure whitespace, but includes some.
   10583             :     // In either case, the whitespaces are not the leading or trailing
   10584             :     // whitespaces defined in the spec, and thus should not be trimmed.
   10585           0 :     TrimLeadingAndTrailingWhitespaces(aState, aItems);
   10586             :   }
   10587             : 
   10588           0 :   FCItemIterator iter(aItems);
   10589           0 :   nsIContent* parentContent = aParentFrame->GetContent();
   10590           0 :   nsStyleContext* parentStyle = aParentFrame->StyleContext();
   10591           0 :   while (!iter.IsDone()) {
   10592           0 :     if (!iter.SkipItemsWantingParentType(ourParentType)) {
   10593           0 :       if (ourParentType == eTypeRuby) {
   10594             :         WrapItemsInPseudoRubyLevelContainer(aState, iter, parentStyle,
   10595           0 :                                             parentContent);
   10596             :       } else {
   10597           0 :         WrapItemsInPseudoRubyLeafBox(iter, parentStyle, parentContent);
   10598             :       }
   10599             :     }
   10600             :   }
   10601             : }
   10602             : 
   10603             : /*
   10604             :  * This function works as follows: we walk through the child list (aItems) and
   10605             :  * find items that cannot have aParentFrame as their parent.  We wrap
   10606             :  * continuous runs of such items into a FrameConstructionItem for a frame that
   10607             :  * gets them closer to their desired parents.  For example, a run of non-row
   10608             :  * children of a row-group will get wrapped in a row.  When we later construct
   10609             :  * the frame for this wrapper (in this case for the row), it'll be the correct
   10610             :  * parent for the cells in the set of items we wrapped or we'll wrap cells
   10611             :  * around everything else.  At the end of this method, aItems is guaranteed to
   10612             :  * contain only items for frames that can be direct kids of aParentFrame.
   10613             :  */
   10614             : void
   10615         413 : nsCSSFrameConstructor::CreateNeededPseudoContainers(
   10616             :     nsFrameConstructorState& aState,
   10617             :     FrameConstructionItemList& aItems,
   10618             :     nsIFrame* aParentFrame)
   10619             : {
   10620         413 :   ParentType ourParentType = GetParentType(aParentFrame);
   10621         826 :   if (IsRubyParentType(ourParentType) ||
   10622         413 :       aItems.AllWantParentType(ourParentType)) {
   10623             :     // Nothing to do here
   10624         826 :     return;
   10625             :   }
   10626             : 
   10627           0 :   FCItemIterator iter(aItems);
   10628           0 :   do {
   10629           0 :     if (iter.SkipItemsWantingParentType(ourParentType)) {
   10630             :       // Nothing else to do here; we're finished
   10631           0 :       return;
   10632             :     }
   10633             : 
   10634             :     // Now we're pointing to the first child that wants a different parent
   10635             :     // type.
   10636             : 
   10637             :     // Now try to figure out what kids we can group together.  We can generally
   10638             :     // group everything that has a different desired parent type from us.  Two
   10639             :     // exceptions to this:
   10640             :     // 1) If our parent type is table, we can't group columns with anything
   10641             :     //    else other than whitespace.
   10642             :     // 2) Whitespace that lies between two things we can group which both want
   10643             :     //    a non-block parent should be dropped, even if we can't group them
   10644             :     //    with each other and even if the whitespace wants a parent of
   10645             :     //    ourParentType.  Ends of the list count as things that don't want a
   10646             :     //    block parent (so that for example we'll drop a whitespace-only list).
   10647             : 
   10648           0 :     FCItemIterator endIter(iter); /* iterator to find the end of the group */
   10649           0 :     ParentType groupingParentType = endIter.item().DesiredParentType();
   10650           0 :     if (aItems.AllWantParentType(groupingParentType) &&
   10651             :         groupingParentType != eTypeBlock) {
   10652             :       // Just group them all and be done with it.  We need the check for
   10653             :       // eTypeBlock here to catch the "all the items are whitespace" case
   10654             :       // described above.
   10655           0 :       endIter.SetToEnd();
   10656             :     } else {
   10657             :       // Locate the end of the group.
   10658             : 
   10659             :       // Keep track of the type the previous item wanted, in case we have to
   10660             :       // deal with whitespace.  Start it off with ourParentType, since that's
   10661             :       // the last thing |iter| would have skipped over.
   10662           0 :       ParentType prevParentType = ourParentType;
   10663           0 :       do {
   10664             :         // Walk an iterator past any whitespace that we might be able to drop
   10665             :         // from the list
   10666           0 :         FCItemIterator spaceEndIter(endIter);
   10667           0 :         if (prevParentType != eTypeBlock &&
   10668           0 :             !aParentFrame->IsGeneratedContentFrame() &&
   10669           0 :             spaceEndIter.item().IsWhitespace(aState)) {
   10670           0 :           bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
   10671             : 
   10672             :           // We drop the whitespace in the following cases:
   10673             :           // 1) If these are not trailing spaces and the next item wants a table
   10674             :           //    or table-part parent
   10675             :           // 2) If these are trailing spaces and aParentFrame is a
   10676             :           //    tabular container according to rule 1.3 of CSS 2.1 Sec 17.2.1.
   10677             :           //    (Being a tabular container pretty much means ourParentType is
   10678             :           //    not eTypeBlock besides the eTypeColGroup case, which won't
   10679             :           //    reach here.)
   10680           0 :           if ((!trailingSpaces &&
   10681           0 :                IsTableParentType(spaceEndIter.item().DesiredParentType())) ||
   10682           0 :               (trailingSpaces && ourParentType != eTypeBlock)) {
   10683           0 :             bool updateStart = (iter == endIter);
   10684           0 :             endIter.DeleteItemsTo(spaceEndIter);
   10685           0 :             NS_ASSERTION(trailingSpaces == endIter.IsDone(),
   10686             :                          "These should match");
   10687             : 
   10688           0 :             if (updateStart) {
   10689           0 :               iter = endIter;
   10690             :             }
   10691             : 
   10692           0 :             if (trailingSpaces) {
   10693           0 :               break; /* Found group end */
   10694             :             }
   10695             : 
   10696           0 :             if (updateStart) {
   10697             :               // Update groupingParentType, since it might have been eTypeBlock
   10698             :               // just because of the whitespace.
   10699           0 :               groupingParentType = iter.item().DesiredParentType();
   10700             :             }
   10701             :           }
   10702             :         }
   10703             : 
   10704             :         // Now endIter points to a non-whitespace item or a non-droppable
   10705             :         // whitespace item. In the latter case, if this is the end of the group
   10706             :         // we'll traverse this whitespace again.  But it'll all just be quick
   10707             :         // DesiredParentType() checks which will match ourParentType (that's
   10708             :         // what it means that this is the group end), so it's OK.
   10709             :         // However, when we are grouping a ruby parent, and endIter points to
   10710             :         // a non-droppable whitespace, if the next non-whitespace item also
   10711             :         // wants a ruby parent, the whitespace should also be included into
   10712             :         // the current ruby container.
   10713           0 :         prevParentType = endIter.item().DesiredParentType();
   10714           0 :         if (prevParentType == ourParentType &&
   10715           0 :             (endIter == spaceEndIter ||
   10716           0 :              spaceEndIter.IsDone() ||
   10717           0 :              !IsRubyParentType(groupingParentType) ||
   10718           0 :              !IsRubyParentType(spaceEndIter.item().DesiredParentType()))) {
   10719             :           // End the group at endIter.
   10720           0 :           break;
   10721             :         }
   10722             : 
   10723           0 :         if (ourParentType == eTypeTable &&
   10724           0 :             (prevParentType == eTypeColGroup) !=
   10725             :             (groupingParentType == eTypeColGroup)) {
   10726             :           // Either we started with columns and now found something else, or vice
   10727             :           // versa.  In any case, end the grouping.
   10728           0 :           break;
   10729             :         }
   10730             : 
   10731             :         // If we have some whitespace that we were not able to drop and there is
   10732             :         // an item after the whitespace that is already properly parented, then
   10733             :         // make sure to include the spaces in our group but stop the group after
   10734             :         // that.
   10735           0 :         if (spaceEndIter != endIter &&
   10736           0 :             !spaceEndIter.IsDone() &&
   10737           0 :             ourParentType == spaceEndIter.item().DesiredParentType()) {
   10738           0 :             endIter = spaceEndIter;
   10739           0 :             break;
   10740             :         }
   10741             : 
   10742             :         // Include the whitespace we didn't drop (if any) in the group.
   10743           0 :         endIter = spaceEndIter;
   10744           0 :         prevParentType = endIter.item().DesiredParentType();
   10745             : 
   10746           0 :         endIter.Next();
   10747           0 :       } while (!endIter.IsDone());
   10748             :     }
   10749             : 
   10750           0 :     if (iter == endIter) {
   10751             :       // Nothing to wrap here; just skipped some whitespace
   10752           0 :       continue;
   10753             :     }
   10754             : 
   10755             :     // Now group together all the items between iter and endIter.  The right
   10756             :     // parent type to use depends on ourParentType.
   10757             :     ParentType wrapperType;
   10758           0 :     switch (ourParentType) {
   10759             :       case eTypeRow:
   10760             :         // The parent type for a cell is eTypeBlock, since that's what a cell
   10761             :         // looks like to its kids.
   10762           0 :         wrapperType = eTypeBlock;
   10763           0 :         break;
   10764             :       case eTypeRowGroup:
   10765           0 :         wrapperType = eTypeRow;
   10766           0 :         break;
   10767             :       case eTypeTable:
   10768             :         // Either colgroup or rowgroup, depending on what we're grouping.
   10769           0 :         wrapperType = groupingParentType == eTypeColGroup ?
   10770             :           eTypeColGroup : eTypeRowGroup;
   10771           0 :         break;
   10772             :       case eTypeColGroup:
   10773           0 :         MOZ_CRASH("Colgroups should be suppresing non-col child items");
   10774             :       default:
   10775           0 :         NS_ASSERTION(ourParentType == eTypeBlock, "Unrecognized parent type");
   10776           0 :         if (IsRubyParentType(groupingParentType)) {
   10777           0 :           wrapperType = eTypeRuby;
   10778             :         } else {
   10779           0 :           NS_ASSERTION(IsTableParentType(groupingParentType),
   10780             :                        "groupingParentType should be either Ruby or table");
   10781           0 :           wrapperType = eTypeTable;
   10782             :         }
   10783             :     }
   10784             : 
   10785           0 :     nsStyleContext* parentStyle = aParentFrame->StyleContext();
   10786           0 :     WrapItemsInPseudoParent(aParentFrame->GetContent(), parentStyle,
   10787           0 :                             wrapperType, iter, endIter);
   10788             : 
   10789             :     // Now |iter| points to the item that was the first one we didn't wrap;
   10790             :     // loop and see whether we need to skip it or wrap it in something
   10791             :     // different.
   10792           0 :   } while (!iter.IsDone());
   10793             : }
   10794             : 
   10795             : /**
   10796             :  * This method wraps frame construction item from |aIter| to
   10797             :  * |aEndIter|. After it returns, aIter points to the first item
   10798             :  * after the wrapper.
   10799             :  */
   10800             : void
   10801           0 : nsCSSFrameConstructor::WrapItemsInPseudoParent(nsIContent* aParentContent,
   10802             :                                                nsStyleContext* aParentStyle,
   10803             :                                                ParentType aWrapperType,
   10804             :                                                FCItemIterator& aIter,
   10805             :                                                const FCItemIterator& aEndIter)
   10806             : {
   10807           0 :   const PseudoParentData& pseudoData = sPseudoParentData[aWrapperType];
   10808           0 :   nsIAtom* pseudoType = *pseudoData.mPseudoType;
   10809           0 :   StyleDisplay parentDisplay = aParentStyle->StyleDisplay()->mDisplay;
   10810             : 
   10811           0 :   if (pseudoType == nsCSSAnonBoxes::table &&
   10812           0 :       (parentDisplay == StyleDisplay::Inline ||
   10813           0 :        parentDisplay == StyleDisplay::RubyBase ||
   10814             :        parentDisplay == StyleDisplay::RubyText)) {
   10815           0 :     pseudoType = nsCSSAnonBoxes::inlineTable;
   10816             :   }
   10817             : 
   10818             :   already_AddRefed<nsStyleContext> wrapperStyle =
   10819           0 :     mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(pseudoType,
   10820           0 :                                                                aParentStyle);
   10821             :   FrameConstructionItem* newItem =
   10822             :     new FrameConstructionItem(&pseudoData.mFCData,
   10823             :                               // Use the content of our parent frame
   10824             :                               aParentContent,
   10825             :                               // Lie about the tag; it doesn't matter anyway
   10826             :                               pseudoType,
   10827             :                               // The namespace does matter, however; it needs
   10828             :                               // to match that of our first child item to
   10829             :                               // match the old behavior
   10830           0 :                               aIter.item().mNameSpaceID,
   10831             :                               // no pending binding
   10832             :                               nullptr,
   10833             :                               wrapperStyle,
   10834           0 :                               true, nullptr);
   10835             : 
   10836           0 :   const nsStyleDisplay* disp = newItem->mStyleContext->StyleDisplay();
   10837             :   // Here we're cheating a tad... technically, table-internal items should be
   10838             :   // inline if aParentFrame is inline, but they'll get wrapped in an
   10839             :   // inline-table in the end, so it'll all work out.  In any case, arguably
   10840             :   // we don't need to maintain this state at this point... but it's better
   10841             :   // to, I guess.
   10842           0 :   newItem->mIsAllInline = newItem->mHasInlineEnds =
   10843           0 :     disp->IsInlineOutsideStyle();
   10844             : 
   10845           0 :   bool isRuby = disp->IsRubyDisplayType();
   10846             :   // All types of ruby frames need a block frame to provide line layout,
   10847             :   // hence they are always line participant.
   10848           0 :   newItem->mIsLineParticipant = isRuby;
   10849             : 
   10850           0 :   if (!isRuby) {
   10851             :     // Table pseudo frames always induce line boundaries around their
   10852             :     // contents.
   10853           0 :     newItem->mChildItems.SetLineBoundaryAtStart(true);
   10854           0 :     newItem->mChildItems.SetLineBoundaryAtEnd(true);
   10855             :   }
   10856             :   // The parent of the items in aItems is also the parent of the items
   10857             :   // in mChildItems
   10858           0 :   newItem->mChildItems.SetParentHasNoXBLChildren(
   10859           0 :       aIter.List()->ParentHasNoXBLChildren());
   10860             : 
   10861             :   // Eat up all items between |aIter| and |aEndIter| and put them in our
   10862             :   // wrapper Advances |aIter| to point to |aEndIter|.
   10863           0 :   aIter.AppendItemsToList(aEndIter, newItem->mChildItems);
   10864             : 
   10865           0 :   aIter.InsertItem(newItem);
   10866           0 : }
   10867             : 
   10868             : void
   10869         413 : nsCSSFrameConstructor::CreateNeededPseudoSiblings(
   10870             :     nsFrameConstructorState& aState,
   10871             :     FrameConstructionItemList& aItems,
   10872             :     nsIFrame* aParentFrame)
   10873             : {
   10874         700 :   if (aItems.IsEmpty() ||
   10875         287 :       GetParentType(aParentFrame) != eTypeRuby) {
   10876         826 :     return;
   10877             :   }
   10878             : 
   10879           0 :   FCItemIterator iter(aItems);
   10880           0 :   StyleDisplay firstDisplay = iter.item().mStyleContext->StyleDisplay()->mDisplay;
   10881           0 :   if (firstDisplay == StyleDisplay::RubyBaseContainer) {
   10882           0 :     return;
   10883             :   }
   10884           0 :   NS_ASSERTION(firstDisplay == StyleDisplay::RubyTextContainer,
   10885             :                "Child of ruby frame should either a rbc or a rtc");
   10886             : 
   10887             :   const PseudoParentData& pseudoData =
   10888           0 :     sPseudoParentData[eTypeRubyBaseContainer];
   10889           0 :   already_AddRefed<nsStyleContext> pseudoStyle = mPresShell->StyleSet()->
   10890           0 :     ResolveInheritingAnonymousBoxStyle(*pseudoData.mPseudoType,
   10891           0 :                                        aParentFrame->StyleContext());
   10892             :   FrameConstructionItem* newItem =
   10893             :     new FrameConstructionItem(&pseudoData.mFCData,
   10894             :                               // Use the content of the parent frame
   10895           0 :                               aParentFrame->GetContent(),
   10896             :                               // Tag type
   10897           0 :                               *pseudoData.mPseudoType,
   10898             :                               // Use the namespace of the rtc frame
   10899           0 :                               iter.item().mNameSpaceID,
   10900             :                               // no pending binding
   10901             :                               nullptr,
   10902             :                               pseudoStyle,
   10903           0 :                               true, nullptr);
   10904           0 :   newItem->mIsAllInline = true;
   10905           0 :   newItem->mChildItems.SetParentHasNoXBLChildren(true);
   10906           0 :   iter.InsertItem(newItem);
   10907             : }
   10908             : 
   10909             : #ifdef DEBUG
   10910             : /**
   10911             :  * Returns true iff aFrame should be wrapped in an anonymous flex/grid item,
   10912             :  * rather than being a direct child of aContainerFrame.
   10913             :  *
   10914             :  * NOTE: aContainerFrame must be a flex or grid container - this function is
   10915             :  * purely for sanity-checking the children of these container types.
   10916             :  * NOTE: See also NeedsAnonFlexOrGridItem(), for the non-debug version of this
   10917             :  * logic (which operates a bit earlier, on FCData instead of frames).
   10918             :  */
   10919             : static bool
   10920           0 : FrameWantsToBeInAnonymousItem(const nsIFrame* aContainerFrame,
   10921             :                               const nsIFrame* aFrame)
   10922             : {
   10923           0 :   LayoutFrameType containerType = aContainerFrame->Type();
   10924           0 :   MOZ_ASSERT(containerType == LayoutFrameType::FlexContainer ||
   10925             :              containerType == LayoutFrameType::GridContainer);
   10926             : 
   10927             :   // Any line-participant frames (e.g. text) definitely want to be wrapped in
   10928             :   // an anonymous flex/grid item.
   10929           0 :   if (aFrame->IsFrameOfType(nsIFrame::eLineParticipant)) {
   10930           0 :     return true;
   10931             :   }
   10932             : 
   10933             :   // If the container is a -webkit-box/-webkit-inline-box, then placeholders
   10934             :   // also need to be wrapped, for compatibility.
   10935           0 :   if (containerType == LayoutFrameType::FlexContainer &&
   10936           0 :       aContainerFrame->HasAnyStateBits(NS_STATE_FLEX_IS_LEGACY_WEBKIT_BOX) &&
   10937           0 :       aFrame->IsPlaceholderFrame()) {
   10938           0 :     return true;
   10939             :   }
   10940             : 
   10941           0 :   return false;
   10942             : }
   10943             : #endif
   10944             : 
   10945             : static void
   10946         413 : VerifyGridFlexContainerChildren(nsIFrame* aParentFrame,
   10947             :                                 const nsFrameList& aChildren)
   10948             : {
   10949             : #ifdef DEBUG
   10950         413 :   auto parentType = aParentFrame->Type();
   10951         413 :   if (parentType != LayoutFrameType::FlexContainer &&
   10952             :       parentType != LayoutFrameType::GridContainer) {
   10953         413 :     return;
   10954             :   }
   10955             : 
   10956           0 :   bool prevChildWasAnonItem = false;
   10957           0 :   for (const nsIFrame* child : aChildren) {
   10958           0 :     MOZ_ASSERT(!FrameWantsToBeInAnonymousItem(aParentFrame, child),
   10959             :                "frame wants to be inside an anonymous item, but it isn't");
   10960           0 :     if (IsAnonymousFlexOrGridItem(child)) {
   10961           0 :       AssertAnonymousFlexOrGridItemParent(child, aParentFrame);
   10962           0 :       MOZ_ASSERT(!prevChildWasAnonItem, "two anon items in a row");
   10963           0 :       nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
   10964           0 :       MOZ_ASSERT(firstWrappedChild, "anonymous item shouldn't be empty");
   10965           0 :       prevChildWasAnonItem = true;
   10966             :     } else {
   10967           0 :       prevChildWasAnonItem = false;
   10968             :     }
   10969             :   }
   10970             : #endif
   10971             : }
   10972             : 
   10973             : inline void
   10974         413 : nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aState,
   10975             :                                                    FrameConstructionItemList& aItems,
   10976             :                                                    nsContainerFrame* aParentFrame,
   10977             :                                                    nsFrameItems& aFrameItems)
   10978             : {
   10979         413 :   CreateNeededPseudoContainers(aState, aItems, aParentFrame);
   10980         413 :   CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
   10981         413 :   CreateNeededPseudoInternalRubyBoxes(aState, aItems, aParentFrame);
   10982         413 :   CreateNeededPseudoSiblings(aState, aItems, aParentFrame);
   10983             : 
   10984         413 :   aItems.SetTriedConstructingFrames();
   10985         905 :   for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
   10986         492 :     NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
   10987             :                  "Needed pseudos didn't get created; expect bad things");
   10988         492 :     ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
   10989             :   }
   10990             : 
   10991         413 :   VerifyGridFlexContainerChildren(aParentFrame, aFrameItems);
   10992         413 :   NS_ASSERTION(!aState.mHavePendingPopupgroup,
   10993             :                "Should have proccessed it by now");
   10994         413 : }
   10995             : 
   10996             : void
   10997         353 : nsCSSFrameConstructor::AddFCItemsForAnonymousContent(
   10998             :             nsFrameConstructorState& aState,
   10999             :             nsContainerFrame* aFrame,
   11000             :             nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
   11001             :             FrameConstructionItemList& aItemsToConstruct,
   11002             :             uint32_t aExtraFlags)
   11003             : {
   11004         415 :   for (uint32_t i = 0; i < aAnonymousItems.Length(); ++i) {
   11005          62 :     nsIContent* content = aAnonymousItems[i].mContent;
   11006             :     // Gecko-styled nodes should have no pending restyle flags.
   11007          62 :     MOZ_ASSERT(content->IsStyledByServo() ||
   11008             :                !content->IsElement() ||
   11009             :                !(content->GetFlags() & ELEMENT_ALL_RESTYLE_FLAGS));
   11010             :     // Assert some things about this content
   11011          62 :     MOZ_ASSERT(!(content->GetFlags() &
   11012             :                  (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME)),
   11013             :                "Should not be marked as needing frames");
   11014          62 :     MOZ_ASSERT(!content->GetPrimaryFrame(),
   11015             :                "Should have no existing frame");
   11016          62 :     MOZ_ASSERT(!content->IsNodeOfType(nsINode::eCOMMENT) &&
   11017             :                !content->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION),
   11018             :                "Why is someone creating garbage anonymous content");
   11019             : 
   11020         124 :     RefPtr<nsStyleContext> styleContext;
   11021             :     Maybe<TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper>
   11022         124 :       parentDisplayBasedStyleFixupSkipper;
   11023          62 :     MOZ_ASSERT(aState.mTreeMatchContext || content->IsStyledByServo());
   11024          62 :     if (aState.mTreeMatchContext) {
   11025          62 :       parentDisplayBasedStyleFixupSkipper.emplace(*aState.mTreeMatchContext);
   11026             :     }
   11027             : 
   11028             :     // Make sure we eagerly performed the servo cascade when the anonymous
   11029             :     // nodes were created.
   11030          62 :     MOZ_ASSERT(!content->IsStyledByServo() || !content->IsElement() ||
   11031             :                content->AsElement()->HasServoData());
   11032             : 
   11033             :     // Determine whether this NAC is pseudo-implementing.
   11034          62 :     nsIAtom* pseudo = nullptr;
   11035          62 :     if (content->IsElement()) {
   11036          62 :       auto pseudoType = content->AsElement()->GetPseudoElementType();
   11037          62 :       if (pseudoType != CSSPseudoElementType::NotPseudo) {
   11038           4 :         pseudo = nsCSSPseudoElements::GetPseudoAtom(pseudoType);
   11039             :       }
   11040             :     }
   11041             : 
   11042             :     // Determine the appropriate parent style for this NAC, and if the NAC
   11043             :     // implements a pseudo-element, the appropriate originating element
   11044             :     // (that is to say, the element to the left of the ::pseudo-element in
   11045             :     // the selector). This is all rather tricky, and merits some discussion.
   11046             :     //
   11047             :     // First, it's important to note that author stylesheets generally do not
   11048             :     // apply to elements in native-anonymous subtrees. The exceptions to
   11049             :     // this are web-exposed pseudo-elements, where authors can style the
   11050             :     // pseudo-implementing NAC if the originating element is not itself in a NAC
   11051             :     // subtree.
   11052             :     //
   11053             :     // For this reason, it's very important that we avoid using a style parent
   11054             :     // that is inside a NAC subtree together with an originating element that
   11055             :     // is not inside a NAC subtree, since that would allow authors to
   11056             :     // explicitly inherit styles from internal elements, potentially making
   11057             :     // the NAC hierarchy observable. To ensure this, and generally simplify
   11058             :     // things, we always set the originating element to the style parent.
   11059             :     //
   11060             :     // As a consequence of the above, all web-exposed pseudo-elements (which,
   11061             :     // by definition, must have a content-accessible originating element) must
   11062             :     // also inherit style from that same content-accessible element. To avoid
   11063             :     // unintuitive behavior differences between NAC elements that do and don't
   11064             :     // correspond to web-exposed pseudo-elements, we follow this protocol for
   11065             :     // all NAC, pseudo-implementing or not.
   11066             :     //
   11067             :     // However, things get tricky with the <video> element, where we have a
   11068             :     // bunch of XBL-generated anonymous content descending from a native-
   11069             :     // anonymous XULElement. The XBL elements inherit style from their
   11070             :     // flattened tree parent, because that's how XBL works. But then we need
   11071             :     // to figure out what to do when one of those anonymous XBL elements
   11072             :     // (like an <input> element) generates its own (possibly pseudo-element-
   11073             :     // implementing) NAC.
   11074             :     //
   11075             :     // In this case, we inherit style from the XBL-generated NAC-creating
   11076             :     // element, rather than the <video> element. There are a number of good
   11077             :     // reasons for this. First, inheriting from the great-grandparent while
   11078             :     // the parent inherits from the grandparent would be bizarre at best.
   11079             :     // Second, exposing pseudo-elements from elements within our particular
   11080             :     // XBL implementation would allow content styles to (un)intentionally
   11081             :     // alter the video controls, which would be very bad. Third, our UA
   11082             :     // stylesheets have selectors like:
   11083             :     //
   11084             :     // input[type=range][orient=horizontal]::-moz-range-track
   11085             :     //
   11086             :     // and we need to make sure that the originating element is the <input>,
   11087             :     // not the <video>, because that's where the |orient| attribute lives.
   11088             :     //
   11089             :     // The upshot of all of this is that, to find the style parent (and
   11090             :     // originating element, if applicable), we walk up our parent chain to the
   11091             :     // first element that is not itself NAC (distinct from whether it happens
   11092             :     // to be in a NAC subtree).
   11093             :     //
   11094             :     // The one exception to all of this is scrollbar content, which we parent
   11095             :     // directly to the scrollframe. This is because the special-snowflake
   11096             :     // construction of scroll frames doesn't result in the placeholder frame
   11097             :     // being constructed until later, which means that GetInFlowParent() doesn't
   11098             :     // work right in the case of out-of-flow scrollframes.
   11099             :     //
   11100             :     // To implement all this, we need to pass the correct parent style context
   11101             :     // here because SetPrimaryFrame() may not have been called on the content
   11102             :     // yet and thus ResolveStyleContext can't find it otherwise.
   11103             :     //
   11104             :     // We don't need to worry about display:contents here, because such
   11105             :     // elements don't get a frame and thus can't generate NAC. But we do need
   11106             :     // to worry about anonymous boxes, which CorrectStyleParentFrame handles
   11107             :     // for us.
   11108          62 :     nsIFrame* inheritFrame = aFrame;
   11109          62 :     if (!content->IsNativeScrollbarContent()) {
   11110          56 :       while (inheritFrame->GetContent()->IsNativeAnonymous()) {
   11111           0 :         inheritFrame = inheritFrame->GetInFlowParent();
   11112             :       }
   11113             :     }
   11114             : 
   11115             :     nsIFrame* styleParentFrame =
   11116          62 :       nsFrame::CorrectStyleParentFrame(inheritFrame, pseudo);
   11117             :     // The only way we can not have a style parent now is if inheritFrame is the
   11118             :     // canvas frame and we're the NAC parent for all the things added via
   11119             :     // nsIDocument::InsertAnonymousContent.
   11120          62 :     MOZ_ASSERT(styleParentFrame || inheritFrame->IsCanvasFrame());
   11121             :     // And that anonymous div has no pseudo.
   11122          62 :     MOZ_ASSERT(styleParentFrame || !pseudo);
   11123             : 
   11124             :     Element* originating =
   11125          62 :       pseudo ? styleParentFrame->GetContent()->AsElement() : nullptr;
   11126             :     nsStyleContext* parentStyle =
   11127          62 :       styleParentFrame ? styleParentFrame->StyleContext() : nullptr;
   11128             :     styleContext =
   11129          62 :       ResolveStyleContext(parentStyle, content, &aState, originating);
   11130             : 
   11131          62 :     nsTArray<nsIAnonymousContentCreator::ContentInfo>* anonChildren = nullptr;
   11132          62 :     if (!aAnonymousItems[i].mChildren.IsEmpty()) {
   11133           0 :       anonChildren = &aAnonymousItems[i].mChildren;
   11134             :     }
   11135             : 
   11136             :     uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK |
   11137          62 :                      ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT | aExtraFlags;
   11138             : 
   11139          62 :     AddFrameConstructionItemsInternal(aState, content, aFrame,
   11140             :                                       content->NodeInfo()->NameAtom(),
   11141             :                                       content->GetNameSpaceID(),
   11142             :                                       true, styleContext, flags,
   11143          62 :                                       anonChildren, aItemsToConstruct);
   11144             :   }
   11145         353 : }
   11146             : 
   11147             : void
   11148         328 : nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
   11149             :                                        nsIContent*              aContent,
   11150             :                                        nsStyleContext*          aStyleContext,
   11151             :                                        nsContainerFrame*        aFrame,
   11152             :                                        const bool               aCanHaveGeneratedContent,
   11153             :                                        nsFrameItems&            aFrameItems,
   11154             :                                        const bool               aAllowBlockStyles,
   11155             :                                        PendingBinding*          aPendingBinding,
   11156             :                                        nsIFrame*                aPossiblyLeafFrame)
   11157             : {
   11158         328 :   NS_PRECONDITION(aFrame, "Must have parent frame here");
   11159         328 :   NS_PRECONDITION(aFrame->GetContentInsertionFrame() == aFrame,
   11160             :                   "Parent frame in ProcessChildren should be its own "
   11161             :                   "content insertion frame");
   11162         328 :   const uint32_t kMaxDepth = 2 * MAX_REFLOW_DEPTH;
   11163             :   static_assert(kMaxDepth <= UINT16_MAX, "mCurrentDepth type is too narrow");
   11164         656 :   AutoRestore<uint16_t> savedDepth(mCurrentDepth);
   11165         328 :   if (mCurrentDepth != UINT16_MAX) {
   11166         328 :     ++mCurrentDepth;
   11167             :   }
   11168             : 
   11169         328 :   if (!aPossiblyLeafFrame) {
   11170          45 :     aPossiblyLeafFrame = aFrame;
   11171             :   }
   11172             : 
   11173             :   // XXXbz ideally, this would do all the pushing of various
   11174             :   // containing blocks as needed, so callers don't have to do it...
   11175             : 
   11176         328 :   bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
   11177         328 :   if (aAllowBlockStyles) {
   11178             :     ShouldHaveSpecialBlockStyle(aContent, aStyleContext, &haveFirstLetterStyle,
   11179          22 :                                 &haveFirstLineStyle);
   11180             :   }
   11181             : 
   11182         328 :   const bool isFlexOrGridContainer = ::IsFlexOrGridContainer(aFrame);
   11183             :   // The logic here needs to match the logic in GetFloatContainingBlock()
   11184             :   // (Since we already have isFlexOrGridContainer, we check that eagerly instead
   11185             :   // of letting ShouldSuppressFloatingOfDescendants look it up redundantly.)
   11186         656 :   nsFrameConstructorSaveState floatSaveState;
   11187         656 :   if (isFlexOrGridContainer ||
   11188         328 :       ShouldSuppressFloatingOfDescendants(aFrame)) {
   11189         223 :     aState.PushFloatContainingBlock(nullptr, floatSaveState);
   11190         105 :   } else if (aFrame->IsFloatContainingBlock()) {
   11191          29 :     aState.PushFloatContainingBlock(aFrame, floatSaveState);
   11192             :   }
   11193             : 
   11194             :   nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
   11195         656 :                                                            aPendingBinding);
   11196             : 
   11197         656 :   FrameConstructionItemList itemsToConstruct;
   11198             : 
   11199             :   // If we have first-letter or first-line style then frames can get
   11200             :   // moved around so don't set these flags.
   11201         328 :   if (aAllowBlockStyles && !haveFirstLetterStyle && !haveFirstLineStyle) {
   11202          22 :     itemsToConstruct.SetLineBoundaryAtStart(true);
   11203          22 :     itemsToConstruct.SetLineBoundaryAtEnd(true);
   11204             :   }
   11205             : 
   11206             :   // Create any anonymous frames we need here.  This must happen before the
   11207             :   // non-anonymous children are processed to ensure that popups are never
   11208             :   // constructed before the popupset.
   11209         656 :   AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
   11210         328 :   GetAnonymousContent(aContent, aPossiblyLeafFrame, anonymousItems);
   11211             : #ifdef DEBUG
   11212         361 :   for (uint32_t i = 0; i < anonymousItems.Length(); ++i) {
   11213          33 :     MOZ_ASSERT(anonymousItems[i].mContent->IsRootOfAnonymousSubtree(),
   11214             :                "Content should know it's an anonymous subtree");
   11215             :   }
   11216             : #endif
   11217             :   AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
   11218         328 :                                 itemsToConstruct);
   11219             : 
   11220         328 :   if (!aPossiblyLeafFrame->IsLeaf()) {
   11221             :     // :before/:after content should have the same style context parent
   11222             :     // as normal kids.
   11223             :     // Note that we don't use this style context for looking up things like
   11224             :     // special block styles because in some cases involving table pseudo-frames
   11225             :     // it has nothing to do with the parent frame's desired behavior.
   11226             :     nsStyleContext* styleContext;
   11227             : 
   11228         254 :     if (aCanHaveGeneratedContent) {
   11229         230 :       aFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
   11230             :       styleContext =
   11231         230 :         nsFrame::CorrectStyleParentFrame(aFrame, nullptr)->StyleContext();
   11232             :       // Probe for generated content before
   11233             :       CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
   11234             :                                  CSSPseudoElementType::before,
   11235         230 :                                  itemsToConstruct);
   11236             :     }
   11237             : 
   11238         254 :     const bool addChildItems = MOZ_LIKELY(mCurrentDepth < kMaxDepth);
   11239         254 :     if (!addChildItems) {
   11240           0 :       NS_WARNING("ProcessChildren max depth exceeded");
   11241             :     }
   11242             : 
   11243             :     // Don't blockify 'display' in ApplyStyleFixups unless aFrame really is
   11244             :     // a flex/grid container frame, not just has display:flex/grid.
   11245             :     Maybe<TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper>
   11246         508 :       parentDisplayBasedStyleFixupSkipper;
   11247         254 :     MOZ_ASSERT(aState.mTreeMatchContext || aContent->IsStyledByServo());
   11248         254 :     if (!isFlexOrGridContainer && aState.mTreeMatchContext) {
   11249         254 :       parentDisplayBasedStyleFixupSkipper.emplace(*aState.mTreeMatchContext);
   11250             :     }
   11251             : 
   11252         254 :     InsertionPoint insertion(aFrame, nullptr);
   11253         508 :     FlattenedChildIterator iter(aContent);
   11254         994 :     for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
   11255             :       // Get the parent of the content and check if it is a XBL children element
   11256             :       // (if the content is a children element then parent != aContent because the
   11257             :       // FlattenedChildIterator will transitively iterate through <xbl:children>
   11258             :       // for default content). Push the children element as an ancestor here because
   11259             :       // it does not have a frame and would not otherwise be pushed as an ancestor.
   11260         740 :       insertion.mContainer = aContent;
   11261         740 :       nsIContent* parent = child->GetParent();
   11262         740 :       MOZ_ASSERT(parent, "Parent must be non-null because we are iterating children.");
   11263        1480 :       TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
   11264         740 :       if (parent != aContent && parent->IsElement()) {
   11265          20 :         insertion.mContainer = child->GetFlattenedTreeParent();
   11266          20 :         MOZ_ASSERT(insertion.mContainer == GetInsertionPoint(parent, child).mContainer);
   11267          20 :         if (aState.HasAncestorFilter()) {
   11268          20 :           ancestorPusher.PushAncestorAndStyleScope(parent->AsElement());
   11269             :         } else {
   11270           0 :           ancestorPusher.PushStyleScope(parent->AsElement());
   11271             :         }
   11272             :       }
   11273             : 
   11274             :       // Frame construction item construction should not post
   11275             :       // restyles, so removing restyle flags here is safe.
   11276         740 :       child->UnsetRestyleFlagsIfGecko();
   11277         740 :       if (addChildItems) {
   11278         740 :         AddFrameConstructionItems(aState, child, iter.XBLInvolved(), insertion,
   11279         740 :                                   itemsToConstruct);
   11280             :       } else {
   11281           0 :         ClearLazyBits(child, child->GetNextSibling());
   11282             :       }
   11283             :     }
   11284         254 :     itemsToConstruct.SetParentHasNoXBLChildren(!iter.XBLInvolved());
   11285             : 
   11286         254 :     if (aCanHaveGeneratedContent) {
   11287             :       // Probe for generated content after
   11288             :       CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
   11289             :                                  CSSPseudoElementType::after,
   11290         230 :                                  itemsToConstruct);
   11291             :     }
   11292             :   } else {
   11293          74 :     ClearLazyBits(aContent->GetFirstChild(), nullptr);
   11294             :   }
   11295             : 
   11296         328 :   ConstructFramesFromItemList(aState, itemsToConstruct, aFrame, aFrameItems);
   11297             : 
   11298         328 :   NS_ASSERTION(!aAllowBlockStyles || !aFrame->IsXULBoxFrame(),
   11299             :                "can't be both block and box");
   11300             : 
   11301         328 :   if (haveFirstLetterStyle) {
   11302           0 :     WrapFramesInFirstLetterFrame(aFrame, aFrameItems);
   11303             :   }
   11304         328 :   if (haveFirstLineStyle) {
   11305             :     WrapFramesInFirstLineFrame(aState, aContent, aFrame, nullptr,
   11306           0 :                                aFrameItems);
   11307             :   }
   11308             : 
   11309             :   // We might end up with first-line frames that change
   11310             :   // AnyKidsNeedBlockParent() without changing itemsToConstruct, but that
   11311             :   // should never happen for cases whan aFrame->IsXULBoxFrame().
   11312         328 :   NS_ASSERTION(!haveFirstLineStyle || !aFrame->IsXULBoxFrame(),
   11313             :                "Shouldn't have first-line style if we're a box");
   11314         328 :   NS_ASSERTION(!aFrame->IsXULBoxFrame() ||
   11315             :                itemsToConstruct.AnyItemsNeedBlockParent() ==
   11316             :                  (AnyKidsNeedBlockParent(aFrameItems.FirstChild()) != nullptr),
   11317             :                "Something went awry in our block parent calculations");
   11318             : 
   11319         328 :   if (aFrame->IsXULBoxFrame() && itemsToConstruct.AnyItemsNeedBlockParent()) {
   11320             :     // XXXbz we could do this on the FrameConstructionItemList level,
   11321             :     // no?  And if we cared we could look through the item list
   11322             :     // instead of groveling through the framelist here..
   11323           5 :     nsStyleContext *frameStyleContext = aFrame->StyleContext();
   11324             :     // Report a warning for non-GC frames, for chrome:
   11325           5 :     if (!aFrame->IsGeneratedContentFrame() &&
   11326           0 :         mPresShell->GetPresContext()->IsChrome()) {
   11327           0 :       nsIContent *badKid = AnyKidsNeedBlockParent(aFrameItems.FirstChild());
   11328           0 :       nsDependentAtomString parentTag(aContent->NodeInfo()->NameAtom()),
   11329           0 :                             kidTag(badKid->NodeInfo()->NameAtom());
   11330           0 :       const char16_t* params[] = { parentTag.get(), kidTag.get() };
   11331           0 :       const nsStyleDisplay *display = frameStyleContext->StyleDisplay();
   11332             :       const char *message =
   11333           0 :         (display->mDisplay == StyleDisplay::MozInlineBox)
   11334           0 :           ? "NeededToWrapXULInlineBox" : "NeededToWrapXUL";
   11335           0 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
   11336           0 :                                       NS_LITERAL_CSTRING("Layout: FrameConstructor"),
   11337           0 :                                       mDocument,
   11338             :                                       nsContentUtils::eXUL_PROPERTIES,
   11339             :                                       message,
   11340           0 :                                       params, ArrayLength(params));
   11341             :     }
   11342             : 
   11343          10 :     RefPtr<nsStyleContext> blockSC = mPresShell->StyleSet()->
   11344          15 :       ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::mozXULAnonymousBlock,
   11345          10 :                                          frameStyleContext);
   11346           5 :     nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
   11347             :     // We might, in theory, want to set NS_BLOCK_FLOAT_MGR and
   11348             :     // NS_BLOCK_MARGIN_ROOT, but I think it's a bad idea given that
   11349             :     // a real block placed here wouldn't get those set on it.
   11350             : 
   11351           5 :     InitAndRestoreFrame(aState, aContent, aFrame, blockFrame, false);
   11352             : 
   11353           5 :     NS_ASSERTION(!blockFrame->HasView(), "need to do view reparenting");
   11354           5 :     ReparentFrames(this, blockFrame, aFrameItems);
   11355             : 
   11356           5 :     blockFrame->SetInitialChildList(kPrincipalList, aFrameItems);
   11357           5 :     NS_ASSERTION(aFrameItems.IsEmpty(), "How did that happen?");
   11358           5 :     aFrameItems.Clear();
   11359           5 :     aFrameItems.AddChild(blockFrame);
   11360             : 
   11361           5 :     aFrame->AddStateBits(NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK);
   11362             :   }
   11363         328 : }
   11364             : 
   11365             : //----------------------------------------------------------------------
   11366             : 
   11367             : // Support for :first-line style
   11368             : 
   11369             : // Special routine to handle placing a list of frames into a block
   11370             : // frame that has first-line style. The routine ensures that the first
   11371             : // collection of inline frames end up in a first-line frame.
   11372             : // NOTE: aState may have containing block information related to a
   11373             : // different part of the frame tree than where the first line occurs.
   11374             : // In particular aState may be set up for where ContentInserted or
   11375             : // ContentAppended is inserting content, which may be some
   11376             : // non-first-in-flow continuation of the block to which the first-line
   11377             : // belongs. So this function needs to be careful about how it uses
   11378             : // aState.
   11379             : void
   11380           0 : nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
   11381             :   nsFrameConstructorState& aState,
   11382             :   nsIContent*              aBlockContent,
   11383             :   nsContainerFrame*        aBlockFrame,
   11384             :   nsFirstLineFrame*        aLineFrame,
   11385             :   nsFrameItems&            aFrameItems)
   11386             : {
   11387             :   // Find the part of aFrameItems that we want to put in the first-line
   11388           0 :   nsFrameList::FrameLinkEnumerator link(aFrameItems);
   11389           0 :   while (!link.AtEnd() && link.NextFrame()->IsInlineOutside()) {
   11390           0 :     link.Next();
   11391             :   }
   11392             : 
   11393           0 :   nsFrameList firstLineChildren = aFrameItems.ExtractHead(link);
   11394             : 
   11395           0 :   if (firstLineChildren.IsEmpty()) {
   11396             :     // Nothing is supposed to go into the first-line; nothing to do
   11397           0 :     return;
   11398             :   }
   11399             : 
   11400           0 :   if (!aLineFrame) {
   11401             :     // Create line frame
   11402             :     nsStyleContext* parentStyle =
   11403             :       nsFrame::CorrectStyleParentFrame(aBlockFrame,
   11404             :                                        nsCSSPseudoElements::firstLine)->
   11405           0 :         StyleContext();
   11406           0 :     RefPtr<nsStyleContext> firstLineStyle = GetFirstLineStyle(aBlockContent,
   11407           0 :                                                                 parentStyle);
   11408             : 
   11409           0 :     aLineFrame = NS_NewFirstLineFrame(mPresShell, firstLineStyle);
   11410             : 
   11411             :     // Initialize the line frame
   11412           0 :     InitAndRestoreFrame(aState, aBlockContent, aBlockFrame, aLineFrame);
   11413             : 
   11414             :     // The lineFrame will be the block's first child; the rest of the
   11415             :     // frame list (after lastInlineFrame) will be the second and
   11416             :     // subsequent children; insert lineFrame into aFrameItems.
   11417           0 :     aFrameItems.InsertFrame(nullptr, nullptr, aLineFrame);
   11418             : 
   11419           0 :     NS_ASSERTION(aLineFrame->StyleContext() == firstLineStyle,
   11420             :                  "Bogus style context on line frame");
   11421             :   }
   11422             : 
   11423             :   // Give the inline frames to the lineFrame <b>after</b> reparenting them
   11424           0 :   ReparentFrames(this, aLineFrame, firstLineChildren);
   11425           0 :   if (aLineFrame->PrincipalChildList().IsEmpty() &&
   11426           0 :       (aLineFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
   11427           0 :     aLineFrame->SetInitialChildList(kPrincipalList, firstLineChildren);
   11428             :   } else {
   11429           0 :     AppendFrames(aLineFrame, kPrincipalList, firstLineChildren);
   11430             :   }
   11431             : }
   11432             : 
   11433             : // Special routine to handle appending a new frame to a block frame's
   11434             : // child list. Takes care of placing the new frame into the right
   11435             : // place when first-line style is present.
   11436             : void
   11437           0 : nsCSSFrameConstructor::AppendFirstLineFrames(
   11438             :   nsFrameConstructorState& aState,
   11439             :   nsIContent*              aBlockContent,
   11440             :   nsContainerFrame*        aBlockFrame,
   11441             :   nsFrameItems&            aFrameItems)
   11442             : {
   11443             :   // It's possible that aBlockFrame needs to have a first-line frame
   11444             :   // created because it doesn't currently have any children.
   11445           0 :   const nsFrameList& blockKids = aBlockFrame->PrincipalChildList();
   11446           0 :   if (blockKids.IsEmpty()) {
   11447             :     WrapFramesInFirstLineFrame(aState, aBlockContent,
   11448           0 :                                aBlockFrame, nullptr, aFrameItems);
   11449           0 :     return;
   11450             :   }
   11451             : 
   11452             :   // Examine the last block child - if it's a first-line frame then
   11453             :   // appended frames need special treatment.
   11454           0 :   nsIFrame* lastBlockKid = blockKids.LastChild();
   11455           0 :   if (!lastBlockKid->IsLineFrame()) {
   11456             :     // No first-line frame at the end of the list, therefore there is
   11457             :     // an intervening block between any first-line frame the frames
   11458             :     // we are appending. Therefore, we don't need any special
   11459             :     // treatment of the appended frames.
   11460           0 :     return;
   11461             :   }
   11462             : 
   11463           0 :   nsFirstLineFrame* lineFrame = static_cast<nsFirstLineFrame*>(lastBlockKid);
   11464             :   WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame,
   11465           0 :                              lineFrame, aFrameItems);
   11466             : }
   11467             : 
   11468             : // Special routine to handle inserting a new frame into a block
   11469             : // frame's child list. Takes care of placing the new frame into the
   11470             : // right place when first-line style is present.
   11471             : void
   11472           0 : nsCSSFrameConstructor::InsertFirstLineFrames(
   11473             :   nsFrameConstructorState& aState,
   11474             :   nsIContent*              aContent,
   11475             :   nsIFrame*                aBlockFrame,
   11476             :   nsContainerFrame**       aParentFrame,
   11477             :   nsIFrame*                aPrevSibling,
   11478             :   nsFrameItems&            aFrameItems)
   11479             : {
   11480             :   // XXXbz If you make this method actually do something, check to
   11481             :   // make sure that the caller is passing what you expect.  In
   11482             :   // particular, which content is aContent?  And audit the rest of
   11483             :   // this code too; it makes bogus assumptions and may not build.
   11484             : #if 0
   11485             :   nsIFrame* parentFrame = *aParentFrame;
   11486             :   nsIFrame* newFrame = aFrameItems.childList;
   11487             :   bool isInline = IsInlineOutside(newFrame);
   11488             : 
   11489             :   if (!aPrevSibling) {
   11490             :     // Insertion will become the first frame. Two cases: we either
   11491             :     // already have a first-line frame or we don't.
   11492             :     nsIFrame* firstBlockKid = aBlockFrame->PrincipalChildList().FirstChild();
   11493             :     if (firstBlockKid->IsLineFrame()) {
   11494             :       // We already have a first-line frame
   11495             :       nsIFrame* lineFrame = firstBlockKid;
   11496             : 
   11497             :       if (isInline) {
   11498             :         // Easy case: the new inline frame will go into the lineFrame.
   11499             :         ReparentFrame(this, lineFrame, newFrame);
   11500             :         InsertFrames(lineFrame, kPrincipalList, nullptr, newFrame);
   11501             : 
   11502             :         // Since the frame is going into the lineFrame, don't let it
   11503             :         // go into the block too.
   11504             :         aFrameItems.childList = nullptr;
   11505             :         aFrameItems.lastChild = nullptr;
   11506             :       }
   11507             :       else {
   11508             :         // Harder case: We are about to insert a block level element
   11509             :         // before the first-line frame.
   11510             :         // XXX need a method to steal away frames from the line-frame
   11511             :       }
   11512             :     }
   11513             :     else {
   11514             :       // We do not have a first-line frame
   11515             :       if (isInline) {
   11516             :         // We now need a first-line frame to contain the inline frame.
   11517             :         nsIFrame* lineFrame = NS_NewFirstLineFrame(firstLineStyle);
   11518             : 
   11519             :         if (NS_SUCCEEDED(rv)) {
   11520             :           // Lookup first-line style context
   11521             :           nsStyleContext* parentStyle =
   11522             :             nsFrame::CorrectStyleParentFrame(aBlockFrame,
   11523             :                                              nsCSSPseudoElements::firstLine)->
   11524             :               StyleContext();
   11525             :           RefPtr<nsStyleContext> firstLineStyle =
   11526             :             GetFirstLineStyle(aContent, parentStyle);
   11527             : 
   11528             :           // Initialize the line frame
   11529             :           InitAndRestoreFrame(aState, aContent, aBlockFrame, lineFrame);
   11530             : 
   11531             :           // Make sure the caller inserts the lineFrame into the
   11532             :           // blocks list of children.
   11533             :           aFrameItems.childList = lineFrame;
   11534             :           aFrameItems.lastChild = lineFrame;
   11535             : 
   11536             :           // Give the inline frames to the lineFrame <b>after</b>
   11537             :           // reparenting them
   11538             :           NS_ASSERTION(lineFrame->StyleContext() == firstLineStyle,
   11539             :                        "Bogus style context on line frame");
   11540             :           ReparentFrame(aPresContext, lineFrame, newFrame);
   11541             :           lineFrame->SetInitialChildList(kPrincipalList, newFrame);
   11542             :         }
   11543             :       }
   11544             :       else {
   11545             :         // Easy case: the regular insertion logic can insert the new
   11546             :         // frame because it's a block frame.
   11547             :       }
   11548             :     }
   11549             :   }
   11550             :   else {
   11551             :     // Insertion will not be the first frame.
   11552             :     nsIFrame* prevSiblingParent = aPrevSibling->GetParent();
   11553             :     if (prevSiblingParent == aBlockFrame) {
   11554             :       // Easy case: The prev-siblings parent is the block
   11555             :       // frame. Therefore the prev-sibling is not currently in a
   11556             :       // line-frame. Therefore the new frame which is going after it,
   11557             :       // regardless of type, is not going into a line-frame.
   11558             :     }
   11559             :     else {
   11560             :       // If the prevSiblingParent is not the block-frame then it must
   11561             :       // be a line-frame (if it were a letter-frame, that logic would
   11562             :       // already have adjusted the prev-sibling to be the
   11563             :       // letter-frame).
   11564             :       if (isInline) {
   11565             :         // Easy case: the insertion can go where the caller thinks it
   11566             :         // should go (which is into prevSiblingParent).
   11567             :       }
   11568             :       else {
   11569             :         // Block elements don't end up in line-frames, therefore
   11570             :         // change the insertion point to aBlockFrame. However, there
   11571             :         // might be more inline elements following aPrevSibling that
   11572             :         // need to be pulled out of the line-frame and become children
   11573             :         // of the block.
   11574             :         nsIFrame* nextSibling = aPrevSibling->GetNextSibling();
   11575             :         nsIFrame* nextLineFrame = prevSiblingParent->GetNextInFlow();
   11576             :         if (nextSibling || nextLineFrame) {
   11577             :           // Oy. We have work to do. Create a list of the new frames
   11578             :           // that are going into the block by stripping them away from
   11579             :           // the line-frame(s).
   11580             :           if (nextSibling) {
   11581             :             nsLineFrame* lineFrame = (nsLineFrame*) prevSiblingParent;
   11582             :             nsFrameList tail = lineFrame->StealFramesAfter(aPrevSibling);
   11583             :             // XXX do something with 'tail'
   11584             :           }
   11585             : 
   11586             :           nsLineFrame* nextLineFrame = (nsLineFrame*) lineFrame;
   11587             :           for (;;) {
   11588             :             nextLineFrame = nextLineFrame->GetNextInFlow();
   11589             :             if (!nextLineFrame) {
   11590             :               break;
   11591             :             }
   11592             :             nsIFrame* kids = nextLineFrame->PrincipalChildList().FirstChild();
   11593             :           }
   11594             :         }
   11595             :         else {
   11596             :           // We got lucky: aPrevSibling was the last inline frame in
   11597             :           // the line-frame.
   11598             :           ReparentFrame(this, aBlockFrame, newFrame);
   11599             :           InsertFrames(aBlockFrame, kPrincipalList,
   11600             :                        prevSiblingParent, newFrame);
   11601             :           aFrameItems.childList = nullptr;
   11602             :           aFrameItems.lastChild = nullptr;
   11603             :         }
   11604             :       }
   11605             :     }
   11606             :   }
   11607             : 
   11608             : #endif
   11609           0 : }
   11610             : 
   11611             : //----------------------------------------------------------------------
   11612             : 
   11613             : // First-letter support
   11614             : 
   11615             : // Determine how many characters in the text fragment apply to the
   11616             : // first letter
   11617             : static int32_t
   11618           0 : FirstLetterCount(const nsTextFragment* aFragment)
   11619             : {
   11620           0 :   int32_t count = 0;
   11621           0 :   int32_t firstLetterLength = 0;
   11622             : 
   11623           0 :   int32_t i, n = aFragment->GetLength();
   11624           0 :   for (i = 0; i < n; i++) {
   11625           0 :     char16_t ch = aFragment->CharAt(i);
   11626             :     // FIXME: take content language into account when deciding whitespace.
   11627           0 :     if (dom::IsSpaceCharacter(ch)) {
   11628           0 :       if (firstLetterLength) {
   11629           0 :         break;
   11630             :       }
   11631           0 :       count++;
   11632           0 :       continue;
   11633             :     }
   11634             :     // XXX I18n
   11635           0 :     if ((ch == '\'') || (ch == '\"')) {
   11636           0 :       if (firstLetterLength) {
   11637           0 :         break;
   11638             :       }
   11639             :       // keep looping
   11640           0 :       firstLetterLength = 1;
   11641             :     }
   11642             :     else {
   11643           0 :       count++;
   11644           0 :       break;
   11645             :     }
   11646             :   }
   11647             : 
   11648           0 :   return count;
   11649             : }
   11650             : 
   11651             : static bool
   11652           0 : NeedFirstLetterContinuation(nsIContent* aContent)
   11653             : {
   11654           0 :   NS_PRECONDITION(aContent, "null ptr");
   11655             : 
   11656           0 :   bool result = false;
   11657           0 :   if (aContent) {
   11658           0 :     const nsTextFragment* frag = aContent->GetText();
   11659           0 :     if (frag) {
   11660           0 :       int32_t flc = FirstLetterCount(frag);
   11661           0 :       int32_t tl = frag->GetLength();
   11662           0 :       if (flc < tl) {
   11663           0 :         result = true;
   11664             :       }
   11665             :     }
   11666             :   }
   11667           0 :   return result;
   11668             : }
   11669             : 
   11670           0 : static bool IsFirstLetterContent(nsIContent* aContent)
   11671             : {
   11672           0 :   return aContent->TextLength() &&
   11673           0 :          !aContent->TextIsOnlyWhitespace();
   11674             : }
   11675             : 
   11676             : /**
   11677             :  * Create a letter frame, only make it a floating frame.
   11678             :  */
   11679             : nsFirstLetterFrame*
   11680           0 : nsCSSFrameConstructor::CreateFloatingLetterFrame(
   11681             :   nsFrameConstructorState& aState,
   11682             :   nsIContent* aTextContent,
   11683             :   nsIFrame* aTextFrame,
   11684             :   nsContainerFrame* aParentFrame,
   11685             :   nsStyleContext* aStyleContext,
   11686             :   nsFrameItems& aResult)
   11687             : {
   11688             :   nsFirstLetterFrame* letterFrame =
   11689           0 :     NS_NewFirstLetterFrame(mPresShell, aStyleContext);
   11690             :   // We don't want to use a text content for a non-text frame (because we want
   11691             :   // its primary frame to be a text frame).  So use its parent for the
   11692             :   // first-letter.
   11693           0 :   nsIContent* letterContent = aTextContent->GetParent();
   11694           0 :   nsContainerFrame* containingBlock = aState.GetGeometricParent(
   11695           0 :     aStyleContext->StyleDisplay(), aParentFrame);
   11696           0 :   InitAndRestoreFrame(aState, letterContent, containingBlock, letterFrame);
   11697             : 
   11698             :   // Init the text frame to refer to the letter frame. Make sure we
   11699             :   // get a proper style context for it (the one passed in is for the
   11700             :   // letter frame and will have the float property set on it; the text
   11701             :   // frame shouldn't have that set).
   11702           0 :   StyleSetHandle styleSet = mPresShell->StyleSet();
   11703             :   RefPtr<nsStyleContext> textSC = styleSet->
   11704           0 :     ResolveStyleForText(aTextContent, aStyleContext);
   11705           0 :   aTextFrame->SetStyleContextWithoutNotification(textSC);
   11706           0 :   InitAndRestoreFrame(aState, aTextContent, letterFrame, aTextFrame);
   11707             : 
   11708             :   // And then give the text frame to the letter frame
   11709           0 :   SetInitialSingleChild(letterFrame, aTextFrame);
   11710             : 
   11711             :   // See if we will need to continue the text frame (does it contain
   11712             :   // more than just the first-letter text or not?) If it does, then we
   11713             :   // create (in advance) a continuation frame for it.
   11714           0 :   nsIFrame* nextTextFrame = nullptr;
   11715           0 :   if (NeedFirstLetterContinuation(aTextContent)) {
   11716             :     // Create continuation
   11717             :     nextTextFrame =
   11718           0 :       CreateContinuingFrame(aState.mPresContext, aTextFrame, aParentFrame);
   11719             :     // Repair the continuations style context
   11720           0 :     nsStyleContext* parentStyleContext = aStyleContext->GetParentAllowServo();
   11721           0 :     if (parentStyleContext) {
   11722             :       RefPtr<nsStyleContext> newSC = styleSet->
   11723           0 :         ResolveStyleForText(aTextContent, parentStyleContext);
   11724           0 :       nextTextFrame->SetStyleContext(newSC);
   11725             :     }
   11726             :   }
   11727             : 
   11728           0 :   NS_ASSERTION(aResult.IsEmpty(), "aResult should be an empty nsFrameItems!");
   11729             :   // Put the new float before any of the floats in the block we're doing
   11730             :   // first-letter for, that is, before any floats whose parent is
   11731             :   // containingBlock.
   11732           0 :   nsFrameList::FrameLinkEnumerator link(aState.mFloatedItems);
   11733           0 :   while (!link.AtEnd() && link.NextFrame()->GetParent() != containingBlock) {
   11734           0 :     link.Next();
   11735             :   }
   11736             : 
   11737           0 :   aState.AddChild(letterFrame, aResult, letterContent, aStyleContext,
   11738             :                   aParentFrame, false, true, false, true,
   11739           0 :                   link.PrevFrame());
   11740             : 
   11741           0 :   if (nextTextFrame) {
   11742           0 :     aResult.AddChild(nextTextFrame);
   11743             :   }
   11744             : 
   11745           0 :   return letterFrame;
   11746             : }
   11747             : 
   11748             : /**
   11749             :  * Create a new letter frame for aTextFrame. The letter frame will be
   11750             :  * a child of aParentFrame.
   11751             :  */
   11752             : void
   11753           0 : nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame,
   11754             :                                          nsContainerFrame* aBlockContinuation,
   11755             :                                          nsIContent* aTextContent,
   11756             :                                          nsContainerFrame* aParentFrame,
   11757             :                                          nsFrameItems& aResult)
   11758             : {
   11759           0 :   NS_PRECONDITION(aTextContent->IsNodeOfType(nsINode::eTEXT),
   11760             :                   "aTextContent isn't text");
   11761           0 :   NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
   11762             :                  "Not a block frame?");
   11763             : 
   11764             :   // Get style context for the first-letter-frame.  Keep this in sync with
   11765             :   // nsBlockFrame::UpdatePseudoElementStyles.
   11766             :   nsStyleContext* parentStyleContext =
   11767             :     nsFrame::CorrectStyleParentFrame(aParentFrame,
   11768             :                                      nsCSSPseudoElements::firstLetter)->
   11769           0 :       StyleContext();
   11770             : 
   11771             :   // Use content from containing block so that we can actually
   11772             :   // find a matching style rule.
   11773           0 :   nsIContent* blockContent = aBlockFrame->GetContent();
   11774             : 
   11775             :   // Create first-letter style rule
   11776           0 :   RefPtr<nsStyleContext> sc = GetFirstLetterStyle(blockContent,
   11777           0 :                                                     parentStyleContext);
   11778           0 :   if (sc) {
   11779           0 :     RefPtr<nsStyleContext> textSC = mPresShell->StyleSet()->
   11780           0 :       ResolveStyleForText(aTextContent, sc);
   11781             : 
   11782             :     // Create a new text frame (the original one will be discarded)
   11783             :     // pass a temporary stylecontext, the correct one will be set
   11784             :     // later.  Start off by unsetting the primary frame for
   11785             :     // aTextContent, so it's no longer pointing to the to-be-destroyed
   11786             :     // frame.
   11787             :     // XXXbz it would be really nice to destroy the old frame _first_,
   11788             :     // then create the new one, so we could avoid this hack.
   11789           0 :     aTextContent->SetPrimaryFrame(nullptr);
   11790           0 :     nsIFrame* textFrame = NS_NewTextFrame(mPresShell, textSC);
   11791             : 
   11792           0 :     NS_ASSERTION(aBlockContinuation == GetFloatContainingBlock(aParentFrame),
   11793             :                  "Containing block is confused");
   11794           0 :     TreeMatchContextHolder matchContext(mDocument);
   11795             :     nsFrameConstructorState state(mPresShell,
   11796             :                                   matchContext,
   11797             :                                   GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
   11798             :                                   GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
   11799           0 :                                   aBlockContinuation);
   11800             : 
   11801             :     // Create the right type of first-letter frame
   11802           0 :     const nsStyleDisplay* display = sc->StyleDisplay();
   11803             :     nsFirstLetterFrame* letterFrame;
   11804           0 :     if (display->IsFloatingStyle() &&
   11805           0 :         !nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
   11806             :       // Make a floating first-letter frame
   11807           0 :       letterFrame = CreateFloatingLetterFrame(state, aTextContent, textFrame,
   11808           0 :                                               aParentFrame, sc, aResult);
   11809             :     }
   11810             :     else {
   11811             :       // Make an inflow first-letter frame
   11812           0 :       letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
   11813             : 
   11814             :       // Initialize the first-letter-frame.  We don't want to use a text
   11815             :       // content for a non-text frame (because we want its primary frame to
   11816             :       // be a text frame).  So use its parent for the first-letter.
   11817           0 :       nsIContent* letterContent = aTextContent->GetParent();
   11818           0 :       letterFrame->Init(letterContent, aParentFrame, nullptr);
   11819             : 
   11820           0 :       InitAndRestoreFrame(state, aTextContent, letterFrame, textFrame);
   11821             : 
   11822           0 :       SetInitialSingleChild(letterFrame, textFrame);
   11823           0 :       aResult.Clear();
   11824           0 :       aResult.AddChild(letterFrame);
   11825           0 :       NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),
   11826             :                    "should have the first continuation here");
   11827           0 :       aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
   11828             :     }
   11829           0 :     MOZ_ASSERT(!aBlockFrame->GetPrevContinuation(),
   11830             :                "Setting up a first-letter frame on a non-first block continuation?");
   11831           0 :     auto parent = static_cast<nsContainerFrame*>(aParentFrame->FirstContinuation());
   11832           0 :     parent->SetHasFirstLetterChild();
   11833           0 :     aBlockFrame->SetProperty(nsContainerFrame::FirstLetterProperty(),
   11834           0 :                              letterFrame);
   11835           0 :     aTextContent->SetPrimaryFrame(textFrame);
   11836             :   }
   11837           0 : }
   11838             : 
   11839             : void
   11840           0 : nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
   11841             :   nsContainerFrame*        aBlockFrame,
   11842             :   nsFrameItems&            aBlockFrames)
   11843             : {
   11844           0 :   aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
   11845             : 
   11846           0 :   nsContainerFrame* parentFrame = nullptr;
   11847           0 :   nsIFrame* textFrame = nullptr;
   11848           0 :   nsIFrame* prevFrame = nullptr;
   11849           0 :   nsFrameItems letterFrames;
   11850           0 :   bool stopLooking = false;
   11851           0 :   WrapFramesInFirstLetterFrame(aBlockFrame, aBlockFrame, aBlockFrame,
   11852             :                                aBlockFrames.FirstChild(),
   11853             :                                &parentFrame, &textFrame, &prevFrame,
   11854           0 :                                letterFrames, &stopLooking);
   11855           0 :   if (parentFrame) {
   11856           0 :     if (parentFrame == aBlockFrame) {
   11857             :       // Take textFrame out of the block's frame list and substitute the
   11858             :       // letter frame(s) instead.
   11859           0 :       aBlockFrames.DestroyFrame(textFrame);
   11860           0 :       aBlockFrames.InsertFrames(nullptr, prevFrame, letterFrames);
   11861             :     }
   11862             :     else {
   11863             :       // Take the old textFrame out of the inline parent's child list
   11864           0 :       RemoveFrame(kPrincipalList, textFrame);
   11865             : 
   11866             :       // Insert in the letter frame(s)
   11867           0 :       parentFrame->InsertFrames(kPrincipalList, prevFrame, letterFrames);
   11868             :     }
   11869             :   }
   11870           0 : }
   11871             : 
   11872             : void
   11873           0 : nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
   11874             :   nsContainerFrame*        aBlockFrame,
   11875             :   nsContainerFrame*        aBlockContinuation,
   11876             :   nsContainerFrame*        aParentFrame,
   11877             :   nsIFrame*                aParentFrameList,
   11878             :   nsContainerFrame**       aModifiedParent,
   11879             :   nsIFrame**               aTextFrame,
   11880             :   nsIFrame**               aPrevFrame,
   11881             :   nsFrameItems&            aLetterFrames,
   11882             :   bool*                    aStopLooking)
   11883             : {
   11884           0 :   nsIFrame* prevFrame = nullptr;
   11885           0 :   nsIFrame* frame = aParentFrameList;
   11886             : 
   11887           0 :   while (frame) {
   11888           0 :     nsIFrame* nextFrame = frame->GetNextSibling();
   11889             : 
   11890           0 :     LayoutFrameType frameType = frame->Type();
   11891           0 :     if (LayoutFrameType::Text == frameType) {
   11892             :       // Wrap up first-letter content in a letter frame
   11893           0 :       nsIContent* textContent = frame->GetContent();
   11894           0 :       if (IsFirstLetterContent(textContent)) {
   11895             :         // Create letter frame to wrap up the text
   11896             :         CreateLetterFrame(aBlockFrame, aBlockContinuation, textContent,
   11897           0 :                           aParentFrame, aLetterFrames);
   11898             : 
   11899             :         // Provide adjustment information for parent
   11900           0 :         *aModifiedParent = aParentFrame;
   11901           0 :         *aTextFrame = frame;
   11902           0 :         *aPrevFrame = prevFrame;
   11903           0 :         *aStopLooking = true;
   11904           0 :         return;
   11905             :       }
   11906           0 :     } else if (IsInlineFrame(frame) && frameType != LayoutFrameType::Br) {
   11907           0 :       nsIFrame* kids = frame->PrincipalChildList().FirstChild();
   11908             :       WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation,
   11909             :                                    static_cast<nsContainerFrame*>(frame),
   11910             :                                    kids, aModifiedParent, aTextFrame,
   11911           0 :                                    aPrevFrame, aLetterFrames, aStopLooking);
   11912           0 :       if (*aStopLooking) {
   11913           0 :         return;
   11914             :       }
   11915             :     }
   11916             :     else {
   11917             :       // This will stop us looking to create more letter frames. For
   11918             :       // example, maybe the frame-type is "letterFrame" or
   11919             :       // "placeholderFrame". This keeps us from creating extra letter
   11920             :       // frames, and also prevents us from creating letter frames when
   11921             :       // the first real content child of a block is not text (e.g. an
   11922             :       // image, hr, etc.)
   11923           0 :       *aStopLooking = true;
   11924           0 :       break;
   11925             :     }
   11926             : 
   11927           0 :     prevFrame = frame;
   11928           0 :     frame = nextFrame;
   11929             :   }
   11930             : }
   11931             : 
   11932             : static nsIFrame*
   11933           0 : FindFirstLetterFrame(nsIFrame* aFrame, nsIFrame::ChildListID aListID)
   11934             : {
   11935           0 :   nsFrameList list = aFrame->GetChildList(aListID);
   11936           0 :   for (nsFrameList::Enumerator e(list); !e.AtEnd(); e.Next()) {
   11937           0 :     if (e.get()->IsLetterFrame()) {
   11938           0 :       return e.get();
   11939             :     }
   11940             :   }
   11941           0 :   return nullptr;
   11942             : }
   11943             : 
   11944             : void
   11945           0 : nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
   11946             :   nsIPresShell* aPresShell,
   11947             :   nsIFrame* aBlockFrame)
   11948             : {
   11949             :   // Look for the first letter frame on the kFloatList, then kPushedFloatsList.
   11950             :   nsIFrame* floatFrame =
   11951           0 :     ::FindFirstLetterFrame(aBlockFrame, nsIFrame::kFloatList);
   11952           0 :   if (!floatFrame) {
   11953             :     floatFrame =
   11954           0 :       ::FindFirstLetterFrame(aBlockFrame, nsIFrame::kPushedFloatsList);
   11955           0 :     if (!floatFrame) {
   11956           0 :       return;
   11957             :     }
   11958             :   }
   11959             : 
   11960             :   // Take the text frame away from the letter frame (so it isn't
   11961             :   // destroyed when we destroy the letter frame).
   11962           0 :   nsIFrame* textFrame = floatFrame->PrincipalChildList().FirstChild();
   11963           0 :   if (!textFrame) {
   11964           0 :     return;
   11965             :   }
   11966             : 
   11967             :   // Discover the placeholder frame for the letter frame
   11968           0 :   nsPlaceholderFrame* placeholderFrame = floatFrame->GetPlaceholderFrame();
   11969           0 :   if (!placeholderFrame) {
   11970             :     // Somethings really wrong
   11971           0 :     return;
   11972             :   }
   11973           0 :   nsContainerFrame* parentFrame = placeholderFrame->GetParent();
   11974           0 :   if (!parentFrame) {
   11975             :     // Somethings really wrong
   11976           0 :     return;
   11977             :   }
   11978           0 :   static_cast<nsContainerFrame*>(parentFrame->FirstContinuation())->
   11979           0 :     ClearHasFirstLetterChild();
   11980             : 
   11981             :   // Create a new text frame with the right style context that maps
   11982             :   // all of the content that was previously part of the letter frame
   11983             :   // (and probably continued elsewhere).
   11984           0 :   nsStyleContext* parentSC = parentFrame->StyleContext();
   11985           0 :   nsIContent* textContent = textFrame->GetContent();
   11986           0 :   if (!textContent) {
   11987           0 :     return;
   11988             :   }
   11989           0 :   RefPtr<nsStyleContext> newSC = aPresShell->StyleSet()->
   11990           0 :     ResolveStyleForText(textContent, parentSC);
   11991           0 :   nsIFrame* newTextFrame = NS_NewTextFrame(aPresShell, newSC);
   11992           0 :   newTextFrame->Init(textContent, parentFrame, nullptr);
   11993             : 
   11994             :   // Destroy the old text frame's continuations (the old text frame
   11995             :   // will be destroyed when its letter frame is destroyed).
   11996           0 :   nsIFrame* frameToDelete = textFrame->LastContinuation();
   11997           0 :   while (frameToDelete != textFrame) {
   11998           0 :     nsIFrame* nextFrameToDelete = frameToDelete->GetPrevContinuation();
   11999           0 :     RemoveFrame(kPrincipalList, frameToDelete);
   12000           0 :     frameToDelete = nextFrameToDelete;
   12001             :   }
   12002             : 
   12003           0 :   nsIFrame* prevSibling = placeholderFrame->GetPrevSibling();
   12004             : 
   12005             :   // Now that everything is set...
   12006             : #ifdef NOISY_FIRST_LETTER
   12007             :   printf("RemoveFloatingFirstLetterFrames: textContent=%p oldTextFrame=%p newTextFrame=%p\n",
   12008             :          textContent.get(), textFrame, newTextFrame);
   12009             : #endif
   12010             : 
   12011             :   // Remove placeholder frame and the float
   12012           0 :   RemoveFrame(kPrincipalList, placeholderFrame);
   12013             : 
   12014             :   // Now that the old frames are gone, we can start pointing to our
   12015             :   // new primary frame.
   12016           0 :   textContent->SetPrimaryFrame(newTextFrame);
   12017             : 
   12018             :   // Wallpaper bug 822910.
   12019           0 :   bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
   12020           0 :   if (offsetsNeedFixing) {
   12021           0 :     prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
   12022             :   }
   12023             : 
   12024             :   // Insert text frame in its place
   12025           0 :   nsFrameList textList(newTextFrame, newTextFrame);
   12026           0 :   InsertFrames(parentFrame, kPrincipalList, prevSibling, textList);
   12027             : 
   12028           0 :   if (offsetsNeedFixing) {
   12029           0 :     prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
   12030             :   }
   12031             : }
   12032             : 
   12033             : void
   12034           0 : nsCSSFrameConstructor::RemoveFirstLetterFrames(nsIPresShell* aPresShell,
   12035             :                                                nsContainerFrame* aFrame,
   12036             :                                                nsContainerFrame* aBlockFrame,
   12037             :                                                bool* aStopLooking)
   12038             : {
   12039           0 :   nsIFrame* prevSibling = nullptr;
   12040           0 :   nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
   12041             : 
   12042           0 :   while (kid) {
   12043           0 :     if (kid->IsLetterFrame()) {
   12044             :       // Bingo. Found it. First steal away the text frame.
   12045           0 :       static_cast<nsContainerFrame*>(aFrame->FirstContinuation())->
   12046           0 :         ClearHasFirstLetterChild();
   12047           0 :       nsIFrame* textFrame = kid->PrincipalChildList().FirstChild();
   12048           0 :       if (!textFrame) {
   12049           0 :         break;
   12050             :       }
   12051             : 
   12052             :       // Create a new textframe
   12053           0 :       nsStyleContext* parentSC = aFrame->StyleContext();
   12054           0 :       if (!parentSC) {
   12055           0 :         break;
   12056             :       }
   12057           0 :       nsIContent* textContent = textFrame->GetContent();
   12058           0 :       if (!textContent) {
   12059           0 :         break;
   12060             :       }
   12061           0 :       RefPtr<nsStyleContext> newSC = aPresShell->StyleSet()->
   12062           0 :         ResolveStyleForText(textContent, parentSC);
   12063           0 :       textFrame = NS_NewTextFrame(aPresShell, newSC);
   12064           0 :       textFrame->Init(textContent, aFrame, nullptr);
   12065             : 
   12066             :       // Next rip out the kid and replace it with the text frame
   12067           0 :       RemoveFrame(kPrincipalList, kid);
   12068             : 
   12069             :       // Now that the old frames are gone, we can start pointing to our
   12070             :       // new primary frame.
   12071           0 :       textContent->SetPrimaryFrame(textFrame);
   12072             : 
   12073             :       // Wallpaper bug 822910.
   12074           0 :       bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
   12075           0 :       if (offsetsNeedFixing) {
   12076           0 :         prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
   12077             :       }
   12078             : 
   12079             :       // Insert text frame in its place
   12080           0 :       nsFrameList textList(textFrame, textFrame);
   12081           0 :       InsertFrames(aFrame, kPrincipalList, prevSibling, textList);
   12082             : 
   12083           0 :       if (offsetsNeedFixing) {
   12084           0 :         prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
   12085             :       }
   12086             : 
   12087           0 :       *aStopLooking = true;
   12088           0 :       NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),
   12089             :                    "should have the first continuation here");
   12090           0 :       aBlockFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
   12091           0 :       break;
   12092             :     }
   12093           0 :     else if (IsInlineFrame(kid)) {
   12094           0 :       nsContainerFrame* kidAsContainerFrame = do_QueryFrame(kid);
   12095           0 :       if (kidAsContainerFrame) {
   12096             :         // Look inside child inline frame for the letter frame.
   12097             :         RemoveFirstLetterFrames(aPresShell, kidAsContainerFrame,
   12098           0 :                                 aBlockFrame, aStopLooking);
   12099           0 :         if (*aStopLooking) {
   12100           0 :           break;
   12101             :         }
   12102             :       }
   12103             :     }
   12104           0 :     prevSibling = kid;
   12105           0 :     kid = kid->GetNextSibling();
   12106             :   }
   12107           0 : }
   12108             : 
   12109             : void
   12110           0 : nsCSSFrameConstructor::RemoveLetterFrames(nsIPresShell* aPresShell,
   12111             :                                           nsContainerFrame* aBlockFrame)
   12112             : {
   12113             :   aBlockFrame =
   12114           0 :     static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
   12115           0 :   aBlockFrame->RemoveProperty(nsContainerFrame::FirstLetterProperty());
   12116           0 :   nsContainerFrame* continuation = aBlockFrame;
   12117             : 
   12118           0 :   bool stopLooking = false;
   12119           0 :   do {
   12120           0 :     RemoveFloatingFirstLetterFrames(aPresShell, continuation);
   12121             :     RemoveFirstLetterFrames(aPresShell, continuation, aBlockFrame,
   12122           0 :                             &stopLooking);
   12123           0 :     if (stopLooking) {
   12124           0 :       break;
   12125             :     }
   12126             :     continuation =
   12127           0 :       static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
   12128           0 :   }  while (continuation);
   12129           0 : }
   12130             : 
   12131             : // Fixup the letter frame situation for the given block
   12132             : void
   12133           0 : nsCSSFrameConstructor::RecoverLetterFrames(nsContainerFrame* aBlockFrame)
   12134             : {
   12135             :   aBlockFrame =
   12136           0 :     static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
   12137           0 :   nsContainerFrame* continuation = aBlockFrame;
   12138             : 
   12139           0 :   nsContainerFrame* parentFrame = nullptr;
   12140           0 :   nsIFrame* textFrame = nullptr;
   12141           0 :   nsIFrame* prevFrame = nullptr;
   12142           0 :   nsFrameItems letterFrames;
   12143           0 :   bool stopLooking = false;
   12144           0 :   do {
   12145             :     // XXX shouldn't this bit be set already (bug 408493), assert instead?
   12146           0 :     continuation->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
   12147           0 :     WrapFramesInFirstLetterFrame(aBlockFrame, continuation, continuation,
   12148           0 :                                  continuation->PrincipalChildList().FirstChild(),
   12149             :                                  &parentFrame, &textFrame, &prevFrame,
   12150           0 :                                  letterFrames, &stopLooking);
   12151           0 :     if (stopLooking) {
   12152           0 :       break;
   12153             :     }
   12154             :     continuation =
   12155           0 :       static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
   12156           0 :   } while (continuation);
   12157             : 
   12158           0 :   if (parentFrame) {
   12159             :     // Take the old textFrame out of the parents child list
   12160           0 :     RemoveFrame(kPrincipalList, textFrame);
   12161             : 
   12162             :     // Insert in the letter frame(s)
   12163           0 :     parentFrame->InsertFrames(kPrincipalList, prevFrame, letterFrames);
   12164             :   }
   12165           0 : }
   12166             : 
   12167             : //----------------------------------------------------------------------
   12168             : 
   12169             : // listbox Widget Routines
   12170             : 
   12171             : void
   12172           0 : nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame*      aParentFrame,
   12173             :                                             nsIFrame*              aPrevFrame,
   12174             :                                             nsIContent*            aChild,
   12175             :                                             nsIFrame**             aNewFrame,
   12176             :                                             bool                   aIsAppend)
   12177             : {
   12178             : #ifdef MOZ_XUL
   12179             :   // Construct a new frame
   12180           0 :   if (nullptr != aParentFrame) {
   12181           0 :     nsFrameItems            frameItems;
   12182           0 :     TreeMatchContextHolder matchContext(mDocument);
   12183             :     nsFrameConstructorState state(mPresShell,
   12184             :                                   matchContext,
   12185             :                                   GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
   12186             :                                   GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
   12187             :                                   GetFloatContainingBlock(aParentFrame),
   12188           0 :                                   do_AddRef(mTempFrameTreeState.get()));
   12189             : 
   12190             :     // If we ever initialize the ancestor filter on |state|, make sure
   12191             :     // to push the right parent!
   12192             : 
   12193           0 :     RefPtr<nsStyleContext> styleContext;
   12194           0 :     styleContext = ResolveStyleContext(aParentFrame, aChild, &state);
   12195             : 
   12196             :     // Pre-check for display "none" - only if we find that, do we create
   12197             :     // any frame at all
   12198           0 :     const nsStyleDisplay* display = styleContext->StyleDisplay();
   12199             : 
   12200           0 :     if (StyleDisplay::None == display->mDisplay) {
   12201           0 :       *aNewFrame = nullptr;
   12202           0 :       return;
   12203             :     }
   12204             : 
   12205           0 :     BeginUpdate();
   12206             : 
   12207           0 :     FrameConstructionItemList items;
   12208           0 :     AddFrameConstructionItemsInternal(state, aChild, aParentFrame,
   12209             :                                       aChild->NodeInfo()->NameAtom(),
   12210             :                                       aChild->GetNameSpaceID(),
   12211             :                                       true, styleContext,
   12212           0 :                                       ITEM_ALLOW_XBL_BASE, nullptr, items);
   12213           0 :     ConstructFramesFromItemList(state, items, aParentFrame, frameItems);
   12214             : 
   12215           0 :     nsIFrame* newFrame = frameItems.FirstChild();
   12216           0 :     *aNewFrame = newFrame;
   12217             : 
   12218           0 :     if (newFrame) {
   12219             :       // Notify the parent frame
   12220           0 :       if (aIsAppend)
   12221           0 :         ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(frameItems);
   12222             :       else
   12223           0 :         ((nsListBoxBodyFrame*)aParentFrame)->ListBoxInsertFrames(aPrevFrame, frameItems);
   12224             :     }
   12225             : 
   12226           0 :     EndUpdate();
   12227             : 
   12228             : #ifdef ACCESSIBILITY
   12229           0 :     if (newFrame) {
   12230           0 :       nsAccessibilityService* accService = nsIPresShell::AccService();
   12231           0 :       if (accService) {
   12232           0 :         accService->ContentRangeInserted(mPresShell, aChild->GetParent(),
   12233           0 :                                          aChild, aChild->GetNextSibling());
   12234             :       }
   12235             :     }
   12236             : #endif
   12237             :   }
   12238             : #endif
   12239             : }
   12240             : 
   12241             : //----------------------------------------
   12242             : 
   12243             : void
   12244          22 : nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
   12245             :                                       nsIContent*              aContent,
   12246             :                                       nsContainerFrame*        aParentFrame,
   12247             :                                       nsContainerFrame*        aContentParentFrame,
   12248             :                                       nsStyleContext*          aStyleContext,
   12249             :                                       nsContainerFrame**       aNewFrame,
   12250             :                                       nsFrameItems&            aFrameItems,
   12251             :                                       nsIFrame*                aPositionedFrameForAbsPosContainer,
   12252             :                                       PendingBinding*          aPendingBinding)
   12253             : {
   12254             :   // Create column wrapper if necessary
   12255          22 :   nsContainerFrame* blockFrame = *aNewFrame;
   12256          22 :   NS_ASSERTION((blockFrame->IsBlockFrame() || blockFrame->IsDetailsFrame()),
   12257             :                "not a block frame nor a details frame?");
   12258          22 :   nsContainerFrame* parent = aParentFrame;
   12259          44 :   RefPtr<nsStyleContext> blockStyle = aStyleContext;
   12260          22 :   const nsStyleColumn* columns = aStyleContext->StyleColumn();
   12261             : 
   12262          44 :   if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO
   12263          22 :       || columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
   12264             :     nsContainerFrame* columnSetFrame =
   12265           0 :       NS_NewColumnSetFrame(mPresShell, aStyleContext,
   12266           0 :                            nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
   12267             : 
   12268           0 :     InitAndRestoreFrame(aState, aContent, aParentFrame, columnSetFrame);
   12269           0 :     blockStyle = mPresShell->StyleSet()->
   12270           0 :       ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::columnContent,
   12271           0 :                                          aStyleContext);
   12272           0 :     parent = columnSetFrame;
   12273           0 :     *aNewFrame = columnSetFrame;
   12274           0 :     if (aPositionedFrameForAbsPosContainer == blockFrame) {
   12275           0 :       aPositionedFrameForAbsPosContainer = columnSetFrame;
   12276             :     }
   12277             : 
   12278           0 :     SetInitialSingleChild(columnSetFrame, blockFrame);
   12279             :   }
   12280             : 
   12281          22 :   blockFrame->SetStyleContextWithoutNotification(blockStyle);
   12282          22 :   InitAndRestoreFrame(aState, aContent, parent, blockFrame);
   12283             : 
   12284          22 :   aState.AddChild(*aNewFrame, aFrameItems, aContent, aStyleContext,
   12285             :                   aContentParentFrame ? aContentParentFrame :
   12286          22 :                                         aParentFrame);
   12287          22 :   if (!mRootElementFrame) {
   12288             :     // The frame we're constructing will be the root element frame.
   12289             :     // Set mRootElementFrame before processing children.
   12290           2 :     mRootElementFrame = *aNewFrame;
   12291             :   }
   12292             : 
   12293             :   // We should make the outer frame be the absolute containing block,
   12294             :   // if one is required. We have to do this because absolute
   12295             :   // positioning must be computed with respect to the CSS dimensions
   12296             :   // of the element, which are the dimensions of the outer block. But
   12297             :   // we can't really do that because only blocks can have absolute
   12298             :   // children. So use the block and try to compensate with hacks
   12299             :   // in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
   12300          44 :   nsFrameConstructorSaveState absoluteSaveState;
   12301          22 :   (*aNewFrame)->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
   12302          22 :   if (aPositionedFrameForAbsPosContainer) {
   12303             :     //    NS_ASSERTION(aRelPos, "should have made area frame for this");
   12304           7 :     aState.PushAbsoluteContainingBlock(*aNewFrame, aPositionedFrameForAbsPosContainer, absoluteSaveState);
   12305             :   }
   12306             : 
   12307             :   // Process the child content
   12308          22 :   nsFrameItems childItems;
   12309             :   ProcessChildren(aState, aContent, aStyleContext, blockFrame, true,
   12310          22 :                   childItems, true, aPendingBinding);
   12311             : 
   12312             :   // Set the frame's initial child list
   12313          22 :   blockFrame->SetInitialChildList(kPrincipalList, childItems);
   12314          22 : }
   12315             : 
   12316             : nsIFrame*
   12317           0 : nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState,
   12318             :                                        FrameConstructionItem&   aItem,
   12319             :                                        nsContainerFrame*        aParentFrame,
   12320             :                                        const nsStyleDisplay*    aDisplay,
   12321             :                                        nsFrameItems&            aFrameItems)
   12322             : {
   12323             :   // If an inline frame has non-inline kids, then we chop up the child list
   12324             :   // into runs of blocks and runs of inlines, create anonymous block frames to
   12325             :   // contain the runs of blocks, inline frames with our style context for the
   12326             :   // runs of inlines, and put all these frames, in order, into aFrameItems.  We
   12327             :   // return the the first one.  The whole setup is called an {ib}
   12328             :   // split; in what follows "frames in the split" refers to the anonymous blocks
   12329             :   // and inlines that contain our children.
   12330             :   //
   12331             :   // {ib} splits maintain the following invariants:
   12332             :   // 1) All frames in the split have the NS_FRAME_PART_OF_IBSPLIT bit
   12333             :   //    set.
   12334             :   // 2) Each frame in the split has the nsIFrame::IBSplitSibling
   12335             :   //    property pointing to the next frame in the split, except for the last
   12336             :   //    one, which does not have it set.
   12337             :   // 3) Each frame in the split has the nsIFrame::IBSplitPrevSibling
   12338             :   //    property pointing to the previous frame in the split, except for the
   12339             :   //    first one, which does not have it set.
   12340             :   // 4) The first and last frame in the split are always inlines.
   12341             :   //
   12342             :   // An invariant that is NOT maintained is that the wrappers are actually
   12343             :   // linked via GetNextSibling linkage.  A simple example is an inline
   12344             :   // containing an inline that contains a block.  The three parts of the inner
   12345             :   // inline end up with three different parents.
   12346             :   //
   12347             :   // For example, this HTML:
   12348             :   // <span>
   12349             :   //   <div>a</div>
   12350             :   //   <span>
   12351             :   //     b
   12352             :   //     <div>c</div>
   12353             :   //   </span>
   12354             :   //   d
   12355             :   //   <div>e</div>
   12356             :   //   f
   12357             :   //  </span>
   12358             :   // Gives the following frame tree:
   12359             :   //
   12360             :   // Inline (outer span)
   12361             :   // Block (anonymous, outer span)
   12362             :   //   Block (div)
   12363             :   //     Text("a")
   12364             :   // Inline (outer span)
   12365             :   //   Inline (inner span)
   12366             :   //     Text("b")
   12367             :   // Block (anonymous, outer span)
   12368             :   //   Block (anonymous, inner span)
   12369             :   //     Block (div)
   12370             :   //       Text("c")
   12371             :   // Inline (outer span)
   12372             :   //   Inline (inner span)
   12373             :   //   Text("d")
   12374             :   // Block (anonymous, outer span)
   12375             :   //   Block (div)
   12376             :   //     Text("e")
   12377             :   // Inline (outer span)
   12378             :   //   Text("f")
   12379             : 
   12380           0 :   nsIContent* const content = aItem.mContent;
   12381           0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
   12382             : 
   12383             :   bool positioned =
   12384           0 :     StyleDisplay::Inline == aDisplay->mDisplay &&
   12385           0 :     aDisplay->IsRelativelyPositionedStyle() &&
   12386           0 :     !nsSVGUtils::IsInSVGTextSubtree(aParentFrame);
   12387             : 
   12388           0 :   nsInlineFrame* newFrame = NS_NewInlineFrame(mPresShell, styleContext);
   12389             : 
   12390             :   // Initialize the frame
   12391           0 :   InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
   12392             : 
   12393             :   // Inline frames can always have generated content
   12394           0 :   newFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
   12395             : 
   12396           0 :   nsFrameConstructorSaveState absoluteSaveState;  // definition cannot be inside next block
   12397             :                                                   // because the object's destructor is significant
   12398             :                                                   // this is part of the fix for bug 42372
   12399             : 
   12400           0 :   newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
   12401           0 :   if (positioned) {
   12402             :     // Relatively positioned frames becomes a container for child
   12403             :     // frames that are positioned
   12404           0 :     aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
   12405             :   }
   12406             : 
   12407             :   // Process the child content
   12408           0 :   nsFrameItems childItems;
   12409           0 :   ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame, childItems);
   12410             : 
   12411           0 :   nsFrameList::FrameLinkEnumerator firstBlockEnumerator(childItems);
   12412           0 :   if (!aItem.mIsAllInline) {
   12413           0 :     FindFirstBlock(firstBlockEnumerator);
   12414             :   }
   12415             : 
   12416           0 :   if (aItem.mIsAllInline || firstBlockEnumerator.AtEnd()) {
   12417             :     // This part is easy.  We either already know we have no non-inline kids,
   12418             :     // or haven't found any when constructing actual frames (the latter can
   12419             :     // happen only if out-of-flows that we thought had no containing block
   12420             :     // acquired one when ancestor inline frames and {ib} splits got
   12421             :     // constructed).  Just put all the kids into the single inline frame and
   12422             :     // bail.
   12423           0 :     newFrame->SetInitialChildList(kPrincipalList, childItems);
   12424           0 :     aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame);
   12425           0 :     return newFrame;
   12426             :   }
   12427             : 
   12428             :   // This inline frame contains several types of children. Therefore this frame
   12429             :   // has to be chopped into several pieces, as described above.
   12430             : 
   12431             :   // Grab the first inline's kids
   12432           0 :   nsFrameList firstInlineKids = childItems.ExtractHead(firstBlockEnumerator);
   12433           0 :   newFrame->SetInitialChildList(kPrincipalList, firstInlineKids);
   12434             : 
   12435           0 :   aFrameItems.AddChild(newFrame);
   12436             : 
   12437           0 :   newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
   12438           0 :   CreateIBSiblings(aState, newFrame, positioned, childItems, aFrameItems);
   12439             : 
   12440           0 :   return newFrame;
   12441             : }
   12442             : 
   12443             : void
   12444           0 : nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState,
   12445             :                                         nsContainerFrame* aInitialInline,
   12446             :                                         bool aIsPositioned,
   12447             :                                         nsFrameItems& aChildItems,
   12448             :                                         nsFrameItems& aSiblings)
   12449             : {
   12450           0 :   nsIContent* content = aInitialInline->GetContent();
   12451           0 :   nsStyleContext* styleContext = aInitialInline->StyleContext();
   12452           0 :   nsContainerFrame* parentFrame = aInitialInline->GetParent();
   12453             : 
   12454             :   // Resolve the right style context for our anonymous blocks.
   12455             :   // The distinction in styles is needed because of CSS 2.1, section
   12456             :   // 9.2.1.1, which says:
   12457             :   //   When such an inline box is affected by relative positioning, any
   12458             :   //   resulting translation also affects the block-level box contained
   12459             :   //   in the inline box.
   12460           0 :   RefPtr<nsStyleContext> blockSC = mPresShell->StyleSet()->
   12461           0 :     ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::mozBlockInsideInlineWrapper,
   12462           0 :                                        styleContext);
   12463             : 
   12464             :   nsContainerFrame* lastNewInline =
   12465           0 :     static_cast<nsContainerFrame*>(aInitialInline->FirstContinuation());
   12466           0 :   do {
   12467             :     // On entry to this loop aChildItems is not empty and the first frame in it
   12468             :     // is block-level.
   12469           0 :     NS_PRECONDITION(aChildItems.NotEmpty(), "Should have child items");
   12470           0 :     NS_PRECONDITION(!aChildItems.FirstChild()->IsInlineOutside(),
   12471             :                     "Must have list starting with block");
   12472             : 
   12473             :     // The initial run of blocks belongs to an anonymous block that we create
   12474             :     // right now. The anonymous block will be the parent of these block
   12475             :     // children of the inline.
   12476           0 :     nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
   12477           0 :     InitAndRestoreFrame(aState, content, parentFrame, blockFrame, false);
   12478             : 
   12479             :     // Find the first non-block child which defines the end of our block kids
   12480             :     // and the start of our next inline's kids
   12481             :     nsFrameList::FrameLinkEnumerator firstNonBlock =
   12482           0 :       FindFirstNonBlock(aChildItems);
   12483           0 :     nsFrameList blockKids = aChildItems.ExtractHead(firstNonBlock);
   12484             : 
   12485           0 :     MoveChildrenTo(aInitialInline, blockFrame, blockKids);
   12486             : 
   12487           0 :     SetFrameIsIBSplit(lastNewInline, blockFrame);
   12488           0 :     aSiblings.AddChild(blockFrame);
   12489             : 
   12490             :     // Now grab the initial inlines in aChildItems and put them into an inline
   12491             :     // frame.
   12492           0 :     nsInlineFrame* inlineFrame = NS_NewInlineFrame(mPresShell, styleContext);
   12493           0 :     InitAndRestoreFrame(aState, content, parentFrame, inlineFrame, false);
   12494           0 :     inlineFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT |
   12495           0 :                               NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
   12496           0 :     if (aIsPositioned) {
   12497           0 :       inlineFrame->MarkAsAbsoluteContainingBlock();
   12498             :     }
   12499             : 
   12500           0 :     if (aChildItems.NotEmpty()) {
   12501           0 :       nsFrameList::FrameLinkEnumerator firstBlock(aChildItems);
   12502           0 :       FindFirstBlock(firstBlock);
   12503           0 :       nsFrameList inlineKids = aChildItems.ExtractHead(firstBlock);
   12504             : 
   12505           0 :       MoveChildrenTo(aInitialInline, inlineFrame, inlineKids);
   12506             :     }
   12507             : 
   12508           0 :     SetFrameIsIBSplit(blockFrame, inlineFrame);
   12509           0 :     aSiblings.AddChild(inlineFrame);
   12510           0 :     lastNewInline = inlineFrame;
   12511           0 :   } while (aChildItems.NotEmpty());
   12512             : 
   12513           0 :   SetFrameIsIBSplit(lastNewInline, nullptr);
   12514           0 : }
   12515             : 
   12516             : void
   12517           0 : nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
   12518             :                                              FrameConstructionItem& aParentItem,
   12519             :                                              bool aItemIsWithinSVGText,
   12520             :                                              bool aItemAllowsTextPathChild)
   12521             : {
   12522             :   // XXXbz should we preallocate aParentItem.mChildItems to some sane
   12523             :   // length?  Maybe even to parentContent->GetChildCount()?
   12524             :   nsFrameConstructorState::PendingBindingAutoPusher
   12525           0 :     pusher(aState, aParentItem.mPendingBinding);
   12526             : 
   12527           0 :   nsStyleContext* const parentStyleContext = aParentItem.mStyleContext;
   12528           0 :   nsIContent* const parentContent = aParentItem.mContent;
   12529             : 
   12530           0 :   TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
   12531           0 :   if (aState.HasAncestorFilter()) {
   12532           0 :     ancestorPusher.PushAncestorAndStyleScope(parentContent->AsElement());
   12533             :   } else {
   12534           0 :     ancestorPusher.PushStyleScope(parentContent->AsElement());
   12535             :   }
   12536             : 
   12537           0 :   if (!aItemIsWithinSVGText) {
   12538             :     // Probe for generated content before
   12539           0 :     CreateGeneratedContentItem(aState, nullptr, parentContent, parentStyleContext,
   12540             :                                CSSPseudoElementType::before,
   12541           0 :                                aParentItem.mChildItems);
   12542             :   }
   12543             : 
   12544           0 :   uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK;
   12545           0 :   if (aItemIsWithinSVGText) {
   12546           0 :     flags |= ITEM_IS_WITHIN_SVG_TEXT;
   12547             :   }
   12548           0 :   if (aItemAllowsTextPathChild && aParentItem.mIsForSVGAElement) {
   12549           0 :     flags |= ITEM_ALLOWS_TEXT_PATH_CHILD;
   12550             :   }
   12551             : 
   12552           0 :   if (!aParentItem.mAnonChildren.IsEmpty()) {
   12553             :     // Use the anon-children list instead of the content tree child list so
   12554             :     // that we use any special style context that should be associated with
   12555             :     // the children, and so that we won't try to construct grandchildren frame
   12556             :     // constructor items before the frame is available for their parent.
   12557           0 :     AddFCItemsForAnonymousContent(aState, nullptr, aParentItem.mAnonChildren,
   12558           0 :                                   aParentItem.mChildItems, flags);
   12559             :   } else {
   12560             :     // Use the content tree child list:
   12561           0 :     FlattenedChildIterator iter(parentContent);
   12562           0 :     for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) {
   12563             :       // Get the parent of the content and check if it is a XBL children element
   12564             :       // (if the content is a children element then contentParent != parentContent because the
   12565             :       // FlattenedChildIterator will transitively iterate through <xbl:children>
   12566             :       // for default content). Push the children element as an ancestor here because
   12567             :       // it does not have a frame and would not otherwise be pushed as an ancestor.
   12568           0 :       nsIContent* contentParent = content->GetParent();
   12569           0 :       MOZ_ASSERT(contentParent, "Parent must be non-null because we are iterating children.");
   12570           0 :       TreeMatchContext::AutoAncestorPusher insertionPointPusher(aState.mTreeMatchContext);
   12571           0 :       if (contentParent != parentContent && contentParent->IsElement()) {
   12572           0 :         if (aState.HasAncestorFilter()) {
   12573           0 :           insertionPointPusher.PushAncestorAndStyleScope(contentParent->AsElement());
   12574             :         } else {
   12575           0 :           insertionPointPusher.PushStyleScope(contentParent->AsElement());
   12576             :         }
   12577             :       }
   12578             : 
   12579             :       // Manually check for comments/PIs, since we don't have a frame to pass to
   12580             :       // AddFrameConstructionItems.  We know our parent is a non-replaced inline,
   12581             :       // so there is no need to do the NeedFrameFor check.
   12582           0 :       content->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
   12583           0 :       if (content->IsNodeOfType(nsINode::eCOMMENT) ||
   12584           0 :           content->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
   12585           0 :         continue;
   12586             :       }
   12587             : 
   12588             :       // See comment explaining why we need to remove the "is possible
   12589             :       // restyle root" flags in AddFrameConstructionItems.  But note
   12590             :       // that we can remove all restyle flags, just like in
   12591             :       // ProcessChildren and for the same reason.
   12592           0 :       content->UnsetRestyleFlagsIfGecko();
   12593             : 
   12594             :       RefPtr<nsStyleContext> childContext =
   12595           0 :         ResolveStyleContext(parentStyleContext, content, &aState);
   12596             : 
   12597           0 :       AddFrameConstructionItemsInternal(aState, content, nullptr,
   12598             :                                         content->NodeInfo()->NameAtom(),
   12599             :                                         content->GetNameSpaceID(),
   12600           0 :                                         iter.XBLInvolved(), childContext,
   12601             :                                         flags, nullptr,
   12602           0 :                                         aParentItem.mChildItems);
   12603             :     }
   12604             :   }
   12605             : 
   12606           0 :   if (!aItemIsWithinSVGText) {
   12607             :     // Probe for generated content after
   12608           0 :     CreateGeneratedContentItem(aState, nullptr, parentContent, parentStyleContext,
   12609             :                                CSSPseudoElementType::after,
   12610           0 :                                aParentItem.mChildItems);
   12611             :   }
   12612             : 
   12613           0 :   aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
   12614           0 : }
   12615             : 
   12616             : // return whether it's ok to append (in the AppendFrames sense) to
   12617             : // aParentFrame if our nextSibling is aNextSibling.  aParentFrame must
   12618             : // be an ib-split inline.
   12619             : static bool
   12620           0 : IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame, nsIFrame* aNextSibling)
   12621             : {
   12622           0 :   NS_PRECONDITION(IsInlineFrame(aParentFrame),
   12623             :                   "Must have an inline parent here");
   12624           0 :   do {
   12625           0 :     NS_ASSERTION(IsFramePartOfIBSplit(aParentFrame),
   12626             :                  "How is this not part of an ib-split?");
   12627           0 :     if (aNextSibling || aParentFrame->GetNextContinuation() ||
   12628           0 :         GetIBSplitSibling(aParentFrame)) {
   12629           0 :       return false;
   12630             :     }
   12631             : 
   12632           0 :     aNextSibling = aParentFrame->GetNextSibling();
   12633           0 :     aParentFrame = aParentFrame->GetParent();
   12634             :   } while (IsInlineFrame(aParentFrame));
   12635             : 
   12636           0 :   return true;
   12637             : }
   12638             : 
   12639             : bool
   12640          60 : nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
   12641             :                                            nsIFrame* aContainingBlock,
   12642             :                                            nsIFrame* aFrame,
   12643             :                                            FrameConstructionItemList& aItems,
   12644             :                                            bool aIsAppend,
   12645             :                                            nsIFrame* aPrevSibling)
   12646             : {
   12647          60 :   if (aItems.IsEmpty()) {
   12648          16 :     return false;
   12649             :   }
   12650             : 
   12651             :   // Before we go and append the frames, we must check for several
   12652             :   // special situations.
   12653             : 
   12654             :   // Situation #1 is a XUL frame that contains frames that are required
   12655             :   // to be wrapped in blocks.
   12656         110 :   if (aFrame->IsXULBoxFrame() &&
   12657          66 :       !(aFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
   12658          22 :       aItems.AnyItemsNeedBlockParent()) {
   12659           0 :     RecreateFramesForContent(aFrame->GetContent(), true,
   12660           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
   12661           0 :     return true;
   12662             :   }
   12663             : 
   12664          44 :   nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
   12665             : 
   12666             :   // Situation #2 is a flex or grid container frame into which we're inserting
   12667             :   // new inline non-replaced children, adjacent to an existing anonymous
   12668             :   // flex or grid item.
   12669          44 :   LayoutFrameType frameType = aFrame->Type();
   12670          44 :   if (frameType == LayoutFrameType::FlexContainer ||
   12671             :       frameType == LayoutFrameType::GridContainer) {
   12672           0 :     FCItemIterator iter(aItems);
   12673             : 
   12674             :     // Check if we're adding to-be-wrapped content right *after* an existing
   12675             :     // anonymous flex or grid item (which would need to absorb this content).
   12676           0 :     const bool isWebkitBox = IsFlexContainerForLegacyBox(aFrame);
   12677           0 :     if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
   12678           0 :         iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox)) {
   12679           0 :       RecreateFramesForContent(aFrame->GetContent(), true,
   12680           0 :                                REMOVE_FOR_RECONSTRUCTION, nullptr);
   12681           0 :       return true;
   12682             :     }
   12683             : 
   12684             :     // Check if we're adding to-be-wrapped content right *before* an existing
   12685             :     // anonymous flex or grid item (which would need to absorb this content).
   12686           0 :     if (nextSibling && IsAnonymousFlexOrGridItem(nextSibling)) {
   12687             :       // Jump to the last entry in the list
   12688           0 :       iter.SetToEnd();
   12689           0 :       iter.Prev();
   12690           0 :       if (iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox)) {
   12691           0 :         RecreateFramesForContent(aFrame->GetContent(), true,
   12692           0 :                                  REMOVE_FOR_RECONSTRUCTION, nullptr);
   12693           0 :         return true;
   12694             :       }
   12695             :     }
   12696             :   }
   12697             : 
   12698             :   // Situation #3 is an anonymous flex or grid item that's getting new children
   12699             :   // who don't want to be wrapped.
   12700          44 :   if (IsAnonymousFlexOrGridItem(aFrame)) {
   12701           0 :     AssertAnonymousFlexOrGridItemParent(aFrame, aFrame->GetParent());
   12702             : 
   12703             :     // We need to push a null float containing block to be sure that
   12704             :     // "NeedsAnonFlexOrGridItem" will know we're not honoring floats for this
   12705             :     // inserted content. (In particular, this is necessary in order for
   12706             :     // its "GetGeometricParent" call to return the correct result.)
   12707             :     // We're not honoring floats on this content because it has the
   12708             :     // _flex/grid container_ as its parent in the content tree.
   12709           0 :     nsFrameConstructorSaveState floatSaveState;
   12710           0 :     aState.PushFloatContainingBlock(nullptr, floatSaveState);
   12711             : 
   12712           0 :     FCItemIterator iter(aItems);
   12713             :     // Skip over things that _do_ need an anonymous flex item, because
   12714             :     // they're perfectly happy to go here -- they won't cause a reframe.
   12715           0 :     nsIFrame* containerFrame = aFrame->GetParent();
   12716           0 :     const bool isWebkitBox = IsFlexContainerForLegacyBox(containerFrame);
   12717           0 :     if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState,
   12718             :                                                   isWebkitBox)) {
   12719             :       // We hit something that _doesn't_ need an anonymous flex item!
   12720             :       // Rebuild the flex container to bust it out.
   12721           0 :       RecreateFramesForContent(containerFrame->GetContent(), true,
   12722           0 :                                REMOVE_FOR_RECONSTRUCTION, nullptr);
   12723           0 :       return true;
   12724             :     }
   12725             : 
   12726             :     // If we get here, then everything in |aItems| needs to be wrapped in
   12727             :     // an anonymous flex or grid item.  That's where it's already going - good!
   12728             :   }
   12729             : 
   12730             :   // Situation #4 is a ruby-related frame that's getting new children.
   12731             :   // The situation for ruby is complex, especially when interacting with
   12732             :   // spaces. It containes these two special cases apart from tables:
   12733             :   // 1) There are effectively three types of white spaces in ruby frames
   12734             :   //    we handle differently: leading/tailing/inter-level space,
   12735             :   //    inter-base/inter-annotation space, and inter-segment space.
   12736             :   //    These three types of spaces can be converted to each other when
   12737             :   //    their sibling changes.
   12738             :   // 2) The first effective child of a ruby frame must always be a ruby
   12739             :   //    base container. It should be created or destroyed accordingly.
   12740          88 :   if (IsRubyPseudo(aFrame) || frameType == LayoutFrameType::Ruby ||
   12741          44 :       RubyUtils::IsRubyContainerBox(frameType)) {
   12742             :     // We want to optimize it better, and avoid reframing as much as
   12743             :     // possible. But given the cases above, and the fact that a ruby
   12744             :     // usually won't be very large, it should be fine to reframe it.
   12745           0 :     RecreateFramesForContent(aFrame->GetContent(), true,
   12746           0 :                              REMOVE_FOR_RECONSTRUCTION, nullptr);
   12747           0 :     return true;
   12748             :   }
   12749             : 
   12750             :   // Situation #5 is a case when table pseudo-frames don't work out right
   12751          44 :   ParentType parentType = GetParentType(aFrame);
   12752             :   // If all the kids want a parent of the type that aFrame is, then we're all
   12753             :   // set to go.  Indeed, there won't be any table pseudo-frames created between
   12754             :   // aFrame and the kids, so those won't need to be merged with any table
   12755             :   // pseudo-frames that might already be kids of aFrame.  If aFrame itself is a
   12756             :   // table pseudo-frame, then all the kids in this list would have wanted a
   12757             :   // frame of that type wrapping them anyway, so putting them inside it is ok.
   12758          44 :   if (!aItems.AllWantParentType(parentType)) {
   12759             :     // Don't give up yet.  If parentType is not eTypeBlock and the parent is
   12760             :     // not a generated content frame, then try filtering whitespace out of the
   12761             :     // list.
   12762           0 :     if (parentType != eTypeBlock && !aFrame->IsGeneratedContentFrame()) {
   12763             :       // For leading whitespace followed by a kid that wants our parent type,
   12764             :       // there are four cases:
   12765             :       // 1) We have a previous sibling which is not a table pseudo.  That means
   12766             :       //    that previous sibling wanted a (non-block) parent of the type we're
   12767             :       //    looking at.  Then the whitespace comes between two table-internal
   12768             :       //    elements, so should be collapsed out.
   12769             :       // 2) We have a previous sibling which is a table pseudo.  It might have
   12770             :       //    kids who want this whitespace, so we need to reframe.
   12771             :       // 3) We have no previous sibling and our parent frame is not a table
   12772             :       //    pseudo.  That means that we'll be at the beginning of our actual
   12773             :       //    non-block-type parent, and the whitespace is OK to collapse out.
   12774             :       //    If something is ever inserted before us, it'll find our own parent
   12775             :       //    as its parent and if it's something that would care about the
   12776             :       //    whitespace it'll want a block parent, so it'll trigger a reframe at
   12777             :       //    that point.
   12778             :       // 4) We have no previous sibling and our parent frame is a table pseudo.
   12779             :       //    Need to reframe.
   12780             :       // All that is predicated on finding the correct previous sibling.  We
   12781             :       // might have to walk backwards along continuations from aFrame to do so.
   12782             :       //
   12783             :       // It's always OK to drop whitespace between any two items that want a
   12784             :       // parent of type parentType.
   12785             :       //
   12786             :       // For trailing whitespace preceded by a kid that wants our parent type,
   12787             :       // there are four cases:
   12788             :       // 1) We have a next sibling which is not a table pseudo.  That means
   12789             :       //    that next sibling wanted a (non-block) parent of the type we're
   12790             :       //    looking at.  Then the whitespace comes between two table-internal
   12791             :       //    elements, so should be collapsed out.
   12792             :       // 2) We have a next sibling which is a table pseudo.  It might have
   12793             :       //    kids who want this whitespace, so we need to reframe.
   12794             :       // 3) We have no next sibling and our parent frame is not a table
   12795             :       //    pseudo.  That means that we'll be at the end of our actual
   12796             :       //    non-block-type parent, and the whitespace is OK to collapse out.
   12797             :       //    If something is ever inserted after us, it'll find our own parent
   12798             :       //    as its parent and if it's something that would care about the
   12799             :       //    whitespace it'll want a block parent, so it'll trigger a reframe at
   12800             :       //    that point.
   12801             :       // 4) We have no next sibling and our parent frame is a table pseudo.
   12802             :       //    Need to reframe.
   12803             :       // All that is predicated on finding the correct next sibling.  We might
   12804             :       // have to walk forward along continuations from aFrame to do so.  That
   12805             :       // said, in the case when nextSibling is null at this point and aIsAppend
   12806             :       // is true, we know we're in case 3.  Furthermore, in that case we don't
   12807             :       // even have to worry about the table pseudo situation; we know our
   12808             :       // parent is not a table pseudo there.
   12809           0 :       FCItemIterator iter(aItems);
   12810           0 :       FCItemIterator start(iter);
   12811           0 :       do {
   12812           0 :         if (iter.SkipItemsWantingParentType(parentType)) {
   12813           0 :           break;
   12814             :         }
   12815             : 
   12816             :         // iter points to an item that wants a different parent.  If it's not
   12817             :         // whitespace, we're done; no more point scanning the list.
   12818           0 :         if (!iter.item().IsWhitespace(aState)) {
   12819           0 :           break;
   12820             :         }
   12821             : 
   12822           0 :         if (iter == start) {
   12823             :           // Leading whitespace.  How to handle this depends on our
   12824             :           // previous sibling and aFrame.  See the long comment above.
   12825           0 :           nsIFrame* prevSibling = aPrevSibling;
   12826           0 :           if (!prevSibling) {
   12827             :             // Try to find one after all
   12828           0 :             nsIFrame* parentPrevCont = aFrame->GetPrevContinuation();
   12829           0 :             while (parentPrevCont) {
   12830           0 :               prevSibling = parentPrevCont->GetChildList(kPrincipalList).LastChild();
   12831           0 :               if (prevSibling) {
   12832           0 :                 break;
   12833             :               }
   12834           0 :               parentPrevCont = parentPrevCont->GetPrevContinuation();
   12835             :             }
   12836             :           };
   12837           0 :           if (prevSibling) {
   12838           0 :             if (IsTablePseudo(prevSibling)) {
   12839             :               // need to reframe
   12840           0 :               break;
   12841             :             }
   12842           0 :           } else if (IsTablePseudo(aFrame)) {
   12843             :             // need to reframe
   12844           0 :             break;
   12845             :           }
   12846             :         }
   12847             : 
   12848           0 :         FCItemIterator spaceEndIter(iter);
   12849             :         // Advance spaceEndIter past any whitespace
   12850           0 :         bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
   12851             : 
   12852             :         bool okToDrop;
   12853           0 :         if (trailingSpaces) {
   12854             :           // Trailing whitespace.  How to handle this depeds on aIsAppend, our
   12855             :           // next sibling and aFrame.  See the long comment above.
   12856           0 :           okToDrop = aIsAppend && !nextSibling;
   12857           0 :           if (!okToDrop) {
   12858           0 :             if (!nextSibling) {
   12859             :               // Try to find one after all
   12860           0 :               nsIFrame* parentNextCont = aFrame->GetNextContinuation();
   12861           0 :               while (parentNextCont) {
   12862           0 :                 nextSibling = parentNextCont->PrincipalChildList().FirstChild();
   12863           0 :                 if (nextSibling) {
   12864           0 :                   break;
   12865             :                 }
   12866           0 :                 parentNextCont = parentNextCont->GetNextContinuation();
   12867             :               }
   12868             :             }
   12869             : 
   12870           0 :             okToDrop = (nextSibling && !IsTablePseudo(nextSibling)) ||
   12871           0 :                        (!nextSibling && !IsTablePseudo(aFrame));
   12872             :           }
   12873             : #ifdef DEBUG
   12874             :           else {
   12875           0 :             NS_ASSERTION(!IsTablePseudo(aFrame), "How did that happen?");
   12876             :           }
   12877             : #endif
   12878             :         } else {
   12879           0 :           okToDrop = (spaceEndIter.item().DesiredParentType() == parentType);
   12880             :         }
   12881             : 
   12882           0 :         if (okToDrop) {
   12883           0 :           iter.DeleteItemsTo(spaceEndIter);
   12884             :         } else {
   12885             :           // We're done: we don't want to drop the whitespace, and it has the
   12886             :           // wrong parent type.
   12887           0 :           break;
   12888             :         }
   12889             : 
   12890             :         // Now loop, since |iter| points to item right after the whitespace we
   12891             :         // removed.
   12892           0 :       } while (!iter.IsDone());
   12893             :     }
   12894             : 
   12895             :     // We might be able to figure out some sort of optimizations here, but they
   12896             :     // would have to depend on having a correct aPrevSibling and a correct next
   12897             :     // sibling.  For example, we can probably avoid reframing if none of
   12898             :     // aFrame, aPrevSibling, and next sibling are table pseudo-frames.  But it
   12899             :     // doesn't seem worth it to worry about that for now, especially since we
   12900             :     // in fact do not have a reliable aPrevSibling, nor any next sibling, in
   12901             :     // this method.
   12902             : 
   12903             :     // aItems might have changed, so recheck the parent type thing.  In fact,
   12904             :     // it might be empty, so recheck that too.
   12905           0 :     if (aItems.IsEmpty()) {
   12906           0 :       return false;
   12907             :     }
   12908             : 
   12909           0 :     if (!aItems.AllWantParentType(parentType)) {
   12910             :       // Reframing aFrame->GetContent() is good enough, since the content of
   12911             :       // table pseudo-frames is the ancestor content.
   12912           0 :       RecreateFramesForContent(aFrame->GetContent(), true,
   12913           0 :                                REMOVE_FOR_RECONSTRUCTION, nullptr);
   12914           0 :       return true;
   12915             :     }
   12916             :   }
   12917             : 
   12918             :   // Now we have several cases involving {ib} splits.  Put them all in a
   12919             :   // do/while with breaks to take us to the "go and reconstruct" code.
   12920             :   do {
   12921          44 :     if (IsInlineFrame(aFrame)) {
   12922           0 :       if (aItems.AreAllItemsInline()) {
   12923             :         // We can just put the kids in.
   12924           0 :         return false;
   12925             :       }
   12926             : 
   12927           0 :       if (!IsFramePartOfIBSplit(aFrame)) {
   12928             :         // Need to go ahead and reconstruct.
   12929           0 :         break;
   12930             :       }
   12931             : 
   12932             :       // Now we're adding kids including some blocks to an inline part of an
   12933             :       // {ib} split.  If we plan to call AppendFrames, and don't have a next
   12934             :       // sibling for the new frames, and our parent is the last continuation of
   12935             :       // the last part of the {ib} split, and the same is true of all our
   12936             :       // ancestor inlines (they have no following continuations and they're the
   12937             :       // last part of their {ib} splits and we'd be adding to the end for all
   12938             :       // of them), then AppendFrames will handle things for us.  Bail out in
   12939             :       // that case.
   12940           0 :       if (aIsAppend && IsSafeToAppendToIBSplitInline(aFrame, nextSibling)) {
   12941           0 :         return false;
   12942             :       }
   12943             : 
   12944             :       // Need to reconstruct.
   12945           0 :       break;
   12946             :     }
   12947             : 
   12948             :     // Now we know we have a block parent.  If it's not part of an
   12949             :     // ib-split, we're all set.
   12950          44 :     if (!IsFramePartOfIBSplit(aFrame)) {
   12951          44 :       return false;
   12952             :     }
   12953             : 
   12954             :     // We're adding some kids to a block part of an {ib} split.  If all the
   12955             :     // kids are blocks, we don't need to reconstruct.
   12956           0 :     if (aItems.AreAllItemsBlock()) {
   12957           0 :       return false;
   12958             :     }
   12959             : 
   12960             :     // We might have some inline kids for this block.  Just fall out of the
   12961             :     // loop and reconstruct.
   12962             :   } while (0);
   12963             : 
   12964             :   // If we don't have a containing block, start with aFrame and look for one.
   12965           0 :   if (!aContainingBlock) {
   12966           0 :     aContainingBlock = aFrame;
   12967             :   }
   12968             : 
   12969             :   // To find the right block to reframe, just walk up the tree until we find a
   12970             :   // frame that is:
   12971             :   // 1)  Not part of an IB split
   12972             :   // 2)  Not a pseudo-frame
   12973             :   // 3)  Not an inline frame
   12974             :   // We're guaranteed to find one, since nsStyleContext::ApplyStyleFixups
   12975             :   // enforces that the root is display:none, display:table, or display:block.
   12976             :   // Note that walking up "too far" is OK in terms of correctness, even if it
   12977             :   // might be a little inefficient.  This is why we walk out of all
   12978             :   // pseudo-frames -- telling which ones are or are not OK to walk out of is
   12979             :   // too hard (and I suspect that we do in fact need to walk out of all of
   12980             :   // them).
   12981           0 :   while (IsFramePartOfIBSplit(aContainingBlock) ||
   12982           0 :          aContainingBlock->IsInlineOutside() ||
   12983           0 :          aContainingBlock->StyleContext()->GetPseudo()) {
   12984           0 :     aContainingBlock = aContainingBlock->GetParent();
   12985           0 :     NS_ASSERTION(aContainingBlock,
   12986             :                  "Must have non-inline, non-ib-split, non-pseudo frame as "
   12987             :                  "root (or child of root, for a table root)!");
   12988             :   }
   12989             : 
   12990             :   // Tell parent of the containing block to reformulate the
   12991             :   // entire block. This is painful and definitely not optimal
   12992             :   // but it will *always* get the right answer.
   12993             : 
   12994           0 :   nsIContent *blockContent = aContainingBlock->GetContent();
   12995             : #ifdef DEBUG
   12996           0 :   if (gNoisyContentUpdates) {
   12997             :     printf("nsCSSFrameConstructor::WipeContainingBlock: blockContent=%p\n",
   12998           0 :            static_cast<void*>(blockContent));
   12999             :   }
   13000             : #endif
   13001             :   RecreateFramesForContent(blockContent, true, REMOVE_FOR_RECONSTRUCTION,
   13002           0 :                            nullptr);
   13003           0 :   return true;
   13004             : }
   13005             : 
   13006             : void
   13007           0 : nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame*    aFrame,
   13008             :                                               RemoveFlags  aFlags,
   13009             :                                               nsIContent** aDestroyedFramesFor)
   13010             : {
   13011             : 
   13012             : #ifdef DEBUG
   13013             :   // ReframeContainingBlock is a NASTY routine, it causes terrible performance problems
   13014             :   // so I want to see when it is happening!  Unfortunately, it is happening way to often because
   13015             :   // so much content on the web causes block-in-inline frame situations and we handle them
   13016             :   // very poorly
   13017           0 :   if (gNoisyContentUpdates) {
   13018             :     printf("nsCSSFrameConstructor::ReframeContainingBlock frame=%p\n",
   13019           0 :            static_cast<void*>(aFrame));
   13020             :   }
   13021             : #endif
   13022             : 
   13023             :   // XXXbz how exactly would we get here while isReflowing anyway?  Should this
   13024             :   // whole test be ifdef DEBUG?
   13025           0 :   if (mPresShell->IsReflowLocked()) {
   13026             :     // don't ReframeContainingBlock, this will result in a crash
   13027             :     // if we remove a tree that's in reflow - see bug 121368 for testcase
   13028           0 :     NS_ERROR("Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a Reflow!!!");
   13029           0 :     return;
   13030             :   }
   13031             : 
   13032             :   // Get the first "normal" ancestor of the target frame.
   13033           0 :   nsIFrame* containingBlock = GetIBContainingBlockFor(aFrame);
   13034           0 :   if (containingBlock) {
   13035             :     // From here we look for the containing block in case the target
   13036             :     // frame is already a block (which can happen when an inline frame
   13037             :     // wraps some of its content in an anonymous block; see
   13038             :     // ConstructInline)
   13039             : 
   13040             :     // NOTE: We used to get the FloatContainingBlock here, but it was often wrong.
   13041             :     // GetIBContainingBlock works much better and provides the correct container in all cases
   13042             :     // so GetFloatContainingBlock(aFrame) has been removed
   13043             : 
   13044             :     // And get the containingBlock's content
   13045           0 :     nsCOMPtr<nsIContent> blockContent = containingBlock->GetContent();
   13046           0 :     if (blockContent) {
   13047             : #ifdef DEBUG
   13048           0 :       if (gNoisyContentUpdates) {
   13049           0 :         printf("  ==> blockContent=%p\n", static_cast<void*>(blockContent));
   13050             :       }
   13051             : #endif
   13052           0 :       return RecreateFramesForContent(blockContent, true, aFlags, aDestroyedFramesFor);
   13053             :     }
   13054             :   }
   13055             : 
   13056             :   // If we get here, we're screwed!
   13057           0 :   return RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
   13058           0 :                                   true, aFlags, nullptr);
   13059             : }
   13060             : 
   13061             : void
   13062           0 : nsCSSFrameConstructor::GenerateChildFrames(nsContainerFrame* aFrame)
   13063             : {
   13064             :   {
   13065           0 :     nsAutoScriptBlocker scriptBlocker;
   13066           0 :     BeginUpdate();
   13067             : 
   13068           0 :     nsFrameItems childItems;
   13069           0 :     TreeMatchContextHolder matchContext(mDocument);
   13070           0 :     nsFrameConstructorState state(mPresShell, matchContext, nullptr, nullptr, nullptr);
   13071             :     // We don't have a parent frame with a pending binding constructor here,
   13072             :     // so no need to worry about ordering of the kids' constructors with it.
   13073             :     // Pass null for the PendingBinding.
   13074           0 :     ProcessChildren(state, aFrame->GetContent(), aFrame->StyleContext(),
   13075             :                     aFrame, false, childItems, false,
   13076           0 :                     nullptr);
   13077             : 
   13078           0 :     aFrame->SetInitialChildList(kPrincipalList, childItems);
   13079             : 
   13080           0 :     EndUpdate();
   13081             :   }
   13082             : 
   13083             : #ifdef ACCESSIBILITY
   13084           0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
   13085           0 :   if (accService) {
   13086           0 :     nsIContent* container = aFrame->GetContent();
   13087           0 :     nsIContent* child = container->GetFirstChild();
   13088           0 :     if (child) {
   13089           0 :       accService->ContentRangeInserted(mPresShell, container, child, nullptr);
   13090             :     }
   13091             :   }
   13092             : #endif
   13093             : 
   13094             :   // call XBL constructors after the frames are created
   13095           0 :   mPresShell->GetDocument()->BindingManager()->ProcessAttachedQueue();
   13096           0 : }
   13097             : 
   13098             : //////////////////////////////////////////////////////////
   13099             : // nsCSSFrameConstructor::FrameConstructionItem methods //
   13100             : //////////////////////////////////////////////////////////
   13101             : bool
   13102           8 : nsCSSFrameConstructor::
   13103             : FrameConstructionItem::IsWhitespace(nsFrameConstructorState& aState) const
   13104             : {
   13105           8 :   NS_PRECONDITION(aState.mCreatingExtraFrames ||
   13106             :                   !mContent->GetPrimaryFrame(), "How did that happen?");
   13107           8 :   if (!mIsText) {
   13108           0 :     return false;
   13109             :   }
   13110           8 :   mContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
   13111           8 :                      NS_REFRAME_IF_WHITESPACE);
   13112           8 :   return mContent->TextIsOnlyWhitespace();
   13113             : }
   13114             : 
   13115             : //////////////////////////////////////////////////////////////
   13116             : // nsCSSFrameConstructor::FrameConstructionItemList methods //
   13117             : //////////////////////////////////////////////////////////////
   13118             : void
   13119           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13120             : AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta)
   13121             : {
   13122           0 :   NS_PRECONDITION(aDelta == 1 || aDelta == -1, "Unexpected delta");
   13123           0 :   mItemCount += aDelta;
   13124           0 :   if (aItem->mIsAllInline) {
   13125           0 :     mInlineCount += aDelta;
   13126             :   }
   13127           0 :   if (aItem->mIsBlock) {
   13128           0 :     mBlockCount += aDelta;
   13129             :   }
   13130           0 :   if (aItem->mIsLineParticipant) {
   13131           0 :     mLineParticipantCount += aDelta;
   13132             :   }
   13133           0 :   mDesiredParentCounts[aItem->DesiredParentType()] += aDelta;
   13134           0 : }
   13135             : 
   13136             : ////////////////////////////////////////////////////////////////////////
   13137             : // nsCSSFrameConstructor::FrameConstructionItemList::Iterator methods //
   13138             : ////////////////////////////////////////////////////////////////////////
   13139             : inline bool
   13140           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13141             : Iterator::SkipItemsWantingParentType(ParentType aParentType)
   13142             : {
   13143           0 :   NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
   13144           0 :   while (item().DesiredParentType() == aParentType) {
   13145           0 :     Next();
   13146           0 :     if (IsDone()) {
   13147           0 :       return true;
   13148             :     }
   13149             :   }
   13150           0 :   return false;
   13151             : }
   13152             : 
   13153             : inline bool
   13154           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13155             : Iterator::SkipItemsNotWantingParentType(ParentType aParentType)
   13156             : {
   13157           0 :   NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
   13158           0 :   while (item().DesiredParentType() != aParentType) {
   13159           0 :     Next();
   13160           0 :     if (IsDone()) {
   13161           0 :       return true;
   13162             :     }
   13163             :   }
   13164           0 :   return false;
   13165             : }
   13166             : 
   13167             : // Note: we implement -webkit-box & -webkit-inline-box using
   13168             : // nsFlexContainerFrame, but we use different rules for what gets wrapped in an
   13169             : // anonymous flex item.
   13170             : bool
   13171           0 : nsCSSFrameConstructor::FrameConstructionItem::
   13172             :   NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
   13173             :                           bool aIsWebkitBox)
   13174             : {
   13175           0 :   if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) {
   13176             :     // This will be an inline non-replaced box.
   13177           0 :     return true;
   13178             :   }
   13179             : 
   13180           0 :   if (aIsWebkitBox) {
   13181           0 :     if (mStyleContext->StyleDisplay()->IsInlineOutsideStyle()) {
   13182             :       // In a -webkit-box, all inline-level content gets wrapped in anon item.
   13183           0 :       return true;
   13184             :     }
   13185           0 :     if (!(mFCData->mBits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
   13186           0 :         aState.GetGeometricParent(mStyleContext->StyleDisplay(), nullptr)) {
   13187             :       // We're abspos or fixedpos, which means we'll spawn a placeholder which
   13188             :       // (because our container is a -webkit-box) we'll need to wrap in an
   13189             :       // anonymous flex item.  So, we just treat _this_ frame as if _it_ needs
   13190             :       // to be wrapped in an anonymous flex item, and then when we spawn the
   13191             :       // placeholder, it'll end up in the right spot.
   13192           0 :       return true;
   13193             :     }
   13194             :   }
   13195             : 
   13196           0 :   return false;
   13197             : }
   13198             : 
   13199             : inline bool
   13200           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13201             : Iterator::SkipItemsThatNeedAnonFlexOrGridItem(
   13202             :   const nsFrameConstructorState& aState,
   13203             :   bool aIsWebkitBox)
   13204             : {
   13205           0 :   NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
   13206           0 :   while (item().NeedsAnonFlexOrGridItem(aState, aIsWebkitBox)) {
   13207           0 :     Next();
   13208           0 :     if (IsDone()) {
   13209           0 :       return true;
   13210             :     }
   13211             :   }
   13212           0 :   return false;
   13213             : }
   13214             : 
   13215             : inline bool
   13216           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13217             : Iterator::SkipItemsThatDontNeedAnonFlexOrGridItem(
   13218             :   const nsFrameConstructorState& aState,
   13219             :   bool aIsWebkitBox)
   13220             : {
   13221           0 :   NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
   13222           0 :   while (!(item().NeedsAnonFlexOrGridItem(aState, aIsWebkitBox))) {
   13223           0 :     Next();
   13224           0 :     if (IsDone()) {
   13225           0 :       return true;
   13226             :     }
   13227             :   }
   13228           0 :   return false;
   13229             : }
   13230             : 
   13231             : inline bool
   13232           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13233             : Iterator::SkipItemsNotWantingRubyParent()
   13234             : {
   13235           0 :   NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
   13236           0 :   while (!IsRubyParentType(item().DesiredParentType())) {
   13237           0 :     Next();
   13238           0 :     if (IsDone()) {
   13239           0 :       return true;
   13240             :     }
   13241             :   }
   13242           0 :   return false;
   13243             : }
   13244             : 
   13245             : inline bool
   13246           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13247             : Iterator::SkipWhitespace(nsFrameConstructorState& aState)
   13248             : {
   13249           0 :   NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
   13250           0 :   NS_PRECONDITION(item().IsWhitespace(aState), "Not pointing to whitespace?");
   13251           0 :   do {
   13252           0 :     Next();
   13253           0 :     if (IsDone()) {
   13254           0 :       return true;
   13255             :     }
   13256           0 :   } while (item().IsWhitespace(aState));
   13257             : 
   13258           0 :   return false;
   13259             : }
   13260             : 
   13261             : void
   13262           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13263             : Iterator::AppendItemToList(FrameConstructionItemList& aTargetList)
   13264             : {
   13265           0 :   NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
   13266           0 :   NS_PRECONDITION(!IsDone(), "should not be done");
   13267             : 
   13268           0 :   FrameConstructionItem* item = mCurrent;
   13269           0 :   Next();
   13270           0 :   item->remove();
   13271           0 :   aTargetList.mItems.insertBack(item);
   13272             : 
   13273           0 :   mList.AdjustCountsForItem(item, -1);
   13274           0 :   aTargetList.AdjustCountsForItem(item, 1);
   13275           0 : }
   13276             : 
   13277             : void
   13278           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13279             : Iterator::AppendItemsToList(const Iterator& aEnd,
   13280             :                             FrameConstructionItemList& aTargetList)
   13281             : {
   13282           0 :   NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
   13283           0 :   NS_PRECONDITION(&mList == &aEnd.mList, "End iterator for some other list?");
   13284             : 
   13285             :   // We can't just move our guts to the other list if it already has
   13286             :   // some information or if we're not moving our entire list.
   13287           0 :   if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty() ||
   13288           0 :       !aTargetList.mUndisplayedItems.IsEmpty()) {
   13289           0 :     do {
   13290           0 :       AppendItemToList(aTargetList);
   13291             :     } while (*this != aEnd);
   13292           0 :     return;
   13293             :   }
   13294             : 
   13295             :   // Move our entire list of items into the empty target list.
   13296           0 :   aTargetList.mItems = Move(mList.mItems);
   13297             : 
   13298             :   // Copy over the various counters
   13299           0 :   aTargetList.mInlineCount = mList.mInlineCount;
   13300           0 :   aTargetList.mBlockCount = mList.mBlockCount;
   13301           0 :   aTargetList.mLineParticipantCount = mList.mLineParticipantCount;
   13302           0 :   aTargetList.mItemCount = mList.mItemCount;
   13303           0 :   memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
   13304           0 :          sizeof(aTargetList.mDesiredParentCounts));
   13305             : 
   13306             :   // Swap out undisplayed item arrays, before we nuke the array on our end
   13307           0 :   aTargetList.mUndisplayedItems.SwapElements(mList.mUndisplayedItems);
   13308             : 
   13309             :   // reset mList
   13310           0 :   mList.~FrameConstructionItemList();
   13311           0 :   new (&mList) FrameConstructionItemList();
   13312             : 
   13313             :   // Point ourselves to aEnd, as advertised
   13314           0 :   SetToEnd();
   13315           0 :   NS_POSTCONDITION(*this == aEnd, "How did that happen?");
   13316             : }
   13317             : 
   13318             : void
   13319           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13320             : Iterator::InsertItem(FrameConstructionItem* aItem)
   13321             : {
   13322           0 :   if (IsDone()) {
   13323           0 :     mList.mItems.insertBack(aItem);
   13324             :   } else {
   13325             :     // Just insert the item before us.  There's no magic here.
   13326           0 :     mCurrent->setPrevious(aItem);
   13327             :   }
   13328           0 :   mList.AdjustCountsForItem(aItem, 1);
   13329             : 
   13330           0 :   NS_POSTCONDITION(aItem->getNext() == mCurrent, "How did that happen?");
   13331           0 : }
   13332             : 
   13333             : void
   13334           0 : nsCSSFrameConstructor::FrameConstructionItemList::
   13335             : Iterator::DeleteItemsTo(const Iterator& aEnd)
   13336             : {
   13337           0 :   NS_PRECONDITION(&mList == &aEnd.mList, "End iterator for some other list?");
   13338           0 :   NS_PRECONDITION(*this != aEnd, "Shouldn't be at aEnd yet");
   13339             : 
   13340           0 :   do {
   13341           0 :     NS_ASSERTION(!IsDone(), "Ran off end of list?");
   13342           0 :     FrameConstructionItem* item = mCurrent;
   13343           0 :     Next();
   13344           0 :     item->remove();
   13345           0 :     mList.AdjustCountsForItem(item, -1);
   13346           0 :     delete item;
   13347             :   } while (*this != aEnd);
   13348           0 : }
   13349             : 
   13350             : void
   13351           0 : nsCSSFrameConstructor::QuotesDirty()
   13352             : {
   13353           0 :   NS_PRECONDITION(mUpdateCount != 0, "Instant quote updates are bad news");
   13354           0 :   mQuotesDirty = true;
   13355           0 :   mPresShell->SetNeedLayoutFlush();
   13356           0 : }
   13357             : 
   13358             : void
   13359           0 : nsCSSFrameConstructor::CountersDirty()
   13360             : {
   13361           0 :   NS_PRECONDITION(mUpdateCount != 0, "Instant counter updates are bad news");
   13362           0 :   mCountersDirty = true;
   13363           0 :   mPresShell->SetNeedLayoutFlush();
   13364           0 : }

Generated by: LCOV version 1.13