Bug 1482019 - part 2: Make HTMLEditor::GetSelectedNode() take nsAtom* for element name r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 10 Aug 2018 17:30:04 +0900
changeset 431873 40fbaeccbd895386d7f64ba330608576d2296cef
parent 431872 9b46ca68f3b0fa45e59cc39e5e922fbb0858d105
child 431874 f6053ad1d49aa8924c4ede25f0247c9c2a86d607
push id34451
push userebalazs@mozilla.com
push dateThu, 16 Aug 2018 09:25:15 +0000
treeherdermozilla-central@161817e6d127 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1482019
milestone63.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 1482019 - part 2: Make HTMLEditor::GetSelectedNode() take nsAtom* for element name r=m_kato Using nsAtom makes the method faster and simpler, although the caller needs to atomize lower-cased string.
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -71,29 +71,53 @@
 
 namespace mozilla {
 
 using namespace dom;
 using namespace widget;
 
 const char16_t kNBSP = 160;
 
+static already_AddRefed<nsAtom>
+GetLowerCaseNameAtom(const nsAString& aTagName)
+{
+  if (aTagName.IsEmpty()) {
+    return nullptr;
+  }
+  nsAutoString lowerTagName;
+  nsContentUtils::ASCIIToLower(aTagName, lowerTagName);
+  return NS_Atomize(lowerTagName);
+}
+
 // Some utilities to handle overloading of "A" tag for link and named anchor.
 static bool
 IsLinkTag(const nsString& s)
 {
   return s.EqualsIgnoreCase("href");
 }
 
 static bool
+IsLinkTag(const nsAtom& aTagName)
+{
+  return aTagName.Equals(NS_LITERAL_STRING("href"));
+}
+
+static bool
 IsNamedAnchorTag(const nsString& s)
 {
   return s.EqualsIgnoreCase("anchor") || s.EqualsIgnoreCase("namedanchor");
 }
 
+static bool
+IsNamedAnchorTag(const nsAtom& aTagName)
+{
+  return aTagName.Equals(NS_LITERAL_STRING("anchor")) ||
+         aTagName.Equals(NS_LITERAL_STRING("namedanchor"));
+}
+
 template EditorDOMPoint
 HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
               nsIContent& aNode,
               const EditorDOMPoint& aPointToInsert,
               SplitAtEdges aSplitAtEdges);
 template EditorDOMPoint
 HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
               nsIContent& aNode,
