tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsCSSFrameConstructor.h (96137B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /*
      8 * construction of a frame tree that is nearly isomorphic to the content
      9 * tree and updating of that tree in response to dynamic changes
     10 */
     11 
     12 #ifndef nsCSSFrameConstructor_h___
     13 #define nsCSSFrameConstructor_h___
     14 
     15 #include "mozilla/ArenaAllocator.h"
     16 #include "mozilla/Attributes.h"
     17 #include "mozilla/ContainStyleScopeManager.h"
     18 #include "mozilla/FunctionRef.h"
     19 #include "mozilla/LinkedList.h"
     20 #include "mozilla/ScrollStyles.h"
     21 #include "mozilla/UniquePtr.h"
     22 #include "nsCOMPtr.h"
     23 #include "nsFrameManager.h"
     24 #include "nsIAnonymousContentCreator.h"
     25 #include "nsIFrame.h"
     26 #include "nsILayoutHistoryState.h"
     27 
     28 struct nsStyleDisplay;
     29 struct nsGenConInitializer;
     30 
     31 class nsBlockFrame;
     32 class nsContainerFrame;
     33 class nsCanvasFrame;
     34 class nsCSSAnonBoxPseudoStaticAtom;
     35 class nsFirstLetterFrame;
     36 class nsFirstLineFrame;
     37 class nsFrameConstructorState;
     38 class nsPageContentFrame;
     39 class nsPageSequenceFrame;
     40 
     41 namespace mozilla {
     42 
     43 class ComputedStyle;
     44 class PresShell;
     45 class PrintedSheetFrame;
     46 class RestyleManager;
     47 class ViewportFrame;
     48 
     49 namespace dom {
     50 
     51 class CharacterData;
     52 class Text;
     53 class FlattenedChildIterator;
     54 
     55 }  // namespace dom
     56 }  // namespace mozilla
     57 
     58 class nsCSSFrameConstructor final : public nsFrameManager {
     59 public:
     60  using ComputedStyle = mozilla::ComputedStyle;
     61  using PseudoStyleType = mozilla::PseudoStyleType;
     62  using PresShell = mozilla::PresShell;
     63  using Element = mozilla::dom::Element;
     64  using Text = mozilla::dom::Text;
     65 
     66  // FIXME(emilio): Is this really needed?
     67  friend class mozilla::RestyleManager;
     68 
     69  nsCSSFrameConstructor(mozilla::dom::Document* aDocument,
     70                        PresShell* aPresShell);
     71  ~nsCSSFrameConstructor() { MOZ_ASSERT(mFCItemsInUse == 0); }
     72 
     73  static void GetAlternateTextFor(const Element&, nsAString& aAltText);
     74 
     75 private:
     76  nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) = delete;
     77  nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) = delete;
     78 
     79 public:
     80  /**
     81   * Whether insertion should be done synchronously or asynchronously.
     82   *
     83   * Generally, insertion is synchronous if we're entering frame construction
     84   * from restyle processing, and async if we're removing stuff, or need to
     85   * reconstruct some ancestor.
     86   *
     87   * Note that constructing async from frame construction will post a restyle
     88   * event, but won't need another whole refresh driver tick to go in. Instead
     89   * change hint processing will keep going as long as there are changes in the
     90   * queue.
     91   */
     92  enum class InsertionKind {
     93    Sync,
     94    Async,
     95  };
     96 
     97  mozilla::RestyleManager* RestyleManager() const;
     98 
     99  mozilla::ViewportFrame* ConstructRootFrame();
    100 
    101 private:
    102  // aChild is the child being inserted for inserts, and the first
    103  // child being appended for appends. All the nodes in the range are
    104  // guaranteed to have the same flat tree parent.
    105  void ConstructLazily(nsIContent* aStartChild, nsIContent* aEndChild);
    106 
    107 #ifdef DEBUG
    108  void CheckBitsForLazyFrameConstruction(nsIContent* aParent);
    109 #else
    110  void CheckBitsForLazyFrameConstruction(nsIContent*) {}
    111 #endif
    112 
    113  // Issues a single ContentInserted for each child in the range
    114  // [aStartChild, aEndChild).
    115  void IssueSingleInsertNofications(nsIContent* aStartChild,
    116                                    nsIContent* aEndChild, InsertionKind);
    117 
    118  /**
    119   * Data that represents an insertion point for some child content.
    120   */
    121  struct InsertionPoint {
    122    InsertionPoint() : mParentFrame(nullptr), mContainer(nullptr) {}
    123 
    124    InsertionPoint(nsContainerFrame* aParentFrame, nsIContent* aContainer)
    125        : mParentFrame(aParentFrame), mContainer(aContainer) {}
    126 
    127    /**
    128     * The parent frame to use if the inserted children needs to create
    129     * frame(s).  May be null, which signals that  we shouldn't try to
    130     * create frames for the inserted children; either because there are
    131     * no parent frame or because there are multiple insertion points and
    132     * we will call IssueSingleInsertNofications for each child instead.
    133     * mContainer should not be used when mParentFrame is null.
    134     */
    135    nsContainerFrame* mParentFrame;
    136    /**
    137     * The flattened tree parent for the inserted children.
    138     * It's undefined if mParentFrame is null.
    139     */
    140    nsIContent* mContainer;
    141  };
    142 
    143  /**
    144   * Checks if the children in the range [aStartChild, aEndChild) can be
    145   * inserted/appended to one insertion point together.
    146   *
    147   * If so, returns that insertion point. If not, returns with
    148   * InsertionPoint.mFrame == nullptr and issues single ContentInserted calls
    149   * for each child.
    150   *
    151   * aEndChild = nullptr indicates that we are dealing with an append.
    152   */
    153  InsertionPoint GetRangeInsertionPoint(nsIContent* aStartChild,
    154                                        nsIContent* aEndChild, InsertionKind);
    155 
    156  // Returns true if parent was recreated due to frameset child, false
    157  // otherwise.
    158  bool MaybeRecreateForFrameset(nsIFrame* aParentFrame, nsIContent* aStartChild,
    159                                nsIContent* aEndChild);
    160 
    161  /**
    162   * For each child in the aStartChild/aEndChild range, calls
    163   * NoteDirtyDescendantsForServo on their flattened tree parents.  This is
    164   * used when content is inserted into the document and we decide that
    165   * we can do lazy frame construction.  It handles children being rebound to
    166   * different insertion points by calling NoteDirtyDescendantsForServo on each
    167   * child's flattened tree parent.  Only used when we are styled by Servo.
    168   */
    169  void LazilyStyleNewChildRange(nsIContent* aStartChild, nsIContent* aEndChild);
    170 
    171  /**
    172   * For each child in the aStartChild/aEndChild range, calls StyleNewChildren
    173   * on their flattened tree parents.  This is used when content is inserted
    174   * into the document and we decide that we cannot do lazy frame construction.
    175   * It handles children being rebound to different insertion points by calling
    176   * StyleNewChildren on each child's flattened tree parent.  Only used when we
    177   * are styled by Servo.
    178   */
    179  void StyleNewChildRange(nsIContent* aStartChild, nsIContent* aEndChild);
    180 
    181 public:
    182  /**
    183   * Lazy frame construction is controlled by the InsertionKind parameter of
    184   * nsCSSFrameConstructor::ContentAppended/Inserted. It is true for all
    185   * inserts/appends as passed from the presshell, except for the insert of the
    186   * root element, which is always non-lazy.
    187   *
    188   * If we construct lazily, then we add NODE_NEEDS_FRAME bits to the newly
    189   * inserted/appended nodes and adds NODE_DESCENDANTS_NEED_FRAMES bits to the
    190   * container and up along the parent chain until it hits the root or another
    191   * node with that bit set. Then it posts a restyle event to ensure that a
    192   * flush happens to construct those frames.
    193   *
    194   * When the flush happens the RestyleManager walks the dirty nodes during
    195   * ProcessPostTraversal, and ends up calling Content{Appended,Inserted} with
    196   * InsertionKind::Sync in ProcessRestyledFrames.
    197   *
    198   * If a node is removed from the document then we don't bother unsetting any
    199   * of the lazy bits that might be set on it, its descendants, or any of its
    200   * ancestor nodes because that is a slow operation, the work might be wasted
    201   * if another node gets inserted in its place, and we can clear the bits
    202   * quicker by processing the content tree from top down the next time we
    203   * reconstruct frames. (We do clear the bits when BindToTree is called on any
    204   * nsIContent; so any nodes added to the document will not have any lazy bits
    205   * set.)
    206   */
    207 
    208  // If the insertion kind is Async then frame construction of the new children
    209  // can be done lazily.
    210  void ContentAppended(nsIContent* aFirstNewContent, InsertionKind);
    211 
    212  // If the insertion kind is Async then frame construction of the new child
    213  // can be done lazily.
    214  void ContentInserted(nsIContent* aChild, InsertionKind);
    215 
    216  // Like ContentInserted but handles inserting the children in the range
    217  // [aStartChild, aEndChild).  aStartChild must be non-null.  aEndChild may be
    218  // null to indicate the range includes all kids after aStartChild.
    219  //
    220  // If aInsertionKind is Async then frame construction of the new children can
    221  // be done lazily. It is only allowed to be Async when inserting a single
    222  // node.
    223  void ContentRangeInserted(nsIContent* aStartChild, nsIContent* aEndChild,
    224                            InsertionKind aInsertionKind);
    225 
    226  // The kind of removal we're dealing with.
    227  enum class RemovalKind : uint8_t {
    228    // The DOM node is getting removed from the document.
    229    Dom,
    230    // We're about to remove this frame, but we will insert it later.
    231    ForReconstruction,
    232    // We're about to remove this frame due to a style change but we know we
    233    // are not going to create a frame later.
    234    ForDisplayNoneChange,
    235  };
    236 
    237  /**
    238   * Recreate or destroy frames for aChild.
    239   *
    240   * Regardless of the removal kind, this method will in some cases try to
    241   * reconstruct frames on some ancestor of aChild.
    242   *
    243   * The return value indicates whether this "reconstruct an ancestor" action
    244   * took place.  If true is returned, that means that the frame subtree rooted
    245   * at some ancestor of aChild's frame was destroyed and will be reconstructed
    246   * async.
    247   */
    248  bool ContentWillBeRemoved(nsIContent* aChild, RemovalKind);
    249 
    250  void CharacterDataChanged(nsIContent* aContent,
    251                            const CharacterDataChangeInfo& aInfo);
    252 
    253  // If aContent is a text node that has been optimized away due to being
    254  // whitespace next to a block boundary (or for some other reason), ensure that
    255  // a frame for it is created the next time frames are flushed, if it can
    256  // possibly have a frame at all.
    257  //
    258  // Returns whether there are chances for the frame to be unsuppressed.
    259  bool EnsureFrameForTextNodeIsCreatedAfterFlush(
    260      mozilla::dom::CharacterData* aContent);
    261 
    262  // Should be called when a frame is going to be destroyed and
    263  // WillDestroyFrameTree hasn't been called yet.
    264  void NotifyDestroyingFrame(nsIFrame* aFrame);
    265 
    266  void RecalcQuotesAndCounters();
    267 
    268  // Called when any counter style is changed.
    269  void NotifyCounterStylesAreDirty();
    270 
    271  // Gets called when the presshell is destroying itself and also
    272  // when we tear down our frame tree to reconstruct it
    273  void WillDestroyFrameTree();
    274 
    275  /**
    276   * Destroy the frames for aContent.  Note that this may destroy frames
    277   * for an ancestor instead.
    278   *
    279   * Returns whether a reconstruct was posted for any ancestor.
    280   */
    281  bool DestroyFramesFor(nsIContent* aContent);
    282 
    283  // Request to create a continuing frame.  This method never returns null.
    284  nsIFrame* CreateContinuingFrame(nsIFrame* aFrame,
    285                                  nsContainerFrame* aParentFrame,
    286                                  bool aIsFluid = true);
    287 
    288  /**
    289   * Sets the page name when a page break is being generated due to a change
    290   * in page name.
    291   *
    292   * Should only be used during paginated reflow, to signal what page value
    293   * the next page content frame should have.
    294   *
    295   * It is an error to set this if a new page name has already been set, either
    296   * through SetNextPageContentFramePageName or
    297   * MaybeSetNextPageContentFramePageName.
    298   */
    299  void SetNextPageContentFramePageName(const nsAtom* aPageName) {
    300    MOZ_ASSERT(aPageName, "New page name should never be null");
    301    MOZ_ASSERT(!mNextPageContentFramePageName,
    302               "PageContentFrame page name was already set");
    303    mNextPageContentFramePageName = aPageName;
    304  }
    305 
    306  /**
    307   * If a new page name has not been set for the next page, sets the value
    308   * using the given frame.
    309   *
    310   * |aFrame| should be a frame to be placed on the new page.
    311   *
    312   * This function handles the work of resolving an atom for the frame, and
    313   * avoids doing this extra work when not necessary.
    314   *
    315   * This is used during block reflow when a page break has occurred but it was
    316   * not caused by a change in page name. It should only be used during
    317   * paginated reflow.
    318   */
    319  void MaybeSetNextPageContentFramePageName(const nsIFrame* aFrame);
    320 
    321  // Copy over fixed frames from aParentFrame's prev-in-flow
    322  nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
    323 
    324  /**
    325   * Get the insertion point for aChild.
    326   */
    327  InsertionPoint GetInsertionPoint(nsIContent* aChild);
    328 
    329  /**
    330   * Return the insertion frame of the primary frame of aContent, or its nearest
    331   * ancestor that isn't display:contents.
    332   */
    333  nsContainerFrame* GetContentInsertionFrameFor(nsIContent* aContent);
    334 
    335  // This returns the outermost frame for the root element.
    336  nsContainerFrame* GetRootElementFrame() { return mRootElementFrame; }
    337  // This returns the frame for the root element that does not
    338  // have a pseudo-element style
    339  nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
    340  nsPageSequenceFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
    341  // Returns the outermost canvas frame. There's usually one per document, but
    342  // if but if we're in printing / paginated mode we might have multiple:  one
    343  // per page plus the background one.
    344  nsCanvasFrame* GetCanvasFrame() { return mCanvasFrame; }
    345  // Get the frame that is the parent of the root element's frame.
    346  nsCanvasFrame* GetDocElementContainingBlock() {
    347    return mDocElementContainingBlock;
    348  }
    349 
    350  void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
    351 
    352 #if defined(ACCESSIBILITY) || defined(MOZ_LAYOUT_DEBUGGER)
    353  // Exposed only for nsLayoutUtils::GetMarkerSpokenText and
    354  // nsLayoutDebuggingTools to use.
    355  mozilla::ContainStyleScopeManager& GetContainStyleScopeManager() {
    356    return mContainStyleScopeManager;
    357  }
    358 #endif
    359 
    360 private:
    361  struct FrameConstructionItem;
    362  class FrameConstructionItemList;
    363 
    364  mozilla::PrintedSheetFrame* ConstructPrintedSheetFrame(
    365      PresShell* aPresShell, nsContainerFrame* aParentFrame,
    366      nsIFrame* aPrevSheetFrame);
    367 
    368  nsContainerFrame* ConstructPageFrame(PresShell* aPresShell,
    369                                       nsContainerFrame* aParentFrame,
    370                                       nsIFrame* aPrevPageFrame,
    371                                       nsCanvasFrame*& aCanvasFrame);
    372 
    373  void InitAndRestoreFrame(const nsFrameConstructorState& aState,
    374                           nsIContent* aContent, nsContainerFrame* aParentFrame,
    375                           nsIFrame* aNewFrame, bool aAllowCounters = true);
    376 
    377  already_AddRefed<ComputedStyle> ResolveComputedStyle(nsIContent* aContent);
    378 
    379  enum class ItemFlag : uint8_t {
    380    // Allow page-break before and after items to be created if the
    381    // style asks for them.
    382    AllowPageBreak,
    383    IsGeneratedContent,
    384    IsWithinSVGText,
    385    // The item allows items to be created for SVG <textPath> children.
    386    AllowTextPathChild,
    387    // The item is content created by an nsIAnonymousContentCreator frame.
    388    IsAnonymousContentCreatorContent,
    389    // The item will be the rendered legend of a <fieldset>.
    390    IsForRenderedLegend,
    391    // This will be an outside ::marker.
    392    IsForOutsideMarker,
    393  };
    394 
    395  using ItemFlags = mozilla::EnumSet<ItemFlag>;
    396 
    397  // Add the frame construction items for the given aContent and aParentFrame
    398  // to the list.  This might add more than one item in some rare cases.
    399  // If aSuppressWhiteSpaceOptimizations is true, optimizations that
    400  // may suppress the construction of white-space-only text frames
    401  // must be skipped for these items and items around them.
    402  void AddFrameConstructionItems(nsFrameConstructorState& aState,
    403                                 nsIContent* aContent,
    404                                 bool aSuppressWhiteSpaceOptimizations,
    405                                 const ComputedStyle& aParentStyle,
    406                                 const InsertionPoint& aInsertion,
    407                                 FrameConstructionItemList& aItems,
    408                                 ItemFlags = {});
    409 
    410  // Helper method for AddFrameConstructionItems etc.
    411  // Unsets the need-frame/restyle bits on aContent.
    412  // return true iff we should attempt to create frames for aContent.
    413  bool ShouldCreateItemsForChild(nsFrameConstructorState& aState,
    414                                 nsIContent* aContent,
    415                                 nsContainerFrame* aParentFrame);
    416 
    417  // Construct the frames for the document element.  This can return null if the
    418  // document element is display:none, or if it's an SVG element that's not
    419  // <svg>, etc.
    420  nsIFrame* ConstructDocElementFrame(Element* aDocElement);
    421 
    422  // Set up our mDocElementContainingBlock correctly for the given root
    423  // content.
    424  void SetUpDocElementContainingBlock(nsIContent* aDocElement);
    425 
    426  /**
    427   * CreateAttributeContent creates a single content/frame combination for an
    428   * |attr(foo)| generated content.
    429   *
    430   * @param aParentContent the parent content for the generated content (that
    431   * is, the originating element).
    432   * @param aParentFrame the parent frame for the generated frame
    433   * @param aAttrNamespace the namespace of the attribute in question
    434   * @param aAttrName the localname of the attribute
    435   * @param aComputedStyle the style to use
    436   * @param aGeneratedContent the array of generated content to append the
    437   *                          created content to.
    438   * @param [out] aNewContent the content node we create
    439   * @param [out] aNewFrame the new frame we create
    440   */
    441  void CreateAttributeContent(const Element& aParentContent,
    442                              nsIFrame* aParentFrame, int32_t aAttrNamespace,
    443                              nsAtom* aAttrName, ComputedStyle* aComputedStyle,
    444                              nsCOMArray<nsIContent>& aGeneratedContent,
    445                              nsIContent** aNewContent, nsIFrame** aNewFrame);
    446 
    447  /**
    448   * Create a text node containing the given string. If aText is non-null
    449   * then we also set aText to the returned node.
    450   */
    451  already_AddRefed<nsIContent> CreateGenConTextNode(
    452      nsFrameConstructorState& aState, const nsAString& aString,
    453      mozilla::UniquePtr<nsGenConInitializer> aInitializer);
    454 
    455  /**
    456   * Create a content node for the given generated content style.
    457   * The caller takes care of making it SetIsNativeAnonymousRoot, binding it
    458   * to the document, and creating frames for it.
    459   * @param aOriginatingElement is the node that has the before/after style.
    460   * @param aComputedStyle is the 'before' or 'after' pseudo-element style.
    461   * @param aContentIndex is the index of the content item to create.
    462   * @param aAddChild callback to be called for each generated content child.
    463   */
    464  void CreateGeneratedContent(
    465      nsFrameConstructorState& aState, Element& aOriginatingElement,
    466      ComputedStyle& aPseudoStyle, const mozilla::StyleContentItem& aItem,
    467      size_t aContentIndex,
    468      const mozilla::FunctionRef<void(nsIContent*)> aAddChild);
    469 
    470  /**
    471   * Create child content nodes for a ::marker from its 'list-style-*' values.
    472   */
    473  void CreateGeneratedContentFromListStyle(
    474      nsFrameConstructorState& aState, Element& aOriginatingElement,
    475      const ComputedStyle& aPseudoStyle,
    476      const mozilla::FunctionRef<void(nsIContent*)> aAddChild);
    477  /**
    478   * Create child content nodes for a ::marker from its 'list-style-type'.
    479   */
    480  void CreateGeneratedContentFromListStyleType(
    481      nsFrameConstructorState& aState, Element& aOriginatingElement,
    482      const ComputedStyle& aPseudoStyle,
    483      const mozilla::FunctionRef<void(nsIContent*)> aAddChild);
    484 
    485  // aParentFrame may be null; this method doesn't use it directly in any case.
    486  void CreateGeneratedContentItem(nsFrameConstructorState& aState,
    487                                  nsContainerFrame* aParentFrame,
    488                                  Element& aOriginatingElement, ComputedStyle&,
    489                                  PseudoStyleType aPseudoElement,
    490                                  FrameConstructionItemList& aItems,
    491                                  ItemFlags aExtraFlags = {});
    492 
    493  // This method is called by ContentAppended() and ContentRangeInserted() when
    494  // appending flowed frames to a parent's principal child list. It handles the
    495  // case where the parent is the trailing inline of an ib-split or is the last
    496  // continuation of a ::-moz-column-content in an nsColumnSetFrame.
    497  //
    498  // This method can change aFrameList: it can chop off the beginning and put it
    499  // in aParentFrame while either putting the remainder into an ib-split sibling
    500  // of aParentFrame or creating aParentFrame's column-span siblings for the
    501  // remainder.
    502  //
    503  // aPrevSibling must be the frame after which aFrameList is to be placed on
    504  // aParentFrame's principal child list. It may be null if aFrameList is being
    505  // added at the beginning of the child list.
    506  void AppendFramesToParent(nsFrameConstructorState& aState,
    507                            nsContainerFrame* aParentFrame,
    508                            nsFrameList& aFrameList, nsIFrame* aPrevSibling,
    509                            bool aIsRecursiveCall = false);
    510 
    511  // BEGIN TABLE SECTION
    512  /**
    513   * Construct a table wrapper frame. This is the FrameConstructionData
    514   * callback used for the job.
    515   */
    516  nsIFrame* ConstructTable(nsFrameConstructorState& aState,
    517                           FrameConstructionItem& aItem,
    518                           nsContainerFrame* aParentFrame,
    519                           const nsStyleDisplay* aDisplay,
    520                           nsFrameList& aFrameList);
    521 
    522  /**
    523   * FrameConstructionData callback for constructing table rows and row groups.
    524   */
    525  nsIFrame* ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
    526                                        FrameConstructionItem& aItem,
    527                                        nsContainerFrame* aParentFrame,
    528                                        const nsStyleDisplay* aStyleDisplay,
    529                                        nsFrameList& aFrameList);
    530 
    531  /**
    532   * FrameConstructionData callback used for constructing table columns.
    533   */
    534  nsIFrame* ConstructTableCol(nsFrameConstructorState& aState,
    535                              FrameConstructionItem& aItem,
    536                              nsContainerFrame* aParentFrame,
    537                              const nsStyleDisplay* aStyleDisplay,
    538                              nsFrameList& aFrameList);
    539 
    540  /**
    541   * FrameConstructionData callback used for constructing table cells.
    542   */
    543  nsIFrame* ConstructTableCell(nsFrameConstructorState& aState,
    544                               FrameConstructionItem& aItem,
    545                               nsContainerFrame* aParentFrame,
    546                               const nsStyleDisplay* aStyleDisplay,
    547                               nsFrameList& aFrameList);
    548 
    549 private:
    550  /* An enum of possible parent types for anonymous table or ruby object
    551     construction */
    552  enum ParentType {
    553    eTypeBlock = 0, /* This includes all non-table-related frames */
    554    eTypeRow,
    555    eTypeRowGroup,
    556    eTypeColGroup,
    557    eTypeTable,
    558    eTypeRuby,
    559    eTypeRubyBase,
    560    eTypeRubyBaseContainer,
    561    eTypeRubyText,
    562    eTypeRubyTextContainer,
    563    eParentTypeCount
    564  };
    565 
    566  /* 4 bits is enough to handle our ParentType values */
    567 #define FCDATA_PARENT_TYPE_OFFSET 28
    568  /* Macro to get the desired parent type out of an mBits member of
    569     FrameConstructionData */
    570 #define FCDATA_DESIRED_PARENT_TYPE(_bits) \
    571  ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET)
    572  /* Macro to create FrameConstructionData bits out of a desired parent type */
    573 #define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type) \
    574  (((uint32_t)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
    575 
    576  /* Get the parent type that aParentFrame has. */
    577  static ParentType GetParentType(nsIFrame* aParentFrame) {
    578    return GetParentType(aParentFrame->Type());
    579  }
    580 
    581  /* Get the parent type for the given LayoutFrameType */
    582  static ParentType GetParentType(mozilla::LayoutFrameType aFrameType);
    583 
    584  static bool IsRubyParentType(ParentType aParentType) {
    585    return (aParentType == eTypeRuby || aParentType == eTypeRubyBase ||
    586            aParentType == eTypeRubyBaseContainer ||
    587            aParentType == eTypeRubyText ||
    588            aParentType == eTypeRubyTextContainer);
    589  }
    590 
    591  static bool IsTableParentType(ParentType aParentType) {
    592    return (aParentType == eTypeTable || aParentType == eTypeRow ||
    593            aParentType == eTypeRowGroup || aParentType == eTypeColGroup);
    594  }
    595 
    596  /* A constructor function that just creates an nsIFrame object.  The caller
    597     is responsible for initializing the object, adding it to frame lists,
    598     constructing frames for the children, etc.
    599 
    600     @param PresShell the presshell whose arena should be used to allocate
    601                      the frame.
    602     @param ComputedStyle the style to use for the frame. */
    603  using FrameCreationFunc = nsIFrame* (*)(PresShell*, ComputedStyle*);
    604  using ContainerFrameCreationFunc = nsContainerFrame* (*)(PresShell*,
    605                                                           ComputedStyle*);
    606  using BlockFrameCreationFunc = nsBlockFrame* (*)(PresShell*, ComputedStyle*);
    607 
    608  /* A function that can be used to get a FrameConstructionData.  Such
    609     a function is allowed to return null.
    610 
    611     @param nsIContent the node for which the frame is being constructed.
    612     @param ComputedStyle the style to be used for the frame.
    613  */
    614  struct FrameConstructionData;
    615  using FrameConstructionDataGetter =
    616      const FrameConstructionData* (*)(const Element&, ComputedStyle&);
    617 
    618  /* A constructor function that's used for complicated construction tasks.
    619     This is expected to create the new frame, initialize it, add whatever
    620     needs to be added to aFrameList (XXXbz is that really necessary?  Could
    621     caller add?  Might there be cases when the returned frame or its
    622     placeholder is not the thing that ends up in aFrameList?  If not, would
    623     it be safe to do the add into the frame construction state after
    624     processing kids?  Look into this as a followup!), process children as
    625     needed, etc.  It is NOT expected to deal with setting the frame on the
    626     content.
    627 
    628     @param aState the frame construction state to use.
    629     @param aItem the frame construction item to use
    630     @param aParentFrame the frame to set as the parent of the
    631                         newly-constructed frame.
    632     @param aStyleDisplay the display struct from aItem's mComputedStyle
    633     @param aFrameList the frame list to add the new frame (or its
    634                        placeholder) to.
    635     @return the frame that was constructed.  This frame is what the caller
    636             will set as the frame on the content.  Guaranteed non-null.
    637  */
    638  using FrameFullConstructor =
    639      nsIFrame* (nsCSSFrameConstructor::*)(nsFrameConstructorState & aState,
    640                                           FrameConstructionItem& aItem,
    641                                           nsContainerFrame* aParentFrame,
    642                                           const nsStyleDisplay* aStyleDisplay,
    643                                           nsFrameList& aFrameList);
    644 
    645  /* Bits that modify the way a FrameConstructionData is handled */
    646 
    647  /* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not
    648     be set as the primary frame on the content node.  This should only be used
    649     in very rare cases when we create more than one frame for a given content
    650     node. */
    651 #define FCDATA_SKIP_FRAMESET 0x1
    652  /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
    653     FrameConstructionData is a getter function that can be used to get the
    654     actual FrameConstructionData to use. */
    655 #define FCDATA_FUNC_IS_DATA_GETTER 0x2
    656  /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData
    657     has an mFullConstructor.  In this case, there is no relevant mData or
    658     mFunc */
    659 #define FCDATA_FUNC_IS_FULL_CTOR 0x4
    660  /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to
    661     float or be absolutely positioned.  This can also be used with
    662     FCDATA_FUNC_IS_FULL_CTOR to indicate what the full-constructor
    663     function will do. */
    664 #define FCDATA_DISALLOW_OUT_OF_FLOW 0x8
    665  /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a
    666     null absolute containing block before processing children for this
    667     frame.  If this is not set, the frame will be pushed as the
    668     absolute containing block as needed, based on its style */
    669 #define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10
    670  /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame
    671     will be wrapped in blocks.  This is only usable for MathML at the
    672     moment. */
    673 #define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20
    674  /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the
    675     content.  If this bit is set, nothing else in the struct needs to be
    676     set. */
    677 #define FCDATA_SUPPRESS_FRAME 0x40
    678  /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
    679     a scrollframe if its overflow type so requires. */
    680 #define FCDATA_MAY_NEED_SCROLLFRAME 0x80
    681  /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame.  These need
    682     some really weird special handling.  */
    683 #define FCDATA_IS_POPUP 0x100
    684  /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
    685     absolute containing block, no matter what its style says. */
    686 #define FCDATA_SKIP_ABSPOS_PUSH 0x200
    687  /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated
    688     content when processing kids of this frame.  This should not be used with
    689     FCDATA_FUNC_IS_FULL_CTOR */
    690 #define FCDATA_DISALLOW_GENERATED_CONTENT 0x400
    691  /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of
    692     table-related thing and we should not attempt to fetch a table-cell parent
    693     for it if it's inside another table-related frame. */
    694 #define FCDATA_IS_TABLE_PART 0x800
    695  /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS
    696     inline box. */
    697 #define FCDATA_IS_INLINE 0x1000
    698  /* If FCDATA_IS_LINE_PARTICIPANT is set, the frame is something that will
    699     return true for IsLineParticipant() */
    700 #define FCDATA_IS_LINE_PARTICIPANT 0x2000
    701  /* If FCDATA_IS_LINE_BREAK is set, the frame is something that will
    702     induce a line break boundary before and after itself. */
    703 #define FCDATA_IS_LINE_BREAK 0x4000
    704  /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing
    705     children of a block (i.e. allow ::first-letter/line).
    706     This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */
    707 #define FCDATA_ALLOW_BLOCK_STYLES 0x8000
    708  /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant
    709     FrameConstructionItem instead of trying to process the content's children.
    710     This can be used with or without FCDATA_FUNC_IS_FULL_CTOR.
    711     The child items might still need table pseudo processing. */
    712 #define FCDATA_USE_CHILD_ITEMS 0x10000
    713  // 0x200000 is free
    714  /* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a
    715     block formatting context wrapper around the kids of this frame
    716     using the FrameConstructionData's mPseudoAtom for its anonymous
    717     box type. */
    718 #define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000
    719  /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of
    720     an SVG text frame. */
    721 #define FCDATA_IS_SVG_TEXT 0x80000
    722  /**
    723   * Whether the kids of this FrameConstructionData should be flagged as having
    724   * a wrapper anon box parent.  This should only be set if
    725   * FCDATA_USE_CHILD_ITEMS is set.
    726   */
    727 #define FCDATA_IS_WRAPPER_ANON_BOX 0x400000
    728 
    729  /* Structure representing information about how a frame should be
    730     constructed.  */
    731  struct FrameConstructionData {
    732    // We have exactly one of three types of functions, so use a union for
    733    // better cache locality.
    734    union Func {
    735      FrameCreationFunc mCreationFunc;
    736      FrameConstructionDataGetter mDataGetter;
    737      FrameFullConstructor mFullConstructor;
    738 
    739      explicit constexpr Func(FrameCreationFunc aFunc) : mCreationFunc(aFunc) {}
    740      explicit constexpr Func(FrameConstructionDataGetter aDataGetter)
    741          : mDataGetter(aDataGetter) {}
    742      explicit constexpr Func(FrameFullConstructor aCtor)
    743          : mFullConstructor(aCtor) {}
    744    } mFunc;
    745    // Flag bits that can modify the way the construction happens
    746    const uint32_t mBits = 0;
    747    // For cases when FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, the
    748    // anonymous box type to use for that wrapper.
    749    PseudoStyleType const mAnonBoxPseudo = PseudoStyleType::NotPseudo;
    750 
    751    constexpr FrameConstructionData() : FrameConstructionData(nullptr) {}
    752 
    753    MOZ_IMPLICIT constexpr FrameConstructionData(std::nullptr_t,
    754                                                 uint32_t aBits = 0)
    755        : mFunc(static_cast<FrameCreationFunc>(nullptr)), mBits(aBits) {}
    756 
    757    MOZ_IMPLICIT constexpr FrameConstructionData(
    758        FrameCreationFunc aCreationFunc, uint32_t aBits = 0)
    759        : mFunc(aCreationFunc), mBits(aBits) {}
    760    constexpr FrameConstructionData(FrameCreationFunc aCreationFunc,
    761                                    uint32_t aBits,
    762                                    PseudoStyleType aAnonBoxPseudo)
    763        : mFunc(aCreationFunc),
    764          mBits(aBits | FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS),
    765          mAnonBoxPseudo(aAnonBoxPseudo) {}
    766    MOZ_IMPLICIT constexpr FrameConstructionData(
    767        FrameConstructionDataGetter aDataGetter, uint32_t aBits = 0)
    768        : mFunc(aDataGetter),
    769          mBits(aBits | FCDATA_FUNC_IS_DATA_GETTER),
    770          mAnonBoxPseudo(PseudoStyleType::NotPseudo) {}
    771    MOZ_IMPLICIT constexpr FrameConstructionData(FrameFullConstructor aCtor,
    772                                                 uint32_t aBits = 0)
    773        : mFunc(aCtor),
    774          mBits(aBits | FCDATA_FUNC_IS_FULL_CTOR),
    775          mAnonBoxPseudo(PseudoStyleType::NotPseudo) {}
    776  };
    777 
    778  /* Structure representing a mapping of an atom to a FrameConstructionData.
    779     This can be used with non-static atoms, assuming that the nsAtom* is
    780     stored somewhere that this struct can point to (that is, a static
    781     nsAtom*) and that it's allocated before the struct is ever used. */
    782  struct FrameConstructionDataByTag {
    783    const nsStaticAtom* const mTag;
    784    const FrameConstructionData mData;
    785  };
    786 
    787  /* Structure representing a mapping of an integer to a
    788     FrameConstructionData. There are no magic integer values here. */
    789  struct FrameConstructionDataByInt {
    790    /* Could be used for display or whatever else */
    791    const int32_t mInt;
    792    const FrameConstructionData mData;
    793  };
    794 
    795  struct FrameConstructionDataByDisplay {
    796 #ifdef DEBUG
    797    const mozilla::StyleDisplay mDisplay;
    798 #endif
    799    const FrameConstructionData mData;
    800  };
    801 
    802  /* Structure that has a FrameConstructionData and style pseudo-type
    803     for a table pseudo-frame */
    804  struct PseudoParentData {
    805    const FrameConstructionData mFCData;
    806    mozilla::PseudoStyleType const mPseudoType;
    807  };
    808  /* Array of such structures that we use to properly construct table
    809     pseudo-frames as needed */
    810  static const PseudoParentData sPseudoParentData[eParentTypeCount];
    811 
    812  const FrameConstructionData* FindDataForContent(nsIContent&, ComputedStyle&,
    813                                                  nsIFrame* aParentFrame,
    814                                                  ItemFlags aFlags);
    815 
    816  // aParentFrame might be null.  If it is, that means it was an inline frame.
    817  static const FrameConstructionData* FindTextData(const Text&,
    818                                                   nsIFrame* aParentFrame);
    819  const FrameConstructionData* FindElementData(const Element&, ComputedStyle&,
    820                                               nsIFrame* aParentFrame,
    821                                               ItemFlags aFlags);
    822  const FrameConstructionData* FindElementTagData(const Element&,
    823                                                  ComputedStyle&,
    824                                                  nsIFrame* aParentFrame,
    825                                                  ItemFlags aFlags);
    826 
    827  /* A function that takes an integer, content, style, and array of
    828     FrameConstructionDataByInts and finds the appropriate frame construction
    829     data to use and returns it.  This can return null if none of the integers
    830     match or if the matching integer has a FrameConstructionDataGetter that
    831     returns null. */
    832  static const FrameConstructionData* FindDataByInt(
    833      int32_t aInt, const Element&, ComputedStyle&,
    834      const FrameConstructionDataByInt* aDataPtr, uint32_t aDataLength);
    835 
    836  /**
    837   * A function that takes a tag, content, style, and array of
    838   * FrameConstructionDataByTags and finds the appropriate frame construction
    839   * data to use and returns it.
    840   *
    841   * This can return null if none of the tags match or if the matching tag has a
    842   * FrameConstructionDataGetter that returns null. In the case that the tags
    843   * actually match, aTagFound will be true, even if the return value is null.
    844   */
    845  static const FrameConstructionData* FindDataByTag(
    846      const Element& aElement, ComputedStyle& aComputedStyle,
    847      const FrameConstructionDataByTag* aDataPtr, uint32_t aDataLength);
    848 
    849  /* A class representing a list of FrameConstructionItems.  Instances of this
    850     class are only created as AutoFrameConstructionItemList, or as a member
    851     of FrameConstructionItem. */
    852  class FrameConstructionItemList {
    853   public:
    854    void Reset(nsCSSFrameConstructor* aFCtor) {
    855      Destroy(aFCtor);
    856      this->~FrameConstructionItemList();
    857      new (this) FrameConstructionItemList();
    858    }
    859 
    860    void SetLineBoundaryAtStart(bool aBoundary) {
    861      mLineBoundaryAtStart = aBoundary;
    862    }
    863    void SetLineBoundaryAtEnd(bool aBoundary) {
    864      mLineBoundaryAtEnd = aBoundary;
    865    }
    866    void SetParentHasNoShadowDOM(bool aValue) {
    867      mParentHasNoShadowDOM = aValue;
    868    }
    869    bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; }
    870    bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; }
    871    bool ParentHasNoShadowDOM() { return mParentHasNoShadowDOM; }
    872    bool IsEmpty() const { return mItems.isEmpty(); }
    873    bool AreAllItemsInline() const { return mInlineCount == mItemCount; }
    874    bool AreAllItemsBlock() const { return mBlockCount == mItemCount; }
    875    bool AllWantParentType(ParentType aDesiredParentType) const {
    876      return mDesiredParentCounts[aDesiredParentType] == mItemCount;
    877    }
    878 
    879    // aSuppressWhiteSpaceOptimizations is true if optimizations that
    880    // skip constructing whitespace frames for this item or items
    881    // around it cannot be performed.
    882    // Also, the return value is always non-null, thanks to infallible 'new'.
    883    FrameConstructionItem* AppendItem(
    884        nsCSSFrameConstructor* aFCtor, const FrameConstructionData* aFCData,
    885        nsIContent* aContent, already_AddRefed<ComputedStyle>&& aComputedStyle,
    886        bool aSuppressWhiteSpaceOptimizations) {
    887      FrameConstructionItem* item = new (aFCtor)
    888          FrameConstructionItem(aFCData, aContent, std::move(aComputedStyle),
    889                                aSuppressWhiteSpaceOptimizations);
    890      mItems.insertBack(item);
    891      ++mItemCount;
    892      ++mDesiredParentCounts[item->DesiredParentType()];
    893      return item;
    894    }
    895 
    896    // Arguments are the same as AppendItem().
    897    FrameConstructionItem* PrependItem(
    898        nsCSSFrameConstructor* aFCtor, const FrameConstructionData* aFCData,
    899        nsIContent* aContent, already_AddRefed<ComputedStyle>&& aComputedStyle,
    900        bool aSuppressWhiteSpaceOptimizations) {
    901      FrameConstructionItem* item = new (aFCtor)
    902          FrameConstructionItem(aFCData, aContent, std::move(aComputedStyle),
    903                                aSuppressWhiteSpaceOptimizations);
    904      mItems.insertFront(item);
    905      ++mItemCount;
    906      ++mDesiredParentCounts[item->DesiredParentType()];
    907      return item;
    908    }
    909 
    910    void InlineItemAdded() { ++mInlineCount; }
    911    void BlockItemAdded() { ++mBlockCount; }
    912 
    913    class Iterator {
    914     public:
    915      explicit Iterator(FrameConstructionItemList& aList)
    916          : mCurrent(aList.mItems.getFirst()), mList(aList) {}
    917      Iterator(const Iterator& aOther) = default;
    918 
    919      bool operator==(const Iterator& aOther) const {
    920        MOZ_ASSERT(&mList == &aOther.mList, "Iterators for different lists?");
    921        return mCurrent == aOther.mCurrent;
    922      }
    923      bool operator!=(const Iterator& aOther) const = default;
    924 
    925      Iterator& operator=(const Iterator& aOther) {
    926        MOZ_ASSERT(&mList == &aOther.mList, "Iterators for different lists?");
    927        mCurrent = aOther.mCurrent;
    928        return *this;
    929      }
    930 
    931      FrameConstructionItemList* List() { return &mList; }
    932 
    933      FrameConstructionItem& item() {
    934        MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
    935        return *mCurrent;
    936      }
    937 
    938      const FrameConstructionItem& item() const {
    939        MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
    940        return *mCurrent;
    941      }
    942 
    943      bool IsDone() const { return mCurrent == nullptr; }
    944      bool AtStart() const { return mCurrent == mList.mItems.getFirst(); }
    945      void Next() {
    946        NS_ASSERTION(!IsDone(), "Should have checked IsDone()!");
    947        mCurrent = mCurrent->getNext();
    948      }
    949      void Prev() {
    950        NS_ASSERTION(!AtStart(), "Should have checked AtStart()!");
    951        mCurrent = mCurrent ? mCurrent->getPrevious() : mList.mItems.getLast();
    952      }
    953      void SetToEnd() { mCurrent = nullptr; }
    954 
    955      // Skip over all items that want the given parent type. Return whether
    956      // the iterator is done after doing that.  The iterator must not be done
    957      // when this is called.
    958      inline bool SkipItemsWantingParentType(ParentType aParentType);
    959 
    960      // Skip over all items that want a parent type different from the given
    961      // one.  Return whether the iterator is done after doing that.  The
    962      // iterator must not be done when this is called.
    963      inline bool SkipItemsNotWantingParentType(ParentType aParentType);
    964 
    965      // Skip over non-replaced inline frames and positioned frames.
    966      // Return whether the iterator is done after doing that.
    967      // The iterator must not be done when this is called.
    968      inline bool SkipItemsThatNeedAnonFlexOrGridItem(
    969          const nsFrameConstructorState& aState, bool aIsWebkitBox);
    970 
    971      // Skip to the first frame that is a non-replaced inline or is
    972      // positioned.  Return whether the iterator is done after doing that.
    973      // The iterator must not be done when this is called.
    974      inline bool SkipItemsThatDontNeedAnonFlexOrGridItem(
    975          const nsFrameConstructorState& aState, bool aIsWebkitBox);
    976 
    977      // Skip over all items that do not want a ruby parent.  Return whether
    978      // the iterator is done after doing that.  The iterator must not be done
    979      // when this is called.
    980      inline bool SkipItemsNotWantingRubyParent();
    981 
    982      // Skip over whitespace.  Return whether the iterator is done after doing
    983      // that.  The iterator must not be done, and must be pointing to a
    984      // whitespace item when this is called.
    985      inline bool SkipWhitespace(nsFrameConstructorState& aState);
    986 
    987      // Remove the item pointed to by this iterator from its current list and
    988      // Append it to aTargetList.  This iterator is advanced to point to the
    989      // next item in its list.  aIter must not be done.  aTargetList must not
    990      // be the list this iterator is iterating over..
    991      void AppendItemToList(FrameConstructionItemList& aTargetList);
    992 
    993      // As above, but moves all items starting with this iterator until we
    994      // get to aEnd; the item pointed to by aEnd is not stolen.  This method
    995      // might have optimizations over just looping and doing StealItem for
    996      // some special cases.  After this method returns, this iterator will
    997      // point to the item aEnd points to now; aEnd is not modified.
    998      // aTargetList must not be the list this iterator is iterating over.
    999      void AppendItemsToList(nsCSSFrameConstructor* aFCtor,
   1000                             const Iterator& aEnd,
   1001                             FrameConstructionItemList& aTargetList);
   1002 
   1003      // Insert aItem in this iterator's list right before the item pointed to
   1004      // by this iterator.  After the insertion, this iterator will continue to
   1005      // point to the item it now points to (the one just after the
   1006      // newly-inserted item).  This iterator is allowed to be done; in that
   1007      // case this call just appends the given item to the list.
   1008      void InsertItem(FrameConstructionItem* aItem);
   1009 
   1010      // Delete the items between this iterator and aEnd, including the item
   1011      // this iterator currently points to but not including the item pointed
   1012      // to by aEnd.  When this returns, this iterator will point to the same
   1013      // item as aEnd.  This iterator must not equal aEnd when this method is
   1014      // called.
   1015      void DeleteItemsTo(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd);
   1016 
   1017     private:
   1018      FrameConstructionItem* mCurrent;
   1019      FrameConstructionItemList& mList;
   1020    };
   1021 
   1022   protected:
   1023    FrameConstructionItemList()
   1024        : mInlineCount(0),
   1025          mBlockCount(0),
   1026          mItemCount(0),
   1027          mLineBoundaryAtStart(false),
   1028          mLineBoundaryAtEnd(false),
   1029          mParentHasNoShadowDOM(false) {
   1030      MOZ_COUNT_CTOR(FrameConstructionItemList);
   1031      memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
   1032    }
   1033 
   1034    void Destroy(nsCSSFrameConstructor* aFCtor) {
   1035      while (FrameConstructionItem* item = mItems.popFirst()) {
   1036        item->Delete(aFCtor);
   1037      }
   1038    }
   1039 
   1040    // Prevent stack instances (except as AutoFrameConstructionItemList).
   1041    friend struct FrameConstructionItem;
   1042    ~FrameConstructionItemList() {
   1043      MOZ_COUNT_DTOR(FrameConstructionItemList);
   1044      MOZ_ASSERT(mItems.isEmpty(), "leaking");
   1045    }
   1046 
   1047   private:
   1048    // Not allocated from the heap!
   1049    void* operator new(size_t) = delete;
   1050    void* operator new[](size_t) = delete;
   1051 #ifdef _MSC_VER /* Visual Studio */
   1052    void operator delete(void*) { MOZ_CRASH("FrameConstructionItemList::del"); }
   1053 #else
   1054    void operator delete(void*) = delete;
   1055 #endif
   1056    void operator delete[](void*) = delete;
   1057    // Placement new is used by Reset().
   1058    void* operator new(size_t, void* aPtr) { return aPtr; }
   1059 
   1060    struct UndisplayedItem {
   1061      UndisplayedItem(nsIContent* aContent, ComputedStyle* aComputedStyle)
   1062          : mContent(aContent), mComputedStyle(aComputedStyle) {}
   1063 
   1064      nsIContent* const mContent;
   1065      RefPtr<ComputedStyle> mComputedStyle;
   1066    };
   1067 
   1068    // Adjust our various counts for aItem being added or removed.  aDelta
   1069    // should be either +1 or -1 depending on which is happening.
   1070    void AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta);
   1071 
   1072    mozilla::LinkedList<FrameConstructionItem> mItems;
   1073    uint32_t mInlineCount;
   1074    uint32_t mBlockCount;
   1075    uint32_t mItemCount;
   1076    uint32_t mDesiredParentCounts[eParentTypeCount];
   1077    // True if there is guaranteed to be a line boundary before the
   1078    // frames created by these items
   1079    bool mLineBoundaryAtStart;
   1080    // True if there is guaranteed to be a line boundary after the
   1081    // frames created by these items
   1082    bool mLineBoundaryAtEnd;
   1083    // True if the parent is guaranteed to have no shadow tree.
   1084    bool mParentHasNoShadowDOM;
   1085  };
   1086 
   1087  /* A struct representing a list of FrameConstructionItems on the stack. */
   1088  struct MOZ_RAII AutoFrameConstructionItemList final
   1089      : public FrameConstructionItemList {
   1090    template <typename... Args>
   1091    explicit AutoFrameConstructionItemList(nsCSSFrameConstructor* aFCtor,
   1092                                           Args&&... args)
   1093        : FrameConstructionItemList(std::forward<Args>(args)...),
   1094          mFCtor(aFCtor) {
   1095      MOZ_ASSERT(mFCtor);
   1096    }
   1097    ~AutoFrameConstructionItemList() { Destroy(mFCtor); }
   1098 
   1099   private:
   1100    nsCSSFrameConstructor* const mFCtor;
   1101  };
   1102 
   1103  typedef FrameConstructionItemList::Iterator FCItemIterator;
   1104 
   1105  /* A struct representing an item for which frames might need to be
   1106   * constructed.  This contains all the information needed to construct the
   1107   * frame other than the parent frame and whatever would be stored in the
   1108   * frame constructor state.  You probably want to use
   1109   * AutoFrameConstructionItem instead of this struct. */
   1110  struct FrameConstructionItem final
   1111      : public mozilla::LinkedListElement<FrameConstructionItem> {
   1112    FrameConstructionItem(const FrameConstructionData* aFCData,
   1113                          nsIContent* aContent,
   1114                          already_AddRefed<ComputedStyle>&& aComputedStyle,
   1115                          bool aSuppressWhiteSpaceOptimizations)
   1116        : mFCData(aFCData),
   1117          mContent(aContent),
   1118          mComputedStyle(std::move(aComputedStyle)),
   1119          mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
   1120          mIsText(false),
   1121          mIsGeneratedContent(false),
   1122          mIsAllInline(false),
   1123          mIsBlock(false),
   1124          mIsPopup(false),
   1125          mIsRenderedLegend(false) {
   1126      MOZ_COUNT_CTOR(FrameConstructionItem);
   1127    }
   1128 
   1129    void* operator new(size_t, nsCSSFrameConstructor* aFCtor) {
   1130      return aFCtor->AllocateFCItem();
   1131    }
   1132 
   1133    void Delete(nsCSSFrameConstructor* aFCtor) {
   1134      mChildItems.Destroy(aFCtor);
   1135      if (mIsGeneratedContent) {
   1136        mContent->UnbindFromTree();
   1137        NS_RELEASE(mContent);
   1138      }
   1139      this->~FrameConstructionItem();
   1140      aFCtor->FreeFCItem(this);
   1141    }
   1142 
   1143    ParentType DesiredParentType() {
   1144      return FCDATA_DESIRED_PARENT_TYPE(mFCData->mBits);
   1145    }
   1146 
   1147    // Indicates whether (when in a flex or grid container) this item needs
   1148    // to be wrapped in an anonymous block.  (Note that we implement
   1149    // -webkit-box/-webkit-inline-box using our standard flexbox frame class,
   1150    // but we use different rules for what gets wrapped. The aIsWebkitBox
   1151    // parameter here tells us whether to use those different rules.)
   1152    bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
   1153                                 bool aIsWebkitBox);
   1154 
   1155    // Don't call this unless the frametree really depends on the answer!
   1156    // Especially so for generated content, where we don't want to reframe
   1157    // things.
   1158    bool IsWhitespace(nsFrameConstructorState& aState) const;
   1159 
   1160    bool IsLineBoundary() const {
   1161      return mIsBlock || (mFCData->mBits & FCDATA_IS_LINE_BREAK);
   1162    }
   1163 
   1164    // Child frame construction items.
   1165    FrameConstructionItemList mChildItems;
   1166 
   1167    // The FrameConstructionData to use.
   1168    const FrameConstructionData* mFCData;
   1169    // The nsIContent node to use when initializing the new frame.
   1170    nsIContent* mContent;
   1171    // The style to use for creating the new frame.
   1172    RefPtr<ComputedStyle> mComputedStyle;
   1173    // Whether optimizations to skip constructing textframes around
   1174    // this content need to be suppressed.
   1175    bool mSuppressWhiteSpaceOptimizations : 1;
   1176    // Whether this is a text content item.
   1177    bool mIsText : 1;
   1178    // Whether this is a generated content container.
   1179    // If it is, mContent is a strong pointer.
   1180    bool mIsGeneratedContent : 1;
   1181    // Whether construction from this item will create only frames that are
   1182    // IsInlineOutside() in the principal child list.  This is not precise, but
   1183    // conservative: if true the frames will really be inline, whereas if false
   1184    // they might still all be inline.
   1185    bool mIsAllInline : 1;
   1186    // Whether construction from this item will create only frames that are
   1187    // IsBlockOutside() in the principal child list.  This is not precise, but
   1188    // conservative: if true the frames will really be blocks, whereas if false
   1189    // they might still be blocks (and in particular, out-of-flows that didn't
   1190    // find a containing block).
   1191    bool mIsBlock : 1;
   1192    // Whether construction from this item will create a popup that needs to
   1193    // go into the global popup items.
   1194    bool mIsPopup : 1;
   1195    // Whether this item is the rendered legend of a <fieldset>
   1196    bool mIsRenderedLegend : 1;
   1197 
   1198   private:
   1199    // Not allocated from the general heap - instead, use the new/Delete APIs
   1200    // that take a nsCSSFrameConstructor* (which manages our arena allocation).
   1201    void* operator new(size_t) = delete;
   1202    void* operator new[](size_t) = delete;
   1203 #ifdef _MSC_VER /* Visual Studio */
   1204    void operator delete(void*) { MOZ_CRASH("FrameConstructionItem::delete"); }
   1205 #else
   1206    void operator delete(void*) = delete;
   1207 #endif
   1208    void operator delete[](void*) = delete;
   1209    FrameConstructionItem(const FrameConstructionItem& aOther) = delete;
   1210    // Not allocated from the stack!
   1211    ~FrameConstructionItem() {
   1212      MOZ_COUNT_DTOR(FrameConstructionItem);
   1213      MOZ_ASSERT(mChildItems.IsEmpty(), "leaking");
   1214    }
   1215  };
   1216 
   1217  /**
   1218   * Convenience struct to assist in managing a temporary FrameConstructionItem
   1219   * using a local variable. Castable to FrameConstructionItem so that it can
   1220   * be passed transparently to functions that expect that type.
   1221   * (This struct exists because FrameConstructionItem is arena-allocated, and
   1222   * it's nice to abstract away its allocation/deallocation.)
   1223   */
   1224  struct MOZ_RAII AutoFrameConstructionItem final {
   1225    template <typename... Args>
   1226    explicit AutoFrameConstructionItem(nsCSSFrameConstructor* aFCtor,
   1227                                       Args&&... args)
   1228        : mFCtor(aFCtor),
   1229          mItem(new(aFCtor)
   1230                    FrameConstructionItem(std::forward<Args>(args)...)) {
   1231      MOZ_ASSERT(mFCtor);
   1232    }
   1233    ~AutoFrameConstructionItem() { mItem->Delete(mFCtor); }
   1234    operator FrameConstructionItem&() { return *mItem; }
   1235 
   1236   private:
   1237    nsCSSFrameConstructor* const mFCtor;
   1238    FrameConstructionItem* const mItem;
   1239  };
   1240 
   1241  /**
   1242   * Updates the nsFrameConstructorState auto page-name value, and restores the
   1243   * previous value on destruction.
   1244   * See https://drafts.csswg.org/css-page-3/#using-named-pages
   1245   *
   1246   * To track this, this will automatically add PageValuesProperty to
   1247   * the frame.
   1248   *
   1249   * Note that this does not add PageValuesProperty to the frame when not in a
   1250   * paginated context.
   1251   */
   1252  class MOZ_RAII AutoFrameConstructionPageName final {
   1253    nsFrameConstructorState& mState;
   1254    const nsAtom* mNameToRestore;
   1255 
   1256   public:
   1257    AutoFrameConstructionPageName(const AutoFrameConstructionPageName&) =
   1258        delete;
   1259    AutoFrameConstructionPageName(AutoFrameConstructionPageName&&) = delete;
   1260    AutoFrameConstructionPageName(nsFrameConstructorState& aState,
   1261                                  nsIFrame* const aFrame);
   1262    ~AutoFrameConstructionPageName();
   1263  };
   1264 
   1265  /**
   1266   * Function to create the anonymous flex or grid items that we need.
   1267   * If aParentFrame is not a nsFlexContainerFrame or nsGridContainerFrame then
   1268   * this method is a NOP.
   1269   * @param aItems the child frame construction items before pseudo creation
   1270   * @param aParentFrame the parent frame
   1271   */
   1272  void CreateNeededAnonFlexOrGridItems(nsFrameConstructorState& aState,
   1273                                       FrameConstructionItemList& aItems,
   1274                                       nsIFrame* aParentFrame);
   1275 
   1276  enum RubyWhitespaceType {
   1277    eRubyNotWhitespace,
   1278    eRubyInterLevelWhitespace,
   1279    // Includes inter-base and inter-annotation whitespace
   1280    eRubyInterLeafWhitespace,
   1281    eRubyInterSegmentWhitespace
   1282  };
   1283 
   1284  /**
   1285   * Function to compute the whitespace type according to the display
   1286   * values of the previous and the next elements.
   1287   */
   1288  static inline RubyWhitespaceType ComputeRubyWhitespaceType(
   1289      mozilla::StyleDisplay aPrevDisplay, mozilla::StyleDisplay aNextDisplay);
   1290 
   1291  /**
   1292   * Function to interpret the type of whitespace between
   1293   * |aStartIter| and |aEndIter|.
   1294   */
   1295  static inline RubyWhitespaceType InterpretRubyWhitespace(
   1296      nsFrameConstructorState& aState, const FCItemIterator& aStartIter,
   1297      const FCItemIterator& aEndIter);
   1298 
   1299  /**
   1300   * Function to wrap consecutive misparented inline content into
   1301   * a ruby base box or a ruby text box.
   1302   */
   1303  void WrapItemsInPseudoRubyLeafBox(FCItemIterator& aIter,
   1304                                    ComputedStyle* aParentStyle,
   1305                                    nsIContent* aParentContent);
   1306 
   1307  /**
   1308   * Function to wrap consecutive misparented items
   1309   * into a ruby level container.
   1310   */
   1311  inline void WrapItemsInPseudoRubyLevelContainer(
   1312      nsFrameConstructorState& aState, FCItemIterator& aIter,
   1313      ComputedStyle* aParentStyle, nsIContent* aParentContent);
   1314 
   1315  /**
   1316   * Function to trim leading and trailing whitespaces.
   1317   */
   1318  inline void TrimLeadingAndTrailingWhitespaces(
   1319      nsFrameConstructorState& aState, FrameConstructionItemList& aItems);
   1320 
   1321  /**
   1322   * Function to create internal ruby boxes.
   1323   */
   1324  inline void CreateNeededPseudoInternalRubyBoxes(
   1325      nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
   1326      nsIFrame* aParentFrame);
   1327 
   1328  /**
   1329   * Function to create the pseudo intermediate containers we need.
   1330   * @param aItems the child frame construction items before pseudo creation
   1331   * @param aParentFrame the parent frame we're creating pseudos for
   1332   */
   1333  inline void CreateNeededPseudoContainers(nsFrameConstructorState& aState,
   1334                                           FrameConstructionItemList& aItems,
   1335                                           nsIFrame* aParentFrame);
   1336 
   1337  /**
   1338   * Function to wrap consecutive items into a pseudo parent.
   1339   */
   1340  inline void WrapItemsInPseudoParent(nsIContent* aParentContent,
   1341                                      ComputedStyle* aParentStyle,
   1342                                      ParentType aWrapperType,
   1343                                      FCItemIterator& aIter,
   1344                                      const FCItemIterator& aEndIter);
   1345 
   1346  /**
   1347   * Function to create the pseudo siblings we need.
   1348   */
   1349  inline void CreateNeededPseudoSiblings(nsFrameConstructorState& aState,
   1350                                         FrameConstructionItemList& aItems,
   1351                                         nsIFrame* aParentFrame);
   1352 
   1353  // END TABLE SECTION
   1354 
   1355 protected:
   1356  static nsIFrame* CreatePlaceholderFrameFor(PresShell* aPresShell,
   1357                                             nsIContent* aContent,
   1358                                             nsIFrame* aFrame,
   1359                                             nsContainerFrame* aParentFrame,
   1360                                             nsIFrame* aPrevInFlow,
   1361                                             nsFrameState aTypeBit);
   1362 
   1363 private:
   1364  // ConstructFieldSetFrame puts the new frame in aFrameList and
   1365  // handles the kids of the fieldset
   1366  nsIFrame* ConstructFieldSetFrame(nsFrameConstructorState& aState,
   1367                                   FrameConstructionItem& aItem,
   1368                                   nsContainerFrame* aParentFrame,
   1369                                   const nsStyleDisplay* aStyleDisplay,
   1370                                   nsFrameList& aFrameList);
   1371 
   1372  nsIFrame* ConstructListBoxSelectFrame(nsFrameConstructorState& aState,
   1373                                        FrameConstructionItem& aItem,
   1374                                        nsContainerFrame* aParentFrame,
   1375                                        const nsStyleDisplay* aStyleDisplay,
   1376                                        nsFrameList& aFrameList);
   1377 
   1378  // Creates a block frame wrapping an anonymous ruby frame.
   1379  nsIFrame* ConstructBlockRubyFrame(nsFrameConstructorState& aState,
   1380                                    FrameConstructionItem& aItem,
   1381                                    nsContainerFrame* aParentFrame,
   1382                                    const nsStyleDisplay* aStyleDisplay,
   1383                                    nsFrameList& aFrameList);
   1384 
   1385  void ConstructTextFrame(const FrameConstructionData* aData,
   1386                          nsFrameConstructorState& aState, nsIContent* aContent,
   1387                          nsContainerFrame* aParentFrame,
   1388                          ComputedStyle* aComputedStyle,
   1389                          nsFrameList& aFrameList);
   1390 
   1391  // If aPossibleTextContent is a text node and doesn't have a frame, append a
   1392  // frame construction item for it to aItems.
   1393  void AddTextItemIfNeeded(nsFrameConstructorState& aState,
   1394                           const ComputedStyle& aParentStyle,
   1395                           const InsertionPoint& aInsertion,
   1396                           nsIContent* aPossibleTextContent,
   1397                           FrameConstructionItemList& aItems);
   1398 
   1399  // If aContent is a text node and doesn't have a frame, try to create a frame
   1400  // for it.
   1401  void ReframeTextIfNeeded(nsIContent* aContent);
   1402 
   1403  void AppendPageBreakItem(nsIContent* aContent,
   1404                           FrameConstructionItemList& aItems);
   1405 
   1406  // Function to find FrameConstructionData for aElement.  Will return
   1407  // null if aElement is not HTML.
   1408  // aParentFrame might be null.  If it is, that means it was an
   1409  // inline frame.
   1410  static const FrameConstructionData* FindHTMLData(const Element&,
   1411                                                   nsIFrame* aParentFrame,
   1412                                                   ComputedStyle&);
   1413  // HTML data-finding helper functions
   1414  static const FrameConstructionData* FindSelectData(const Element&,
   1415                                                     ComputedStyle&);
   1416  static const FrameConstructionData* FindImgData(const Element&,
   1417                                                  ComputedStyle&);
   1418  static const FrameConstructionData* FindHTMLButtonData(const Element&,
   1419                                                         ComputedStyle&);
   1420  static const FrameConstructionData* FindGeneratedImageData(const Element&,
   1421                                                             ComputedStyle&);
   1422  static const FrameConstructionData* FindImgControlData(const Element&,
   1423                                                         ComputedStyle&);
   1424  static const FrameConstructionData* FindSearchControlData(const Element&,
   1425                                                            ComputedStyle&);
   1426  static const FrameConstructionData* FindInputData(const Element&,
   1427                                                    ComputedStyle&);
   1428  static const FrameConstructionData* FindObjectData(const Element&,
   1429                                                     ComputedStyle&);
   1430  static const FrameConstructionData* FindCanvasData(const Element&,
   1431                                                     ComputedStyle&);
   1432  // <details> always creates a block per spec *if* the about:config pref
   1433  // 'layout.details.force-block-layout' is set to 'true'.  This is a legacy
   1434  // restriction (based on old spec-text) and we're planning to remove it.
   1435  static const FrameConstructionData* FindDetailsData(const Element&,
   1436                                                      ComputedStyle&);
   1437 
   1438  /* Construct a frame from the given FrameConstructionItem.  This function
   1439     will handle adding the frame to frame lists, processing children, setting
   1440     the frame as the primary frame for the item's content, and so forth.
   1441 
   1442     @param aItem the FrameConstructionItem to use.
   1443     @param aState the frame construction state to use.
   1444     @param aParentFrame the frame to set as the parent of the
   1445                         newly-constructed frame.
   1446     @param aFrameList the frame list to add the new frame (or its
   1447                        placeholder) to.
   1448  */
   1449  void ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
   1450                                      nsFrameConstructorState& aState,
   1451                                      nsContainerFrame* aParentFrame,
   1452                                      nsFrameList& aFrameList);
   1453 
   1454  // The guts of AddFrameConstructionItems
   1455  // aParentFrame might be null.  If it is, that means it was an
   1456  // inline frame.
   1457  void AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
   1458                                         nsIContent* aContent,
   1459                                         nsContainerFrame* aParentFrame,
   1460                                         bool aSuppressWhiteSpaceOptimizations,
   1461                                         ComputedStyle*, ItemFlags,
   1462                                         FrameConstructionItemList& aItems);
   1463 
   1464  /**
   1465   * Construct frames for the given item list and parent frame, and put the
   1466   * resulting frames in aFrameList.
   1467   */
   1468  void ConstructFramesFromItemList(nsFrameConstructorState& aState,
   1469                                   FrameConstructionItemList& aItems,
   1470                                   nsContainerFrame* aParentFrame,
   1471                                   bool aParentIsWrapperAnonBox,
   1472                                   nsFrameList& aFrameList);
   1473  void ConstructFramesFromItem(nsFrameConstructorState& aState,
   1474                               FCItemIterator& aItem,
   1475                               nsContainerFrame* aParentFrame,
   1476                               nsFrameList& aFrameList);
   1477  static bool AtLineBoundary(FCItemIterator& aIter);
   1478 
   1479  nsresult GetAnonymousContent(
   1480      nsIContent* aParent, nsIFrame* aParentFrame,
   1481      nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonContent);
   1482 
   1483  // MathML Mod - RBS
   1484  /**
   1485   * Takes the frames in aBlockList and wraps them in a new anonymous block
   1486   * frame whose content is aContent and whose parent will be aParentFrame.
   1487   * The anonymous block is added to aNewList and aBlockList is cleared.
   1488   */
   1489  void FlushAccumulatedBlock(nsFrameConstructorState& aState,
   1490                             nsIContent* aContent,
   1491                             nsContainerFrame* aParentFrame,
   1492                             nsFrameList& aBlockList, nsFrameList& aNewList);
   1493 
   1494  // Function to find FrameConstructionData for an element.  Will return
   1495  // null if the element is not MathML.
   1496  static const FrameConstructionData* FindMathMLData(const Element&,
   1497                                                     ComputedStyle&);
   1498 
   1499  // Function to find FrameConstructionData for an element.  Will return
   1500  // null if the element is not XUL.
   1501  static const FrameConstructionData* FindXULTagData(const Element&,
   1502                                                     ComputedStyle&);
   1503  // XUL data-finding helper functions and structures
   1504  static const FrameConstructionData* FindPopupGroupData(const Element&,
   1505                                                         ComputedStyle&);
   1506  static const FrameConstructionData* FindXULButtonData(const Element&,
   1507                                                        ComputedStyle&);
   1508  static const FrameConstructionData* FindXULLabelOrDescriptionData(
   1509      const Element&, ComputedStyle&);
   1510 #ifdef XP_MACOSX
   1511  static const FrameConstructionData* FindXULMenubarData(const Element&,
   1512                                                         ComputedStyle&);
   1513 #endif /* XP_MACOSX */
   1514 
   1515  /**
   1516   * Constructs an outer frame, an anonymous child that wraps its real
   1517   * children, and its descendant frames.  This is used by both
   1518   * ConstructOuterSVG and ConstructMarker, which both want an anonymous block
   1519   * child for their children to go in to.
   1520   */
   1521  nsContainerFrame* ConstructFrameWithAnonymousChild(
   1522      nsFrameConstructorState& aState, FrameConstructionItem& aItem,
   1523      nsContainerFrame* aParentFrame, nsFrameList& aFrameList,
   1524      ContainerFrameCreationFunc aConstructor,
   1525      ContainerFrameCreationFunc aInnerConstructor,
   1526      mozilla::PseudoStyleType aInnerPseudo, bool aCandidateRootFrame);
   1527 
   1528  /**
   1529   * Construct an SVGOuterSVGFrame.
   1530   */
   1531  nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState,
   1532                              FrameConstructionItem& aItem,
   1533                              nsContainerFrame* aParentFrame,
   1534                              const nsStyleDisplay* aDisplay,
   1535                              nsFrameList& aFrameList);
   1536 
   1537  /**
   1538   * Construct an SVGMarkerFrame.
   1539   */
   1540  nsIFrame* ConstructMarker(nsFrameConstructorState& aState,
   1541                            FrameConstructionItem& aItem,
   1542                            nsContainerFrame* aParentFrame,
   1543                            const nsStyleDisplay* aDisplay,
   1544                            nsFrameList& aFrameList);
   1545 
   1546  static const FrameConstructionData* FindSVGData(const Element&,
   1547                                                  nsIFrame* aParentFrame,
   1548                                                  bool aIsWithinSVGText,
   1549                                                  bool aAllowsTextPathChild,
   1550                                                  ComputedStyle&);
   1551 
   1552  // Not static because it does PropagateScrollToViewport.  If this
   1553  // changes, make this static.
   1554  const FrameConstructionData* FindDisplayData(const nsStyleDisplay&,
   1555                                               const Element&);
   1556 
   1557  /**
   1558   * Construct a scrollable block frame
   1559   */
   1560  nsIFrame* ConstructScrollableBlock(nsFrameConstructorState& aState,
   1561                                     FrameConstructionItem& aItem,
   1562                                     nsContainerFrame* aParentFrame,
   1563                                     const nsStyleDisplay* aDisplay,
   1564                                     nsFrameList& aFrameList);
   1565 
   1566  /**
   1567   * Construct a non-scrollable block frame
   1568   */
   1569  nsIFrame* ConstructNonScrollableBlock(nsFrameConstructorState& aState,
   1570                                        FrameConstructionItem& aItem,
   1571                                        nsContainerFrame* aParentFrame,
   1572                                        const nsStyleDisplay* aDisplay,
   1573                                        nsFrameList& aFrameList);
   1574 
   1575  /**
   1576   * This adds FrameConstructionItem objects to aItemsToConstruct for the
   1577   * anonymous content returned by an nsIAnonymousContentCreator::
   1578   * CreateAnonymousContent implementation.
   1579   * This includes an AutoFrameConstructionPageName argument as it is always
   1580   * the caller's responsibility to handle page-name tracking before calling
   1581   * this function.
   1582   */
   1583  void AddFCItemsForAnonymousContent(
   1584      nsFrameConstructorState& aState, nsContainerFrame* aFrame,
   1585      const nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
   1586      FrameConstructionItemList& aItemsToConstruct,
   1587      const AutoFrameConstructionPageName& aUnusedPageNameTracker);
   1588 
   1589  /**
   1590   * Construct the frames for the children of aContent.  "children" is defined
   1591   * as "whatever FlattenedChildIterator returns for aContent".  This means
   1592   * we're basically operating on children in the "flattened tree":
   1593   *
   1594   *   https://drafts.csswg.org/css-scoping/#flat-tree
   1595   *
   1596   * This method will also handle constructing ::before, ::after,
   1597   * ::first-letter, and ::first-line frames, as needed and if allowed.
   1598   *
   1599   * If the parent is a float containing block, this method will handle pushing
   1600   * it as the float containing block in aState (so there's no need for callers
   1601   * to push it themselves).
   1602   *
   1603   * @param aState the frame construction state
   1604   * @param aContent the content node whose children need frames
   1605   * @param aComputedStyle the style for aContent
   1606   * @param aParentFrame the frame to use as the parent frame for the new
   1607   * in-flow kids. Note that this must be its own content insertion frame, but
   1608   *        need not be be the primary frame for aContent.  This frame will be
   1609   *        pushed as the float containing block, as needed.  aFrame is also
   1610   *        used to find the parent style for the kids' style
   1611   *        (not necessary aFrame's style).
   1612   * @param aCanHaveGeneratedContent Whether to allow :before and
   1613   *        :after styles on the parent.
   1614   * @param aFrameList the list in which we should place the in-flow children
   1615   * @param aAllowBlockStyles Whether to allow first-letter and first-line
   1616   *        styles on the parent.
   1617   * @param aPossiblyLeafFrame if non-null, this should be used for the isLeaf
   1618   *        test and the anonymous content creation.  If null, aFrame will be
   1619   *        used.
   1620   */
   1621  void ProcessChildren(nsFrameConstructorState& aState, nsIContent* aContent,
   1622                       ComputedStyle* aComputedStyle,
   1623                       nsContainerFrame* aParentFrame,
   1624                       const bool aCanHaveGeneratedContent,
   1625                       nsFrameList& aFrameList, const bool aAllowBlockStyles,
   1626                       nsIFrame* aPossiblyLeafFrame = nullptr);
   1627 
   1628  /**
   1629   * These two functions are used when we start frame creation from a non-root
   1630   * element. They should recreate the same state that we would have
   1631   * arrived at if we had built frames from the root frame to aFrame.
   1632   * Therefore, any calls to PushFloatContainingBlock and
   1633   * PushAbsoluteContainingBlock during frame construction should get
   1634   * corresponding logic in these functions.
   1635   */
   1636 public:
   1637  enum ContainingBlockType { ABS_POS, FIXED_POS };
   1638  nsContainerFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame,
   1639                                               ContainingBlockType aType);
   1640  nsContainerFrame* GetFloatContainingBlock(nsIFrame* aFrame);
   1641 
   1642 private:
   1643  // Build a scroll container frame, and wrap the scrolled frame. The
   1644  // hierarchy will look like this:
   1645  //
   1646  //       ScrollContainerFrame
   1647  //                 ^
   1648  //                 |
   1649  //               Frame (scrolled frame you passed in as aScrolledFrame)
   1650  //
   1651  // @param aContent the content node of the child to wrap.
   1652  //
   1653  // @param aContentStyle the style that has already been resolved for the
   1654  // content being passed in.
   1655  //
   1656  // @param aScrolledFrame The frame of the content to wrap. This should not be
   1657  // initialized (i.e. Init() should not yet have been called). This method will
   1658  // initialize it with a scrolled pseudo and no nsIContent. The content will be
   1659  // attached to the scroll container frame that this function returns.
   1660  //
   1661  // @param aParentFrame The geometric parent to attach the scroll container
   1662  // frame to.
   1663  //
   1664  // @param aNewFrame [in/out] If this is not nullptr, we will just use it as
   1665  // the scroll container frame, rather than creating a new scroll container
   1666  // frame. Otherwise (i.e. if it's nullptr), we'll create a new scroll
   1667  // container frame, and return it by reference via this param.
   1668  void BuildScrollContainerFrame(nsFrameConstructorState& aState,
   1669                                 nsIContent* aContent,
   1670                                 ComputedStyle* aContentStyle,
   1671                                 nsIFrame* aScrolledFrame,
   1672                                 nsContainerFrame* aParentFrame,
   1673                                 nsContainerFrame*& aNewFrame);
   1674 
   1675  // Builds the initial scroll container frame.
   1676  already_AddRefed<ComputedStyle> BeginBuildingScrollContainerFrame(
   1677      nsFrameConstructorState& aState, nsIContent* aContent,
   1678      ComputedStyle* aContentStyle, nsContainerFrame* aParentFrame,
   1679      mozilla::PseudoStyleType aScrolledPseudo, bool aIsRoot,
   1680      nsContainerFrame*& aNewFrame);
   1681 
   1682  // Completes the building of the scroll container frame.
   1683  // Creates a view for the scrolledframe and makes it the child of the
   1684  // scroll container frame.
   1685  void FinishBuildingScrollContainerFrame(
   1686      nsContainerFrame* aScrollContainerFrame, nsIFrame* aScrolledFrame);
   1687 
   1688  void InitializeListboxSelect(nsFrameConstructorState& aState,
   1689                               nsContainerFrame* aScrollFrame,
   1690                               nsContainerFrame* aScrolledFrame,
   1691                               nsIContent* aContent,
   1692                               nsContainerFrame* aParentFrame,
   1693                               ComputedStyle* aComputedStyle,
   1694                               nsFrameList& aFrameList);
   1695 
   1696  /**
   1697   * Recreate frames for aContent.
   1698   */
   1699  void RecreateFramesForContent(nsIContent* aContent, InsertionKind);
   1700 
   1701  /**
   1702   *  Handles change of rowspan and colspan attributes on table cells.
   1703   */
   1704  void UpdateTableCellSpans(nsIContent* aContent);
   1705 
   1706  // If removal of aFrame from the frame tree requires reconstruction of some
   1707  // containing block (either of aFrame or of its parent) due to {ib} splits or
   1708  // table pseudo-frames, recreate the relevant frame subtree.  The return value
   1709  // indicates whether this happened.  aFrame must be the result of a
   1710  // GetPrimaryFrame() call on a content node (which means its parent is also
   1711  // not null).
   1712  bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame);
   1713 
   1714  nsIFrame* CreateContinuingOuterTableFrame(nsIFrame* aFrame,
   1715                                            nsContainerFrame* aParentFrame,
   1716                                            nsIContent* aContent,
   1717                                            ComputedStyle* aComputedStyle);
   1718 
   1719  nsIFrame* CreateContinuingTableFrame(nsIFrame* aFrame,
   1720                                       nsContainerFrame* aParentFrame,
   1721                                       nsIContent* aContent,
   1722                                       ComputedStyle* aComputedStyle);
   1723 
   1724  //----------------------------------------
   1725 
   1726  // Methods support creating block frames and their children
   1727 
   1728  already_AddRefed<ComputedStyle> GetFirstLetterStyle(
   1729      nsIContent* aContent, ComputedStyle* aComputedStyle);
   1730 
   1731  already_AddRefed<ComputedStyle> GetFirstLineStyle(
   1732      nsIContent* aContent, ComputedStyle* aComputedStyle);
   1733 
   1734  bool ShouldHaveFirstLetterStyle(nsIContent* aContent,
   1735                                  ComputedStyle* aComputedStyle);
   1736 
   1737  // Check whether a given block has first-letter style.  Make sure to
   1738  // only pass in blocks!  And don't pass in null either.
   1739  bool HasFirstLetterStyle(nsIFrame* aBlockFrame);
   1740 
   1741  bool ShouldHaveFirstLineStyle(nsIContent* aContent,
   1742                                ComputedStyle* aComputedStyle);
   1743 
   1744  void ShouldHaveSpecialBlockStyle(nsIContent* aContent,
   1745                                   ComputedStyle* aComputedStyle,
   1746                                   bool* aHaveFirstLetterStyle,
   1747                                   bool* aHaveFirstLineStyle);
   1748 
   1749  // |aContentParentFrame| should be null if it's really the same as
   1750  // |aParentFrame|.
   1751  // @param aFrameList where we want to put the block in case it's in-flow.
   1752  // @param aNewFrame an in/out parameter. On input it is the block to be
   1753  // constructed. On output it is reset to the outermost
   1754  // frame constructed (e.g. if we need to wrap the block in an
   1755  // nsColumnSetFrame.
   1756  // @param aParentFrame is the desired parent for the (possibly wrapped)
   1757  // block
   1758  // @param aContentParent is the parent the block would have if it
   1759  // were in-flow
   1760  // @param aPositionedFrameForAbsPosContainer if non-null, then the new
   1761  // block should be an abs-pos container and aPositionedFrameForAbsPosContainer
   1762  // is the frame whose style is making this block an abs-pos container.
   1763  void ConstructBlock(nsFrameConstructorState& aState, nsIContent* aContent,
   1764                      nsContainerFrame* aParentFrame,
   1765                      nsContainerFrame* aContentParentFrame,
   1766                      ComputedStyle* aComputedStyle,
   1767                      nsContainerFrame** aNewFrame, nsFrameList& aFrameList,
   1768                      nsIFrame* aPositionedFrameForAbsPosContainer);
   1769 
   1770  // Build the initial column hierarchy around aColumnContent. This function
   1771  // should be called before constructing aColumnContent's children.
   1772  //
   1773  // Before calling FinishBuildingColumns(), we need to create column-span
   1774  // siblings for aColumnContent's children. Caller can use helpers
   1775  // MayNeedToCreateColumnSpanSiblings() and CreateColumnSpanSiblings() to
   1776  // check whether column-span siblings might need to be created and to do
   1777  // the actual work of creating them if they're needed.
   1778  //
   1779  // @param aColumnContent the block that we're wrapping in a ColumnSet. On
   1780  //        entry to this function it has aComputedStyle as its style. After
   1781  //        this function returns, aColumnContent has a ::-moz-column-content
   1782  //        anonymous box style.
   1783  // @param aParentFrame the parent frame we want to use for the
   1784  //        ColumnSetWrapperFrame (which would have been the parent of
   1785  //        aColumnContent if we were not creating a column hierarchy).
   1786  // @param aContent is the content of the aColumnContent.
   1787  // @return the outermost ColumnSetWrapperFrame.
   1788  nsBlockFrame* BeginBuildingColumns(nsFrameConstructorState& aState,
   1789                                     nsIContent* aContent,
   1790                                     nsContainerFrame* aParentFrame,
   1791                                     nsContainerFrame* aColumnContent,
   1792                                     ComputedStyle* aComputedStyle);
   1793 
   1794  // Complete building the column hierarchy by first wrapping each
   1795  // non-column-span child in aChildList in a ColumnSetFrame (skipping
   1796  // column-span children), and reparenting them to have aColumnSetWrapper
   1797  // as their parent.
   1798  //
   1799  // @param aColumnSetWrapper is the frame returned by
   1800  //        BeginBuildingColumns(), and is the grandparent of aColumnContent.
   1801  // @param aColumnContent is the block frame passed into
   1802  //        BeginBuildingColumns()
   1803  // @param aColumnContentSiblings contains the aColumnContent's siblings, which
   1804  //        are the column spanners and aColumnContent's continuations returned
   1805  //        by CreateColumnSpanSiblings(). It'll become empty after this call.
   1806  void FinishBuildingColumns(nsFrameConstructorState& aState,
   1807                             nsContainerFrame* aColumnSetWrapper,
   1808                             nsContainerFrame* aColumnContent,
   1809                             nsFrameList& aColumnContentSiblings);
   1810 
   1811  // Return whether aBlockFrame's children in aChildList, which might
   1812  // contain column-span, may need to be wrapped in
   1813  // ::moz-column-span-wrapper and promoted as aBlockFrame's siblings.
   1814  //
   1815  // @param aBlockFrame is the parent of the frames in aChildList.
   1816  //
   1817  // Note: This a check without actually looking into each frame in the
   1818  // child list, so it may return false positive.
   1819  bool MayNeedToCreateColumnSpanSiblings(nsContainerFrame* aBlockFrame,
   1820                                         const nsFrameList& aChildList);
   1821 
   1822  // Wrap consecutive runs of column-span kids and runs of non-column-span
   1823  // kids in blocks for aInitialBlock's children.
   1824  //
   1825  // @param aInitialBlock is the parent of those frames in aChildList.
   1826  // @param aChildList must begin with a column-span kid. It becomes empty
   1827  //        after this call.
   1828  // @param aPositionedFrame if non-null, it's the frame whose style is making
   1829  //        aInitialBlock an abs-pos container.
   1830  //
   1831  // Return those wrapping blocks in nsFrameList.
   1832  nsFrameList CreateColumnSpanSiblings(nsFrameConstructorState& aState,
   1833                                       nsContainerFrame* aInitialBlock,
   1834                                       nsFrameList& aChildList,
   1835                                       nsIFrame* aPositionedFrame);
   1836 
   1837  // Reconstruct the multi-column containing block of aParentFrame when we want
   1838  // to insert aFrameList into aParentFrame immediately after aPrevSibling but
   1839  // cannot fix the frame tree because aFrameList contains some column-spans.
   1840  //
   1841  // Note: This method is intended to be called as a helper in ContentAppended()
   1842  // and ContentRangeInserted(). It assumes aState was set up locally and wasn't
   1843  // used to construct any ancestors of aParentFrame in aFrameList.
   1844  //
   1845  // @param aParentFrame the to-be parent frame for aFrameList.
   1846  // @param aFrameList the frames to be inserted. It will be cleared if we need
   1847  //        reconstruction.
   1848  // @param aPrevSibling the position where the frames in aFrameList are going
   1849  //        to be inserted. Nullptr means aFrameList is being inserted at
   1850  //        the beginning.
   1851  // @return true if the multi-column containing block of aParentFrame is
   1852  //         reconstructed; false otherwise.
   1853  bool MaybeRecreateForColumnSpan(nsFrameConstructorState& aState,
   1854                                  nsContainerFrame* aParentFrame,
   1855                                  nsFrameList& aFrameList,
   1856                                  nsIFrame* aPrevSibling);
   1857 
   1858  nsIFrame* ConstructInline(nsFrameConstructorState& aState,
   1859                            FrameConstructionItem& aItem,
   1860                            nsContainerFrame* aParentFrame,
   1861                            const nsStyleDisplay* aDisplay,
   1862                            nsFrameList& aFrameList);
   1863 
   1864  /**
   1865   * Create any additional {ib} siblings needed to contain aChildList and put
   1866   * them in aSiblings.
   1867   *
   1868   * @param aState the frame constructor state
   1869   * @param aInitialInline is an already-existing inline frame that will be
   1870   *                       part of this {ib} split and come before everything
   1871   *                       in aSiblings.
   1872   * @param aIsPositioned true if aInitialInline is positioned.
   1873   * @param aChildList is a child list starting with a block; this method
   1874   *                    assumes that the inline has already taken all the
   1875   *                    children it wants.  When the method returns aChildList
   1876   *                    will be empty.
   1877   * @param aSiblings the nsFrameList to put the newly-created siblings into.
   1878   *
   1879   * This method is responsible for making any SetFrameIsIBSplit calls that are
   1880   * needed.
   1881   */
   1882  void CreateIBSiblings(nsFrameConstructorState& aState,
   1883                        nsContainerFrame* aInitialInline, bool aIsPositioned,
   1884                        nsFrameList& aChildList, nsFrameList& aSiblings);
   1885 
   1886  /**
   1887   * For an inline aParentItem, construct its list of child
   1888   * FrameConstructionItems and set its mIsAllInline flag appropriately.
   1889   */
   1890  void BuildInlineChildItems(nsFrameConstructorState& aState,
   1891                             FrameConstructionItem& aParentItem,
   1892                             bool aItemIsWithinSVGText,
   1893                             bool aItemAllowsTextPathChild);
   1894 
   1895  // Determine whether we need to wipe out aFrame (the insertion parent) and
   1896  // rebuild the entire subtree when we insert or append new content under
   1897  // aFrame.
   1898  //
   1899  // This is similar to WipeContainingBlock(), but is called
   1900  // before constructing any frame construction items. Any container frames
   1901  // which need reframing regardless of the content inserted or appended can add
   1902  // a check in this method.
   1903  //
   1904  // @return true if we reconstructed the insertion parent frame; false
   1905  // otherwise
   1906  bool WipeInsertionParent(nsContainerFrame* aFrame);
   1907 
   1908  // Determine whether we need to wipe out what we just did and start over
   1909  // because we're doing something like adding block kids to an inline frame
   1910  // (and therefore need an {ib} split).  aPrevSibling must be correct, even in
   1911  // aIsAppend cases.  Passing aIsAppend false even when an append is happening
   1912  // is ok in terms of correctness, but can lead to unnecessary reframing.
   1913  //
   1914  // @return true if we reconstructed the containing block, false otherwise.
   1915  bool WipeContainingBlock(nsFrameConstructorState& aState,
   1916                           nsIFrame* aContainingBlock, nsIFrame* aFrame,
   1917                           FrameConstructionItemList& aItems, bool aIsAppend,
   1918                           nsIFrame* aPrevSibling);
   1919 
   1920  void ReframeContainingBlock(nsIFrame* aFrame);
   1921 
   1922  //----------------------------------------
   1923 
   1924  // Methods support :first-letter style
   1925 
   1926  nsFirstLetterFrame* CreateFloatingLetterFrame(
   1927      nsFrameConstructorState& aState, mozilla::dom::Text* aTextContent,
   1928      nsIFrame* aTextFrame, nsContainerFrame* aParentFrame,
   1929      ComputedStyle* aParentStyle, ComputedStyle* aComputedStyle,
   1930      nsFrameList& aResult);
   1931 
   1932  void CreateLetterFrame(nsContainerFrame* aBlockFrame,
   1933                         nsContainerFrame* aBlockContinuation,
   1934                         mozilla::dom::Text* aTextContent,
   1935                         nsContainerFrame* aParentFrame, nsFrameList& aResult);
   1936 
   1937  void WrapFramesInFirstLetterFrame(nsContainerFrame* aBlockFrame,
   1938                                    nsFrameList& aBlockFrames);
   1939 
   1940  /**
   1941   * Looks in the block aBlockFrame for a text frame that contains the
   1942   * first-letter of the block and creates the necessary first-letter frames
   1943   * and returns them in aLetterFrames.
   1944   *
   1945   * @param aBlockFrame the (first-continuation of) the block we are creating a
   1946   *                    first-letter frame for
   1947   * @param aBlockContinuation the current continuation of the block that we
   1948   *                           are looking in for a textframe with suitable
   1949   *                           contents for first-letter
   1950   * @param aParentFrame the current frame whose children we are looking at for
   1951   *                     a suitable first-letter textframe
   1952   * @param aParentFrameList the first child of aParentFrame
   1953   * @param aModifiedParent returns the parent of the textframe that contains
   1954   *                        the first-letter
   1955   * @param aTextFrame returns the textframe that had the first-letter
   1956   * @param aPrevFrame returns the previous sibling of aTextFrame
   1957   * @param aLetterFrames returns the frames that were created
   1958   */
   1959  void WrapFramesInFirstLetterFrame(
   1960      nsContainerFrame* aBlockFrame, nsContainerFrame* aBlockContinuation,
   1961      nsContainerFrame* aParentFrame, nsIFrame* aParentFrameList,
   1962      nsContainerFrame** aModifiedParent, nsIFrame** aTextFrame,
   1963      nsIFrame** aPrevFrame, nsFrameList& aLetterFrames, bool* aStopLooking);
   1964 
   1965  void RecoverLetterFrames(nsContainerFrame* aBlockFrame);
   1966 
   1967  void RemoveLetterFrames(PresShell* aPresShell, nsContainerFrame* aBlockFrame);
   1968 
   1969  // Recursive helper for RemoveLetterFrames
   1970  void RemoveFirstLetterFrames(PresShell* aPresShell, nsContainerFrame* aFrame,
   1971                               nsContainerFrame* aBlockFrame,
   1972                               bool* aStopLooking);
   1973 
   1974  // Special remove method for those pesky floating first-letter frames
   1975  void RemoveFloatingFirstLetterFrames(PresShell* aPresShell,
   1976                                       nsIFrame* aBlockFrame);
   1977 
   1978  // Capture state for the frame tree rooted at the frame associated with the
   1979  // content object, aContent
   1980  void CaptureStateForFramesOf(nsIContent* aContent,
   1981                               nsILayoutHistoryState* aHistoryState);
   1982 
   1983  //----------------------------------------
   1984 
   1985  // Methods support :first-line style
   1986 
   1987  // This method chops the initial inline-outside frames out of aFrameList.
   1988  // If aLineFrame is non-null, it appends them to that frame.  Otherwise, it
   1989  // creates a new line frame, sets the inline frames as its initial child
   1990  // list, and inserts that line frame at the front of what's left of
   1991  // aFrameList.  In both cases, the kids are reparented to the line frame.
   1992  // After this call, aFrameList holds the frames that need to become kids of
   1993  // the block (possibly including line frames).
   1994  void WrapFramesInFirstLineFrame(nsFrameConstructorState& aState,
   1995                                  nsIContent* aBlockContent,
   1996                                  nsContainerFrame* aBlockFrame,
   1997                                  nsFirstLineFrame* aLineFrame,
   1998                                  nsFrameList& aFrameList);
   1999 
   2000  // Handle the case when a block with first-line style is appended to (by
   2001  // possibly calling WrapFramesInFirstLineFrame as needed).
   2002  void AppendFirstLineFrames(nsFrameConstructorState& aState,
   2003                             nsIContent* aContent,
   2004                             nsContainerFrame* aBlockFrame,
   2005                             nsFrameList& aFrameList);
   2006 
   2007  /**
   2008   * When aFrameList is being inserted into aParentFrame, and aParentFrame has
   2009   * pseudo-element-affected styles, it's possible that we're inserting under a
   2010   * ::first-line frame.  In that case, with servo's style system, the styles we
   2011   * resolved for aFrameList are wrong (they don't take ::first-line into
   2012   * account), and we should fix them up, which is what this method does.
   2013   *
   2014   * This method does not mutate aFrameList.
   2015   */
   2016  void CheckForFirstLineInsertion(nsIFrame* aParentFrame,
   2017                                  nsFrameList& aFrameList);
   2018 
   2019  // The direction in which we should look for siblings.
   2020  enum class SiblingDirection {
   2021    Forward,
   2022    Backward,
   2023  };
   2024 
   2025  /**
   2026   * Find the frame for the content immediately next to the one aIter points to,
   2027   * in the direction SiblingDirection indicates, following continuations if
   2028   * necessary.
   2029   *
   2030   * aIter is passed by const reference on purpose, so as not to modify the
   2031   * caller's iterator.
   2032   *
   2033   * @param aIter should be positioned such that aIter.GetPreviousChild()
   2034   *          is the first content to search for frames
   2035   */
   2036  template <SiblingDirection>
   2037  nsIFrame* FindSibling(const mozilla::dom::FlattenedChildIterator& aIter);
   2038 
   2039  // Helper for the implementation of FindSibling.
   2040  //
   2041  // Beware that this function does mutate the iterator.
   2042  template <SiblingDirection>
   2043  nsIFrame* FindSiblingInternal(mozilla::dom::FlattenedChildIterator&);
   2044 
   2045  // An alias of FindSibling<SiblingDirection::Forward>.
   2046  nsIFrame* FindNextSibling(const mozilla::dom::FlattenedChildIterator& aIter);
   2047  // An alias of FindSibling<SiblingDirection::Backward>.
   2048  nsIFrame* FindPreviousSibling(
   2049      const mozilla::dom::FlattenedChildIterator& aIter);
   2050 
   2051  // Given a potential first-continuation sibling frame, return the
   2052  // appropriate continuation the new frame should be inserted next to.
   2053  nsIFrame* AdjustSiblingFrame(nsIFrame* aSibling, SiblingDirection);
   2054 
   2055  // Find the right previous sibling for an insertion.  This also updates the
   2056  // parent frame to point to the correct continuation of the parent frame to
   2057  // use, and returns whether this insertion is to be treated as an append.
   2058  // aChild is the child being inserted.
   2059  // It is the callers' responsibility to check whether a range insert is safe
   2060  // with regards to fieldsets / tables.
   2061  nsIFrame* GetInsertionPrevSibling(InsertionPoint* aInsertion,  // inout
   2062                                    nsIContent* aChild, bool* aIsAppend);
   2063 
   2064  void QuotesDirty();
   2065  void CountersDirty();
   2066 
   2067  void ConstructAnonymousContentForRoot(nsFrameConstructorState& aState,
   2068                                        nsContainerFrame* aCanvasFrame,
   2069                                        nsIContent* aDocElement, nsFrameList&);
   2070 
   2071 public:
   2072  friend class nsFrameConstructorState;
   2073 
   2074 private:
   2075  // For allocating FrameConstructionItems from the mFCItemPool arena.
   2076  friend struct FrameConstructionItem;
   2077  void* AllocateFCItem();
   2078  void FreeFCItem(FrameConstructionItem*);
   2079 
   2080  mozilla::dom::Document* mDocument;  // Weak ref
   2081 
   2082  // See the comment at the start of ConstructRootFrame for more details
   2083  // about the following frames.
   2084 
   2085  // This is just the outermost frame for the root element.
   2086  nsContainerFrame* mRootElementFrame = nullptr;
   2087  // This is the frame for the root element that has no pseudo-element style.
   2088  nsIFrame* mRootElementStyleFrame = nullptr;
   2089  // This is the containing block that contains the root element ---
   2090  // the real "initial containing block" according to CSS 2.1.
   2091  nsCanvasFrame* mDocElementContainingBlock = nullptr;
   2092  // This is usually mDocElementContainingBlock, except when printing, where it
   2093  // is the canvas frame that is under all the printed pages.
   2094  nsCanvasFrame* mCanvasFrame = nullptr;
   2095  nsPageSequenceFrame* mPageSequenceFrame = nullptr;
   2096 
   2097  // FrameConstructionItem arena + list of freed items available for re-use.
   2098  mozilla::ArenaAllocator<4096, 8> mFCItemPool;
   2099 
   2100  // This indicates what page name to use for the next nsPageContentFrame.
   2101  // Set when CSS named pages cause a breakpoint.
   2102  // This does not apply to the first page content frame, which has its name
   2103  // set by nsPageContentFrame::EnsurePageName() during first reflow.
   2104  RefPtr<const nsAtom> mNextPageContentFramePageName;
   2105 
   2106  struct FreeFCItemLink {
   2107    FreeFCItemLink* mNext;
   2108  };
   2109  FreeFCItemLink* mFirstFreeFCItem;
   2110  size_t mFCItemsInUse;
   2111 
   2112  mozilla::ContainStyleScopeManager mContainStyleScopeManager;
   2113 
   2114  // Current ProcessChildren depth.
   2115  uint16_t mCurrentDepth;
   2116  bool mQuotesDirty : 1;
   2117  bool mCountersDirty : 1;
   2118  bool mAlwaysCreateFramesForIgnorableWhitespace : 1;
   2119  bool mRemovingContent : 1;
   2120 
   2121  // The layout state from our history entry (to restore scroll positions and
   2122  // such from history), or a new one if there was none (so we can store scroll
   2123  // positions and such during reframe).
   2124  //
   2125  // FIXME(bug 1397239): This can leak some state sometimes for the lifetime of
   2126  // the frame constructor, which is not great.
   2127  nsCOMPtr<nsILayoutHistoryState> mFrameTreeState;
   2128 };
   2129 
   2130 #endif /* nsCSSFrameConstructor_h___ */