diff options
Diffstat (limited to 'layout/generic')
-rw-r--r-- | layout/generic/DetailsFrame.cpp | 9 | ||||
-rw-r--r-- | layout/generic/DetailsFrame.h | 6 | ||||
-rw-r--r-- | layout/generic/ReflowInput.cpp | 3 | ||||
-rw-r--r-- | layout/generic/Selection.h | 4 | ||||
-rw-r--r-- | layout/generic/crashtests/1381134-2.html | 45 | ||||
-rw-r--r-- | layout/generic/crashtests/1381134.html | 45 | ||||
-rw-r--r-- | layout/generic/crashtests/crashtests.list | 2 | ||||
-rw-r--r-- | layout/generic/nsAbsoluteContainingBlock.cpp | 21 | ||||
-rw-r--r-- | layout/generic/nsBlockFrame.cpp | 15 | ||||
-rw-r--r-- | layout/generic/nsFirstLetterFrame.cpp | 3 | ||||
-rw-r--r-- | layout/generic/nsFrame.cpp | 61 | ||||
-rw-r--r-- | layout/generic/nsHTMLParts.h | 3 | ||||
-rw-r--r-- | layout/generic/nsIAnonymousContentCreator.h | 17 | ||||
-rw-r--r-- | layout/generic/nsIFrame.h | 24 | ||||
-rw-r--r-- | layout/generic/nsIFrameInlines.h | 13 | ||||
-rw-r--r-- | layout/generic/nsImageFrame.cpp | 14 | ||||
-rw-r--r-- | layout/generic/nsPlaceholderFrame.cpp | 5 | ||||
-rw-r--r-- | layout/generic/nsSelection.cpp | 103 | ||||
-rw-r--r-- | layout/generic/nsTextFrame.cpp | 3 |
19 files changed, 264 insertions, 132 deletions
diff --git a/layout/generic/DetailsFrame.cpp b/layout/generic/DetailsFrame.cpp index 1d28bbe960..389a476cba 100644 --- a/layout/generic/DetailsFrame.cpp +++ b/layout/generic/DetailsFrame.cpp @@ -129,3 +129,12 @@ DetailsFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, aElements.AppendElement(mDefaultSummary); } } + +bool +DetailsFrame::HasMainSummaryFrame(nsIFrame* aSummaryFrame) +{ + nsIFrame* firstChild = + nsPlaceholderFrame::GetRealFrameFor(mFrames.FirstChild()); + + return aSummaryFrame == firstChild; +} diff --git a/layout/generic/DetailsFrame.h b/layout/generic/DetailsFrame.h index 1eb4ea87be..4ae177f16f 100644 --- a/layout/generic/DetailsFrame.h +++ b/layout/generic/DetailsFrame.h @@ -54,6 +54,12 @@ public: void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, uint32_t aFilter) override; + // Returns true if |aSummaryFrame| is the main summary (i.e. the first child + // of this details frame). + // This function is used when the summary element is removed from the parent + // details element since at that moment the summary element has been already + // removed from the details element children. + bool HasMainSummaryFrame(nsIFrame* aSummaryFrame); private: nsCOMPtr<nsIContent> mDefaultSummary; diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp index 78eca8c6cb..9f7b4368c3 100644 --- a/layout/generic/ReflowInput.cpp +++ b/layout/generic/ReflowInput.cpp @@ -1564,8 +1564,7 @@ ReflowInput::InitAbsoluteConstraints(nsPresContext* aPresContext, // have been if it had been in the flow nsHypotheticalPosition hypotheticalPos; if ((iStartIsAuto && iEndIsAuto) || (bStartIsAuto && bEndIsAuto)) { - nsIFrame* placeholderFrame = - aPresContext->PresShell()->GetPlaceholderFrameFor(mFrame); + nsPlaceholderFrame* placeholderFrame = mFrame->GetPlaceholderFrame(); NS_ASSERTION(placeholderFrame, "no placeholder frame"); if (placeholderFrame->HasAnyStateBits( diff --git a/layout/generic/Selection.h b/layout/generic/Selection.h index 5414d15c12..cc696a7c78 100644 --- a/layout/generic/Selection.h +++ b/layout/generic/Selection.h @@ -31,6 +31,9 @@ class nsHTMLCopyEncoder; namespace mozilla { class ErrorResult; struct AutoPrepareFocusRange; +namespace dom { +class DocGroup; +} // namespace dom } // namespace mozilla struct RangeData @@ -73,6 +76,7 @@ public: nsresult EndBatchChangesInternal(int16_t aReason = nsISelectionListener::NO_REASON); nsIDocument* GetParentObject() const; + DocGroup* GetDocGroup() const; // utility methods for scrolling the selection into view nsPresContext* GetPresContext() const; diff --git a/layout/generic/crashtests/1381134-2.html b/layout/generic/crashtests/1381134-2.html new file mode 100644 index 0000000000..d3ac73507a --- /dev/null +++ b/layout/generic/crashtests/1381134-2.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="UTF-8"> +<script> +addEventListener("DOMContentLoaded", () => { + [d1, d2] = document.getElementsByTagName("div"); + [s1, s2] = document.getElementsByTagName("span") + d3 = document.createElement("div") + d4 = document.createElement("div") + d4.setAttribute("class", "grid") + d3.appendChild(d4) + d1.appendChild(document.createElement("span")) + setTimeout(() => { + d2.removeChild(s2) + setTimeout(() => { + d2.insertBefore(d3, s1) + }, 100) + }, 100) +}) +</script> +<style> +.columns { + columns: 3; +} +.grid { + border:5px solid; + counter-reset: item; +} +.grid * { display:block; } +span { display:contents; } +span::before { content: counter(item) ":before"; } +span::after { content: counter(item) ":after"; } +</style> +</head> +<body> +<div class=columns> +<div class=grid> +<c></c> +<span><c></c></span> +<span><c></c></span> +</div> +</div> +</body> +</html> diff --git a/layout/generic/crashtests/1381134.html b/layout/generic/crashtests/1381134.html new file mode 100644 index 0000000000..a45fa04ecb --- /dev/null +++ b/layout/generic/crashtests/1381134.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="UTF-8"> +<script> +addEventListener("DOMContentLoaded", () => { + [d1, d2] = document.getElementsByTagName("div"); + [s1, s2] = document.getElementsByTagName("span") + d3 = document.createElement("div") + d4 = document.createElement("div") + d4.setAttribute("class", "grid") + d3.appendChild(d4) + d1.appendChild(document.createElement("span")) + setTimeout(() => { + d2.removeChild(s2) + setTimeout(() => { + d2.insertBefore(d3, s1) + }, 100) + }, 100) +}) +</script> +<style> +.columns { + columns: 3; +} +.grid { + display: grid; + border:5px solid; + counter-reset: item; +} +span { display:contents; } +span::before { content: counter(item) ":before"; } +span::after { content: counter(item) ":after"; } +</style> +</head> +<body> +<div class=columns> +<div class=grid> +<c></c> +<span><c></c></span> +<span><c></c></span> +</div> +</div> +</body> +</html> diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index a3c0d62c68..1a597e51c0 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -642,3 +642,5 @@ load 1278461-1.html load 1278461-2.html load 1304441.html load 1316649.html +load 1381134.html +load 1381134-2.html diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index e3c847d01b..a92a2062d5 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -338,17 +338,9 @@ nsAbsoluteContainingBlock::DoMarkFramesDirty(bool aMarkAllDirty) // Given an out-of-flow frame, this method returns the parent frame of // its placeholder frame, if that parent is a nsContainerFrame. static nsContainerFrame* -GetPlaceholderContainer(nsPresContext* aPresContext, - nsIFrame* aPositionedFrame) +GetPlaceholderContainer(nsIFrame* aPositionedFrame) { - MOZ_ASSERT(aPositionedFrame, "need non-null frame"); - MOZ_ASSERT(aPositionedFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW), - "expecting abspos frame"); - MOZ_ASSERT(aPresContext && aPresContext == aPositionedFrame->PresContext(), - "need non-null pres context which matches our frame"); - - nsIFrame* placeholder = - aPresContext->PresShell()->GetPlaceholderFrameFor(aPositionedFrame); + nsIFrame* placeholder = aPositionedFrame->GetPlaceholderFrame(); if (!placeholder) { return nullptr; @@ -557,8 +549,7 @@ nsAbsoluteContainingBlock::ResolveSizeDependentOffsets( aOffsets->IEnd(outerWM) - aMargin.IStartEnd(outerWM) - aKidSize.ISize(outerWM); } else if (aKidReflowInput.mFlags.mIOffsetsNeedCSSAlign) { - placeholderContainer = GetPlaceholderContainer(aPresContext, - aKidReflowInput.mFrame); + placeholderContainer = GetPlaceholderContainer(aKidReflowInput.mFrame); nscoord offset = OffsetToAlignedStaticPos(aKidReflowInput, aKidSize, logicalCBSizeOuterWM, placeholderContainer, @@ -579,8 +570,7 @@ nsAbsoluteContainingBlock::ResolveSizeDependentOffsets( aKidSize.BSize(outerWM); } else if (aKidReflowInput.mFlags.mBOffsetsNeedCSSAlign) { if (!placeholderContainer) { - placeholderContainer = GetPlaceholderContainer(aPresContext, - aKidReflowInput.mFrame); + placeholderContainer = GetPlaceholderContainer(aKidReflowInput.mFrame); } nscoord offset = OffsetToAlignedStaticPos(aKidReflowInput, aKidSize, logicalCBSizeOuterWM, @@ -655,8 +645,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat // due to the multiple coordinate spaces in play, we use a convenience flag // to simply have the child's ReflowInput give it a static position at its // abs.pos. CB origin, and then we'll align & offset it from there. - nsIFrame* placeholder = - aPresContext->PresShell()->GetPlaceholderFrameFor(aKidFrame); + nsIFrame* placeholder = aKidFrame->GetPlaceholderFrame(); if (placeholder && placeholder->GetParent() == aDelegatingFrame) { rsFlags |= ReflowInput::STATIC_POS_IS_CB_ORIGIN; } diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index a37bfc06bd..8fec6cd6a6 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -4336,8 +4336,7 @@ CheckPlaceholderInLine(nsIFrame* aBlock, nsLineBox* aLine, nsFloatCache* aFC) "float in a line should never be a continuation"); NS_ASSERTION(!(aFC->mFloat->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT), "float in a line should never be a pushed float"); - nsIFrame* ph = aBlock->PresContext()->FrameManager()-> - GetPlaceholderFrameFor(aFC->mFloat->FirstInFlow()); + nsIFrame* ph = aFC->mFloat->FirstInFlow()->GetPlaceholderFrame(); for (nsIFrame* f = ph; f; f = f->GetParent()) { if (f->GetParent() == aBlock) return aLine->Contains(f); @@ -4939,9 +4938,8 @@ nsBlockFrame::DrainSelfPushedFloats() if (f->GetPrevContinuation()) { // FIXME } else { - nsPlaceholderFrame *placeholder = - presContext->FrameManager()->GetPlaceholderFrameFor(f); - nsIFrame *floatOriginalParent = presContext->PresShell()-> + nsPlaceholderFrame* placeholder = f->GetPlaceholderFrame(); + nsIFrame* floatOriginalParent = presContext->PresShell()-> FrameConstructor()->GetFloatContainingBlock(placeholder); if (floatOriginalParent != this) { // This is a first continuation that was pushed from one of our @@ -5565,7 +5563,7 @@ FindChildContaining(nsBlockFrame* aFrame, nsIFrame* aFindFrame) return nullptr; if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) break; - aFindFrame = aFrame->PresContext()->FrameManager()->GetPlaceholderFrameFor(child); + aFindFrame = child->GetPlaceholderFrame(); } return child; @@ -6847,9 +6845,8 @@ nsBlockFrame::ChildIsDirty(nsIFrame* aChild) AddStateBits(NS_BLOCK_LOOK_FOR_DIRTY_FRAMES); } else { NS_ASSERTION(aChild->IsFloating(), "should be a float"); - nsIFrame *thisFC = FirstContinuation(); - nsIFrame *placeholderPath = - PresContext()->FrameManager()->GetPlaceholderFrameFor(aChild); + nsIFrame* thisFC = FirstContinuation(); + nsIFrame* placeholderPath = aChild->GetPlaceholderFrame(); // SVG code sometimes sends FrameNeedsReflow notifications during // frame destruction, leading to null placeholders, but we're safe // ignoring those. diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 980e1e9bed..5f561c7593 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -320,8 +320,7 @@ nsFirstLetterFrame::CreateContinuationForFloatingParent(nsPresContext* aPresCont *aContinuation = nullptr; nsIPresShell* presShell = aPresContext->PresShell(); - nsPlaceholderFrame* placeholderFrame = - presShell->FrameManager()->GetPlaceholderFrameFor(this); + nsPlaceholderFrame* placeholderFrame = GetPlaceholderFrame(); nsContainerFrame* parent = placeholderFrame->GetParent(); nsIFrame* continuation = presShell->FrameConstructor()-> diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 0d0c7108cc..ea29c6945e 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -633,8 +633,7 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot) nsIPresShell *shell = presContext->GetPresShell(); if (mState & NS_FRAME_OUT_OF_FLOW) { - nsPlaceholderFrame* placeholder = - shell->FrameManager()->GetPlaceholderFrameFor(this); + nsPlaceholderFrame* placeholder = GetPlaceholderFrame(); NS_ASSERTION(!placeholder || (aDestructRoot != this), "Don't call Destroy() on OOFs, call Destroy() on the placeholder."); NS_ASSERTION(!placeholder || @@ -642,7 +641,6 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot) "Placeholder relationship should have been torn down already; " "this might mean we have a stray placeholder in the tree."); if (placeholder) { - shell->FrameManager()->UnregisterPlaceholderFrame(placeholder); placeholder->SetOutOfFlowFrame(nullptr); } } @@ -8073,9 +8071,8 @@ int32_t nsFrame::GetLineNumber(nsIFrame *aFrame, bool aLockScroll, nsIFrame** aContainingBlock) { NS_ASSERTION(aFrame, "null aFrame"); - nsFrameManager* frameManager = aFrame->PresContext()->FrameManager(); - nsIFrame *blockFrame = aFrame; - nsIFrame *thisBlock; + nsIFrame* blockFrame = aFrame; + nsIFrame* thisBlock; nsAutoLineIterator it; nsresult result = NS_ERROR_FAILURE; while (NS_FAILED(result) && blockFrame) @@ -8088,7 +8085,7 @@ nsFrame::GetLineNumber(nsIFrame *aFrame, bool aLockScroll, nsIFrame** aContainin // abspos continuations don't have placeholders, get the fif thisBlock = thisBlock->FirstInFlow(); } - thisBlock = frameManager->GetPlaceholderFrameFor(thisBlock); + thisBlock = thisBlock->GetPlaceholderFrame(); if (!thisBlock) return -1; } @@ -8918,6 +8915,8 @@ GetIBSplitSiblingForAnonymousBlock(const nsIFrame* aFrame) * * Also skip anonymous scrolled-content parents; inherit directly from the * outer scroll frame. + * + * Also skip NAC parents if the child frame is NAC. */ static nsIFrame* GetCorrectedParent(const nsIFrame* aFrame) @@ -8943,6 +8942,32 @@ GetCorrectedParent(const nsIFrame* aFrame) if (pseudo == nsCSSAnonBoxes::tableWrapper) { pseudo = aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo(); } + + // Prevent NAC from inheriting NAC. This partially duplicates the logic + // implemented in nsCSSFrameConstructor::AddFCItemsForAnonymousContent, and is + // necessary so that restyle inherits style contexts in the same way as the + // initial styling performed in frame construction. + // + // It would be nice to put it in CorrectStyleParentFrame and therefore share + // it, but that would lose the information of whether the _child_ is NAC, + // since CorrectStyleParentFrame only knows about the prospective _parent_. + // This duplication and complexity will go away when we fully switch to the + // Servo style system, where all this can be handled much more naturally. + // + // We need to take special care not to disrupt the style inheritance of frames + // whose content is NAC but who implement a pseudo (like an anonymous + // box, or a non-NAC-backed pseudo like ::first-line) that does not match the + // one that the NAC implements, if any. + nsIContent* content = aFrame->GetContent(); + Element* element = + content && content->IsElement() ? content->AsElement() : nullptr; + if (element && element->IsNativeAnonymous() && !element->IsNativeScrollbarContent() && + element->GetPseudoElementType() == aFrame->StyleContext()->GetPseudoType()) { + while (parent->GetContent() && parent->GetContent()->IsNativeAnonymous()) { + parent = parent->GetInFlowParent(); + } + } + return nsFrame::CorrectStyleParentFrame(parent, pseudo); } @@ -9012,7 +9037,9 @@ nsStyleContext* nsFrame::DoGetParentStyleContext(nsIFrame** aProviderFrame) const { *aProviderFrame = nullptr; - nsFrameManager* fm = PresContext()->FrameManager(); + + // Handle display:contents and the root frame, when there's no parent frame + // to inherit from. if (MOZ_LIKELY(mContent)) { nsIContent* parentContent = mContent->GetFlattenedTreeParent(); if (MOZ_LIKELY(parentContent)) { @@ -9026,6 +9053,7 @@ nsFrame::DoGetParentStyleContext(nsIFrame** aProviderFrame) const /* if next is true then it's really a request for the table frame's parent context, see nsTable[Outer]Frame::GetParentStyleContext. */ pseudo == nsCSSAnonBoxes::tableWrapper) { + nsFrameManager* fm = PresContext()->FrameManager(); nsStyleContext* sc = fm->GetDisplayContentsStyleFor(parentContent); if (MOZ_UNLIKELY(sc)) { return sc; @@ -9062,7 +9090,7 @@ nsFrame::DoGetParentStyleContext(nsIFrame** aProviderFrame) const // 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()); + nsIFrame* placeholder = FirstInFlow()->GetPlaceholderFrame(); if (!placeholder) { NS_NOTREACHED("no placeholder frame for out-of-flow frame"); *aProviderFrame = GetCorrectedParent(this); @@ -9977,19 +10005,16 @@ nsIFrame::IsPseudoStackingContextFromStyle() { Element* nsIFrame::GetPseudoElement(CSSPseudoElementType aType) { - nsIFrame* frame = nullptr; + if (!mContent) { + return nullptr; + } if (aType == CSSPseudoElementType::before) { - frame = nsLayoutUtils::GetBeforeFrame(this); - } else if (aType == CSSPseudoElementType::after) { - frame = nsLayoutUtils::GetAfterFrame(this); + return nsLayoutUtils::GetBeforePseudo(mContent); } - if (frame) { - nsIContent* content = frame->GetContent(); - if (content->IsElement()) { - return content->AsElement(); - } + if (aType == CSSPseudoElementType::after) { + return nsLayoutUtils::GetAfterPseudo(mContent); } return nullptr; diff --git a/layout/generic/nsHTMLParts.h b/layout/generic/nsHTMLParts.h index 89a7a6edde..243c432b2f 100644 --- a/layout/generic/nsHTMLParts.h +++ b/layout/generic/nsHTMLParts.h @@ -11,6 +11,7 @@ #include "nscore.h" #include "nsISupports.h" #include "nsIFrame.h" +class nsComboboxControlFrame; class nsIAtom; class nsNodeInfoManager; class nsIContent; @@ -161,7 +162,7 @@ nsIFrame* NS_NewNativeSelectControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsContainerFrame* NS_NewListControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); -nsContainerFrame* +nsComboboxControlFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, nsFrameState aFlags); nsIFrame* NS_NewProgressFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); diff --git a/layout/generic/nsIAnonymousContentCreator.h b/layout/generic/nsIAnonymousContentCreator.h index e7d4399b6b..5167178b83 100644 --- a/layout/generic/nsIAnonymousContentCreator.h +++ b/layout/generic/nsIAnonymousContentCreator.h @@ -34,12 +34,7 @@ public: mContent(aContent) {} - ContentInfo(nsIContent* aContent, nsStyleContext* aStyleContext) : - mContent(aContent), mStyleContext(aStyleContext) - {} - nsIContent* mContent; - RefPtr<nsStyleContext> mStyleContext; nsTArray<ContentInfo> mChildren; }; @@ -66,18 +61,12 @@ public: * Appends "native" anonymous children created by CreateAnonymousContent() * to the given content list depending on the filter. * - * @see nsIContent::GetChildren for set of values used for filter. + * @see nsIContent::GetChildren for set of values used for filter. Currently, + * eSkipPlaceholderContent is the only flag that any implementation of + * this method heeds. */ virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, uint32_t aFilter) = 0; - - /** - * Implementations can override this method to create special frames for the - * anonymous content returned from CreateAnonymousContent. - * By default this method returns nullptr, which means the default frame - * is created. - */ - virtual nsIFrame* CreateFrameFor(nsIContent* aContent) { return nullptr; } }; #endif diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 93eb95099a..e22dd690a8 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -82,6 +82,7 @@ class nsLineList_iterator; class nsAbsoluteContainingBlock; class nsIContent; class nsContainerFrame; +class nsPlaceholderFrame; struct nsPeekOffsetStruct; struct nsPoint; @@ -721,6 +722,23 @@ public: * Accessor functions for geometric parent. */ nsContainerFrame* GetParent() const { return mParent; } + + /** + * Gets the parent of a frame, using the parent of the placeholder for + * out-of-flow frames. + */ + inline nsContainerFrame* GetInFlowParent(); + + /** + * Return the placeholder for this frame (which must be out-of-flow). + * @note this will only return non-null if |this| is the first-in-flow + * although we don't assert that here for legacy reasons. + */ + inline nsPlaceholderFrame* GetPlaceholderFrame() const { + MOZ_ASSERT(HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)); + return GetProperty(PlaceholderFrameProperty()); + } + /** * Set this frame's parent to aParent. * If the frame may have moved into or out of a scrollframe's @@ -1040,6 +1058,8 @@ public: NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty, mozilla::FrameBidiData) + NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty, nsPlaceholderFrame) + mozilla::FrameBidiData GetBidiData() { return GetProperty(BidiDataProperty()); @@ -1055,10 +1075,6 @@ public: return GetBidiData().embeddingLevel; } - nsTArray<nsIContent*>* GetGenConPseudos() { - return GetProperty(GenConProperty()); - } - /** * Return the distance between the border edge of the frame and the * margin edge of the frame. Like GetRect(), returns the dimensions diff --git a/layout/generic/nsIFrameInlines.h b/layout/generic/nsIFrameInlines.h index eb9a7202a3..a3da7ebca9 100644 --- a/layout/generic/nsIFrameInlines.h +++ b/layout/generic/nsIFrameInlines.h @@ -8,8 +8,10 @@ #define nsIFrameInlines_h___ #include "nsContainerFrame.h" +#include "nsPlaceholderFrame.h" #include "nsStyleStructInlines.h" #include "nsCSSAnonBoxes.h" +#include "nsFrameManager.h" bool nsIFrame::IsFlexItem() const @@ -160,4 +162,15 @@ nsIFrame::BaselineBOffset(mozilla::WritingMode aWM, return SynthesizeBaselineBOffsetFromBorderBox(aWM, aBaselineGroup); } +nsContainerFrame* +nsIFrame::GetInFlowParent() +{ + if (GetStateBits() & NS_FRAME_OUT_OF_FLOW) { + nsIFrame* ph = FirstContinuation()->GetProperty(nsIFrame::PlaceholderFrameProperty()); + return ph->GetParent(); + } + + return GetParent(); +} + #endif diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index c64520f2ea..ee35ecad81 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1836,7 +1836,7 @@ nsImageFrame::ShouldDisplaySelection() int32_t thisOffset = parentContent->IndexOf(mContent); nsCOMPtr<nsIDOMNode> parentNode = do_QueryInterface(parentContent); nsCOMPtr<nsIDOMNode> rangeNode; - int32_t rangeOffset; + uint32_t rangeOffset; nsCOMPtr<nsIDOMRange> range; selection->GetRangeAt(0,getter_AddRefs(range)); if (range) @@ -1844,12 +1844,16 @@ nsImageFrame::ShouldDisplaySelection() range->GetStartContainer(getter_AddRefs(rangeNode)); range->GetStartOffset(&rangeOffset); - if (parentNode && rangeNode && (rangeNode == parentNode) && rangeOffset == thisOffset) - { + if (parentNode && rangeNode && rangeNode == parentNode && + static_cast<int32_t>(rangeOffset) == thisOffset) { range->GetEndContainer(getter_AddRefs(rangeNode)); range->GetEndOffset(&rangeOffset); - if ((rangeNode == parentNode) && (rangeOffset == (thisOffset +1))) //+1 since that would mean this whole content is selected only - return false; //do not allow nsFrame do draw any further selection + // +1 since that would mean this whole content is selected only + if (rangeNode == parentNode && + static_cast<int32_t>(rangeOffset) == thisOffset + 1) { + // Do not allow nsFrame do draw any further selection + return false; + } } } } diff --git a/layout/generic/nsPlaceholderFrame.cpp b/layout/generic/nsPlaceholderFrame.cpp index bd380a2d98..62370a06a4 100644 --- a/layout/generic/nsPlaceholderFrame.cpp +++ b/layout/generic/nsPlaceholderFrame.cpp @@ -156,16 +156,15 @@ nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot) { nsIFrame* oof = mOutOfFlowFrame; if (oof) { - // Unregister out-of-flow frame - nsFrameManager* fm = PresContext()->GetPresShell()->FrameManager(); - fm->UnregisterPlaceholderFrame(this); mOutOfFlowFrame = nullptr; + oof->DeleteProperty(nsIFrame::PlaceholderFrameProperty()); // If aDestructRoot is not an ancestor of the out-of-flow frame, // then call RemoveFrame on it here. // Also destroy it here if it's a popup frame. (Bug 96291) if ((GetStateBits() & PLACEHOLDER_FOR_POPUP) || !nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, oof)) { ChildListID listId = nsLayoutUtils::GetChildListNameFor(oof); + nsFrameManager* fm = PresContext()->GetPresShell()->FrameManager(); fm->RemoveFrame(listId, oof); } // else oof will be destroyed by its parent diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 5ccb2d8bf8..919ab0815a 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -1788,8 +1788,7 @@ nsFrameSelection::TakeFocus(nsIContent* aNewFocus, RefPtr<nsRange> newRange = new nsRange(aNewFocus); - newRange->SetStart(aNewFocus, aContentOffset); - newRange->SetEnd(aNewFocus, aContentOffset); + newRange->CollapseTo(aNewFocus, aContentOffset); mDomSelections[index]->AddRange(newRange); mBatching = batching; mChangesDuringBatching = changes; @@ -3352,10 +3351,11 @@ nsFrameSelection::CreateAndAddRange(nsINode *aParentNode, int32_t aOffset) RefPtr<nsRange> range = new nsRange(aParentNode); // Set range around child at given offset - nsresult result = range->SetStart(aParentNode, aOffset); - if (NS_FAILED(result)) return result; - result = range->SetEnd(aParentNode, aOffset+1); - if (NS_FAILED(result)) return result; + nsresult rv = range->SetStartAndEnd(aParentNode, aOffset, + aParentNode, aOffset + 1); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } int8_t index = GetIndexFromSelectionType(SelectionType::eNormal); if (!mDomSelections[index]) @@ -3521,6 +3521,18 @@ Selection::GetParentObject() const return nullptr; } +DocGroup* +Selection::GetDocGroup() const +{ + nsIPresShell* shell = GetPresShell(); + if (!shell) { + return nullptr; + } + + nsIDocument* doc = shell->GetDocument(); + return doc ? doc->GetDocGroup() : nullptr; +} + NS_IMPL_CYCLE_COLLECTION_CLASS(Selection) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Selection) @@ -3780,13 +3792,12 @@ Selection::SubtractRange(RangeData* aRange, nsRange* aSubtract, // We need to add a new RangeData to the output, running from // the end of aSubtract to the end of range RefPtr<nsRange> postOverlap = new nsRange(aSubtract->GetEndParent()); - - rv = - postOverlap->SetStart(aSubtract->GetEndParent(), aSubtract->EndOffset()); - NS_ENSURE_SUCCESS(rv, rv); - rv = - postOverlap->SetEnd(range->GetEndParent(), range->EndOffset()); - NS_ENSURE_SUCCESS(rv, rv); + rv = postOverlap->SetStartAndEnd( + aSubtract->GetEndParent(), aSubtract->EndOffset(), + range->GetEndParent(), range->EndOffset()); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } if (!postOverlap->Collapsed()) { if (!aOutput->InsertElementAt(0, RangeData(postOverlap))) return NS_ERROR_OUT_OF_MEMORY; @@ -3799,12 +3810,12 @@ Selection::SubtractRange(RangeData* aRange, nsRange* aSubtract, // the start of the range to the start of aSubtract RefPtr<nsRange> preOverlap = new nsRange(range->GetStartParent()); - nsresult rv = - preOverlap->SetStart(range->GetStartParent(), range->StartOffset()); - NS_ENSURE_SUCCESS(rv, rv); - rv = - preOverlap->SetEnd(aSubtract->GetStartParent(), aSubtract->StartOffset()); - NS_ENSURE_SUCCESS(rv, rv); + rv = preOverlap->SetStartAndEnd( + range->GetStartParent(), range->StartOffset(), + aSubtract->GetStartParent(), aSubtract->StartOffset()); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } if (!preOverlap->Collapsed()) { if (!aOutput->InsertElementAt(0, RangeData(preOverlap))) @@ -4120,13 +4131,15 @@ Selection::GetType(int16_t* aType) static inline bool RangeMatchesBeginPoint(nsRange* aRange, nsINode* aNode, int32_t aOffset) { - return aRange->GetStartParent() == aNode && aRange->StartOffset() == aOffset; + return aRange->GetStartParent() == aNode && + static_cast<int32_t>(aRange->StartOffset()) == aOffset; } static inline bool RangeMatchesEndPoint(nsRange* aRange, nsINode* aNode, int32_t aOffset) { - return aRange->GetEndParent() == aNode && aRange->EndOffset() == aOffset; + return aRange->GetEndParent() == aNode && + static_cast<int32_t>(aRange->EndOffset()) == aOffset; } // Selection::EqualsRangeAtPoint @@ -5186,12 +5199,7 @@ Selection::Collapse(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) } RefPtr<nsRange> range = new nsRange(parentNode); - result = range->SetEnd(parentNode, aOffset); - if (NS_FAILED(result)) { - aRv.Throw(result); - return; - } - result = range->SetStart(parentNode, aOffset); + result = range->CollapseTo(parentNode, aOffset); if (NS_FAILED(result)) { aRv.Throw(result); return; @@ -5579,11 +5587,8 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) return; } SetDirection(eDirNext); - res = difRange->SetEnd(range->GetEndParent(), range->EndOffset()); - nsresult tmp = difRange->SetStart(focusNode, focusOffset); - if (NS_FAILED(tmp)) { - res = tmp; - } + res = difRange->SetStartAndEnd(focusNode, focusOffset, + range->GetEndParent(), range->EndOffset()); if (NS_FAILED(res)) { aRv.Throw(res); return; @@ -5611,11 +5616,8 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) } else if (result3 <= 0 && result2 >= 0) {//a,2,1 or a2,1 or a,21 or a21 //deselect from 2 to 1 - res = difRange->SetEnd(focusNode, focusOffset); - difRange->SetStart(aParentNode, aOffset, aRv); - if (aRv.Failed()) { - return; - } + res = difRange->SetStartAndEnd(&aParentNode, aOffset, + focusNode, focusOffset); if (NS_FAILED(res)) { aRv.Throw(res); return; @@ -5678,11 +5680,8 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) } else if (result2 <= 0 && result3 >= 0) {//1,2,a or 12,a or 1,2a or 12a //deselect from 1 to 2 - difRange->SetEnd(aParentNode, aOffset, aRv); - res = difRange->SetStart(focusNode, focusOffset); - if (aRv.Failed()) { - return; - } + res = difRange->SetStartAndEnd(focusNode, focusOffset, + &aParentNode, aOffset); if (NS_FAILED(res)) { aRv.Throw(res); return; @@ -5713,15 +5712,9 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) } //deselect from a to 1 if (focusNode != anchorNode || focusOffset!= anchorOffset) {//if collapsed diff dont do anything - res = difRange->SetStart(anchorNode, anchorOffset); - nsresult tmp = difRange->SetEnd(focusNode, focusOffset); - if (NS_FAILED(tmp)) { - res = tmp; - } - tmp = SetAnchorFocusToRange(range); - if (NS_FAILED(tmp)) { - res = tmp; - } + res = difRange->SetStartAndEnd(anchorNode, anchorOffset, + focusNode, focusOffset); + nsresult tmp = SetAnchorFocusToRange(range); if (NS_FAILED(res)) { aRv.Throw(res); return; @@ -5746,11 +5739,9 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) return; } SetDirection(eDirPrevious); - res = difRange->SetEnd(focusNode, focusOffset); - nsresult tmp = difRange->SetStart(range->GetStartParent(), range->StartOffset()); - if (NS_FAILED(tmp)) { - res = tmp; - } + res = difRange->SetStartAndEnd( + range->GetStartParent(), range->StartOffset(), + focusNode, focusOffset); if (NS_FAILED(res)) { aRv.Throw(res); return; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 59ef020ce2..6875f33e88 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1383,8 +1383,7 @@ BuildTextRuns(DrawTarget* aDrawTarget, nsTextFrame* aForFrame, nsIFrame* lineContainerChild = aForFrame; if (!aLineContainer) { if (aForFrame->IsFloatingFirstLetterChild()) { - lineContainerChild = aForFrame->PresContext()->PresShell()-> - GetPlaceholderFrameFor(aForFrame->GetParent()); + lineContainerChild = aForFrame->GetParent()->GetPlaceholderFrame(); } aLineContainer = FindLineContainer(lineContainerChild); } else { |