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:
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