Bug 1213589 part.1 Make ContentEventHandler::GetTextLength() and GetNativeTextLength() called only with a text node r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 02 Dec 2015 13:20:00 +0900
changeset 309282 cd5fdb842f905c8afccf35efa4dbb95d6981c675
parent 309281 76b3518b8c7a844a19f2c4d655218a273e226fbe
child 309283 d045e3b436223420edaf2933fb281d4f6cc464a3
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1213589
milestone45.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 1213589 part.1 Make ContentEventHandler::GetTextLength() and GetNativeTextLength() called only with a text node r=smaug
dom/events/ContentEventHandler.cpp
dom/events/ContentEventHandler.h
dom/events/IMEContentObserver.cpp
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -322,69 +322,81 @@ static uint32_t CountNewlinesInNativeLen
 
 /* static */ uint32_t
 ContentEventHandler::GetNativeTextLength(nsIContent* aContent,
                                          uint32_t aStartOffset,
                                          uint32_t aEndOffset)
 {
   MOZ_ASSERT(aEndOffset >= aStartOffset,
              "aEndOffset must be equals or larger than aStartOffset");
+  if (NS_WARN_IF(!aContent->IsNodeOfType(nsINode::eTEXT))) {
+    return 0;
+  }
   if (aStartOffset == aEndOffset) {
     return 0;
   }
   return GetTextLength(aContent, LINE_BREAK_TYPE_NATIVE, aEndOffset) -
            GetTextLength(aContent, LINE_BREAK_TYPE_NATIVE, aStartOffset);
 }
 
 /* static */ uint32_t
 ContentEventHandler::GetNativeTextLength(nsIContent* aContent,
                                          uint32_t aMaxLength)
 {
+  if (NS_WARN_IF(!aContent->IsNodeOfType(nsINode::eTEXT))) {
+    return 0;
+  }
   return GetTextLength(aContent, LINE_BREAK_TYPE_NATIVE, aMaxLength);
 }
 
