Bug 751323 - Cleanup nsHTMLEditRules::RemoveEmptyNodes(); r=ehsan
authorMs2ger <ms2ger@gmail.com>
Sat, 05 May 2012 11:00:06 +0200
changeset 93256 896a6869b2d363df821d44b0266cdcb1b697a455
parent 93255 9469025cf2f8c7f33ad6098dfb7cf49cc6f0c285
child 93257 ba92a52a645e3fd60f4306c94bbad801fff7be36
push id22617
push userMs2ger@gmail.com
push dateSat, 05 May 2012 09:01:38 +0000
treeherdermozilla-central@5b9ee59e6e60 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs751323
milestone15.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 751323 - Cleanup nsHTMLEditRules::RemoveEmptyNodes(); r=ehsan
content/base/src/nsGkAtomList.h
editor/libeditor/html/nsHTMLEditRules.cpp
editor/libeditor/html/nsHTMLEditRules.h
editor/libeditor/html/nsHTMLEditUtils.cpp
editor/libeditor/html/nsHTMLEditUtils.h
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -66,16 +66,17 @@ GK_ATOM(moz, "_moz")
 GK_ATOM(mozallowfullscreen, "mozallowfullscreen")
 GK_ATOM(moztype, "_moz-type")
 GK_ATOM(mozdirty, "_moz_dirty")
 GK_ATOM(mozdonotsend, "moz-do-not-send")
 GK_ATOM(mozeditorbogusnode, "_moz_editor_bogus_node")
 GK_ATOM(mozgeneratedcontentbefore, "_moz_generated_content_before")
 GK_ATOM(mozgeneratedcontentafter, "_moz_generated_content_after")
 GK_ATOM(mozgeneratedcontentimage, "_moz_generated_content_image")
+GK_ATOM(mozquote, "_moz_quote")
 GK_ATOM(_moz_original_size, "_moz_original_size")
 GK_ATOM(_moz_target, "_moz_target")
 GK_ATOM(_moz_type, "_moz-type")
 GK_ATOM(menuactive, "_moz-menuactive")
 GK_ATOM(_poundDefault, "#default")
 GK_ATOM(_asterix, "*")
 GK_ATOM(a, "a")
 GK_ATOM(abbr, "abbr")
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -7927,20 +7927,16 @@ nsHTMLEditRules::InDifferentTableElement
   
   return NS_OK;
 }
 
 
 nsresult 
 nsHTMLEditRules::RemoveEmptyNodes()
 {
-  nsCOMArray<nsIDOMNode> arrayOfEmptyNodes, arrayOfEmptyCites;
-  nsCOMPtr<nsISupports> isupports;
-  PRInt32 nodeCount,j;
-  
   // some general notes on the algorithm used here: the goal is to examine all the
   // nodes in mDocChangeRange, and remove the empty ones.  We do this by using a
   // content iterator to traverse all the nodes in the range, and placing the empty
   // nodes into an array.  After finishing the iteration, we delete the empty nodes
   // in the array.  (they cannot be deleted as we find them becasue that would 
   // invalidate the iterator.)  
   // Since checking to see if a node is empty can be costly for nodes with many
   // descendants, there are some optimizations made.  I rely on the fact that the
@@ -7961,119 +7957,105 @@ nsHTMLEditRules::RemoveEmptyNodes()
   // need an iterator
   nsCOMPtr<nsIContentIterator> iter =
                   do_CreateInstance("@mozilla.org/content/post-content-iterator;1");
   NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER);
   
   nsresult res = iter->Init(mDocChangeRange);
   NS_ENSURE_SUCCESS(res, res);
   
-  nsTArray<nsIDOMNode*> skipList;
+  nsCOMArray<nsINode> arrayOfEmptyNodes, arrayOfEmptyCites;
+  nsTArray<nsINode*> skipList;
 
   // check for empty nodes
