Bug 1740859 - part 1: Make `HTMLEditor::SplitNodeWithTransaction()` return `NS_ERROR_EDITOR_DESTROYED` if it happens r=m_kato

For making the code simpler, this patch makes it returns
`Result<nsCOMPtr<nsIContent>, nsresult>` instead of using `ErrorResult`.
This must make the construction faster and callers simpler.

Depends on D130950

Differential Revision: https://phabricator.services.mozilla.com/D131043
This commit is contained in:
Masayuki Nakano 2021-11-15 02:23:33 +00:00
Родитель 44f94fa3e3
Коммит c3d57d415e
5 изменённых файлов: 115 добавлений и 122 удалений

Просмотреть файл

@ -344,6 +344,27 @@ class MOZ_STACK_CLASS SplitNodeResult final {
mRv(NS_OK) {
MOZ_DIAGNOSTIC_ASSERT(mPreviousNode || mNextNode);
}
SplitNodeResult(nsCOMPtr<nsIContent>&& aPreviousNodeOfSplitPoint,
nsIContent* aNextNodeOfSplitPoint)
: mPreviousNode(std::move(aPreviousNodeOfSplitPoint)),
mNextNode(aNextNodeOfSplitPoint),
mRv(NS_OK) {
MOZ_DIAGNOSTIC_ASSERT(mPreviousNode || mNextNode);
}
SplitNodeResult(nsIContent* aPreviousNodeOfSplitPoint,
nsCOMPtr<nsIContent>&& aNextNodeOfSplitPoint)
: mPreviousNode(aPreviousNodeOfSplitPoint),
mNextNode(std::move(aNextNodeOfSplitPoint)),
mRv(NS_OK) {
MOZ_DIAGNOSTIC_ASSERT(mPreviousNode || mNextNode);
}
SplitNodeResult(nsCOMPtr<nsIContent>&& aPreviousNodeOfSplitPoint,
nsCOMPtr<nsIContent>&& aNextNodeOfSplitPoint)
: mPreviousNode(std::move(aPreviousNodeOfSplitPoint)),
mNextNode(std::move(aNextNodeOfSplitPoint)),
mRv(NS_OK) {
MOZ_DIAGNOSTIC_ASSERT(mPreviousNode || mNextNode);
}
/**
* This constructor should be used when the method didn't split any nodes

Просмотреть файл

@ -3163,16 +3163,11 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
if (NS_WARN_IF(!atContent.GetContainerAsContent())) {
return EditActionResult(NS_ERROR_FAILURE);
}
ErrorResult error;
nsCOMPtr<nsIContent> newLeftNode =
SplitNodeWithTransaction(atContent, error);
if (NS_WARN_IF(Destroyed())) {
error.SuppressException();
return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
}
if (error.Failed()) {
Result<nsCOMPtr<nsIContent>, nsresult> newLeftNodeOrError =
SplitNodeWithTransaction(atContent);
if (MOZ_UNLIKELY(newLeftNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return EditActionResult(error.StealNSResult());
return EditActionResult(newLeftNodeOrError.unwrapErr());
}
Result<RefPtr<Element>, nsresult> maybeNewListElement =
CreateNodeWithTransaction(
@ -6476,7 +6471,6 @@ nsresult HTMLEditor::SplitTextNodesAtRangeEnd(
nsTArray<RefPtr<nsRange>>& aArrayOfRanges) {
// Split text nodes. This is necessary, since given ranges may end in text
// nodes in case where part of a pre-formatted elements needs to be moved.
ErrorResult error;
IgnoredErrorResult ignoredError;
for (RefPtr<nsRange>& range : aArrayOfRanges) {
EditorDOMPoint atEnd(range->EndRef());
@ -6486,14 +6480,11 @@ nsresult HTMLEditor::SplitTextNodesAtRangeEnd(
if (!atEnd.IsStartOfContainer() && !atEnd.IsEndOfContainer()) {
// Split the text node.
nsCOMPtr<nsIContent> newLeftNode = SplitNodeWithTransaction(atEnd, error);
if (NS_WARN_IF(Destroyed())) {
error = NS_ERROR_EDITOR_DESTROYED;
}
if (error.Failed()) {
NS_WARNING_ASSERTION(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED),
"HTMLEditor::SplitNodeWithTransaction() failed");
return error.StealNSResult();
Result<nsCOMPtr<nsIContent>, nsresult> newLeftNodeOrError =
SplitNodeWithTransaction(atEnd);
if (MOZ_UNLIKELY(newLeftNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return newLeftNodeOrError.unwrapErr();
}
// Correct the range.
@ -7173,18 +7164,13 @@ EditActionResult HTMLEditor::HandleInsertParagraphInParagraph(
if (pointToSplitOrError.inspect().IsSet()) {
pointToSplitParentDivOrP = pointToSplitOrError.unwrap();
}
ErrorResult error;
nsCOMPtr<nsIContent> newLeftTextNode =
SplitNodeWithTransaction(pointToSplitParentDivOrP, error);
if (NS_WARN_IF(Destroyed())) {
error = NS_ERROR_EDITOR_DESTROYED;
Result<nsCOMPtr<nsIContent>, nsresult> newLeftTextNodeOrError =
SplitNodeWithTransaction(pointToSplitParentDivOrP);
if (MOZ_UNLIKELY(newLeftTextNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return EditActionResult(newLeftTextNodeOrError.unwrapErr());
}
if (error.Failed()) {
NS_WARNING_ASSERTION(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED),
"HTMLEditor::SplitNodeWithTransaction() failed");
return EditActionResult(error.StealNSResult());
}
pointToSplitParentDivOrP.SetToEndOf(newLeftTextNode);
pointToSplitParentDivOrP.SetToEndOf(newLeftTextNodeOrError.unwrap());
}
// We need to put new <br> after the left node if given node was split
@ -7368,17 +7354,13 @@ nsresult HTMLEditor::HandleInsertParagraphInListItemElement(
if (!HTMLEditUtils::IsLastChild(aListItem,
{WalkTreeOption::IgnoreNonEditableNode})) {
// We need to split the list!
EditorDOMPoint atListItem(&aListItem);
ErrorResult error;
leftListNode = SplitNodeWithTransaction(atListItem, error);
if (NS_WARN_IF(Destroyed())) {
error = NS_ERROR_EDITOR_DESTROYED;
}
if (error.Failed()) {
NS_WARNING_ASSERTION(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED),
"HTMLEditor::SplitNodeWithTransaction() failed");
return error.StealNSResult();
Result<nsCOMPtr<nsIContent>, nsresult> newListElementOrError =
SplitNodeWithTransaction(EditorDOMPoint(&aListItem));
if (MOZ_UNLIKELY(newListElementOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return newListElementOrError.unwrapErr();
}
leftListNode = newListElementOrError.unwrap();
}
// Are we in a sublist?
@ -8971,24 +8953,19 @@ nsresult HTMLEditor::LiftUpListItemElement(
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(atListItemElement.IsSetAndValid());
ErrorResult error;
nsCOMPtr<nsIContent> maybeLeftListContent =
SplitNodeWithTransaction(atListItemElement, error);
if (NS_WARN_IF(Destroyed())) {
error = NS_ERROR_EDITOR_DESTROYED;
Result<nsCOMPtr<nsIContent>, nsresult> leftListElementOrError =
SplitNodeWithTransaction(atListItemElement);
if (MOZ_UNLIKELY(leftListElementOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return leftListElementOrError.unwrapErr();
}
if (error.Failed()) {
NS_WARNING_ASSERTION(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED),
"HTMLEditor::SplitNodeWithTransaction() failed");
return error.StealNSResult();
}
if (!maybeLeftListContent->IsElement()) {
leftListElement = Element::FromNodeOrNull(leftListElementOrError.unwrap());
if (MOZ_UNLIKELY(!leftListElement)) {
NS_WARNING(
"HTMLEditor::SplitNodeWithTransaction() didn't return left list "
"element");
return NS_ERROR_FAILURE;
}
leftListElement = maybeLeftListContent->AsElement();
}
// In most cases, insert the list item into the new left list node..

Просмотреть файл

@ -3497,15 +3497,16 @@ Result<EditorDOMPoint, nsresult> HTMLEditor::PrepareToInsertBRElement(
MOZ_DIAGNOSTIC_ASSERT(aPointToInsert.IsSetAndValid());
// Unfortunately, we need to split the text node at the offset.
ErrorResult error;
nsCOMPtr<nsIContent> newLeftNode =
SplitNodeWithTransaction(aPointToInsert, error);
if (error.Failed()) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return Err(error.StealNSResult());
{
// Unfortunately, we need to split the text node at the offset.
Result<nsCOMPtr<nsIContent>, nsresult> newLeftTextNodeOrError =
SplitNodeWithTransaction(aPointToInsert);
if (MOZ_UNLIKELY(newLeftTextNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return Err(newLeftTextNodeOrError.unwrapErr());
}
}
Unused << newLeftNode;
// Insert new <br> before the right node.
EditorDOMPoint pointInContainer(aPointToInsert.GetContainer());
if (!pointInContainer.IsSet()) {
@ -4190,31 +4191,30 @@ nsresult HTMLEditor::RemoveBlockContainerWithTransaction(Element& aElement) {
return rv;
}
already_AddRefed<nsIContent> HTMLEditor::SplitNodeWithTransaction(
const EditorDOMPoint& aStartOfRightNode, ErrorResult& aError) {
Result<nsCOMPtr<nsIContent>, nsresult> HTMLEditor::SplitNodeWithTransaction(
const EditorDOMPoint& aStartOfRightNode) {
MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!aStartOfRightNode.IsInContentNode())) {
aError.Throw(NS_ERROR_INVALID_ARG);
return nullptr;
if (MOZ_UNLIKELY(NS_WARN_IF(!aStartOfRightNode.IsInContentNode()))) {
return Err(NS_ERROR_INVALID_ARG);
}
MOZ_ASSERT(aStartOfRightNode.IsSetAndValid());
if (NS_WARN_IF(!HTMLEditUtils::IsSplittableNode(
*aStartOfRightNode.ContainerAsContent()))) {
aError.Throw(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
return nullptr;
if (MOZ_UNLIKELY(NS_WARN_IF(!HTMLEditUtils::IsSplittableNode(
*aStartOfRightNode.ContainerAsContent())))) {
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
}
IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eSplitNode, nsIEditor::eNext, aError);
if (NS_WARN_IF(aError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return nullptr;
*this, EditSubAction::eSplitNode, nsIEditor::eNext, ignoredError);
if (MOZ_UNLIKELY(
NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED)))) {
return Err(NS_ERROR_EDITOR_DESTROYED);
}
NS_WARNING_ASSERTION(
!aError.Failed(),
!ignoredError.Failed(),
"OnStartToHandleTopLevelEditSubAction() failed, but ignored");
aError.SuppressException();
// XXX Unfortunately, storing offset of the split point in
// SplitNodeTransaction is necessary for now. We should fix this
@ -4223,8 +4223,8 @@ already_AddRefed<nsIContent> HTMLEditor::SplitNodeWithTransaction(
RefPtr<SplitNodeTransaction> transaction =
SplitNodeTransaction::Create(*this, aStartOfRightNode);
aError = DoTransactionInternal(transaction);
NS_WARNING_ASSERTION(!aError.Failed(),
nsresult rv = DoTransactionInternal(transaction);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::DoTransactionInternal() failed");
nsCOMPtr<nsIContent> newLeftContent = transaction->GetNewLeftContent();
@ -4244,11 +4244,15 @@ already_AddRefed<nsIContent> HTMLEditor::SplitNodeWithTransaction(
SplitNodeDirection::LeftNodeIsNewOne);
}
if (aError.Failed()) {
return nullptr;
if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) {
return Err(NS_ERROR_EDITOR_DESTROYED);
}
return newLeftContent.forget();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
return Err(rv);
}
return newLeftContent;
}
SplitNodeResult HTMLEditor::SplitNodeDeepWithTransaction(
@ -4300,15 +4304,15 @@ SplitNodeResult HTMLEditor::SplitNodeDeepWithTransaction(
!atStartOfRightNode.GetContainerAsText()) ||
(!atStartOfRightNode.IsStartOfContainer() &&
!atStartOfRightNode.IsEndOfContainer())) {
ErrorResult error;
nsCOMPtr<nsIContent> newLeftNode =
SplitNodeWithTransaction(atStartOfRightNode, error);
if (error.Failed()) {
Result<nsCOMPtr<nsIContent>, nsresult> newLeftContentOrError =
SplitNodeWithTransaction(atStartOfRightNode);
if (MOZ_UNLIKELY(newLeftContentOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return SplitNodeResult(error.StealNSResult());
return SplitNodeResult(newLeftContentOrError.unwrapErr());
}
lastSplitNodeResult = SplitNodeResult(newLeftNode, currentRightNode);
lastSplitNodeResult =
SplitNodeResult(newLeftContentOrError.unwrap(), currentRightNode);
if (currentRightNode == &aMostAncestorToSplit) {
// Actually, we split aMostAncestorToSplit.
return lastSplitNodeResult;
@ -4979,11 +4983,11 @@ nsresult HTMLEditor::DeleteSelectionAndPrepareToCreateNode() {
return error.StealNSResult();
}
ErrorResult error;
nsCOMPtr<nsIContent> newLeftNode = SplitNodeWithTransaction(atAnchor, error);
if (error.Failed()) {
Result<nsCOMPtr<nsIContent>, nsresult> newLeftNodeOrError =
SplitNodeWithTransaction(atAnchor);
if (MOZ_UNLIKELY(newLeftNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return error.StealNSResult();
return newLeftNodeOrError.unwrapErr();
}
EditorRawDOMPoint atRightNode(atAnchor.GetContainer());
@ -4991,6 +4995,7 @@ nsresult HTMLEditor::DeleteSelectionAndPrepareToCreateNode() {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(atRightNode.IsSetAndValid());
ErrorResult error;
SelectionRef().CollapseInLimiter(atRightNode, error);
NS_WARNING_ASSERTION(!error.Failed(),
"Selection::CollapseInLimiter() failed");

Просмотреть файл

@ -2077,11 +2077,9 @@ class HTMLEditor final : public EditorBase,
* the right node, i.e., become the new node's
* next sibling. And the point will be start
* of the right node.
* @param aError If succeed, returns no error. Otherwise, an
* error.
*/
MOZ_CAN_RUN_SCRIPT already_AddRefed<nsIContent> SplitNodeWithTransaction(
const EditorDOMPoint& aStartOfRightNode, ErrorResult& aResult);
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<nsCOMPtr<nsIContent>, nsresult>
SplitNodeWithTransaction(const EditorDOMPoint& aStartOfRightNode);
enum class SplitAtEdges {
// SplitNodeDeepWithTransaction() won't split container element

Просмотреть файл

@ -458,39 +458,31 @@ nsresult HTMLEditor::SetInlinePropertyOnTextNode(
}
// Make the range an independent node.
nsCOMPtr<nsIContent> textNodeForTheRange = &aText;
RefPtr<Text> textNodeForTheRange = &aText;
// Split at the end of the range.
EditorDOMPoint atEnd(textNodeForTheRange, aEndOffset);
if (!atEnd.IsEndOfContainer()) {
// We need to split off back of text node
ErrorResult error;
textNodeForTheRange = SplitNodeWithTransaction(atEnd, error);
if (NS_WARN_IF(Destroyed())) {
error = NS_ERROR_EDITOR_DESTROYED;
}
if (error.Failed()) {
NS_WARNING_ASSERTION(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED),
"HTMLEditor::SplitNodeWithTransaction() failed");
return error.StealNSResult();
Result<nsCOMPtr<nsIContent>, nsresult> newLeftTextNodeOrError =
SplitNodeWithTransaction(atEnd);
if (MOZ_UNLIKELY(newLeftTextNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return newLeftTextNodeOrError.unwrapErr();
}
textNodeForTheRange = Text::FromNodeOrNull(newLeftTextNodeOrError.unwrap());
}
// Split at the start of the range.
EditorDOMPoint atStart(textNodeForTheRange, aStartOffset);
if (!atStart.IsStartOfContainer()) {
// We need to split off front of text node
ErrorResult error;
nsCOMPtr<nsIContent> newLeftNode = SplitNodeWithTransaction(atStart, error);
if (NS_WARN_IF(Destroyed())) {
error = NS_ERROR_EDITOR_DESTROYED;
Result<nsCOMPtr<nsIContent>, nsresult> newLeftTextNodeOrError =
SplitNodeWithTransaction(atStart);
if (MOZ_UNLIKELY(newLeftTextNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return newLeftTextNodeOrError.unwrapErr();
}
if (error.Failed()) {
NS_WARNING_ASSERTION(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED),
"HTMLEditor::SplitNodeWithTransaction() failed");
return error.StealNSResult();
}
Unused << newLeftNode;
}
if (aAttribute) {
@ -2381,18 +2373,19 @@ nsresult HTMLEditor::RelativeFontChangeOnTextNode(FontSize aDir,
aEndOffset = std::min(aTextNode.Length(), aEndOffset);
// Make the range an independent node.
nsCOMPtr<nsIContent> textNodeForTheRange = &aTextNode;
RefPtr<Text> textNodeForTheRange = &aTextNode;
// Split at the end of the range.
EditorDOMPoint atEnd(textNodeForTheRange, aEndOffset);
if (!atEnd.IsEndOfContainer()) {
// We need to split off back of text node
ErrorResult error;
textNodeForTheRange = SplitNodeWithTransaction(atEnd, error);
if (error.Failed()) {
Result<nsCOMPtr<nsIContent>, nsresult> newLeftTextNodeOrError =
SplitNodeWithTransaction(atEnd);
if (MOZ_UNLIKELY(newLeftTextNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return error.StealNSResult();
return newLeftTextNodeOrError.unwrapErr();
}
textNodeForTheRange = Text::FromNodeOrNull(newLeftTextNodeOrError.unwrap());
MOZ_DIAGNOSTIC_ASSERT(textNodeForTheRange);
}
@ -2400,13 +2393,12 @@ nsresult HTMLEditor::RelativeFontChangeOnTextNode(FontSize aDir,
EditorDOMPoint atStart(textNodeForTheRange, aStartOffset);
if (!atStart.IsStartOfContainer()) {
// We need to split off front of text node
ErrorResult error;
nsCOMPtr<nsIContent> newLeftNode = SplitNodeWithTransaction(atStart, error);
if (error.Failed()) {
Result<nsCOMPtr<nsIContent>, nsresult> newLeftTextNodeOrError =
SplitNodeWithTransaction(atStart);
if (MOZ_UNLIKELY(newLeftTextNodeOrError.isErr())) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return error.StealNSResult();
return newLeftTextNodeOrError.unwrapErr();
}
Unused << newLeftNode;
}
// Look for siblings that are correct type of node