-static inline uint32_t
-GetBRLength(LineBreakType aLineBreakType)
+/* static */ uint32_t
+ContentEventHandler::GetNativeTextLengthBefore(nsIContent* aContent)
+{
+  if (NS_WARN_IF(aContent->IsNodeOfType(nsINode::eTEXT))) {
+    return 0;
+  }
+  return IsContentBR(aContent) ? GetBRLength(LINE_BREAK_TYPE_NATIVE) : 0;
+}
+
+/* static inline */ uint32_t
+ContentEventHandler::GetBRLength(LineBreakType aLineBreakType)
 {
 #if defined(XP_WIN)
   // Length of \r\n
   return (aLineBreakType == LINE_BREAK_TYPE_NATIVE) ? 2 : 1;
 #else
   return 1;
 #endif
 }
 
 /* static */ uint32_t
 ContentEventHandler::GetTextLength(nsIContent* aContent,
                                    LineBreakType aLineBreakType,
                                    uint32_t aMaxLength)
 {
-  if (aContent->IsNodeOfType(nsINode::eTEXT)) {
-    uint32_t textLengthDifference =
+  MOZ_ASSERT(aContent->IsNodeOfType(nsINode::eTEXT));
+
+  uint32_t textLengthDifference =
 #if defined(XP_WIN)
-      // On Windows, the length of a native newline ("\r\n") is twice the length
-      // of the XP newline ("\n"), so XP length is equal to the length of the
-      // native offset plus the number of newlines encountered in the string.
-      (aLineBreakType == LINE_BREAK_TYPE_NATIVE) ?
-        CountNewlinesInXPLength(aContent, aMaxLength) : 0;
+    // On Windows, the length of a native newline ("\r\n") is twice the length
+    // of the XP newline ("\n"), so XP length is equal to the length of the
+    // native offset plus the number of newlines encountered in the string.
+    (aLineBreakType == LINE_BREAK_TYPE_NATIVE) ?
+      CountNewlinesInXPLength(aContent, aMaxLength) : 0;
 #else
-      // On other platforms, the native and XP newlines are the same.
-      0;
+    // On other platforms, the native and XP newlines are the same.
+    0;
 #endif
 
-    const nsTextFragment* text = aContent->GetText();
-    if (!text) {
-      return 0;
-    }
-    uint32_t length = std::min(text->GetLength(), aMaxLength);
-    return length + textLengthDifference;
-  } else if (IsContentBR(aContent)) {
-    return GetBRLength(aLineBreakType);
+  const nsTextFragment* text = aContent->GetText();
+  if (!text) {
+    return 0;
   }
-  return 0;
+  uint32_t length = std::min(text->GetLength(), aMaxLength);
+  return length + textLengthDifference;
 }
 
 static uint32_t ConvertToXPOffset(nsIContent* aContent, uint32_t aNativeOffset)
 {
 #if defined(XP_WIN)
   // On Windows, the length of a native newline ("\r\n") is twice the length of
   // the XP newline ("\n"), so XP offset is equal to the length of the native
   // offset minus the number of newlines encountered in the string.
@@ -455,29 +467,33 @@ AppendFontRange(nsTArray<FontRange>& aFo
 }
 
 /* static */ uint32_t
 ContentEventHandler::GetTextLengthInRange(nsIContent* aContent,
                                           uint32_t aXPStartOffset,
                                           uint32_t aXPEndOffset,
                                           LineBreakType aLineBreakType)
 {
+  MOZ_ASSERT(aContent->IsNodeOfType(nsINode::eTEXT));
+
   return aLineBreakType == LINE_BREAK_TYPE_NATIVE ?
     GetNativeTextLength(aContent, aXPStartOffset, aXPEndOffset) :
     aXPEndOffset - aXPStartOffset;
 }
 
 /* static */ void
 ContentEventHandler::AppendFontRanges(FontRangeArray& aFontRanges,
                                       nsIContent* aContent,
                                       int32_t aBaseOffset,
                                       int32_t aXPStartOffset,
                                       int32_t aXPEndOffset,
                                       LineBreakType aLineBreakType)
 {
+  MOZ_ASSERT(aContent->IsNodeOfType(nsINode::eTEXT));
+
   nsIFrame* frame = aContent->GetPrimaryFrame();
   if (!frame) {
     // It is a non-rendered content, create an empty range for it.
     AppendFontRange(aFontRanges, aBaseOffset);
     return;
   }
 
   int32_t baseOffset = aBaseOffset;
@@ -684,17 +700,20 @@ ContentEventHandler::SetRangeFromFlatTex
     if (!node) {
       break;
     }
     if (!node->IsNodeOfType(nsINode::eCONTENT)) {
       continue;
     }
     nsIContent* content = static_cast<nsIContent*>(node);
 
-    uint32_t textLength = GetTextLength(content, aLineBreakType);
+    uint32_t textLength =
+      content->IsNodeOfType(nsINode::eTEXT) ?
+        GetTextLength(content, aLineBreakType) :
+        (IsContentBR(content) ? GetBRLength(aLineBreakType) : 0);
     if (!textLength) {
       continue;
     }
 
     if (offset <= aOffset && aOffset < offset + textLength) {
       uint32_t xpOffset;
       if (!content->IsNodeOfType(nsINode::eTEXT)) {
         xpOffset = 0;
@@ -1438,23 +1457,17 @@ ContentEventHandler::GetFlatTextOffsetOf
     if (node->IsNodeOfType(nsINode::eTEXT)) {
       // Note: our range always starts from offset 0
       if (node == endNode) {
         *aOffset += GetTextLength(content, aLineBreakType, aNodeOffset);
       } else {
         *aOffset += GetTextLength(content, aLineBreakType);
       }
     } else if (IsContentBR(content)) {
-#if defined(XP_WIN)
-      // On Windows, the length of the newline is 2.
-      *aOffset += (aLineBreakType == LINE_BREAK_TYPE_NATIVE) ? 2 : 1;
-#else
-      // On other platforms, the length of the newline is 1.
-      *aOffset += 1;
-#endif
+      *aOffset += GetBRLength(aLineBreakType);
     }
   }
   return NS_OK;
 }
 
 /* static */ nsresult
 ContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
                                               nsRange* aRange,
--- a/dom/events/ContentEventHandler.h
+++ b/dom/events/ContentEventHandler.h
@@ -87,34 +87,40 @@ public:
                                            int32_t aNodeOffset,
                                            uint32_t* aOffset,
                                            LineBreakType aLineBreakType);
   static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
                                            nsRange* aRange,
                                            uint32_t* aOffset,
                                            LineBreakType aLineBreakType);
   // Computes the native text length between aStartOffset and aEndOffset of
-  // aContent.  Currently, this method supports only text node or br element
-  // for aContent.
+  // aContent.  aContent must be a text node.
   static uint32_t GetNativeTextLength(nsIContent* aContent,
                                       uint32_t aStartOffset,
                                       uint32_t aEndOffset);
-  // Get the native text length of a content node excluding any children
+  // Get the native text length of aContent.  aContent must be a text node.
   static uint32_t GetNativeTextLength(nsIContent* aContent,
                                       uint32_t aMaxLength = UINT32_MAX);
+  // Get the native text length which is inserted before aContent.
+  // aContent should be a <br> element for now.
+  static uint32_t GetNativeTextLengthBefore(nsIContent* aContent);
+
+protected:
+  // Get the text length of aContent.  aContent must be a text node.
+  static uint32_t GetTextLength(nsIContent* aContent,
+                                LineBreakType aLineBreakType,
+                                uint32_t aMaxLength = UINT32_MAX);
   // Get the text length of a given range of a content node in
   // the given line break type.
   static uint32_t GetTextLengthInRange(nsIContent* aContent,
                                        uint32_t aXPStartOffset,
                                        uint32_t aXPEndOffset,
                                        LineBreakType aLineBreakType);
-protected:
-  static uint32_t GetTextLength(nsIContent* aContent,
-                                LineBreakType aLineBreakType,
-                                uint32_t aMaxLength = UINT32_MAX);
+  // Get the line breaker length.
+  static inline uint32_t GetBRLength(LineBreakType aLineBreakType);
   static LineBreakType GetLineBreakType(WidgetQueryContentEvent* aEvent);
   static LineBreakType GetLineBreakType(WidgetSelectionEvent* aEvent);
   static LineBreakType GetLineBreakType(bool aUseNativeLineBreak);
   // Returns focused content (including its descendant documents).
   nsIContent* GetFocusedContent();
   // Returns true if the content is a plugin host.
   bool IsPlugin(nsIContent* aContent);
   // QueryContentRect() sets the rect of aContent's frame(s) to aEvent.
--- a/dom/events/IMEContentObserver.cpp
+++ b/dom/events/IMEContentObserver.cpp
@@ -1021,37 +1021,26 @@ IMEContentObserver::ContentRemoved(nsIDo
     return;
   }
 
   TextChangeData data(offset, offset + textLength, offset,
                       causedByComposition, IsEditorComposing());
   MaybeNotifyIMEOfTextChange(data);
 }
 
