Bug 1762115 - part 13: Make EditorBase::InsertNodeWithTransaction stop touching Selection directly r=m_kato

Differential Revision: https://phabricator.services.mozilla.com/D144656
This commit is contained in:
Masayuki Nakano
2022-05-03 01:21:51 +00:00
parent a5cabe7ad7
commit ed197035df
8 changed files with 295 additions and 119 deletions

View File

@@ -13,6 +13,7 @@
#include "mozilla/EditorDOMPoint.h"
#include "mozilla/EditorUtils.h"
#include "mozilla/FlushType.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/Element.h"
@@ -135,12 +136,21 @@ nsresult HTMLEditor::InsertCell(Element* aCell, int32_t aRowSpan,
"Failed to advance offset to after the old cell");
}
// Don't let Rules System change the selection.
// TODO: Remove AutoTransactionsConserveSelection here. It's not necessary
// in normal cases. However, it may be required for nested edit
// actions which may be caused by legacy mutation event listeners or
// chrome script.
AutoTransactionsConserveSelection dontChangeSelection(*this);
nsresult rv = InsertNodeWithTransaction(*newCell, pointToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::InsertNodeWithTransaction() failed");
return rv;
CreateElementResult insertNewCellResult =
InsertNodeWithTransaction<Element>(*newCell, pointToInsert);
if (insertNewCellResult.isErr()) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return insertNewCellResult.unwrapErr();
}
// Because of dontChangeSelection, we've never allowed to transactions to
// update selection here.
insertNewCellResult.IgnoreCaretPointSuggestion();
return NS_OK;
}
nsresult HTMLEditor::SetColSpan(Element* aCell, int32_t aColSpan) {
@@ -254,7 +264,10 @@ nsresult HTMLEditor::InsertTableCellsWithTransaction(
AutoSelectionSetterAfterTableEdit setCaret(
*this, table, cellDataAtSelection.mCurrent.mRow, newCellIndex,
ePreviousColumn, false);
// So, suppress Rules System selection munging.
// TODO: Remove AutoTransactionsConserveSelection here. It's not necessary
// in normal cases. However, it may be required for nested edit
// actions which may be caused by legacy mutation event listeners or
// chrome script.
AutoTransactionsConserveSelection dontChangeSelection(*this);
EditorDOMPoint pointToInsert(cellParent, cellOffset);
@@ -266,18 +279,23 @@ nsresult HTMLEditor::InsertTableCellsWithTransaction(
NS_WARNING_ASSERTION(advanced,
"Failed to move insertion point after the cell");
}
for (int32_t i = 0; i < aNumberOfCellsToInsert; i++) {
for ([[maybe_unused]] const auto i :
IntegerRange<uint32_t>(aNumberOfCellsToInsert)) {
RefPtr<Element> newCell = CreateElementWithDefaults(*nsGkAtoms::td);
if (!newCell) {
if (MOZ_UNLIKELY(!newCell)) {
NS_WARNING("HTMLEditor::CreateElementWithDefaults(nsGkAtoms::td) failed");
return NS_ERROR_FAILURE;
}
AutoEditorDOMPointChildInvalidator lockOffset(pointToInsert);
nsresult rv = InsertNodeWithTransaction(*newCell, pointToInsert);
if (NS_FAILED(rv)) {
CreateElementResult insertNewCellResult =
InsertNodeWithTransaction<Element>(*newCell, pointToInsert);
if (insertNewCellResult.isErr()) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return rv;
return insertNewCellResult.unwrapErr();
}
// Because of dontChangeSelection, we've never allowed to transactions to
// update selection here.
insertNewCellResult.IgnoreCaretPointSuggestion();
}
return NS_OK;
}
@@ -762,7 +780,10 @@ nsresult HTMLEditor::InsertTableRowsWithTransaction(
AutoSelectionSetterAfterTableEdit setCaret(
*this, table, startRowIndex, cellDataAtSelection.mCurrent.mColumn,
ePreviousColumn, false);
// Suppress Rules System selection munging.
// TODO: Remove AutoTransactionsConserveSelection here. It's not necessary
// in normal cases. However, it may be required for nested edit
// actions which may be caused by legacy mutation event listeners or
// chrome script.
AutoTransactionsConserveSelection dontChangeSelection(*this);
RefPtr<Element> cellForRowParent;
@@ -890,11 +911,15 @@ nsresult HTMLEditor::InsertTableRowsWithTransaction(
}
AutoEditorDOMPointChildInvalidator lockOffset(pointToInsert);
nsresult rv = InsertNodeWithTransaction(*newRow, pointToInsert);
if (NS_FAILED(rv)) {
CreateElementResult insertNewRowResult =
InsertNodeWithTransaction<Element>(*newRow, pointToInsert);
if (insertNewRowResult.isErr()) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return rv;
return insertNewRowResult.unwrapErr();
}
// Because of dontChangeSelection, we've never allowed to transactions to
// update selection here.
insertNewRowResult.IgnoreCaretPointSuggestion();
}
// SetSelectionAfterTableEdit from AutoSelectionSetterAfterTableEdit will
@@ -3110,6 +3135,7 @@ nsresult HTMLEditor::MergeCells(RefPtr<Element> aTargetCell,
}
// Move the contents
EditorDOMPoint pointToPutCaret;
while (aCellToMerge->HasChildren()) {
nsCOMPtr<nsIContent> cellChild = aCellToMerge->GetLastChild();
if (NS_WARN_IF(!cellChild)) {
@@ -3120,12 +3146,27 @@ nsresult HTMLEditor::MergeCells(RefPtr<Element> aTargetCell,
NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
return rv;
}
rv = InsertNodeWithTransaction(*cellChild,
EditorDOMPoint(aTargetCell, insertIndex));
if (NS_FAILED(rv)) {
CreateContentResult insertChildContentResult = InsertNodeWithTransaction(
*cellChild, EditorDOMPoint(aTargetCell, insertIndex));
if (insertChildContentResult.isErr()) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return rv;
return insertChildContentResult.unwrapErr();
}
insertChildContentResult.MoveCaretPointTo(
pointToPutCaret, *this,
{SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
}
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");
}
}