Bug 1407305 - Part 4: Avoid using GetChildAt() in EditorBase::GetNextNode(); r=masayuki
authorEhsan Akhgari <ehsan@mozilla.com>
Sat, 07 Oct 2017 18:36:50 -0400
changeset 385577 e22de36807c6229b3710382f0094ffe5e31eaa26
parent 385576 8c6f9b6b56ebe5bfd1eb7d6345e9af2e94cc914e
child 385578 ab5dcb5b8f1f09cff4c52880ea0c1281cce8d77d
push id32662
push userryanvm@gmail.com
push dateWed, 11 Oct 2017 21:53:47 +0000
treeherdermozilla-central@3d918ff5d634 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1407305
milestone58.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 1407305 - Part 4: Avoid using GetChildAt() in EditorBase::GetNextNode(); r=masayuki
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorBase.h
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditor.cpp
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -3308,39 +3308,41 @@ EditorBase::GetPriorNode(nsINode* aParen
 
   // restart the search from the non-editable node we just found
   return GetPriorNode(resultNode, aEditableNode, aNoBlockCrossing);
 }
 
 nsIContent*
 EditorBase::GetNextNode(nsINode* aParentNode,
                         int32_t aOffset,
+                        nsINode* aChildAtOffset,
                         bool aEditableNode,
                         bool aNoBlockCrossing)
 {
   MOZ_ASSERT(aParentNode);
 
   // if aParentNode is a text node, use its location instead
   if (aParentNode->NodeType() == nsIDOMNode::TEXT_NODE) {
     nsINode* parent = aParentNode->GetParentNode();
     NS_ENSURE_TRUE(parent, nullptr);
     aOffset = parent->IndexOf(aParentNode) + 1; // _after_ the text node
     aParentNode = parent;
   }
 
   // look at the child at 'aOffset'
-  nsIContent* child = aParentNode->GetChildAt(aOffset);
-  if (child) {
-    if (aNoBlockCrossing && IsBlockNode(child)) {
-      return child;
+  if (aChildAtOffset) {
+    if (aNoBlockCrossing && IsBlockNode(aChildAtOffset)) {
+      MOZ_ASSERT(aChildAtOffset->IsContent());
+      return aChildAtOffset->AsContent();
     }
 
-    nsIContent* resultNode = GetLeftmostChild(child, aNoBlockCrossing);
+    nsIContent* resultNode = GetLeftmostChild(aChildAtOffset, aNoBlockCrossing);
     if (!resultNode) {
-      return child;
+      MOZ_ASSERT(aChildAtOffset->IsContent());
+      return aChildAtOffset->AsContent();
     }
 
     if (!IsDescendantOfEditorRoot(resultNode)) {
       return nullptr;
     }
 
     if (!aEditableNode || IsEditable(resultNode)) {
       return resultNode;
@@ -4655,17 +4657,17 @@ EditorBase::CreateTxnForDeleteRange(nsRa
   }
 
   // we're either deleting a node or chardata, need to dig into the next/prev
   // node to find out
   nsCOMPtr<nsINode> selectedNode;
   if (aAction == ePrevious) {
     selectedNode = GetPriorNode(node, offset, child, true);
   } else if (aAction == eNext) {
-    selectedNode = GetNextNode(node, offset, true);
+    selectedNode = GetNextNode(node, offset, child, true);
   }
 
   while (selectedNode &&
          selectedNode->IsNodeOfType(nsINode::eDATA_NODE) &&
          !selectedNode->Length()) {
     // Can't delete an empty chardata node (bug 762183)
     if (aAction == ePrevious) {
       selectedNode = GetPriorNode(selectedNode, true);
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -726,16 +726,17 @@ public:
                           bool aEditableNode,
                           bool bNoBlockCrossing = false);
 
   /**
    * And another version that takes a {parent,offset} pair rather than a node.
    */
   nsIContent* GetNextNode(nsINode* aParentNode,
                           int32_t aOffset,
+                          nsINode* aChildAtOffset,
                           bool aEditableNode,
                           bool aNoBlockCrossing = false);
 
   /**
    * Helper for GetNextNode() and GetPriorNode().
    */
   nsIContent* FindNode(nsINode* aCurrentNode,
                        bool aGoForward,
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -849,28 +849,29 @@ HTMLEditRules::GetAlignment(bool* aMixed
 
   int32_t rootOffset = root->GetParentNode() ?
                        root->GetParentNode()->IndexOf(root) : -1;
 
   NS_ENSURE_STATE(selection->GetRangeAt(0) &&
                   selection->GetRangeAt(0)->GetStartContainer());
   OwningNonNull<nsINode> parent =
     *selection->GetRangeAt(0)->GetStartContainer();
+  nsIContent* child = selection->GetRangeAt(0)->GetChildAtStartOffset();
   int32_t offset = selection->GetRangeAt(0)->StartOffset();
 
   // Is the selection collapsed?
   nsCOMPtr<nsINode> nodeToExamine;
   if (selection->Collapsed() || parent->GetAsText()) {
     // If selection is collapsed, we want to look at 'parent' and its ancestors
     // for divs with alignment on them.  If we are in a text node, then that is
     // the node of interest.
     nodeToExamine = parent;
   } else if (parent->IsHTMLElement(nsGkAtoms::html) && offset == rootOffset) {
     // If we have selected the body, let's look at the first editable node
-    nodeToExamine = htmlEditor->GetNextNode(parent, offset, true);
+    nodeToExamine = htmlEditor->GetNextNode(parent, offset, child, true);
   } else {
     nsTArray<RefPtr<nsRange>> arrayOfRanges;
     GetPromotedRanges(selection, arrayOfRanges, EditAction::align);
 
     // Use these ranges to construct a list of nodes to act on.
     nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
     nsresult rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
                                        EditAction::align, TouchContent::no);
@@ -5042,18 +5043,19 @@ HTMLEditRules::CheckForEmptyBlock(nsINod
         }
         // Else just let selection percolate up.  We'll adjust it in
         // AfterEdit()
       }
     } else {
       if (aAction == nsIEditor::eNext || aAction == nsIEditor::eNextWord ||
           aAction == nsIEditor::eToEndOfLine) {
         // Move to the start of the next node, if any
-        nsCOMPtr<nsIContent> nextNode = htmlEditor->GetNextNode(blockParent,
-                                                                offset + 1, true);
+        nsINode* child = emptyBlock->GetNextSibling();
+        nsCOMPtr<nsIContent> nextNode =
+          htmlEditor->GetNextNode(blockParent, offset + 1, child, true);
         if (nextNode) {
           EditorDOMPoint pt = GetGoodSelPointForNode(*nextNode, aAction);
           nsresult rv = aSelection->Collapse(pt.node, pt.offset);
           NS_ENSURE_SUCCESS(rv, rv);
         } else {
           // Adjust selection to be right after it.
           nsresult rv = aSelection->Collapse(blockParent, offset + 1);
           NS_ENSURE_SUCCESS(rv, rv);
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -3941,17 +3941,18 @@ HTMLEditor::GetNextHTMLNode(nsIDOMNode* 
  * GetNextHTMLNode() is same as above but takes {parent,offset} instead of node.
  */
 nsIContent*
 HTMLEditor::GetNextHTMLNode(nsINode* aParent,
                             int32_t aOffset,
                             nsINode* aChildAtOffset,
                             bool aNoBlockCrossing)
 {
-  nsIContent* content = GetNextNode(aParent, aOffset, true, aNoBlockCrossing);
+  nsIContent* content = GetNextNode(aParent, aOffset, aChildAtOffset,
+                                    true, aNoBlockCrossing);
   if (content && !IsDescendantOfEditorRoot(content)) {
     return nullptr;
   }
   return content;
 }
 
 bool
 HTMLEditor::IsFirstEditableChild(nsINode* aNode)