From 9d4fda135f7ab937e6fbfdc008e7f7462d98f29b Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Sat, 15 Feb 2020 08:18:43 +0000 Subject: [PATCH] Bug 1601585 - Make `Document::EditingStateChanged()` stop calling `HTMLEditor::BeginingOfDocument()` when there is a pending state change for `contenteditable` elements and there is a selection range r=smaug For backward compatibility, `Document::EditingStateChanged()` calls `HTMLEditor::BeginingOfDocument()` to initialize selection when the document becomes editable first time. However, it checks whether `Document::mEditingState` was ``EditingState::eOff` or not. This looks enough, but not so because `Document::MaybeEditingStateChanged()` calls it asynchronously if `contenteditable` element appears at not safe to run script. Therefore, this patch makes it check `Document::mContentEditableCount` value which is modified synchronously from `Element::AfterSetAttr()` (additionally, this makes it check whether there is at least a range in normal selection too, though). Differential Revision: https://phabricator.services.mozilla.com/D62814 --HG-- extra : moz-landing-system : lando --- dom/base/Document.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 0c30acb56d71..af8eb2336a89 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -5387,6 +5387,27 @@ nsresult Document::EditingStateChanged() { RefPtr presShell = GetPresShell(); NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); + // If we're entering the design mode from non-editable state, put the + // selection at the beginning of the document for compatibility reasons. + bool collapseSelectionAtBeginningOfDocument = + designMode && oldState == EditingState::eOff; + // However, mEditingState may be eOff even if there is some + // `contenteditable` area and selection has been initialized for it because + // mEditingState for `contenteditable` may have been scheduled to modify + // when safe. In such case, we should not reinitialize selection. + if (collapseSelectionAtBeginningOfDocument && mContentEditableCount) { + Selection* selection = + presShell->GetSelection(nsISelectionController::SELECTION_NORMAL); + NS_WARNING_ASSERTION(selection, "Why don't we have Selection?"); + if (selection && selection->RangeCount()) { + // Perhaps, we don't need to check whether the selection is in + // an editing host or not because all contents will be editable + // in designMode. (And we don't want to make this code so complicated + // because of legacy API.) + collapseSelectionAtBeginningOfDocument = false; + } + } + MOZ_ASSERT(mStyleSetFilled); // Before making this window editable, we need to modify UA style sheet @@ -5451,9 +5472,7 @@ nsresult Document::EditingStateChanged() { return NS_OK; } - // If we're entering the design mode, put the selection at the beginning of - // the document for compatibility reasons. - if (designMode && oldState == EditingState::eOff) { + if (collapseSelectionAtBeginningOfDocument) { htmlEditor->BeginningOfDocument(); }