Bug 1718815 - part 2: Move EditorBase::AutoSelectionRestorer and EditorBase methods called only by it to HTMLEditor r=m_kato

Unfortunately, marking its constructor and destructor as `MOZ_CAN_RUN_SCRIPT`,
`Maybe<AutoSelectionRestorer>::reset()` and
`Maybe<AutoSelectionRestorer>::emplace()` cause bustage.  Therefore, this patch
just mark them as `MOZ_CAN_RUN_SCRIPT_BOUNDARY`.

Note that `EditorBase::SavedSelectionRef()` cannot be moved to `HTMLEditor`
because `mEditActionData` is a private member of `EditorBase`.

Depends on D119001

Differential Revision: https://phabricator.services.mozilla.com/D119002
This commit is contained in:
Masayuki Nakano 2021-07-02 08:23:45 +00:00
parent 7ac37b46ec
commit a68528b057
5 changed files with 120 additions and 104 deletions

View File

@ -2445,39 +2445,6 @@ NS_IMETHODIMP EditorBase::RemoveDocumentStateListener(
return NS_OK;
}
bool EditorBase::ArePreservingSelection() {
return IsEditActionDataAvailable() && !SavedSelectionRef().IsEmpty();
}
void EditorBase::PreserveSelectionAcrossActions() {
MOZ_ASSERT(IsEditActionDataAvailable());
SavedSelectionRef().SaveSelection(SelectionRef());
RangeUpdaterRef().RegisterSelectionState(SavedSelectionRef());
}
nsresult EditorBase::RestorePreservedSelection() {
MOZ_ASSERT(IsEditActionDataAvailable());
if (SavedSelectionRef().IsEmpty()) {
return NS_ERROR_FAILURE;
}
DebugOnly<nsresult> rvIgnored =
SavedSelectionRef().RestoreSelection(SelectionRef());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"SelectionState::RestoreSelection() failed, but ignored");
StopPreservingSelection();
return NS_OK;
}
void EditorBase::StopPreservingSelection() {
MOZ_ASSERT(IsEditActionDataAvailable());
RangeUpdaterRef().DropSelectionState(SavedSelectionRef());
SavedSelectionRef().Clear();
}
NS_IMETHODIMP EditorBase::ForceCompositionEnd() {
nsresult rv = CommitComposition();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
@ -6114,38 +6081,6 @@ nsresult EditorBase::InsertLineBreakAsSubAction() {
return result.Rv();
}
/******************************************************************************
* EditorBase::AutoSelectionRestorer
*****************************************************************************/
EditorBase::AutoSelectionRestorer::AutoSelectionRestorer(
EditorBase& aEditorBase)
: mEditorBase(nullptr) {
if (aEditorBase.ArePreservingSelection()) {
// We already have initialized mParentData::mSavedSelection, so this must
// be nested call.
return;
}
MOZ_ASSERT(aEditorBase.IsEditActionDataAvailable());
mEditorBase = &aEditorBase;
mEditorBase->PreserveSelectionAcrossActions();
}
EditorBase::AutoSelectionRestorer::~AutoSelectionRestorer() {
if (mEditorBase && mEditorBase->ArePreservingSelection()) {
DebugOnly<nsresult> rvIgnored = mEditorBase->RestorePreservedSelection();
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"EditorBase::RestorePreservedSelection() failed, but ignored");
}
}
void EditorBase::AutoSelectionRestorer::Abort() {
if (mEditorBase) {
mEditorBase->StopPreservingSelection();
}
}
/*****************************************************************************
* mozilla::EditorBase::AutoEditActionDataSetter
*****************************************************************************/

View File