@@ -2612,40 +2636,38 @@ HTMLEditor::GetSelectedElement(const nsA
   *aReturn = nullptr;
 
   RefPtr<Selection> selection = GetSelection();
   if (NS_WARN_IF(!selection)) {
     return NS_ERROR_FAILURE;
   }
 
   ErrorResult error;
-  RefPtr<nsINode> selectedNode = GetSelectedNode(*selection, aTagName, error);
+  RefPtr<nsAtom> tagName = GetLowerCaseNameAtom(aTagName);
+  RefPtr<nsINode> selectedNode = GetSelectedNode(*selection, tagName, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   selectedNode.forget(aReturn);
   return NS_OK;
 }
 
 already_AddRefed<nsINode>
 HTMLEditor::GetSelectedNode(Selection& aSelection,
-                            const nsAString& aTagName,
+                            const nsAtom* aTagName,
                             ErrorResult& aRv)
 {
   MOZ_ASSERT(!aRv.Failed());
 
   bool isCollapsed = aSelection.IsCollapsed();
 
-  nsAutoString domTagName;
-  nsAutoString TagName(aTagName);
-  ToLowerCase(TagName);
-  // Empty string indicates we should match any element tag
-  bool anyTag = (TagName.IsEmpty());
-  bool isLinkTag = IsLinkTag(TagName);
-  bool isNamedAnchorTag = IsNamedAnchorTag(TagName);
+  // nullptr indicates we should look for any element.
+  bool anyTag = !aTagName;
+  bool isLinkTag = aTagName && IsLinkTag(*aTagName);
+  bool isNamedAnchorTag = aTagName && IsNamedAnchorTag(*aTagName);
 
   RefPtr<nsRange> range = aSelection.GetRangeAt(0);
   if (NS_WARN_IF(!range)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsCOMPtr<nsINode> startContainer = range->GetStartContainer();
@@ -2654,21 +2676,18 @@ HTMLEditor::GetSelectedNode(Selection& a
   nsCOMPtr<nsINode> endContainer = range->GetEndContainer();
   nsIContent* endNode = range->GetChildAtEndOffset();
 
   // Optimization for a single selected element
   if (startContainer && startContainer == endContainer &&
       startNode && endNode && startNode->GetNextSibling() == endNode) {
     nsCOMPtr<nsINode> selectedNode = startNode;
     if (selectedNode) {
-      domTagName = selectedNode->NodeName();
-      ToLowerCase(domTagName);
-
       // Test for appropriate node type requested
-      if (anyTag || (TagName == domTagName) ||
+      if (anyTag || aTagName == selectedNode->NodeInfo()->NameAtom() ||
           (isLinkTag && HTMLEditUtils::IsLink(selectedNode)) ||
           (isNamedAnchorTag && HTMLEditUtils::IsNamedAnchor(selectedNode))) {
         return selectedNode.forget();
       }
     }
   }
 
   bool bNodeFound = false;
@@ -2723,49 +2742,49 @@ HTMLEditor::GetSelectedNode(Selection& a
       nsCOMPtr<nsIContentIterator> iter =
         do_CreateInstance("@mozilla.org/content/post-content-iterator;1",
                           &rv);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         aRv.Throw(rv);
         return nullptr;
       }
 
+      const nsAtom* tagNameLookingFor = aTagName;
       iter->Init(currange);
       // loop through the content iterator for each content node
       while (!iter->IsDone()) {
         // Query interface to cast nsIContent to Element
         //  then get tagType to compare to  aTagName
         // Clone node of each desired type and append it to the aDomFrag
         selectedElement = Element::FromNodeOrNull(iter->GetCurrentNode());
         if (selectedElement) {
           // If we already found a node, then we have another element,
           //  thus there's not just one element selected
           if (bNodeFound) {
             bNodeFound = false;
             break;
           }
 
-          domTagName = selectedElement->NodeName();
-          ToLowerCase(domTagName);
-
           if (anyTag) {
             // Get name of first selected element
-            selectedElement->GetTagName(TagName);
-            ToLowerCase(TagName);
+            tagNameLookingFor = selectedElement->NodeInfo()->NameAtom();
             anyTag = false;
           }
 
           // The "A" tag is a pain,
           //  used for both link(href is set) and "Named Anchor"
           if ((isLinkTag &&
                HTMLEditUtils::IsLink(selectedElement)) ||
               (isNamedAnchorTag &&
                HTMLEditUtils::IsNamedAnchor(selectedElement))) {
             bNodeFound = true;
-          } else if (TagName == domTagName) { // All other tag names are handled here
+          }
+          // All other tag names are handled here.
+          else if (tagNameLookingFor ==
+                     selectedElement->NodeInfo()->NameAtom()) {
             bNodeFound = true;
           }
           if (!bNodeFound) {
             // Check if node we have is really part of the selection???
             break;
           }
         }
         iter->Next();
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -814,23 +814,29 @@ protected: // Shouldn't be used by frien
    *     4-1. When first element node does *not* match with the argument,
    *          *returns* the element.
    *     4-2. When first element node matches with the argument, returns
    *          *next* element node.
    * XXX This may return non-element node in some cases.  Perhaps, it's a
    *     bug.
    *
    * @param aSelection          The Selection.
-   * @param aTagName            The name of element which you looking for.
+   * @param aTagName            The atom of tag name in lower case.
+   *                            If nullptr, look for any element node.
+   *                            If nsGkAtoms::href, look for an <a> element
+   *                            which has non-empty href attribute.
+   *                            If nsGkAtoms::anchor or atomized "namedanchor",
+   *                            look for an <a> element which has non-empty
+   *                            name attribute.
    * @param aRv                 Returns error code.
    * @return                    An element in first range of aSelection.
    */
   already_AddRefed<nsINode>
   GetSelectedNode(Selection& aSelection,
-                  const nsAString& aTagName,
+                  const nsAtom* aTagName,
                   ErrorResult& aRv);
 
   /**
    * PasteInternal() pasts text with replacing selected content.
    * This tries to dispatch ePaste event first.  If its defaultPrevent() is
    * called, this does nothing but returns NS_OK.
    *
    * @param aClipboardType  nsIClipboard::kGlobalClipboard or