Bug 1761395 - part 1-4: Make `HTMLEditor::CopyLastEditableChildStylesWithTransaction()` return `Result` r=m_kato

This is not directly related to this bug, but it's a helper class of
`HandleInsertParagraphInListItemElement()`.

Differential Revision: https://phabricator.services.mozilla.com/D142411
This commit is contained in:
Masayuki Nakano 2022-04-05 05:25:50 +00:00
Родитель 3da5ef2528
Коммит d7bb598bdb
3 изменённых файлов: 63 добавлений и 60 удалений

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

@ -7526,8 +7526,7 @@ HTMLEditor::HandleInsertParagraphInListItemElement(
EditorDOMPoint::After(rightListItemElement));
if (MOZ_UNLIKELY(maybeNewListItemElement.isErr())) {
NS_WARNING(
"HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) "
"failed");
"HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) failed");
return Err(maybeNewListItemElement.unwrapErr());
}
MOZ_ASSERT(maybeNewListItemElement.inspect());
@ -7549,23 +7548,20 @@ HTMLEditor::HandleInsertParagraphInListItemElement(
// direct child of the editing host, copy all inline elements affecting to
// the style at end of the left list item element to the right list item
// element.
RefPtr<Element> brElement;
// MOZ_KnownLive(*ListItemElement) because they are grabbed by
// splitListItemResult.
nsresult rv = CopyLastEditableChildStylesWithTransaction(
MOZ_KnownLive(leftListItemElement), MOZ_KnownLive(rightListItemElement),
address_of(brElement));
if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) {
return Err(NS_ERROR_EDITOR_DESTROYED);
}
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
Result<RefPtr<HTMLBRElement>, nsresult> newBRElementOrError =
CopyLastEditableChildStylesWithTransaction(
MOZ_KnownLive(leftListItemElement),
MOZ_KnownLive(rightListItemElement), aEditingHost);
if (MOZ_UNLIKELY(newBRElementOrError.isErr())) {
NS_WARNING(
"HTMLEditor::CopyLastEditableChildStylesWithTransaction() "
"failed");
return Err(NS_ERROR_FAILURE);
"HTMLEditor::CopyLastEditableChildStylesWithTransaction() failed");
return Err(newBRElementOrError.unwrapErr());
}
return brElement ? EditorDOMPoint(brElement)
: EditorDOMPoint(&rightListItemElement, 0u);
return newBRElementOrError.inspect()
? EditorDOMPoint(newBRElementOrError.unwrap().get())
: EditorDOMPoint(&rightListItemElement, 0u);
}
// If the right list item element is not empty, we need to consider where to

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