@ -59,7 +59,6 @@ class nsRange;
namespace mozilla {
class AlignStateAtSelection;
class AutoRangeArray;
class AutoSelectionRestorer;
class AutoTopLevelEditSubActionNotifier;
class AutoTransactionBatch;
class AutoTransactionsConserveSelection;
@ -1386,7 +1385,7 @@ class EditorBase : public nsIEditor,
// the DOM tree. In such case, we need to handle edit action separately.
AutoEditActionDataSetter* mParentData;
// Cached selection for AutoSelectionRestorer.
// Cached selection for HTMLEditor::AutoSelectionRestorer.
SelectionState mSavedSelection;
// Utility class object for maintaining preserved ranges.
@ -1583,13 +1582,15 @@ class EditorBase : public nsIEditor,
/**
* SavedSelection() returns reference to saved selection which are
* stored by AutoSelectionRestorer.
* stored by HTMLEditor::AutoSelectionRestorer.
*/
SelectionState& SavedSelectionRef() {
MOZ_ASSERT(IsHTMLEditor());
MOZ_ASSERT(IsEditActionDataAvailable());
return mEditActionData->SavedSelectionRef();
}
const SelectionState& SavedSelectionRef() const {
MOZ_ASSERT(IsHTMLEditor());
MOZ_ASSERT(IsEditActionDataAvailable());
return mEditActionData->SavedSelectionRef();
}
@ -2127,15 +2128,6 @@ class EditorBase : public nsIEditor,
void OnStartToHandleEditSubAction() { EditSubActionDataRef().Clear(); }
void OnEndHandlingEditSubAction() { EditSubActionDataRef().Clear(); }
/**
* Routines for managing the preservation of selection across
* various editor actions.
*/
bool ArePreservingSelection();
void PreserveSelectionAcrossActions();
nsresult RestorePreservedSelection();
void StopPreservingSelection();
/**
* (Begin|End)PlaceholderTransaction() are called by AutoPlaceholderBatch.
* This set of methods are similar to the (Begin|End)Transaction(), but do
@ -2668,32 +2660,6 @@ class EditorBase : public nsIEditor,
ScrollSelectionIntoView mScrollSelectionIntoView;
};
/**
* Stack based helper class for saving/restoring selection. Note that this
* assumes that the nodes involved are still around afterwords!
*/
class MOZ_RAII AutoSelectionRestorer final {
public:
/**
* Constructor responsible for remembering all state needed to restore
* aSelection.
*/
explicit AutoSelectionRestorer(EditorBase& aEditorBase);
/**
* Destructor restores mSelection to its former state
*/
~AutoSelectionRestorer();
/**
* Abort() cancels to restore the selection.
*/
void Abort();
protected:
EditorBase* mEditorBase;
};
/**
* AutoEditSubActionNotifier notifies editor of start to handle
* top level edit sub-action and end handling top level edit sub-action.

View File

@ -95,6 +95,43 @@ struct MOZ_STACK_CLASS SavedRange final {
uint32_t mEndOffset = 0;
};
/******************************************************************************
* HTMLEditor::AutoSelectionRestorer
*****************************************************************************/
HTMLEditor::AutoSelectionRestorer::AutoSelectionRestorer(
HTMLEditor& aHTMLEditor)
: mHTMLEditor(nullptr) {
if (aHTMLEditor.ArePreservingSelection()) {
// We already have initialized mParentData::mSavedSelection, so this must
// be nested call.
return;
}
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
mHTMLEditor = &aHTMLEditor;
mHTMLEditor->PreserveSelectionAcrossActions();
}
HTMLEditor::AutoSelectionRestorer::~AutoSelectionRestorer() {
if (!mHTMLEditor || !mHTMLEditor->ArePreservingSelection()) {
return;
}
DebugOnly<nsresult> rvIgnored = mHTMLEditor->RestorePreservedSelection();
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"EditorBase::RestorePreservedSelection() failed, but ignored");
}
void HTMLEditor::AutoSelectionRestorer::Abort() {
if (mHTMLEditor) {
mHTMLEditor->StopPreservingSelection();
}
}
/******************************************************************************
* HTMLEditor
*****************************************************************************/
HTMLEditor::HTMLEditor()
: mCRInParagraphCreatesParagraph(false),
mIsObjectResizingEnabled(
@ -828,6 +865,39 @@ nsresult HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
return rv;
}
bool HTMLEditor::ArePreservingSelection() const {
return IsEditActionDataAvailable() && !SavedSelectionRef().IsEmpty();
}
void HTMLEditor::PreserveSelectionAcrossActions() {
MOZ_ASSERT(IsEditActionDataAvailable());
SavedSelectionRef().SaveSelection(SelectionRef());
RangeUpdaterRef().RegisterSelectionState(SavedSelectionRef());
}
nsresult HTMLEditor::RestorePreservedSelection() {
MOZ_ASSERT(IsEditActionDataAvailable());
if (SavedSelectionRef().IsEmpty()) {
return NS_ERROR_FAILURE;
}
DebugOnly<nsresult> rvIgnored =
SavedSelectionRef().RestoreSelection(SelectionRef());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"SelectionState::RestoreSelection() failed, but ignored");
StopPreservingSelection();
return NS_OK;
}
void HTMLEditor::StopPreservingSelection() {
MOZ_ASSERT(IsEditActionDataAvailable());
RangeUpdaterRef().DropSelectionState(SavedSelectionRef());
SavedSelectionRef().Clear();
}
void HTMLEditor::PreHandleMouseDown(const MouseEvent& aMouseDownEvent) {
if (mTypeInState) {
// mTypeInState will be notified of selection change even if aMouseDownEvent

View File

@ -1001,6 +1001,15 @@ class HTMLEditor final : public EditorBase,
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
DoJoinNodes(nsIContent& aContentToKeep, nsIContent& aContentToJoin);
/**
* Routines for managing the preservation of selection across
* various editor actions.
*/
bool ArePreservingSelection() const;
void PreserveSelectionAcrossActions();
MOZ_CAN_RUN_SCRIPT nsresult RestorePreservedSelection();
void StopPreservingSelection();
protected: // edit sub-action handler
/**
* CanHandleHTMLEditSubAction() checks whether there is at least one
@ -4362,6 +4371,42 @@ class HTMLEditor final : public EditorBase,
IndentListChild(RefPtr<Element>* aCurList, const EditorDOMPoint& aCurPoint,
nsIContent& aContent);
/**
* Stack based helper class for saving/restoring selection. Note that this
* assumes that the nodes involved are still around afterwords!
*/
class AutoSelectionRestorer final {
public:
AutoSelectionRestorer() = delete;
explicit AutoSelectionRestorer(const AutoSelectionRestorer& aOther) =
delete;
AutoSelectionRestorer(AutoSelectionRestorer&& aOther) = delete;
/**
* Constructor responsible for remembering all state needed to restore
* aSelection.
* XXX This constructor and the destructor should be marked as
* `MOZ_CAN_RUN_SCRIPT`, but it's impossible due to this may be used
* with `Maybe`.
*/
MOZ_CAN_RUN_SCRIPT_BOUNDARY explicit AutoSelectionRestorer(
HTMLEditor& aHTMLEditor);
/**
* Destructor restores mSelection to its former state
*/
MOZ_CAN_RUN_SCRIPT_BOUNDARY ~AutoSelectionRestorer();
/**
* Abort() cancels to restore the selection.
*/
void Abort();
protected:
// The lifetime must be guaranteed by the creator of this instance.
MOZ_KNOWN_LIVE HTMLEditor* mHTMLEditor = nullptr;
};
RefPtr<TypeInState> mTypeInState;
RefPtr<ComposerCommandsUpdater> mComposerCommandsUpdater;

View File

@ -618,7 +618,7 @@ nsresult HTMLEditor::HTMLWithContextInserter::Run(
// Save current selection since DeleteTableCellWithTransaction() perturbs
// it.
{
AutoSelectionRestorer restoreSelectionLater(mHTMLEditor);
AutoSelectionRestorer restoreSelectionLater(MOZ_KnownLive(mHTMLEditor));
rv = MOZ_KnownLive(mHTMLEditor).DeleteTableCellWithTransaction(1);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteTableCellWithTransaction(1) failed");