Bug 1156062 part 9 - Clean up nsHTMLEditRules::WillAlign
☠☠ backed out by 2102e672350f ☠ ☠
authorAryeh Gregor <ayg@aryeh.name>
Sat, 23 Apr 2016 19:22:48 +0900
changeset 332516 1e142031ab51ed18a6526766707151fdc9e8ed71
parent 332515 9e0cca233833e1cd574e7d73dcfa9d341c8b5e83
child 332517 a530f2e280a48ff03ffb45c0bb0eb5fedb26b2a0
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1156062
milestone48.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 1156062 part 9 - Clean up nsHTMLEditRules::WillAlign
editor/libeditor/nsHTMLEditRules.cpp
editor/libeditor/nsHTMLEditRules.h
editor/libeditor/nsHTMLEditUtils.cpp
editor/libeditor/nsHTMLEditUtils.h
--- a/editor/libeditor/nsHTMLEditRules.cpp
+++ b/editor/libeditor/nsHTMLEditRules.cpp
@@ -130,17 +130,17 @@ class nsBRNodeFunctor : public nsBoolDom
 class nsEmptyEditableFunctor : public nsBoolDomIterFunctor
 {
   public:
     explicit nsEmptyEditableFunctor(nsHTMLEditor* editor) : mHTMLEditor(editor) {}
     virtual bool operator()(nsINode* aNode) const
     {
       if (mHTMLEditor->IsEditable(aNode) &&
           (nsHTMLEditUtils::IsListItem(aNode) ||
-           nsHTMLEditUtils::IsTableCellOrCaption(GetAsDOMNode(aNode)))) {
+           nsHTMLEditUtils::IsTableCellOrCaption(*aNode))) {
         bool bIsEmptyNode;
         nsresult res = mHTMLEditor->IsEmptyNode(aNode, &bIsEmptyNode, false, false);
         NS_ENSURE_SUCCESS(res, false);
         if (bIsEmptyNode)
           return true;
       }
       return false;
     }
@@ -646,17 +646,17 @@ nsHTMLEditRules::WillDoAction(Selection*
       return WillIndent(aSelection, aCancel, aHandled);
     case EditAction::outdent:
       return WillOutdent(aSelection, aCancel, aHandled);
     case EditAction::setAbsolutePosition:
       return WillAbsolutePosition(aSelection, aCancel, aHandled);
     case EditAction::removeAbsolutePosition:
       return WillRemoveAbsolutePosition(aSelection, aCancel, aHandled);
     case EditAction::align:
-      return WillAlign(aSelection, info->alignType, aCancel, aHandled);
+      return WillAlign(*aSelection, *info->alignType, aCancel, aHandled);
     case EditAction::makeBasicBlock:
       return WillMakeBasicBlock(aSelection, info->blockType, aCancel, aHandled);
     case EditAction::removeList:
       return WillRemoveList(aSelection, info->bOrdered, aCancel, aHandled);
     case EditAction::makeDefListItem:
       return WillMakeDefListItem(aSelection, info->blockType, info->entireList,
                                  aCancel, aHandled);
     case EditAction::insertElement:
@@ -4596,249 +4596,228 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode
 
   NS_ENSURE_TRUE(nodeToTest, NS_ERROR_NULL_POINTER);
   return mHTMLEditor->IsEmptyNode(nodeToTest, outIsEmptyBlock,
                      aMozBRDoesntCount, aListItemsNotEmpty);
 }
 
 
 nsresult
