tor-browser

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

commit 94124bfa08024db7df2cb6f16dcf1996154b57db
parent 44c1e061076ff328f8f0f00fd6fc223c4a591ce9
Author: Masayuki Nakano <masayuki@d-toybox.com>
Date:   Fri, 31 Oct 2025 05:02:57 +0000

Bug 1996501 - part 1: Make `TextFragmentData` refer proper `display` value for the scanning direction r=m_kato

In theory, scanning from outside to inside, i.e., checking a sibling
or a child, `display-outside` should be used to check whether the
element is a block or an inline. Similarly, scanning from inside to
outside, i.e., checking a parent, `display-inside` should be used to
check whether the element is a block or an inline.

`HTMLEditUtils`'s related methods are low API, but `WSRunScanner` is
higher API.  Therefore, I think `WSRunScanner` should work with the
theory.

This patch makes the internal scanner of `WSRunScanner`,
`TextFragmentData`, take only whether refer HTML default style or CSS
style and consider itself whether use
`BlockInlineCheck::UseComputedDisplayOutsideStyle` or
`BlockInlineCheck::UseComputedDisplayStyle`.

So, this patch should fix some edge case bugs of
`display: inline-block`.  However, unfortunately, there is not enough
tests for that.

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

Diffstat:
Meditor/libeditor/HTMLEditorDeleteHandler.cpp | 10+++++-----
Meditor/libeditor/WSRunScanner.cpp | 72+++++++++++++++++++++++++++++++++---------------------------------------
Meditor/libeditor/WSRunScanner.h | 60+++++++++++++++++++++++++++++++++++-------------------------
Meditor/libeditor/WSRunScannerNestedClasses.cpp | 210+++++++++++++++++++++++++++++++++++++++----------------------------------------
Meditor/libeditor/WhiteSpaceVisibilityKeeper.cpp | 15+++++++--------
Meditor/libeditor/WhiteSpaceVisibilityKeeper.h | 1+
6 files changed, 184 insertions(+), 184 deletions(-)

