Bug 1657270 - part 1: Move `HTMLEditor::MaybeDeleteTopMostEmptyAncestor()` into new stack only class r=m_kato

Differential Revision: https://phabricator.services.mozilla.com/D85995
This commit is contained in:
Masayuki Nakano 2020-08-11 02:02:19 +00:00
Родитель 555c643104
Коммит 42c32fd19a
2 изменённых файлов: 60 добавлений и 53 удалений

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

@ -2462,13 +2462,13 @@ EditActionResult HTMLEditor::HandleDeleteSelectionInternal(
if (startPoint.GetContainerAsContent()) {
AutoEditorDOMPointChildInvalidator lockOffset(startPoint);
EditActionResult result = MaybeDeleteTopMostEmptyAncestor(
MOZ_KnownLive(*startPoint.GetContainerAsContent()), *editingHost,
aDirectionAndAmount);
AutoEmptyBlockAncestorDeleter deleter;
EditActionResult result =
deleter.Run(*this, MOZ_KnownLive(*startPoint.GetContainerAsContent()),
*editingHost, aDirectionAndAmount);
if (result.Failed() || result.Handled()) {
NS_WARNING_ASSERTION(
result.Succeeded(),
"HTMLEditor::MaybeDeleteTopMostEmptyAncestor() failed");
NS_WARNING_ASSERTION(result.Succeeded(),
"AutoEmptyBlockAncestorDeleter::Run() failed");
return result;
}
}
@ -7859,10 +7859,10 @@ nsresult HTMLEditor::AlignBlockContentsWithDivElement(
return NS_OK;
}
EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
nsIContent& aStartContent, Element& aEditingHostElement,
nsIEditor::EDirection aDirectionAndAmount) {
MOZ_ASSERT(IsEditActionDataAvailable());
EditActionResult HTMLEditor::AutoEmptyBlockAncestorDeleter::Run(
HTMLEditor& aHTMLEditor, nsIContent& aStartContent,
Element& aEditingHostElement, nsIEditor::EDirection aDirectionAndAmount) {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
// If the editing host is an inline element, bail out early.
if (HTMLEditUtils::IsInlineElement(aEditingHostElement)) {
@ -7876,7 +7876,7 @@ EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
RefPtr<Element> topMostEmptyBlockElement;
while (blockElement && blockElement != &aEditingHostElement &&
!HTMLEditUtils::IsAnyTableElement(blockElement) &&
IsEmptyNode(*blockElement, true, false)) {
aHTMLEditor.IsEmptyNode(*blockElement, true, false)) {
topMostEmptyBlockElement = blockElement;
blockElement =
HTMLEditUtils::GetAncestorBlockElement(*topMostEmptyBlockElement);
@ -7906,7 +7906,7 @@ EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
// last list item is deleted. We should follow it since current
// behavior is annoying when you type new list item with selecting
// all list items.
if (IsFirstEditableChild(topMostEmptyBlockElement)) {
if (aHTMLEditor.IsFirstEditableChild(topMostEmptyBlockElement)) {
EditorDOMPoint atParentOfEmptyBlock(parentOfEmptyBlockElement);
if (NS_WARN_IF(!atParentOfEmptyBlock.IsSet())) {
return EditActionResult(NS_ERROR_FAILURE);
@ -7916,15 +7916,16 @@ EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
if (!HTMLEditUtils::IsAnyListElement(
atParentOfEmptyBlock.GetContainer())) {
RefPtr<Element> brElement =
InsertBRElementWithTransaction(atParentOfEmptyBlock);
if (NS_WARN_IF(Destroyed())) {
aHTMLEditor.InsertBRElementWithTransaction(atParentOfEmptyBlock);
if (NS_WARN_IF(aHTMLEditor.Destroyed())) {
return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
}
if (!brElement) {
NS_WARNING("HTMLEditor::InsertBRElementWithTransaction() failed");
return EditActionResult(NS_ERROR_FAILURE);
}
nsresult rv = CollapseSelectionTo(EditorRawDOMPoint(brElement));
nsresult rv =
aHTMLEditor.CollapseSelectionTo(EditorRawDOMPoint(brElement));
if (NS_FAILED(rv)) {
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"HTMLEditor::CollapseSelectionTo() failed");
@ -7945,14 +7946,14 @@ EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
advancedFromEmptyBlock,
"Failed to set selection to the after the empty block");
nsCOMPtr<nsIContent> nextContentOfEmptyBlock =
GetNextNode(afterEmptyBlock);
aHTMLEditor.GetNextNode(afterEmptyBlock);
if (nextContentOfEmptyBlock) {
EditorDOMPoint pt = GetGoodCaretPointFor(*nextContentOfEmptyBlock,
aDirectionAndAmount);
EditorDOMPoint pt = aHTMLEditor.GetGoodCaretPointFor(
*nextContentOfEmptyBlock, aDirectionAndAmount);
NS_WARNING_ASSERTION(
pt.IsSet(),
"HTMLEditor::GetGoodCaretPointFor() failed, but ignored");
nsresult rv = CollapseSelectionTo(pt);
nsresult rv = aHTMLEditor.CollapseSelectionTo(pt);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::CollapseSelectionTo() failed");
return EditActionResult(rv);
@ -7962,7 +7963,7 @@ EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
if (NS_WARN_IF(!advancedFromEmptyBlock)) {
return EditActionResult(NS_ERROR_FAILURE);
}
nsresult rv = CollapseSelectionTo(afterEmptyBlock);
nsresult rv = aHTMLEditor.CollapseSelectionTo(afterEmptyBlock);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::CollapseSelectionTo() failed");
return EditActionResult(rv);
@ -7976,14 +7977,14 @@ EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
// if there is. Otherwise, to after the empty block.
EditorRawDOMPoint atEmptyBlock(topMostEmptyBlockElement);
nsCOMPtr<nsIContent> previousContentOfEmptyBlock =
GetPreviousEditableNode(atEmptyBlock);
aHTMLEditor.GetPreviousEditableNode(atEmptyBlock);
if (previousContentOfEmptyBlock) {
EditorDOMPoint pt = GetGoodCaretPointFor(*previousContentOfEmptyBlock,
aDirectionAndAmount);
EditorDOMPoint pt = aHTMLEditor.GetGoodCaretPointFor(
*previousContentOfEmptyBlock, aDirectionAndAmount);
NS_WARNING_ASSERTION(
pt.IsSet(),
"HTMLEditor::GetGoodCaretPointFor() failed, but ignored");
nsresult rv = CollapseSelectionTo(pt);
nsresult rv = aHTMLEditor.CollapseSelectionTo(pt);
if (NS_FAILED(rv)) {
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"HTMLEditor::CollapseSelectionTo() failed");
@ -7996,7 +7997,7 @@ EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
if (NS_WARN_IF(!afterEmptyBlock.IsSet())) {
return EditActionResult(NS_ERROR_FAILURE);
}
nsresult rv = CollapseSelectionTo(afterEmptyBlock);
nsresult rv = aHTMLEditor.CollapseSelectionTo(afterEmptyBlock);
if (NS_FAILED(rv)) {
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"HTMLEditor::CollapseSelectionTo() failed");
@ -8010,8 +8011,9 @@ EditActionResult HTMLEditor::MaybeDeleteTopMostEmptyAncestor(
MOZ_CRASH("CheckForEmptyBlock doesn't support this action yet");
}
}
nsresult rv = DeleteNodeWithTransaction(*topMostEmptyBlockElement);
if (NS_WARN_IF(Destroyed())) {
nsresult rv =
aHTMLEditor.DeleteNodeWithTransaction(*topMostEmptyBlockElement);
if (NS_WARN_IF(aHTMLEditor.Destroyed())) {
return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
}
if (NS_FAILED(rv)) {

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

@ -2423,32 +2423,6 @@ class HTMLEditor final : public TextEditor,
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
RemoveEmptyInclusiveAncestorInlineElements(nsIContent& aContent);
/**
* MaybeDeleteTopMostEmptyAncestor() looks for top most empty block ancestor
* of aStartContent in aEditingHostElement.
* If found empty ancestor is a list item element, inserts a <br> element
* before its parent element if grand parent is a list element. Then,
* collapse Selection to after the empty block.
* If found empty ancestor is not a list item element, collapse Selection to
* somewhere depending on aAction.
* Finally, removes the empty block ancestor.
*
* @param aStartContent Start content to look for empty ancestors.
* @param aEditingHostElement Current editing host.
* @param aDirectionAndAmount If found empty ancestor block is a list item
* element, this is ignored. Otherwise:
* - If eNext, eNextWord or eToEndOfLine, collapse
* Selection to after found empty ancestor.
* - If ePrevious, ePreviousWord or
* eToBeginningOfLine, collapse Selection to
* end of previous editable node.
* Otherwise, eNone is allowed but does nothing.
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT EditActionResult
MaybeDeleteTopMostEmptyAncestor(nsIContent& aStartContent,
Element& aEditingHostElement,
nsIEditor::EDirection aDirectionAndAmount);
/**
* ExtendRangeToIncludeInvisibleNodes() extends aRange if there are some
* invisible nodes around it.
@ -2684,6 +2658,37 @@ class HTMLEditor final : public TextEditor,
nsIEditor::EStripWrappers aStripWrappers, nsIContent& aAtomicContent,
const EditorDOMPoint& aCaretPoint, WSRunScanner& aWSRunScannerAtCaret);
class MOZ_STACK_CLASS AutoEmptyBlockAncestorDeleter final {
public:
/**
* Look for topmost empty block ancestor of aStartContent in
* aEditingHostElement. If found empty ancestor is a list item element,
* inserts a <br> element before its parent element if grand parent is a
* list element. Then, collapse Selection to after the empty block. If
* found empty ancestor is not a list item element, collapse Selection to
* somewhere depending on aAction.
* Finally, removes the empty block ancestor.
*
* @param aHTMLEditor The HTMLEditor.
* @param aStartContent Start content to look for empty ancestors.
* @param aEditingHostElement Current editing host.
* @param aDirectionAndAmount If found empty ancestor block is a list item
* element, this is ignored. Otherwise:
* - If eNext, eNextWord or eToEndOfLine,
* collapse Selection to after found empty
* ancestor.
* - If ePrevious, ePreviousWord or
* eToBeginningOfLine, collapse Selection to
* end of previous editable node.
* - Otherwise, eNone is allowed but does
* nothing.
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT EditActionResult
Run(HTMLEditor& aHTMLEditor, nsIContent& aStartContent,
Element& aEditingHostElement,
nsIEditor::EDirection aDirectionAndAmount);
};
class MOZ_STACK_CLASS AutoBlockElementsJoiner final {
public:
/**