tor-browser

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

commit dd46967eb4b7cb89e09a713c664548c7123b3fb4
parent ca50a4a628a3ea7e8b7fcd8071a48881e3a0846a
Author: Masayuki Nakano <masayuki@d-toybox.com>
Date:   Wed,  7 Jan 2026 01:10:20 +0000

Bug 1998077 - part 4: Replace some callers of `HTMLEditUtils::Get(Next|Previous)Content()` with `HTMLEditUtils::Get(Next|Previous)LeafContentOr(Next|Previous)BlockElement()` r=m_kato

`HTMLEditUtils::Get(Next|Previous)Content()` returns a next/previous
leaf content or next/previous block element if
`WalkTreeOption::StopAtBlockBoundary` is specified.  That's the same
as `HTMLEditUtils::Get(Next|Previous)LeafContentOr(Next|Previous)BlockElement()`.

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

Diffstat:
Meditor/libeditor/AutoClonedRangeArray.cpp | 78+++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Meditor/libeditor/HTMLEditSubActionHandler.cpp | 53+++++++++++++++++++++++++++++------------------------
Meditor/libeditor/HTMLEditUtils.cpp | 35+++++++++++++++--------------------
Meditor/libeditor/HTMLEditorDeleteHandler.cpp | 29++++++++++++++++-------------
Mtesting/web-platform/meta/editing/run/delete.html.ini | 3---
5 files changed, 107 insertions(+), 91 deletions(-)