-  while (!iter->IsDone())
-  {
-    nsCOMPtr<nsIDOMNode> node, parent;
-
-    node = do_QueryInterface(iter->GetCurrentNode());
+  while (!iter->IsDone()) {
+    nsINode* node = iter->GetCurrentNode();
     NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
-    node->GetParentNode(getter_AddRefs(parent));
+    nsINode* parent = node->GetNodeParent();
     
     PRUint32 idx = skipList.IndexOf(node);
-    if (idx != skipList.NoIndex)
-    {
+    if (idx != skipList.NoIndex) {
       // this node is on our skip list.  Skip processing for this node, 
       // and replace its value in the skip list with the value of its parent
       skipList[idx] = parent;
-    }
-    else
-    {
+    } else {
       bool bIsCandidate = false;
       bool bIsEmptyNode = false;
       bool bIsMailCite = false;
 
-      // don't delete the body
-      if (!nsTextEditUtils::IsBody(node))
-      {
-        // only consider certain nodes to be empty for purposes of removal
-        if (  (bIsMailCite = nsHTMLEditUtils::IsMailCite(node))  ||
-              nsEditor::NodeIsType(node, nsEditProperty::a)      ||
-              nsHTMLEditUtils::IsInlineStyle(node)               ||
-              nsHTMLEditUtils::IsList(node)                      ||
-              nsHTMLEditUtils::IsDiv(node)  )
-        {
+      if (node->IsElement()) {
+        dom::Element* element = node->AsElement();
+        if (element->IsHTML(nsGkAtoms::body)) {
+          // don't delete the body
+        } else if ((bIsMailCite = nsHTMLEditUtils::IsMailCite(element))  ||
+                   element->IsHTML(nsGkAtoms::a)                         ||
+                   nsHTMLEditUtils::IsInlineStyle(element)               ||
+                   nsHTMLEditUtils::IsList(element)                      ||
+                   element->IsHTML(nsGkAtoms::div)) {
+          // only consider certain nodes to be empty for purposes of removal
           bIsCandidate = true;
-        }
-        // these node types are candidates if selection is not in them
-        else if (nsHTMLEditUtils::IsFormatNode(node) ||
-            nsHTMLEditUtils::IsListItem(node)  ||
-            nsHTMLEditUtils::IsBlockquote(node) )
-        {
+        } else if (nsHTMLEditUtils::IsFormatNode(element) ||
+                   nsHTMLEditUtils::IsListItem(element)   ||
+                   element->IsHTML(nsGkAtoms::blockquote)) {
+          // these node types are candidates if selection is not in them
           // if it is one of these, don't delete if selection inside.
           // this is so we can create empty headings, etc, for the
           // user to type into.
           bool bIsSelInNode;
           res = SelectionEndpointInNode(node, &bIsSelInNode);
           NS_ENSURE_SUCCESS(res, res);
           if (!bIsSelInNode)
           {
             bIsCandidate = true;
           }
         }
       }
       
-      if (bIsCandidate)
-      {
-        if (bIsMailCite)  // we delete mailcites even if they have a solo br in them
-          res = mHTMLEditor->IsEmptyNode(node, &bIsEmptyNode, true, true);  
-        else  // other nodes we require to be empty
-          res = mHTMLEditor->IsEmptyNode(node, &bIsEmptyNode, false, true);
+      if (bIsCandidate) {
+        // we delete mailcites even if they have a solo br in them
+        // other nodes we require to be empty
+        res = mHTMLEditor->IsEmptyNode(node->AsDOMNode(), &bIsEmptyNode,
+                                       bIsMailCite, true);
         NS_ENSURE_SUCCESS(res, res);
-        if (bIsEmptyNode)
-        {
-          if (bIsMailCite)  // mailcites go on a separate list from other empty nodes
-          {
+        if (bIsEmptyNode) {
+          if (bIsMailCite) {
+            // mailcites go on a separate list from other empty nodes
             arrayOfEmptyCites.AppendObject(node);
-          }
-          else
-          {
+          } else {
             arrayOfEmptyNodes.AppendObject(node);
           }
         }
       }
       
-      if (!bIsEmptyNode)
-      {
+      if (!bIsEmptyNode) {
         // put parent on skip list
         skipList.AppendElement(parent);
       }
     }
 
     iter->Next();
   }
   
   // now delete the empty nodes
-  nodeCount = arrayOfEmptyNodes.Count();
-  for (j = 0; j < nodeCount; j++)
-  {
-    nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyNodes[0];
+  PRInt32 nodeCount = arrayOfEmptyNodes.Count();
+  for (PRInt32 j = 0; j < nodeCount; j++) {
+    nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyNodes[0]->AsDOMNode();
     arrayOfEmptyNodes.RemoveObjectAt(0);
     if (mHTMLEditor->IsModifiableNode(delNode)) {
       res = mHTMLEditor->DeleteNode(delNode);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   
   // now delete the empty mailcites
   // this is a separate step because we want to pull out any br's and preserve them.
   nodeCount = arrayOfEmptyCites.Count();
-  for (j = 0; j < nodeCount; j++)
-  {
-    nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyCites[0];
+  for (PRInt32 j = 0; j < nodeCount; j++) {
+    nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyCites[0]->AsDOMNode();
     arrayOfEmptyCites.RemoveObjectAt(0);
     bool bIsEmptyNode;
     res = mHTMLEditor->IsEmptyNode(delNode, &bIsEmptyNode, false, true);
     NS_ENSURE_SUCCESS(res, res);
     if (!bIsEmptyNode)
     {
       // we are deleting a cite that has just a br.  We want to delete cite, 
       // but preserve br.
@@ -8087,19 +8069,21 @@ nsHTMLEditRules::RemoveEmptyNodes()
     res = mHTMLEditor->DeleteNode(delNode);
     NS_ENSURE_SUCCESS(res, res);
   }
   
   return res;
 }
 
 nsresult
-nsHTMLEditRules::SelectionEndpointInNode(nsIDOMNode *aNode, bool *aResult)
+nsHTMLEditRules::SelectionEndpointInNode(nsINode* aNode, bool* aResult)
 {
   NS_ENSURE_TRUE(aNode && aResult, NS_ERROR_NULL_POINTER);
+
+  nsIDOMNode* node = aNode->AsDOMNode();
   
   *aResult = false;
   
   nsCOMPtr<nsISelection>selection;
   nsresult res = mHTMLEditor->GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(res, res);
   nsCOMPtr<nsISelectionPrivate>selPriv(do_QueryInterface(selection));
   
@@ -8115,38 +8099,34 @@ nsHTMLEditRules::SelectionEndpointInNode
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(currentItem, NS_ERROR_UNEXPECTED);
 
     nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
     nsCOMPtr<nsIDOMNode> startParent, endParent;
     range->GetStartContainer(getter_AddRefs(startParent));
     if (startParent)
     {
-      if (aNode == startParent)
-      {
+      if (node == startParent) {
         *aResult = true;
         return NS_OK;
       }
-      if (nsEditorUtils::IsDescendantOf(startParent, aNode)) 
-      {
+      if (nsEditorUtils::IsDescendantOf(startParent, node)) {
         *aResult = true;
         return NS_OK;
       }
     }
     range->GetEndContainer(getter_AddRefs(endParent));
     if (startParent == endParent) continue;
     if (endParent)
     {
-      if (aNode == endParent) 
-      {
+      if (node == endParent) {
         *aResult = true;
         return NS_OK;
       }
-      if (nsEditorUtils::IsDescendantOf(endParent, aNode))
-      {
+      if (nsEditorUtils::IsDescendantOf(endParent, node)) {
         *aResult = true;
         return NS_OK;
       }
     }
   }
   return res;
 }
 
--- a/editor/libeditor/html/nsHTMLEditRules.h
+++ b/editor/libeditor/html/nsHTMLEditRules.h
@@ -285,17 +285,17 @@ protected:
   nsresult CheckInterlinePosition(nsISelection *aSelection);
   nsresult AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection aAction);
   nsresult FindNearSelectableNode(nsIDOMNode *aSelNode, 
                                   PRInt32 aSelOffset, 
                                   nsIEditor::EDirection &aDirection,
                                   nsCOMPtr<nsIDOMNode> *outSelectableNode);
   nsresult InDifferentTableElements(nsIDOMNode *aNode1, nsIDOMNode *aNode2, bool *aResult);
   nsresult RemoveEmptyNodes();
-  nsresult SelectionEndpointInNode(nsIDOMNode *aNode, bool *aResult);
+  nsresult SelectionEndpointInNode(nsINode *aNode, bool *aResult);
   nsresult UpdateDocChangeRange(nsIDOMRange *aRange);
   nsresult ConfirmSelectionInBody();
   nsresult InsertMozBRIfNeeded(nsIDOMNode *aNode);
   bool     IsEmptyInline(nsIDOMNode *aNode);
   bool     ListIsEmptyLine(nsCOMArray<nsIDOMNode> &arrayOfNodes);
   nsresult RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignType, bool aChildrenOnly);
   nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, bool aStarts);
   nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly);
--- a/editor/libeditor/html/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/html/nsHTMLEditUtils.cpp
@@ -67,17 +67,25 @@ nsHTMLEditUtils::IsBig(nsIDOMNode *node)
 
 ///////////////////////////////////////////////////////////////////////////
 // IsInlineStyle true if node is an inline style
 //                  
 bool 
 nsHTMLEditUtils::IsInlineStyle(nsIDOMNode *node)
 {
   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsInlineStyle");
-  nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
+  nsCOMPtr<dom::Element> element = do_QueryInterface(node);
+  return element && IsInlineStyle(element);
+}
+
+bool
+nsHTMLEditUtils::IsInlineStyle(dom::Element* aElement)
+{
+  MOZ_ASSERT(aElement);
+  nsIAtom* nodeAtom = aElement->Tag();
   return (nodeAtom == nsEditProperty::b)
       || (nodeAtom == nsEditProperty::i)
       || (nodeAtom == nsEditProperty::u)
       || (nodeAtom == nsEditProperty::tt)
       || (nodeAtom == nsEditProperty::s)
       || (nodeAtom == nsEditProperty::strike)
       || (nodeAtom == nsEditProperty::big)
       || (nodeAtom == nsEditProperty::small)
@@ -89,17 +97,25 @@ nsHTMLEditUtils::IsInlineStyle(nsIDOMNod
 
 ///////////////////////////////////////////////////////////////////////////
 // IsFormatNode true if node is a format node
 // 
 bool
 nsHTMLEditUtils::IsFormatNode(nsIDOMNode *node)
 {
   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsFormatNode");
-  nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
+  nsCOMPtr<dom::Element> element = do_QueryInterface(node);
+  return element && IsFormatNode(element);
+}
+
+bool
+nsHTMLEditUtils::IsFormatNode(dom::Element* aElement)
+{
+  MOZ_ASSERT(aElement);
+  nsIAtom* nodeAtom = aElement->Tag();
   return (nodeAtom == nsEditProperty::p)
       || (nodeAtom == nsEditProperty::pre)
       || (nodeAtom == nsEditProperty::h1)
       || (nodeAtom == nsEditProperty::h2)
       || (nodeAtom == nsEditProperty::h3)
       || (nodeAtom == nsEditProperty::h4)
       || (nodeAtom == nsEditProperty::h5)
       || (nodeAtom == nsEditProperty::h6)
@@ -418,44 +434,39 @@ nsHTMLEditUtils::IsMozDiv(nsIDOMNode *no
   return false;
 }
 
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsMailCite: true if node an html blockquote with type=cite
 //                  
-bool 
-nsHTMLEditUtils::IsMailCite(nsIDOMNode *node)
+bool
+nsHTMLEditUtils::IsMailCite(nsIDOMNode* aNode)
 {
-  NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsMailCite");
-  nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
-  if (!elem) {
-    return false;
-  }
-  nsAutoString attrName (NS_LITERAL_STRING("type")); 
-  
+  NS_PRECONDITION(aNode, "null parent passed to nsHTMLEditUtils::IsMailCite");
+  nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
+  return element && IsMailCite(element);
+}
+
+bool
+nsHTMLEditUtils::IsMailCite(dom::Element* aElement)
+{
+  MOZ_ASSERT(aElement);
+
   // don't ask me why, but our html mailcites are id'd by "type=cite"...
-  nsAutoString attrVal;
-  nsresult res = elem->GetAttribute(attrName, attrVal);
-  ToLowerCase(attrVal);
-  if (NS_SUCCEEDED(res))
-  {
-    if (attrVal.EqualsLiteral("cite"))
-      return true;
+  if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            NS_LITERAL_STRING("cite"), eIgnoreCase)) {
+    return true;
   }
 
   // ... but our plaintext mailcites by "_moz_quote=true".  go figure.
-  attrName.AssignLiteral("_moz_quote");
-  res = elem->GetAttribute(attrName, attrVal);
-  if (NS_SUCCEEDED(res))
-  {
-    ToLowerCase(attrVal);
-    if (attrVal.EqualsLiteral("true"))
-      return true;
+  if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozquote,
+                            NS_LITERAL_STRING("true"), eIgnoreCase)) {
+    return true;
   }
 
   return false;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsFormWidget: true if node is a form widget of some kind
--- a/editor/libeditor/html/nsHTMLEditUtils.h
+++ b/editor/libeditor/html/nsHTMLEditUtils.h
@@ -51,17 +51,19 @@ class nsIDOMNode;
 class nsHTMLEditUtils
 {
 public:
   // from nsTextEditRules:
   static bool IsBig(nsIDOMNode *aNode);
   static bool IsSmall(nsIDOMNode *aNode);
 
   // from nsHTMLEditRules:
+  static bool IsInlineStyle(mozilla::dom::Element* aNode);
   static bool IsInlineStyle(nsIDOMNode *aNode);
+  static bool IsFormatNode(mozilla::dom::Element* aNode);
   static bool IsFormatNode(nsIDOMNode *aNode);
   static bool IsNodeThatCanOutdent(nsIDOMNode *aNode);
   static bool IsHeader(nsIDOMNode *aNode);
   static bool IsParagraph(nsIDOMNode *aNode);
   static bool IsHR(nsIDOMNode *aNode);
   static bool IsListItem(mozilla::dom::Element* aNode);
   static bool IsListItem(nsIDOMNode *aNode);
   static bool IsTable(nsIDOMNode *aNode);
@@ -80,16 +82,17 @@ public:
   static bool IsPre(nsIDOMNode *aNode);
   static bool IsAnchor(nsIDOMNode *aNode);
   static bool IsImage(nsIDOMNode *aNode);
   static bool IsLink(nsIDOMNode *aNode);
   static bool IsNamedAnchor(mozilla::dom::Element* aNode);
   static bool IsNamedAnchor(nsIDOMNode *aNode);
   static bool IsDiv(nsIDOMNode *aNode);
   static bool IsMozDiv(nsIDOMNode *aNode);
+  static bool IsMailCite(mozilla::dom::Element* aNode);
   static bool IsMailCite(nsIDOMNode *aNode);
   static bool IsFormWidget(mozilla::dom::Element* aNode);
   static bool IsFormWidget(nsIDOMNode *aNode);
   static bool SupportsAlignAttr(nsIDOMNode *aNode);
   static bool CanContain(PRInt32 aParent, PRInt32 aChild);
   static bool IsContainer(PRInt32 aTag);
 };