-nsHTMLEditRules::WillAlign(Selection* aSelection,
-                           const nsAString *alignType,
-                           bool *aCancel,
-                           bool *aHandled)
-{
-  if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
-
-  WillInsert(*aSelection, aCancel);
-
-  // initialize out param
-  // we want to ignore result of WillInsert()
+nsHTMLEditRules::WillAlign(Selection& aSelection,
+                           const nsAString& aAlignType,
+                           bool* aCancel,
+                           bool* aHandled)
+{
+  MOZ_ASSERT(aCancel && aHandled);
+
+  NS_ENSURE_STATE(mHTMLEditor);
+  nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
+
+  WillInsert(aSelection, aCancel);
+
+  // Initialize out param.  We want to ignore result of WillInsert().
   *aCancel = false;
   *aHandled = false;
 
-  nsresult res = NormalizeSelection(aSelection);
-  NS_ENSURE_SUCCESS(res, res);
-  nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
-
-  // convert the selection ranges into "promoted" selection ranges:
-  // this basically just expands the range to include the immediate
-  // block parent, and then further expands to include any ancestors
-  // whose children are all in the range
+  nsresult rv = NormalizeSelection(&aSelection);
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsAutoSelectionReset selectionResetter(&aSelection, mHTMLEditor);
+
+  // Convert the selection ranges into "promoted" selection ranges: This
+  // basically just expands the range to include the immediate block parent,
+  // and then further expands to include any ancestors whose children are all
+  // in the range
   *aHandled = true;
   nsTArray<OwningNonNull<nsINode>> nodeArray;
-  res = GetNodesFromSelection(*aSelection, EditAction::align, nodeArray);
-  NS_ENSURE_SUCCESS(res, res);
-
-  // if we don't have any nodes, or we have only a single br, then we are
-  // creating an empty alignment div.  We have to do some different things for these.
-  bool emptyDiv = false;
-  int32_t listCount = nodeArray.Length();
-  if (!listCount) emptyDiv = true;
-  if (listCount == 1)
-  {
-    OwningNonNull<nsINode> theNode = nodeArray[0];
-
-    if (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(theNode))) {
-      // the node is a table element, an horiz rule, a paragraph, a div
-      // or a section header; in HTML 4, it can directly carry the ALIGN
-      // attribute and we don't need to make a div! If we are in CSS mode,
-      // all the work is done in AlignBlock
-      nsCOMPtr<nsIDOMElement> theElem = do_QueryInterface(theNode);
-      res = AlignBlock(theElem, alignType, true);
-      NS_ENSURE_SUCCESS(res, res);
+  rv = GetNodesFromSelection(aSelection, EditAction::align, nodeArray);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // If we don't have any nodes, or we have only a single br, then we are
+  // creating an empty alignment div.  We have to do some different things for
+  // these.
+  bool emptyDiv = nodeArray.IsEmpty();
+  if (nodeArray.Length() == 1) {
+    OwningNonNull<nsINode> node = nodeArray[0];
+
+    if (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(node))) {
+      // The node is a table element, an hr, a paragraph, a div or a section
+      // header; in HTML 4, it can directly carry the ALIGN attribute and we
+      // don't need to make a div! If we are in CSS mode, all the work is done
+      // in AlignBlock
+      rv = AlignBlock(static_cast<nsIDOMElement*>(node->AsDOMNode()),
+                       &aAlignType, true);
+      NS_ENSURE_SUCCESS(rv, rv);
       return NS_OK;
     }
 
-    if (nsTextEditUtils::IsBreak(theNode))
-    {
-      // The special case emptyDiv code (below) that consumes BRs can
-      // cause tables to split if the start node of the selection is
-      // not in a table cell or caption, for example parent is a <tr>.
-      // Avoid this unnecessary splitting if possible by leaving emptyDiv
-      // FALSE so that we fall through to the normal case alignment code.
+    if (nsTextEditUtils::IsBreak(node)) {
+      // The special case emptyDiv code (below) that consumes BRs can cause
+      // tables to split if the start node of the selection is not in a table
+      // cell or caption, for example parent is a <tr>.  Avoid this unnecessary
+      // splitting if possible by leaving emptyDiv FALSE so that we fall
+      // through to the normal case alignment code.
       //
-      // XXX: It seems a little error prone for the emptyDiv special
-      //      case code to assume that the start node of the selection
-      //      is the parent of the single node in the nodeArray, as
-      //      the paragraph above points out. Do we rely on the selection
-      //      start node because of the fact that nodeArray can be empty?
-      //      We should probably revisit this issue. - kin
-
-      nsCOMPtr<nsIDOMNode> parent;
-      int32_t offset;
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
-
-      if (!nsHTMLEditUtils::IsTableElement(parent) || nsHTMLEditUtils::IsTableCellOrCaption(parent))
-        emptyDiv = true;
-    }
-  }
-  if (emptyDiv)
-  {
-    nsCOMPtr<nsIDOMNode> brNode, sib;
-    NS_NAMED_LITERAL_STRING(divType, "div");
-
-    NS_ENSURE_STATE(aSelection->GetRangeAt(0));
-    nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
-    int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
-    NS_ENSURE_STATE(parent);
-
-    res = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
-    NS_ENSURE_SUCCESS(res, res);
-    // consume a trailing br, if any.  This is to keep an alignment from
+      // XXX: It seems a little error prone for the emptyDiv special case code
+      // to assume that the start node of the selection is the parent of the
+      // single node in the nodeArray, as the paragraph above points out. Do we
+      // rely on the selection start node because of the fact that nodeArray
+      // can be empty?  We should probably revisit this issue. - kin
+
+      NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
+                      aSelection.GetRangeAt(0)->GetStartParent());
+      OwningNonNull<nsINode> parent =
+        *aSelection.GetRangeAt(0)->GetStartParent();
+
+      emptyDiv = !nsHTMLEditUtils::IsTableElement(parent) ||
+                 nsHTMLEditUtils::IsTableCellOrCaption(parent);
+    }
+  }
+  if (emptyDiv) {
+    NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
+                    aSelection.GetRangeAt(0)->GetStartParent());
+    OwningNonNull<nsINode> parent =
+      *aSelection.GetRangeAt(0)->GetStartParent();
+    int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
+
+    rv = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
+    NS_ENSURE_SUCCESS(rv, rv);
+    // Consume a trailing br, if any.  This is to keep an alignment from
     // creating extra lines, if possible.
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->GetNextHTMLNode(GetAsDOMNode(parent), offset,
-                                       address_of(brNode));
-    NS_ENSURE_SUCCESS(res, res);
-    if (brNode && nsTextEditUtils::IsBreak(brNode))
-    {
-      // making use of html structure... if next node after where
-      // we are putting our div is not a block, then the br we
-      // found is in same block we are, so its safe to consume it.
-      NS_ENSURE_STATE(mHTMLEditor);
-      res = mHTMLEditor->GetNextHTMLSibling(GetAsDOMNode(parent), offset,
-                                            address_of(sib));
-      NS_ENSURE_SUCCESS(res, res);
-      if (!IsBlockNode(sib))
-      {
-        NS_ENSURE_STATE(mHTMLEditor);
-        res = mHTMLEditor->DeleteNode(brNode);
-        NS_ENSURE_SUCCESS(res, res);
-      }
-    }
-    NS_ENSURE_STATE(mHTMLEditor);
-    nsCOMPtr<Element> theDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, parent,
-                                                       offset);
-    NS_ENSURE_STATE(theDiv);
-    // remember our new block for postprocessing
-    mNewBlock = GetAsDOMNode(theDiv);
-    // set up the alignment on the div, using HTML or CSS
-    nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(theDiv);
-    res = AlignBlock(divElem, alignType, true);
-    NS_ENSURE_SUCCESS(res, res);
+    nsCOMPtr<nsIContent> brContent =
+      mHTMLEditor->GetNextHTMLNode(parent, offset);
+    if (brContent && nsTextEditUtils::IsBreak(brContent)) {
+      // Making use of html structure... if next node after where we are
+      // putting our div is not a block, then the br we found is in same block
+      // we are, so it's safe to consume it.
+      nsCOMPtr<nsIContent> sibling = mHTMLEditor->GetNextHTMLSibling(parent,
+                                                                     offset);
+      if (!IsBlockNode(GetAsDOMNode(sibling))) {
+        rv = mHTMLEditor->DeleteNode(brContent);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+    }
+    nsCOMPtr<Element> div = mHTMLEditor->CreateNode(nsGkAtoms::div, parent,
+                                                    offset);
+    NS_ENSURE_STATE(div);
+    // Remember our new block for postprocessing
+    mNewBlock = div->AsDOMNode();
+    // Set up the alignment on the div, using HTML or CSS
+    rv = AlignBlock(static_cast<nsIDOMElement*>(GetAsDOMNode(div)),
+                    &aAlignType, true);
+    NS_ENSURE_SUCCESS(rv, rv);
     *aHandled = true;
-    // put in a moz-br so that it won't get deleted
-    res = CreateMozBR(GetAsDOMNode(theDiv), 0);
-    NS_ENSURE_SUCCESS(res, res);
-    res = aSelection->Collapse(theDiv, 0);
-    selectionResetter.Abort();  // don't reset our selection in this case.
-    return res;
+    // Put in a moz-br so that it won't get deleted
+    rv = CreateMozBR(div->AsDOMNode(), 0);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = aSelection.Collapse(div, 0);
+    // Don't reset our selection in this case.
+    selectionResetter.Abort();
+    NS_ENSURE_SUCCESS(rv, rv);
+    return NS_OK;
   }
 
   // Next we detect all the transitions in the array, where a transition
   // means that adjacent nodes in the array don't have the same parent.
 
   nsTArray<bool> transitionList;
   MakeTransitionList(nodeArray, transitionList);
 