diff --git a/editor/libeditor/HTMLEditorDeleteHandler.cpp b/editor/libeditor/HTMLEditorDeleteHandler.cpp @@ -5452,7 +5452,7 @@ Result<bool, nsresult> HTMLEditor::AutoDeleteRangesHandler:: WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound( WSRunScanner::Scan::EditableNodes, EditorDOMPoint::AtEndOf(mLeftBlockElement), - BlockInlineCheck::UseComputedDisplayOutsideStyle); + WSRunScanner::ReferHTMLDefaultStyle::No); // `WhiteSpaceVisibilityKeeper:: // MergeFirstLineOfRightBlockElementIntoDescendantLeftBlockElement()` // returns ignored when: @@ -5483,7 +5483,7 @@ Result<bool, nsresult> HTMLEditor::AutoDeleteRangesHandler:: WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound( WSRunScanner::Scan::EditableNodes, mPointContainingTheOtherBlockElement, - BlockInlineCheck::UseComputedDisplayOutsideStyle); + WSRunScanner::ReferHTMLDefaultStyle::No); // `WhiteSpaceVisibilityKeeper:: // MergeFirstLineOfRightBlockElementIntoAncestorLeftBlockElement()` // returns ignored when: @@ -5519,7 +5519,7 @@ Result<bool, nsresult> HTMLEditor::AutoDeleteRangesHandler:: WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound( WSRunScanner::Scan::EditableNodes, EditorDOMPoint::AtEndOf(mLeftBlockElement), - BlockInlineCheck::UseComputedDisplayOutsideStyle); + WSRunScanner::ReferHTMLDefaultStyle::No); // `WhiteSpaceVisibilityKeeper:: // MergeFirstLineOfRightBlockElementIntoLeftBlockElement()` always // return "handled". @@ -7505,7 +7505,7 @@ HTMLEditor::AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete( if (Element* const maybeEditableBlockElement = HTMLEditUtils::GetInclusiveAncestorElement( *commonAncestor, HTMLEditUtils::ClosestBlockElement, - BlockInlineCheck::UseComputedDisplayOutsideStyle, + BlockInlineCheck::UseComputedDisplayStyle, closestEditingHost)) { return maybeEditableBlockElement; } @@ -7667,7 +7667,7 @@ HTMLEditor::AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete( HTMLEditUtils::GetInclusiveAncestorElement( *atFirstInvisibleBRElement.ContainerAs<nsIContent>(), HTMLEditUtils::ClosestEditableBlockElement, - BlockInlineCheck::UseComputedDisplayOutsideStyle)) { + BlockInlineCheck::UseComputedDisplayStyle)) { if (rangeToDelete.Contains( EditorRawDOMPoint(editableBlockContainingBRElement))) { return rangeToDelete; diff --git a/editor/libeditor/WSRunScanner.cpp b/editor/libeditor/WSRunScanner.cpp @@ -76,10 +76,12 @@ void WSScanResult::AssertIfInvalidData(const WSRunScanner& aScanner) const { (mContent->IsText() && !mContent->IsEditable()) || (!mContent->IsHTMLElement(nsGkAtoms::br) && !HTMLEditUtils::IsBlockElement( - *mContent, aScanner.BlockInlineCheckMode()))); + *mContent, RespectChildBlockBoundary( + aScanner.BlockInlineCheckMode())))); MOZ_ASSERT_IF(mReason == WSType::OtherBlockBoundary, - HTMLEditUtils::IsBlockElement(*mContent, - aScanner.BlockInlineCheckMode())); + HTMLEditUtils::IsBlockElement( + *mContent, RespectChildBlockBoundary( + aScanner.BlockInlineCheckMode()))); MOZ_ASSERT_IF(mReason == WSType::CurrentBlockBoundary, mContent->IsElement()); MOZ_ASSERT_IF(mReason == WSType::CurrentBlockBoundary && aScanner.mScanMode == WSRunScanner::Scan::EditableNodes, @@ -95,7 +97,8 @@ void WSScanResult::AssertIfInvalidData(const WSRunScanner& aScanner) const { mContent->IsEditable()); MOZ_ASSERT_IF(mReason == WSType::InlineEditingHostBoundary, !HTMLEditUtils::IsBlockElement( - *mContent, aScanner.BlockInlineCheckMode())); + *mContent, RespectParentBlockBoundary( + aScanner.BlockInlineCheckMode()))); MOZ_ASSERT_IF(mReason == WSType::InlineEditingHostBoundary, !mContent->GetParentElement() || !mContent->GetParentElement()->IsEditable()); @@ -214,8 +217,7 @@ WSScanResult WSRunScanner::ScanPreviousVisibleNodeOrBlockBoundaryFrom( // invisible. while (true) { const EditorRawDOMPoint atComment(comment); - WSRunScanner scanner(mScanMode, atComment, - mTextFragmentDataAtStart.BlockInlineCheckMode(), + WSRunScanner scanner(mScanMode, atComment, mBlockInlineCheck, mTextFragmentDataAtStart.GetAncestorLimiter()); if (scanner.TextFragmentDataAtStartRef().StartRawReason() == WSType::SpecialContent) { @@ -333,8 +335,7 @@ WSScanResult WSRunScanner::ScanInclusiveNextVisibleNodeOrBlockBoundaryFrom( while (true) { const EditorRawDOMPoint afterComment = EditorRawDOMPoint::After(*comment); - WSRunScanner scanner(mScanMode, afterComment, - mTextFragmentDataAtStart.BlockInlineCheckMode(), + WSRunScanner scanner(mScanMode, afterComment, mBlockInlineCheck, mTextFragmentDataAtStart.GetAncestorLimiter()); if (scanner.TextFragmentDataAtStartRef().EndRawReason() == WSType::SpecialContent) { @@ -384,9 +385,9 @@ EditorDOMPointType WSRunScanner::GetAfterLastVisiblePoint( !atLastCharOfTextNode.IsCharCollapsibleASCIISpace()) { return EditorDOMPointType::AtEndOf(aTextNode); } - const TextFragmentData textFragmentData( - aScanMode, atLastCharOfTextNode, - BlockInlineCheck::UseComputedDisplayStyle, aAncestorLimiter); + const TextFragmentData textFragmentData(aScanMode, atLastCharOfTextNode, + ReferHTMLDefaultStyle::No, + aAncestorLimiter); if (NS_WARN_IF(!textFragmentData.IsInitialized())) { return EditorDOMPointType(); // TODO: Make here return error with Err. } @@ -409,9 +410,9 @@ EditorDOMPointType WSRunScanner::GetFirstVisiblePoint( !atStartOfTextNode.IsCharCollapsibleASCIISpace()) { return atStartOfTextNode.To<EditorDOMPointType>(); } - const TextFragmentData textFragmentData( - aScanMode, atStartOfTextNode, BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter); + const TextFragmentData textFragmentData(aScanMode, atStartOfTextNode, + ReferHTMLDefaultStyle::No, + aAncestorLimiter); if (NS_WARN_IF(!textFragmentData.IsInitialized())) { return EditorDOMPointType(); // TODO: Make here return error with Err. } @@ -555,8 +556,7 @@ WSRunScanner::GetRangeInTextNodesToBackspaceFrom( MOZ_ASSERT(aPoint.IsSetAndValid()); const TextFragmentData textFragmentDataAtCaret( - aScanMode, aPoint, BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter); + aScanMode, aPoint, ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAtCaret.IsInitialized())) { return Err(NS_ERROR_FAILURE); } @@ -628,14 +628,12 @@ WSRunScanner::GetRangeInTextNodesToBackspaceFrom( const TextFragmentData textFragmentDataAtStart = rangeToDelete.StartRef() != aPoint ? TextFragmentData(aScanMode, rangeToDelete.StartRef(), - BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter) + ReferHTMLDefaultStyle::No, aAncestorLimiter) : textFragmentDataAtCaret; const TextFragmentData textFragmentDataAtEnd = rangeToDelete.EndRef() != aPoint ? TextFragmentData(aScanMode, rangeToDelete.EndRef(), - BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter) + ReferHTMLDefaultStyle::No, aAncestorLimiter) : textFragmentDataAtCaret; if (NS_WARN_IF(!textFragmentDataAtStart.IsInitialized()) || NS_WARN_IF(!textFragmentDataAtEnd.IsInitialized())) { @@ -659,8 +657,7 @@ WSRunScanner::GetRangeInTextNodesToForwardDeleteFrom( MOZ_ASSERT(aPoint.IsSetAndValid()); const TextFragmentData textFragmentDataAtCaret( - aScanMode, aPoint, BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter); + aScanMode, aPoint, ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAtCaret.IsInitialized())) { return Err(NS_ERROR_FAILURE); } @@ -731,14 +728,12 @@ WSRunScanner::GetRangeInTextNodesToForwardDeleteFrom( const TextFragmentData textFragmentDataAtStart = rangeToDelete.StartRef() != aPoint ? TextFragmentData(aScanMode, rangeToDelete.StartRef(), - BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter) + ReferHTMLDefaultStyle::No, aAncestorLimiter) : textFragmentDataAtCaret; const TextFragmentData textFragmentDataAtEnd = rangeToDelete.EndRef() != aPoint ? TextFragmentData(aScanMode, rangeToDelete.EndRef(), - BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter) + ReferHTMLDefaultStyle::No, aAncestorLimiter) : textFragmentDataAtCaret; if (NS_WARN_IF(!textFragmentDataAtStart.IsInitialized()) || NS_WARN_IF(!textFragmentDataAtEnd.IsInitialized())) { @@ -761,7 +756,7 @@ EditorDOMRange WSRunScanner::GetRangesForDeletingAtomicContent( // white-spaces should be invisible around `<br>` element. const TextFragmentData textFragmentDataAfterBRElement( aScanMode, EditorDOMPoint::After(aAtomicContent), - BlockInlineCheck::UseComputedDisplayStyle, aAncestorLimiter); + ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAfterBRElement.IsInitialized())) { return EditorDOMRange(); // TODO: Make here return error with Err. } @@ -780,7 +775,7 @@ EditorDOMRange WSRunScanner::GetRangesForDeletingAtomicContent( } if (!HTMLEditUtils::IsBlockElement( - aAtomicContent, BlockInlineCheck::UseComputedDisplayStyle)) { + aAtomicContent, BlockInlineCheck::UseComputedDisplayOutsideStyle)) { // Both preceding and following white-spaces around it should be preserved // around inline elements like `<img>`. return EditorDOMRange( @@ -792,7 +787,7 @@ EditorDOMRange WSRunScanner::GetRangesForDeletingAtomicContent( // block element. const TextFragmentData textFragmentDataBeforeAtomicContent( aScanMode, EditorDOMPoint(const_cast<nsIContent*>(&aAtomicContent)), - BlockInlineCheck::UseComputedDisplayStyle, aAncestorLimiter); + ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataBeforeAtomicContent.IsInitialized())) { return EditorDOMRange(); // TODO: Make here return error with Err. } @@ -802,7 +797,7 @@ EditorDOMRange WSRunScanner::GetRangesForDeletingAtomicContent( .InvisibleTrailingWhiteSpaceRangeRef()); const TextFragmentData textFragmentDataAfterAtomicContent( aScanMode, EditorDOMPoint::After(aAtomicContent), - BlockInlineCheck::UseComputedDisplayStyle, aAncestorLimiter); + ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAfterAtomicContent.IsInitialized())) { return EditorDOMRange(); // TODO: Make here return error with Err. } @@ -873,7 +868,7 @@ EditorDOMRange WSRunScanner::GetRangeForDeletingBlockElementBoundaries( aPointContainingTheOtherBlock.GetContainer() == &aLeftBlockElement ? aPointContainingTheOtherBlock : EditorDOMPoint::AtEndOf(const_cast<Element&>(aLeftBlockElement)), - BlockInlineCheck::UseComputedDisplayOutsideStyle, aAncestorLimiter); + ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAtEndOfLeftBlockElement.IsInitialized())) { return EditorDOMRange(); // TODO: Make here return error with Err. } @@ -901,7 +896,7 @@ EditorDOMRange WSRunScanner::GetRangeForDeletingBlockElementBoundaries( !aPointContainingTheOtherBlock.IsEndOfContainer() ? aPointContainingTheOtherBlock.NextPoint() : EditorDOMPoint(const_cast<Element*>(&aRightBlockElement), 0u), - BlockInlineCheck::UseComputedDisplayOutsideStyle, aAncestorLimiter); + ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAtStartOfRightBlockElement.IsInitialized())) { return EditorDOMRange(); // TODO: Make here return error with Err. } @@ -926,9 +921,9 @@ WSRunScanner::GetRangeContainingInvisibleWhiteSpacesAtRangeBoundaries( MOZ_ASSERT(aRange.StartRef().IsSetAndValid()); EditorDOMRange result; - const TextFragmentData textFragmentDataAtStart( - aScanMode, aRange.StartRef(), BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter); + const TextFragmentData textFragmentDataAtStart(aScanMode, aRange.StartRef(), + ReferHTMLDefaultStyle::No, + aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAtStart.IsInitialized())) { return EditorDOMRange(); // TODO: Make here return error with Err. } @@ -963,8 +958,7 @@ WSRunScanner::GetRangeContainingInvisibleWhiteSpacesAtRangeBoundaries( } const TextFragmentData textFragmentDataAtEnd( - aScanMode, aRange.EndRef(), BlockInlineCheck::UseComputedDisplayStyle, - aAncestorLimiter); + aScanMode, aRange.EndRef(), ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAtEnd.IsInitialized())) { return EditorDOMRange(); // TODO: Make here return error with Err. } @@ -1050,7 +1044,7 @@ WSRunScanner::ShrinkRangeIfStartsFromOrEndsAfterAtomicContent( // element like `<hr>`, the range should start with it. const TextFragmentData textFragmentDataAtStart( aScanMode, EditorRawDOMPoint(aRange.StartRef()), - BlockInlineCheck::UseComputedDisplayStyle, aAncestorLimiter); + ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAtStart.IsInitialized())) { return Err(NS_ERROR_FAILURE); } @@ -1073,7 +1067,7 @@ WSRunScanner::ShrinkRangeIfStartsFromOrEndsAfterAtomicContent( // element like `<hr>`, the range should end after it. const TextFragmentData textFragmentDataAtEnd( aScanMode, EditorRawDOMPoint(aRange.EndRef()), - BlockInlineCheck::UseComputedDisplayStyle, aAncestorLimiter); + ReferHTMLDefaultStyle::No, aAncestorLimiter); if (NS_WARN_IF(!textFragmentDataAtEnd.IsInitialized())) { return Err(NS_ERROR_FAILURE); } diff --git a/editor/libeditor/WSRunScanner.h b/editor/libeditor/WSRunScanner.h @@ -390,6 +390,7 @@ class MOZ_STACK_CLASS WSRunScanner final { enum class IgnoreNonEditableNodes : bool { No, Yes }; enum class StopAtNonEditableNode : bool { No, Yes }; enum class Scan : bool { All, EditableNodes }; + enum class ReferHTMLDefaultStyle : bool { No, Yes }; [[nodiscard]] constexpr static IgnoreNonEditableNodes ShouldIgnoreNonEditableSiblingsOrDescendants(Scan aScan) { @@ -400,14 +401,22 @@ class MOZ_STACK_CLASS WSRunScanner final { return static_cast<StopAtNonEditableNode>(static_cast<bool>(aScan)); } + [[nodiscard]] constexpr static ReferHTMLDefaultStyle + ShouldReferHTMLDefaultStyle(BlockInlineCheck aBlockInlineCheck) { + return static_cast<ReferHTMLDefaultStyle>( + aBlockInlineCheck == BlockInlineCheck::UseHTMLDefaultStyle); + } + template <typename EditorDOMPointType> WSRunScanner(Scan aScanMode, const EditorDOMPointType& aScanStartPoint, BlockInlineCheck aBlockInlineCheck, const Element* aAncestorLimiter = nullptr) : mScanStartPoint(aScanStartPoint.template To<EditorDOMPoint>()), - mTextFragmentDataAtStart(aScanMode, mScanStartPoint, aBlockInlineCheck, + mTextFragmentDataAtStart(aScanMode, mScanStartPoint, + ShouldReferHTMLDefaultStyle(aBlockInlineCheck), aAncestorLimiter), - mScanMode(aScanMode) {} + mScanMode(aScanMode), + mBlockInlineCheck(aBlockInlineCheck) {} // ScanInclusiveNextVisibleNodeOrBlockBoundaryFrom() returns the first visible // node at or after aPoint. If there is no visible nodes after aPoint, @@ -580,7 +589,7 @@ class MOZ_STACK_CLASS WSRunScanner final { MOZ_NEVER_INLINE_DEBUG static HTMLBRElement* GetPrecedingBRElementUnlessVisibleContentFound( Scan aScanMode, const EditorDOMPointType& aPoint, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, const Element* aAncestorLimiter = nullptr) { MOZ_ASSERT(aPoint.IsSetAndValid()); // XXX This method behaves differently even in similar point. @@ -595,7 +604,7 @@ class MOZ_STACK_CLASS WSRunScanner final { } // TODO: Scan for end boundary is redundant in this case, we should optimize // it. - TextFragmentData textFragmentData(aScanMode, aPoint, aBlockInlineCheck, + TextFragmentData textFragmentData(aScanMode, aPoint, aReferHTMLDefaultStyle, aAncestorLimiter); return textFragmentData.StartsFromBRElement() ? textFragmentData.StartReasonBRElementPtr() @@ -603,7 +612,7 @@ class MOZ_STACK_CLASS WSRunScanner final { } constexpr BlockInlineCheck BlockInlineCheckMode() const { - return mTextFragmentDataAtStart.BlockInlineCheckMode(); + return mBlockInlineCheck; } const EditorDOMPoint& ScanStartRef() const { return mScanStartPoint; } @@ -821,7 +830,8 @@ class MOZ_STACK_CLASS WSRunScanner final { template <typename EditorDOMPointType> static BoundaryData ScanCollapsibleWhiteSpaceStartFrom( Scan aScanMode, const EditorDOMPointType& aPoint, - NoBreakingSpaceData* aNBSPData, BlockInlineCheck aBlockInlineCheck, + NoBreakingSpaceData* aNBSPData, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, StopAtNonEditableNode aStopAtNonEditableNode, const Element& aAncestorLimiter); @@ -838,7 +848,8 @@ class MOZ_STACK_CLASS WSRunScanner final { template <typename EditorDOMPointType> static BoundaryData ScanCollapsibleWhiteSpaceEndFrom( Scan aScanMode, const EditorDOMPointType& aPoint, - NoBreakingSpaceData* aNBSPData, BlockInlineCheck aBlockInlineCheck, + NoBreakingSpaceData* aNBSPData, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, StopAtNonEditableNode aStopAtNonEditableNode, const Element& aAncestorLimiter); @@ -901,12 +912,10 @@ class MOZ_STACK_CLASS WSRunScanner final { */ template <typename EditorDOMPointType> static Maybe<BoundaryData> ScanCollapsibleWhiteSpaceStartInTextNode( - const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData, - BlockInlineCheck aBlockInlineCheck); + const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData); template <typename EditorDOMPointType> static Maybe<BoundaryData> ScanCollapsibleWhiteSpaceEndInTextNode( - const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData, - BlockInlineCheck aBlockInlineCheck); + const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData); nsCOMPtr<nsIContent> mReasonContent; EditorDOMPoint mPoint; @@ -955,7 +964,7 @@ class MOZ_STACK_CLASS WSRunScanner final { */ template <typename EditorDOMPointType> TextFragmentData(Scan aScanMode, const EditorDOMPointType& aPoint, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, const Element* aAncestorLimiter = nullptr); bool IsInitialized() const { @@ -964,8 +973,8 @@ class MOZ_STACK_CLASS WSRunScanner final { constexpr Scan ScanMode() const { return mScanMode; } - constexpr BlockInlineCheck BlockInlineCheckMode() const { - return mBlockInlineCheck; + constexpr bool ReferredHTMLDefaultStyle() const { + return static_cast<bool>(mReferHTMLDefaultStyle); } const Element* GetAncestorLimiter() const { return mAncestorLimiter; } @@ -1067,7 +1076,7 @@ class MOZ_STACK_CLASS WSRunScanner final { template <typename EditorDOMPointType, typename PT, typename CT> [[nodiscard]] static EditorDOMPointType GetInclusiveNextCharPoint( const EditorDOMPointBase<PT, CT>& aPoint, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, IgnoreNonEditableNodes aIgnoreNonEditableNodes, const nsIContent* aFollowingLimiterContent = nullptr); @@ -1076,7 +1085,7 @@ class MOZ_STACK_CLASS WSRunScanner final { const EditorDOMPointBase<PT, CT>& aPoint, IgnoreNonEditableNodes aIgnoreNonEditableNodes) const { return GetInclusiveNextCharPoint<EditorDOMPointType>( - aPoint, mBlockInlineCheck, aIgnoreNonEditableNodes, + aPoint, mReferHTMLDefaultStyle, aIgnoreNonEditableNodes, GetEndReasonContent()); } @@ -1087,7 +1096,7 @@ class MOZ_STACK_CLASS WSRunScanner final { template <typename EditorDOMPointType, typename PT, typename CT> [[nodiscard]] static EditorDOMPointType GetPreviousCharPoint( const EditorDOMPointBase<PT, CT>& aPoint, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, IgnoreNonEditableNodes aIgnoreNonEditableNodes, const nsIContent* aPrecedingLimiterContent = nullptr); @@ -1095,9 +1104,9 @@ class MOZ_STACK_CLASS WSRunScanner final { [[nodiscard]] EditorDOMPointType GetPreviousCharPoint( const EditorDOMPointBase<PT, CT>& aPoint, IgnoreNonEditableNodes aIgnoreNonEditableNodes) const { - return GetPreviousCharPoint<EditorDOMPointType>(aPoint, mBlockInlineCheck, - aIgnoreNonEditableNodes, - GetStartReasonContent()); + return GetPreviousCharPoint<EditorDOMPointType>( + aPoint, mReferHTMLDefaultStyle, aIgnoreNonEditableNodes, + GetStartReasonContent()); } /** @@ -1111,7 +1120,7 @@ class MOZ_STACK_CLASS WSRunScanner final { [[nodiscard]] static EditorDOMPointType GetEndOfCollapsibleASCIIWhiteSpaces( const EditorDOMPointInText& aPointAtASCIIWhiteSpace, nsIEditor::EDirection aDirectionToDelete, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, IgnoreNonEditableNodes aIgnoreNonEditableNodes, const nsIContent* aFollowingLimiterContent = nullptr); @@ -1121,7 +1130,7 @@ class MOZ_STACK_CLASS WSRunScanner final { nsIEditor::EDirection aDirectionToDelete, IgnoreNonEditableNodes aIgnoreNonEditableNodes) const { return GetEndOfCollapsibleASCIIWhiteSpaces<EditorDOMPointType>( - aPointAtASCIIWhiteSpace, aDirectionToDelete, mBlockInlineCheck, + aPointAtASCIIWhiteSpace, aDirectionToDelete, mReferHTMLDefaultStyle, aIgnoreNonEditableNodes, GetEndReasonContent()); } @@ -1137,7 +1146,7 @@ class MOZ_STACK_CLASS WSRunScanner final { GetFirstASCIIWhiteSpacePointCollapsedTo( const EditorDOMPointInText& aPointAtASCIIWhiteSpace, nsIEditor::EDirection aDirectionToDelete, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, IgnoreNonEditableNodes aIgnoreNonEditableNodes, const nsIContent* aPrecedingLimiterContent = nullptr); @@ -1147,7 +1156,7 @@ class MOZ_STACK_CLASS WSRunScanner final { nsIEditor::EDirection aDirectionToDelete, IgnoreNonEditableNodes aIgnoreNonEditableNodes) const { return GetFirstASCIIWhiteSpacePointCollapsedTo<EditorDOMPointType>( - aPointAtASCIIWhiteSpace, aDirectionToDelete, mBlockInlineCheck, + aPointAtASCIIWhiteSpace, aDirectionToDelete, mReferHTMLDefaultStyle, aIgnoreNonEditableNodes, GetStartReasonContent()); } @@ -1397,7 +1406,7 @@ class MOZ_STACK_CLASS WSRunScanner final { mutable Maybe<EditorDOMRange> mLeadingWhiteSpaceRange; mutable Maybe<EditorDOMRange> mTrailingWhiteSpaceRange; mutable Maybe<VisibleWhiteSpacesData> mVisibleWhiteSpacesData; - BlockInlineCheck mBlockInlineCheck; + const ReferHTMLDefaultStyle mReferHTMLDefaultStyle; Scan mScanMode; }; @@ -1428,6 +1437,7 @@ class MOZ_STACK_CLASS WSRunScanner final { TextFragmentData mTextFragmentDataAtStart; const Scan mScanMode; + const BlockInlineCheck mBlockInlineCheck; friend class WhiteSpaceVisibilityKeeper; friend class WSScanResult; diff --git a/editor/libeditor/WSRunScannerNestedClasses.cpp b/editor/libeditor/WSRunScannerNestedClasses.cpp @@ -27,76 +27,60 @@ using AncestorTypes = HTMLEditUtils::AncestorTypes; using LeafNodeType = HTMLEditUtils::LeafNodeType; using LeafNodeTypes = HTMLEditUtils::LeafNodeTypes; +template WSRunScanner::TextFragmentData::TextFragmentData(Scan, + const EditorDOMPoint&, + ReferHTMLDefaultStyle, + const Element*); template WSRunScanner::TextFragmentData::TextFragmentData( - Scan aScanMode, const EditorDOMPoint& aPoint, - BlockInlineCheck aBlockInlineCheck, const Element* aAncestorLimiter); + Scan, const EditorRawDOMPoint&, ReferHTMLDefaultStyle, const Element*); template WSRunScanner::TextFragmentData::TextFragmentData( - Scan aScanMode, const EditorRawDOMPoint& aPoint, - BlockInlineCheck aBlockInlineCheck, const Element* aAncestorLimiter); + Scan, const EditorDOMPointInText&, ReferHTMLDefaultStyle, const Element*); template WSRunScanner::TextFragmentData::TextFragmentData( - Scan aScanMode, const EditorDOMPointInText& aPoint, - BlockInlineCheck aBlockInlineCheck, const Element* aAncestorLimiter); -template WSRunScanner::TextFragmentData::TextFragmentData( - Scan aScanMode, const EditorRawDOMPointInText& aPoint, - BlockInlineCheck aBlockInlineCheck, const Element* aAncestorLimiter); + Scan, const EditorRawDOMPointInText&, ReferHTMLDefaultStyle, + const Element*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint, - const EditorDOMPoint& aPoint, BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aFollowingLimiterContent); + const EditorDOMPoint&, ReferHTMLDefaultStyle, IgnoreNonEditableNodes, + const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint, - const EditorRawDOMPoint& aPoint, BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aFollowingLimiterContent); + const EditorRawDOMPoint&, ReferHTMLDefaultStyle, IgnoreNonEditableNodes, + const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint, - const EditorDOMPointInText& aPoint, BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aFollowingLimiterContent); + const EditorDOMPointInText&, ReferHTMLDefaultStyle, IgnoreNonEditableNodes, + const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint, - const EditorRawDOMPointInText& aPoint, BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aFollowingLimiterContent); + const EditorRawDOMPointInText&, ReferHTMLDefaultStyle, + IgnoreNonEditableNodes, const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( - WSRunScanner::TextFragmentData::GetPreviousCharPoint, - const EditorDOMPoint& aPoint, BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aPrecedingLimiterContent); + WSRunScanner::TextFragmentData::GetPreviousCharPoint, const EditorDOMPoint&, + ReferHTMLDefaultStyle, IgnoreNonEditableNodes, const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetPreviousCharPoint, - const EditorRawDOMPoint& aPoint, BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aPrecedingLimiterContent); + const EditorRawDOMPoint&, ReferHTMLDefaultStyle, IgnoreNonEditableNodes, + const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetPreviousCharPoint, - const EditorDOMPointInText& aPoint, BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aPrecedingLimiterContent); + const EditorDOMPointInText&, ReferHTMLDefaultStyle, IgnoreNonEditableNodes, + const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetPreviousCharPoint, - const EditorRawDOMPointInText& aPoint, BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aPrecedingLimiterContent); + const EditorRawDOMPointInText&, ReferHTMLDefaultStyle, + IgnoreNonEditableNodes, const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetEndOfCollapsibleASCIIWhiteSpaces, - const EditorDOMPointInText& aPointAtASCIIWhiteSpace, - nsIEditor::EDirection aDirectionToDelete, - BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aFollowingLimiterContent); + const EditorDOMPointInText&, nsIEditor::EDirection, ReferHTMLDefaultStyle, + IgnoreNonEditableNodes, const nsIContent*); NS_INSTANTIATE_METHOD_RETURNING_ANY_EDITOR_DOM_POINT( WSRunScanner::TextFragmentData::GetFirstASCIIWhiteSpacePointCollapsedTo, - const EditorDOMPointInText& aPointAtASCIIWhiteSpace, - nsIEditor::EDirection aDirectionToDelete, - BlockInlineCheck aBlockInlineCheck, - IgnoreNonEditableNodes aIgnoreNonEditableNodes, - const nsIContent* aPrecedingLimiterContent); + const EditorDOMPointInText&, nsIEditor::EDirection, ReferHTMLDefaultStyle, + IgnoreNonEditableNodes, const nsIContent*); // FIXME: I think the scanner should not cross the <button> element boundaries. constexpr static const AncestorTypes kScanAnyRootAncestorTypes = { @@ -120,10 +104,10 @@ constexpr static const AncestorTypes kScanEditableRootAncestorTypes = { template <typename EditorDOMPointType> WSRunScanner::TextFragmentData::TextFragmentData( Scan aScanMode, const EditorDOMPointType& aPoint, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, const Element* aAncestorLimiter /* = nullptr */) : mAncestorLimiter(aAncestorLimiter), - mBlockInlineCheck(aBlockInlineCheck), + mReferHTMLDefaultStyle(aReferHTMLDefaultStyle), mScanMode(aScanMode) { if (NS_WARN_IF(!aPoint.IsInContentNodeAndValidInComposedDoc()) || NS_WARN_IF(!aPoint.GetContainerOrContainerParentElement())) { @@ -143,13 +127,16 @@ WSRunScanner::TextFragmentData::TextFragmentData( *mScanStartPoint.ContainerAs<nsIContent>(), aScanMode == Scan::EditableNodes ? kScanEditableRootAncestorTypes : kScanAnyRootAncestorTypes, - aBlockInlineCheck, aAncestorLimiter); + static_cast<bool>(mReferHTMLDefaultStyle) + ? BlockInlineCheck::UseHTMLDefaultStyle + : BlockInlineCheck::UseComputedDisplayOutsideStyle, + aAncestorLimiter); if (NS_WARN_IF( !editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) { return; } mStart = BoundaryData::ScanCollapsibleWhiteSpaceStartFrom( - aScanMode, mScanStartPoint, &mNBSPData, aBlockInlineCheck, + aScanMode, mScanStartPoint, &mNBSPData, aReferHTMLDefaultStyle, ShouldStopAtNonEditableNode(aScanMode), *editableBlockElementOrInlineEditingHostOrNonEditableRootElement); MOZ_ASSERT_IF(mStart.IsNonCollapsibleCharacters(), @@ -157,7 +144,7 @@ WSRunScanner::TextFragmentData::TextFragmentData( MOZ_ASSERT_IF(mStart.IsPreformattedLineBreak(), mStart.PointRef().IsPreviousCharPreformattedNewLine()); mEnd = BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( - aScanMode, mScanStartPoint, &mNBSPData, aBlockInlineCheck, + aScanMode, mScanStartPoint, &mNBSPData, aReferHTMLDefaultStyle, ShouldStopAtNonEditableNode(aScanMode), *editableBlockElementOrInlineEditingHostOrNonEditableRootElement); MOZ_ASSERT_IF(mEnd.IsNonCollapsibleCharacters(), @@ -170,8 +157,7 @@ WSRunScanner::TextFragmentData::TextFragmentData( template <typename EditorDOMPointType> Maybe<WSRunScanner::TextFragmentData::BoundaryData> WSRunScanner:: TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceStartInTextNode( - const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData, - BlockInlineCheck aBlockInlineCheck) { + const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData) { MOZ_ASSERT(aPoint.IsSetAndValid()); MOZ_DIAGNOSTIC_ASSERT(aPoint.IsInTextNode()); @@ -238,7 +224,8 @@ template <typename EditorDOMPointType> WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData:: BoundaryData::ScanCollapsibleWhiteSpaceStartFrom( Scan aScanMode, const EditorDOMPointType& aPoint, - NoBreakingSpaceData* aNBSPData, BlockInlineCheck aBlockInlineCheck, + NoBreakingSpaceData* aNBSPData, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, StopAtNonEditableNode aStopAtNonEditableNode, const Element& aAncestorLimiter) { MOZ_ASSERT(aPoint.IsSetAndValid()); @@ -249,8 +236,8 @@ WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData:: if (aPoint.IsInTextNode() && !aPoint.IsStartOfContainer()) { Maybe<BoundaryData> startInTextNode = - BoundaryData::ScanCollapsibleWhiteSpaceStartInTextNode( - aPoint, aNBSPData, aBlockInlineCheck); + BoundaryData::ScanCollapsibleWhiteSpaceStartInTextNode(aPoint, + aNBSPData); if (startInTextNode.isSome()) { return startInTextNode.ref(); } @@ -258,9 +245,14 @@ WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData:: // preceding nodes. return BoundaryData::ScanCollapsibleWhiteSpaceStartFrom( aScanMode, EditorDOMPoint(aPoint.template ContainerAs<Text>(), 0), - aNBSPData, aBlockInlineCheck, aStopAtNonEditableNode, aAncestorLimiter); + aNBSPData, aReferHTMLDefaultStyle, aStopAtNonEditableNode, + aAncestorLimiter); } + const BlockInlineCheck blockInlineCheck = + static_cast<bool>(aReferHTMLDefaultStyle) + ? BlockInlineCheck::UseHTMLDefaultStyle + : BlockInlineCheck::UseComputedDisplayOutsideStyle; // Then, we need to check previous leaf node. const auto leafNodeTypes = aStopAtNonEditableNode == StopAtNonEditableNode::Yes @@ -268,19 +260,19 @@ WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData:: : LeafNodeTypes{LeafNodeType::OnlyLeafNode}; nsIContent* previousLeafContentOrBlock = HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( - aPoint, leafNodeTypes, aBlockInlineCheck, &aAncestorLimiter); + aPoint, leafNodeTypes, blockInlineCheck, &aAncestorLimiter); if (!previousLeafContentOrBlock) { // No previous content means that we reached the aAncestorLimiter boundary. return BoundaryData( aPoint, const_cast<Element&>(aAncestorLimiter), HTMLEditUtils::IsBlockElement( - aAncestorLimiter, RespectParentBlockBoundary(aBlockInlineCheck)) + aAncestorLimiter, RespectParentBlockBoundary(blockInlineCheck)) ? WSType::CurrentBlockBoundary : WSType::InlineEditingHostBoundary); } if (HTMLEditUtils::IsBlockElement(*previousLeafContentOrBlock, - aBlockInlineCheck)) { + blockInlineCheck)) { return BoundaryData(aPoint, *previousLeafContentOrBlock, WSType::OtherBlockBoundary); } @@ -304,13 +296,14 @@ WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData:: return BoundaryData::ScanCollapsibleWhiteSpaceStartFrom( aScanMode, EditorDOMPointInText(previousLeafContentOrBlock->AsText(), 0), - aNBSPData, aBlockInlineCheck, aStopAtNonEditableNode, aAncestorLimiter); + aNBSPData, aReferHTMLDefaultStyle, aStopAtNonEditableNode, + aAncestorLimiter); } Maybe<BoundaryData> startInTextNode = BoundaryData::ScanCollapsibleWhiteSpaceStartInTextNode( EditorDOMPointInText::AtEndOf(*previousLeafContentOrBlock->AsText()), - aNBSPData, aBlockInlineCheck); + aNBSPData); if (startInTextNode.isSome()) { return startInTextNode.ref(); } @@ -319,15 +312,15 @@ WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData:: // preceding nodes. return BoundaryData::ScanCollapsibleWhiteSpaceStartFrom( aScanMode, EditorDOMPointInText(previousLeafContentOrBlock->AsText(), 0), - aNBSPData, aBlockInlineCheck, aStopAtNonEditableNode, aAncestorLimiter); + aNBSPData, aReferHTMLDefaultStyle, aStopAtNonEditableNode, + aAncestorLimiter); } // static template <typename EditorDOMPointType> Maybe<WSRunScanner::TextFragmentData::BoundaryData> WSRunScanner:: TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndInTextNode( - const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData, - BlockInlineCheck aBlockInlineCheck) { + const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData) { MOZ_ASSERT(aPoint.IsSetAndValid()); MOZ_DIAGNOSTIC_ASSERT(aPoint.IsInTextNode()); @@ -392,7 +385,8 @@ template <typename EditorDOMPointType> WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( Scan aScanMode, const EditorDOMPointType& aPoint, - NoBreakingSpaceData* aNBSPData, BlockInlineCheck aBlockInlineCheck, + NoBreakingSpaceData* aNBSPData, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, StopAtNonEditableNode aStopAtNonEditableNode, const Element& aAncestorLimiter) { MOZ_ASSERT(aPoint.IsSetAndValid()); @@ -403,8 +397,7 @@ WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( if (aPoint.IsInTextNode() && !aPoint.IsEndOfContainer()) { Maybe<BoundaryData> endInTextNode = - BoundaryData::ScanCollapsibleWhiteSpaceEndInTextNode(aPoint, aNBSPData, - aBlockInlineCheck); + BoundaryData::ScanCollapsibleWhiteSpaceEndInTextNode(aPoint, aNBSPData); if (endInTextNode.isSome()) { return endInTextNode.ref(); } @@ -413,9 +406,15 @@ WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( return BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( aScanMode, EditorDOMPointInText::AtEndOf(*aPoint.template ContainerAs<Text>()), - aNBSPData, aBlockInlineCheck, aStopAtNonEditableNode, aAncestorLimiter); + aNBSPData, aReferHTMLDefaultStyle, aStopAtNonEditableNode, + aAncestorLimiter); } + const BlockInlineCheck blockInlineCheck = + static_cast<bool>(aReferHTMLDefaultStyle) + ? BlockInlineCheck::UseHTMLDefaultStyle + : BlockInlineCheck::UseComputedDisplayOutsideStyle; + // Then, we need to check next leaf node. const auto leafNodeTypes = aStopAtNonEditableNode == StopAtNonEditableNode::Yes @@ -423,20 +422,20 @@ WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( : LeafNodeTypes{LeafNodeType::OnlyLeafNode}; nsIContent* nextLeafContentOrBlock = HTMLEditUtils::GetNextLeafContentOrNextBlockElement( - aPoint, leafNodeTypes, aBlockInlineCheck, &aAncestorLimiter); + aPoint, leafNodeTypes, blockInlineCheck, &aAncestorLimiter); if (!nextLeafContentOrBlock) { // No next content means that we reached aAncestorLimiter boundary. return BoundaryData( aPoint.template To<EditorDOMPoint>(), const_cast<Element&>(aAncestorLimiter), HTMLEditUtils::IsBlockElement( - aAncestorLimiter, RespectParentBlockBoundary(aBlockInlineCheck)) + aAncestorLimiter, RespectParentBlockBoundary(blockInlineCheck)) ? WSType::CurrentBlockBoundary : WSType::InlineEditingHostBoundary); } if (HTMLEditUtils::IsBlockElement(*nextLeafContentOrBlock, - aBlockInlineCheck)) { + blockInlineCheck)) { // we encountered a new block. therefore no more ws. return BoundaryData(aPoint, *nextLeafContentOrBlock, WSType::OtherBlockBoundary); @@ -461,13 +460,13 @@ WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( // looking for the next one. return BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( aScanMode, EditorDOMPointInText(nextLeafContentOrBlock->AsText(), 0), - aNBSPData, aBlockInlineCheck, aStopAtNonEditableNode, aAncestorLimiter); + aNBSPData, aReferHTMLDefaultStyle, aStopAtNonEditableNode, + aAncestorLimiter); } Maybe<BoundaryData> endInTextNode = BoundaryData::ScanCollapsibleWhiteSpaceEndInTextNode( - EditorDOMPointInText(nextLeafContentOrBlock->AsText(), 0), aNBSPData, - aBlockInlineCheck); + EditorDOMPointInText(nextLeafContentOrBlock->AsText(), 0), aNBSPData); if (endInTextNode.isSome()) { return endInTextNode.ref(); } @@ -477,7 +476,8 @@ WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( return BoundaryData::ScanCollapsibleWhiteSpaceEndFrom( aScanMode, EditorDOMPointInText::AtEndOf(*nextLeafContentOrBlock->AsText()), - aNBSPData, aBlockInlineCheck, aStopAtNonEditableNode, aAncestorLimiter); + aNBSPData, aReferHTMLDefaultStyle, aStopAtNonEditableNode, + aAncestorLimiter); } const EditorDOMRange& @@ -863,7 +863,7 @@ WSRunScanner::TextFragmentData::GetReplaceRangeDataAtStartOfDeletionRange( template <typename EditorDOMPointType, typename PT, typename CT> EditorDOMPointType WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint( const EditorDOMPointBase<PT, CT>& aPoint, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, IgnoreNonEditableNodes aIgnoreNonEditableNodes, const nsIContent* aFollowingLimiterContent /* = nullptr */) { MOZ_ASSERT(aPoint.IsSetAndValid()); @@ -872,12 +872,14 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint( return EditorDOMPointType(); } + const BlockInlineCheck blockInlineCheck = + static_cast<bool>(aReferHTMLDefaultStyle) + ? BlockInlineCheck::UseHTMLDefaultStyle + : BlockInlineCheck::UseComputedDisplayOutsideStyle; const EditorRawDOMPoint point = [&]() MOZ_NEVER_INLINE_DEBUG { nsIContent* const child = aPoint.CanContainerHaveChildren() ? aPoint.GetChild() : nullptr; - if (!child || - HTMLEditUtils::IsBlockElement( - *child, IgnoreInsideBlockBoundary(aBlockInlineCheck)) || + if (!child || HTMLEditUtils::IsBlockElement(*child, blockInlineCheck) || HTMLEditUtils::IsVisibleElementEvenIfLeafNode(*child)) { return aPoint.template To<EditorRawDOMPoint>(); } @@ -890,11 +892,9 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint( // block because end reason content should not be the other side of the // following block boundary. nsIContent* const leafContent = HTMLEditUtils::GetFirstLeafContent( - *child, {LeafNodeType::LeafNodeOrChildBlock}, - IgnoreInsideBlockBoundary(aBlockInlineCheck)); + *child, {LeafNodeType::LeafNodeOrChildBlock}, blockInlineCheck); if (NS_WARN_IF(!leafContent) || - HTMLEditUtils::IsBlockElement( - *leafContent, IgnoreInsideBlockBoundary(aBlockInlineCheck)) || + HTMLEditUtils::IsBlockElement(*leafContent, blockInlineCheck) || HTMLEditUtils::IsVisibleElementEvenIfLeafNode(*leafContent)) { return EditorRawDOMPoint(); } @@ -926,7 +926,7 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint( *aPoint.template ContainerAs<nsIContent>()) ? kScanEditableRootAncestorTypes : kScanAnyRootAncestorTypes, - aBlockInlineCheck); + RespectParentBlockBoundary(blockInlineCheck)); if (NS_WARN_IF( !editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) { return EditorDOMPointType(); @@ -940,19 +940,17 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint( for (nsIContent* nextContent = HTMLEditUtils::GetNextLeafContentOrNextBlockElement( *point.ContainerAs<nsIContent>(), leafNodeTypes, - IgnoreInsideBlockBoundary(aBlockInlineCheck), + blockInlineCheck, editableBlockElementOrInlineEditingHostOrNonEditableRootElement); nextContent; nextContent = HTMLEditUtils::GetNextLeafContentOrNextBlockElement( - *nextContent, leafNodeTypes, - IgnoreInsideBlockBoundary(aBlockInlineCheck), + *nextContent, leafNodeTypes, blockInlineCheck, editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) { if (!nextContent->IsText() || (aIgnoreNonEditableNodes == IgnoreNonEditableNodes::Yes && !HTMLEditUtils::IsSimplyEditableNode(*nextContent))) { if (nextContent == aFollowingLimiterContent || - HTMLEditUtils::IsBlockElement( - *nextContent, IgnoreInsideBlockBoundary(aBlockInlineCheck)) || + HTMLEditUtils::IsBlockElement(*nextContent, blockInlineCheck) || HTMLEditUtils::IsVisibleElementEvenIfLeafNode(*nextContent)) { break; // Reached end of current runs. } @@ -967,7 +965,7 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetInclusiveNextCharPoint( template <typename EditorDOMPointType, typename PT, typename CT> EditorDOMPointType WSRunScanner::TextFragmentData::GetPreviousCharPoint( const EditorDOMPointBase<PT, CT>& aPoint, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, IgnoreNonEditableNodes aIgnoreNonEditableNodes, const nsIContent* aPrecedingLimiterContent /* = nullptr */) { MOZ_ASSERT(aPoint.IsSetAndValid()); @@ -976,13 +974,16 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetPreviousCharPoint( return EditorDOMPointType(); } + const BlockInlineCheck blockInlineCheck = + static_cast<bool>(aReferHTMLDefaultStyle) + ? BlockInlineCheck::UseHTMLDefaultStyle + : BlockInlineCheck::UseComputedDisplayOutsideStyle; const EditorRawDOMPoint point = [&]() MOZ_NEVER_INLINE_DEBUG { nsIContent* const previousChild = aPoint.CanContainerHaveChildren() ? aPoint.GetPreviousSiblingOfChild() : nullptr; if (!previousChild || - HTMLEditUtils::IsBlockElement( - *previousChild, IgnoreInsideBlockBoundary(aBlockInlineCheck)) || + HTMLEditUtils::IsBlockElement(*previousChild, blockInlineCheck) || HTMLEditUtils::IsVisibleElementEvenIfLeafNode(*previousChild)) { return aPoint.template To<EditorRawDOMPoint>(); } @@ -995,11 +996,9 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetPreviousCharPoint( // block because end reason content should not be the other side of the // following block boundary. nsIContent* const leafContent = HTMLEditUtils::GetLastLeafContent( - *previousChild, {LeafNodeType::LeafNodeOrChildBlock}, - IgnoreInsideBlockBoundary(aBlockInlineCheck)); + *previousChild, {LeafNodeType::LeafNodeOrChildBlock}, blockInlineCheck); if (NS_WARN_IF(!leafContent) || - HTMLEditUtils::IsBlockElement( - *leafContent, IgnoreInsideBlockBoundary(aBlockInlineCheck)) || + HTMLEditUtils::IsBlockElement(*leafContent, blockInlineCheck) || HTMLEditUtils::IsVisibleElementEvenIfLeafNode(*leafContent)) { return EditorRawDOMPoint(); } @@ -1032,7 +1031,7 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetPreviousCharPoint( *aPoint.template ContainerAs<nsIContent>()) ? kScanEditableRootAncestorTypes : kScanAnyRootAncestorTypes, - aBlockInlineCheck); + RespectParentBlockBoundary(blockInlineCheck)); if (NS_WARN_IF( !editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) { return EditorDOMPointType(); @@ -1046,21 +1045,18 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetPreviousCharPoint( for ( nsIContent* previousContent = HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( - *point.ContainerAs<nsIContent>(), leafNodeTypes, - IgnoreInsideBlockBoundary(aBlockInlineCheck), + *point.ContainerAs<nsIContent>(), leafNodeTypes, blockInlineCheck, editableBlockElementOrInlineEditingHostOrNonEditableRootElement); previousContent; previousContent = HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( - *previousContent, leafNodeTypes, - IgnoreInsideBlockBoundary(aBlockInlineCheck), + *previousContent, leafNodeTypes, blockInlineCheck, editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) { if (!previousContent->IsText() || (aIgnoreNonEditableNodes == IgnoreNonEditableNodes::Yes && !HTMLEditUtils::IsSimplyEditableNode(*previousContent))) { if (previousContent == aPrecedingLimiterContent || - HTMLEditUtils::IsBlockElement( - *previousContent, IgnoreInsideBlockBoundary(aBlockInlineCheck)) || + HTMLEditUtils::IsBlockElement(*previousContent, blockInlineCheck) || HTMLEditUtils::IsVisibleElementEvenIfLeafNode(*previousContent)) { break; // Reached start of current runs. } @@ -1080,7 +1076,7 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetEndOfCollapsibleASCIIWhiteSpaces( const EditorDOMPointInText& aPointAtASCIIWhiteSpace, nsIEditor::EDirection aDirectionToDelete, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, IgnoreNonEditableNodes aIgnoreNonEditableNodes, const nsIContent* aFollowingLimiterContent /* = nullptr */) { MOZ_ASSERT(aDirectionToDelete == nsIEditor::eNone || @@ -1155,8 +1151,8 @@ WSRunScanner::TextFragmentData::GetEndOfCollapsibleASCIIWhiteSpaces( for (EditorDOMPointInText atEndOfPreviousTextNode = afterLastWhiteSpace;;) { const auto atStartOfNextTextNode = TextFragmentData::GetInclusiveNextCharPoint<EditorDOMPointInText>( - atEndOfPreviousTextNode, aBlockInlineCheck, aIgnoreNonEditableNodes, - aFollowingLimiterContent); + atEndOfPreviousTextNode, aReferHTMLDefaultStyle, + aIgnoreNonEditableNodes, aFollowingLimiterContent); if (!atStartOfNextTextNode.IsSet()) { // There is no more text nodes. Return end of the previous text node. return afterLastWhiteSpace.To<EditorDOMPointType>(); @@ -1198,7 +1194,7 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetFirstASCIIWhiteSpacePointCollapsedTo( const EditorDOMPointInText& aPointAtASCIIWhiteSpace, nsIEditor::EDirection aDirectionToDelete, - BlockInlineCheck aBlockInlineCheck, + ReferHTMLDefaultStyle aReferHTMLDefaultStyle, IgnoreNonEditableNodes aIgnoreNonEditableNodes, const nsIContent* aPrecedingLimiterContent) { MOZ_ASSERT(aDirectionToDelete == nsIEditor::eNone || @@ -1275,7 +1271,7 @@ WSRunScanner::TextFragmentData::GetFirstASCIIWhiteSpacePointCollapsedTo( for (EditorDOMPointInText atStartOfPreviousTextNode = atLastWhiteSpace;;) { const auto atLastCharOfPreviousTextNode = TextFragmentData::GetPreviousCharPoint<EditorDOMPointInText>( - atStartOfPreviousTextNode, aBlockInlineCheck, + atStartOfPreviousTextNode, aReferHTMLDefaultStyle, aIgnoreNonEditableNodes, aPrecedingLimiterContent); if (!atLastCharOfPreviousTextNode.IsSet()) { // There is no more text nodes. Return end of last text node. diff --git a/editor/libeditor/WhiteSpaceVisibilityKeeper.cpp b/editor/libeditor/WhiteSpaceVisibilityKeeper.cpp @@ -200,7 +200,7 @@ Result<MoveNodeResult, nsresult> WhiteSpaceVisibilityKeeper:: WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound( WSRunScanner::Scan::EditableNodes, EditorDOMPoint::AtEndOf(aLeftBlockElement), - BlockInlineCheck::UseComputedDisplayStyle); + ReferHTMLDefaultStyle::No); NS_ASSERTION( aPrecedingInvisibleBRElement == invisibleBRElementAtEndOfLeftBlockElement, "The preceding invisible BR element computation was different"); @@ -430,7 +430,7 @@ Result<MoveNodeResult, nsresult> WhiteSpaceVisibilityKeeper:: const RefPtr<HTMLBRElement> invisibleBRElementBeforeLeftBlockElement = WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound( WSRunScanner::Scan::EditableNodes, atLeftBlockChild, - BlockInlineCheck::UseComputedDisplayStyle); + ReferHTMLDefaultStyle::No); NS_ASSERTION( aPrecedingInvisibleBRElement == invisibleBRElementBeforeLeftBlockElement, "The preceding invisible BR element computation was different"); @@ -739,7 +739,7 @@ Result<MoveNodeResult, nsresult> WhiteSpaceVisibilityKeeper:: WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound( WSRunScanner::Scan::EditableNodes, EditorDOMPoint::AtEndOf(aLeftBlockElement), - BlockInlineCheck::UseComputedDisplayStyle); + ReferHTMLDefaultStyle::No); NS_ASSERTION( aPrecedingInvisibleBRElement == invisibleBRElementAtEndOfLeftBlockElement, "The preceding invisible BR element computation was different"); @@ -1881,8 +1881,7 @@ WhiteSpaceVisibilityKeeper::EnsureNoInvisibleWhiteSpaces( aPoint.GetContainer()->IsEditingHost()) ? aPoint : aPoint.PreviousPointOrParentPoint<EditorDOMPoint>(), - BlockInlineCheck::UseComputedDisplayStyle, - maybeNonEditableClosestBlockElement); + ReferHTMLDefaultStyle::No, maybeNonEditableClosestBlockElement); if (NS_WARN_IF(!textFragmentDataForLeadingWhiteSpaces.IsInitialized())) { return Err(NS_ERROR_FAILURE); } @@ -1942,7 +1941,7 @@ WhiteSpaceVisibilityKeeper::EnsureNoInvisibleWhiteSpaces( textFragmentDataForLeadingWhiteSpaces.ScanStartRef() == aPoint ? textFragmentDataForLeadingWhiteSpaces : TextFragmentData(Scan::EditableNodes, aPoint, - BlockInlineCheck::UseComputedDisplayStyle, + ReferHTMLDefaultStyle::No, maybeNonEditableClosestBlockElement); const EditorDOMRange& trailingWhiteSpaceRange = textFragmentData.InvisibleTrailingWhiteSpaceRangeRef(); @@ -2608,8 +2607,8 @@ Result<CaretPoint, nsresult> WhiteSpaceVisibilityKeeper::DeleteInvisibleASCIIWhiteSpaces( HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPoint) { MOZ_ASSERT(aPoint.IsSet()); - const TextFragmentData textFragmentData( - Scan::EditableNodes, aPoint, BlockInlineCheck::UseComputedDisplayStyle); + const TextFragmentData textFragmentData(Scan::EditableNodes, aPoint, + ReferHTMLDefaultStyle::No); if (NS_WARN_IF(!textFragmentData.IsInitialized())) { return Err(NS_ERROR_FAILURE); } diff --git a/editor/libeditor/WhiteSpaceVisibilityKeeper.h b/editor/libeditor/WhiteSpaceVisibilityKeeper.h @@ -46,6 +46,7 @@ class WhiteSpaceVisibilityKeeper final { using InsertTextTo = EditorBase::InsertTextTo; using LineBreakType = HTMLEditor::LineBreakType; using PointPosition = WSRunScanner::PointPosition; + using ReferHTMLDefaultStyle = WSRunScanner::ReferHTMLDefaultStyle; using Scan = WSRunScanner::Scan; using TextFragmentData = WSRunScanner::TextFragmentData; using VisibleWhiteSpacesData = WSRunScanner::VisibleWhiteSpacesData;