Bug 1726064 - part 13: Make AutoEmptyBlockAncestorDeleter::ScanEmptyBlockInclusiveAncestor() use HTMLEditUtils::Get(Inclusive)AncestorElement() r=m_kato

Additionally, the given content may be in a nested editing host.  Then, this
method may delete a nested-block editing host if it's empty.  Therefore,
this patch get rid of `aEditingHost` and check same thing with
`HTMLEditUtils::IsRemovableFromParentNode()`.

Depends on D123066

Differential Revision: https://phabricator.services.mozilla.com/D123067
This commit is contained in:
Masayuki Nakano 2021-08-21 21:28:52 +00:00
parent 125fa92a05
commit 368e3f0587
4 changed files with 59 additions and 23 deletions

View File

@ -966,11 +966,9 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
*
* @param aHTMLEditor The HTMLEditor.
* @param aStartContent Start content to look for empty ancestors.
* @param aEditingHostElement Current editing host.
*/
[[nodiscard]] Element* ScanEmptyBlockInclusiveAncestor(
const HTMLEditor& aHTMLEditor, nsIContent& aStartContent,
Element& aEditingHostElement);
const HTMLEditor& aHTMLEditor, nsIContent& aStartContent);
/**
* ComputeTargetRanges() computes "target ranges" for deleting
@ -1184,7 +1182,7 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDelete(
if (startPoint.GetContainerAsContent()) {
AutoEmptyBlockAncestorDeleter deleter;
if (deleter.ScanEmptyBlockInclusiveAncestor(
aHTMLEditor, *startPoint.GetContainerAsContent(), *editingHost)) {
aHTMLEditor, *startPoint.GetContainerAsContent())) {
nsresult rv = deleter.ComputeTargetRanges(
aHTMLEditor, aDirectionAndAmount, *editingHost, aRangesToDelete);
NS_WARNING_ASSERTION(
@ -1432,7 +1430,7 @@ EditActionResult HTMLEditor::AutoDeleteRangesHandler::Run(
#endif // #ifdef DEBUG
AutoEmptyBlockAncestorDeleter deleter;
if (deleter.ScanEmptyBlockInclusiveAncestor(
aHTMLEditor, *startPoint.GetContainerAsContent(), *editingHost)) {
aHTMLEditor, *startPoint.GetContainerAsContent())) {
EditActionResult result = deleter.Run(aHTMLEditor, aDirectionAndAmount);
if (result.Failed() || result.Handled()) {
NS_WARNING_ASSERTION(result.Succeeded(),
@ -5029,28 +5027,29 @@ nsresult HTMLEditor::DeleteMostAncestorMailCiteElementIfEmpty(
Element* HTMLEditor::AutoDeleteRangesHandler::AutoEmptyBlockAncestorDeleter::
ScanEmptyBlockInclusiveAncestor(const HTMLEditor& aHTMLEditor,
nsIContent& aStartContent,
Element& aEditingHostElement) {
nsIContent& aStartContent) {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
// If the editing host is an inline element, bail out early.
if (HTMLEditUtils::IsInlineElement(aEditingHostElement)) {
// If we are inside an empty block, delete it.
// Note: do NOT delete table elements this way.
// Note: do NOT delete non-editable block element.
Element* editableBlockElement = HTMLEditUtils::GetInclusiveAncestorElement(
aStartContent, HTMLEditUtils::ClosestEditableBlockElement);
if (!editableBlockElement) {
return nullptr;
}
// If we are inside an empty block, delete it. Note: do NOT delete table
// elements this way.
Element* blockElement =
HTMLEditUtils::GetInclusiveAncestorBlockElement(aStartContent);
if (!blockElement) {
return nullptr;
}
while (blockElement && blockElement != &aEditingHostElement &&
!HTMLEditUtils::IsAnyTableElement(blockElement) &&
HTMLEditUtils::IsEmptyNode(*blockElement)) {
mEmptyInclusiveAncestorBlockElement = blockElement;
blockElement = HTMLEditUtils::GetAncestorBlockElement(
*mEmptyInclusiveAncestorBlockElement);
// XXX Perhaps, this is slow loop. If empty blocks are nested, then,
// each block checks whether it's empty or not. However, descendant
// blocks are checked again and again by IsEmptyNode(). Perhaps, it
// should be able to take "known empty element" for avoiding same checks.
while (editableBlockElement &&
HTMLEditUtils::IsRemovableFromParentNode(*editableBlockElement) &&
!HTMLEditUtils::IsAnyTableElement(editableBlockElement) &&
HTMLEditUtils::IsEmptyNode(*editableBlockElement)) {
mEmptyInclusiveAncestorBlockElement = editableBlockElement;
editableBlockElement = HTMLEditUtils::GetAncestorElement(
*mEmptyInclusiveAncestorBlockElement,
HTMLEditUtils::ClosestEditableBlockElement);
}
if (!mEmptyInclusiveAncestorBlockElement) {
return nullptr;

View File

@ -622,3 +622,6 @@
[[["forwarddelete",""\]\] "<p><span>[abc\]</span></p>" compare innerHTML]
expected: FAIL
[[["forwarddelete",""\]\] "<div><div contenteditable=false><span contenteditable>{}<br></span></div></div>": execCommand("forwarddelete", false, "") return value]
expected: FAIL

View File

@ -2616,4 +2616,21 @@ var browserTests = [
"<p contenteditable=\"false\"><span contenteditable=\"true\"></span></p>",
[true],
{"delete":[false,false,"",false,false,""]}],
["<div><div>{}<br></div></div>",
[["delete",""]],
["", "<br>"],
[true],
{"delete":[false,false,"",false,false,""]}],
["<div><div contenteditable=false><div contenteditable><div>{}<br></div></div></div></div>",
[["delete",""]],
["<div><div contenteditable=\"false\"><div contenteditable=\"\"></div></div></div>",
"<div><div contenteditable=\"false\"><div contenteditable=\"\"><br></div></div></div>"],
[true],
{"delete":[false,false,"",false,false,""]}],
["<div><div contenteditable=false><span contenteditable>{}<br></span></div></div></div>",
[["delete",""]],
["<div><div contenteditable=\"false\"><span contenteditable=\"\"></span></div></div>",
"<div><div contenteditable=\"false\"><span contenteditable=\"\"><br></span></div></div>"],
[true],
{"delete":[false,false,"",false,false,""]}],
]

View File

@ -2501,4 +2501,21 @@ var browserTests = [
"<p contenteditable=\"false\"><span contenteditable=\"true\"></span></p>",
[true],
{"forwarddelete":[false,false,"",false,false,""]}],
["<div><div>{}<br></div></div>",
[["forwarddelete",""]],
["", "<br>"],
[true],
{"forwarddelete":[false,false,"",false,false,""]}],
["<div><div contenteditable=false><div contenteditable><div>{}<br></div></div></div></div>",
[["forwarddelete",""]],
["<div><div contenteditable=\"false\"><div contenteditable=\"\"></div></div></div>",
"<div><div contenteditable=\"false\"><div contenteditable=\"\"><br></div></div></div>"],
[true],
{"forwarddelete":[false,false,"",false,false,""]}],
["<div><div contenteditable=false><span contenteditable>{}<br></span></div></div>",
[["forwarddelete",""]],
["<div><div contenteditable=\"false\"><span contenteditable=\"\"></span></div></div>",
"<div><div contenteditable=\"false\"><span contenteditable=\"\"><br></span></div></div>"],
[true],
{"forwarddelete":[false,false,"",false,false,""]}],
]