@ -45,6 +45,7 @@
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/HTMLAnchorElement.h"
#include "mozilla/dom/HTMLBodyElement.h"
#include "mozilla/dom/HTMLBRElement.h"
#include "mozilla/dom/Selection.h"
#include "nsContentList.h"
@ -5706,33 +5707,29 @@ nsresult HTMLEditor::SetBackgroundColorAsAction(const nsAString& aColor,
return EditorBase::ToGenericNSResult(rv);
}
nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction(
Element& aPreviousBlock, Element& aNewBlock,
RefPtr<Element>* aNewBRElement) {
Result<RefPtr<HTMLBRElement>, nsresult>
HTMLEditor::CopyLastEditableChildStylesWithTransaction(Element& aPreviousBlock,
Element& aNewBlock,
Element& aEditingHost) {
MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!aNewBRElement)) {
return NS_ERROR_INVALID_ARG;
}
*aNewBRElement = nullptr;
RefPtr<Element> previousBlock(&aPreviousBlock);
RefPtr<Element> newBlock(&aNewBlock);
// First, clear out aNewBlock. Contract is that we want only the styles
// from aPreviousBlock.
for (nsCOMPtr<nsIContent> child = newBlock->GetFirstChild(); child;
child = newBlock->GetFirstChild()) {
nsresult rv = DeleteNodeWithTransaction(*child);
if (NS_FAILED(rv)) {
AutoTArray<OwningNonNull<nsIContent>, 32> newBlockChildren;
HTMLEditor::GetChildNodesOf(aNewBlock, newBlockChildren);
for (const OwningNonNull<nsIContent>& child : newBlockChildren) {
// MOZ_KNownLive(child) because of bug 1622253
nsresult rv = DeleteNodeWithTransaction(MOZ_KnownLive(child));
if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) {
return Err(NS_ERROR_EDITOR_DESTROYED);
}
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
return rv;
return Err(rv);
}
}
RefPtr<Element> editingHost = GetActiveEditingHost();
if (!editingHost) {
return NS_OK;
if (MOZ_UNLIKELY(aNewBlock.GetFirstChild())) {
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
}
// XXX aNewBlock may be moved or removed. Even in such case, we should
@ -5741,7 +5738,7 @@ nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction(
// Look for the deepest last editable leaf node in aPreviousBlock.
// Then, if found one is a <br> element, look for non-<br> element.
nsIContent* deepestEditableContent = nullptr;
for (nsCOMPtr<nsIContent> child = previousBlock.get(); child;
for (nsCOMPtr<nsIContent> child = &aPreviousBlock; child;
child = HTMLEditUtils::GetLastChild(
*child, {WalkTreeOption::IgnoreNonEditableNode})) {
deepestEditableContent = child;
@ -5750,16 +5747,16 @@ nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction(
deepestEditableContent->IsHTMLElement(nsGkAtoms::br)) {
deepestEditableContent = HTMLEditUtils::GetPreviousContent(
*deepestEditableContent, {WalkTreeOption::IgnoreNonEditableNode},
editingHost);
&aEditingHost);
}
if (!deepestEditableContent) {
return NS_OK;
return RefPtr<HTMLBRElement>();
}
Element* deepestVisibleEditableElement =
deepestEditableContent->GetAsElementOrParentElement();
if (!deepestVisibleEditableElement) {
return NS_OK;
return RefPtr<HTMLBRElement>();
}
// Clone inline elements to keep current style in the new block.
@ -5769,20 +5766,20 @@ nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction(
// after that with transaction.
RefPtr<Element> lastClonedElement, firstClonedElement;
for (RefPtr<Element> elementInPreviousBlock = deepestVisibleEditableElement;
elementInPreviousBlock && elementInPreviousBlock != previousBlock;
elementInPreviousBlock && elementInPreviousBlock != &aPreviousBlock;
elementInPreviousBlock = elementInPreviousBlock->GetParentElement()) {
if (!HTMLEditUtils::IsInlineStyle(elementInPreviousBlock) &&
!elementInPreviousBlock->IsHTMLElement(nsGkAtoms::span)) {
continue;
}
nsAtom* tagName = elementInPreviousBlock->NodeInfo()->NameAtom();
OwningNonNull<nsAtom> tagName =
*elementInPreviousBlock->NodeInfo()->NameAtom();
// At first time, just create the most descendant inline container
// element.
if (!firstClonedElement) {
Result<RefPtr<Element>, nsresult> maybeNewElement =
CreateAndInsertElement(
WithTransaction::Yes, MOZ_KnownLive(*tagName),
EditorDOMPoint(newBlock, 0u),
WithTransaction::Yes, tagName, EditorDOMPoint(&aNewBlock, 0u),
// MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868
[&elementInPreviousBlock](
HTMLEditor& aHTMLEditor, Element& aNewElement,
@ -5796,41 +5793,47 @@ nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction(
aNewElement, *elementInPreviousBlock);
return NS_OK;
});
if (maybeNewElement.isErr()) {
if (MOZ_UNLIKELY(maybeNewElement.isErr())) {
NS_WARNING(
"HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) failed");
return maybeNewElement.unwrapErr();
return Err(maybeNewElement.unwrapErr());
}
firstClonedElement = lastClonedElement = maybeNewElement.unwrap();
continue;
}
// Otherwise, inserts new parent inline container to the previous inserted
// inline container.
lastClonedElement = InsertContainerWithTransaction(*lastClonedElement,
MOZ_KnownLive(*tagName));
if (!lastClonedElement) {
lastClonedElement =
InsertContainerWithTransaction(*lastClonedElement, tagName);
if (MOZ_UNLIKELY(!lastClonedElement)) {
NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed");
return NS_ERROR_FAILURE;
return Err(NS_ERROR_FAILURE);
}
CloneAttributesWithTransaction(*lastClonedElement, *elementInPreviousBlock);
if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) {
return Err(NS_ERROR_EDITOR_DESTROYED);
}
}
if (!firstClonedElement) {
// XXX Even if no inline elements are cloned, shouldn't we create new
// <br> element for aNewBlock?
return NS_OK;
return RefPtr<HTMLBRElement>();
}
Result<RefPtr<Element>, nsresult> resultOfInsertingBRElement =
InsertBRElement(WithTransaction::Yes,
EditorDOMPoint(firstClonedElement, 0u));
if (resultOfInsertingBRElement.isErr()) {
if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) {
return Err(NS_ERROR_EDITOR_DESTROYED);
}
if (MOZ_UNLIKELY(resultOfInsertingBRElement.isErr())) {
NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return resultOfInsertingBRElement.unwrapErr();
return Err(resultOfInsertingBRElement.unwrapErr());
}
MOZ_ASSERT(resultOfInsertingBRElement.inspect());
*aNewBRElement = resultOfInsertingBRElement.unwrap().forget();
return NS_OK;
return RefPtr<HTMLBRElement>(
HTMLBRElement::FromNode(resultOfInsertingBRElement.unwrap().get()));
}
nsresult HTMLEditor::GetElementOrigin(Element& aElement, int32_t& aX,

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

@ -73,6 +73,7 @@ class AbstractRange;
class Blob;
class DocumentFragment;
class Event;
class HTMLBRElement;
class MouseEvent;
class StaticRange;
} // namespace dom
@ -807,14 +808,17 @@ class HTMLEditor final : public EditorBase,
* @param aPreviousBlock The previous block element. All inline
* elements which are last sibling of each level
* are cloned to aNewBlock.
* @param aNewBlock New block container element.
* @param aNewBRElement If this method creates a new <br> element for
* placeholder, this is set to the new <br>
* @param aNewBlock New block container element. All children of
* this is deleted first.
* @param aEditingHost Current editing host.
* @return If this method creates a new <br> element for
* placeholder, this returns the new <br>
* element.
*/
MOZ_CAN_RUN_SCRIPT nsresult CopyLastEditableChildStylesWithTransaction(
Element& aPreviousBlock, Element& aNewBlock,
RefPtr<Element>* aNewBRElement);
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<RefPtr<dom::HTMLBRElement>, nsresult>
CopyLastEditableChildStylesWithTransaction(Element& aPreviousBlock,
Element& aNewBlock,
Element& aEditingHost);
/**
* RemoveBlockContainerWithTransaction() removes aElement from the DOM tree