Bug 1572375 - part 1: Move `TextEditRules::mPaddingBRElementForEmptyEditor` to `EditorBase` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 09 Aug 2019 07:03:29 +0000
changeset 487562 235c10b6af849e1658fefd1dfdc6e21a02c023b2
parent 487561 7b77bedf4ca3985787482064df89323576c6d616
child 487563 94b4e63c71df3c07e8a2ac8dab406284782b73e5
push id92340
push usermasayuki@d-toybox.com
push dateTue, 13 Aug 2019 02:32:12 +0000
treeherderautoland@3a07d2f4b955 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1572375
milestone70.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 1572375 - part 1: Move `TextEditRules::mPaddingBRElementForEmptyEditor` to `EditorBase` r=m_kato `TextEditRules::mPaddingBRElementForEmptyEditor` are used by both `TextEditor` and `HTMLEditor`. Therefore, it should be in `EditorBase`. This patch makes `TextEditRules` and `HTMLEditRules` directly access the private member of `EditorBase` temporarily. It'll be fixed by the following patches. Differential Revision: https://phabricator.services.mozilla.com/D41155
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorBase.h
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditRules.h
editor/libeditor/TextEditor.cpp
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -51,16 +51,17 @@
 #include "mozilla/TextServicesDocument.h"  // for TextServicesDocument
 #include "mozilla/TextEvents.h"
 #include "mozilla/TransactionManager.h"  // for TransactionManager
 #include "mozilla/dom/CharacterData.h"   // for CharacterData
 #include "mozilla/dom/DataTransfer.h"    // for DataTransfer
 #include "mozilla/dom/Element.h"         // for Element, nsINode::AsElement
 #include "mozilla/dom/EventTarget.h"     // for EventTarget
 #include "mozilla/dom/HTMLBodyElement.h"
+#include "mozilla/dom/HTMLBRElement.h"
 #include "mozilla/dom/Text.h"
 #include "mozilla/dom/Event.h"
 #include "nsAString.h"                // for nsAString::Length, etc.
 #include "nsCCUncollectableMarker.h"  // for nsCCUncollectableMarker
 #include "nsCaret.h"                  // for nsCaret
 #include "nsCaseTreatment.h"
 #include "nsCharTraits.h"              // for NS_IS_HIGH_SURROGATE, etc.
 #include "nsComponentManagerUtils.h"   // for do_CreateInstance
@@ -159,16 +160,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Ed
   // Remove event listeners first since EditorEventListener may need
   // mDocument, mEventTarget, etc.
   if (tmp->mEventListener) {
     tmp->mEventListener->Disconnect();
     tmp->mEventListener = nullptr;
   }
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaddingBRElementForEmptyEditor)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectionController)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMEContentObserver)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextServicesDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextInputListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTransactionManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners)
@@ -181,16 +183,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase)
   Document* currentDoc =
       tmp->mRootElement ? tmp->mRootElement->GetUncomposedDoc() : nullptr;
   if (currentDoc && nsCCUncollectableMarker::InGeneration(
                         cb, currentDoc->GetMarkedCCGeneration())) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaddingBRElementForEmptyEditor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionController)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMEContentObserver)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextServicesDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextInputListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransactionManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActionListeners)
