Bug 1764684 - part 2: Make editor use methods of EditorBase to collapse Selection r=m_kato

First, move methods of `HTMLEditor` which collapse `Selection` to `EditorBase`.
Then, make editor stop accessing `Selection::CollapseInLimiter` directly.

Differential Revision: https://phabricator.services.mozilla.com/D143814
This commit is contained in:
Masayuki Nakano 2022-04-20 14:36:52 +00:00
parent 4fa991f17a
commit 17fc88e168
15 changed files with 225 additions and 210 deletions

View File

@ -183,30 +183,23 @@ NS_IMETHODIMP CompositionTransaction::UndoTransaction() {
("%p CompositionTransaction::%s this=%s", this, __FUNCTION__,
ToString(*this).c_str()));
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
return NS_ERROR_NOT_AVAILABLE;
}
// Get the selection first so we'll fail before making any changes if we
// can't get it
RefPtr<Selection> selection = mEditorBase->GetSelection();
if (NS_WARN_IF(!selection)) {
if (MOZ_UNLIKELY(NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode))) {
return NS_ERROR_NOT_AVAILABLE;
}
OwningNonNull<EditorBase> editorBase = *mEditorBase;
OwningNonNull<Text> textNode = *mTextNode;
ErrorResult error;
IgnoredErrorResult error;
editorBase->DoDeleteText(textNode, mOffset, mStringToInsert.Length(), error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("EditorBase::DoDeleteText() failed");
return error.StealNSResult();
}
// set the selection to the insertion point where the string was removed
nsresult rv = selection->CollapseInLimiter(textNode, mOffset);
NS_ASSERTION(NS_SUCCEEDED(rv), "Selection::CollapseInLimiter() failed");
return rv;
editorBase->CollapseSelectionTo(EditorRawDOMPoint(textNode, mOffset), error);
NS_ASSERTION(!error.Failed(), "EditorBase::CollapseSelectionTo() failed");
return error.StealNSResult();
}
NS_IMETHODIMP CompositionTransaction::RedoTransaction() {

View File

@ -7,12 +7,13 @@
#include "DeleteNodeTransaction.h"
#include "DeleteTextTransaction.h"
#include "EditorBase.h"
#include "EditorDOMPoint.h"
#include "EditorUtils.h"
#include "HTMLEditUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/ContentIterator.h"
#include "mozilla/EditorBase.h"
#include "mozilla/Logging.h"
#include "mozilla/mozalloc.h"
#include "mozilla/RangeBoundary.h"
@ -116,13 +117,11 @@ NS_IMETHODIMP DeleteRangeTransaction::DoTransaction() {
return NS_OK;
}
RefPtr<Selection> selection = mEditorBase->GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_NOT_INITIALIZED;
}
rv = selection->CollapseInLimiter(startRef.AsRaw());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Selection::CollapseInLimiter() failed");
OwningNonNull<EditorBase> editorBase = *mEditorBase;
rv = editorBase->CollapseSelectionTo(EditorRawDOMPoint(startRef));
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionToEndOfLastLeafNode() failed");
return rv;
}

View File

@ -123,9 +123,9 @@ NS_IMETHODIMP DeleteTextTransaction::DoTransaction() {
}
// Get the text that we're about to delete
ErrorResult error;
IgnoredErrorResult error;
mTextNode->SubstringData(mOffset, mLengthToDelete, mDeletedText, error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("Text::SubstringData() failed");
return error.StealNSResult();
}
@ -133,7 +133,7 @@ NS_IMETHODIMP DeleteTextTransaction::DoTransaction() {
OwningNonNull<EditorBase> editorBase = *mEditorBase;
OwningNonNull<Text> textNode = *mTextNode;
editorBase->DoDeleteText(textNode, mOffset, mLengthToDelete, error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("EditorBase::DoDeleteText() failed");
return error.StealNSResult();
}
@ -145,13 +145,9 @@ NS_IMETHODIMP DeleteTextTransaction::DoTransaction() {
return NS_OK;
}
RefPtr<Selection> selection = editorBase->GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
selection->CollapseInLimiter(EditorRawDOMPoint(textNode, mOffset), error);
editorBase->CollapseSelectionTo(EditorRawDOMPoint(textNode, mOffset), error);
NS_WARNING_ASSERTION(!error.Failed(),
"Selection::CollapseInLimiter() failed");
"EditorBase::CollapseSelectionTo() failed");
return error.StealNSResult();
}