-  // Ok, now go through all the nodes and give them an align attrib or put them in a div,
-  // or whatever is appropriate.  Wohoo!
-
-  nsCOMPtr<nsINode> curParent;
+  // Okay, now go through all the nodes and give them an align attrib or put
+  // them in a div, or whatever is appropriate.  Woohoo!
+
   nsCOMPtr<Element> curDiv;
   bool useCSS = mHTMLEditor->IsCSSEnabled();
-  for (int32_t i = 0; i < listCount; ++i) {
-    // here's where we actually figure out what to do
-    nsCOMPtr<nsIDOMNode> curNode = nodeArray[i]->AsDOMNode();
-    nsCOMPtr<nsIContent> curContent = do_QueryInterface(curNode);
-    NS_ENSURE_STATE(curContent);
+  for (size_t i = 0; i < nodeArray.Length(); i++) {
+    auto& curNode = nodeArray[i];
+    // Here's where we actually figure out what to do
 
     // Ignore all non-editable nodes.  Leave them be.
-    if (!mHTMLEditor->IsEditable(curNode)) continue;
-
-    curParent = curContent->GetParentNode();
-    int32_t offset = curParent ? curParent->IndexOf(curContent) : -1;
-
-    // the node is a table element, an horiz rule, a paragraph, a div
-    // or a section header; in HTML 4, it can directly carry the ALIGN
-    // attribute and we don't need to nest it, just set the alignment.
-    // In CSS, assign the corresponding CSS styles in AlignBlock
-    if (nsHTMLEditUtils::SupportsAlignAttr(curNode))
-    {
-      nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(curNode);
-      res = AlignBlock(curElem, alignType, false);
-      NS_ENSURE_SUCCESS(res, res);
-      // clear out curDiv so that we don't put nodes after this one into it
-      curDiv = 0;
+    if (!mHTMLEditor->IsEditable(curNode)) {
       continue;
     }
 
-    // Skip insignificant formatting text nodes to prevent
-    // unnecessary structure splitting!
-    bool isEmptyTextNode = false;
-    if (nsEditor::IsTextNode(curNode) &&
-       ((nsHTMLEditUtils::IsTableElement(curParent) &&
-         !nsHTMLEditUtils::IsTableCellOrCaption(GetAsDOMNode(curParent))) ||
-        nsHTMLEditUtils::IsList(curParent) ||
-        (NS_SUCCEEDED(mHTMLEditor->IsEmptyNode(curNode, &isEmptyTextNode)) && isEmptyTextNode)))
+    // The node is a table element, an hr, a paragraph, a div or a section
+    // header; in HTML 4, it can directly carry the ALIGN attribute and we
+    // don't need to nest it, just set the alignment.  In CSS, assign the
+    // corresponding CSS styles in AlignBlock
+    if (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(curNode))) {
+      rv = AlignBlock(static_cast<nsIDOMElement*>(curNode->AsDOMNode()),
+                      &aAlignType, false);
+      NS_ENSURE_SUCCESS(rv, rv);
+      // Clear out curDiv so that we don't put nodes after this one into it
+      curDiv = nullptr;
       continue;
-
-    // if it's a list item, or a list
-    // inside a list, forget any "current" div, and instead put divs inside
-    // the appropriate block (td, li, etc)
-    if ( nsHTMLEditUtils::IsListItem(curNode)
-         || nsHTMLEditUtils::IsList(curNode))
-    {
-      res = RemoveAlignment(curNode, *alignType, true);
-      NS_ENSURE_SUCCESS(res, res);
+    }
+
+    nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
+    int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
+
+    // Skip insignificant formatting text nodes to prevent unnecessary
+    // structure splitting!
+    bool isEmptyTextNode = false;
+    if (curNode->GetAsText() &&
+        ((nsHTMLEditUtils::IsTableElement(curParent) &&
+          !nsHTMLEditUtils::IsTableCellOrCaption(*curParent)) ||
+         nsHTMLEditUtils::IsList(curParent) ||
+         (NS_SUCCEEDED(mHTMLEditor->IsEmptyNode(curNode, &isEmptyTextNode)) &&
+          isEmptyTextNode))) {
+      continue;
+    }
+
+    // If it's a list item, or a list inside a list, forget any "current" div,
+    // and instead put divs inside the appropriate block (td, li, etc)
+    if (nsHTMLEditUtils::IsListItem(curNode) ||
+        nsHTMLEditUtils::IsList(curNode)) {
+      rv = RemoveAlignment(GetAsDOMNode(curNode), aAlignType, true);
+      NS_ENSURE_SUCCESS(rv, rv);
       if (useCSS) {
-        nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(curNode);
-        NS_NAMED_LITERAL_STRING(attrName, "align");
-        int32_t count;
-        mHTMLEditor->mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(curNode, nullptr,
-                                                                &attrName, alignType,
-                                                                &count, false);
-        curDiv = 0;
+        mHTMLEditor->mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(
+            curNode->AsElement(), nullptr, &NS_LITERAL_STRING("align"),
+            &aAlignType, false);
+        curDiv = nullptr;
         continue;
-      }
-      else if (nsHTMLEditUtils::IsList(curParent)) {
-        // if we don't use CSS, add a contraint to list element : they have
-        // to be inside another list, ie >= second level of nesting
-        res = AlignInnerBlocks(*curContent, alignType);
-        NS_ENSURE_SUCCESS(res, res);
-        curDiv = 0;
+      } else if (nsHTMLEditUtils::IsList(curParent)) {
+        // If we don't use CSS, add a contraint to list element: they have to
+        // be inside another list, i.e., >= second level of nesting
+        rv = AlignInnerBlocks(*curNode, &aAlignType);
+        NS_ENSURE_SUCCESS(rv, rv);
+        curDiv = nullptr;
         continue;
       }
-      // clear out curDiv so that we don't put nodes after this one into it
-    }
-
-    // need to make a div to put things in if we haven't already,
-    // or if this node doesn't go in div we used earlier.
-    if (!curDiv || transitionList[i])
-    {
+      // Clear out curDiv so that we don't put nodes after this one into it
+    }
+
+    // Need to make a div to put things in if we haven't already, or if this
+    // node doesn't go in div we used earlier.
+    if (!curDiv || transitionList[i]) {
       // First, check that our element can contain a div.
       if (!mEditor->CanContainTag(*curParent, *nsGkAtoms::div)) {
-        return NS_OK; // cancelled
-      }
-
-      res = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
-      NS_ENSURE_SUCCESS(res, res);
-      NS_ENSURE_STATE(mHTMLEditor);
+        // Cancelled
+        return NS_OK;
+      }
+
+      rv = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
+      NS_ENSURE_SUCCESS(rv, rv);
       curDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, curParent, offset);
       NS_ENSURE_STATE(curDiv);
-      // remember our new block for postprocessing
-      mNewBlock = GetAsDOMNode(curDiv);
-      // set up the alignment on the div
-      nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(curDiv);
-      res = AlignBlock(divElem, alignType, true);
-      //nsAutoString attr(NS_LITERAL_STRING("align"));
-      //res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
-      //NS_ENSURE_SUCCESS(res, res);
-      // curDiv is now the correct thing to put curNode in
-    }
-
-    // tuck the node into the end of the active div
-    NS_ENSURE_STATE(mHTMLEditor);
-    res = mHTMLEditor->MoveNode(curContent, curDiv, -1);
-    NS_ENSURE_SUCCESS(res, res);
-  }
-
-  return res;
+      // Remember our new block for postprocessing
+      mNewBlock = curDiv->AsDOMNode();
+      // Set up the alignment on the div
+      rv = AlignBlock(static_cast<nsIDOMElement*>(curDiv->AsDOMNode()),
+                       &aAlignType, true);
+    }
+
+    NS_ENSURE_STATE(curNode->IsContent());
+
+    // Tuck the node into the end of the active div
+    rv = mHTMLEditor->MoveNode(curNode->AsContent(), curDiv, -1);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // AlignInnerBlocks: Align inside table cells or list items
 //
 nsresult
 nsHTMLEditRules::AlignInnerBlocks(nsINode& aNode, const nsAString* alignType)
