diff --git a/dom/base/nsIContent.h b/dom/base/nsIContent.h index 78711472f..eb7cf5bfa 100644 --- a/dom/base/nsIContent.h +++ b/dom/base/nsIContent.h @@ -870,12 +870,9 @@ public: { return (IsInDoc() || IsInShadowTree()) ? mPrimaryFrame : nullptr; } - void SetPrimaryFrame(nsIFrame* aFrame) { - MOZ_ASSERT(IsInDoc() || IsInShadowTree(), "This will end badly!"); - NS_PRECONDITION(!aFrame || !mPrimaryFrame || aFrame == mPrimaryFrame, - "Losing track of existing primary frame"); - mPrimaryFrame = aFrame; - } + + // Defined in nsIContentInlines.h because it needs nsIFrame. + inline void SetPrimaryFrame(nsIFrame* aFrame); nsresult LookupNamespaceURIInternal(const nsAString& aNamespacePrefix, nsAString& aNamespaceURI) const; diff --git a/dom/base/nsIContentInlines.h b/dom/base/nsIContentInlines.h index 67391a713..4762942e9 100644 --- a/dom/base/nsIContentInlines.h +++ b/dom/base/nsIContentInlines.h @@ -9,6 +9,8 @@ #include "nsIContent.h" #include "nsIDocument.h" +#include "nsContentUtils.h" +#include "nsIFrame.h" inline bool nsIContent::IsInHTMLDocument() const @@ -16,4 +18,20 @@ nsIContent::IsInHTMLDocument() const return OwnerDoc()->IsHTMLDocument(); } +inline void +nsIContent::SetPrimaryFrame(nsIFrame* aFrame) +{ + MOZ_ASSERT(IsInUncomposedDoc() || IsInShadowTree(), "This will end badly!"); + NS_PRECONDITION(!aFrame || !mPrimaryFrame || aFrame == mPrimaryFrame, + "Losing track of existing primary frame"); + + if (aFrame) { + aFrame->SetIsPrimaryFrame(true); + } else if (nsIFrame* currentPrimaryFrame = GetPrimaryFrame()) { + currentPrimaryFrame->SetIsPrimaryFrame(false); + } + + mPrimaryFrame = aFrame; +} + #endif // nsIContentInlines_h diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 7cb5279bc..8e7e83f6f 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -109,6 +109,7 @@ #include "nsRuleProcessorData.h" #include "nsTextNode.h" #include "ActiveLayerTracker.h" +#include "nsIContentInlines.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index ab6f4251c..bb3f2778e 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -47,6 +47,7 @@ #include "mozilla/MouseEvents.h" #include "mozilla/unused.h" #include "gfx2DGlue.h" +#include "nsIContentInlines.h" #ifdef XP_WIN #define COMBOBOX_ROLLUP_CONSUME_EVENT 0 diff --git a/layout/forms/nsGfxButtonControlFrame.cpp b/layout/forms/nsGfxButtonControlFrame.cpp index 73b568926..0c10b6b90 100644 --- a/layout/forms/nsGfxButtonControlFrame.cpp +++ b/layout/forms/nsGfxButtonControlFrame.cpp @@ -14,6 +14,7 @@ #include "nsIDOMHTMLInputElement.h" #include "nsTextNode.h" +#include "nsIContentInlines.h" using namespace mozilla; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index f549ed6a8..20e7a892f 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -23,6 +23,7 @@ #include "nsFrameList.h" #include "nsPlaceholderFrame.h" #include "nsIContent.h" +#include "nsIContentInlines.h" #include "nsContentUtils.h" #include "nsIAtom.h" #include "nsString.h" @@ -398,6 +399,7 @@ nsFrame::nsFrame(nsStyleContext* aContext) mState = NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY; mMayHaveRoundedCorners = false; mReflowRequestedForCharDataChange = false; + mIsPrimaryFrame = false; mStyleContext = aContext; mStyleContext->AddRef(); #ifdef DEBUG @@ -663,6 +665,13 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot) } } + // from bug 1381157 + // XXXneerja All instances of 'mContent->GetPrimaryFrame() == this' have been + // replaced with IsPrimaryFrame() except for this one. The reason is that + // for native anonymous content our subclass Destroy method has already + // called UnbindFromTree so nsINode::mSubtreeRoot might be in use here and + // we don't want to call mContent->SetPrimaryFrame(nullptr) in that case. + // (bug 1400618 will fix that order) bool isPrimaryFrame = (mContent && mContent->GetPrimaryFrame() == this); if (isPrimaryFrame) { // This needs to happen before shell->NotifyDestroyingFrame because @@ -1096,7 +1105,7 @@ nsIFrame::IsTransformed() const EffectCompositor::HasAnimationsForCompositor( this, eCSSProperty_transform) && IsFrameOfType(eSupportsCSSTransforms) && - mContent->GetPrimaryFrame() == this))); + IsPrimaryFrame()))); } bool @@ -1109,7 +1118,7 @@ nsIFrame::HasOpacityInternal(float aThreshold) const (mContent && EffectCompositor::HasAnimationsForCompositor( this, eCSSProperty_opacity) && - mContent->GetPrimaryFrame() == this); + IsPrimaryFrame()); } bool @@ -8285,7 +8294,7 @@ nsFrame::DoGetParentStyleContext(nsIFrame** aProviderFrame) const // Ensure that we don't return the display:contents style // of the parent content for pseudos that have the same content // as their primary frame (like -moz-list-bullets do): - mContent->GetPrimaryFrame() == this) || + IsPrimaryFrame()) || /* if next is true then it's really a request for the table frame's parent context, see nsTable[Outer]Frame::GetParentStyleContext. */ pseudo == nsCSSAnonBoxes::tableOuter) { diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 36c37e0ef..158b916ad 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -40,6 +40,7 @@ #include "mozilla/LookAndFeel.h" #include "mozilla/MouseEvents.h" #include "nsSubDocumentFrame.h" +#include "nsIContentInlines.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index eddf73067..9ec946e3c 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1416,6 +1416,13 @@ public: return mState & aBits; } + /** + * Return true if this frame is the primary frame for mContent. + */ + bool IsPrimaryFrame() const { return mIsPrimaryFrame; } + + void SetIsPrimaryFrame(bool aIsPrimary) { mIsPrimaryFrame = aIsPrimary; } + /** * This call is invoked on the primary frame for a character data content * node, when it is changed in the content tree. @@ -3171,6 +3178,14 @@ protected: */ bool mReflowRequestedForCharDataChange : 1; +private: + /** + * True if this is the primary frame for mContent. + */ + bool mIsPrimaryFrame : 1; + +protected: + // Helpers /** * Can we stop inside this frame when we're skipping non-rendered whitespace? diff --git a/layout/generic/nsImageMap.cpp b/layout/generic/nsImageMap.cpp index 7c3bce4fb..74d669edf 100644 --- a/layout/generic/nsImageMap.cpp +++ b/layout/generic/nsImageMap.cpp @@ -22,6 +22,7 @@ #include "nsIStringBundle.h" #include "nsContentUtils.h" #include "ImageLayers.h" +#include "nsIContentInlines.h" #ifdef ACCESSIBILITY #include "nsAccessibilityService.h" diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index 49ef0ceb7..1969d5a56 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -41,6 +41,7 @@ #include "nsIPermissionManager.h" #include "nsServiceManagerUtils.h" #include "nsIDOMMutationEvent.h" +#include "nsIContentInlines.h" using namespace mozilla; using mozilla::layout::RenderFrameParent;