зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1630168 - Make `HTMLEditor` stop adding same runnable method into the queue r=m_kato
When `HTMLEditor` is notified of content changes, it may add a runnable method `HTMLEditor::OnModifyDocument` or `HTMLEditor::NotifyRootChanged` for each notification. However, their code do not need running twice nor more. This could cause performance issues on complicated web apps which sets `innerHTML` at every key press. Differential Revision: https://phabricator.services.mozilla.com/D71001
This commit is contained in:
Родитель
3ef497088e
Коммит
9f7fb5bb0f
|
@ -11848,8 +11848,12 @@ EditActionResult HTMLEditor::AddZIndexAsSubAction(int32_t aChange) {
|
|||
}
|
||||
|
||||
nsresult HTMLEditor::OnDocumentModified() {
|
||||
nsContentUtils::AddScriptRunner(NewRunnableMethod(
|
||||
"HTMLEditor::OnModifyDocument", this, &HTMLEditor::OnModifyDocument));
|
||||
if (mPendingDocumentModifiedRunner) {
|
||||
return NS_OK; // We've already posted same runnable into the queue.
|
||||
}
|
||||
mPendingDocumentModifiedRunner = NewRunnableMethod(
|
||||
"HTMLEditor::OnModifyDocument", this, &HTMLEditor::OnModifyDocument);
|
||||
nsContentUtils::AddScriptRunner(do_AddRef(mPendingDocumentModifiedRunner));
|
||||
// Be aware, if OnModifyDocument() may be called synchronously, the
|
||||
// editor might have been destroyed here.
|
||||
return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
|
||||
|
|
|
@ -3650,11 +3650,18 @@ void HTMLEditor::DoContentInserted(nsIContent* aChild,
|
|||
|
||||
if (ShouldReplaceRootElement()) {
|
||||
UpdateRootElement();
|
||||
nsContentUtils::AddScriptRunner(NewRunnableMethod(
|
||||
"HTMLEditor::NotifyRootChanged", this, &HTMLEditor::NotifyRootChanged));
|
||||
if (mPendingRootElementUpdatedRunner) {
|
||||
return;
|
||||
}
|
||||
mPendingRootElementUpdatedRunner = NewRunnableMethod(
|
||||
"HTMLEditor::NotifyRootChanged", this, &HTMLEditor::NotifyRootChanged);
|
||||
nsContentUtils::AddScriptRunner(
|
||||
do_AddRef(mPendingRootElementUpdatedRunner));
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't need to handle our own modifications
|
||||
else if (!GetTopLevelEditSubAction() && container->IsEditable()) {
|
||||
if (!GetTopLevelEditSubAction() && container->IsEditable()) {
|
||||
if (EditorUtils::IsPaddingBRElementForEmptyEditor(*aChild)) {
|
||||
// Ignore insertion of the padding <br> element.
|
||||
return;
|
||||
|
@ -3703,11 +3710,18 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY void HTMLEditor::ContentRemoved(
|
|||
|
||||
if (SameCOMIdentity(aChild, mRootElement)) {
|
||||
mRootElement = nullptr;
|
||||
nsContentUtils::AddScriptRunner(NewRunnableMethod(
|
||||
"HTMLEditor::NotifyRootChanged", this, &HTMLEditor::NotifyRootChanged));
|
||||
// We don't need to handle our own modifications
|
||||
} else if (!GetTopLevelEditSubAction() &&
|
||||
aChild->GetParentNode()->IsEditable()) {
|
||||
if (mPendingRootElementUpdatedRunner) {
|
||||
return;
|
||||
}
|
||||
mPendingRootElementUpdatedRunner = NewRunnableMethod(
|
||||
"HTMLEditor::NotifyRootChanged", this, &HTMLEditor::NotifyRootChanged);
|
||||
nsContentUtils::AddScriptRunner(
|
||||
do_AddRef(mPendingRootElementUpdatedRunner));
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't need to handle our own modifications
|
||||
if (!GetTopLevelEditSubAction() && aChild->GetParentNode()->IsEditable()) {
|
||||
if (aChild && EditorUtils::IsPaddingBRElementForEmptyEditor(*aChild)) {
|
||||
// Ignore removal of the padding <br> element for empty editor.
|
||||
return;
|
||||
|
@ -5124,6 +5138,10 @@ bool HTMLEditor::ShouldReplaceRootElement() const {
|
|||
}
|
||||
|
||||
void HTMLEditor::NotifyRootChanged() {
|
||||
MOZ_ASSERT(mPendingRootElementUpdatedRunner,
|
||||
"HTMLEditor::NotifyRootChanged() should be called via a runner");
|
||||
mPendingRootElementUpdatedRunner = nullptr;
|
||||
|
||||
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
|
||||
|
||||
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
|
||||
|
@ -5339,6 +5357,10 @@ nsHTMLDocument* HTMLEditor::GetHTMLDocument() const {
|
|||
}
|
||||
|
||||
nsresult HTMLEditor::OnModifyDocument() {
|
||||
MOZ_ASSERT(mPendingDocumentModifiedRunner,
|
||||
"HTMLEditor::OnModifyDocument() should be called via a runner");
|
||||
mPendingDocumentModifiedRunner = nullptr;
|
||||
|
||||
if (IsEditActionDataAvailable()) {
|
||||
return OnModifyDocumentInternal();
|
||||
}
|
||||
|
@ -5357,6 +5379,7 @@ nsresult HTMLEditor::OnModifyDocument() {
|
|||
|
||||
nsresult HTMLEditor::OnModifyDocumentInternal() {
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(!mPendingDocumentModifiedRunner);
|
||||
|
||||
// EnsureNoPaddingBRElementForEmptyEditor() below may cause a flush, which
|
||||
// could destroy the editor
|
||||
|
|
|
@ -54,6 +54,7 @@ class ListItemElementSelectionState;
|
|||
class MoveNodeResult;
|
||||
class ParagraphStateAtSelection;
|
||||
class ResizerSelectionListener;
|
||||
class Runnable;
|
||||
class SplitRangeOffFromNodeResult;
|
||||
class SplitRangeOffResult;
|
||||
class WSRunObject;
|
||||
|
@ -4442,6 +4443,9 @@ class HTMLEditor final : public TextEditor,
|
|||
// Used by TopLevelEditSubActionData::mChangedRange.
|
||||
mutable RefPtr<nsRange> mChangedRangeForTopLevelEditSubAction;
|
||||
|
||||
RefPtr<Runnable> mPendingRootElementUpdatedRunner;
|
||||
RefPtr<Runnable> mPendingDocumentModifiedRunner;
|
||||
|
||||
bool mCRInParagraphCreatesParagraph;
|
||||
|
||||
bool mCSSAware;
|
||||
|
|
Загрузка…
Ссылка в новой задаче