Bug 1572375 - part 4: Move `TextEditRules::RemoveRedundantTrailingBR()` into `TextEditor` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 09 Aug 2019 09:01:56 +0000
changeset 487549 8059efaac8ca4a45dd3d4161aa3e09e644e3c5ca
parent 487548 e7d953d0be6cf385c848d80039a1cb737b47606b
child 487550 8c7339d7cd3b9679b17c02b8f6d2d5d12cd1b949
push id36425
push userbtara@mozilla.com
push dateTue, 13 Aug 2019 09:54:32 +0000
treeherdermozilla-central@e29ba984dad2 [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 4: Move `TextEditRules::RemoveRedundantTrailingBR()` into `TextEditor` r=m_kato `TextEditRules::RemoveRedundantTrailingBR()` is used only by multiline text editor (i.e., `<textarea>`). Therefore, it should be moved into `TextEditor`. Differential Revision: https://phabricator.services.mozilla.com/D41158
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditRules.h
editor/libeditor/TextEditor.cpp
editor/libeditor/TextEditor.h
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -245,18 +245,17 @@ nsresult TextEditRules::AfterEdit(EditSu
         0, nullptr, 0);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     // no longer uses mCachedSelectionNode, so release it.
     mCachedSelectionNode = nullptr;
 
-    // if only trailing <br> remaining remove it
-    rv = RemoveRedundantTrailingBR();
+    rv = TextEditorRef().MaybeChangePaddingBRElementForEmptyEditor();
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     // detect empty doc
     rv = CreatePaddingBRElementForEmptyEditorIfNeeded();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
@@ -1218,57 +1217,16 @@ nsresult TextEditRules::WillOutputText(c
 
   // Otherwise, the text is the value.
   text->GetData(*aOutString);
 
   *aHandled = true;
   return NS_OK;
 }
 
-nsresult TextEditRules::RemoveRedundantTrailingBR() {
-  MOZ_ASSERT(IsEditorDataAvailable());
-
-  // If the passing <br> element exists, we have no work to do.
-  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;
-  }
-
-  Element* rootElement = TextEditorRef().GetRoot();
-  if (NS_WARN_IF(!rootElement)) {
-    return NS_ERROR_NULL_POINTER;
-  }
-
-  if (rootElement->GetChildCount() > 1) {
-    // The trailing br is redundant if it is the only remaining child node
-    return NS_OK;
-  }
-
-  RefPtr<HTMLBRElement> brElement =
-      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.
-  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
   if (IsSingleLineEditor()) {
     return NS_OK;
   }
 
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -231,21 +231,16 @@ class TextEditRules {
    * @param aOutText   The string to use for output, if aCancel is set to true.
    * @param aOutCancel If set to true, the caller should cancel the operation
    *                   and use aOutText as the result.
    */
   nsresult WillOutputText(const nsAString* aInFormat, nsAString* aOutText,
                           uint32_t aFlags, bool* aOutCancel, bool* aHandled);
 
   /**
-   * Check for and replace a redundant trailing break.
-   */
-  MOZ_MUST_USE nsresult RemoveRedundantTrailingBR();
-
-  /**
    * Creates a trailing break in the text doc if there is not one already.
    */
   MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult CreateTrailingBRIfNeeded();
 
   /**
    * Creates a padding <br> element for empty editor if the root element has no
    * editable content.
    */
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -2160,16 +2160,59 @@ nsresult TextEditor::RemoveAttributeOrEq
 
   nsresult rv = RemoveAttributeWithTransaction(*aElement, *aAttribute);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return EditorBase::ToGenericNSResult(rv);
   }
   return NS_OK;
 }
 
+nsresult TextEditor::MaybeChangePaddingBRElementForEmptyEditor() {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+  MOZ_ASSERT(!AsHTMLEditor());
+
+  // If there is padding <br> element for empty editor, we have no work to do.
+  if (mPaddingBRElementForEmptyEditor) {
+    return NS_OK;
+  }
+
+  // Likewise, nothing to be done if we could never have inserted a trailing
+  // <br> element.
+  // XXX Why don't we use same path for <textarea> and <input>?
+  if (IsSingleLineEditor()) {
+    return NS_OK;
+  }
+
+  if (NS_WARN_IF(!mRootElement)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (mRootElement->GetChildCount() > 1) {
+    // The trailing br is redundant if it is the only remaining child node
+    return NS_OK;
+  }
+
+  RefPtr<HTMLBRElement> brElement =
+      HTMLBRElement::FromNodeOrNull(mRootElement->GetFirstChild());
+  if (!brElement ||
+      !EditorBase::IsPaddingBRElementForEmptyLastLine(*brElement)) {
+    // XXX Why don't we create new padding <br> element when there is no
+    //     children?
+    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);
+
+  return NS_OK;
+}
+
 nsresult TextEditor::SetUnmaskRangeInternal(uint32_t aStart, uint32_t aLength,
                                             uint32_t aTimeout, bool aNotify,
                                             bool aForceStartMasking) {
   mIsMaskingPassword = aForceStartMasking || aTimeout != 0;
 
   // We cannot manage multiple unmasked ranges so that shrink the previous
   // range first.
   if (!IsAllMasked()) {
--- a/editor/libeditor/TextEditor.h
+++ b/editor/libeditor/TextEditor.h
@@ -579,16 +579,23 @@ class TextEditor : public EditorBase,
       EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
   MOZ_CAN_RUN_SCRIPT
   virtual void OnEndHandlingTopLevelEditSubAction() override;
 
   void BeginEditorInit();
   MOZ_CAN_RUN_SCRIPT
   nsresult EndEditorInit();
 
+  /**
+   * If editor has a padding <br> element for empty last line but the editor
+   * is now empty, this method changes it to padding <br> element for empty
+   * editor.
+   */
+  nsresult MaybeChangePaddingBRElementForEmptyEditor();
+
  protected:  // Shouldn't be used by friend classes
   virtual ~TextEditor();
 
   int32_t WrapWidth() const { return mWrapColumn; }
 
   /**
    * Make the given selection span the entire document.
    */