Bug 1343078 part 7. Make placeholders a non-inheriting anon box. r=dbaron
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 08 Mar 2017 00:18:40 -0500
changeset 346444 afd58f4674d1fdc102e1887b7dbcc13a0c255fc2
parent 346443 930853cae5a4933387751ac54caccd29b8f4a41e
child 346445 74bd66f2490e43cb9dfc9a8dbc4a0f01a2629126
push id31467
push usercbook@mozilla.com
push dateWed, 08 Mar 2017 13:18:20 +0000
treeherdermozilla-central@becff35a0bed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1343078
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1343078 part 7. Make placeholders a non-inheriting anon box. r=dbaron MozReview-Commit-ID: 3kQQroDRlr8
layout/base/GeckoRestyleManager.cpp
layout/base/crashtests/crashtests.list
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/generic/nsFrame.cpp
layout/generic/nsPlaceholderFrame.cpp
layout/generic/nsPlaceholderFrame.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/StyleSetHandle.h
layout/style/StyleSetHandleInlines.h
layout/style/nsCSSAnonBoxList.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
layout/xul/tree/nsTreeStyleCache.cpp
--- 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) {