diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp index 46174a3aa828..5e5e62e01063 100644 --- a/editor/libeditor/EditorBase.cpp +++ b/editor/libeditor/EditorBase.cpp @@ -3462,6 +3462,45 @@ EditorBase::CreateTransactionForCollapsedRange( if (NS_WARN_IF(!point.IsSet())) { return nullptr; } + if (IsTextEditor()) { + // There should be only one text node in the anonymous `
` (but may + // be followed by a padding `
`). We should adjust the point into + // the text node (or return nullptr if there is no text to delete) for + // avoiding finding the text node with complicated API. + if (!point.IsInTextNode()) { + const Element* anonymousDiv = GetRoot(); + if (NS_WARN_IF(!anonymousDiv)) { + return nullptr; + } + if (!anonymousDiv->GetFirstChild() || + !anonymousDiv->GetFirstChild()->IsText()) { + return nullptr; // The value is empty. + } + if (point.GetContainer() == anonymousDiv) { + if (point.IsStartOfContainer()) { + point.Set(anonymousDiv->GetFirstChild(), 0); + } else { + point.SetToEndOf(anonymousDiv->GetFirstChild()); + } + } else { + // Must be referring a padding `
` element or after the text node. + point.SetToEndOf(anonymousDiv->GetFirstChild()); + } + } + MOZ_ASSERT(!point.ContainerAsText()->GetPreviousSibling()); + MOZ_ASSERT(!point.ContainerAsText()->GetNextSibling() || + !point.ContainerAsText()->GetNextSibling()->IsText()); + if (aHowToHandleCollapsedRange == + HowToHandleCollapsedRange::ExtendBackward && + point.IsStartOfContainer()) { + return nullptr; + } + if (aHowToHandleCollapsedRange == + HowToHandleCollapsedRange::ExtendForward && + point.IsEndOfContainer()) { + return nullptr; + } + } // XXX: if the container of point is empty, then we'll need to delete the node // as well as the 1 child @@ -3470,11 +3509,12 @@ EditorBase::CreateTransactionForCollapsedRange( // XXX: this has to come from rule section if (aHowToHandleCollapsedRange == HowToHandleCollapsedRange::ExtendBackward && point.IsStartOfContainer()) { + MOZ_ASSERT(IsHTMLEditor()); // We're backspacing from the beginning of a node. Delete the last thing // of previous editable content. nsIContent* previousEditableContent = EditorBase::GetPreviousContent( *point.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode}, - GetEditorType(), GetEditorRoot()); + EditorType::HTML, GetEditorRoot()); if (!previousEditableContent) { NS_WARNING("There was no editable content before the collapsed range"); return nullptr; @@ -3513,11 +3553,12 @@ EditorBase::CreateTransactionForCollapsedRange( if (aHowToHandleCollapsedRange == HowToHandleCollapsedRange::ExtendForward && point.IsEndOfContainer()) { + MOZ_ASSERT(IsHTMLEditor()); // We're deleting from the end of a node. Delete the first thing of // next editable content. nsIContent* nextEditableContent = EditorBase::GetNextContent( *point.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode}, - GetEditorType(), GetEditorRoot()); + EditorType::HTML, GetEditorRoot()); if (!nextEditableContent) { NS_WARNING("There was no editable content after the collapsed range"); return nullptr; @@ -3574,35 +3615,46 @@ EditorBase::CreateTransactionForCollapsedRange( return deleteTextTransaction.forget(); } - nsIContent* editableContent = - aHowToHandleCollapsedRange == HowToHandleCollapsedRange::ExtendBackward - ? EditorBase::GetPreviousContent( - point, {WalkTreeOption::IgnoreNonEditableNode}, GetEditorType(), - GetEditorRoot()) - : EditorBase::GetNextContent(point, - {WalkTreeOption::IgnoreNonEditableNode}, - GetEditorType(), GetEditorRoot()); - if (!editableContent) { - NS_WARNING("There was no editable content around the collapsed range"); - return nullptr; - } - while (editableContent && editableContent->IsCharacterData() && - !editableContent->Length()) { - // Can't delete an empty text node (bug 762183) + nsIContent* editableContent = nullptr; + if (IsHTMLEditor()) { editableContent = aHowToHandleCollapsedRange == HowToHandleCollapsedRange::ExtendBackward ? EditorBase::GetPreviousContent( - *editableContent, {WalkTreeOption::IgnoreNonEditableNode}, - GetEditorType(), GetEditorRoot()) + point, {WalkTreeOption::IgnoreNonEditableNode}, + EditorType::HTML, GetEditorRoot()) : EditorBase::GetNextContent( - *editableContent, {WalkTreeOption::IgnoreNonEditableNode}, - GetEditorType(), GetEditorRoot()); - } - if (NS_WARN_IF(!editableContent)) { - NS_WARNING( - "There was no editable content which is not empty around the collapsed " - "range"); - return nullptr; + point, {WalkTreeOption::IgnoreNonEditableNode}, + EditorType::HTML, GetEditorRoot()); + if (!editableContent) { + NS_WARNING("There was no editable content around the collapsed range"); + return nullptr; + } + while (editableContent && editableContent->IsCharacterData() && + !editableContent->Length()) { + // Can't delete an empty text node (bug 762183) + editableContent = + aHowToHandleCollapsedRange == + HowToHandleCollapsedRange::ExtendBackward + ? EditorBase::GetPreviousContent( + *editableContent, {WalkTreeOption::IgnoreNonEditableNode}, + EditorType::HTML, GetEditorRoot()) + : EditorBase::GetNextContent( + *editableContent, {WalkTreeOption::IgnoreNonEditableNode}, + EditorType::HTML, GetEditorRoot()); + } + if (!editableContent) { + NS_WARNING( + "There was no editable content which is not empty around the " + "collapsed range"); + return nullptr; + } + } else { + MOZ_ASSERT(point.IsInTextNode()); + editableContent = point.GetContainerAsContent(); + if (!editableContent) { + NS_WARNING("If there was no text node, should've been handled first"); + return nullptr; + } } if (editableContent->IsText()) { @@ -3626,6 +3678,7 @@ EditorBase::CreateTransactionForCollapsedRange( return deleteTextTransaction.forget(); } + MOZ_ASSERT(IsHTMLEditor()); RefPtr deleteNodeTransaction = DeleteNodeTransaction::MaybeCreate(*this, *editableContent); NS_WARNING_ASSERTION(deleteNodeTransaction,