Bug 1156062 part 1d - Clean up nsEditor::SplitNodeDeep; r=ehsan
authorAryeh Gregor <ayg@aryeh.name>
Sun, 11 Oct 2015 18:57:48 +0300
changeset 302377 74e5c9314b72cf8fbba214377301314c33a6b4a7
parent 302376 54b2262a04e52168c29b2361014ab506c6867747
child 302378 d83a21f9dd57d417c0c498a469089540ba882de7
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1156062
milestone44.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 1d - Clean up nsEditor::SplitNodeDeep; r=ehsan
editor/libeditor/nsEditor.cpp
editor/libeditor/nsEditor.h
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -3790,128 +3790,91 @@ nsEditor::IsPreformatted(nsIDOMNode *aNo
 
   const nsStyleText* styleText = elementStyle->StyleText();
 
   *aResult = styleText->WhiteSpaceIsSignificant();
   return NS_OK;
 }
 
 
-///////////////////////////////////////////////////////////////////////////
-// SplitNodeDeep: this splits a node "deeply", splitting children as
-//                appropriate.  The place to split is represented by
-//                a dom point at {splitPointParent, splitPointOffset}.
-//                That dom point must be inside aNode, which is the node to
-//                split.  outOffset is set to the offset in the parent of aNode where
-//                the split terminates - where you would want to insert
-//                a new element, for instance, if that's why you were splitting
-//                the node.
-//
+/**
+ * This splits a node "deeply", splitting children as appropriate.  The place
+ * to split is represented by a DOM point at {splitPointParent,
+ * splitPointOffset}.  That DOM point must be inside aNode, which is the node
+ * to split.  We return the offset in the parent of aNode where the split
+ * terminates - where you would want to insert a new element, for instance, if
+ * that's why you were splitting the node.
+ *
+ * -1 is returned on failure, in unlikely cases like the selection being
+ * unavailable or cloning the node failing.  Make sure not to use the returned
+ * offset for anything without checking that it's valid!  If you're not using
+ * the offset, it's okay to ignore the return value.
+ */
 int32_t