@@ -495,16 +498,17 @@ void EditorBase::PreDestroy(bool aDestro
   mActionListeners.Clear();
   mEditorObservers.Clear();
   mDocStateListeners.Clear();
   mInlineSpellChecker = nullptr;
   mTextServicesDocument = nullptr;
   mTextInputListener = nullptr;
   mSpellcheckCheckboxState = eTriUnset;
   mRootElement = nullptr;
+  mPaddingBRElementForEmptyEditor = nullptr;
 
   // Transaction may grab this instance.  Therefore, they should be released
   // here for stopping the circular reference with this instance.
   if (mTransactionManager) {
     DebugOnly<bool> disabledUndoRedo = DisableUndoRedo();
     NS_WARNING_ASSERTION(disabledUndoRedo,
                          "Failed to disable undo/redo transactions");
     mTransactionManager = nullptr;
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -95,16 +95,17 @@ template <typename NodeType>
 class CreateNodeResultBase;
 typedef CreateNodeResultBase<dom::Element> CreateElementResult;
 
 namespace dom {
 class DataTransfer;
 class DragEvent;
 class Element;
 class EventTarget;
+class HTMLBRElement;
 }  // namespace dom
 
 namespace widget {
 struct IMEState;
 }  // namespace widget
 
 /**
  * SplitAtEdges is for EditorBase::SplitNodeDeepWithTransaction(),
@@ -2291,16 +2292,21 @@ class EditorBase : public nsIEditor,
 
   RefPtr<mozInlineSpellChecker> mInlineSpellChecker;
   // Reference to text services document for mInlineSpellChecker.
   RefPtr<TextServicesDocument> mTextServicesDocument;
 
   RefPtr<TransactionManager> mTransactionManager;
   // Cached root node.
   RefPtr<Element> mRootElement;
+
+  // mPaddingBRElementForEmptyEditor should be used for placing caret
+  // at proper position when editor is empty.
+  RefPtr<dom::HTMLBRElement> mPaddingBRElementForEmptyEditor;
+
   // The form field as an event receiver.
   nsCOMPtr<dom::EventTarget> mEventTarget;
   RefPtr<EditorEventListener> mEventListener;
   // Strong reference to placeholder for begin/end batch purposes.
   RefPtr<PlaceholderTransaction> mPlaceholderTransaction;
   // Name of placeholder transaction.
   nsAtom* mPlaceholderName;
   // Saved selection state for placeholder transaction batching.
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -801,17 +801,17 @@ nsresult HTMLEditRules::DidDoAction(Edit
       return DidAbsolutePosition();
     }
     default:
       return TextEditRules::DidDoAction(aInfo, aResult);
   }
 }
 
 bool HTMLEditRules::DocumentIsEmpty() const {
-  return !!mPaddingBRElementForEmptyEditor;
+  return !!HTMLEditorRef().mPaddingBRElementForEmptyEditor;
 }
 
 nsresult HTMLEditRules::GetListState(bool* aMixed, bool* aOL, bool* aUL,
                                      bool* aDL) {
   NS_ENSURE_TRUE(aMixed && aOL && aUL && aDL, NS_ERROR_NULL_POINTER);
   *aMixed = false;
   *aOL = false;
   *aUL = false;
@@ -1643,22 +1643,22 @@ nsresult HTMLEditRules::WillInsertText(E
   return NS_OK;
 }
 
 nsresult HTMLEditRules::WillLoadHTML() {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // Delete mPaddingBRElementForEmptyEditor if it exists. If we really
   // need one, it will be added during post-processing in AfterEditInner().
-  if (mPaddingBRElementForEmptyEditor) {
+  if (HTMLEditorRef().mPaddingBRElementForEmptyEditor) {
     // A mutation event listener may recreate padding <br> element for empty
     // editor again during the call of DeleteNodeWithTransaction().  So, move
     // it first.
     RefPtr<HTMLBRElement> paddingBRElement(
-        std::move(mPaddingBRElementForEmptyEditor));
+        std::move(HTMLEditorRef().mPaddingBRElementForEmptyEditor));
     DebugOnly<nsresult> rv = MOZ_KnownLive(HTMLEditorRef())
                                  .DeleteNodeWithTransaction(*paddingBRElement);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                          "Failed to remove the padding <br> element");
   }
@@ -2287,17 +2287,17 @@ nsresult HTMLEditRules::WillDeleteSelect
   *aHandled = false;
 
   // Remember that we did a selection deletion.  Used by
   // CreateStyleForInsertText()
   mDidDeleteSelection = true;
 
   // If there is only padding <br> element for empty editor, cancel the
   // operation.
-  if (mPaddingBRElementForEmptyEditor) {
+  if (HTMLEditorRef().mPaddingBRElementForEmptyEditor) {
     *aCancel = true;
     return NS_OK;
   }
 
   // First check for table selection mode.  If so, hand off to table editor.
   ErrorResult error;
   RefPtr<Element> cellElement =
       HTMLEditorRef().GetFirstSelectedTableCellElement(error);
@@ -11127,22 +11127,22 @@ void HTMLEditRules::OnModifyDocument() {
   AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   // DeleteNodeWithTransaction() below may cause a flush, which could destroy
   // the editor
   nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
 
   // Delete our padding <br> element for empty editor, if we have one, since
   // the document might not be empty any more.
-  if (mPaddingBRElementForEmptyEditor) {
+  if (HTMLEditorRef().mPaddingBRElementForEmptyEditor) {
     // A mutation event listener may recreate padding <br> element for empty
     // editor again during the call of DeleteNodeWithTransaction().  So, move
     // it first.
     RefPtr<HTMLBRElement> paddingBRElement(
-        std::move(mPaddingBRElementForEmptyEditor));
+        std::move(HTMLEditorRef().mPaddingBRElementForEmptyEditor));
     DebugOnly<nsresult> rv = MOZ_KnownLive(HTMLEditorRef())
                                  .DeleteNodeWithTransaction(*paddingBRElement);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                          "Failed to remove the padding <br> element");
   }
 
   // Try to recreate the padding <br> element for empty editor if needed.
   DebugOnly<nsresult> rv = CreatePaddingBRElementForEmptyEditorIfNeeded();
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -58,29 +58,27 @@ using namespace dom;
 
 /********************************************************
  * mozilla::TextEditRules
  ********************************************************/
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(TextEditRules)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TextEditRules)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaddingBRElementForEmptyEditor)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedSelectionNode)
   if (HTMLEditRules* htmlEditRules = tmp->AsHTMLEditRules()) {
     HTMLEditRules* tmp = htmlEditRules;
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocChangeRange)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mUtilRange)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mNewBlock)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRangeItem)
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TextEditRules)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaddingBRElementForEmptyEditor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedSelectionNode)
   if (HTMLEditRules* htmlEditRules = tmp->AsHTMLEditRules()) {
     HTMLEditRules* tmp = htmlEditRules;
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocChangeRange)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUtilRange)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNewBlock)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRangeItem)
   }
