Bug 1598327 - part 2: Make `TopLevelEditSubActionData::mCachedInlineStyle` create only in `HTMLEditor` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Sat, 23 Nov 2019 01:12:33 +0000
changeset 503633 4a55bfa7885fdc20a04063c89a0940418c0a376f
parent 503632 a2110a152aa5dbd5dc51483cdf5f3ca3487a0cfe
child 503634 d39f4366eba4bf1b89f0f3a48ace2d8c9e1f410f
push id101429
push usermasayuki@d-toybox.com
push dateMon, 25 Nov 2019 06:45:45 +0000
treeherderautoland@4a55bfa7885f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1598327
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1598327 - part 2: Make `TopLevelEditSubActionData::mCachedInlineStyle` create only in `HTMLEditor` r=m_kato The initialization cost of `AutoStyleCacheArray` is still expensive and it's used only by `HTMLEditor`. Therefore, we should make it `Maybe` and construct it only when the editor is an `HTMLEditor`. Depends on D54253 Differential Revision: https://phabricator.services.mozilla.com/D54254
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorBase.h
editor/libeditor/HTMLEditSubActionHandler.cpp
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -5486,16 +5486,17 @@ EditorBase::AutoEditActionDataSetter::Au
     mEditAction = aEditAction;
     mDirectionOfTopLevelEditSubAction = eNone;
     if (mEditorBase.mIsHTMLEditorClass) {
       mTopLevelEditSubActionData.mSelectedRange =
           mEditorBase.AsHTMLEditor()
               ->GetSelectedRangeItemForTopLevelEditSubAction();
       mTopLevelEditSubActionData.mChangedRange =
           mEditorBase.AsHTMLEditor()->GetChangedRangeForTopLevelEditSubAction();
+      mTopLevelEditSubActionData.mCachedInlineStyles.emplace();
     }
   }
   mEditorBase.mEditActionData = this;
 }
 
 EditorBase::AutoEditActionDataSetter::~AutoEditActionDataSetter() {
   if (!mSelection || NS_WARN_IF(mEditorBase.mEditActionData != this)) {
     return;
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -625,17 +625,20 @@ class EditorBase : public nsIEditor,
 
     // Computing changed range while we're handling sub actions.
     RefPtr<nsRange> mChangedRange;
 
     // XXX In strict speaking, mCachedInlineStyles isn't enough to cache inline
     //     styles because inline style can be specified with "style" attribute
     //     and/or CSS in <style> elements or CSS files.  So, we need to look
     //     for better implementation about this.
-    AutoStyleCacheArray mCachedInlineStyles;
+    // FYI: Initialization cost of AutoStyleCacheArray is expensive and it is
+    //      not used by TextEditor so that we should construct it only when
+    //      we're an HTMLEditor.
+    Maybe<AutoStyleCacheArray> mCachedInlineStyles;
 
     // If we tried to delete selection, set to true.
     bool mDidDeleteSelection;
 
     // If we have explicitly set selection inter line, set to true.
     // `AfterEdit()` or something shouldn't overwrite it in such case.
     bool mDidExplicitlySetInterLine;
 
@@ -693,17 +696,19 @@ class EditorBase : public nsIEditor,
       // editor is an HTML editor anymore.  Note that if `mSelectedRange` is
       // non-nullptr, that means that we're in `HTMLEditor`.
       if (!mSelectedRange) {
         return;
       }
       mNewBlockElement = nullptr;
       mSelectedRange->Clear();
       mChangedRange->Reset();
-      mCachedInlineStyles.Clear();
+      if (mCachedInlineStyles.isSome()) {
+        mCachedInlineStyles->Clear();
+      }
       mDidDeleteSelection = false;
       mDidDeleteNonCollapsedRange = false;
       mDidDeleteEmptyParentBlocks = false;
       mRestoreContentEditableCount = false;
     }
 
     /**
      * Extend mChangedRange to include `aNode`.
--- a/editor/libeditor/HTMLEditSubActionHandler.cpp
+++ b/editor/libeditor/HTMLEditSubActionHandler.cpp
@@ -636,17 +636,17 @@ nsresult HTMLEditor::OnEndHandlingTopLev
         break;
     }
     if (reapplyCachedStyle) {
       mTypeInState->UpdateSelState(SelectionRefPtr());
       rv = ReapplyCachedStyles();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
-      TopLevelEditSubActionDataRef().mCachedInlineStyles.Clear();
+      TopLevelEditSubActionDataRef().mCachedInlineStyles->Clear();
     }
   }
 
   rv = HandleInlineSpellCheck(
       TopLevelEditSubActionDataRef().mSelectedRange->StartPoint(),
       TopLevelEditSubActionDataRef().mChangedRange);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -1287,17 +1287,17 @@ nsresult HTMLEditor::PrepareInlineStyles
       }
       default:
         break;
     }
   }
   // For most actions we want to clear the cached styles, but there are
   // exceptions
   if (!IsStyleCachePreservingSubAction(GetTopLevelEditSubAction())) {
-    TopLevelEditSubActionDataRef().mCachedInlineStyles.Clear();
+    TopLevelEditSubActionDataRef().mCachedInlineStyles->Clear();
   }
   return NS_OK;
 }
 
 EditActionResult HTMLEditor::HandleInsertText(
     EditSubAction aEditSubAction, const nsAString& aInsertionString) {
   MOZ_ASSERT(IsTopLevelEditSubActionDataAvailable());
   MOZ_ASSERT(aEditSubAction == EditSubAction::eInsertText ||
@@ -8148,17 +8148,17 @@ nsresult HTMLEditor::HandleInsertParagra
     }
     // Layout tells the caret to blink in a weird place if we don't place a
     // break after the header.
     nsCOMPtr<nsIContent> sibling;
     if (aHeader.GetNextSibling()) {
       sibling = GetNextHTMLSibling(aHeader.GetNextSibling());
     }
     if (!sibling || !sibling->IsHTMLElement(nsGkAtoms::br)) {
-      TopLevelEditSubActionDataRef().mCachedInlineStyles.Clear();
+      TopLevelEditSubActionDataRef().mCachedInlineStyles->Clear();
       mTypeInState->ClearAllProps();
 
       // Create a paragraph
       nsStaticAtom& paraAtom = DefaultParagraphSeparatorTagName();
       // We want a wrapper element even if we separate with <br>
       EditorDOMPoint nextToHeader(headerParent, offset + 1);
       RefPtr<Element> pNode = CreateNodeWithTransaction(
           &paraAtom == nsGkAtoms::br ? *nsGkAtoms::p : MOZ_KnownLive(paraAtom),
@@ -9362,17 +9362,17 @@ Element* HTMLEditor::GetMostAncestorMail
   }
   return mailCiteElement;
 }
 
 nsresult HTMLEditor::CacheInlineStyles(nsINode& aNode) {
   MOZ_ASSERT(IsTopLevelEditSubActionDataAvailable());
 
   nsresult rv = GetInlineStyles(
-      aNode, TopLevelEditSubActionDataRef().mCachedInlineStyles);
+      aNode, *TopLevelEditSubActionDataRef().mCachedInlineStyles);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "GetInlineStyles() failed");
   return rv;
 }
 
 nsresult HTMLEditor::GetInlineStyles(nsINode& aNode,
                                      AutoStyleCacheArray& aStyleCacheArray) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
@@ -9441,17 +9441,17 @@ nsresult HTMLEditor::ReapplyCachedStyles
   nsresult rv = GetInlineStyles(*selNode, styleCacheArrayAtInsertionPoint);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv == NS_ERROR_EDITOR_DESTROYED ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
   }
 
   for (size_t i = 0; i < styleCacheArrayAtInsertionPoint.Length(); ++i) {
     StyleCache& styleCacheAtInsertionPoint = styleCacheArrayAtInsertionPoint[i];
     StyleCache& styleCacheBeforeEdit =
-        TopLevelEditSubActionDataRef().mCachedInlineStyles[i];
+        TopLevelEditSubActionDataRef().mCachedInlineStyles->ElementAt(i);
     if (styleCacheBeforeEdit.mPresent) {
       bool bFirst, bAny, bAll;
       bFirst = bAny = bAll = false;
 
       nsAutoString curValue;
       if (useCSS) {
         // check computed style first in css case
         bAny = CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(