Bug 1729578 - Adjust overly-strict assertion in nsContinuingTextFrame::FirstContinuation(). r=emilio

It turns out this assertion (added as part of bug 1725555) is not necessarily valid.
When we're updating the frame tree in response to DOM modifications (in the testcase
here, we're under nsCSSFrameConstructor::ContentRemoved), we may call DeleteFrom on
the primary textFrame first, which results in calling SetPrevInFlow(nullptr) on its
nextContinuation; this in turn clears the mFirstContinuation back-pointers in all
the successors. But if we then call DeleteFrom on one of the continuations later
in the chain, those nulled-out pointers trigger this assertion. In fact, it's OK
for them to be null in this case, so the assertion is over-zealous and we should
drop it.

I believe the only time it's OK for this to happen is if the chain of nsContinuingTextFrames
has been "detached" from the primary frame during frame-tree updating, as has happened in
this example.

We can still sanity-check the mFirstContinuation pointer here by asserting that it
matches the FirstContinuation() reported by our prev-continuation, or is null if there
is no prev-continuation. This is a bit expensive, though, so it's a only a debug-mode
assertion (for the fuzzers to try and hit).

Differential Revision: https://phabricator.services.mozilla.com/D125444
This commit is contained in:
Jonathan Kew 2021-09-14 10:10:11 +00:00
Родитель 691b7f9b13
Коммит 0b513c5331
3 изменённых файлов: 32 добавлений и 2 удалений

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

@ -0,0 +1,26 @@
<style>
#b {
column-span: all;
}
* {
column-count: 17;
}
.c {
column-span: all;
overflow-wrap: break-word;
height: 0.001592530849548246em;
}
</style>
<script>
let go = () => {
a.appendChild(d)
}
</script>
<body onload=go()>
<ol id="b">
<li></li>
</ol>
<a id="a">x</a>
<dl id="d">
<dd class="c">;MLCI|=oV;nvAP*o7U</dd>
<u>x</u>

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

@ -560,3 +560,4 @@ load 1685146.html
load 1689912.html
load 1690163.html
load 1723200.html
load 1729578.html

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

@ -4493,8 +4493,11 @@ class nsContinuingTextFrame final : public nsTextFrame {
nsIFrame* FirstInFlow() const final;
nsTextFrame* FirstContinuation() const final {
MOZ_DIAGNOSTIC_ASSERT(mFirstContinuation || !mPrevContinuation,
"mFirstContinuation unexpectedly null!");
// If we have a prev-continuation pointer, then our first-continuation
// must be the same as that frame's.
MOZ_ASSERT((!mPrevContinuation && !mFirstContinuation) ||
(mPrevContinuation &&
mPrevContinuation->FirstContinuation() == mFirstContinuation));
return mFirstContinuation;
};