@@ -99,17 +97,16 @@ TextEditRules::TextEditRules()
       mDeleteBidiImmediately(false),
       mIsHTMLEditRules(false),
       mTopLevelEditSubAction(EditSubAction::eNone) {
   InitFields();
 }
 
 void TextEditRules::InitFields() {
   mTextEditor = nullptr;
-  mPaddingBRElementForEmptyEditor = nullptr;
   mCachedSelectionNode = nullptr;
   mCachedSelectionOffset = 0;
   mActionNesting = 0;
   mLockRulesSniffing = false;
   mDidExplicitlySetInterline = false;
   mDeleteBidiImmediately = false;
   mTopLevelEditSubAction = EditSubAction::eNone;
 }
@@ -390,25 +387,25 @@ nsresult TextEditRules::WillInsert(bool*
     *aCancel = false;
   }
 
   if (IsPasswordEditor() && IsMaskingPassword()) {
     TextEditorRef().MaskAllCharacters();
   }
 
   // check for the magic content node and delete it if it exists
-  if (!mPaddingBRElementForEmptyEditor) {
+  if (!TextEditorRef().mPaddingBRElementForEmptyEditor) {
     return NS_OK;
   }
 
   // A mutation event listener may recreate padding <br> element for empty
   // editor again during the call of DeleteNodeWithTransaction().  So, move
   // it first.
   RefPtr<HTMLBRElement> paddingBRElement(
-      std::move(mPaddingBRElementForEmptyEditor));
+      std::move(TextEditorRef().mPaddingBRElementForEmptyEditor));
   DebugOnly<nsresult> rv = MOZ_KnownLive(TextEditorRef())
                                .DeleteNodeWithTransaction(*paddingBRElement);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                        "Failed to remove the padding <br> element");
   return NS_OK;
@@ -1031,17 +1028,17 @@ nsresult TextEditRules::WillDeleteSelect
   CANCEL_OPERATION_IF_READONLY_OR_DISABLED
 
   // initialize out param
   *aCancel = false;
   *aHandled = false;
 
   // if there is only padding <br> element for empty editor, cancel the
   // operation.
