Backed out 3 changesets (bug 1725555) for causing crashes in nsTextFrame.

CLOSED TREE

Backed out changeset d0864a5c8e90 (bug 1725555)
Backed out changeset 22b941581212 (bug 1725555)
Backed out changeset f2357e055668 (bug 1725555)
This commit is contained in:
Alexandru Michis 2021-08-26 20:43:41 +03:00
Родитель df1cf61b96
Коммит 010cf9dd17
3 изменённых файлов: 28 добавлений и 157 удалений

Просмотреть файл

@ -2647,16 +2647,10 @@ static nsresult GetPartialTextRect(RectCallback* aCallback,
if (textFrame) {
nsIFrame* relativeTo =
nsLayoutUtils::GetContainingBlockForClientRect(textFrame);
for (nsTextFrame* f = textFrame->FindContinuationForOffset(aStartOffset); f;
for (nsTextFrame* f = textFrame; f;
f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
int32_t fstart = f->GetContentOffset(), fend = f->GetContentEnd();
if (fend <= aStartOffset) {
continue;
}
if (fstart >= aEndOffset) {
break;
}
if (fend <= aStartOffset || fstart >= aEndOffset) continue;
// Calculate the text content offsets we'll need if text is requested.
int32_t textContentStart = fstart;

Просмотреть файл

@ -4384,35 +4384,6 @@ void nsTextFrame::DestroyFrom(nsIFrame* aDestructRoot,
nsIFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}
nsTArray<nsTextFrame*>* nsTextFrame::GetContinuations() {
MOZ_ASSERT(NS_IsMainThread());
// Only for use on the primary frame, which has no prev-continuation.
MOZ_ASSERT(!GetPrevContinuation());
if (!mNextContinuation) {
return nullptr;
}
if (mHasContinuationsProperty) {
return GetProperty(ContinuationsProperty());
}
size_t count = 0;
for (nsIFrame* f = this; f; f = f->GetNextContinuation()) {
++count;
}
auto* continuations = new nsTArray<nsTextFrame*>;
if (continuations->SetCapacity(count, fallible)) {
for (nsTextFrame* f = this; f;
f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
continuations->AppendElement(f);
}
} else {
delete continuations;
continuations = nullptr;
}
AddProperty(ContinuationsProperty(), continuations);
mHasContinuationsProperty = true;
return continuations;
}
class nsContinuingTextFrame final : public nsTextFrame {
public:
NS_DECL_FRAMEARENA_HELPERS(nsContinuingTextFrame)
@ -4427,7 +4398,6 @@ class nsContinuingTextFrame final : public nsTextFrame {
PostDestroyData& aPostDestroyData) final;
nsTextFrame* GetPrevContinuation() const final { return mPrevContinuation; }
void SetPrevContinuation(nsIFrame* aPrevContinuation) final {
NS_ASSERTION(!aPrevContinuation || Type() == aPrevContinuation->Type(),
"setting a prev continuation with incorrect type!");
@ -4436,32 +4406,11 @@ class nsContinuingTextFrame final : public nsTextFrame {
"creating a loop in continuation chain!");
mPrevContinuation = static_cast<nsTextFrame*>(aPrevContinuation);
RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
nsTextFrame* prevFirst = mFirstContinuation;
if (mPrevContinuation) {
mFirstContinuation = mPrevContinuation->FirstContinuation();
if (mFirstContinuation) {
mFirstContinuation->ClearCachedContinuations();
}
} else {
mFirstContinuation = nullptr;
}
if (mFirstContinuation != prevFirst) {
if (prevFirst) {
prevFirst->ClearCachedContinuations();
}
auto* f = static_cast<nsContinuingTextFrame*>(mNextContinuation);
while (f) {
f->mFirstContinuation = mFirstContinuation;
f = static_cast<nsContinuingTextFrame*>(f->mNextContinuation);
}
}
}
nsTextFrame* GetPrevInFlow() const final {
return HasAnyStateBits(NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation
: nullptr;
}
void SetPrevInFlow(nsIFrame* aPrevInFlow) final {
NS_ASSERTION(!aPrevInFlow || Type() == aPrevInFlow->Type(),
"setting a prev in flow with incorrect type!");
@ -4470,33 +4419,9 @@ class nsContinuingTextFrame final : public nsTextFrame {
"creating a loop in continuation chain!");
mPrevContinuation = static_cast<nsTextFrame*>(aPrevInFlow);
AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
nsTextFrame* prevFirst = mFirstContinuation;
if (mPrevContinuation) {
mFirstContinuation = mPrevContinuation->FirstContinuation();
if (mFirstContinuation) {
mFirstContinuation->ClearCachedContinuations();
}
} else {
mFirstContinuation = nullptr;
}
if (mFirstContinuation != prevFirst) {
if (prevFirst) {
prevFirst->ClearCachedContinuations();
}
auto* f = static_cast<nsContinuingTextFrame*>(mNextContinuation);
while (f) {
f->mFirstContinuation = mFirstContinuation;
f = static_cast<nsContinuingTextFrame*>(f->mNextContinuation);
}
}
}
nsIFrame* FirstInFlow() const final;
nsTextFrame* FirstContinuation() const final {
MOZ_DIAGNOSTIC_ASSERT(mFirstContinuation || !mPrevContinuation,
"mFirstContinuation unexpectedly null!");
return mFirstContinuation;
};
nsIFrame* FirstContinuation() const final;
void AddInlineMinISize(gfxContext* aRenderingContext,
InlineMinISizeData* aData) final;
@ -4509,7 +4434,6 @@ class nsContinuingTextFrame final : public nsTextFrame {
: nsTextFrame(aStyle, aPresContext, kClassID) {}
nsTextFrame* mPrevContinuation;
nsTextFrame* mFirstContinuation = nullptr;
};
void nsContinuingTextFrame::Init(nsIContent* aContent,
@ -4612,6 +4536,23 @@ nsIFrame* nsContinuingTextFrame::FirstInFlow() const {
return firstInFlow;
}
nsIFrame* nsContinuingTextFrame::FirstContinuation() const {
// Can't cast to |nsContinuingTextFrame*| because the first one isn't.
nsIFrame *firstContinuation,
*previous = const_cast<nsIFrame*>(
static_cast<const nsIFrame*>(mPrevContinuation));
NS_ASSERTION(previous,
"How can an nsContinuingTextFrame be the first continuation?");
do {
firstContinuation = previous;
previous = firstContinuation->GetPrevContinuation();
} while (previous);
MOZ_ASSERT(firstContinuation, "post-condition failed");
return firstContinuation;
}
// XXX Do we want to do all the work for the first-in-flow or do the
// work for each part? (Be careful of first-letter / first-line, though,
// especially first-line!) Doing all the work on the first-in-flow has
@ -7505,33 +7446,6 @@ bool nsTextFrame::IsFrameSelected() const {
return mIsSelected == nsTextFrame::SelectionState::Selected;
}
nsTextFrame* nsTextFrame::FindContinuationForOffset(int32_t aOffset) {
// Use a continuations array to accelerate finding the first continuation
// of interest, if possible.
MOZ_ASSERT(!GetPrevContinuation(), "should be called on the primary frame");
auto* continuations = GetContinuations();
nsTextFrame* f = this;
if (continuations) {
size_t index;
if (BinarySearchIf(
*continuations, 0, continuations->Length(),
[=](nsTextFrame* aFrame) -> int {
return aOffset - aFrame->GetContentOffset();
},
&index)) {
f = (*continuations)[index];
} else {
f = (*continuations)[index ? index - 1 : 0];
}
}
while (f && f->GetContentEnd() <= aOffset) {
f = f->GetNextContinuation();
}
return f;
}
void nsTextFrame::SelectionStateChanged(uint32_t aStart, uint32_t aEnd,
bool aSelected,
SelectionType aSelectionType) {
@ -7542,11 +7456,12 @@ void nsTextFrame::SelectionStateChanged(uint32_t aStart, uint32_t aEnd,
InvalidateSelectionState();
// Selection is collapsed, which can't affect text frame rendering
if (aStart == aEnd) {
return;
}
if (aStart == aEnd) return;
nsTextFrame* f = FindContinuationForOffset(aStart);
nsTextFrame* f = this;
while (f && f->GetContentEnd() <= int32_t(aStart)) {
f = f->GetNextContinuation();
}
nsPresContext* presContext = PresContext();
while (f && f->GetContentOffset() < int32_t(aEnd)) {
@ -8950,13 +8865,8 @@ static void RemoveEmptyInFlows(nsTextFrame* aFrame,
prevContinuation->SetNextInFlow(aFirstToNotRemove);
aFirstToNotRemove->SetPrevInFlow(prevContinuation);
// **Note: it is important here that we clear the Next link from lastRemoved
// BEFORE clearing the Prev link from aFrame, because SetPrevInFlow() will
// follow the Next pointers, wiping out the cached mFirstContinuation field
// from each following frame in the list. We need this to stop when it
// reaches lastRemoved!
lastRemoved->SetNextInFlow(nullptr);
aFrame->SetPrevInFlow(nullptr);
lastRemoved->SetNextInFlow(nullptr);
nsContainerFrame* parent = aFrame->GetParent();
nsBlockFrame* parentBlock = do_QueryFrame(parent);
@ -9188,12 +9098,6 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS);
mReflowRequestedForCharDataChange = false;
RemoveProperty(WebRenderTextBounds());
// Discard cached continuations array that will be invalidated by the reflow.
if (nsTextFrame* first = FirstContinuation()) {
first->ClearCachedContinuations();
}
// Temporarily map all possible content while we construct our new textrun.
// so that when doing reflow our styles prevail over any part of the
// textrun we look at. Note that next-in-flows may be mapping the same

Просмотреть файл

@ -214,9 +214,6 @@ class nsTextFrame : public nsIFrame {
// nsQueryFrame
NS_DECL_QUERYFRAME
NS_DECLARE_FRAME_PROPERTY_DELETABLE(ContinuationsProperty,
nsTArray<nsTextFrame*>)
// nsIFrame
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) final;
@ -231,9 +228,6 @@ class nsTextFrame : public nsIFrame {
nsresult CharacterDataChanged(const CharacterDataChangeInfo&) final;
nsTextFrame* FirstContinuation() const override {
return const_cast<nsTextFrame*>(this);
}
nsTextFrame* GetPrevContinuation() const override { return nullptr; }
nsTextFrame* GetNextContinuation() const final { return mNextContinuation; }
void SetNextContinuation(nsIFrame* aNextContinuation) final {
@ -784,12 +778,6 @@ class nsTextFrame : public nsIFrame {
nsRect WebRenderBounds();
// Find the continuation (which may be this frame itself) containing the
// given offset. Note that this may return null, if the offset is beyond the
// text covered by the continuation chain.
// (To be used only on the first textframe in the chain.)
nsTextFrame* FindContinuationForOffset(int32_t aOffset);
protected:
virtual ~nsTextFrame();
@ -824,9 +812,6 @@ class nsTextFrame : public nsIFrame {
};
mutable SelectionState mIsSelected;
// Whether a cached continuations array is present.
bool mHasContinuationsProperty = false;
/**
* Return true if the frame is part of a Selection.
* Helper method to implement the public IsSelected() API.
@ -1011,20 +996,6 @@ class nsTextFrame : public nsIFrame {
void ClearMetrics(ReflowOutput& aMetrics);
// Return pointer to an array of all frames in the continuation chain, or
// null if we're too short of memory.
nsTArray<nsTextFrame*>* GetContinuations();
// Clear any cached continuations array; this should be called whenever the
// chain is modified.
void ClearCachedContinuations() {
MOZ_ASSERT(NS_IsMainThread());
if (mHasContinuationsProperty) {
RemoveProperty(ContinuationsProperty());
mHasContinuationsProperty = false;
}
}
/**
* UpdateIteratorFromOffset() updates the iterator from a given offset.
* Also, aInOffset may be updated to cluster start if aInOffset isn't
@ -1036,6 +1007,8 @@ class nsTextFrame : public nsIFrame {
nsPoint GetPointFromIterator(const gfxSkipCharsIterator& aIter,
PropertyProvider& aProperties);
public:
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsTextFrame::TrimmedOffsetFlags)