--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -6425,18 +6425,18 @@ IsRootBoxFrame(nsIFrame *aFrame)
void
nsCSSFrameConstructor::ReconstructDocElementHierarchy()
{
Element* rootElement = mDocument->GetRootElement();
if (!rootElement) {
/* nothing to do */
return;
}
- RecreateFramesForContent(rootElement, false, REMOVE_FOR_RECONSTRUCTION,
- nullptr);
+ RecreateFramesForContent(rootElement, InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
}
nsContainerFrame*
nsCSSFrameConstructor::GetAbsoluteContainingBlock(nsIFrame* aFrame,
ContainingBlockType aType)
{
// Starting with aFrame, look for a frame that is absolutely positioned or
// relatively positioned (and transformed, if aType is FIXED)
@@ -7213,17 +7213,18 @@ 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");
- ContentInserted(aParentContent, aContent, nullptr, false);
+ const bool allowLazyConstruction = true;
+ ContentInserted(aParentContent, aContent, nullptr, allowLazyConstruction);
}
#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
@@ -7544,18 +7545,19 @@ nsCSSFrameConstructor::MaybeRecreateForF
{
if (aParentFrame->IsFrameSetFrame()) {
// Check whether we have any kids we care about.
for (nsIContent* cur = aStartChild;
cur != aEndChild;
cur = cur->GetNextSibling()) {
if (IsSpecialFramesetChild(cur)) {
// Just reframe the parent, since framesets are weird like that.
- RecreateFramesForContent(aParentFrame->GetContent(), false,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(aParentFrame->GetContent(),
+ InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
return true;
}
}
}
return false;
}
void
@@ -7712,18 +7714,18 @@ nsCSSFrameConstructor::ContentAppended(n
if (isNewShadowTreeContent) {
// Recreate frames if content is appended into a ShadowRoot
// because children of ShadowRoot are rendered in place of children
// of the host.
//XXXsmaug This is super unefficient!
nsIContent* bindingParent = aContainer->GetBindingParent();
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(bindingParent, false,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(bindingParent, InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
LAYOUT_PHASE_TEMP_EXIT();
InsertionPoint insertion =
GetRangeInsertionPoint(aContainer, aFirstNewContent, nullptr,
aAllowLazyConstruction, aForReconstruction);
@@ -7744,18 +7746,19 @@ nsCSSFrameConstructor::ContentAppended(n
// Nothing to do here; we shouldn't be constructing kids of leaves
// Clear lazy bits so we don't try to construct again.
ClearLazyBits(aFirstNewContent, nullptr);
return;
}
if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) {
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(parentFrame->GetContent(), false,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(parentFrame->GetContent(),
+ InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
// If the frame we are manipulating is a ib-split frame (that is, one
// that's been created as a result of a block-in-inline situation) then we
// need to append to the last ib-split sibling, not to the frame itself.
bool parentIBSplit = IsFramePartOfIBSplit(parentFrame);
@@ -8199,18 +8202,18 @@ nsCSSFrameConstructor::ContentRangeInser
if (isNewShadowTreeContent) {
// Recreate frames if content is inserted into a ShadowRoot
// because children of ShadowRoot are rendered in place of
// the children of the host.
//XXXsmaug This is super unefficient!
nsIContent* bindingParent = aContainer->GetBindingParent();
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(bindingParent, false,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(bindingParent, InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
InsertionPoint insertion;
if (isSingleInsert) {
// 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
@@ -8262,48 +8265,51 @@ nsCSSFrameConstructor::ContentRangeInser
aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
// Just reframe the parent, since figuring out whether this
// should be the new legend and then handling it is too complex.
// We could do a little better here --- check if the fieldset already
// has a legend which occurs earlier in its child list than this node,
// and if so, proceed. But we'd have to extend nsFieldSetFrame
// to locate this legend in the inserted frames and extract it.
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(insertion.mParentFrame->GetContent(), false,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(insertion.mParentFrame->GetContent(),
+ InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
// We should only get here with details when doing a single insertion because
// we treat details frame as if it has multiple insertion points.
MOZ_ASSERT(isSingleInsert || frameType != LayoutFrameType::Details);
if (frameType == LayoutFrameType::Details) {
// When inserting an element into <details>, just reframe the details frame
// and let it figure out where the element should be laid out. It might seem
// expensive to recreate the entire details frame, but it's the simplest way
// to handle the insertion.
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(insertion.mParentFrame->GetContent(), false,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(insertion.mParentFrame->GetContent(),
+ InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
// Don't construct kids of leaves
if (insertion.mParentFrame->IsLeaf()) {
// Clear lazy bits so we don't try to construct again.
ClearLazyBits(aStartChild, aEndChild);
return;
}
if (insertion.mParentFrame->IsFrameOfType(nsIFrame::eMathML)) {
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(insertion.mParentFrame->GetContent(), false,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(insertion.mParentFrame->GetContent(),
+ InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
Maybe<TreeMatchContext> matchContext;
if (!aProvidedTreeMatchContext && !aContainer->IsStyledByServo()) {
matchContext.emplace(mDocument, TreeMatchContext::ForFrameConstruction);
matchContext->InitAncestors(aContainer ? aContainer->AsElement() : nullptr);
@@ -8633,31 +8639,35 @@ nsCSSFrameConstructor::ContentRangeInser
if (accService) {
accService->ContentRangeInserted(mPresShell, aContainer,
aStartChild, aEndChild);
}
#endif
}
void
-nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
- nsIContent* aChild,
- nsIContent* aOldNextSibling,
- RemoveFlags aFlags,
- bool* aDidReconstruct,
- nsIContent** aDestroyedFramesFor)
-{
+nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
+ nsIContent* aChild,
+ nsIContent* aOldNextSibling,
+ RemoveFlags aFlags,
+ bool* aDidReconstruct)
+{
+ MOZ_ASSERT(aChild);
+ MOZ_ASSERT(aDidReconstruct);
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
NS_PRECONDITION(mUpdateCount != 0,
"Should be in an update while destroying frames");
*aDidReconstruct = false;
- if (aDestroyedFramesFor) {
- *aDestroyedFramesFor = aChild;
- }
+
+ // Only recreate sync if we're already in frame construction, that is,
+ // recreate async for XBL DOM changes, and normal content removals.
+ const InsertionKind insertionKind = (aFlags == REMOVE_FOR_RECONSTRUCTION)
+ ? InsertionKind::Sync
+ : InsertionKind::Async;
// We're destroying our frame(s). This normally happens either when the
// content is being removed from the DOM (in which case we'll drop all Servo
// data in UnbindFromTree), or when we're recreating frames (usually in
// response to having retrieved a ReconstructFrame change hint after
// restyling). In both of those cases, there are no pending restyles we need
// to worry about.
//
@@ -8715,41 +8725,39 @@ nsCSSFrameConstructor::ContentRemoved(ns
if (!childFrame || childFrame->GetContent() != aChild) {
// XXXbz the GetContent() != aChild check is needed due to bug 135040.
// Remove it once that's fixed.
UnregisterDisplayNoneStyleFor(aChild, aContainer);
}
MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild),
"display:contents nodes shouldn't have a frame");
if (!childFrame && GetDisplayContentsStyleFor(aChild)) {
- nsIContent* ancestor = aContainer;
+ nsIContent* ancestor = aChild->GetFlattenedTreeParent();
MOZ_ASSERT(ancestor, "display: contents on the root?");
while (!ancestor->GetPrimaryFrame()) {
- // FIXME(emilio): Should this use the flattened tree parent instead?
- ancestor = ancestor->GetParent();
+ ancestor = ancestor->GetFlattenedTreeParent();
MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!");
}
nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame();
if (ancestorFrame->GetProperty(nsIFrame::GenConProperty())) {
*aDidReconstruct = true;
- LAYOUT_PHASE_TEMP_EXIT();
-
// XXXmats Can we recreate frames only for the ::after/::before content?
// XXX Perhaps even only those that belong to the aChild sub-tree?
- RecreateFramesForContent(ancestor, false, aFlags, aDestroyedFramesFor);
+ LAYOUT_PHASE_TEMP_EXIT();
+ RecreateFramesForContent(ancestor, insertionKind, aFlags);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
FlattenedChildIterator iter(aChild);
for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
if (c->GetPrimaryFrame() || GetDisplayContentsStyleFor(c)) {
LAYOUT_PHASE_TEMP_EXIT();
- ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct, aDestroyedFramesFor);
+ ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct);
LAYOUT_PHASE_TEMP_REENTER();
if (aFlags != REMOVE_DESTROY_FRAMES && *aDidReconstruct) {
return;
}
}
}
UnregisterDisplayContentsStyleFor(aChild, aContainer);
}
@@ -8792,92 +8800,86 @@ nsCSSFrameConstructor::ContentRemoved(ns
!aChild->IsInNativeAnonymousSubtree()) {
// Recreate frames if content is removed from a ShadowRoot because it may
// contain an insertion point which can change how the host is rendered.
//
// XXXsmaug This is super unefficient!
nsIContent* bindingParent = aContainer->GetBindingParent();
*aDidReconstruct = true;
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(bindingParent, false, aFlags, aDestroyedFramesFor);
+ RecreateFramesForContent(bindingParent, insertionKind, aFlags);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
if (aFlags == REMOVE_DESTROY_FRAMES) {
CaptureStateForFramesOf(aChild, mTempFrameTreeState);
}
if (childFrame) {
InvalidateCanvasIfNeeded(mPresShell, aChild);
// See whether we need to remove more than just childFrame
LAYOUT_PHASE_TEMP_EXIT();
- nsIContent* container;
- if (MaybeRecreateContainerForFrameRemoval(childFrame, aFlags, &container)) {
+ if (MaybeRecreateContainerForFrameRemoval(
+ childFrame, insertionKind, aFlags)) {
+ *aDidReconstruct = true;
LAYOUT_PHASE_TEMP_REENTER();
- MOZ_ASSERT(container);
- *aDidReconstruct = true;
- if (aDestroyedFramesFor) {
- *aDestroyedFramesFor = container;
- }
return;
}
LAYOUT_PHASE_TEMP_REENTER();
// Get the childFrame's parent frame
nsIFrame* parentFrame = childFrame->GetParent();
LayoutFrameType parentType = parentFrame->Type();
if (parentType == LayoutFrameType::FrameSet &&
IsSpecialFramesetChild(aChild)) {
// Just reframe the parent, since framesets are weird like that.
*aDidReconstruct = true;
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(parentFrame->GetContent(), false,
- aFlags, aDestroyedFramesFor);
+ RecreateFramesForContent(parentFrame->GetContent(), insertionKind,
+ aFlags);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
// If we're a child of MathML, then we should reframe the MathML content.
// If we're non-MathML, then we would be wrapped in a block so we need to
// check our grandparent in that case.
nsIFrame* possibleMathMLAncestor = parentType == LayoutFrameType::Block
? parentFrame->GetParent()
: parentFrame;
if (possibleMathMLAncestor->IsFrameOfType(nsIFrame::eMathML)) {
*aDidReconstruct = true;
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(possibleMathMLAncestor->GetContent(),
- false, aFlags, aDestroyedFramesFor);
+ RecreateFramesForContent(parentFrame->GetContent(), insertionKind, aFlags);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
// Undo XUL wrapping if it's no longer needed.
// (If we're in the XUL block-wrapping situation, parentFrame is the
// wrapper frame.)
nsIFrame* grandparentFrame = parentFrame->GetParent();
if (grandparentFrame && grandparentFrame->IsXULBoxFrame() &&
(grandparentFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
// check if this frame is the only one needing wrapping
aChild == AnyKidsNeedBlockParent(parentFrame->PrincipalChildList().FirstChild()) &&
!AnyKidsNeedBlockParent(childFrame->GetNextSibling())) {
*aDidReconstruct = true;
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(grandparentFrame->GetContent(), true,
- aFlags, aDestroyedFramesFor);
+ RecreateFramesForContent(grandparentFrame->GetContent(), insertionKind,
+ aFlags);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
#ifdef ACCESSIBILITY
- nsAccessibilityService* accService = nsIPresShell::AccService();
- if (accService) {
+ if (nsAccessibilityService* accService = nsIPresShell::AccService()) {
accService->ContentRemoved(mPresShell, aChild);
}
#endif
// Examine the containing-block for the removed content and see if
// :first-letter style applies.
nsIFrame* inflowChild = childFrame;
if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
@@ -8971,16 +8973,19 @@ nsCSSFrameConstructor::ContentRemoved(ns
// if necessary.
// Reframe any text node just before the node being removed, if there is
// one, and if it's not the last child or the first child. If a whitespace
// textframe was being suppressed and it's now the last child or first
// child then it can stay suppressed since the parent must be a block
// and hence it's adjacent to a block end.
// If aOldNextSibling is null, then the text node before the node being
// removed is the last node, and we don't need to worry about it.
+ //
+ // FIXME(emilio): This should probably use the lazy frame construction
+ // bits if possible instead of reframing it in place.
if (aOldNextSibling) {
nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
if (prevSibling && prevSibling->GetPreviousSibling()) {
LAYOUT_PHASE_TEMP_EXIT();
ReframeTextIfNeeded(aContainer, prevSibling);
LAYOUT_PHASE_TEMP_REENTER();
}
}
@@ -9073,18 +9078,18 @@ nsCSSFrameConstructor::CharacterDataChan
(aContent->HasFlag(NS_REFRAME_IF_WHITESPACE) &&
aContent->TextIsOnlyWhitespace())) {
#ifdef DEBUG
nsIFrame* frame = aContent->GetPrimaryFrame();
NS_ASSERTION(!frame || !frame->IsGeneratedContentFrame(),
"Bit should never be set on generated content");
#endif
LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(aContent, false,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(aContent, InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
// Find the child frame
nsIFrame* frame = aContent->GetPrimaryFrame();
// Notify the first frame that maps the content. It will generate a reflow
@@ -9754,17 +9759,18 @@ nsCSSFrameConstructor::MaybeRecreateFram
}
const nsStyleDisplay* oldDisp = oldContext->PeekStyleDisplay();
if (oldDisp &&
DefinitelyEqualURIsAndPrincipal(disp->mBinding, oldDisp->mBinding)) {
return newContext;
}
}
- RecreateFramesForContent(aElement, false, REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(aElement, InsertionKind::Sync,
+ REMOVE_FOR_RECONSTRUCTION);
return nullptr;
}
static bool
IsWhitespaceFrame(nsIFrame* aFrame)
{
MOZ_ASSERT(aFrame, "invalid argument");
return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
@@ -9796,50 +9802,47 @@ FindPreviousNonWhitespaceSibling(nsIFram
nsIFrame* f = aFrame;
do {
f = f->GetPrevSibling();
} while (f && IsWhitespaceFrame(f));
return f;
}
bool
-nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
- RemoveFlags aFlags,
- nsIContent** aDestroyedFramesFor)
+nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
+ nsIFrame* aFrame,
+ InsertionKind aInsertionKind,
+ RemoveFlags aFlags)
{
NS_PRECONDITION(aFrame, "Must have a frame");
NS_PRECONDITION(aFrame->GetParent(), "Frame shouldn't be root");
NS_PRECONDITION(aFrame == aFrame->FirstContinuation(),
"aFrame not the result of GetPrimaryFrame()?");
- *aDestroyedFramesFor = nullptr;
-
if (IsFramePartOfIBSplit(aFrame)) {
// The removal functions can't handle removal of an {ib} split directly; we
// need to rebuild the containing block.
#ifdef DEBUG
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
"frame=");
nsFrame::ListTag(stdout, aFrame);
printf(" is ib-split\n");
}
#endif
- ReframeContainingBlock(aFrame, aFlags, aDestroyedFramesFor);
+ ReframeContainingBlock(aFrame, aInsertionKind, aFlags);
return true;
}
nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame();
if (insertionFrame && insertionFrame->IsLegendFrame() &&
aFrame->GetParent()->IsFieldSetFrame()) {
- // When we remove the legend for a fieldset, we should reframe
- // the fieldset to ensure another legend is used, if there is one
- RecreateFramesForContent(aFrame->GetParent()->GetContent(), false,
- aFlags, aDestroyedFramesFor);
+ RecreateFramesForContent(aFrame->GetParent()->GetContent(), aInsertionKind,
+ aFlags);
return true;
}
nsIFrame* inFlowFrame =
(aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) ?
aFrame->GetPlaceholderFrame() : aFrame;
MOZ_ASSERT(inFlowFrame, "How did that happen?");
MOZ_ASSERT(inFlowFrame == inFlowFrame->FirstContinuation(),
@@ -9853,19 +9856,17 @@ nsCSSFrameConstructor::MaybeRecreateCont
// Unlike adding summary element cases, we need to check children of the
// parent details frame since at this moment the summary element has been
// already removed from the parent details element's child list.
if (summary && detailsFrame->HasMainSummaryFrame(aFrame)) {
// When removing a summary, we should reframe the parent details frame to
// ensure that another summary is used or the default summary is
// generated.
- RecreateFramesForContent(parent->GetContent(),
- false, REMOVE_FOR_RECONSTRUCTION,
- aDestroyedFramesFor);
+ RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags);
return true;
}
}
// Now check for possibly needing to reconstruct due to a pseudo parent
// For the case of ruby pseudo parent, effectively, only pseudo rb/rt frame
// need to be checked here, since all other types of parent will be catched
// by "Check ruby containers" section below.
@@ -9878,20 +9879,17 @@ nsCSSFrameConstructor::MaybeRecreateCont
parent->PrincipalChildList().OnlyChild()) ||
// If we're a table-column-group, then the OnlyChild check above is
// not going to catch cases when we're the first child.
(inFlowFrame->IsTableColGroupFrame() &&
parent->GetChildList(nsIFrame::kColGroupList).FirstChild() == inFlowFrame) ||
// Similar if we're a table-caption.
(inFlowFrame->IsTableCaption() &&
parent->GetChildList(nsIFrame::kCaptionList).FirstChild() == inFlowFrame)) {
- // We're the first or last frame in the pseudo. Need to reframe.
- // Good enough to recreate frames for |parent|'s content
- RecreateFramesForContent(parent->GetContent(), true, aFlags,
- aDestroyedFramesFor);
+ RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags);
return true;
}
}
// Might need to reconstruct things if this frame's nextSibling is a table
// or ruby pseudo, since removal of this frame might mean that this pseudo
// needs to get merged with the frame's prevSibling if that's also a table
// or ruby pseudo.
@@ -9910,35 +9908,33 @@ nsCSSFrameConstructor::MaybeRecreateCont
"frame=");
nsFrame::ListTag(stdout, aFrame);
printf(" has a table pseudo next sibling of different type and a "
"table pseudo prevsibling\n");
}
#endif
// Good enough to recreate frames for aFrame's parent's content; even if
// aFrame's parent is a pseudo, that'll be the right content node.
- RecreateFramesForContent(parent->GetContent(), true, aFlags,
- aDestroyedFramesFor);
+ RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags);
return true;
}
}
// Check ruby containers
LayoutFrameType parentType = parent->Type();
if (parentType == LayoutFrameType::Ruby ||
RubyUtils::IsRubyContainerBox(parentType)) {
// In ruby containers, pseudo frames may be created from
// whitespaces or even nothing. There are two cases we actually
// need to handle here, but hard to check exactly:
// 1. Status of spaces beside the frame may vary, and related
// frames may be constructed or destroyed accordingly.
// 2. The type of the first child of a ruby frame determines
// whether a pseudo ruby base container should exist.
- RecreateFramesForContent(parent->GetContent(), true, aFlags,
- aDestroyedFramesFor);
+ RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags);
return true;
}
// Might need to reconstruct things if the removed frame's nextSibling is an
// anonymous flex item. The removed frame might've been what divided two
// runs of inline content into two anonymous flex items, which would now
// need to be merged.
// NOTE: It's fine that we've advanced nextSibling past whitespace (up above);
@@ -9951,18 +9947,17 @@ nsCSSFrameConstructor::MaybeRecreateCont
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
"frame=");
nsFrame::ListTag(stdout, aFrame);
printf(" has an anonymous flex item as its next sibling\n");
}
#endif // DEBUG
// Recreate frames for the flex container (the removed frame's parent)
- RecreateFramesForContent(parent->GetContent(), true, aFlags,
- aDestroyedFramesFor);
+ RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags);
return true;
}
// Might need to reconstruct things if the removed frame's nextSibling is
// null and its parent is an anonymous flex item. (This might be the last
// remaining child of that anonymous flex item, which can then go away.)
if (!nextSibling && IsAnonymousFlexOrGridItem(parent)) {
AssertAnonymousFlexOrGridItemParent(parent, parent->GetParent());
@@ -9970,18 +9965,18 @@ nsCSSFrameConstructor::MaybeRecreateCont
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
"frame=");
nsFrame::ListTag(stdout, aFrame);
printf(" has an anonymous flex item as its parent\n");
}
#endif // DEBUG
// Recreate frames for the flex container (the removed frame's grandparent)
- RecreateFramesForContent(parent->GetParent()->GetContent(), true,
- aFlags, aDestroyedFramesFor);
+ RecreateFramesForContent(parent->GetParent()->GetContent(), aInsertionKind,
+ aFlags);
return true;
}
#ifdef MOZ_XUL
if (aFrame->IsPopupSetFrame()) {
nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
if (rootBox && rootBox->GetPopupSetFrame() == aFrame) {
ReconstructDocElementHierarchy();
@@ -9991,18 +9986,17 @@ nsCSSFrameConstructor::MaybeRecreateCont
#endif
// Reconstruct if inflowFrame is parent's only child, and parent is, or has,
// a non-fluid continuation, i.e. it was split by bidi resolution
if (!inFlowFrame->GetPrevSibling() &&
!inFlowFrame->GetNextSibling() &&
((parent->GetPrevContinuation() && !parent->GetPrevInFlow()) ||
(parent->GetNextContinuation() && !parent->GetNextInFlow()))) {
- RecreateFramesForContent(parent->GetContent(), true, aFlags,
- aDestroyedFramesFor);
+ RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags);
return true;
}
// We might still need to reconstruct things if the parent of inFlowFrame is
// ib-split, since in that case the removal of aFrame might affect the
// splitting of its parent.
if (!IsFramePartOfIBSplit(parent)) {
return false;
@@ -10028,28 +10022,28 @@ nsCSSFrameConstructor::MaybeRecreateCont
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
"frame=");
nsFrame::ListTag(stdout, parent);
printf(" is ib-split\n");
}
#endif
- ReframeContainingBlock(parent, aFlags, aDestroyedFramesFor);
+ ReframeContainingBlock(parent, aInsertionKind, aFlags);
return true;
}
void
-nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent,
- bool aAsyncInsert,
- RemoveFlags aFlags,
- nsIContent** aDestroyedFramesFor)
-{
- NS_PRECONDITION(!aAsyncInsert || aContent->IsElement(),
- "Can only insert elements async");
+nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent,
+ InsertionKind aInsertionKind,
+ RemoveFlags aFlags)
+{
+ MOZ_ASSERT(aInsertionKind != InsertionKind::Async || aContent->IsElement());
+ MOZ_ASSERT(aContent);
+
// If there is no document, we don't want to recreate frames for it. (You
// shouldn't generally be giving this method content without a document
// anyway).
// Rebuilding the frame tree can have bad effects, especially if it's the
// frame tree for chrome (see bug 157322).
if (NS_WARN_IF(!aContent->GetComposedDoc())) {
return;
}
@@ -10073,18 +10067,18 @@ nsCSSFrameConstructor::RecreateFramesFor
aContent = parentContent;
frame = parentContentFrame;
}
}
if (frame) {
nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(frame);
if (nonGeneratedAncestor->GetContent() != aContent) {
- return RecreateFramesForContent(nonGeneratedAncestor->GetContent(), aAsyncInsert,
- aFlags, aDestroyedFramesFor);
+ return RecreateFramesForContent(nonGeneratedAncestor->GetContent(),
+ aInsertionKind, aFlags);
}
if (frame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
// Recreate the frames for the entire nsIAnonymousContentCreator tree
// since |frame| or one of its descendants may need an nsStyleContext
// that associates it to a CSS pseudo-element, and only the
// nsIAnonymousContentCreator that created this content knows how to make
// that happen.
@@ -10094,92 +10088,88 @@ nsCSSFrameConstructor::RecreateFramesFor
ancestor = nsLayoutUtils::GetParentOrPlaceholderFor(ancestor);
}
NS_ASSERTION(acc, "Where is the nsIAnonymousContentCreator? We may fail "
"to recreate its content correctly");
// nsSVGUseFrame is special, and we know this is unnecessary for it.
if (!ancestor->IsSVGUseFrame()) {
NS_ASSERTION(aContent->IsInNativeAnonymousSubtree(),
"Why is NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT set?");
- return RecreateFramesForContent(ancestor->GetContent(), aAsyncInsert,
- aFlags, aDestroyedFramesFor);
+ return RecreateFramesForContent(ancestor->GetContent(), aInsertionKind,
+ aFlags);
}
}
nsIFrame* parent = frame->GetParent();
nsIContent* parentContent = parent ? parent->GetContent() : nullptr;
// If the parent frame is a leaf then the subsequent insert will fail to
// create a frame, so we need to recreate the parent content. This happens
// with native anonymous content from the editor.
if (parent && parent->IsLeaf() && parentContent &&
parentContent != aContent) {
- return RecreateFramesForContent(parentContent, aAsyncInsert, aFlags,
- aDestroyedFramesFor);
- }
- }
-
- nsIContent* container;
- if (frame && MaybeRecreateContainerForFrameRemoval(frame, aFlags,
- &container)) {
- MOZ_ASSERT(container);
- if (aDestroyedFramesFor) {
- *aDestroyedFramesFor = container;
- }
+ return RecreateFramesForContent(parentContent, aInsertionKind, aFlags);
+ }
+ }
+
+ if (frame &&
+ MaybeRecreateContainerForFrameRemoval(frame, aInsertionKind, aFlags)) {
return;
}
nsINode* containerNode = aContent->GetParentNode();
// XXXbz how can containerNode be null here?
if (containerNode) {
// Before removing the frames associated with the content object,
// ask them to save their state onto a temporary state object.
CaptureStateForFramesOf(aContent, mTempFrameTreeState);
// Need the nsIContent parent, which might be null here, since we need to
// pass it to ContentInserted and ContentRemoved.
+ //
+ // FIXME(emilio): Do we need a strong ref here?
nsCOMPtr<nsIContent> container = aContent->GetParent();
// Remove the frames associated with the content object.
bool didReconstruct;
nsIContent* nextSibling = aContent->IsRootOfAnonymousSubtree() ?
nullptr : aContent->GetNextSibling();
- const bool reconstruct = aFlags != REMOVE_DESTROY_FRAMES;
- RemoveFlags flags = reconstruct ? REMOVE_FOR_RECONSTRUCTION : aFlags;
- ContentRemoved(container, aContent, nextSibling, flags,
- &didReconstruct, aDestroyedFramesFor);
- if (reconstruct && !didReconstruct) {
- // 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.
- if (aAsyncInsert) {
+ ContentRemoved(container, aContent, nextSibling, aFlags, &didReconstruct);
+ if (!didReconstruct) {
+ if (aInsertionKind == InsertionKind::Async) {
// XXXmats doesn't frame state need to be restored in this case too?
- RestyleManager()->PostRestyleEvent(
- aContent->AsElement(), nsRestyleHint(0), nsChangeHint_ReconstructFrame);
+ RestyleManager()->PostRestyleEvent(aContent->AsElement(),
+ 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
true, // aForReconstruction
nullptr);
}
}
}
}
void
-nsCSSFrameConstructor::DestroyFramesFor(nsIContent* aContent,
- nsIContent** aDestroyedFramesFor)
+nsCSSFrameConstructor::DestroyFramesFor(nsIContent* aContent,
+ bool* aDidReconstruct)
{
MOZ_ASSERT(aContent && aContent->GetParentNode());
- bool didReconstruct;
nsIContent* nextSibling =
aContent->IsRootOfAnonymousSubtree() ? nullptr : aContent->GetNextSibling();
- ContentRemoved(aContent->GetParent(), aContent, nextSibling,
- REMOVE_DESTROY_FRAMES, &didReconstruct, aDestroyedFramesFor);
+ ContentRemoved(aContent->GetParent(),
+ aContent,
+ nextSibling,
+ REMOVE_DESTROY_FRAMES,
+ aDidReconstruct);
}
//////////////////////////////////////////////////////////////////////
// Block frame construction code
already_AddRefed<nsStyleContext>
nsCSSFrameConstructor::GetFirstLetterStyle(nsIContent* aContent,
@@ -12851,18 +12841,18 @@ nsCSSFrameConstructor::WipeContainingBlo
// Before we go and append the frames, we must check for several
// special situations.
// Situation #1 is a XUL frame that contains frames that are required
// to be wrapped in blocks.
if (aFrame->IsXULBoxFrame() &&
!(aFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
aItems.AnyItemsNeedBlockParent()) {
- RecreateFramesForContent(aFrame->GetContent(), true,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async,
+ REMOVE_FOR_RECONSTRUCTION);
return true;
}
nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
// Situation #2 is a flex or grid container frame into which we're inserting
// new inline non-replaced children, adjacent to an existing anonymous
// flex or grid item.
@@ -12871,30 +12861,31 @@ nsCSSFrameConstructor::WipeContainingBlo
frameType == LayoutFrameType::GridContainer) {
FCItemIterator iter(aItems);
// Check if we're adding to-be-wrapped content right *after* an existing
// anonymous flex or grid item (which would need to absorb this content).
const bool isWebkitBox = IsFlexContainerForLegacyBox(aFrame);
if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) &&
iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox)) {
- RecreateFramesForContent(aFrame->GetContent(), true,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async,
+ REMOVE_FOR_RECONSTRUCTION);
return true;
}
// Check if we're adding to-be-wrapped content right *before* an existing
// anonymous flex or grid item (which would need to absorb this content).
if (nextSibling && IsAnonymousFlexOrGridItem(nextSibling)) {
// Jump to the last entry in the list
iter.SetToEnd();
iter.Prev();
if (iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox)) {
- RecreateFramesForContent(aFrame->GetContent(), true,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(aFrame->GetContent(),
+ InsertionKind::Async,
+ REMOVE_FOR_RECONSTRUCTION);
return true;
}
}
}
// Situation #3 is an anonymous flex or grid item that's getting new children
// who don't want to be wrapped.
if (IsAnonymousFlexOrGridItem(aFrame)) {
@@ -12913,18 +12904,19 @@ nsCSSFrameConstructor::WipeContainingBlo
// Skip over things that _do_ need an anonymous flex item, because
// they're perfectly happy to go here -- they won't cause a reframe.
nsIFrame* containerFrame = aFrame->GetParent();
const bool isWebkitBox = IsFlexContainerForLegacyBox(containerFrame);
if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState,
isWebkitBox)) {
// We hit something that _doesn't_ need an anonymous flex item!
// Rebuild the flex container to bust it out.
- RecreateFramesForContent(containerFrame->GetContent(), true,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(containerFrame->GetContent(),
+ InsertionKind::Async,
+ REMOVE_FOR_RECONSTRUCTION);
return true;
}
// If we get here, then everything in |aItems| needs to be wrapped in
// an anonymous flex or grid item. That's where it's already going - good!
}
// Situation #4 is a ruby-related frame that's getting new children.
@@ -12937,18 +12929,18 @@ nsCSSFrameConstructor::WipeContainingBlo
// their sibling changes.
// 2) The first effective child of a ruby frame must always be a ruby
// base container. It should be created or destroyed accordingly.
if (IsRubyPseudo(aFrame) || frameType == LayoutFrameType::Ruby ||
RubyUtils::IsRubyContainerBox(frameType)) {
// We want to optimize it better, and avoid reframing as much as
// possible. But given the cases above, and the fact that a ruby
// usually won't be very large, it should be fine to reframe it.
- RecreateFramesForContent(aFrame->GetContent(), true,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async,
+ REMOVE_FOR_RECONSTRUCTION);
return true;
}
// Situation #5 is a case when table pseudo-frames don't work out right
ParentType parentType = GetParentType(aFrame);
// If all the kids want a parent of the type that aFrame is, then we're all
// set to go. Indeed, there won't be any table pseudo-frames created between
// aFrame and the kids, so those won't need to be merged with any table
@@ -13104,18 +13096,18 @@ nsCSSFrameConstructor::WipeContainingBlo
// it might be empty, so recheck that too.
if (aItems.IsEmpty()) {
return false;
}
if (!aItems.AllWantParentType(parentType)) {
// Reframing aFrame->GetContent() is good enough, since the content of
// table pseudo-frames is the ancestor content.
- RecreateFramesForContent(aFrame->GetContent(), true,
- REMOVE_FOR_RECONSTRUCTION, nullptr);
+ RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async,
+ REMOVE_FOR_RECONSTRUCTION);
return true;
}
}
// Now we have several cases involving {ib} splits. Put them all in a
// do/while with breaks to take us to the "go and reconstruct" code.
do {
if (IsInlineFrame(aFrame)) {
@@ -13193,25 +13185,25 @@ nsCSSFrameConstructor::WipeContainingBlo
nsIContent *blockContent = aContainingBlock->GetContent();
#ifdef DEBUG
if (gNoisyContentUpdates) {
printf("nsCSSFrameConstructor::WipeContainingBlock: blockContent=%p\n",
static_cast<void*>(blockContent));
}
#endif
- RecreateFramesForContent(blockContent, true, REMOVE_FOR_RECONSTRUCTION,
- nullptr);
+ RecreateFramesForContent(blockContent, InsertionKind::Async,
+ REMOVE_FOR_RECONSTRUCTION);
return true;
}
void
-nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame,
- RemoveFlags aFlags,
- nsIContent** aDestroyedFramesFor)
+nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame,
+ InsertionKind aInsertionKind,
+ RemoveFlags aFlags)
{
#ifdef DEBUG
// ReframeContainingBlock is a NASTY routine, it causes terrible performance problems
// so I want to see when it is happening! Unfortunately, it is happening way to often because
// so much content on the web causes block-in-inline frame situations and we handle them
// very poorly
if (gNoisyContentUpdates) {
@@ -13237,30 +13229,32 @@ nsCSSFrameConstructor::ReframeContaining
// wraps some of its content in an anonymous block; see
// ConstructInline)
// NOTE: We used to get the FloatContainingBlock here, but it was often wrong.
// GetIBContainingBlock works much better and provides the correct container in all cases
// so GetFloatContainingBlock(aFrame) has been removed
// And get the containingBlock's content
- nsCOMPtr<nsIContent> blockContent = containingBlock->GetContent();
- if (blockContent) {
+ if (nsIContent* blockContent = containingBlock->GetContent()) {
#ifdef DEBUG
if (gNoisyContentUpdates) {
printf(" ==> blockContent=%p\n", static_cast<void*>(blockContent));
}
#endif
- return RecreateFramesForContent(blockContent, true, aFlags, aDestroyedFramesFor);
+ RecreateFramesForContent(blockContent->AsElement(), aInsertionKind,
+ REMOVE_FOR_RECONSTRUCTION);
+ return;
}
}
// If we get here, we're screwed!
- return RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
- true, aFlags, nullptr);
+ RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
+ aInsertionKind,
+ REMOVE_FOR_RECONSTRUCTION);
}
void
nsCSSFrameConstructor::GenerateChildFrames(nsContainerFrame* aFrame)
{
{
nsAutoScriptBlocker scriptBlocker;
BeginUpdate();
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -94,18 +94,18 @@ private:
enum Operation {
CONTENTAPPEND,
CONTENTINSERT
};
// aChild is the child being inserted for inserts, and the first
// child being appended for appends.
bool MaybeConstructLazily(Operation aOperation,
- nsIContent* aContainer,
- nsIContent* aChild);
+ nsIContent* aContainer,
+ nsIContent* aChild);
#ifdef DEBUG
void CheckBitsForLazyFrameConstruction(nsIContent* aParent);
#else
void CheckBitsForLazyFrameConstruction(nsIContent*) {}
#endif
// Issues a single ContentInserted for each child of aContainer in the range
@@ -157,18 +157,18 @@ private:
InsertionPoint GetRangeInsertionPoint(nsIContent* aContainer,
nsIContent* aStartChild,
nsIContent* aEndChild,
bool aAllowLazyConstruction,
bool aForReconstruction);
// Returns true if parent was recreated due to frameset child, false otherwise.
bool MaybeRecreateForFrameset(nsIFrame* aParentFrame,
- nsIContent* aStartChild,
- nsIContent* aEndChild);
+ nsIContent* aStartChild,
+ nsIContent* aEndChild);
/**
* For each child in the aStartChild/aEndChild range, calls
* NoteDirtyDescendantsForServo on their flattened tree parents. This is
* used when content is inserted into the document and we decide that
* we can do lazy frame construction. It handles children being rebound to
* different insertion points by calling NoteDirtyDescendantsForServo on each
* child's flattened tree parent. Only used when we are styled by Servo.
@@ -301,16 +301,20 @@ private:
nsIContent* aStartChild,
nsIContent* aEndChild,
nsILayoutHistoryState* aFrameState,
bool aAllowLazyConstruction,
bool aForReconstruction,
TreeMatchContext* aProvidedTreeMatchContext);
public:
+ // FIXME(emilio): How important is it to keep the frame tree state around for
+ // REMOVE_DESTROY_FRAMES?
+ //
+ // Seems like otherwise we could just remove it.
enum RemoveFlags {
REMOVE_CONTENT, REMOVE_FOR_RECONSTRUCTION, REMOVE_DESTROY_FRAMES };
/**
* Recreate or destroy frames for aChild in aContainer.
* aFlags == REMOVE_CONTENT means aChild has been removed from the document.
* aFlags == REMOVE_FOR_RECONSTRUCTION means the caller will reconstruct the
* frames later.
* In both the above cases, this method will in some cases try to reconstruct
@@ -319,22 +323,21 @@ public:
* it. Ancestors may have been reframed though.
* aFlags == REMOVE_DESTROY_FRAMES is the same as REMOVE_FOR_RECONSTRUCTION
* except it will never try to reconstruct frames. Instead, the caller is
* responsible for doing that, on the content returned in aDestroyedFramesFor.
* The layout frame state is guarranted to be captured for the removed frames
* only when aFlags == REMOVE_DESTROY_FRAMES, otherwise it will only be
* captured if we reconstructed frames for an ancestor.
*/
- void ContentRemoved(nsIContent* aContainer,
- nsIContent* aChild,
- nsIContent* aOldNextSibling,
- RemoveFlags aFlags,
- bool* aDidReconstruct,
- nsIContent** aDestroyedFramesFor = nullptr);
+ void ContentRemoved(nsIContent* aContainer,
+ nsIContent* aChild,
+ nsIContent* aOldNextSibling,
+ RemoveFlags aFlags,
+ bool* aDidReconstruct);
void CharacterDataChanged(nsIContent* aContent,
CharacterDataChangeInfo* aInfo);
// 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), stop
// doing that and create a frame for it if it should have one. This recreates
// frames so be careful (although this should not change actual layout).
@@ -356,24 +359,20 @@ public:
void NotifyCounterStylesAreDirty();
// Gets called when the presshell is destroying itself and also
// when we tear down our frame tree to reconstruct it
void WillDestroyFrameTree();
/**
* Destroy the frames for aContent. Note that this may destroy frames
- * for an ancestor instead - aDestroyedFramesFor contains the content node
- * where frames were actually destroyed (which should be used in the
- * ContentInserted call to recreate frames). The frame tree state
- * is captured before the frames are destroyed and can be retrieved using
- * GetLastCapturedLayoutHistoryState().
+ * for an ancestor instead - aDidReconstruct contains whether a reconstruct
+ * was posted for any ancestor.
*/
- void DestroyFramesFor(nsIContent* aContent,
- nsIContent** aDestroyedFramesFor);
+ void DestroyFramesFor(nsIContent* aContent, bool* aDidReconstruct);
// Request to create a continuing frame. This method never returns null.
nsIFrame* CreateContinuingFrame(nsPresContext* aPresContext,
nsIFrame* aFrame,
nsContainerFrame* aParentFrame,
bool aIsFluid = true);
// Copy over fixed frames from aParentFrame's prev-in-flow
@@ -398,25 +397,16 @@ public:
// have a psuedo-element style
nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
// Get the frame that is the parent of the root element.
nsContainerFrame* GetDocElementContainingBlock()
{ return mDocElementContainingBlock; }
- /**
- * Return the layout history state that was captured in the last
- * ContentRemoved / RecreateFramesForContent call.
- */
- nsILayoutHistoryState* GetLastCapturedLayoutHistoryState()
- {
- return mTempFrameTreeState;
- }
-
private:
struct FrameConstructionItem;
class FrameConstructionItemList;
nsContainerFrame* ConstructPageFrame(nsIPresShell* aPresShell,
nsContainerFrame* aParentFrame,
nsIFrame* aPrevPageFrame,
nsContainerFrame*& aCanvasFrame);
@@ -1794,43 +1784,46 @@ private:
* Do nothing for other types of style changes, except for undisplayed nodes
* (display:none/contents) which will have their style context updated in the
* frame manager undisplayed maps.
* @return null if frames were recreated, the new style context otherwise
*/
nsStyleContext* MaybeRecreateFramesForElement(Element* aElement);
/**
+ * Whether insertion should be done synchronously or asynchronously.
+ *
+ * Generally, insertion is synchronous if we're reconstructing something from
+ * frame construction/reconstruction, and async if we're removing stuff, like
+ * from ContentRemoved.
+ */
+ enum class InsertionKind
+ {
+ Sync,
+ Async,
+ };
+
+ /**
* Recreate frames for aContent.
* @param aContent the content to recreate frames for
- * @param aAsyncInsert if true then a restyle event will be posted to handle
- * the required ContentInserted call instead of doing it immediately.
* @param aFlags normally you want to pass REMOVE_FOR_RECONSTRUCTION here
- * @param aDestroyedFramesFor if non-null, it will contain the content that
- * was actually reframed - it may be different than aContent.
*/
- void
- RecreateFramesForContent(nsIContent* aContent,
- bool aAsyncInsert,
- RemoveFlags aFlags,
- nsIContent** aDestroyedFramesFor);
+ void RecreateFramesForContent(nsIContent* aContent,
+ InsertionKind aInsertionKind,
+ RemoveFlags aFlags);
// 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. If this method returns true, *aResult is
- // the return value of ReframeContainingBlock or RecreateFramesForContent. If
- // this method returns false, the value of *aResult is not affected. aFrame
- // and aResult must not be null. aFrame must be the result of a
+ // 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). If this method returns true, aDestroyedFramesFor contains the
- // content that was reframed.
- bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
- RemoveFlags aFlags,
- nsIContent** aDestroyedFramesFor);
+ // not null).
+ bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
+ InsertionKind aInsertionKind,
+ RemoveFlags aFlags);
nsIFrame* CreateContinuingOuterTableFrame(nsIPresShell* aPresShell,
nsPresContext* aPresContext,
nsIFrame* aFrame,
nsContainerFrame* aParentFrame,
nsIContent* aContent,
nsStyleContext* aStyleContext);
@@ -1944,19 +1937,19 @@ private:
// otherwise
bool WipeContainingBlock(nsFrameConstructorState& aState,
nsIFrame* aContainingBlock,
nsIFrame* aFrame,
FrameConstructionItemList& aItems,
bool aIsAppend,
nsIFrame* aPrevSibling);
- void ReframeContainingBlock(nsIFrame* aFrame,
- RemoveFlags aFlags,
- nsIContent** aReframeContent);
+ void ReframeContainingBlock(nsIFrame* aFrame,
+ InsertionKind aInsertionKind,
+ RemoveFlags aFlags);
//----------------------------------------
// Methods support :first-letter style
nsFirstLetterFrame*
CreateFloatingLetterFrame(nsFrameConstructorState& aState,
nsIContent* aTextContent,