-nsEditor::SplitNodeDeep(nsIContent& aNode, nsIContent& aSplitPointParent,
+nsEditor::SplitNodeDeep(nsIContent& aNode,
+                        nsIContent& aSplitPointParent,
                         int32_t aSplitPointOffset,
                         EmptyContainers aEmptyContainers,
-                        nsIContent** outLeftNode,
-                        nsIContent** outRightNode)
-{
-  int32_t offset;
-  nsCOMPtr<nsIDOMNode> leftNodeDOM, rightNodeDOM;
-  nsresult res = SplitNodeDeep(aNode.AsDOMNode(),
-      aSplitPointParent.AsDOMNode(), aSplitPointOffset, &offset,
-      aEmptyContainers == EmptyContainers::no, address_of(leftNodeDOM),
-      address_of(rightNodeDOM));
-  NS_ENSURE_SUCCESS(res, -1);
-  if (outLeftNode) {
-    nsCOMPtr<nsIContent> leftNode = do_QueryInterface(leftNodeDOM);
-    MOZ_ASSERT(!leftNodeDOM || leftNode);
-    leftNode.forget(outLeftNode);
-  }
-  if (outRightNode) {
-    nsCOMPtr<nsIContent> rightNode = do_QueryInterface(rightNodeDOM);
-    MOZ_ASSERT(!rightNodeDOM || rightNode);
-    rightNode.forget(outRightNode);
-  }
-  return offset;
-}
-
-nsresult
-nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
-                        nsIDOMNode *aSplitPointParent,
-                        int32_t aSplitPointOffset,
-                        int32_t *outOffset,
-                        bool    aNoEmptyContainers,
-                        nsCOMPtr<nsIDOMNode> *outLeftNode,
-                        nsCOMPtr<nsIDOMNode> *outRightNode)
-{
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  NS_ENSURE_TRUE(node && aSplitPointParent && outOffset, NS_ERROR_NULL_POINTER);
+                        nsIContent** aOutLeftNode,
+                        nsIContent** aOutRightNode)
+{
+  MOZ_ASSERT(&aSplitPointParent == &aNode ||
+             nsEditorUtils::IsDescendantOf(&aSplitPointParent, &aNode));
   int32_t offset = aSplitPointOffset;
 
-  if (outLeftNode)  *outLeftNode  = nullptr;
-  if (outRightNode) *outRightNode = nullptr;
-
-  nsCOMPtr<nsINode> nodeToSplit = do_QueryInterface(aSplitPointParent);
-  while (nodeToSplit) {
-    // need to insert rules code call here to do things like
-    // not split a list if you are after the last <li> or before the first, etc.
-    // for now we just have some smarts about unneccessarily splitting
-    // textnodes, which should be universal enough to put straight in
-    // this nsEditor routine.
-
-    nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(nodeToSplit);
-    uint32_t len = nodeToSplit->Length();
-    bool bDoSplit = false;
-
-    if (!(aNoEmptyContainers || nodeAsText) || (offset && (offset != (int32_t)len)))
-    {
-      bDoSplit = true;
-      nsCOMPtr<nsIDOMNode> tempNode;
-      nsresult rv = SplitNode(nodeToSplit->AsDOMNode(), offset,
-                              getter_AddRefs(tempNode));
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      if (outRightNode) {
-        *outRightNode = nodeToSplit->AsDOMNode();
-      }
-      if (outLeftNode) {
-        *outLeftNode = tempNode;
-      }
+  nsCOMPtr<nsIContent> leftNode, rightNode;
+  OwningNonNull<nsIContent> nodeToSplit = aSplitPointParent;
+  while (true) {
+    // Need to insert rules code call here to do things like not split a list
+    // if you are after the last <li> or before the first, etc.  For now we
+    // just have some smarts about unneccessarily splitting text nodes, which
+    // should be universal enough to put straight in this nsEditor routine.
+
+    bool didSplit = false;
+
+    if ((aEmptyContainers == EmptyContainers::yes &&
+         !nodeToSplit->GetAsText()) ||
+        (offset && offset != (int32_t)nodeToSplit->Length())) {
+      didSplit = true;
+      ErrorResult rv;
+      nsCOMPtr<nsIContent> newLeftNode = SplitNode(nodeToSplit, offset, rv);
+      NS_ENSURE_TRUE(!rv.Failed(), -1);
+
+      rightNode = nodeToSplit;
+      leftNode = newLeftNode;
     }
 
-    nsINode* parentNode = nodeToSplit->GetParentNode();
-    NS_ENSURE_TRUE(parentNode, NS_ERROR_FAILURE);
-
-    if (!bDoSplit && offset) {
-      // must be "end of text node" case, we didn't split it, just move past it
+    NS_ENSURE_TRUE(nodeToSplit->GetParent(), -1);
+    OwningNonNull<nsIContent> parentNode = *nodeToSplit->GetParent();
+
+    if (!didSplit && offset) {
+      // Must be "end of text node" case, we didn't split it, just move past it
       offset = parentNode->IndexOf(nodeToSplit) + 1;
-      if (outLeftNode) {
-        *outLeftNode = nodeToSplit->AsDOMNode();
-      }
+      leftNode = nodeToSplit;
     } else {
       offset = parentNode->IndexOf(nodeToSplit);
-      if (outRightNode) {
-        *outRightNode = nodeToSplit->AsDOMNode();
-      }
+      rightNode = nodeToSplit;
     }
 
-    if (nodeToSplit == node) {
+    if (nodeToSplit == &aNode) {
       // we split all the way up to (and including) aNode; we're done
       break;
     }
 
     nodeToSplit = parentNode;
   }
 
-  if (!nodeToSplit) {
-    NS_NOTREACHED("null node obtained in nsEditor::SplitNodeDeep()");
-    return NS_ERROR_FAILURE;
-  }
-
-  *outOffset = offset;
-  return NS_OK;
+  if (aOutLeftNode) {
+    leftNode.forget(aOutLeftNode);
+  }
+  if (aOutRightNode) {
+    rightNode.forget(aOutRightNode);
+  }
+
+  return offset;
 }
 
 
 /**
  * This joins two like nodes "deeply", joining children as appropriate.
  * Returns the point of the join, or (nullptr, -1) in case of error.
  */
 ::DOMPoint
--- a/editor/libeditor/nsEditor.h
+++ b/editor/libeditor/nsEditor.h
@@ -636,20 +636,16 @@ public:
 
   enum class EmptyContainers { no, yes };
   int32_t SplitNodeDeep(nsIContent& aNode, nsIContent& aSplitPointParent,
                         int32_t aSplitPointOffset,
                         EmptyContainers aEmptyContainers =
                           EmptyContainers::yes,
                         nsIContent** outLeftNode = nullptr,
                         nsIContent** outRightNode = nullptr);
-  nsresult SplitNodeDeep(nsIDOMNode* aNode, nsIDOMNode* aSplitPointParent,
-      int32_t aSplitPointOffset, int32_t* outOffset, bool aNoEmptyContainers =
-      false, nsCOMPtr<nsIDOMNode>* outLeftNode = nullptr, nsCOMPtr<nsIDOMNode>*
-      outRightNode = nullptr);
   ::DOMPoint JoinNodeDeep(nsIContent& aLeftNode, nsIContent& aRightNode);
 
   nsresult GetString(const nsAString& name, nsAString& value);
 
   void BeginUpdateViewBatch(void);
   virtual nsresult EndUpdateViewBatch(void);
 
   bool GetShouldTxnSetSelection();