tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit a8154dccaa8c98ec37ae6ec5c52279d0369e9533
parent b2ed6ac947d48e37479b5cc16a9af372e4f8b953
Author: Jonathan Kew <jkew@mozilla.com>
Date:   Thu,  6 Nov 2025 13:28:57 +0000

Bug 1998521 - Don't assume we can always get a line iterator in ComputeDecorationInset. r=layout-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D271552

Diffstat:
Alayout/generic/crashtests/1998521.html | 5+++++
Mlayout/generic/crashtests/crashtests.list | 1+
Mlayout/generic/nsTextFrame.cpp | 78++++++++++++++++++++++++++++++++++++++++--------------------------------------
3 files changed, 46 insertions(+), 38 deletions(-)

diff --git a/layout/generic/crashtests/1998521.html b/layout/generic/crashtests/1998521.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<!-- COMMENT --> +<del style="display: ruby-text; -webkit-flex-grow: 946015166.8948371" lang="zh-hk"> +<!-- COMMENT --> +\ No newline at end of file diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list @@ -824,3 +824,4 @@ asserts(0-5) load 1965081.html # Bug 457400 - ASSERTION: can't mark frame dirty load 1978475-1.html load 1990258.html load 1990319.html +load 1998521.html diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp @@ -5853,54 +5853,56 @@ static bool ComputeDecorationInset( decContainer = aDecFrame; } else { nsIFrame* const lineContainer = FindLineContainer(aFrame); - nsILineIterator* const iter = lineContainer->GetLineIterator(); - MOZ_ASSERT(iter, - "Line container of a text frame must be able to produce a " - "line iterator"); MOZ_ASSERT( lineContainer->GetWritingMode().IsVertical() == wm.IsVertical(), "Decorating frame and line container must have writing modes in the " "same axis"); - const int32_t lineNum = GetFrameLineNum(aFrame, iter); - const nsILineIterator::LineInfo lineInfo = iter->GetLine(lineNum).unwrap(); - - // Create the rects, relative to the line container. - decRect = lineInfo.mLineBounds; - decContainer = lineContainer; - - // Account for text-indent, which will push text frames into the line box. - const StyleTextIndent& textIndent = aFrame->StyleText()->mTextIndent; - if (!textIndent.length.IsDefinitelyZero()) { - bool isFirstLineOrAfterHardBreak = true; - if (lineNum > 0 && !textIndent.each_line) { - isFirstLineOrAfterHardBreak = false; - } else if (nsBlockFrame* prevBlock = - do_QueryFrame(lineContainer->GetPrevInFlow())) { - if (!(textIndent.each_line && - (prevBlock->Lines().empty() || - !prevBlock->LinesEnd().prev()->IsLineWrapped()))) { + if (nsILineIterator* const iter = lineContainer->GetLineIterator()) { + const int32_t lineNum = GetFrameLineNum(aFrame, iter); + const nsILineIterator::LineInfo lineInfo = + iter->GetLine(lineNum).unwrap(); + decRect = lineInfo.mLineBounds; + + // Account for text-indent, which will push text frames into the line box. + const StyleTextIndent& textIndent = aFrame->StyleText()->mTextIndent; + if (!textIndent.length.IsDefinitelyZero()) { + bool isFirstLineOrAfterHardBreak = true; + if (lineNum > 0 && !textIndent.each_line) { isFirstLineOrAfterHardBreak = false; + } else if (nsBlockFrame* prevBlock = + do_QueryFrame(lineContainer->GetPrevInFlow())) { + if (!(textIndent.each_line && + (prevBlock->Lines().empty() || + !prevBlock->LinesEnd().prev()->IsLineWrapped()))) { + isFirstLineOrAfterHardBreak = false; + } + } + if (isFirstLineOrAfterHardBreak != textIndent.hanging) { + // Determine which side to shrink. + const Side side = wm.PhysicalSide(LogicalSide::IStart); + // Calculate the text indent, and shrink the line box by this amount + // to account for the indent size at the start of the line. + const nscoord basis = lineContainer->GetLogicalSize(wm).ISize(wm); + nsMargin indentMargin; + indentMargin.Side(side) = textIndent.length.Resolve(basis); + decRect.Deflate(indentMargin); } } - if (isFirstLineOrAfterHardBreak != textIndent.hanging) { - // Determine which side to shrink. - const Side side = wm.PhysicalSide(LogicalSide::IStart); - // Calculate the text indent, and shrink the line box by this amount to - // acount for the indent size at the start of the line. - const nscoord basis = lineContainer->GetLogicalSize(wm).ISize(wm); - nsMargin indentMargin; - indentMargin.Side(side) = textIndent.length.Resolve(basis); - decRect.Deflate(indentMargin); + + // We can't allow a block frame to retain a line iterator if we're + // currently in reflow, as it will become invalid as the line list is + // reflowed. + if (lineContainer->HasAnyStateBits(NS_FRAME_IN_REFLOW) && + lineContainer->IsBlockFrameOrSubclass()) { + static_cast<nsBlockFrame*>(lineContainer)->ClearLineIterator(); } + } else { + // Not a block or similar container with multiple lines; just use the + // content rect directly. + decRect = lineContainer->GetContentRectRelativeToSelf(); } - // We can't allow a block frame to retain a line iterator if we're - // currently in reflow, as it will become invalid as the line list is - // reflowed. - if (lineContainer->HasAnyStateBits(NS_FRAME_IN_REFLOW) && - lineContainer->IsBlockFrameOrSubclass()) { - static_cast<nsBlockFrame*>(lineContainer)->ClearLineIterator(); - } + decContainer = lineContainer; } // The rect of the current frame, mapped to the same coordinate space as