--- a/layout/base/GeckoRestyleManager.cpp
+++ b/layout/base/GeckoRestyleManager.cpp
@@ -2481,17 +2481,20 @@ ElementRestyler::RestyleSelf(nsIFrame* a
newContext = prevContinuationContext;
} else if (pseudoTag == nsCSSAnonBoxes::mozText) {
MOZ_ASSERT(aSelf->GetType() == nsGkAtoms::textFrame);
newContext =
styleSet->ResolveStyleForText(aSelf->GetContent(), parentContext);
} else if (pseudoTag == nsCSSAnonBoxes::firstLetterContinuation) {
newContext = styleSet->ResolveStyleForFirstLetterContinuation(parentContext);
} else if (pseudoTag == nsCSSAnonBoxes::oofPlaceholder) {
- newContext = styleSet->ResolveStyleForPlaceholder(parentContext);
+ // We still need to ResolveStyleForPlaceholder() here, because we may be
+ // doing a ruletree reconstruct and hence actually changing our style
+ // context.
+ newContext = styleSet->ResolveStyleForPlaceholder();
}
else {
Element* element = ElementForStyleContext(mParentContent, aSelf, pseudoType);
if (!MustRestyleSelf(aRestyleHint, element)) {
if (CanReparentStyleContext(aRestyleHint)) {
LOG_RESTYLE("reparenting style context");
newContext =
styleSet->ReparentStyleContext(oldContext, parentContext, element);
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -105,17 +105,17 @@ load 344057-1.xhtml
load 344064-1.html
load 344300-1.html
load 344300-2.html
load 344340-1.xul
load 347898-1.html
load 348126-1.html
load 348688-1.html
load 348708-1.xhtml
-asserts(2) asserts-if(stylo,0) load 348729-1.html # bug 548836
+asserts(1) asserts-if(stylo,0) load 348729-1.html # bug 548836
load 349095-1.xhtml
load 350128-1.xhtml
load 350267-1.html
load 354133-1.html
load 354766-1.xhtml
load 354771-1.xul
load 355989-1.xhtml
load 355993-1.xhtml
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1243,18 +1243,17 @@ nsFrameConstructorState::ConstructBackdr
nsFrameState placeholderType;
nsAbsoluteItems* frameItems = GetOutOfFlowFrameItems(backdropFrame,
true, true, false,
&placeholderType);
MOZ_ASSERT(placeholderType == PLACEHOLDER_FOR_TOPLAYER);
nsIFrame* placeholder = nsCSSFrameConstructor::
CreatePlaceholderFrameFor(mPresShell, aContent, backdropFrame,
- frame->StyleContext(), frame, nullptr,
- PLACEHOLDER_FOR_TOPLAYER);
+ frame, nullptr, PLACEHOLDER_FOR_TOPLAYER);
nsFrameList temp(placeholder, placeholder);
frame->SetInitialChildList(nsIFrame::kBackdropList, temp);
frameItems->AddChild(backdropFrame);
}
void
nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
@@ -1286,22 +1285,20 @@ nsFrameConstructorState::AddChild(nsIFra
} else {
frameItems = &aFrameItems;
placeholderType = nsFrameState(0);
}
if (placeholderType) {
NS_ASSERTION(frameItems != &aFrameItems,
"Putting frame in-flow _and_ want a placeholder?");
- nsStyleContext* parentContext = aStyleContext->GetParent();
nsIFrame* placeholderFrame =
nsCSSFrameConstructor::CreatePlaceholderFrameFor(mPresShell,
aContent,
aNewFrame,
- parentContext,
aParentFrame,
nullptr,
placeholderType);
placeholderFrame->AddStateBits(mAdditionalStateBits);
// Add the placeholder frame to the flow
aFrameItems.AddChild(placeholderFrame);
@@ -3029,23 +3026,22 @@ nsCSSFrameConstructor::ConstructPageFram
return pageFrame;
}
/* static */
nsIFrame*
nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell* aPresShell,
nsIContent* aContent,
nsIFrame* aFrame,
- nsStyleContext* aParentStyle,
nsContainerFrame* aParentFrame,
nsIFrame* aPrevInFlow,
nsFrameState aTypeBit)
{
RefPtr<nsStyleContext> placeholderStyle = aPresShell->StyleSet()->
- ResolveStyleForPlaceholder(aParentStyle);
+ ResolveStyleForPlaceholder();
// The placeholder frame gets a pseudo style context
nsPlaceholderFrame* placeholderFrame =
(nsPlaceholderFrame*)NS_NewPlaceholderFrame(aPresShell, placeholderStyle,
aTypeBit);
placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow);
@@ -9124,17 +9120,16 @@ nsCSSFrameConstructor::CreateContinuingF
newFrame->Init(content, aParentFrame, aFrame);
} else if (nsGkAtoms::placeholderFrame == frameType) {
// create a continuing out of flow frame
nsIFrame* oofFrame = nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
nsIFrame* oofContFrame =
CreateContinuingFrame(aPresContext, oofFrame, aParentFrame);
newFrame =
CreatePlaceholderFrameFor(shell, content, oofContFrame,
- styleContext->GetParent(),
aParentFrame, aFrame,
aFrame->GetStateBits() & PLACEHOLDER_TYPE_MASK);
} else if (nsGkAtoms::fieldSetFrame == frameType) {
nsContainerFrame* fieldset = NS_NewFieldSetFrame(shell, styleContext);
fieldset->Init(content, aParentFrame, aFrame);
// Create a continuing area frame
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -1308,17 +1308,16 @@ private:
nsStyleContext* aStyleContext);
// END TABLE SECTION
protected:
static nsIFrame* CreatePlaceholderFrameFor(nsIPresShell* aPresShell,
nsIContent* aContent,
nsIFrame* aFrame,
- nsStyleContext* aParentStyle,
nsContainerFrame* aParentFrame,
nsIFrame* aPrevInFlow,
nsFrameState aTypeBit);
static nsIFrame* CreateBackdropFrameFor(nsIPresShell* aPresShell,
nsIContent* aContent,
nsIFrame* aFrame,
nsContainerFrame* aParentFrame);
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -9288,23 +9288,23 @@ nsFrame::DoGetParentStyleContext(nsIFram
// frame would have if we didn't mangle the frame structure.
*aProviderFrame = GetCorrectedParent(this);
return *aProviderFrame ? (*aProviderFrame)->StyleContext() : nullptr;
}
// We're an out-of-flow frame. For out-of-flow frames, we must
// resolve underneath the placeholder's parent. The placeholder is
// reached from the first-in-flow.
- nsIFrame* placeholder = fm->GetPlaceholderFrameFor(FirstInFlow());
+ nsPlaceholderFrame* placeholder = fm->GetPlaceholderFrameFor(FirstInFlow());
if (!placeholder) {
NS_NOTREACHED("no placeholder frame for out-of-flow frame");
*aProviderFrame = GetCorrectedParent(this);
return *aProviderFrame ? (*aProviderFrame)->StyleContext() : nullptr;
}
- return placeholder->GetParentStyleContext(aProviderFrame);
+ return placeholder->GetParentStyleContextForOutOfFlow(aProviderFrame);
}
void
nsFrame::GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
{
if (!aFrame || !*aFrame) {
return;
}
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -187,17 +187,17 @@ nsPlaceholderFrame::CanContinueTextRun()
return false;
}
// first-letter frames can continue text runs, and placeholders for floated
// first-letter frames can too
return mOutOfFlowFrame->CanContinueTextRun();
}
nsStyleContext*
-nsPlaceholderFrame::GetParentStyleContext(nsIFrame** aProviderFrame) const
+nsPlaceholderFrame::GetParentStyleContextForOutOfFlow(nsIFrame** aProviderFrame) const
{
NS_PRECONDITION(GetParent(), "How can we not have a parent here?");
nsIContent* parentContent = mContent ? mContent->GetFlattenedTreeParent() : nullptr;
if (parentContent) {
nsStyleContext* sc =
PresContext()->FrameManager()->GetDisplayContentsStyleFor(parentContent);
if (sc) {
--- a/layout/generic/nsPlaceholderFrame.h
+++ b/layout/generic/nsPlaceholderFrame.h
@@ -132,17 +132,17 @@ public:
virtual mozilla::a11y::AccType AccessibleType() override
{
nsIFrame* realFrame = GetRealFrameForPlaceholder(this);
return realFrame ? realFrame->AccessibleType() :
nsFrame::AccessibleType();
}
#endif
- virtual nsStyleContext* GetParentStyleContext(nsIFrame** aProviderFrame) const override;
+ nsStyleContext* GetParentStyleContextForOutOfFlow(nsIFrame** aProviderFrame) const;
bool RenumberFrameAndDescendants(int32_t* aOrdinal,
int32_t aDepth,
int32_t aIncrement,
bool aForCounting) override
{
return mOutOfFlowFrame->
RenumberFrameAndDescendants(aOrdinal, aDepth, aIncrement, aForCounting);
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -263,30 +263,37 @@ ServoStyleSet::ResolveStyleForFirstLette
return GetContext(computedValues.forget(), aParentContext,
nsCSSAnonBoxes::firstLetterContinuation,
CSSPseudoElementType::AnonBox,
nullptr);
}
already_AddRefed<nsStyleContext>
-ServoStyleSet::ResolveStyleForPlaceholder(nsStyleContext* aParentContext)
+ServoStyleSet::ResolveStyleForPlaceholder()
{
- // The parent context can be null if the placeholder's element is a root
- // element.
- const ServoComputedValues* parent =
- aParentContext ? aParentContext->StyleSource().AsServoComputedValues() : nullptr;
+ RefPtr<nsStyleContext>& cache =
+ mNonInheritingStyleContexts[
+ static_cast<nsCSSAnonBoxes::NonInheritingBase>(nsCSSAnonBoxes::NonInheriting::oofPlaceholder)];
+ if (cache) {
+ RefPtr<nsStyleContext> retval = cache;
+ return retval.forget();
+ }
+
RefPtr<ServoComputedValues> computedValues =
- Servo_ComputedValues_Inherit(mRawSet.get(), parent).Consume();
+ Servo_ComputedValues_Inherit(mRawSet.get(), nullptr).Consume();
MOZ_ASSERT(computedValues);
- return GetContext(computedValues.forget(), aParentContext,
- nsCSSAnonBoxes::oofPlaceholder,
- CSSPseudoElementType::AnonBox,
- nullptr);
+ RefPtr<nsStyleContext> retval =
+ GetContext(computedValues.forget(), nullptr,
+ nsCSSAnonBoxes::oofPlaceholder,
+ CSSPseudoElementType::AnonBox,
+ nullptr);
+ cache = retval;
+ return retval.forget();
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
CSSPseudoElementType aType,
nsStyleContext* aParentContext,
Element* aPseudoElement)
{
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -109,20 +109,20 @@ public:
ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext);
// Get a style context for a placeholder frame (which no rules will match).
//
// The returned style context will have nsCSSAnonBoxes::oofPlaceholder as
// its pseudo.
//
// (Perhaps nsCSSAnonBoxes::oofPaceholder should go away and we shouldn't even
- // create style contexts for placeholders. However, not doing
- // any rule matching for them is a first step.)
+ // create style contexts for placeholders. However, not doing any rule
+ // matching for them is a first step.)
already_AddRefed<nsStyleContext>
- ResolveStyleForPlaceholder(nsStyleContext* aParentContext);
+ ResolveStyleForPlaceholder();
// Get a style context for a pseudo-element. aParentElement must be
// non-null. aPseudoID is the CSSPseudoElementType for the
// pseudo-element. aPseudoElement must be non-null if the pseudo-element
// type is one that allows user action pseudo-classes after it or allows
// style attributes; otherwise, it is ignored.
already_AddRefed<nsStyleContext>
ResolvePseudoElementStyle(dom::Element* aOriginatingElement,
--- a/layout/style/StyleSetHandle.h
+++ b/layout/style/StyleSetHandle.h
@@ -123,17 +123,17 @@ public:
LazyComputeBehavior aMayCompute,
TreeMatchContext& aTreeMatchContext);
inline already_AddRefed<nsStyleContext>
ResolveStyleForText(nsIContent* aTextNode,
nsStyleContext* aParentContext);
inline already_AddRefed<nsStyleContext>
ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext);
inline already_AddRefed<nsStyleContext>
- ResolveStyleForPlaceholder(nsStyleContext* aParentContext);
+ ResolveStyleForPlaceholder();
inline already_AddRefed<nsStyleContext>
ResolvePseudoElementStyle(dom::Element* aParentElement,
mozilla::CSSPseudoElementType aType,
nsStyleContext* aParentContext,
dom::Element* aPseudoElement);
inline already_AddRefed<nsStyleContext>
ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext,
uint32_t aFlags = 0);
--- a/layout/style/StyleSetHandleInlines.h
+++ b/layout/style/StyleSetHandleInlines.h
@@ -97,19 +97,19 @@ StyleSetHandle::Ptr::ResolveStyleFor(dom
already_AddRefed<nsStyleContext>
StyleSetHandle::Ptr::ResolveStyleForText(nsIContent* aTextNode,
nsStyleContext* aParentContext)
{
FORWARD(ResolveStyleForText, (aTextNode, aParentContext));
}
already_AddRefed<nsStyleContext>
-StyleSetHandle::Ptr::ResolveStyleForPlaceholder(nsStyleContext* aParentContext)
+StyleSetHandle::Ptr::ResolveStyleForPlaceholder()
{
- FORWARD(ResolveStyleForPlaceholder, (aParentContext));
+ FORWARD(ResolveStyleForPlaceholder, ());
}
already_AddRefed<nsStyleContext>
StyleSetHandle::Ptr::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
{
FORWARD(ResolveStyleForFirstLetterContinuation, (aParentContext));
}
--- a/layout/style/nsCSSAnonBoxList.h
+++ b/layout/style/nsCSSAnonBoxList.h
@@ -33,17 +33,17 @@
#endif /* CSS_NON_INHERITING_ANON_BOX */
// ::-moz-text, ::-moz-oof-placeholder, and ::-moz-first-letter-continuation are
// non-elements which no rule will match.
CSS_ANON_BOX(mozText, ":-moz-text")
// placeholder frames for out of flows. Note that :-moz-placeholder is used for
// the pseudo-element that represents the placeholder text in <input
// placeholder="foo">, so we need a different string here.
-CSS_ANON_BOX(oofPlaceholder, ":-moz-oof-placeholder")
+CSS_NON_INHERITING_ANON_BOX(oofPlaceholder, ":-moz-oof-placeholder")
// nsFirstLetterFrames for content outside the ::first-letter.
CSS_ANON_BOX(firstLetterContinuation, ":-moz-first-letter-continuation")
CSS_ANON_BOX(mozAnonymousBlock, ":-moz-anonymous-block")
CSS_ANON_BOX(mozAnonymousPositionedBlock, ":-moz-anonymous-positioned-block")
CSS_ANON_BOX(mozMathMLAnonymousBlock, ":-moz-mathml-anonymous-block")
CSS_ANON_BOX(mozXULAnonymousBlock, ":-moz-xul-anonymous-block")
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -1836,21 +1836,32 @@ already_AddRefed<nsStyleContext>
nsStyleSet::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
{
return GetContext(aParentContext, mRuleTree, nullptr,
nsCSSAnonBoxes::firstLetterContinuation,
CSSPseudoElementType::AnonBox, nullptr, eNoFlags);
}
already_AddRefed<nsStyleContext>
-nsStyleSet::ResolveStyleForPlaceholder(nsStyleContext* aParentContext)
+nsStyleSet::ResolveStyleForPlaceholder()
{
- return GetContext(aParentContext, mRuleTree, nullptr,
- nsCSSAnonBoxes::oofPlaceholder,
- CSSPseudoElementType::AnonBox, nullptr, eNoFlags);
+ RefPtr<nsStyleContext>& cache =
+ mNonInheritingStyleContexts[
+ static_cast<nsCSSAnonBoxes::NonInheritingBase>(nsCSSAnonBoxes::NonInheriting::oofPlaceholder)];
+ if (cache) {
+ RefPtr<nsStyleContext> retval = cache;
+ return retval.forget();
+ }
+
+ RefPtr<nsStyleContext> retval =
+ GetContext(nullptr, mRuleTree, nullptr,
+ nsCSSAnonBoxes::oofPlaceholder,
+ CSSPseudoElementType::AnonBox, nullptr, eNoFlags);
+ cache = retval;
+ return retval.forget();
}
void
nsStyleSet::WalkRestrictionRule(CSSPseudoElementType aPseudoType,
nsRuleWalker* aRuleWalker)
{
// This needs to match GetPseudoRestriction in nsRuleNode.cpp.
aRuleWalker->SetLevel(SheetType::Agent, false, false);
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -227,17 +227,17 @@ class nsStyleSet final
//
// The returned style context will have nsCSSAnonBoxes::oofPlaceholder as
// its pseudo.
//
// (Perhaps nsCSSAnonBoxes::oofPlaceholder should go away and we shouldn't
// even create style contexts for placeholders. However, not doing any rule
// matching for them is a first step.)
already_AddRefed<nsStyleContext>
- ResolveStyleForPlaceholder(nsStyleContext* aParentContext);
+ ResolveStyleForPlaceholder();
// Get a style context for a pseudo-element. aParentElement must be
// non-null. aPseudoID is the CSSPseudoElementType for the
// pseudo-element. aPseudoElement must be non-null if the pseudo-element
// type is one that allows user action pseudo-classes after it or allows
// style attributes; otherwise, it is ignored.
already_AddRefed<nsStyleContext>
ResolvePseudoElementStyle(mozilla::dom::Element* aParentElement,
--- a/layout/xul/tree/nsTreeStyleCache.cpp
+++ b/layout/xul/tree/nsTreeStyleCache.cpp
@@ -78,17 +78,17 @@ nsTreeStyleCache::GetStyleContext(nsICSS
}
if (!result) {
// We missed the cache. Resolve this pseudo-style.
// XXXheycam ServoStyleSets do not support XUL tree styles.
RefPtr<nsStyleContext> newResult;
if (aPresContext->StyleSet()->IsServo()) {
NS_ERROR("stylo: ServoStyleSets should not support XUL tree styles yet");
newResult = aPresContext->StyleSet()->
- ResolveStyleForPlaceholder(aContext);
+ ResolveStyleForPlaceholder();
} else {
newResult = aPresContext->StyleSet()->AsGecko()->
ResolveXULTreePseudoStyle(aContent->AsElement(), aPseudoElement,
aContext, aComparator);
}
// Put the style context in our table, transferring the owning reference to the table.
if (!mCache) {