--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -7202,18 +7202,17 @@ nsCSSFrameConstructor::ReframeTextIfNeed
!aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
// Not text, or not suppressed due to being all-whitespace (if it
// were being suppressed, it would have the
// NS_CREATE_FRAME_IF_NON_WHITESPACE flag)
return;
}
NS_ASSERTION(!aContent->GetPrimaryFrame(),
"Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
- const bool allowLazyConstruction = true;
- ContentInserted(aParentContent, aContent, nullptr, allowLazyConstruction);
+ ContentInserted(aParentContent, aContent, nullptr, LazyConstructionAllowed::Yes);
}
#ifdef DEBUG
void
nsCSSFrameConstructor::CheckBitsForLazyFrameConstruction(nsIContent* aParent)
{
// If we hit a node with no primary frame, or the NODE_NEEDS_FRAME bit set
// we want to assert, but leaf frames that process their own children and may
@@ -7376,26 +7375,26 @@ nsCSSFrameConstructor::CreateNeededFrame
inRun = true;
firstChildInRun = child;
}
} else {
if (inRun) {
inRun = false;
// generate a ContentRangeInserted for [startOfRun,i)
ContentRangeInserted(aContent, firstChildInRun, child, nullptr,
- false, // aAllowLazyConstruction
+ LazyConstructionAllowed::No,
true, // aForReconstruction
&aTreeMatchContext);
}
}
}
if (inRun) {
ContentAppended(aContent, firstChildInRun,
- false, // aAllowLazyConstruction
+ LazyConstructionAllowed::No,
true, // aForReconstruction
&aTreeMatchContext);
}
// Now descend.
FlattenedChildIterator iter(aContent);
for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
if (child->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
@@ -7434,17 +7433,17 @@ nsCSSFrameConstructor::CreateNeededFrame
EndUpdate();
}
}
void
nsCSSFrameConstructor::IssueSingleInsertNofications(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed aLazyConstructionAllowed,
bool aForReconstruction)
{
for (nsIContent* child = aStartChild;
child != aEndChild;
child = child->GetNextSibling()) {
if ((child->GetPrimaryFrame() || GetDisplayNoneStyleFor(child) ||
GetDisplayContentsStyleFor(child))
#ifdef MOZ_XUL
@@ -7455,26 +7454,26 @@ nsCSSFrameConstructor::IssueSingleInsert
) {
// Already have a frame or undisplayed entry for this content; a
// previous ContentRangeInserted in this loop must have reconstructed
// its insertion parent. Skip it.
continue;
}
// Call ContentRangeInserted with this node.
ContentRangeInserted(aContainer, child, child->GetNextSibling(),
- mTempFrameTreeState, aAllowLazyConstruction,
+ mTempFrameTreeState, aLazyConstructionAllowed,
aForReconstruction, nullptr);
}
}
nsCSSFrameConstructor::InsertionPoint
nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed aLazyConstructionAllowed,
bool aForReconstruction)
{
// See if we have an XBL insertion point. If so, then that's our
// real parent frame; if not, then the frame hasn't been built yet
// and we just bail.
InsertionPoint insertionPoint = GetInsertionPoint(aContainer, nullptr);
if (!insertionPoint.mParentFrame && !insertionPoint.mMultiple) {
return insertionPoint; // Don't build the frames.
@@ -7514,17 +7513,17 @@ nsCSSFrameConstructor::GetRangeInsertion
// If we have multiple insertion points or if we have an insertion point
// and the operation is not a true append or if the insertion point already
// has explicit children, then we must fall back.
if (insertionPoint.mMultiple || aEndChild != nullptr || childCount > 0) {
// Now comes the fun part. For each inserted child, make a
// ContentInserted call as if it had just gotten inserted and
// let ContentInserted handle the mess.
IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
- aAllowLazyConstruction, aForReconstruction);
+ aLazyConstructionAllowed, aForReconstruction);
insertionPoint.mParentFrame = nullptr;
}
}
return insertionPoint;
}
bool
@@ -7586,33 +7585,35 @@ nsCSSFrameConstructor::StyleNewChildRang
}
}
}
}
void
nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
nsIContent* aFirstNewContent,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed aLazyConstructionAllowed,
bool aForReconstruction,
TreeMatchContext* aProvidedTreeMatchContext)
{
- MOZ_ASSERT(!aProvidedTreeMatchContext || !aAllowLazyConstruction);
- MOZ_ASSERT(!aAllowLazyConstruction || !RestyleManager()->IsInStyleRefresh());
+ MOZ_ASSERT(!aProvidedTreeMatchContext ||
+ aLazyConstructionAllowed == LazyConstructionAllowed::No);
+ MOZ_ASSERT(aLazyConstructionAllowed == LazyConstructionAllowed::No ||
+ !RestyleManager()->IsInStyleRefresh());
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
NS_PRECONDITION(mUpdateCount != 0,
"Should be in an update while creating frames");
#ifdef DEBUG
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::ContentAppended container=%p "
"first-child=%p lazy=%d\n",
static_cast<void*>(aContainer), aFirstNewContent,
- aAllowLazyConstruction);
+ static_cast<int>(aLazyConstructionAllowed));
if (gReallyNoisyContentUpdates && aContainer) {
aContainer->List(stdout, 0);
}
}
#endif
#ifdef DEBUG
for (nsIContent* child = aFirstNewContent;
@@ -7656,23 +7657,24 @@ nsCSSFrameConstructor::ContentAppended(n
if (!isNewShadowTreeContent) {
// See comment in ContentRangeInserted for why this is necessary.
if (!GetContentInsertionFrameFor(aContainer) &&
!aContainer->IsActiveChildrenElement()) {
// We're punting on frame construction because there's no container frame.
// The Servo-backed style system handles this case like the lazy frame
// construction case, except when we're already constructing frames, in
// which case we shouldn't need to do anything else.
- if (isNewlyAddedContentForServo && aAllowLazyConstruction) {
+ if (isNewlyAddedContentForServo &&
+ aLazyConstructionAllowed == LazyConstructionAllowed::Yes) {
LazilyStyleNewChildRange(aFirstNewContent, nullptr);
}
return;
}
- if (aAllowLazyConstruction &&
+ if (aLazyConstructionAllowed == LazyConstructionAllowed::Yes &&
MaybeConstructLazily(CONTENTAPPEND, aContainer, aFirstNewContent)) {
if (isNewlyAddedContentForServo) {
LazilyStyleNewChildRange(aFirstNewContent, nullptr);
}
return;
}
}
@@ -7691,17 +7693,17 @@ nsCSSFrameConstructor::ContentAppended(n
RecreateFramesForContent(bindingParent, InsertionKind::Sync);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
LAYOUT_PHASE_TEMP_EXIT();
InsertionPoint insertion =
GetRangeInsertionPoint(aContainer, aFirstNewContent, nullptr,
- aAllowLazyConstruction, aForReconstruction);
+ aLazyConstructionAllowed, aForReconstruction);
nsContainerFrame*& parentFrame = insertion.mParentFrame;
LAYOUT_PHASE_TEMP_REENTER();
if (!parentFrame) {
return;
}
LAYOUT_PHASE_TEMP_EXIT();
if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) {
@@ -7964,26 +7966,26 @@ bool NotifyListBoxBody(nsPresContext*
}
}
return false;
}
#endif // MOZ_XUL
void
-nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer,
- nsIContent* aChild,
+nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer,
+ nsIContent* aChild,
nsILayoutHistoryState* aFrameState,
- bool aAllowLazyConstruction)
+ LazyConstructionAllowed aLazyConstructionAllowed)
{
ContentRangeInserted(aContainer,
aChild,
aChild->GetNextSibling(),
aFrameState,
- aAllowLazyConstruction);
+ aLazyConstructionAllowed);
}
// ContentRangeInserted handles creating frames for a range of nodes that
// aren't at the end of their childlist. ContentRangeInserted isn't a real
// content notification, but rather it handles regular ContentInserted calls
// for a single node as well as the lazy construction of frames for a range of
// nodes when called from CreateNeededFrames. For a range of nodes to be
// suitable to have its frames constructed all at once they must meet the same
@@ -7999,36 +8001,38 @@ nsCSSFrameConstructor::ContentInserted(n
// in the caption list, while skipping any nodes in the range being inserted
// (because when we treat the caption frames the other nodes have had their
// frames constructed but not yet inserted into the frame tree).
void
nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
nsILayoutHistoryState* aFrameState,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed aLazyConstructionAllowed,
bool aForReconstruction,
TreeMatchContext* aProvidedTreeMatchContext)
{
- MOZ_ASSERT(!aProvidedTreeMatchContext || !aAllowLazyConstruction);
- MOZ_ASSERT(!aAllowLazyConstruction || !RestyleManager()->IsInStyleRefresh());
+ MOZ_ASSERT(!aProvidedTreeMatchContext ||
+ aLazyConstructionAllowed == LazyConstructionAllowed::No);
+ MOZ_ASSERT(aLazyConstructionAllowed == LazyConstructionAllowed::No ||
+ !RestyleManager()->IsInStyleRefresh());
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
NS_PRECONDITION(mUpdateCount != 0,
"Should be in an update while creating frames");
NS_PRECONDITION(aStartChild, "must always pass a child");
#ifdef DEBUG
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::ContentRangeInserted container=%p "
"start-child=%p end-child=%p lazy=%d\n",
static_cast<void*>(aContainer),
static_cast<void*>(aStartChild), static_cast<void*>(aEndChild),
- aAllowLazyConstruction);
+ static_cast<int>(aLazyConstructionAllowed));
if (gReallyNoisyContentUpdates) {
if (aContainer) {
aContainer->List(stdout,0);
} else {
aStartChild->List(stdout, 0);
}
}
}
@@ -8040,17 +8044,18 @@ nsCSSFrameConstructor::ContentRangeInser
// Remove it once that's fixed.
NS_ASSERTION(!child->GetPrimaryFrame() ||
child->GetPrimaryFrame()->GetContent() != child,
"asked to construct a frame for a node that already has a frame");
}
#endif
bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
- NS_ASSERTION(isSingleInsert || !aAllowLazyConstruction,
+ NS_ASSERTION(isSingleInsert ||
+ aLazyConstructionAllowed == LazyConstructionAllowed::No,
"range insert shouldn't be lazy");
NS_ASSERTION(isSingleInsert || aEndChild,
"range should not include all nodes after aStartChild");
#ifdef MOZ_XUL
if (aContainer && IsXULListBox(aContainer)) {
if (isSingleInsert) {
if (NotifyListBoxBody(mPresShell->GetPresContext(), aContainer,
@@ -8059,17 +8064,17 @@ nsCSSFrameConstructor::ContentRangeInser
aStartChild, nullptr, nullptr, CONTENT_INSERTED)) {
return;
}
} else {
// We don't handle a range insert to a listbox parent, issue single
// ContertInserted calls for each node inserted.
LAYOUT_PHASE_TEMP_EXIT();
IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
- aAllowLazyConstruction, aForReconstruction);
+ aLazyConstructionAllowed, aForReconstruction);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
}
#endif // MOZ_XUL
// If we have a null parent, then this must be the document element being
// inserted, or some other child of the document in the DOM (might be a PI,
@@ -8134,27 +8139,28 @@ nsCSSFrameConstructor::ContentRangeInser
// The xbl:children element won't have a frame, but default content can have the children as
// a parent. While its uncommon to change the structure of the default content itself, a label,
// for example, can be reframed by having its value attribute set or removed.
if (!parentFrame && !aContainer->IsActiveChildrenElement()) {
// We're punting on frame construction because there's no container frame.
// The Servo-backed style system handles this case like the lazy frame
// construction case, except when we're already constructing frames, in
// which case we shouldn't need to do anything else.
- if (isNewlyAddedContentForServo && aAllowLazyConstruction) {
+ if (isNewlyAddedContentForServo &&
+ aLazyConstructionAllowed == LazyConstructionAllowed::Yes) {
LazilyStyleNewChildRange(aStartChild, aEndChild);
}
return;
}
// Otherwise, we've got parent content. Find its frame.
NS_ASSERTION(!parentFrame || parentFrame->GetContent() == aContainer ||
GetDisplayContentsStyleFor(aContainer), "New XBL code is possibly wrong!");
- if (aAllowLazyConstruction &&
+ if (aLazyConstructionAllowed == LazyConstructionAllowed::Yes &&
MaybeConstructLazily(CONTENTINSERT, aContainer, aStartChild)) {
if (isNewlyAddedContentForServo) {
LazilyStyleNewChildRange(aStartChild, aEndChild);
}
return;
}
}
@@ -8181,17 +8187,17 @@ nsCSSFrameConstructor::ContentRangeInser
// real parent frame; if not, then the frame hasn't been built yet
// and we just bail.
insertion = GetInsertionPoint(aContainer, aStartChild);
} else {
// Get our insertion point. If we need to issue single ContentInserted's
// GetRangeInsertionPoint will take care of that for us.
LAYOUT_PHASE_TEMP_EXIT();
insertion = GetRangeInsertionPoint(aContainer, aStartChild, aEndChild,
- aAllowLazyConstruction,
+ aLazyConstructionAllowed,
aForReconstruction);
LAYOUT_PHASE_TEMP_REENTER();
}
if (!insertion.mParentFrame) {
return;
}
@@ -8199,17 +8205,17 @@ nsCSSFrameConstructor::ContentRangeInser
nsIFrame* prevSibling = GetInsertionPrevSibling(&insertion, aStartChild,
&isAppend, &isRangeInsertSafe);
// check if range insert is safe
if (!isSingleInsert && !isRangeInsertSafe) {
// must fall back to a single ContertInserted for each child in the range
LAYOUT_PHASE_TEMP_EXIT();
IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
- aAllowLazyConstruction, aForReconstruction);
+ aLazyConstructionAllowed, aForReconstruction);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
nsIContent* container = insertion.mParentFrame->GetContent();
LayoutFrameType frameType = insertion.mParentFrame->Type();
LAYOUT_PHASE_TEMP_EXIT();
@@ -8338,17 +8344,17 @@ nsCSSFrameConstructor::ContentRangeInser
// Need check whether a range insert is still safe.
if (!isSingleInsert && !isRangeInsertSafe) {
// Need to recover the letter frames first.
RecoverLetterFrames(state.mFloatedItems.containingBlock);
// must fall back to a single ContertInserted for each child in the range
LAYOUT_PHASE_TEMP_EXIT();
IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
- aAllowLazyConstruction, aForReconstruction);
+ aLazyConstructionAllowed, aForReconstruction);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
container = insertion.mParentFrame->GetContent();
frameType = insertion.mParentFrame->Type();
}
}
@@ -10058,17 +10064,17 @@ nsCSSFrameConstructor::RecreateFramesFor
nsRestyleHint(0),
nsChangeHint_ReconstructFrame);
} else {
// Now, recreate the frames associated with this content object. If
// ContentRemoved triggered reconstruction, then we don't need to do this
// because the frames will already have been built.
ContentRangeInserted(container, aContent, aContent->GetNextSibling(),
mTempFrameTreeState,
- false, // aAllowLazyConstruction
+ LazyConstructionAllowed::No,
true, // aForReconstruction
nullptr);
}
}
}
}
bool
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -82,16 +82,22 @@ public:
* from ContentRemoved.
*/
enum class InsertionKind
{
Sync,
Async,
};
+ enum class LazyConstructionAllowed
+ {
+ No = 0,
+ Yes,
+ };
+
mozilla::RestyleManager* RestyleManager() const
{ return mPresShell->GetPresContext()->RestyleManager(); }
nsIFrame* ConstructRootFrame();
void ReconstructDocElementHierarchy(InsertionKind);
// Create frames for content nodes that are marked as needing frames. This
@@ -121,17 +127,17 @@ private:
void CheckBitsForLazyFrameConstruction(nsIContent*) {}
#endif
// Issues a single ContentInserted for each child of aContainer in the range
// [aStartChild, aEndChild).
void IssueSingleInsertNofications(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed,
bool aForReconstruction);
/**
* Data that represents an insertion point for some child content.
*/
struct InsertionPoint
{
InsertionPoint()
@@ -165,17 +171,17 @@ private:
* can be inserted/appended to one insertion point together. If so, returns
* that insertion point. If not, returns with InsertionPoint.mFrame == nullptr
* and issues single ContentInserted calls for each child.
* aEndChild = nullptr indicates that we are dealing with an append.
*/
InsertionPoint GetRangeInsertionPoint(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed,
bool aForReconstruction);
// Returns true if parent was recreated due to frameset child, false otherwise.
bool MaybeRecreateForFrameset(nsIFrame* aParentFrame,
nsIContent* aStartChild,
nsIContent* aEndChild);
/**
@@ -247,72 +253,72 @@ public:
// children can be done lazily.
//
// When constructing frames lazily, we can keep the tree match context in a
// much easier way than nsFrameConstructorState, and thus, we're allowed to
// provide a TreeMatchContext to avoid calling InitAncestors repeatedly deep
// in the DOM.
void ContentAppended(nsIContent* aContainer,
nsIContent* aFirstNewContent,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed aLazyConstructionAllowed,
TreeMatchContext* aProvidedTreeMatchContext = nullptr)
{
- ContentAppended(aContainer, aFirstNewContent, aAllowLazyConstruction, false,
+ ContentAppended(aContainer, aFirstNewContent, aLazyConstructionAllowed, false,
aProvidedTreeMatchContext);
}
// If aAllowLazyConstruction is true then frame construction of the new child
// can be done lazily.
void ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
nsILayoutHistoryState* aFrameState,
- bool aAllowLazyConstruction);
+ LazyConstructionAllowed aLazyConstructionAllowed);
// Like ContentInserted but handles inserting the children of aContainer in
// the range [aStartChild, aEndChild). aStartChild must be non-null.
// aEndChild may be null to indicate the range includes all kids after
// aStartChild.
//
// If aAllowLazyConstruction is true then frame construction of
// the new children can be done lazily. It is only allowed to be true when
// inserting a single node.
//
// See ContentAppended to see why we allow passing an already initialized
// TreeMatchContext.
void ContentRangeInserted(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
nsILayoutHistoryState* aFrameState,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed aLazyConstructionAllowed,
TreeMatchContext* aProvidedTreeMatchContext = nullptr)
{
ContentRangeInserted(aContainer, aStartChild, aEndChild, aFrameState,
- aAllowLazyConstruction, false,
+ aLazyConstructionAllowed, false,
aProvidedTreeMatchContext);
}
private:
// Helpers for the public ContentAppended, ContentInserted and
// ContentRangeInserted functions above.
//
// aForReconstruction indicates whether this call is for frame reconstruction
// via RecreateFramesFor or lazy frame construction via CreateNeededFrames.
// (This latter case admittedly isn't always for "reconstruction" per se, but
// the important thing is that aForReconstruction is false for real content
// insertions, and true for other cases.)
void ContentAppended(nsIContent* aContainer,
nsIContent* aFirstNewContent,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed aLazyConstructionAllowed,
bool aForReconstruction,
TreeMatchContext* aProvidedTreeMatchContext);
void ContentRangeInserted(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
nsILayoutHistoryState* aFrameState,
- bool aAllowLazyConstruction,
+ LazyConstructionAllowed aLazyConstructionAllowed,
bool aForReconstruction,
TreeMatchContext* aProvidedTreeMatchContext);
public:
enum RemoveFlags {
REMOVE_CONTENT,
REMOVE_FOR_RECONSTRUCTION,
};