View File

@ -378,9 +378,9 @@ nsresult EditorBase::InitEditorContentAndSelection() {
// removed by the web app and if they call `Selection::AddRange()`,
// it may cause multiple selection ranges.
if (!SelectionRef().RangeCount()) {
nsresult rv = CollapseSelectionToEnd();
if (NS_FAILED(rv)) {
NS_WARNING("EditorBase::CollapseSelectionToEnd() failed");
nsresult rv = CollapseSelectionToEndOfLastLeafNode();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("EditorBase::CollapseSelectionToEndOfLastLeafNode() failed");
return rv;
}
}
@ -1328,18 +1328,18 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP EditorBase::BeginningOfDocument() {
}
if (!firstEditableLeaf) {
// just the root node, set selection to inside the root
nsresult rv = SelectionRef().CollapseInLimiter(rootElement, 0);
nsresult rv = CollapseSelectionToStartOf(*rootElement);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Selection::CollapseInLimiter() failed");
"EditorBase::CollapseSelectionToStartOf() failed");
return rv;
}
if (firstEditableLeaf->IsText()) {
// If firstEditableLeaf is text, set selection to beginning of the text
// node.
nsresult rv = SelectionRef().CollapseInLimiter(firstEditableLeaf, 0);
nsresult rv = CollapseSelectionToStartOf(*firstEditableLeaf);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Selection::CollapseInLimiter() failed");
"EditorBase::CollapseSelectionToStartOf() failed");
return rv;
}
@ -1352,9 +1352,9 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP EditorBase::BeginningOfDocument() {
MOZ_ASSERT(
parent->ComputeIndexOf(firstEditableLeaf).valueOr(UINT32_MAX) == 0,
"How come the first node isn't the left most child in its parent?");
nsresult rv = SelectionRef().CollapseInLimiter(parent, 0);
nsresult rv = CollapseSelectionToStartOf(*parent);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Selection::CollapseInLimiter() failed");
"EditorBase::CollapseSelectionToStartOf() failed");
return rv;
}
@ -1363,15 +1363,16 @@ NS_IMETHODIMP EditorBase::EndOfDocument() {
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
}
nsresult rv = CollapseSelectionToEnd();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionToEnd() failed");
nsresult rv = CollapseSelectionToEndOfLastLeafNode();
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionToEndOfLastLeafNode() failed");
// This is low level API for XUL applcation. So, we should return raw
// error code here.
return rv;
}
nsresult EditorBase::CollapseSelectionToEnd() const {
nsresult EditorBase::CollapseSelectionToEndOfLastLeafNode() const {
MOZ_ASSERT(IsEditActionDataAvailable());
// XXX Why doesn't this check if the document is alive?
@ -1385,22 +1386,22 @@ nsresult EditorBase::CollapseSelectionToEnd() const {
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIContent> lastContent = rootElement;
nsIContent* lastLeafContent = rootElement;
if (IsTextEditor()) {
lastContent = rootElement->GetFirstChild();
MOZ_ASSERT(lastContent && lastContent->IsText());
lastLeafContent = rootElement->GetFirstChild();
MOZ_ASSERT(lastLeafContent && lastLeafContent->IsText());
} else {
for (nsIContent* child = lastContent->GetLastChild();
for (nsIContent* child = lastLeafContent->GetLastChild();
child && HTMLEditUtils::IsContainerNode(*child);
child = child->GetLastChild()) {
lastContent = child;
lastLeafContent = child;
}
}
nsresult rv =
SelectionRef().CollapseInLimiter(lastContent, lastContent->Length());
CollapseSelectionToEndOf(OwningNonNull<nsINode>(*lastLeafContent));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Selection::CollapseInLimiter() failed");
"EditorBase::CollapseSelectionToEndOf() failed");
return rv;
}
@ -1778,14 +1779,10 @@ nsresult EditorBase::PrepareToInsertContent(
}
}
IgnoredErrorResult error;
SelectionRef().CollapseInLimiter(pointToInsert, error);
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(!error.Failed(),
"Selection::CollapseInLimiter() failed");
return error.StealNSResult();
nsresult rv = CollapseSelectionTo(pointToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionTo() failed");
return rv;
}
nsresult EditorBase::InsertTextAt(const nsAString& aStringToInsert,
@ -3157,20 +3154,20 @@ nsresult EditorBase::SetTextNodeWithoutTransaction(const nsAString& aString,
// We don't support undo here, so we don't really need all of the transaction
// machinery, therefore we can run our transaction directly, breaking all of
// the rules!
ErrorResult error;
IgnoredErrorResult error;
DoSetText(aTextNode, aString, error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("EditorBase::DoSetText() failed");
return error.StealNSResult();
}
DebugOnly<nsresult> rvIgnored = SelectionRef().CollapseInLimiter(
MOZ_KnownLive(&aTextNode), aString.Length());
if (NS_WARN_IF(Destroyed())) {
CollapseSelectionTo(EditorRawDOMPoint(&aTextNode, aString.Length()), error);
if (MOZ_UNLIKELY(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
NS_WARNING("EditorBase::CollapseSelection() caused destroying the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Selection::CollapseInLimiter() failed, but ignored");
NS_ASSERTION(!error.Failed(),
"EditorBase::CollapseSelectionTo() failed, but ignored");
RangeUpdaterRef().SelAdjReplaceText(aTextNode, 0, length, aString.Length());

View File

@ -11,6 +11,7 @@
#include "mozilla/EditAction.h" // for EditAction and EditSubAction
#include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint
#include "mozilla/EventForwards.h" // for InputEventTargetRanges
#include "mozilla/Likely.h" // for MOZ_UNLIKELY, MOZ_LIKELY
#include "mozilla/Maybe.h" // for Maybe
#include "mozilla/OwningNonNull.h" // for OwningNonNull
#include "mozilla/TypeInState.h" // for PropItem, StyleCache
@ -1869,10 +1870,66 @@ class EditorBase : public nsIEditor,
static nsresult GetEndChildNode(const Selection& aSelection,
nsIContent** aEndNode);
template <typename PT, typename CT>
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
CollapseSelectionTo(const EditorDOMPointBase<PT, CT>& aPoint) const {
// We don't need to throw exception directly for a failure of updating
// selection. Therefore, let's use IgnoredErrorResult for the performance.
IgnoredErrorResult error;
CollapseSelectionTo(aPoint, error);
return error.StealNSResult();
}
template <typename PT, typename CT>
MOZ_CAN_RUN_SCRIPT void CollapseSelectionTo(
const EditorDOMPointBase<PT, CT>& aPoint, ErrorResult& aRv) const {
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(!aRv.Failed());
if (aPoint.GetInterlinePosition() != InterlinePosition::Undefined) {
if (MOZ_UNLIKELY(NS_FAILED(SelectionRef().SetInterlinePosition(
aPoint.GetInterlinePosition())))) {
NS_WARNING("Selection::SetInterlinePosition() failed");
aRv.Throw(NS_ERROR_FAILURE);
return;
}
}
SelectionRef().CollapseInLimiter(aPoint, aRv);
if (MOZ_UNLIKELY(Destroyed())) {
NS_WARNING("Selection::CollapseInLimiter() caused destroying the editor");
aRv.Throw(NS_ERROR_EDITOR_DESTROYED);
return;
}
NS_WARNING_ASSERTION(!aRv.Failed(),
"Selection::CollapseInLimiter() failed");
}
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
CollapseSelectionToStartOf(nsINode& aNode) const {
return CollapseSelectionTo(EditorRawDOMPoint(&aNode, 0u));
}
MOZ_CAN_RUN_SCRIPT void CollapseSelectionToStartOf(nsINode& aNode,
ErrorResult& aRv) const {
CollapseSelectionTo(EditorRawDOMPoint(&aNode, 0u), aRv);
}
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
CollapseSelectionToEndOf(nsINode& aNode) const {
return CollapseSelectionTo(EditorRawDOMPoint::AtEndOf(aNode));
}
MOZ_CAN_RUN_SCRIPT void CollapseSelectionToEndOf(nsINode& aNode,
ErrorResult& aRv) const {
CollapseSelectionTo(EditorRawDOMPoint::AtEndOf(aNode), aRv);
}
/**
* CollapseSelectionToEnd() collapses the selection to the end of the editor.
* CollapseSelectionToEnd() collapses the selection to the last leaf content
* of the editor.
*/
MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult CollapseSelectionToEnd() const;
MOZ_CAN_RUN_SCRIPT nsresult CollapseSelectionToEndOfLastLeafNode() const;
/**
* AllowsTransactionsToChangeSelection() returns true if editor allows any

View File

@ -934,13 +934,16 @@ nsresult HTMLEditor::MaybeCreatePaddingBRElementForEmptyEditor() {
}
// Set selection.
SelectionRef().CollapseInLimiter(EditorRawDOMPoint(rootElement, 0),
ignoredError);
if (NS_WARN_IF(Destroyed())) {
rv = CollapseSelectionToStartOf(*rootElement);
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
NS_WARNING(
"EditorBase::CollapseSelectionToStartOf() caused destroying the "
"editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"Selection::CollapseInLimiter() failed, but ignored");
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionToStartOf() failed, but ignored");
return NS_OK;
}

View File

@ -5026,13 +5026,16 @@ nsresult HTMLEditor::DoJoinNodes(nsIContent& aContentToKeep,
if (allowedTransactionsToChangeSelection) {
// Editor wants us to set selection at join point.
DebugOnly<nsresult> rvIgnored = SelectionRef().CollapseInLimiter(
&aContentToKeep, removingContentLength);
if (NS_WARN_IF(Destroyed())) {
DebugOnly<nsresult> rvIgnored = CollapseSelectionTo(
EditorRawDOMPoint(&aContentToKeep, removingContentLength));
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
NS_WARNING(
"EditorBase::CollapseSelectionTo() caused destroying the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Selection::CollapseInLimiter() failed, but ignored");
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"EditorBases::CollapseSelectionTos() failed, but ignored");
}
return NS_OK;
@ -5105,17 +5108,16 @@ Result<RefPtr<Element>, nsresult> HTMLEditor::DeleteSelectionAndCreateElement(
MOZ_ASSERT(newElementOrError.inspect());
// We want the selection to be just after the new node
EditorRawDOMPoint afterNewElement(
EditorRawDOMPoint::After(newElementOrError.inspect()));
const auto afterNewElement =
EditorRawDOMPoint::After(newElementOrError.inspect());
MOZ_ASSERT(afterNewElement.IsSetAndValid());
IgnoredErrorResult ignoredError;
SelectionRef().CollapseInLimiter(afterNewElement, ignoredError);
if (ignoredError.Failed()) {
NS_WARNING("Selection::CollapseInLimiter() failed");
rv = CollapseSelectionTo(afterNewElement);
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("EditorBase::CollapseSelectionTo() failed");
// XXX Even if it succeeded to create new element, this returns error
// when Selection.Collapse() fails something. This could occur with
// when CollapseSelectionTo() fails something. This could occur with
// mutation observer or mutation event listener.
return Err(NS_ERROR_FAILURE);
return Err(rv);
}
return newElementOrError;
}
@ -5151,27 +5153,25 @@ nsresult HTMLEditor::DeleteSelectionAndPrepareToCreateNode() {
}
if (atAnchor.IsStartOfContainer()) {
EditorRawDOMPoint atAnchorContainer(atAnchor.GetContainer());
if (NS_WARN_IF(!atAnchorContainer.IsSetAndValid())) {
const EditorRawDOMPoint atAnchorContainer(atAnchor.GetContainer());
if (MOZ_UNLIKELY(NS_WARN_IF(!atAnchorContainer.IsSetAndValid()))) {
return NS_ERROR_FAILURE;
}
ErrorResult error;
SelectionRef().CollapseInLimiter(atAnchorContainer, error);
NS_WARNING_ASSERTION(!error.Failed(),
"Selection::CollapseInLimiter() failed");
return error.StealNSResult();
nsresult rv = CollapseSelectionTo(atAnchorContainer);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionTo() failed");
return rv;
}
if (atAnchor.IsEndOfContainer()) {
EditorRawDOMPoint afterAnchorContainer(atAnchor.GetContainer());
if (NS_WARN_IF(!afterAnchorContainer.AdvanceOffset())) {
if (MOZ_UNLIKELY(NS_WARN_IF(!afterAnchorContainer.AdvanceOffset()))) {
return NS_ERROR_FAILURE;
}
ErrorResult error;
SelectionRef().CollapseInLimiter(afterAnchorContainer, error);
NS_WARNING_ASSERTION(!error.Failed(),
"Selection::CollapseInLimiter() failed");
return error.StealNSResult();
nsresult rv = CollapseSelectionTo(afterAnchorContainer);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionTo() failed");
return rv;
}
SplitNodeResult splitAtAnchorResult = SplitNodeWithTransaction(atAnchor);

View File

@ -2863,39 +2863,6 @@ class HTMLEditor final : public EditorBase,
protected: // Shouldn't be used by friend classes
virtual ~HTMLEditor();
template <typename PT, typename CT>
[[nodiscard]] MOZ_CAN_RUN_SCRIPT MOZ_NEVER_INLINE_DEBUG nsresult
CollapseSelectionTo(const EditorDOMPointBase<PT, CT>& aPoint) const {
ErrorResult error;
CollapseSelectionTo(aPoint, error);
return error.StealNSResult();
}
template <typename PT, typename CT>
MOZ_CAN_RUN_SCRIPT MOZ_NEVER_INLINE_DEBUG void CollapseSelectionTo(
const EditorDOMPointBase<PT, CT>& aPoint, ErrorResult& aRv) const {
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(!aRv.Failed());
SelectionRef().CollapseInLimiter(aPoint, aRv);
if (NS_WARN_IF(Destroyed())) {
aRv = NS_ERROR_EDITOR_DESTROYED;
return;
}
NS_WARNING_ASSERTION(!aRv.Failed(),
"Selection::CollapseInLimiter() failed");
}
[[nodiscard]] MOZ_CAN_RUN_SCRIPT MOZ_NEVER_INLINE_DEBUG nsresult
CollapseSelectionToStartOf(nsINode& aNode) {
return CollapseSelectionTo(EditorRawDOMPoint(&aNode, 0));
}
MOZ_CAN_RUN_SCRIPT MOZ_NEVER_INLINE_DEBUG void CollapseSelectionToStartOf(
nsINode& aNode, ErrorResult& aRv) const {
CollapseSelectionTo(EditorRawDOMPoint(&aNode, 0), aRv);
}
/**
* InitEditorContentAndSelection() may insert `<br>` elements and padding
* `<br>` elements if they are required for `<body>` or document element.

View File

@ -1989,10 +1989,14 @@ HTMLEditor::AutoDeleteRangesHandler::HandleDeleteTextAroundCollapsedRanges(
const EditorDOMPoint& newCaretPosition = result.inspect();
MOZ_ASSERT(newCaretPosition.IsSetAndValid());
DebugOnly<nsresult> rvIgnored = aHTMLEditor.SelectionRef().CollapseInLimiter(
newCaretPosition.ToRawRangeBoundary());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Selection::Collapse() failed, but ignored");
rv = aHTMLEditor.CollapseSelectionTo(newCaretPosition);
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
NS_WARNING(
"EditorBase::CollapseSelectionTo() caused destroying the editor");
return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
}
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionTo() failed, but ignored");
return EditActionHandled();
}

View File

@ -129,7 +129,7 @@ NS_IMETHODIMP InsertNodeTransaction::DoTransaction() {
"EditorBase::MarkElementDirty() failed, but ignored");
}
ErrorResult error;
IgnoredErrorResult error;
container->InsertBefore(contentToInsert, refChild, error);
// InsertBefore() may call MightThrowJSException() even if there is no
// error. We don't need the flag here.
@ -149,14 +149,10 @@ NS_IMETHODIMP InsertNodeTransaction::DoTransaction() {
}
// Place the selection just after the inserted element.
EditorRawDOMPoint afterInsertedNode(
EditorRawDOMPoint::After(contentToInsert));
NS_WARNING_ASSERTION(afterInsertedNode.IsSet(),
"Failed to set after the inserted node");
IgnoredErrorResult ignoredError;
selection->CollapseInLimiter(afterInsertedNode, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"Selection::CollapseInLimiter() failed, but ignored");
editorBase->CollapseSelectionTo(EditorRawDOMPoint::After(contentToInsert),
error);
NS_WARNING_ASSERTION(!error.Failed(),
"EditorBase::CollapseSelectionTo() failed, but ignored");
return NS_OK;
}

View File

@ -83,10 +83,12 @@ NS_IMETHODIMP InsertTextTransaction::DoTransaction() {
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
DebugOnly<nsresult> rvIgnored = selection->CollapseInLimiter(
textNode, mOffset + mStringToInsert.Length());
DebugOnly<nsresult> rvIgnored = editorBase->CollapseSelectionTo(
EditorRawDOMPoint(textNode, mOffset + mStringToInsert.Length()));
NS_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Selection::CollapseInLimiter() failed, but ignored");
"EditorBase::CollapseSelectionTo() failed, but ignored");
// Keep handling to adjust the ranges in the range updater even if the
// editor is destroyed.
} else {
// Do nothing - DOM Range gravity will adjust selection
}
@ -95,7 +97,8 @@ NS_IMETHODIMP InsertTextTransaction::DoTransaction() {
editorBase->RangeUpdaterRef().SelAdjInsertText(textNode, mOffset,
mStringToInsert.Length());
return NS_OK;
return MOZ_UNLIKELY(editorBase->Destroyed()) ? NS_ERROR_EDITOR_DESTROYED
: NS_OK;
}
NS_IMETHODIMP InsertTextTransaction::UndoTransaction() {

View File

@ -43,18 +43,19 @@ NS_IMETHODIMP ReplaceTextTransaction::DoTransaction() {
("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__,
ToString(*this).c_str()));
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode))) {
if (MOZ_UNLIKELY(
NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode)))) {
return NS_ERROR_NOT_AVAILABLE;
}
OwningNonNull<EditorBase> editorBase = *mEditorBase;
OwningNonNull<Text> textNode = *mTextNode;
ErrorResult error;
IgnoredErrorResult error;
editorBase->DoReplaceText(textNode, mOffset, mStringToBeReplaced.Length(),
mStringToInsert, error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("EditorBase::DoReplaceText() failed");
return error.StealNSResult();
}
@ -69,17 +70,15 @@ NS_IMETHODIMP ReplaceTextTransaction::DoTransaction() {
// XXX Should we stop setting selection when mutation event listener
// modifies the text node?
RefPtr<Selection> selection = editorBase->GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
DebugOnly<nsresult> rvIgnored = selection->CollapseInLimiter(
textNode, mOffset + mStringToInsert.Length());
if (NS_WARN_IF(editorBase->Destroyed())) {
editorBase->CollapseSelectionTo(
EditorRawDOMPoint(textNode, mOffset + mStringToInsert.Length()), error);
if (MOZ_UNLIKELY(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
NS_WARNING(
"EditorBase::CollapseSelectionTo() caused destroying the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Selection::CollapseInLimiter() failed, but ignored");
NS_ASSERTION(!error.Failed(),
"EditorBase::CollapseSelectionTo() failed, but ignored");
return NS_OK;
}
@ -88,20 +87,21 @@ NS_IMETHODIMP ReplaceTextTransaction::UndoTransaction() {
("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__,
ToString(*this).c_str()));
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode))) {
if (MOZ_UNLIKELY(
NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode)))) {
return NS_ERROR_NOT_AVAILABLE;
}
ErrorResult error;
IgnoredErrorResult error;
nsAutoString insertedString;
mTextNode->SubstringData(mOffset, mStringToInsert.Length(), insertedString,
error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("CharacterData::SubstringData() failed");
return error.StealNSResult();
}
if (insertedString != mStringToInsert) {
if (MOZ_UNLIKELY(insertedString != mStringToInsert)) {
NS_WARNING(
"ReplaceTextTransaction::UndoTransaction() did nothing due to "
"unexpected text");
@ -113,7 +113,7 @@ NS_IMETHODIMP ReplaceTextTransaction::UndoTransaction() {
editorBase->DoReplaceText(textNode, mOffset, mStringToInsert.Length(),
mStringToBeReplaced, error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("EditorBase::DoReplaceText() failed");
return error.StealNSResult();
}
@ -128,17 +128,16 @@ NS_IMETHODIMP ReplaceTextTransaction::UndoTransaction() {
// XXX Should we stop setting selection when mutation event listener
// modifies the text node?
RefPtr<Selection> selection = editorBase->GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
DebugOnly<nsresult> rvIgnored = selection->CollapseInLimiter(
textNode, mOffset + mStringToBeReplaced.Length());
if (NS_WARN_IF(editorBase->Destroyed())) {
editorBase->CollapseSelectionTo(
EditorRawDOMPoint(textNode, mOffset + mStringToBeReplaced.Length()),
error);
if (MOZ_UNLIKELY(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
NS_WARNING(
"EditorBase::CollapseSelectionTo() caused destroying the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Selection::CollapseInLimiter() failed, but ignored");
NS_ASSERTION(!error.Failed(),
"EditorBase::CollapseSelectionTo() failed, but ignored");
return NS_OK;
}
@ -147,20 +146,21 @@ NS_IMETHODIMP ReplaceTextTransaction::RedoTransaction() {
("%p ReplaceTextTransaction::%s this=%s", this, __FUNCTION__,
ToString(*this).c_str()));
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode))) {
if (MOZ_UNLIKELY(
NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode) ||
NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(*mTextNode)))) {
return NS_ERROR_NOT_AVAILABLE;
}
ErrorResult error;
IgnoredErrorResult error;
nsAutoString undoneString;
mTextNode->SubstringData(mOffset, mStringToBeReplaced.Length(), undoneString,
error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("CharacterData::SubstringData() failed");
return error.StealNSResult();
}
if (undoneString != mStringToBeReplaced) {
if (MOZ_UNLIKELY(undoneString != mStringToBeReplaced)) {
NS_WARNING(
"ReplaceTextTransaction::RedoTransaction() did nothing due to "
"unexpected text");
@ -172,7 +172,7 @@ NS_IMETHODIMP ReplaceTextTransaction::RedoTransaction() {
editorBase->DoReplaceText(textNode, mOffset, mStringToBeReplaced.Length(),
mStringToInsert, error);
if (error.Failed()) {
if (MOZ_UNLIKELY(error.Failed())) {
NS_WARNING("EditorBase::DoReplaceText() failed");
return error.StealNSResult();
}
@ -187,17 +187,15 @@ NS_IMETHODIMP ReplaceTextTransaction::RedoTransaction() {
// XXX Should we stop setting selection when mutation event listener
// modifies the text node?
RefPtr<Selection> selection = editorBase->GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
DebugOnly<nsresult> rvIgnored = selection->CollapseInLimiter(
textNode, mOffset + mStringToInsert.Length());
if (NS_WARN_IF(editorBase->Destroyed())) {
editorBase->CollapseSelectionTo(
EditorRawDOMPoint(textNode, mOffset + mStringToInsert.Length()), error);
if (MOZ_UNLIKELY(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
NS_WARNING(
"EditorBase::CollapseSelectionTo() caused destroying the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Selection::CollapseInLimiter() failed, but ignored");
NS_ASSERTION(!error.Failed(),
"EditorBase::CollapseSelectionTo() failed, but ignored");
return NS_OK;
}

View File

@ -133,7 +133,7 @@ NS_IMETHODIMP SplitNodeTransaction::DoTransaction() {
htmlEditor->CollapseSelectionTo(
EditorRawDOMPoint::AtEndOf(*splitNodeResult.GetNewContent()), error);
NS_WARNING_ASSERTION(!error.Failed(),
"Selection::CollapseInLimiter() failed");
"EditorBase::CollapseSelectionTo() failed");
return error.StealNSResult();
}

View File

@ -240,9 +240,9 @@ EditActionResult TextEditor::InsertLineFeedCharacterAtSelection() {
!pointAfterInsertedLineFeed.GetChild(),
"After inserting text into a text node, pointAfterInsertedLineFeed."
"GetChild() should be nullptr");
rv = SelectionRef().CollapseInLimiter(pointAfterInsertedLineFeed);
if (NS_FAILED(rv)) {
NS_WARNING("Selection::CollapseInLimiter() failed");
rv = CollapseSelectionTo(pointAfterInsertedLineFeed);
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("EditorBase::CollapseSelectionTo() failed");
return EditActionIgnored(rv);
}
@ -276,13 +276,16 @@ nsresult TextEditor::EnsureCaretNotAtEndOfTextNode() {
return NS_OK;
}
DebugOnly<nsresult> rvIgnored = CollapseSelectionToEnd();
if (NS_WARN_IF(Destroyed())) {
nsresult rv = CollapseSelectionToEndOfLastLeafNode();
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
NS_WARNING(
"EditorBase::CollapseSelectionToEndOfLastLeafNode() caused destroying "
"the editor");
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"EditorBase::CollapseSelectionToEnd() failed, but ignored");
NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionToEndOfLastLeafNode() failed, but ignored");
return NS_OK;
}
@ -508,25 +511,20 @@ EditActionResult TextEditor::HandleInsertText(
// a LF, in which case make the caret attach to the next line.
const bool endsWithLF =
!insertionString.IsEmpty() && insertionString.Last() == nsCRT::LF;
DebugOnly<nsresult> rvIgnored = SelectionRef().SetInterlinePosition(
pointAfterStringInserted.SetInterlinePosition(
endsWithLF ? InterlinePosition::StartOfNextLine
: InterlinePosition::EndOfLine);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"Selection::SetInterlinePosition() failed, but ignored");
MOZ_ASSERT(
!pointAfterStringInserted.GetChild(),
"After inserting text into a text node, pointAfterStringInserted."
"GetChild() should be nullptr");
IgnoredErrorResult ignoredError;
SelectionRef().CollapseInLimiter(pointAfterStringInserted, ignoredError);
if (NS_WARN_IF(Destroyed())) {
nsresult rv = CollapseSelectionTo(pointAfterStringInserted);
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
}
NS_WARNING_ASSERTION(
!ignoredError.Failed(),
"Selection::CollapseInLimiter() failed, but ignored");
NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionTo() failed, but ignored");
}
}

View File

@ -378,7 +378,11 @@ interface nsIEditor : nsISupports
[can_run_script]
void beginningOfDocument();
/** sets the document selection to the end of the document */
/**
* Sets the selection to the end of the last leaf child/descendant or the root
* element.
*/
[can_run_script]
void endOfDocument();
/* ------------ Node manipulation methods -------------- */