/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
class nsBlockFrame; class nsContainerFrame; class nsCanvasFrame; class nsFirstLetterFrame; class nsFirstLineFrame; class nsFrameConstructorState; class nsPageContentFrame; class nsPageSequenceFrame;
namespace mozilla {
class ComputedStyle; class PresShell; class PrintedSheetFrame; class RestyleManager; class ViewportFrame;
namespace dom {
class CharacterData; class Text; class FlattenedChildIterator;
} // namespace dom
} // namespace mozilla
class nsCSSFrameConstructor final : public nsFrameManager { public: using ComputedStyle = mozilla::ComputedStyle; using PseudoStyleType = mozilla::PseudoStyleType; using PresShell = mozilla::PresShell; using Element = mozilla::dom::Element; using Text = mozilla::dom::Text;
// FIXME(emilio): Is this really needed? friendclass mozilla::RestyleManager;
private: // aChild is the child being inserted for inserts, and the first // child being appended for appends. All the nodes in the range are // guaranteed to have the same flat tree parent. void ConstructLazily(nsIContent* aStartChild, nsIContent* aEndChild);
// Issues a single ContentInserted for each child in the range // [aStartChild, aEndChild). void IssueSingleInsertNofications(nsIContent* aStartChild,
nsIContent* aEndChild, InsertionKind);
// If the insertion kind is Async then frame construction of the new children // can be done lazily. void ContentAppended(nsIContent* aFirstNewContent, InsertionKind);
// If the insertion kind is Async then frame construction of the new child // can be done lazily. void ContentInserted(nsIContent* aChild, InsertionKind);
// Like ContentInserted but handles inserting the children in the range // [aStartChild, aEndChild). aStartChild must be non-null. aEndChild may be // null to indicate the range includes all kids after aStartChild. // // If aInsertionKind is Async then frame construction of the new children can // be done lazily. It is only allowed to be Async when inserting a single // node. void ContentRangeInserted(nsIContent* aStartChild, nsIContent* aEndChild,
InsertionKind aInsertionKind);
// The kind of removal we're dealing with. enumclass RemovalKind : uint8_t { // The DOM node is getting removed from the document.
Dom, // We're about to remove this frame, but we will insert it later.
ForReconstruction, // We're about to remove this frame due to a style change but we know we // are not going to create a frame later.
ForDisplayNoneChange,
};
// If aContent is a text node that has been optimized away due to being // whitespace next to a block boundary (or for some other reason), ensure that // a frame for it is created the next time frames are flushed, if it can // possibly have a frame at all. // // Returns whether there are chances for the frame to be unsuppressed. bool EnsureFrameForTextNodeIsCreatedAfterFlush(
mozilla::dom::CharacterData* aContent);
// Should be called when a frame is going to be destroyed and // WillDestroyFrameTree hasn't been called yet. void NotifyDestroyingFrame(nsIFrame* aFrame);
void RecalcQuotesAndCounters();
// Called when any counter style is changed. void NotifyCounterStylesAreDirty();
// Gets called when the presshell is destroying itself and also // when we tear down our frame tree to reconstruct it void WillDestroyFrameTree();
// Request to create a continuing frame. This method never returns null.
nsIFrame* CreateContinuingFrame(nsIFrame* aFrame,
nsContainerFrame* aParentFrame, bool aIsFluid = true);
/** *Setsthepagenamewhenapagebreakisbeinggeneratedduetoachange *inpagename. * *Shouldonlybeusedduringpaginatedreflow,tosignalwhatpagevalue *thenextpagecontentframeshouldhave. * *Itisanerrortosetthisifanewpagenamehasalreadybeenset,either *throughSetNextPageContentFramePageNameor *MaybeSetNextPageContentFramePageName.
*/ void SetNextPageContentFramePageName(const nsAtom* aPageName) {
MOZ_ASSERT(aPageName, "New page name should never be null");
MOZ_ASSERT(!mNextPageContentFramePageName, "PageContentFrame page name was already set");
mNextPageContentFramePageName = aPageName;
}
// This returns the outermost frame for the root element.
nsContainerFrame* GetRootElementFrame() { return mRootElementFrame; } // This returns the frame for the root element that does not // have a pseudo-element style
nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
nsPageSequenceFrame* GetPageSequenceFrame() { return mPageSequenceFrame; } // Returns the outermost canvas frame. There's usually one per document, but // if but if we're in printing / paginated mode we might have multiple: one // per page plus the background one.
nsCanvasFrame* GetCanvasFrame() { return mCanvasFrame; } // Get the frame that is the parent of the root element's frame.
nsCanvasFrame* GetDocElementContainingBlock() { return mDocElementContainingBlock;
}
#ifdefined(ACCESSIBILITY) || defined(MOZ_LAYOUT_DEBUGGER) // Exposed only for nsLayoutUtils::GetMarkerSpokenText and // nsLayoutDebuggingTools to use.
mozilla::ContainStyleScopeManager& GetContainStyleScopeManager() { return mContainStyleScopeManager;
} #endif
private: struct FrameConstructionItem; class FrameConstructionItemList;
enumclass ItemFlag : uint8_t { // Allow page-break before and after items to be created if the // style asks for them.
AllowPageBreak,
IsGeneratedContent,
IsWithinSVGText, // The item allows items to be created for SVG <textPath> children.
AllowTextPathChild, // The item is content created by an nsIAnonymousContentCreator frame.
IsAnonymousContentCreatorContent, // The item will be the rendered legend of a <fieldset>.
IsForRenderedLegend, // This will be an outside ::marker.
IsForOutsideMarker,
};
using ItemFlags = mozilla::EnumSet<ItemFlag>;
// Add the frame construction items for the given aContent and aParentFrame // to the list. This might add more than one item in some rare cases. // If aSuppressWhiteSpaceOptimizations is true, optimizations that // may suppress the construction of white-space-only text frames // must be skipped for these items and items around them. void AddFrameConstructionItems(nsFrameConstructorState& aState,
nsIContent* aContent, bool aSuppressWhiteSpaceOptimizations, const ComputedStyle& aParentStyle, const InsertionPoint& aInsertion,
FrameConstructionItemList& aItems,
ItemFlags = {});
// Helper method for AddFrameConstructionItems etc. // Unsets the need-frame/restyle bits on aContent. // return true iff we should attempt to create frames for aContent. bool ShouldCreateItemsForChild(nsFrameConstructorState& aState,
nsIContent* aContent,
nsContainerFrame* aParentFrame);
// Construct the frames for the document element. This can return null if the // document element is display:none, or if it's an SVG element that's not // <svg>, etc.
nsIFrame* ConstructDocElementFrame(Element* aDocElement);
// Set up our mDocElementContainingBlock correctly for the given root // content. void SetUpDocElementContainingBlock(nsIContent* aDocElement);
// aParentFrame may be null; this method doesn't use it directly in any case. void CreateGeneratedContentItem(nsFrameConstructorState& aState,
nsContainerFrame* aParentFrame,
Element& aOriginatingElement, ComputedStyle&,
PseudoStyleType aPseudoElement,
FrameConstructionItemList& aItems,
ItemFlags aExtraFlags = {});
// This method is called by ContentAppended() and ContentRangeInserted() when // appending flowed frames to a parent's principal child list. It handles the // case where the parent is the trailing inline of an ib-split or is the last // continuation of a ::-moz-column-content in an nsColumnSetFrame. // // This method can change aFrameList: it can chop off the beginning and put it // in aParentFrame while either putting the remainder into an ib-split sibling // of aParentFrame or creating aParentFrame's column-span siblings for the // remainder. // // aPrevSibling must be the frame after which aFrameList is to be placed on // aParentFrame's principal child list. It may be null if aFrameList is being // added at the beginning of the child list. void AppendFramesToParent(nsFrameConstructorState& aState,
nsContainerFrame* aParentFrame,
nsFrameList& aFrameList, nsIFrame* aPrevSibling, bool aIsRecursiveCall = false);
private: /* An enum of possible parent types for anonymous table or ruby object
construction */ enum ParentType {
eTypeBlock = 0, /* This includes all non-table-related frames */
eTypeRow,
eTypeRowGroup,
eTypeColGroup,
eTypeTable,
eTypeRuby,
eTypeRubyBase,
eTypeRubyBaseContainer,
eTypeRubyText,
eTypeRubyTextContainer,
eParentTypeCount
};
/* 4 bits is enough to handle our ParentType values */ #define FCDATA_PARENT_TYPE_OFFSET 28 /* Macro to get the desired parent type out of an mBits member of
FrameConstructionData */ #define FCDATA_DESIRED_PARENT_TYPE(_bits) \
ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET) /* Macro to create FrameConstructionData bits out of a desired parent type */ #define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type) \
(((uint32_t)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
/* Get the parent type that aParentFrame has. */ static ParentType GetParentType(nsIFrame* aParentFrame) { return GetParentType(aParentFrame->Type());
}
/* Get the parent type for the given LayoutFrameType */ static ParentType GetParentType(mozilla::LayoutFrameType aFrameType);
/* A constructor function that just creates an nsIFrame object. The caller isresponsibleforinitializingtheobject,addingittoframelists, constructingframesforthechildren,etc.
@paramPresShellthepresshellwhosearenashouldbeusedtoallocate theframe.
@param ComputedStyle the style to use for the frame. */ using FrameCreationFunc = nsIFrame* (*)(PresShell*, ComputedStyle*); using ContainerFrameCreationFunc = nsContainerFrame* (*)(PresShell*,
ComputedStyle*); using BlockFrameCreationFunc = nsBlockFrame* (*)(PresShell*, ComputedStyle*);
/* A function that can be used to get a FrameConstructionData. Such afunctionisallowedtoreturnnull.
/* A constructor function that's used for complicated construction tasks. Thisisexpectedtocreatethenewframe,initializeit,addwhatever needstobeaddedtoaFrameList(XXXbzisthatreallynecessary?Could calleradd?Mighttherebecaseswhenthereturnedframeorits placeholderisnotthethingthatendsupinaFrameList?Ifnot,would itbesafetodotheaddintotheframeconstructionstateafter processingkids?Lookintothisasafollowup!),processchildrenas needed,etc.ItisNOTexpectedtodealwithsettingtheframeonthe content.
/* Bits that modify the way a FrameConstructionData is handled */
/* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not besetastheprimaryframeonthecontentnode.Thisshouldonlybeused inveryrarecaseswhenwecreatemorethanoneframeforagivencontent
node. */ #define FCDATA_SKIP_FRAMESET 0x1 /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the FrameConstructionDataisagetterfunctionthatcanbeusedtogetthe
actual FrameConstructionData to use. */ #define FCDATA_FUNC_IS_DATA_GETTER 0x2 /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData hasanmFullConstructor.Inthiscase,thereisnorelevantmDataor
mFunc */ #define FCDATA_FUNC_IS_FULL_CTOR 0x4 /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to floatorbeabsolutelypositioned.Thiscanalsobeusedwith FCDATA_FUNC_IS_FULL_CTORtoindicatewhatthefull-constructor
function will do. */ #define FCDATA_DISALLOW_OUT_OF_FLOW 0x8 /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a nullabsolutecontainingblockbeforeprocessingchildrenforthis frame.Ifthisisnotset,theframewillbepushedasthe
absolute containing block as needed, based on its style */ #define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10 /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame willbewrappedinblocks.ThisisonlyusableforMathMLatthe
moment. */ #define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20 /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the content.Ifthisbitisset,nothingelseinthestructneedstobe
set. */ #define FCDATA_SUPPRESS_FRAME 0x40 /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
a scrollframe if its overflow type so requires. */ #define FCDATA_MAY_NEED_SCROLLFRAME 0x80 /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
absolute containing block, no matter what its style says. */ #define FCDATA_SKIP_ABSPOS_PUSH 0x200 /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated contentwhenprocessingkidsofthisframe.Thisshouldnotbeusedwith
FCDATA_FUNC_IS_FULL_CTOR */ #define FCDATA_DISALLOW_GENERATED_CONTENT 0x400 /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of table-relatedthingandweshouldnotattempttofetchatable-cellparent
for it if it's inside another table-related frame. */ #define FCDATA_IS_TABLE_PART 0x800 /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS
inline box. */ #define FCDATA_IS_INLINE 0x1000 /* If FCDATA_IS_LINE_PARTICIPANT is set, the frame is something that will
return true for IsLineParticipant() */ #define FCDATA_IS_LINE_PARTICIPANT 0x2000 /* If FCDATA_IS_LINE_BREAK is set, the frame is something that will
induce a line break boundary before and after itself. */ #define FCDATA_IS_LINE_BREAK 0x4000 /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing childrenofablock(i.e.allow::first-letter/line).
This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */ #define FCDATA_ALLOW_BLOCK_STYLES 0x8000 /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant FrameConstructionIteminsteadoftryingtoprocessthecontent'schildren. ThiscanbeusedwithorwithoutFCDATA_FUNC_IS_FULL_CTOR.
The child items might still need table pseudo processing. */ #define FCDATA_USE_CHILD_ITEMS 0x10000 // 0x200000 is free /* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a blockformattingcontextwrapperaroundthekidsofthisframe usingtheFrameConstructionData'smPseudoAtomforitsanonymous
box type. */ #define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000 /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of
an SVG text frame. */ #define FCDATA_IS_SVG_TEXT 0x80000 /** *WhetherthekidsofthisFrameConstructionDatashouldbeflaggedashaving *awrapperanonboxparent.Thisshouldonlybesetif *FCDATA_USE_CHILD_ITEMSisset.
*/ #define FCDATA_IS_WRAPPER_ANON_BOX 0x400000
/* Structure representing information about how a frame should be
constructed. */ struct FrameConstructionData { // We have exactly one of three types of functions, so use a union for // better cache locality. union Func {
FrameCreationFunc mCreationFunc;
FrameConstructionDataGetter mDataGetter;
FrameFullConstructor mFullConstructor;
explicit constexpr Func(FrameCreationFunc aFunc) : mCreationFunc(aFunc) {} explicit constexpr Func(FrameConstructionDataGetter aDataGetter)
: mDataGetter(aDataGetter) {} explicit constexpr Func(FrameFullConstructor aCtor)
: mFullConstructor(aCtor) {}
} mFunc; // Flag bits that can modify the way the construction happens const uint32_t mBits = 0; // For cases when FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, the // anonymous box type to use for that wrapper.
PseudoStyleType const mAnonBoxPseudo = PseudoStyleType::NotPseudo;
/* Structure representing a mapping of an atom to a FrameConstructionData. Thiscanbeusedwithnon-staticatoms,assumingthatthensAtom*is storedsomewherethatthisstructcanpointto(thatis,astatic
nsAtom*) and that it's allocated before the struct is ever used. */ struct FrameConstructionDataByTag { const nsStaticAtom* const mTag; const FrameConstructionData mData;
};
/* Structure representing a mapping of an integer to a
FrameConstructionData. There are no magic integer values here. */ struct FrameConstructionDataByInt { /* Could be used for display or whatever else */ const int32_t mInt; const FrameConstructionData mData;
};
/* Structure that has a FrameConstructionData and style pseudo-type
for a table pseudo-frame */ struct PseudoParentData { const FrameConstructionData mFCData;
mozilla::PseudoStyleType const mPseudoType;
}; /* Array of such structures that we use to properly construct table
pseudo-frames as needed */ staticconst PseudoParentData sPseudoParentData[eParentTypeCount];
// aParentFrame might be null. If it is, that means it was an inline frame. staticconst FrameConstructionData* FindTextData(const Text&,
nsIFrame* aParentFrame); const FrameConstructionData* FindElementData(const Element&, ComputedStyle&,
nsIFrame* aParentFrame,
ItemFlags aFlags); const FrameConstructionData* FindElementTagData(const Element&,
ComputedStyle&,
nsIFrame* aParentFrame,
ItemFlags aFlags);
/* A function that takes an integer, content, style, and array of FrameConstructionDataByIntsandfindstheappropriateframeconstruction datatouseandreturnsit.Thiscanreturnnullifnoneoftheintegers matchorifthematchingintegerhasaFrameConstructionDataGetterthat
returns null. */ staticconst FrameConstructionData* FindDataByInt(
int32_t aInt, const Element&, ComputedStyle&, const FrameConstructionDataByInt* aDataPtr, uint32_t aDataLength);
/* A class representing a list of FrameConstructionItems. Instances of this classareonlycreatedasAutoFrameConstructionItemList,orasamember
of FrameConstructionItem. */ class FrameConstructionItemList { public: void Reset(nsCSSFrameConstructor* aFCtor) {
Destroy(aFCtor); this->~FrameConstructionItemList(); new (this) FrameConstructionItemList();
}
// aSuppressWhiteSpaceOptimizations is true if optimizations that // skip constructing whitespace frames for this item or items // around it cannot be performed. // Also, the return value is always non-null, thanks to infallible 'new'.
FrameConstructionItem* AppendItem(
nsCSSFrameConstructor* aFCtor, const FrameConstructionData* aFCData,
nsIContent* aContent, already_AddRefed<ComputedStyle> aComputedStyle, bool aSuppressWhiteSpaceOptimizations) {
FrameConstructionItem* item = new (aFCtor)
FrameConstructionItem(aFCData, aContent, std::move(aComputedStyle),
aSuppressWhiteSpaceOptimizations);
mItems.insertBack(item);
++mItemCount;
++mDesiredParentCounts[item->DesiredParentType()]; return item;
}
// Arguments are the same as AppendItem().
FrameConstructionItem* PrependItem(
nsCSSFrameConstructor* aFCtor, const FrameConstructionData* aFCData,
nsIContent* aContent, already_AddRefed<ComputedStyle> aComputedStyle, bool aSuppressWhiteSpaceOptimizations) {
FrameConstructionItem* item = new (aFCtor)
FrameConstructionItem(aFCData, aContent, std::move(aComputedStyle),
aSuppressWhiteSpaceOptimizations);
mItems.insertFront(item);
++mItemCount;
++mDesiredParentCounts[item->DesiredParentType()]; return item;
}
// Skip over all items that want the given parent type. Return whether // the iterator is done after doing that. The iterator must not be done // when this is called. inlinebool SkipItemsWantingParentType(ParentType aParentType);
// Skip over all items that want a parent type different from the given // one. Return whether the iterator is done after doing that. The // iterator must not be done when this is called. inlinebool SkipItemsNotWantingParentType(ParentType aParentType);
// Skip over non-replaced inline frames and positioned frames. // Return whether the iterator is done after doing that. // The iterator must not be done when this is called. inlinebool SkipItemsThatNeedAnonFlexOrGridItem( const nsFrameConstructorState& aState, bool aIsWebkitBox);
// Skip to the first frame that is a non-replaced inline or is // positioned. Return whether the iterator is done after doing that. // The iterator must not be done when this is called. inlinebool SkipItemsThatDontNeedAnonFlexOrGridItem( const nsFrameConstructorState& aState, bool aIsWebkitBox);
// Skip over all items that do not want a ruby parent. Return whether // the iterator is done after doing that. The iterator must not be done // when this is called. inlinebool SkipItemsNotWantingRubyParent();
// Skip over whitespace. Return whether the iterator is done after doing // that. The iterator must not be done, and must be pointing to a // whitespace item when this is called. inlinebool SkipWhitespace(nsFrameConstructorState& aState);
// Remove the item pointed to by this iterator from its current list and // Append it to aTargetList. This iterator is advanced to point to the // next item in its list. aIter must not be done. aTargetList must not // be the list this iterator is iterating over.. void AppendItemToList(FrameConstructionItemList& aTargetList);
// As above, but moves all items starting with this iterator until we // get to aEnd; the item pointed to by aEnd is not stolen. This method // might have optimizations over just looping and doing StealItem for // some special cases. After this method returns, this iterator will // point to the item aEnd points to now; aEnd is not modified. // aTargetList must not be the list this iterator is iterating over. void AppendItemsToList(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd,
FrameConstructionItemList& aTargetList);
// Insert aItem in this iterator's list right before the item pointed to // by this iterator. After the insertion, this iterator will continue to // point to the item it now points to (the one just after the // newly-inserted item). This iterator is allowed to be done; in that // case this call just appends the given item to the list. void InsertItem(FrameConstructionItem* aItem);
// Delete the items between this iterator and aEnd, including the item // this iterator currently points to but not including the item pointed // to by aEnd. When this returns, this iterator will point to the same // item as aEnd. This iterator must not equal aEnd when this method is // called. void DeleteItemsTo(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd);
// Adjust our various counts for aItem being added or removed. aDelta // should be either +1 or -1 depending on which is happening. void AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta);
mozilla::LinkedList<FrameConstructionItem> mItems;
uint32_t mInlineCount;
uint32_t mBlockCount;
uint32_t mItemCount;
uint32_t mDesiredParentCounts[eParentTypeCount]; // True if there is guaranteed to be a line boundary before the // frames created by these items bool mLineBoundaryAtStart; // True if there is guaranteed to be a line boundary after the // frames created by these items bool mLineBoundaryAtEnd; // True if the parent is guaranteed to have no shadow tree. bool mParentHasNoShadowDOM;
};
/* A struct representing a list of FrameConstructionItems on the stack. */ struct MOZ_RAII AutoFrameConstructionItemList final
: public FrameConstructionItemList { template <typename... Args> explicit AutoFrameConstructionItemList(nsCSSFrameConstructor* aFCtor,
Args&&... args)
: FrameConstructionItemList(std::forward<Args>(args)...),
mFCtor(aFCtor) {
MOZ_ASSERT(mFCtor);
}
~AutoFrameConstructionItemList() { Destroy(mFCtor); }
/* A struct representing an item for which frames might need to be *constructed.Thiscontainsalltheinformationneededtoconstructthe *frameotherthantheparentframeandwhateverwouldbestoredinthe *frameconstructorstate.Youprobablywanttouse
* AutoFrameConstructionItem instead of this struct. */ struct FrameConstructionItem final
: public mozilla::LinkedListElement<FrameConstructionItem> {
FrameConstructionItem(const FrameConstructionData* aFCData,
nsIContent* aContent,
already_AddRefed<ComputedStyle> aComputedStyle, bool aSuppressWhiteSpaceOptimizations)
: mFCData(aFCData),
mContent(aContent),
mComputedStyle(std::move(aComputedStyle)),
mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
mIsText(false),
mIsGeneratedContent(false),
mIsAllInline(false),
mIsBlock(false),
mIsRenderedLegend(false) {
MOZ_COUNT_CTOR(FrameConstructionItem);
}
// Not allocated from the general heap - instead, use the new/Delete APIs // that take a nsCSSFrameConstructor* (which manages our arena allocation). void* operatornew(size_t) = delete; void* operatornew[](size_t) = delete; #ifdef _MSC_VER /* Visual Studio */ private: voidoperatordelete(void*) { MOZ_CRASH("FrameConstructionItem::delete"); }
// Indicates whether (when in a flex or grid container) this item needs // to be wrapped in an anonymous block. (Note that we implement // -webkit-box/-webkit-inline-box using our standard flexbox frame class, // but we use different rules for what gets wrapped. The aIsWebkitBox // parameter here tells us whether to use those different rules.) bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState, bool aIsWebkitBox);
// Don't call this unless the frametree really depends on the answer! // Especially so for generated content, where we don't want to reframe // things. bool IsWhitespace(nsFrameConstructorState& aState) const;
// Child frame construction items.
FrameConstructionItemList mChildItems;
// The FrameConstructionData to use. const FrameConstructionData* mFCData; // The nsIContent node to use when initializing the new frame.
nsIContent* mContent; // The style to use for creating the new frame.
RefPtr<ComputedStyle> mComputedStyle; // Whether optimizations to skip constructing textframes around // this content need to be suppressed. bool mSuppressWhiteSpaceOptimizations : 1; // Whether this is a text content item. bool mIsText : 1; // Whether this is a generated content container. // If it is, mContent is a strong pointer. bool mIsGeneratedContent : 1; // Whether construction from this item will create only frames that are // IsInlineOutside() in the principal child list. This is not precise, but // conservative: if true the frames will really be inline, whereas if false // they might still all be inline. bool mIsAllInline : 1; // Whether construction from this item will create only frames that are // IsBlockOutside() in the principal child list. This is not precise, but // conservative: if true the frames will really be blocks, whereas if false // they might still be blocks (and in particular, out-of-flows that didn't // find a containing block). bool mIsBlock : 1; // Whether this item is the rendered legend of a <fieldset> bool mIsRenderedLegend : 1;
private: // Not allocated from the stack!
~FrameConstructionItem() {
MOZ_COUNT_DTOR(FrameConstructionItem);
MOZ_ASSERT(mChildItems.IsEmpty(), "leaking");
}
};
private: // ConstructFieldSetFrame puts the new frame in aFrameList and // handles the kids of the fieldset
nsIFrame* ConstructFieldSetFrame(nsFrameConstructorState& aState,
FrameConstructionItem& aItem,
nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
nsFrameList& aFrameList);
// If aPossibleTextContent is a text node and doesn't have a frame, append a // frame construction item for it to aItems. void AddTextItemIfNeeded(nsFrameConstructorState& aState, const ComputedStyle& aParentStyle, const InsertionPoint& aInsertion,
nsIContent* aPossibleTextContent,
FrameConstructionItemList& aItems);
// If aContent is a text node and doesn't have a frame, try to create a frame // for it. void ReframeTextIfNeeded(nsIContent* aContent);
// Function to find FrameConstructionData for aElement. Will return // null if aElement is not HTML. // aParentFrame might be null. If it is, that means it was an // inline frame. staticconst FrameConstructionData* FindHTMLData(const Element&,
nsIFrame* aParentFrame,
ComputedStyle&); // HTML data-finding helper functions staticconst FrameConstructionData* FindSelectData(const Element&,
ComputedStyle&); staticconst FrameConstructionData* FindImgData(const Element&,
ComputedStyle&); staticconst FrameConstructionData* FindHTMLButtonData(const Element&,
ComputedStyle&); staticconst FrameConstructionData* FindGeneratedImageData(const Element&,
ComputedStyle&); staticconst FrameConstructionData* FindImgControlData(const Element&,
ComputedStyle&); staticconst FrameConstructionData* FindSearchControlData(const Element&,
ComputedStyle&); staticconst FrameConstructionData* FindInputData(const Element&,
ComputedStyle&); staticconst FrameConstructionData* FindObjectData(const Element&,
ComputedStyle&); staticconst FrameConstructionData* FindCanvasData(const Element&,
ComputedStyle&); // <details> always creates a block per spec *if* the about:config pref // 'layout.details.force-block-layout' is set to 'true'. This is a legacy // restriction (based on old spec-text) and we're planning to remove it. staticconst FrameConstructionData* FindDetailsData(const Element&,
ComputedStyle&);
/* Construct a frame from the given FrameConstructionItem. This function willhandleaddingtheframetoframelists,processingchildren,setting theframeastheprimaryframefortheitem'scontent,andsoforth.
// The guts of AddFrameConstructionItems // aParentFrame might be null. If it is, that means it was an // inline frame. void AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
nsIContent* aContent,
nsContainerFrame* aParentFrame, bool aSuppressWhiteSpaceOptimizations,
ComputedStyle*, ItemFlags,
FrameConstructionItemList& aItems);
// Function to find FrameConstructionData for an element. Will return // null if the element is not MathML. staticconst FrameConstructionData* FindMathMLData(const Element&,
ComputedStyle&);
// Function to find FrameConstructionData for an element. Will return // null if the element is not XUL. staticconst FrameConstructionData* FindXULTagData(const Element&,
ComputedStyle&); // XUL data-finding helper functions and structures staticconst FrameConstructionData* FindXULLabelOrDescriptionData( const Element&, ComputedStyle&);
// Not static because it does PropagateScrollToViewport. If this // changes, make this static. const FrameConstructionData* FindDisplayData(const nsStyleDisplay&, const Element&);
// Construct a scrollable block with an already created subclass of // ScrollContainerFrame, or nullptr for a plain ScrollContainerFrame. void ConstructScrollableBlockWithScrollContainer(
nsFrameConstructorState& aState, FrameConstructionItem& aItem,
nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
nsFrameList& aFrameList, nsContainerFrame*&);
private: // Build a scroll container frame, and wrap the scrolled frame. The // hierarchy will look like this: // // ScrollContainerFrame // ^ // | // Frame (scrolled frame you passed in as aScrolledFrame) // // @param aContent the content node of the child to wrap. // // @param aContentStyle the style that has already been resolved for the // content being passed in. // // @param aScrolledFrame The frame of the content to wrap. This should not be // initialized (i.e. Init() should not yet have been called). This method will // initialize it with a scrolled pseudo and no nsIContent. The content will be // attached to the scroll container frame that this function returns. // // @param aParentFrame The geometric parent to attach the scroll container // frame to. // // @param aNewFrame [in/out] If this is not nullptr, we will just use it as // the scroll container frame, rather than creating a new scroll container // frame. Otherwise (i.e. if it's nullptr), we'll create a new scroll // container frame, and return it by reference via this param. void BuildScrollContainerFrame(nsFrameConstructorState& aState,
nsIContent* aContent,
ComputedStyle* aContentStyle,
nsIFrame* aScrolledFrame,
nsContainerFrame* aParentFrame,
nsContainerFrame*& aNewFrame);
// Completes the building of the scroll container frame. // Creates a view for the scrolledframe and makes it the child of the // scroll container frame. void FinishBuildingScrollContainerFrame(
nsContainerFrame* aScrollContainerFrame, nsIFrame* aScrolledFrame);
// If removal of aFrame from the frame tree requires reconstruction of some // containing block (either of aFrame or of its parent) due to {ib} splits or // table pseudo-frames, recreate the relevant frame subtree. The return value // indicates whether this happened. aFrame must be the result of a // GetPrimaryFrame() call on a content node (which means its parent is also // not null). bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame);
// Check whether a given block has first-letter style. Make sure to // only pass in blocks! And don't pass in null either. bool HasFirstLetterStyle(nsIFrame* aBlockFrame);
// |aContentParentFrame| should be null if it's really the same as // |aParentFrame|. // @param aFrameList where we want to put the block in case it's in-flow. // @param aNewFrame an in/out parameter. On input it is the block to be // constructed. On output it is reset to the outermost // frame constructed (e.g. if we need to wrap the block in an // nsColumnSetFrame. // @param aParentFrame is the desired parent for the (possibly wrapped) // block // @param aContentParent is the parent the block would have if it // were in-flow // @param aPositionedFrameForAbsPosContainer if non-null, then the new // block should be an abs-pos container and aPositionedFrameForAbsPosContainer // is the frame whose style is making this block an abs-pos container. void ConstructBlock(nsFrameConstructorState& aState, nsIContent* aContent,
nsContainerFrame* aParentFrame,
nsContainerFrame* aContentParentFrame,
ComputedStyle* aComputedStyle,
nsContainerFrame** aNewFrame, nsFrameList& aFrameList,
nsIFrame* aPositionedFrameForAbsPosContainer);
// Build the initial column hierarchy around aColumnContent. This function // should be called before constructing aColumnContent's children. // // Before calling FinishBuildingColumns(), we need to create column-span // siblings for aColumnContent's children. Caller can use helpers // MayNeedToCreateColumnSpanSiblings() and CreateColumnSpanSiblings() to // check whether column-span siblings might need to be created and to do // the actual work of creating them if they're needed. // // @param aColumnContent the block that we're wrapping in a ColumnSet. On // entry to this function it has aComputedStyle as its style. After // this function returns, aColumnContent has a ::-moz-column-content // anonymous box style. // @param aParentFrame the parent frame we want to use for the // ColumnSetWrapperFrame (which would have been the parent of // aColumnContent if we were not creating a column hierarchy). // @param aContent is the content of the aColumnContent. // @return the outermost ColumnSetWrapperFrame.
nsBlockFrame* BeginBuildingColumns(nsFrameConstructorState& aState,
nsIContent* aContent,
nsContainerFrame* aParentFrame,
nsContainerFrame* aColumnContent,
ComputedStyle* aComputedStyle);
// Complete building the column hierarchy by first wrapping each // non-column-span child in aChildList in a ColumnSetFrame (skipping // column-span children), and reparenting them to have aColumnSetWrapper // as their parent. // // @param aColumnSetWrapper is the frame returned by // BeginBuildingColumns(), and is the grandparent of aColumnContent. // @param aColumnContent is the block frame passed into // BeginBuildingColumns() // @param aColumnContentSiblings contains the aColumnContent's siblings, which // are the column spanners and aColumnContent's continuations returned // by CreateColumnSpanSiblings(). It'll become empty after this call. void FinishBuildingColumns(nsFrameConstructorState& aState,
nsContainerFrame* aColumnSetWrapper,
nsContainerFrame* aColumnContent,
nsFrameList& aColumnContentSiblings);
// Return whether aBlockFrame's children in aChildList, which might // contain column-span, may need to be wrapped in // ::moz-column-span-wrapper and promoted as aBlockFrame's siblings. // // @param aBlockFrame is the parent of the frames in aChildList. // // Note: This a check without actually looking into each frame in the // child list, so it may return false positive. bool MayNeedToCreateColumnSpanSiblings(nsContainerFrame* aBlockFrame, const nsFrameList& aChildList);
// Wrap consecutive runs of column-span kids and runs of non-column-span // kids in blocks for aInitialBlock's children. // // @param aInitialBlock is the parent of those frames in aChildList. // @param aChildList must begin with a column-span kid. It becomes empty // after this call. // @param aPositionedFrame if non-null, it's the frame whose style is making // aInitialBlock an abs-pos container. // // Return those wrapping blocks in nsFrameList.
nsFrameList CreateColumnSpanSiblings(nsFrameConstructorState& aState,
nsContainerFrame* aInitialBlock,
nsFrameList& aChildList,
nsIFrame* aPositionedFrame);
// Reconstruct the multi-column containing block of aParentFrame when we want // to insert aFrameList into aParentFrame immediately after aPrevSibling but // cannot fix the frame tree because aFrameList contains some column-spans. // // Note: This method is intended to be called as a helper in ContentAppended() // and ContentRangeInserted(). It assumes aState was set up locally and wasn't // used to construct any ancestors of aParentFrame in aFrameList. // // @param aParentFrame the to-be parent frame for aFrameList. // @param aFrameList the frames to be inserted. It will be cleared if we need // reconstruction. // @param aPrevSibling the position where the frames in aFrameList are going // to be inserted. Nullptr means aFrameList is being inserted at // the beginning. // @return true if the multi-column containing block of aParentFrame is // reconstructed; false otherwise. bool MaybeRecreateForColumnSpan(nsFrameConstructorState& aState,
nsContainerFrame* aParentFrame,
nsFrameList& aFrameList,
nsIFrame* aPrevSibling);
// Determine whether we need to wipe out aFrame (the insertion parent) and // rebuild the entire subtree when we insert or append new content under // aFrame. // // This is similar to WipeContainingBlock(), but is called // before constructing any frame construction items. Any container frames // which need reframing regardless of the content inserted or appended can add // a check in this method. // // @return true if we reconstructed the insertion parent frame; false // otherwise bool WipeInsertionParent(nsContainerFrame* aFrame);
// Determine whether we need to wipe out what we just did and start over // because we're doing something like adding block kids to an inline frame // (and therefore need an {ib} split). aPrevSibling must be correct, even in // aIsAppend cases. Passing aIsAppend false even when an append is happening // is ok in terms of correctness, but can lead to unnecessary reframing. // // @return true if we reconstructed the containing block, false otherwise. bool WipeContainingBlock(nsFrameConstructorState& aState,
nsIFrame* aContainingBlock, nsIFrame* aFrame,
FrameConstructionItemList& aItems, bool aIsAppend,
nsIFrame* aPrevSibling);
// Special remove method for those pesky floating first-letter frames void RemoveFloatingFirstLetterFrames(PresShell* aPresShell,
nsIFrame* aBlockFrame);
// Capture state for the frame tree rooted at the frame associated with the // content object, aContent void CaptureStateForFramesOf(nsIContent* aContent,
nsILayoutHistoryState* aHistoryState);
//----------------------------------------
// Methods support :first-line style
// This method chops the initial inline-outside frames out of aFrameList. // If aLineFrame is non-null, it appends them to that frame. Otherwise, it // creates a new line frame, sets the inline frames as its initial child // list, and inserts that line frame at the front of what's left of // aFrameList. In both cases, the kids are reparented to the line frame. // After this call, aFrameList holds the frames that need to become kids of // the block (possibly including line frames). void WrapFramesInFirstLineFrame(nsFrameConstructorState& aState,
nsIContent* aBlockContent,
nsContainerFrame* aBlockFrame,
nsFirstLineFrame* aLineFrame,
nsFrameList& aFrameList);
// Handle the case when a block with first-line style is appended to (by // possibly calling WrapFramesInFirstLineFrame as needed). void AppendFirstLineFrames(nsFrameConstructorState& aState,
nsIContent* aContent,
nsContainerFrame* aBlockFrame,
nsFrameList& aFrameList);
// Helper for the implementation of FindSibling. // // Beware that this function does mutate the iterator. template <SiblingDirection>
nsIFrame* FindSiblingInternal(mozilla::dom::FlattenedChildIterator&);
// An alias of FindSibling<SiblingDirection::Forward>.
nsIFrame* FindNextSibling(const mozilla::dom::FlattenedChildIterator& aIter); // An alias of FindSibling<SiblingDirection::Backward>.
nsIFrame* FindPreviousSibling( const mozilla::dom::FlattenedChildIterator& aIter);
// Given a potential first-continuation sibling frame, return the // appropriate continuation the new frame should be inserted next to.
nsIFrame* AdjustSiblingFrame(nsIFrame* aSibling, SiblingDirection);
// Find the right previous sibling for an insertion. This also updates the // parent frame to point to the correct continuation of the parent frame to // use, and returns whether this insertion is to be treated as an append. // aChild is the child being inserted. // It is the callers' responsibility to check whether a range insert is safe // with regards to fieldsets / tables.
nsIFrame* GetInsertionPrevSibling(InsertionPoint* aInsertion, // inout
nsIContent* aChild, bool* aIsAppend);
private: // For allocating FrameConstructionItems from the mFCItemPool arena. friendstruct FrameConstructionItem; void* AllocateFCItem(); void FreeFCItem(FrameConstructionItem*);
mozilla::dom::Document* mDocument; // Weak ref
// See the comment at the start of ConstructRootFrame for more details // about the following frames.
// This is just the outermost frame for the root element.
nsContainerFrame* mRootElementFrame = nullptr; // This is the frame for the root element that has no pseudo-element style.
nsIFrame* mRootElementStyleFrame = nullptr; // This is the containing block that contains the root element --- // the real "initial containing block" according to CSS 2.1.
nsCanvasFrame* mDocElementContainingBlock = nullptr; // This is usually mDocElementContainingBlock, except when printing, where it // is the canvas frame that is under all the printed pages.
nsCanvasFrame* mCanvasFrame = nullptr;
nsPageSequenceFrame* mPageSequenceFrame = nullptr;
// FrameConstructionItem arena + list of freed items available for re-use.
mozilla::ArenaAllocator<4096, 8> mFCItemPool;
// This indicates what page name to use for the next nsPageContentFrame. // Set when CSS named pages cause a breakpoint. // This does not apply to the first page content frame, which has its name // set by nsPageContentFrame::EnsurePageName() during first reflow.
RefPtr<const nsAtom> mNextPageContentFramePageName;
// The layout state from our history entry (to restore scroll positions and // such from history), or a new one if there was none (so we can store scroll // positions and such during reframe). // // FIXME(bug 1397239): This can leak some state sometimes for the lifetime of // the frame constructor, which is not great.
nsCOMPtr<nsILayoutHistoryState> mFrameTreeState;
};
#endif/* nsCSSFrameConstructor_h_ */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.85 Sekunden
(vorverarbeitet am 2026-09-30)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.