--- a/editor/libeditor/nsHTMLEditRules.h
+++ b/editor/libeditor/nsHTMLEditRules.h
@@ -169,18 +169,18 @@ protected:
   nsresult WillIndent(mozilla::dom::Selection* aSelection,
                       bool* aCancel, bool* aHandled);
   nsresult WillCSSIndent(mozilla::dom::Selection* aSelection,
                          bool* aCancel, bool* aHandled);
   nsresult WillHTMLIndent(mozilla::dom::Selection* aSelection,
                           bool* aCancel, bool* aHandled);
   nsresult WillOutdent(mozilla::dom::Selection* aSelection,
                        bool* aCancel, bool* aHandled);
-  nsresult WillAlign(mozilla::dom::Selection* aSelection,
-                     const nsAString* alignType,
+  nsresult WillAlign(mozilla::dom::Selection& aSelection,
+                     const nsAString& aAlignType,
                      bool* aCancel, bool* aHandled);
   nsresult WillAbsolutePosition(mozilla::dom::Selection* aSelection,
                                 bool* aCancel, bool* aHandled);
   nsresult WillRemoveAbsolutePosition(mozilla::dom::Selection* aSelection,
                                       bool* aCancel, bool* aHandled);
   nsresult WillRelativeChangeZIndex(mozilla::dom::Selection* aSelection,
                                     int32_t aChange,
                                     bool* aCancel, bool* aHandled);
--- a/editor/libeditor/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/nsHTMLEditUtils.cpp
@@ -254,26 +254,23 @@ bool
 nsHTMLEditUtils::IsTableCell(nsINode* aNode)
 {
   MOZ_ASSERT(aNode);
   return aNode->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
-// IsTableCell: true if node an html td or th
+// IsTableCellOrCaption: true if node an html td or th or caption
 //
 bool
-nsHTMLEditUtils::IsTableCellOrCaption(nsIDOMNode* aNode)
+nsHTMLEditUtils::IsTableCellOrCaption(nsINode& aNode)
 {
-  NS_PRECONDITION(aNode, "null parent passed to nsHTMLEditUtils::IsTableCell");
-  nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aNode);
-  return (nodeAtom == nsGkAtoms::td)
-      || (nodeAtom == nsGkAtoms::th)
-      || (nodeAtom == nsGkAtoms::caption);
+  return aNode.IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th,
+                                   nsGkAtoms::caption);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsList: true if node an html list
 //
 bool
 nsHTMLEditUtils::IsList(nsIDOMNode* aNode)
--- a/editor/libeditor/nsHTMLEditUtils.h
+++ b/editor/libeditor/nsHTMLEditUtils.h
@@ -30,17 +30,17 @@ public:
   static bool IsTable(nsINode* aNode);
   static bool IsTableRow(nsIDOMNode *aNode);
   static bool IsTableElement(nsINode* aNode);
   static bool IsTableElement(nsIDOMNode *aNode);
   static bool IsTableElementButNotTable(nsINode* aNode);
   static bool IsTableElementButNotTable(nsIDOMNode *aNode);
   static bool IsTableCell(nsINode* node);
   static bool IsTableCell(nsIDOMNode *aNode);
-  static bool IsTableCellOrCaption(nsIDOMNode *aNode);
+  static bool IsTableCellOrCaption(nsINode& aNode);
   static bool IsList(nsINode* aNode);
   static bool IsList(nsIDOMNode *aNode);
   static bool IsOrderedList(nsIDOMNode *aNode);
   static bool IsUnorderedList(nsIDOMNode *aNode);
   static bool IsBlockquote(nsIDOMNode *aNode);
   static bool IsPre(nsIDOMNode *aNode);
   static bool IsAnchor(nsIDOMNode *aNode);
   static bool IsImage(nsINode* aNode);