-  if (mPaddingBRElementForEmptyEditor) {
+  if (TextEditorRef().mPaddingBRElementForEmptyEditor) {
     *aCancel = true;
     return NS_OK;
   }
   nsresult rv =
       DeleteSelectionWithTransaction(aCollapsedAction, aCancel, aHandled);
   // DeleteSelectionWithTransaction() creates SelectionBatcher.  Therefore,
   // quitting from it might cause having destroyed the editor.
   if (NS_WARN_IF(!CanHandleEditAction())) {
@@ -1171,19 +1168,20 @@ nsresult TextEditRules::DidUndo(nsresult
 
   // The idea here is to see if the magic empty node has suddenly reappeared as
   // the result of the undo.  If it has, set our state so we remember it.
   // There is a tradeoff between doing here and at redo, or doing it everywhere
   // else that might care.  Since undo and redo are relatively rare, it makes
   // sense to take the (small) performance hit here.
   nsIContent* node = TextEditorRef().GetLeftmostChild(rootElement);
   if (node && EditorBase::IsPaddingBRElementForEmptyEditor(*node)) {
-    mPaddingBRElementForEmptyEditor = static_cast<HTMLBRElement*>(node);
+    TextEditorRef().mPaddingBRElementForEmptyEditor =
+        static_cast<HTMLBRElement*>(node);
   } else {
-    mPaddingBRElementForEmptyEditor = nullptr;
+    TextEditorRef().mPaddingBRElementForEmptyEditor = nullptr;
   }
   return aResult;
 }
 
 nsresult TextEditRules::WillRedo(bool* aCancel, bool* aHandled) {
   if (NS_WARN_IF(!aCancel) || NS_WARN_IF(!aHandled)) {
     return NS_ERROR_INVALID_ARG;
   }
@@ -1208,25 +1206,26 @@ nsresult TextEditRules::DidRedo(nsresult
 
   nsCOMPtr<nsIHTMLCollection> nodeList =
       rootElement->GetElementsByTagName(NS_LITERAL_STRING("br"));
   MOZ_ASSERT(nodeList);
   uint32_t len = nodeList->Length();
 
   if (len != 1) {
     // only in the case of one br could there be the padding <br> element.
-    mPaddingBRElementForEmptyEditor = nullptr;
+    TextEditorRef().mPaddingBRElementForEmptyEditor = nullptr;
     return NS_OK;
   }
 
   Element* brElement = nodeList->Item(0);
   if (EditorBase::IsPaddingBRElementForEmptyEditor(*brElement)) {
-    mPaddingBRElementForEmptyEditor = static_cast<HTMLBRElement*>(brElement);
+    TextEditorRef().mPaddingBRElementForEmptyEditor =
+        static_cast<HTMLBRElement*>(brElement);
   } else {
-    mPaddingBRElementForEmptyEditor = nullptr;
+    TextEditorRef().mPaddingBRElementForEmptyEditor = nullptr;
   }
   return NS_OK;
 }
 
 nsresult TextEditRules::WillOutputText(const nsAString* aOutputFormat,
                                        nsAString* aOutString, uint32_t aFlags,
                                        bool* aCancel, bool* aHandled) {
   MOZ_ASSERT(IsEditorDataAvailable());
@@ -1242,17 +1241,17 @@ nsresult TextEditRules::WillOutputText(c
   *aHandled = false;
 
   if (!aOutputFormat->LowerCaseEqualsLiteral("text/plain")) {
     return NS_OK;
   }
 
   // If there is a padding <br> element, there's no content.  So output empty
   // string.
-  if (mPaddingBRElementForEmptyEditor) {
+  if (TextEditorRef().mPaddingBRElementForEmptyEditor) {
     aOutString->Truncate();
     *aHandled = true;
     return NS_OK;
   }
 
   // If it's necessary to check selection range or the editor wraps hard,
   // we need some complicated handling.  In such case, we need to use the
   // expensive path.
@@ -1325,17 +1324,17 @@ nsresult TextEditRules::WillOutputText(c
   *aHandled = true;
   return NS_OK;
 }
 
 nsresult TextEditRules::RemoveRedundantTrailingBR() {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // If the passing <br> element exists, we have no work to do.
-  if (mPaddingBRElementForEmptyEditor) {
+  if (TextEditorRef().mPaddingBRElementForEmptyEditor) {
     return NS_OK;
   }
 
   // Likewise, nothing to be done if we could never have inserted a trailing br
   if (IsSingleLineEditor()) {
     return NS_OK;
   }
 
@@ -1353,19 +1352,21 @@ nsresult TextEditRules::RemoveRedundantT
       HTMLBRElement::FromNodeOrNull(rootElement->GetFirstChild());
   if (!brElement ||
       !EditorBase::IsPaddingBRElementForEmptyLastLine(*brElement)) {
     return NS_OK;
   }
 
   // Rather than deleting this node from the DOM tree we should instead
   // morph this <br> element into the padding <br> element for editor.
-  mPaddingBRElementForEmptyEditor = std::move(brElement);
-  mPaddingBRElementForEmptyEditor->UnsetFlags(NS_PADDING_FOR_EMPTY_LAST_LINE);
-  mPaddingBRElementForEmptyEditor->SetFlags(NS_PADDING_FOR_EMPTY_EDITOR);
+  TextEditorRef().mPaddingBRElementForEmptyEditor = std::move(brElement);
+  TextEditorRef().mPaddingBRElementForEmptyEditor->UnsetFlags(
+      NS_PADDING_FOR_EMPTY_LAST_LINE);
+  TextEditorRef().mPaddingBRElementForEmptyEditor->SetFlags(
+      NS_PADDING_FOR_EMPTY_EDITOR);
 
   return NS_OK;
 }
 
 nsresult TextEditRules::CreateTrailingBRIfNeeded() {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // but only if we aren't a single line edit field
@@ -1411,17 +1412,17 @@ nsresult TextEditRules::CreateTrailingBR
   brElement->SetFlags(NS_PADDING_FOR_EMPTY_LAST_LINE);
 
   return NS_OK;
 }
 
 nsresult TextEditRules::CreatePaddingBRElementForEmptyEditorIfNeeded() {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  if (mPaddingBRElementForEmptyEditor) {
+  if (TextEditorRef().mPaddingBRElementForEmptyEditor) {
     // Let's not create more than one, ok?
     return NS_OK;
   }
 
   // tell rules system to not do any post-processing
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
       TextEditorRef(), EditSubAction::eCreatePaddingBRElementForEmptyEditor,
       nsIEditor::eNone);
@@ -1457,17 +1458,17 @@ nsresult TextEditRules::CreatePaddingBRE
       TextEditorRef().CreateHTMLContent(nsGkAtoms::br);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(!newBrElement)) {
     return NS_ERROR_FAILURE;
   }
 
-  mPaddingBRElementForEmptyEditor =
+  TextEditorRef().mPaddingBRElementForEmptyEditor =
       static_cast<HTMLBRElement*>(newBrElement.get());
 
   // Give it a special attribute.
   newBrElement->SetFlags(NS_PADDING_FOR_EMPTY_EDITOR);
 
   // Put the node in the document.
   nsresult rv = MOZ_KnownLive(TextEditorRef())
                     .InsertNodeWithTransaction(*newBrElement,
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -126,20 +126,16 @@ class TextEditRules {
    *     only remove the leading and trailing newlines.
    *   nsIPlaintextEditor::eNewlinesPasteToFirst (1) or any other value:
    *     remove the first newline and all characters following it.
    *
    * @param aString the string to be modified in place.
    */
   void HandleNewLines(nsString& aString);
 
-  bool HasPaddingBRElementForEmptyEditor() const {
-    return !!mPaddingBRElementForEmptyEditor;
-  }
-
  protected:
   void InitFields();
 
   // TextEditRules implementation methods
 
   /**
    * Called before inserting text.
    * This method may actually inserts text into the editor.  Therefore, this
@@ -383,19 +379,16 @@ class TextEditRules {
   /**
    * GetTextNodeAroundSelectionStartContainer() may return a Text node around
    * start container of Selection.  If current selection container is not
    * a text node, this will look for descendants and next siblings of the
    * container.
    */
   inline already_AddRefed<nsINode> GetTextNodeAroundSelectionStartContainer();
 
-  // mPaddingBRElementForEmptyEditor should be used for placing caret
-  // at proper position when editor is empty.
-  RefPtr<dom::HTMLBRElement> mPaddingBRElementForEmptyEditor;
   // Cached selected node.
   nsCOMPtr<nsINode> mCachedSelectionNode;
   // Cached selected offset.
   uint32_t mCachedSelectionOffset;
   uint32_t mActionNesting;
   bool mLockRulesSniffing;
   bool mDidExplicitlySetInterline;
   // In bidirectional text, delete characters not visually adjacent to the
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -1337,17 +1337,17 @@ already_AddRefed<Element> TextEditor::Ge
 
 nsresult TextEditor::IsEmpty(bool* aIsEmpty) const {
   if (NS_WARN_IF(!mRules)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   *aIsEmpty = true;
 
-  if (mRules->HasPaddingBRElementForEmptyEditor()) {
+  if (mPaddingBRElementForEmptyEditor) {
     return NS_OK;
   }
 
   // Even if there is no padding <br> element for empty editor, we should be
   // detected as empty editor if all the children are text nodes and these
   // have no content.
   Element* rootElement = GetRoot();
   if (!rootElement) {