diff --git a/editor/libeditor/AutoClonedRangeArray.cpp b/editor/libeditor/AutoClonedRangeArray.cpp @@ -35,6 +35,7 @@ namespace mozilla { using namespace dom; using EmptyCheckOption = HTMLEditUtils::EmptyCheckOption; +using LeafNodeOption = HTMLEditUtils::LeafNodeOption; using ReplaceOrVoidElementOption = HTMLEditUtils::ReplaceOrVoidElementOption; /****************************************************************************** @@ -437,20 +438,22 @@ GetPointAtFirstContentOfLineOrParentHTMLBlockIfFirstContentOfBlock( // Look back through any further inline nodes that aren't across a <br> // from us, and that are enclosed in the same block. // I.e., looking for start of current hard line. - constexpr HTMLEditUtils::WalkTreeOptions - ignoreNonEditableNodeAndStopAtBlockBoundary{ - HTMLEditUtils::WalkTreeOption::IgnoreNonEditableNode, - HTMLEditUtils::WalkTreeOption::StopAtBlockBoundary}; - for (nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent( - point, ignoreNonEditableNodeAndStopAtBlockBoundary, - aBlockInlineCheck, &aAncestorLimiter); + for (nsIContent* previousEditableContent = + HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + aBlockInlineCheck, &aAncestorLimiter); previousEditableContent && previousEditableContent->GetParentNode() && !HTMLEditUtils::IsVisibleBRElement(*previousEditableContent) && !HTMLEditUtils::IsBlockElement(*previousEditableContent, aBlockInlineCheck); - previousEditableContent = HTMLEditUtils::GetPreviousContent( - point, ignoreNonEditableNodeAndStopAtBlockBoundary, - aBlockInlineCheck, &aAncestorLimiter)) { + previousEditableContent = + HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + aBlockInlineCheck, &aAncestorLimiter)) { EditorDOMPoint atLastPreformattedNewLine = HTMLEditUtils::GetPreviousPreformattedNewLineInTextNode<EditorDOMPoint>( EditorRawDOMPoint::AtEndOf(*previousEditableContent)); @@ -464,14 +467,20 @@ GetPointAtFirstContentOfLineOrParentHTMLBlockIfFirstContentOfBlock( // <br> element. Look up the tree for as long as we are the first node in // the container (typically, start of nearest block ancestor), and as long // as we haven't hit the body node. - for (nsIContent* nearContent = HTMLEditUtils::GetPreviousContent( - point, ignoreNonEditableNodeAndStopAtBlockBoundary, - aBlockInlineCheck, &aAncestorLimiter); + for (nsIContent* nearContent = + HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + aBlockInlineCheck, &aAncestorLimiter); !nearContent && !point.IsContainerHTMLElement(nsGkAtoms::body) && point.GetContainerParent(); - nearContent = HTMLEditUtils::GetPreviousContent( - point, ignoreNonEditableNodeAndStopAtBlockBoundary, - aBlockInlineCheck, &aAncestorLimiter)) { + nearContent = + HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + aBlockInlineCheck, &aAncestorLimiter)) { // Don't keep looking up if we have found a blockquote element to act on // when we handle outdent. // XXX Sounds like this is hacky. If possible, it should be check in @@ -601,20 +610,22 @@ GetPointAfterFollowingLineBreakOrAtFollowingHTMLBlock( // * <div contenteditable>foo[]<b contenteditable="false">bar</b>baz</div> // Only in the first case, after the caret position isn't wrapped with // new <div> element. - constexpr HTMLEditUtils::WalkTreeOptions - ignoreNonEditableNodeAndStopAtBlockBoundary{ - HTMLEditUtils::WalkTreeOption::IgnoreNonEditableNode, - HTMLEditUtils::WalkTreeOption::StopAtBlockBoundary}; - for (nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent( - point, ignoreNonEditableNodeAndStopAtBlockBoundary, - aBlockInlineCheck, &aAncestorLimiter); + for (nsIContent* nextEditableContent = + HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + aBlockInlineCheck, &aAncestorLimiter); nextEditableContent && !HTMLEditUtils::IsBlockElement(*nextEditableContent, aBlockInlineCheck) && nextEditableContent->GetParent(); - nextEditableContent = HTMLEditUtils::GetNextContent( - point, ignoreNonEditableNodeAndStopAtBlockBoundary, - aBlockInlineCheck, &aAncestorLimiter)) { + nextEditableContent = + HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + aBlockInlineCheck, &aAncestorLimiter)) { EditorDOMPoint atFirstPreformattedNewLine = HTMLEditUtils::GetInclusiveNextPreformattedNewLineInTextNode< EditorDOMPoint>(EditorRawDOMPoint(nextEditableContent, 0)); @@ -658,13 +669,18 @@ GetPointAfterFollowingLineBreakOrAtFollowingHTMLBlock( // element. Look up the tree for as long as we are the last node in the // container (typically, block node), and as long as we haven't hit the body // node. - for (nsIContent* nearContent = HTMLEditUtils::GetNextContent( - point, ignoreNonEditableNodeAndStopAtBlockBoundary, - aBlockInlineCheck, &aAncestorLimiter); + for (nsIContent* nearContent = + HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + aBlockInlineCheck, &aAncestorLimiter); !nearContent && !point.IsContainerHTMLElement(nsGkAtoms::body) && point.GetContainerParent(); - nearContent = HTMLEditUtils::GetNextContent( - point, ignoreNonEditableNodeAndStopAtBlockBoundary, + nearContent = HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, aBlockInlineCheck, &aAncestorLimiter)) { // Don't walk past the editable section. Note that we need to check before // walking up to a parent because we need to return the parent object, so diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp @@ -4234,11 +4234,13 @@ HTMLEditor::FormatBlockContainerWithTransaction( } // We are making a block. Consume a br, if needed. - if (nsCOMPtr<nsIContent> maybeBRContent = HTMLEditUtils::GetNextContent( - pointToInsertBlock, - {WalkTreeOption::IgnoreNonEditableNode, - WalkTreeOption::StopAtBlockBoundary}, - BlockInlineCheck::UseComputedDisplayOutsideStyle, &aEditingHost)) { + if (nsCOMPtr<nsIContent> maybeBRContent = + HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + pointToInsertBlock, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + BlockInlineCheck::UseComputedDisplayOutsideStyle, + &aEditingHost)) { if (maybeBRContent->IsHTMLElement(nsGkAtoms::br)) { AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertBlock); nsresult rv = DeleteNodeWithTransaction(*maybeBRContent); @@ -8317,11 +8319,13 @@ HTMLEditor::InsertElementWithSplittingAncestorsWithTransaction( if (aBRElementNextToSplitPoint == BRElementNextToSplitPoint::Delete) { // Consume a trailing br, if any. This is to keep an alignment from // creating extra lines, if possible. - if (nsCOMPtr<nsIContent> maybeBRContent = HTMLEditUtils::GetNextContent( - splitPoint, - {WalkTreeOption::IgnoreNonEditableNode, - WalkTreeOption::StopAtBlockBoundary}, - BlockInlineCheck::UseComputedDisplayOutsideStyle, &aEditingHost)) { + if (nsCOMPtr<nsIContent> maybeBRContent = + HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + splitPoint, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + BlockInlineCheck::UseComputedDisplayOutsideStyle, + &aEditingHost)) { if (maybeBRContent->IsHTMLElement(nsGkAtoms::br) && splitPoint.GetChild()) { // Making use of html structure... if next node after where we are @@ -8800,10 +8804,10 @@ void HTMLEditor::SetSelectionInterlinePosition() { // content is `<br>`, does this do right thing? if (Element* editingHost = ComputeEditingHost()) { if (nsIContent* previousEditableContentInBlock = - HTMLEditUtils::GetPreviousContent( + HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( atCaret, - {WalkTreeOption::IgnoreNonEditableNode, - WalkTreeOption::StopAtBlockBoundary}, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayStyle, editingHost)) { if (previousEditableContentInBlock->IsHTMLElement(nsGkAtoms::br)) { DebugOnly<nsresult> rvIgnored = SelectionRef().SetInterlinePosition( @@ -8996,10 +9000,10 @@ nsresult HTMLEditor::AdjustCaretPositionAndEnsurePaddingBRElement( // If it's a visible `<br>` element and next editable content is a // padding `<br>` element, we need to set interline position. else if (nsIContent* nextEditableContentInBlock = - HTMLEditUtils::GetNextContent( + HTMLEditUtils::GetNextLeafContentOrNextBlockElement( *previousEditableContent, - {WalkTreeOption::IgnoreNonEditableNode, - WalkTreeOption::StopAtBlockBoundary}, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayStyle, editingHost)) { if (EditorUtils::IsPaddingBRElementForEmptyLastLine( @@ -9020,10 +9024,10 @@ nsresult HTMLEditor::AdjustCaretPositionAndEnsurePaddingBRElement( // If previous editable content in same block is `<br>`, text node, `<img>` // or `<hr>`, current caret position is fine. if (nsIContent* const previousEditableContentInBlock = - HTMLEditUtils::GetPreviousContent( + HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( point, - {WalkTreeOption::IgnoreNonEditableNode, - WalkTreeOption::StopAtBlockBoundary}, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayStyle, editingHost)) { if (previousEditableContentInBlock->IsHTMLElement(nsGkAtoms::br) || previousEditableContentInBlock->IsText() || @@ -9035,11 +9039,12 @@ nsresult HTMLEditor::AdjustCaretPositionAndEnsurePaddingBRElement( // If next editable content in same block is `<br>`, text node, `<img>` or // `<hr>`, current caret position is fine. - if (nsIContent* nextEditableContentInBlock = HTMLEditUtils::GetNextContent( - point, - {WalkTreeOption::IgnoreNonEditableNode, - WalkTreeOption::StopAtBlockBoundary}, - BlockInlineCheck::UseComputedDisplayStyle, editingHost)) { + if (nsIContent* nextEditableContentInBlock = + HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + point, + {LeafNodeOption::IgnoreNonEditableNode, + LeafNodeOption::TreatChildBlockAsLeafNode}, + BlockInlineCheck::UseComputedDisplayStyle, editingHost)) { if (nextEditableContentInBlock->IsText() || nextEditableContentInBlock->IsAnyOfHTMLElements( nsGkAtoms::br, nsGkAtoms::img, nsGkAtoms::hr)) { diff --git a/editor/libeditor/HTMLEditUtils.cpp b/editor/libeditor/HTMLEditUtils.cpp @@ -992,16 +992,12 @@ Element* HTMLEditUtils::GetElementOfImmediateBlockBoundary( auto getNextContent = [&aDirection, &maybeNonEditableAncestorBlock]( const nsIContent& aContent) -> nsIContent* { return aDirection == WalkTreeDirection::Forward - ? HTMLEditUtils::GetNextContent( - aContent, - {WalkTreeOption::IgnoreDataNodeExceptText, - WalkTreeOption::StopAtBlockBoundary}, + ? HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + aContent, {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayStyle, maybeNonEditableAncestorBlock) - : HTMLEditUtils::GetPreviousContent( - aContent, - {WalkTreeOption::IgnoreDataNodeExceptText, - WalkTreeOption::StopAtBlockBoundary}, + : HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + aContent, {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayStyle, maybeNonEditableAncestorBlock); }; @@ -1657,25 +1653,24 @@ template <typename EditorLineBreakType> Maybe<EditorLineBreakType> HTMLEditUtils::GetUnnecessaryLineBreak( const Element& aBlockElement, ScanLineBreak aScanLineBreak) { auto* lastLineBreakContent = [&]() -> nsIContent* { - const WalkTreeOptions onlyPrecedingLine{ - WalkTreeOption::StopAtBlockBoundary}; for (nsIContent* content = aScanLineBreak == ScanLineBreak::AtEndOfBlock ? HTMLEditUtils::GetLastLeafContent(aBlockElement, {}) - : HTMLEditUtils::GetPreviousContent( - aBlockElement, onlyPrecedingLine, + : HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + aBlockElement, + {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayStyle, aBlockElement.GetParentElement()); content; - content = + content = HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + *content, aScanLineBreak == ScanLineBreak::AtEndOfBlock - ? HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( - *content, {}, BlockInlineCheck::UseComputedDisplayStyle, - &aBlockElement) - : HTMLEditUtils::GetPreviousContent( - *content, onlyPrecedingLine, - BlockInlineCheck::UseComputedDisplayStyle, - aBlockElement.GetParentElement())) { + ? LeafNodeOptions{} + : LeafNodeOptions{LeafNodeOption::TreatChildBlockAsLeafNode}, + BlockInlineCheck::UseComputedDisplayStyle, + aScanLineBreak == ScanLineBreak::AtEndOfBlock + ? &aBlockElement + : aBlockElement.GetParentElement())) { // If we're scanning preceding <br> element of aBlockElement, we don't // need to look for a line break in another block because the caller // needs to handle only preceding <br> element of aBlockElement. diff --git a/editor/libeditor/HTMLEditorDeleteHandler.cpp b/editor/libeditor/HTMLEditorDeleteHandler.cpp @@ -2574,23 +2574,27 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner:: MOZ_ASSERT(mSkippedInvisibleContents.IsEmpty()); for (nsIContent* adjacentContent = aDirectionAndAmount == nsIEditor::ePrevious - ? HTMLEditUtils::GetPreviousContent( - *targetContent, {WalkTreeOption::StopAtBlockBoundary}, + ? HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + *targetContent, + {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayOutsideStyle, &aEditingHost) - : HTMLEditUtils::GetNextContent( - *targetContent, {WalkTreeOption::StopAtBlockBoundary}, + : HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + *targetContent, + {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayOutsideStyle, &aEditingHost); adjacentContent; adjacentContent = aDirectionAndAmount == nsIEditor::ePrevious - ? HTMLEditUtils::GetPreviousContent( - *adjacentContent, {WalkTreeOption::StopAtBlockBoundary}, + ? HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( + *adjacentContent, + {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayOutsideStyle, &aEditingHost) - : HTMLEditUtils::GetNextContent( - *adjacentContent, {WalkTreeOption::StopAtBlockBoundary}, + : HTMLEditUtils::GetNextLeafContentOrNextBlockElement( + *adjacentContent, + {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayOutsideStyle, &aEditingHost)) { // If non-editable element is found, we should not skip it to avoid @@ -5589,10 +5593,9 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner:: atStart.IsEndOfContainer() && range.StartRef().GetChild() && HTMLEditUtils::IsInvisibleBRElement( *range.StartRef().GetChild()) - ? HTMLEditUtils::GetNextContent( + ? HTMLEditUtils::GetNextLeafContentOrNextBlockElement( *atStart.ContainerAs<nsIContent>(), - {WalkTreeOption::IgnoreDataNodeExceptText, - WalkTreeOption::StopAtBlockBoundary}, + {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayOutsideStyle, editingHost) : nullptr; @@ -6366,9 +6369,9 @@ nsresult HTMLEditor::AutoMoveOneLineHandler:: const RefPtr<Text> textNodeEndingWithUnnecessaryLineBreak = [&]() -> Text* { Text* lastTextNode = Text::FromNodeOrNull( mMovingToParentBlock - ? HTMLEditUtils::GetPreviousContent( + ? HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement( *mTopmostSrcAncestorBlockInDestBlock, - {WalkTreeOption::StopAtBlockBoundary}, + {LeafNodeOption::TreatChildBlockAsLeafNode}, BlockInlineCheck::UseComputedDisplayOutsideStyle, mDestInclusiveAncestorBlock) : HTMLEditUtils::GetLastLeafContent( diff --git a/testing/web-platform/meta/editing/run/delete.html.ini b/testing/web-platform/meta/editing/run/delete.html.ini @@ -571,9 +571,6 @@ [[["delete",""\]\] "<p>abc</p><ul><li contenteditable=\\"false\\">def</li></ul><p>[\]ghi</p>" compare innerHTML] expected: FAIL - [[["delete",""\]\] "<p>abc</p><ul><li contenteditable=\\"false\\">def</li><li>[\]ghi</li></ul>": execCommand("delete", false, "") return value] - expected: FAIL - [[["delete",""\]\] "<p>abc</p><ul><li contenteditable=\\"false\\">def</li><li>[\]ghi</li></ul>" compare innerHTML] expected: FAIL