-static nsIContent*
-GetContentBR(dom::Element* aElement)
-{
-  if (!aElement->IsNodeOfType(nsINode::eCONTENT)) {
-    return nullptr;
-  }
-  nsIContent* content = static_cast<nsIContent*>(aElement);
-  return content->IsHTMLElement(nsGkAtoms::br) ? content : nullptr;
-}
-
 void
 IMEContentObserver::AttributeWillChange(nsIDocument* aDocument,
                                         dom::Element* aElement,
                                         int32_t aNameSpaceID,
                                         nsIAtom* aAttribute,
                                         int32_t aModType,
                                         const nsAttrValue* aNewValue)
 {
-  nsIContent *content = GetContentBR(aElement);
-  mPreAttrChangeLength = content ?
-    ContentEventHandler::GetNativeTextLength(content) : 0;
+  mPreAttrChangeLength =
+    ContentEventHandler::GetNativeTextLengthBefore(aElement);
 }
 
 void
 IMEContentObserver::AttributeChanged(nsIDocument* aDocument,
                                      dom::Element* aElement,
                                      int32_t aNameSpaceID,
                                      nsIAtom* aAttribute,
                                      int32_t aModType,
@@ -1061,29 +1050,24 @@ IMEContentObserver::AttributeChanged(nsI
   mStartOfRemovingTextRangeCache.Clear();
 
   bool causedByComposition = IsEditorHandlingEventForComposition();
   if (!mTextChangeData.IsValid() && causedByComposition &&
       !mUpdatePreference.WantChangesCausedByComposition()) {
     return;
   }
 
-  nsIContent *content = GetContentBR(aElement);
-  if (!content) {
-    return;
-  }
-
   uint32_t postAttrChangeLength =
-    ContentEventHandler::GetNativeTextLength(content);
+    ContentEventHandler::GetNativeTextLengthBefore(aElement);
   if (postAttrChangeLength == mPreAttrChangeLength) {
     return;
   }
   uint32_t start;
   nsresult rv =
-    ContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, content,
+    ContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, aElement,
                                                   0, &start,
                                                   LINE_BREAK_TYPE_NATIVE);
   NS_ENSURE_SUCCESS_VOID(rv);
 
   TextChangeData data(start, start + mPreAttrChangeLength,
                       start + postAttrChangeLength, causedByComposition,
                       IsEditorComposing());
   MaybeNotifyIMEOfTextChange(data);