Bug 1766355 - part 4: Make HTMLEditor::MoveNodeWithTransaction and HTMLEditor::MoveNodeToEndWithTransaction return MoveNodeResult r=m_kato

Differential Revision: https://phabricator.services.mozilla.com/D146400
This commit is contained in:
Masayuki Nakano
2022-05-20 08:28:09 +00:00
parent c1a368b6a5
commit 7bfa21cc89
7 changed files with 660 additions and 241 deletions

View File

@@ -259,6 +259,50 @@ class MOZ_STACK_CLASS MoveNodeResult final {
mNextInsertionPoint); mNextInsertionPoint);
} }
} }
explicit MoveNodeResult(const EditorDOMPoint& aNextInsertionPoint,
const EditorDOMPoint& aPointToPutCaret)
: mNextInsertionPoint(aNextInsertionPoint),
mCaretPoint(aPointToPutCaret),
mRv(mNextInsertionPoint.IsSet() ? NS_OK : NS_ERROR_FAILURE),
mHandled(mNextInsertionPoint.IsSet()) {
if (mNextInsertionPoint.IsSet()) {
AutoEditorDOMPointChildInvalidator computeOffsetAndForgetChild(
mNextInsertionPoint);
}
}
explicit MoveNodeResult(EditorDOMPoint&& aNextInsertionPoint,
const EditorDOMPoint& aPointToPutCaret)
: mNextInsertionPoint(std::move(aNextInsertionPoint)),
mCaretPoint(aPointToPutCaret),
mRv(mNextInsertionPoint.IsSet() ? NS_OK : NS_ERROR_FAILURE),
mHandled(mNextInsertionPoint.IsSet()) {
if (mNextInsertionPoint.IsSet()) {
AutoEditorDOMPointChildInvalidator computeOffsetAndForgetChild(
mNextInsertionPoint);
}
}
explicit MoveNodeResult(const EditorDOMPoint& aNextInsertionPoint,
EditorDOMPoint&& aPointToPutCaret)
: mNextInsertionPoint(aNextInsertionPoint),
mCaretPoint(std::move(aPointToPutCaret)),
mRv(mNextInsertionPoint.IsSet() ? NS_OK : NS_ERROR_FAILURE),
mHandled(mNextInsertionPoint.IsSet()) {
if (mNextInsertionPoint.IsSet()) {
AutoEditorDOMPointChildInvalidator computeOffsetAndForgetChild(
mNextInsertionPoint);
}
}
explicit MoveNodeResult(EditorDOMPoint&& aNextInsertionPoint,
EditorDOMPoint&& aPointToPutCaret)
: mNextInsertionPoint(std::move(aNextInsertionPoint)),
mCaretPoint(std::move(aPointToPutCaret)),
mRv(mNextInsertionPoint.IsSet() ? NS_OK : NS_ERROR_FAILURE),
mHandled(mNextInsertionPoint.IsSet()) {
if (mNextInsertionPoint.IsSet()) {
AutoEditorDOMPointChildInvalidator computeOffsetAndForgetChild(
mNextInsertionPoint);
}
}
EditorDOMPoint mNextInsertionPoint; EditorDOMPoint mNextInsertionPoint;
// Recommended caret point after moving a node. // Recommended caret point after moving a node.
@@ -273,6 +317,16 @@ class MOZ_STACK_CLASS MoveNodeResult final {
friend MoveNodeResult MoveNodeHandled( friend MoveNodeResult MoveNodeHandled(
const EditorDOMPoint& aNextInsertionPoint); const EditorDOMPoint& aNextInsertionPoint);
friend MoveNodeResult MoveNodeHandled(EditorDOMPoint&& aNextInsertionPoint); friend MoveNodeResult MoveNodeHandled(EditorDOMPoint&& aNextInsertionPoint);
friend MoveNodeResult MoveNodeHandled(
const EditorDOMPoint& aNextInsertionPoint,
const EditorDOMPoint& aPointToPutCaret);
friend MoveNodeResult MoveNodeHandled(EditorDOMPoint&& aNextInsertionPoint,
const EditorDOMPoint& aPointToPutCaret);
friend MoveNodeResult MoveNodeHandled(
const EditorDOMPoint& aNextInsertionPoint,
EditorDOMPoint&& aPointToPutCaret);
friend MoveNodeResult MoveNodeHandled(EditorDOMPoint&& aNextInsertionPoint,
EditorDOMPoint&& aPointToPutCaret);
}; };
/***************************************************************************** /*****************************************************************************
@@ -301,6 +355,27 @@ inline MoveNodeResult MoveNodeHandled(EditorDOMPoint&& aNextInsertionPoint) {
return MoveNodeResult(std::move(aNextInsertionPoint), true); return MoveNodeResult(std::move(aNextInsertionPoint), true);
} }
inline MoveNodeResult MoveNodeHandled(const EditorDOMPoint& aNextInsertionPoint,
const EditorDOMPoint& aPointToPutCaret) {
return MoveNodeResult(aNextInsertionPoint, aPointToPutCaret);
}
inline MoveNodeResult MoveNodeHandled(EditorDOMPoint&& aNextInsertionPoint,
const EditorDOMPoint& aPointToPutCaret) {
return MoveNodeResult(std::move(aNextInsertionPoint), aPointToPutCaret);
}
inline MoveNodeResult MoveNodeHandled(const EditorDOMPoint& aNextInsertionPoint,
EditorDOMPoint&& aPointToPutCaret) {
return MoveNodeResult(aNextInsertionPoint, std::move(aPointToPutCaret));
}
inline MoveNodeResult MoveNodeHandled(EditorDOMPoint&& aNextInsertionPoint,
EditorDOMPoint&& aPointToPutCaret) {
return MoveNodeResult(std::move(aNextInsertionPoint),
std::move(aPointToPutCaret));
}
/***************************************************************************** /*****************************************************************************
* SplitNodeResult is a simple class for * SplitNodeResult is a simple class for
* HTMLEditor::SplitNodeDeepWithTransaction(). * HTMLEditor::SplitNodeDeepWithTransaction().

View File

@@ -2066,19 +2066,24 @@ CreateElementResult HTMLEditor::HandleInsertBRElement(
if (brElement->GetNextSibling() != if (brElement->GetNextSibling() !=
forwardScanFromAfterBRElementResult.BRElementPtr()) { forwardScanFromAfterBRElementResult.BRElementPtr()) {
MOZ_ASSERT(forwardScanFromAfterBRElementResult.BRElementPtr()); MOZ_ASSERT(forwardScanFromAfterBRElementResult.BRElementPtr());
nsresult rv = MoveNodeWithTransaction( const MoveNodeResult moveBRElementResult = MoveNodeWithTransaction(
MOZ_KnownLive(*forwardScanFromAfterBRElementResult.BRElementPtr()), MOZ_KnownLive(*forwardScanFromAfterBRElementResult.BRElementPtr()),
afterBRElement); afterBRElement);
if (MOZ_UNLIKELY((Destroyed()))) { if (moveBRElementResult.isErr()) {
NS_WARNING(
"HTMLEditor::MoveNodeWithTransaction() caused destroying the "
"editor");
return CreateElementResult(NS_ERROR_EDITOR_DESTROYED);
}
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return CreateElementResult(moveBRElementResult.unwrapErr());
}
nsresult rv = moveBRElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return CreateElementResult(rv); return CreateElementResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
} }
} }
@@ -3306,14 +3311,23 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
// of the list, append current node to end of the current list element. // of the list, append current node to end of the current list element.
// Then, wrap it with list item element and delete the old container. // Then, wrap it with list item element and delete the old container.
if (curList && !EditorUtils::IsDescendantOf(*content, *curList)) { if (curList && !EditorUtils::IsDescendantOf(*content, *curList)) {
nsresult rv = MoveNodeToEndWithTransaction(*content, *curList); const MoveNodeResult moveNodeResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(*content, *curList);
return EditActionResult(NS_ERROR_EDITOR_DESTROYED); if (moveNodeResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return EditActionResult(moveNodeResult.unwrapErr());
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return EditActionResult(rv); return EditActionResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
CreateElementResult convertListTypeResult = CreateElementResult convertListTypeResult =
ChangeListElementType(MOZ_KnownLive(*content->AsElement()), ChangeListElementType(MOZ_KnownLive(*content->AsElement()),
aListElementTagName, aListItemElementTagName); aListElementTagName, aListItemElementTagName);
@@ -3400,14 +3414,23 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
MOZ_ASSERT(curList); MOZ_ASSERT(curList);
} }
// Then, move current node into current list element. // Then, move current node into current list element.
nsresult rv = MoveNodeToEndWithTransaction(*content, *curList); const MoveNodeResult moveNodeResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(*content, *curList);
return EditActionResult(NS_ERROR_EDITOR_DESTROYED); if (moveNodeResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return EditActionResult(moveNodeResult.unwrapErr());
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return EditActionResult(rv); return EditActionResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// Convert list item type if current node is different list item type. // Convert list item type if current node is different list item type.
if (!content->IsHTMLElement(&aListItemElementTagName)) { if (!content->IsHTMLElement(&aListItemElementTagName)) {
RefPtr<Element> newListItemElement = ReplaceContainerWithTransaction( RefPtr<Element> newListItemElement = ReplaceContainerWithTransaction(
@@ -3432,14 +3455,23 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
// If current list item element is not a child of current list element, // If current list item element is not a child of current list element,
// move it into current list item. // move it into current list item.
else if (atContent.GetContainer() != curList) { else if (atContent.GetContainer() != curList) {
nsresult rv = MoveNodeToEndWithTransaction(*content, *curList); const MoveNodeResult moveNodeResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(*content, *curList);
return EditActionResult(NS_ERROR_EDITOR_DESTROYED); if (moveNodeResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return EditActionResult(moveNodeResult.unwrapErr());
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return EditActionResult(rv); return EditActionResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
} }
// Then, if current list item element is not proper type for current // Then, if current list item element is not proper type for current
// list element, convert list item element to proper element. // list element, convert list item element to proper element.
@@ -3558,14 +3590,23 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
// If we're currently handling contents of a list item and current node // If we're currently handling contents of a list item and current node
// is not a block element, move current node into the list item. // is not a block element, move current node into the list item.
if (HTMLEditUtils::IsInlineElement(content) && prevListItem) { if (HTMLEditUtils::IsInlineElement(content) && prevListItem) {
nsresult rv = MoveNodeToEndWithTransaction(*content, *prevListItem); const MoveNodeResult moveInlineElementResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(*content, *prevListItem);
return EditActionResult(NS_ERROR_EDITOR_DESTROYED); if (moveInlineElementResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return EditActionResult(moveInlineElementResult.unwrapErr());
}
nsresult rv = moveInlineElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return EditActionResult(rv); return EditActionResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
continue; continue;
} }
@@ -3585,14 +3626,23 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
return EditActionResult(NS_ERROR_FAILURE); return EditActionResult(NS_ERROR_FAILURE);
} }
prevListItem = nullptr; prevListItem = nullptr;
nsresult rv = MoveNodeToEndWithTransaction(*newListItemElement, *curList); const MoveNodeResult moveListItemElementResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(*newListItemElement, *curList);
return EditActionResult(NS_ERROR_EDITOR_DESTROYED); if (moveListItemElementResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return EditActionResult(moveListItemElementResult.unwrapErr());
}
nsresult rv = moveListItemElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return EditActionResult(rv); return EditActionResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// XXX Why don't we set `type` attribute here?? // XXX Why don't we set `type` attribute here??
continue; continue;
} }
@@ -3615,14 +3665,23 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
} else { } else {
prevListItem = nullptr; prevListItem = nullptr;
} }
nsresult rv = MoveNodeToEndWithTransaction(*newListItemElement, *curList); const MoveNodeResult moveListItemElementResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(*newListItemElement, *curList);
return EditActionResult(NS_ERROR_EDITOR_DESTROYED); if (moveListItemElementResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return EditActionResult(moveListItemElementResult.unwrapErr());
}
nsresult rv = moveListItemElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return EditActionResult(rv); return EditActionResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// XXX Why don't we set `type` attribute here?? // XXX Why don't we set `type` attribute here??
} }
@@ -4022,15 +4081,25 @@ nsresult HTMLEditor::IndentListChild(RefPtr<Element>* aCurList,
nextEditableSibling->NodeInfo()->NameAtom() && nextEditableSibling->NodeInfo()->NameAtom() &&
aCurPoint.GetContainer()->NodeInfo()->NamespaceID() == aCurPoint.GetContainer()->NodeInfo()->NamespaceID() ==
nextEditableSibling->NodeInfo()->NamespaceID()) { nextEditableSibling->NodeInfo()->NamespaceID()) {
nsresult rv = MoveNodeWithTransaction( const MoveNodeResult moveListElementResult = MoveNodeWithTransaction(
aContent, EditorDOMPoint(nextEditableSibling, 0)); aContent, EditorDOMPoint(nextEditableSibling, 0u));
if (NS_WARN_IF(Destroyed())) { if (moveListElementResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED; NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveListElementResult.unwrapErr();
} }
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), nsresult rv = moveListElementResult.SuggestCaretPointTo(
"EdigtorBase::MoveNodeWithTransaction() failed"); *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
}
} }
// Check for whether we should join a list that preceeds aContent. // Check for whether we should join a list that preceeds aContent.
@@ -4045,15 +4114,25 @@ nsresult HTMLEditor::IndentListChild(RefPtr<Element>* aCurList,
previousEditableSibling->NodeInfo()->NameAtom() && previousEditableSibling->NodeInfo()->NameAtom() &&
aCurPoint.GetContainer()->NodeInfo()->NamespaceID() == aCurPoint.GetContainer()->NodeInfo()->NamespaceID() ==
previousEditableSibling->NodeInfo()->NamespaceID()) { previousEditableSibling->NodeInfo()->NamespaceID()) {
nsresult rv = const MoveNodeResult moveListElementResult =
MoveNodeToEndWithTransaction(aContent, *previousEditableSibling); MoveNodeToEndWithTransaction(aContent, *previousEditableSibling);
if (NS_WARN_IF(Destroyed())) { if (moveListElementResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED; NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveListElementResult.unwrapErr();
} }
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), nsresult rv = moveListElementResult.SuggestCaretPointTo(
"HTMLEditor::MoveNodeToEndWithTransaction() failed"); *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
}
} }
// check to see if aCurList is still appropriate. Which it is if // check to see if aCurList is still appropriate. Which it is if
@@ -4096,14 +4175,25 @@ nsresult HTMLEditor::IndentListChild(RefPtr<Element>* aCurList,
} }
// tuck the node into the end of the active list // tuck the node into the end of the active list
RefPtr<nsINode> container = *aCurList; RefPtr<nsINode> container = *aCurList;
nsresult rv = MoveNodeToEndWithTransaction(aContent, *container); const MoveNodeResult moveNodeResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(aContent, *container);
return NS_ERROR_EDITOR_DESTROYED; if (moveNodeResult.isErr()) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
} }
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), nsresult rv = moveNodeResult.SuggestCaretPointTo(
"HTMLEditor::MoveNodeToEndWithTransaction() failed"); *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
}
EditActionResult HTMLEditor::HandleIndentAtSelection() { EditActionResult HTMLEditor::HandleIndentAtSelection() {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
@@ -4375,15 +4465,23 @@ nsresult HTMLEditor::HandleCSSIndentAtSelectionInternal() {
// tuck the node into the end of the active blockquote // tuck the node into the end of the active blockquote
// MOZ_KnownLive because 'arrayOfContents' is guaranteed to // MOZ_KnownLive because 'arrayOfContents' is guaranteed to
// keep it alive. // keep it alive.
nsresult rv = const MoveNodeResult moveNodeResult =
MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *curQuote); MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *curQuote);
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
} }
return NS_OK; return NS_OK;
} }
@@ -4585,14 +4683,23 @@ nsresult HTMLEditor::HandleHTMLIndentAtSelectionInternal() {
curList = createNewListElementResult.UnwrapNewNode(); curList = createNewListElementResult.UnwrapNewNode();
} }
rv = MoveNodeToEndWithTransaction(*listItem, *curList); const MoveNodeResult moveListItemElementResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(*listItem, *curList);
return NS_ERROR_EDITOR_DESTROYED; if (moveListItemElementResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveListItemElementResult.unwrapErr();
}
nsresult rv = moveListItemElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// remember we indented this li // remember we indented this li
indentedLI = listItem; indentedLI = listItem;
@@ -4647,14 +4754,23 @@ nsresult HTMLEditor::HandleHTMLIndentAtSelectionInternal() {
// tuck the node into the end of the active blockquote // tuck the node into the end of the active blockquote
// MOZ_KnownLive because 'arrayOfContents' is guaranteed to // MOZ_KnownLive because 'arrayOfContents' is guaranteed to
// keep it alive. // keep it alive.
rv = MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *curQuote); const MoveNodeResult moveNodeResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *curQuote);
return NS_ERROR_EDITOR_DESTROYED; if (moveNodeResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// forget curList, if any // forget curList, if any
curList = nullptr; curList = nullptr;
} }
@@ -5082,15 +5198,24 @@ SplitRangeOffFromNodeResult HTMLEditor::HandleOutdentAtSelectionInternal() {
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
afterCurrentList.IsSet(), afterCurrentList.IsSet(),
"Failed to set it to after current list element"); "Failed to set it to after current list element");
nsresult rv = const MoveNodeResult moveListElementResult =
MoveNodeWithTransaction(*lastChildContent, afterCurrentList); MoveNodeWithTransaction(*lastChildContent, afterCurrentList);
if (NS_WARN_IF(Destroyed())) { if (moveListElementResult.isErr()) {
return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return SplitRangeOffFromNodeResult(
moveListElementResult.unwrapErr());
}
nsresult rv = moveListElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return SplitRangeOffFromNodeResult(rv); return SplitRangeOffFromNodeResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
continue; continue;
} }
@@ -5890,15 +6015,23 @@ nsresult HTMLEditor::AlignNodesAndDescendants(
// Tuck the node into the end of the active div // Tuck the node into the end of the active div
// //
// MOZ_KnownLive because 'aArrayOfContents' is guaranteed to keep it alive. // MOZ_KnownLive because 'aArrayOfContents' is guaranteed to keep it alive.
nsresult rv = MoveNodeToEndWithTransaction(MOZ_KnownLive(content), MoveNodeResult moveNodeResult = MoveNodeToEndWithTransaction(
*createdDivElement); MOZ_KnownLive(content), *createdDivElement);
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
} }
return NS_OK; return NS_OK;
@@ -6009,19 +6142,32 @@ nsresult HTMLEditor::AlignBlockContentsWithDivElement(
// But I'm not sure what we should do if new content is inserted. // But I'm not sure what we should do if new content is inserted.
// Anyway, I don't think that we should move editable contents // Anyway, I don't think that we should move editable contents
// over non-editable contents. Chrome does no do that. // over non-editable contents. Chrome does no do that.
EditorDOMPoint pointToPutCaret;
while (lastEditableContent && (lastEditableContent != newDivElement)) { while (lastEditableContent && (lastEditableContent != newDivElement)) {
nsresult rv = MoveNodeWithTransaction(*lastEditableContent, MoveNodeResult moveNodeResult = MoveNodeWithTransaction(
EditorDOMPoint(newDivElement, 0u)); *lastEditableContent, EditorDOMPoint(newDivElement, 0u));
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return rv; return moveNodeResult.unwrapErr();
} }
moveNodeResult.MoveCaretPointTo(
pointToPutCaret, *this,
{SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
lastEditableContent = HTMLEditUtils::GetLastChild( lastEditableContent = HTMLEditUtils::GetLastChild(
aBlockElement, {WalkTreeOption::IgnoreNonEditableNode}); aBlockElement, {WalkTreeOption::IgnoreNonEditableNode});
} }
if (pointToPutCaret.IsSet()) {
nsresult rv = CollapseSelectionTo(pointToPutCaret);
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(rv),
"EditorBase::CollapseSelectionTo() failed, but ignored");
}
return NS_OK; return NS_OK;
} }
@@ -7155,16 +7301,24 @@ nsresult HTMLEditor::SplitElementsAtEveryBRElement(
// Move break outside of container and also put in node list // Move break outside of container and also put in node list
// MOZ_KnownLive because 'arrayOfBRElements' is guaranteed to keep it alive. // MOZ_KnownLive because 'arrayOfBRElements' is guaranteed to keep it alive.
rv = MoveNodeWithTransaction( const MoveNodeResult moveBRElementResult = MoveNodeWithTransaction(
MOZ_KnownLive(brElement), MOZ_KnownLive(brElement),
splitNodeResult.AtNextContent<EditorDOMPoint>()); splitNodeResult.AtNextContent<EditorDOMPoint>());
if (NS_WARN_IF(Destroyed())) { if (moveBRElementResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveBRElementResult.unwrapErr();
}
rv = moveBRElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
aOutArrayOfContents.AppendElement(brElement); aOutArrayOfContents.AppendElement(brElement);
nextContent = splitNodeResult.GetNextContent(); nextContent = splitNodeResult.GetNextContent();
@@ -7790,15 +7944,13 @@ HTMLEditor::HandleInsertParagraphInListItemElement(
// If aListItemElement is in an invalid sub-list element, move it into // If aListItemElement is in an invalid sub-list element, move it into
// the grand parent list element in order to outdent. // the grand parent list element in order to outdent.
if (HTMLEditUtils::IsAnyListElement(afterLeftListElement.GetContainer())) { if (HTMLEditUtils::IsAnyListElement(afterLeftListElement.GetContainer())) {
nsresult rv = const MoveNodeResult moveListItemElementResult =
MoveNodeWithTransaction(aListItemElement, afterLeftListElement); MoveNodeWithTransaction(aListItemElement, afterLeftListElement);
if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) { if (moveListItemElementResult.isErr()) {
return Err(NS_ERROR_EDITOR_DESTROYED);
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return Err(rv); return Err(moveListItemElementResult.unwrapErr());
} }
moveListItemElementResult.IgnoreCaretPointSuggestion();
return EditorDOMPoint(&aListItemElement, 0u); return EditorDOMPoint(&aListItemElement, 0u);
} }
@@ -8102,15 +8254,23 @@ nsresult HTMLEditor::MoveNodesIntoNewBlockquoteElement(
} }
// MOZ_KnownLive because 'aArrayOfContents' is guaranteed to/ keep it alive. // MOZ_KnownLive because 'aArrayOfContents' is guaranteed to/ keep it alive.
nsresult rv = const MoveNodeResult moveNodeResult =
MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *curBlock); MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *curBlock);
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
} }
return NS_OK; return NS_OK;
} }
@@ -8415,15 +8575,23 @@ nsresult HTMLEditor::CreateOrChangeBlockContainerElement(
TopLevelEditSubActionDataRef().mNewBlockElement = newBlockElement; TopLevelEditSubActionDataRef().mNewBlockElement = newBlockElement;
// MOZ_KnownLive because 'aArrayOfContents' is guaranteed to keep it // MOZ_KnownLive because 'aArrayOfContents' is guaranteed to keep it
// alive. // alive.
rv = MoveNodeToEndWithTransaction(MOZ_KnownLive(content), const MoveNodeResult moveNodeResult = MoveNodeToEndWithTransaction(
*newBlockElement); MOZ_KnownLive(content), *newBlockElement);
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
curBlock = std::move(newBlockElement); curBlock = std::move(newBlockElement);
continue; continue;
} }
@@ -8488,15 +8656,23 @@ nsresult HTMLEditor::CreateOrChangeBlockContainerElement(
// alive. We could try to make that a rvalue ref and create a const array // alive. We could try to make that a rvalue ref and create a const array
// on the stack here, but callers are passing in auto arrays, and we don't // on the stack here, but callers are passing in auto arrays, and we don't
// want to introduce copies.. // want to introduce copies..
nsresult rv = const MoveNodeResult moveNodeResult =
MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *curBlock); MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *curBlock);
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
} }
} }
return NS_OK; return NS_OK;
@@ -8660,15 +8836,23 @@ nsresult HTMLEditor::JoinNearestEditableNodesWithTransaction(
// If they don't have the same parent, first move the right node to after // If they don't have the same parent, first move the right node to after
// the left one // the left one
if (aNodeLeft.GetParentNode() != aNodeRight.GetParentNode()) { if (aNodeLeft.GetParentNode() != aNodeRight.GetParentNode()) {
nsresult rv = const MoveNodeResult moveNodeResult =
MoveNodeWithTransaction(aNodeRight, EditorDOMPoint(&aNodeLeft)); MoveNodeWithTransaction(aNodeRight, EditorDOMPoint(&aNodeLeft));
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
} }
// Separate join rules for differing blocks // Separate join rules for differing blocks
@@ -9573,15 +9757,23 @@ nsresult HTMLEditor::LiftUpListItemElement(
"Failed to advance offset to right list node"); "Failed to advance offset to right list node");
} }
nsresult rv = const MoveNodeResult moveListItemElementResult =
MoveNodeWithTransaction(aListItemElement, pointToInsertListItem); MoveNodeWithTransaction(aListItemElement, pointToInsertListItem);
if (NS_WARN_IF(Destroyed())) { if (moveListItemElementResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveListItemElementResult.unwrapErr();
}
nsresult rv = moveListItemElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// Unwrap list item contents if they are no longer in a list // Unwrap list item contents if they are no longer in a list
// XXX If the parent list element is a child of another list element // XXX If the parent list element is a child of another list element
@@ -10478,14 +10670,23 @@ nsresult HTMLEditor::MoveSelectedContentsToDivElementToMakeItAbsolutePosition(
// new list element in the target `<div>` element to be positioned // new list element in the target `<div>` element to be positioned
// absolutely. // absolutely.
// MOZ_KnownLive because 'arrayOfContents' is guaranteed to keep it alive. // MOZ_KnownLive because 'arrayOfContents' is guaranteed to keep it alive.
nsresult rv = MoveNodeToEndWithTransaction(MOZ_KnownLive(content), const MoveNodeResult moveNodeResult = MoveNodeToEndWithTransaction(
*createdListElement); MOZ_KnownLive(content), *createdListElement);
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED; NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return Err(moveNodeResult.unwrapErr());
} }
if (NS_WARN_IF(NS_FAILED(rv))) { nsresult rv = moveNodeResult.SuggestCaretPointTo(
return rv; *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return Err(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
continue; continue;
} }
@@ -10579,15 +10780,23 @@ nsresult HTMLEditor::MoveSelectedContentsToDivElementToMakeItAbsolutePosition(
// Move current list item element into the createdListElement (could be // Move current list item element into the createdListElement (could be
// non-list element due to the above bug) in a candidate `<div>` element // non-list element due to the above bug) in a candidate `<div>` element
// to be positioned absolutely. // to be positioned absolutely.
nsresult rv = const MoveNodeResult moveListItemElementResult =
MoveNodeToEndWithTransaction(*listItemElement, *createdListElement); MoveNodeToEndWithTransaction(*listItemElement, *createdListElement);
if (NS_WARN_IF(Destroyed())) { if (moveListItemElementResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return rv; return Err(moveListItemElementResult.unwrapErr());
} }
nsresult rv = moveListItemElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return Err(rv);
}
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
handledListItemElement = std::move(listItemElement); handledListItemElement = std::move(listItemElement);
continue; continue;
} }
@@ -10628,15 +10837,23 @@ nsresult HTMLEditor::MoveSelectedContentsToDivElementToMakeItAbsolutePosition(
} }
// MOZ_KnownLive because 'arrayOfContents' is guaranteed to keep it alive. // MOZ_KnownLive because 'arrayOfContents' is guaranteed to keep it alive.
nsresult rv = const MoveNodeResult moveNodeResult =
MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *targetDivElement); MoveNodeToEndWithTransaction(MOZ_KnownLive(content), *targetDivElement);
if (NS_WARN_IF(Destroyed())) { if (moveNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// Forget createdListElement, if any // Forget createdListElement, if any
createdListElement = nullptr; createdListElement = nullptr;
} }

View File

@@ -5114,67 +5114,52 @@ nsresult HTMLEditor::DoJoinNodes(nsIContent& aContentToKeep,
return NS_OK; return NS_OK;
} }
nsresult HTMLEditor::MoveNodeWithTransaction( MoveNodeResult HTMLEditor::MoveNodeWithTransaction(
nsIContent& aContent, const EditorDOMPoint& aPointToInsert) { nsIContent& aContentToMove, const EditorDOMPoint& aPointToInsert) {
MOZ_ASSERT(aPointToInsert.IsSetAndValid()); MOZ_ASSERT(aPointToInsert.IsSetAndValid());
EditorDOMPoint oldPoint(&aContent); EditorDOMPoint oldPoint(&aContentToMove);
if (NS_WARN_IF(!oldPoint.IsSet())) { if (NS_WARN_IF(!oldPoint.IsSet())) {
return NS_ERROR_FAILURE; return MoveNodeResult(NS_ERROR_FAILURE);
} }
// Don't do anything if it's already in right place. // Don't do anything if it's already in right place.
if (aPointToInsert == oldPoint) { if (aPointToInsert == oldPoint) {
return NS_OK; return MoveNodeIgnored(aPointToInsert.NextPoint());
} }
RefPtr<MoveNodeTransaction> moveNodeTransaction = RefPtr<MoveNodeTransaction> moveNodeTransaction =
MoveNodeTransaction::MaybeCreate(*this, aContent, aPointToInsert); MoveNodeTransaction::MaybeCreate(*this, aContentToMove, aPointToInsert);
if (MOZ_UNLIKELY(!moveNodeTransaction)) { if (MOZ_UNLIKELY(!moveNodeTransaction)) {
NS_WARNING("MoveNodeTransaction::MaybeCreate() failed"); NS_WARNING("MoveNodeTransaction::MaybeCreate() failed");
return NS_ERROR_FAILURE; return MoveNodeResult(NS_ERROR_FAILURE);
} }
IgnoredErrorResult ignoredError; IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction( AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eMoveNode, nsIEditor::eNext, ignoredError); *this, EditSubAction::eMoveNode, nsIEditor::eNext, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) { if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ignoredError.StealNSResult(); return MoveNodeResult(ignoredError.StealNSResult());
} }
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
!ignoredError.Failed(), !ignoredError.Failed(),
"TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored"); "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored");
TopLevelEditSubActionDataRef().WillDeleteContent(*this, aContent); TopLevelEditSubActionDataRef().WillDeleteContent(*this, aContentToMove);
nsresult rv = DoTransactionInternal(moveNodeTransaction); nsresult rv = DoTransactionInternal(moveNodeTransaction);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
if (AllowsTransactionsToChangeSelection()) {
const auto pointToPutCaret =
moveNodeTransaction->SuggestPointToPutCaret<EditorRawDOMPoint>();
if (pointToPutCaret.IsSet()) {
nsresult rv = CollapseSelectionTo(pointToPutCaret);
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(rv),
"EditorBase::CollapseSelectionTo() failed, but ignored");
}
}
if (mTextServicesDocument) { if (mTextServicesDocument) {
const OwningNonNull<TextServicesDocument> textServicesDocument = const OwningNonNull<TextServicesDocument> textServicesDocument =
*mTextServicesDocument; *mTextServicesDocument;
textServicesDocument->DidDeleteContent(aContent); textServicesDocument->DidDeleteContent(aContentToMove);
} }
} }
if (!mActionListeners.IsEmpty()) { if (!mActionListeners.IsEmpty()) {
for (auto& listener : mActionListeners.Clone()) { for (auto& listener : mActionListeners.Clone()) {
DebugOnly<nsresult> rvIgnored = listener->DidDeleteNode(&aContent, rv); DebugOnly<nsresult> rvIgnored =
listener->DidDeleteNode(&aContentToMove, rv);
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored), NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::DidDeleteNode() failed, but ignored"); "nsIEditActionListener::DidDeleteNode() failed, but ignored");
@@ -5184,17 +5169,19 @@ nsresult HTMLEditor::MoveNodeWithTransaction(
if (MOZ_UNLIKELY(Destroyed())) { if (MOZ_UNLIKELY(Destroyed())) {
NS_WARNING( NS_WARNING(
"MoveNodeTransaction::DoTransaction() caused destroying the editor"); "MoveNodeTransaction::DoTransaction() caused destroying the editor");
return NS_ERROR_EDITOR_DESTROYED; return MoveNodeResult(NS_ERROR_EDITOR_DESTROYED);
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeTransaction::DoTransaction() failed"); NS_WARNING("MoveNodeTransaction::DoTransaction() failed");
return rv; return MoveNodeResult(rv);
} }
TopLevelEditSubActionDataRef().DidInsertContent(*this, aContent); TopLevelEditSubActionDataRef().DidInsertContent(*this, aContentToMove);
return NS_OK; return MoveNodeHandled(
moveNodeTransaction->SuggestNextInsertionPoint<EditorDOMPoint>(),
moveNodeTransaction->SuggestPointToPutCaret<EditorDOMPoint>());
} }
Result<RefPtr<Element>, nsresult> HTMLEditor::DeleteSelectionAndCreateElement( Result<RefPtr<Element>, nsresult> HTMLEditor::DeleteSelectionAndCreateElement(

View File

@@ -1977,25 +1977,26 @@ class HTMLEditor final : public EditorBase,
} }
/** /**
* MoveNodeWithTransaction() moves aContent to aPointToInsert. * MoveNodeWithTransaction() moves aContentToMove to aPointToInsert.
* *
* @param aContent The node to be moved. * @param aContentToMove The node to be moved.
* @param aPointToInsert The point where aContentToMove will be inserted.
*/ */
MOZ_CAN_RUN_SCRIPT nsresult MoveNodeWithTransaction( [[nodiscard]] MOZ_CAN_RUN_SCRIPT MoveNodeResult MoveNodeWithTransaction(
nsIContent& aContent, const EditorDOMPoint& aPointToInsert); nsIContent& aContentToMove, const EditorDOMPoint& aPointToInsert);
/** /**
* MoveNodeToEndWithTransaction() moves aContent to end of aNewContainer. * MoveNodeToEndWithTransaction() moves aContentToMove to end of
* aNewContainer.
* *
* @param aContent The node to be moved. * @param aContentToMove The node to be moved.
* @param aNewContainer The new container which will contain aContent as * @param aNewContainer The new container which will contain aContentToMove
* its last child. * as its last child.
*/ */
MOZ_CAN_RUN_SCRIPT nsresult [[nodiscard]] MOZ_CAN_RUN_SCRIPT MoveNodeResult MoveNodeToEndWithTransaction(
MoveNodeToEndWithTransaction(nsIContent& aContent, nsINode& aNewContainer) { nsIContent& aContentToMove, nsINode& aNewContainer) {
EditorDOMPoint pointToInsert; return MoveNodeWithTransaction(aContentToMove,
pointToInsert.SetToEndOf(&aNewContainer); EditorDOMPoint::AtEndOf(aNewContainer));
return MoveNodeWithTransaction(aContent, pointToInsert);
} }
/** /**

View File

@@ -4849,21 +4849,28 @@ MoveNodeResult HTMLEditor::MoveNodeOrChildrenWithTransaction(
if (HTMLEditUtils::CanNodeContain(*aPointToInsert.GetContainer(), aContent)) { if (HTMLEditUtils::CanNodeContain(*aPointToInsert.GetContainer(), aContent)) {
// If it can, move it there. // If it can, move it there.
EditorDOMPoint pointToInsert(aPointToInsert); EditorDOMPoint pointToInsert(aPointToInsert);
{ MoveNodeResult moveNodeResult =
AutoEditorDOMPointChildInvalidator lockOffset(pointToInsert); MoveNodeWithTransaction(aContent, pointToInsert);
nsresult rv = MoveNodeWithTransaction(aContent, pointToInsert); if (moveNodeResult.isErr()) {
if (NS_WARN_IF(Destroyed())) {
return MoveNodeResult(NS_ERROR_EDITOR_DESTROYED);
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return MoveNodeResult(moveNodeResult.unwrapErr());
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return MoveNodeResult(rv); return MoveNodeResult(rv);
} }
} NS_WARNING_ASSERTION(
// Advance DOM point with offset for keeping backward compatibility. rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
// XXX Where should we insert next content if a mutation event listener "MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// break the relation of offset and moved node? // XXX This is odd to override the handled state here, but stopping this
return MoveNodeHandled(pointToInsert.NextPoint()); // hits an NS_ASSERTION in WhiteSpaceVisibilityKeeper::
// MergeFirstLineOfRightBlockElementIntoAncestorLeftBlockElement.
moveNodeResult.MarkAsHandled();
return moveNodeResult;
} }
// If it can't, move its children (if any), and then delete it. // If it can't, move its children (if any), and then delete it.

View File

@@ -548,15 +548,24 @@ nsresult HTMLEditor::SetInlinePropertyOnTextNode(
} }
if (result.inspect()) { if (result.inspect()) {
// Previous sib is already right kind of inline node; slide this over // Previous sib is already right kind of inline node; slide this over
nsresult rv = const MoveNodeResult moveTextNodeResult =
MoveNodeToEndWithTransaction(*textNodeForTheRange, element); MoveNodeToEndWithTransaction(*textNodeForTheRange, element);
if (NS_WARN_IF(Destroyed())) { if (moveTextNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED; NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveTextNodeResult.unwrapErr();
}
nsresult rv = moveTextNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv;
} }
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv), rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"HTMLEditor::MoveNodeToEndWithTransaction() failed"); "MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return rv; return NS_OK;
} }
} }
sibling = HTMLEditUtils::GetNextSibling( sibling = HTMLEditUtils::GetNextSibling(
@@ -571,15 +580,25 @@ nsresult HTMLEditor::SetInlinePropertyOnTextNode(
} }
if (result.inspect()) { if (result.inspect()) {
// Following sib is already right kind of inline node; slide this over // Following sib is already right kind of inline node; slide this over
nsresult rv = MoveNodeWithTransaction(*textNodeForTheRange, const MoveNodeResult moveTextNodeResult = MoveNodeWithTransaction(
EditorDOMPoint(sibling, 0)); *textNodeForTheRange, EditorDOMPoint(sibling, 0u));
if (NS_WARN_IF(Destroyed())) { if (moveTextNodeResult.isErr()) {
return NS_ERROR_EDITOR_DESTROYED; NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveTextNodeResult.unwrapErr();
} }
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), nsresult rv = moveTextNodeResult.SuggestCaretPointTo(
"HTMLEditor::MoveNodeWithTransaction() failed"); *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
}
} }
} }
@@ -644,11 +663,23 @@ nsresult HTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aContent,
return canMoveIntoPreviousSibling.unwrapErr(); return canMoveIntoPreviousSibling.unwrapErr();
} }
if (canMoveIntoPreviousSibling.inspect()) { if (canMoveIntoPreviousSibling.inspect()) {
nsresult rv = MoveNodeToEndWithTransaction(aContent, *previousSibling); const MoveNodeResult moveNodeResult =
if (NS_FAILED(rv)) { MoveNodeToEndWithTransaction(aContent, *previousSibling);
if (moveNodeResult.isErr()) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
if (!nextSibling || !nextSibling->IsElement()) { if (!nextSibling || !nextSibling->IsElement()) {
return NS_OK; return NS_OK;
} }
@@ -681,12 +712,25 @@ nsresult HTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aContent,
return canMoveIntoNextSibling.unwrapErr(); return canMoveIntoNextSibling.unwrapErr();
} }
if (canMoveIntoNextSibling.inspect()) { if (canMoveIntoNextSibling.inspect()) {
nsresult rv = const MoveNodeResult moveNodeResult =
MoveNodeWithTransaction(aContent, EditorDOMPoint(nextElement, 0)); MoveNodeWithTransaction(aContent, EditorDOMPoint(nextElement, 0u));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), if (moveNodeResult.isErr()) {
"HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
}
} }
// Don't need to do anything if property already set on node // Don't need to do anything if property already set on node
@@ -1169,14 +1213,23 @@ EditResult HTMLEditor::ClearStyleAt(const EditorDOMPoint& aPoint,
// the left node left node. This is so we you don't revert back to the // the left node left node. This is so we you don't revert back to the
// previous style if you happen to click at the end of a line. // previous style if you happen to click at the end of a line.
if (brElement) { if (brElement) {
nsresult rv = MoveNodeWithTransaction(*brElement, pointToPutCaret); const MoveNodeResult moveBRElementResult =
if (NS_WARN_IF(Destroyed())) { MoveNodeWithTransaction(*brElement, pointToPutCaret);
return EditResult(NS_ERROR_EDITOR_DESTROYED); if (moveBRElementResult.isErr()) {
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return EditResult(moveBRElementResult.unwrapErr());
}
nsresult rv = moveBRElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return EditResult(rv); return EditResult(rv);
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
// Update the child. // Update the child.
pointToPutCaret.Set(pointToPutCaret.GetContainer(), 0); pointToPutCaret.Set(pointToPutCaret.GetContainer(), 0);
} }
@@ -2596,21 +2649,48 @@ nsresult HTMLEditor::RelativeFontChangeOnTextNode(FontSize aDir,
*textNodeForTheRange, {WalkTreeOption::IgnoreNonEditableNode}); *textNodeForTheRange, {WalkTreeOption::IgnoreNonEditableNode});
if (sibling && sibling->IsHTMLElement(nodeType)) { if (sibling && sibling->IsHTMLElement(nodeType)) {
// Previous sib is already right kind of inline node; slide this over // Previous sib is already right kind of inline node; slide this over
nsresult rv = MoveNodeToEndWithTransaction(*textNodeForTheRange, *sibling); const MoveNodeResult moveTextNodeResult =
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), MoveNodeToEndWithTransaction(*textNodeForTheRange, *sibling);
"HTMLEditor::MoveNodeToEndWithTransaction() failed"); if (moveTextNodeResult.isErr()) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveTextNodeResult.unwrapErr();
}
nsresult rv = moveTextNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
}
sibling = HTMLEditUtils::GetNextSibling( sibling = HTMLEditUtils::GetNextSibling(
*textNodeForTheRange, {WalkTreeOption::IgnoreNonEditableNode}); *textNodeForTheRange, {WalkTreeOption::IgnoreNonEditableNode});
if (sibling && sibling->IsHTMLElement(nodeType)) { if (sibling && sibling->IsHTMLElement(nodeType)) {
// Following sib is already right kind of inline node; slide this over // Following sib is already right kind of inline node; slide this over
nsresult rv = MoveNodeWithTransaction(*textNodeForTheRange, const MoveNodeResult moveTextNodeResult = MoveNodeWithTransaction(
EditorDOMPoint(sibling, 0)); *textNodeForTheRange, EditorDOMPoint(sibling, 0u));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), if (moveTextNodeResult.isErr()) {
"HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveTextNodeResult.unwrapErr();
}
nsresult rv = moveTextNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
}
// Else reparent the node inside font node with appropriate relative size // Else reparent the node inside font node with appropriate relative size
RefPtr<Element> newElement = InsertContainerWithTransaction( RefPtr<Element> newElement = InsertContainerWithTransaction(
@@ -2728,18 +2808,49 @@ nsresult HTMLEditor::RelativeFontChangeOnNode(int32_t aSizeChange,
if (sibling && sibling->IsHTMLElement(atom)) { if (sibling && sibling->IsHTMLElement(atom)) {
// previous sib is already right kind of inline node; slide this over into // previous sib is already right kind of inline node; slide this over into
// it // it
nsresult rv = MoveNodeToEndWithTransaction(*aNode, *sibling); const MoveNodeResult moveNodeResult =
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), MoveNodeToEndWithTransaction(*aNode, *sibling);
"HTMLEditor::MoveNodeToEndWithTransaction() failed"); if (moveNodeResult.isErr()) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv; return rv;
} }
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
}
sibling = HTMLEditUtils::GetNextSibling( sibling = HTMLEditUtils::GetNextSibling(
*aNode, {WalkTreeOption::IgnoreNonEditableNode}); *aNode, {WalkTreeOption::IgnoreNonEditableNode});
if (sibling && sibling->IsHTMLElement(atom)) { if (sibling && sibling->IsHTMLElement(atom)) {
// following sib is already right kind of inline node; slide this over // following sib is already right kind of inline node; slide this over
// into it // into it
return MoveNodeWithTransaction(*aNode, EditorDOMPoint(sibling, 0)); const MoveNodeResult moveNodeResult =
MoveNodeWithTransaction(*aNode, EditorDOMPoint(sibling, 0u));
if (moveNodeResult.isErr()) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveNodeResult.unwrapErr();
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv;
}
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
} }
// else insert it above aNode // else insert it above aNode

View File

@@ -63,6 +63,27 @@ class MoveNodeTransaction final : public EditTransactionBase {
return EditorDOMPointType::After(mContentToMove); return EditorDOMPointType::After(mContentToMove);
} }
/**
* Suggest next insertion point if the caller wants to move another content
* node around the insertion point.
*/
template <typename EditorDOMPointType>
EditorDOMPointType SuggestNextInsertionPoint() const {
if (MOZ_UNLIKELY(!mContainer)) {
return EditorDOMPointType();
}
if (!mReference) {
return EditorDOMPointType::AtEndOf(mContainer);
}
if (MOZ_UNLIKELY(mReference->GetParentNode() != mContainer)) {
if (MOZ_LIKELY(mContentToMove->GetParentNode() == mContainer)) {
return EditorDOMPointType(mContentToMove).NextPoint();
}
return EditorDOMPointType::AtEndOf(mContainer);
}
return EditorDOMPointType(mReference);
}
friend std::ostream& operator<<(std::ostream& aStream, friend std::ostream& operator<<(std::ostream& aStream,
const MoveNodeTransaction& aTransaction); const MoveNodeTransaction& aTransaction);