Bug 1407305 - Part 2: Add a aChildAtOffset argument to HTMLEditor::GetNextHTMLNode(); r=masayuki
authorEhsan Akhgari <ehsan@mozilla.com>
Sat, 07 Oct 2017 17:36:21 -0400
changeset 385575 dc1c6227e652a56ac396d9f4717c0bc49ff5247f
parent 385574 aa6c322a98b09b94faf4184274b10d62b7393075
child 385576 8c6f9b6b56ebe5bfd1eb7d6345e9af2e94cc914e
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 2: Add a aChildAtOffset argument to HTMLEditor::GetNextHTMLNode(); r=masayuki
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -3595,29 +3595,30 @@ HTMLEditRules::MakeBasicBlock(Selection&
 
   // If nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
     // Get selection location
     NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
                     aSelection.GetRangeAt(0)->GetStartContainer());
     OwningNonNull<nsINode> container =
       *aSelection.GetRangeAt(0)->GetStartContainer();
+    nsIContent* child = aSelection.GetRangeAt(0)->GetChildAtStartOffset();
     int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
 
     if (&blockType == nsGkAtoms::normal ||
         &blockType == nsGkAtoms::_empty) {
       // We are removing blocks (going to "body text")
       NS_ENSURE_TRUE(htmlEditor->GetBlock(container), NS_ERROR_NULL_POINTER);
       OwningNonNull<Element> curBlock = *htmlEditor->GetBlock(container);
       if (HTMLEditUtils::IsFormatNode(curBlock)) {
         // If the first editable node after selection is a br, consume it.
         // Otherwise it gets pushed into a following block after the split,
         // which is visually bad.
         nsCOMPtr<nsIContent> brNode =
-          htmlEditor->GetNextHTMLNode(container, offset);
+          htmlEditor->GetNextHTMLNode(container, offset, child);
         if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
           rv = htmlEditor->DeleteNode(brNode);
           NS_ENSURE_SUCCESS(rv, rv);
         }
         // Do the splits!
         offset = htmlEditor->SplitNodeDeep(curBlock, *container->AsContent(),
                                             offset,
                                             HTMLEditor::EmptyContainers::no);
@@ -3630,17 +3631,17 @@ HTMLEditRules::MakeBasicBlock(Selection&
         // Don't restore the selection
         selectionRestorer.Abort();
         NS_ENSURE_SUCCESS(rv, rv);
       }
       // Else nothing to do!
     } else {
       // We are making a block.  Consume a br, if needed.
       nsCOMPtr<nsIContent> brNode =
-        htmlEditor->GetNextHTMLNode(container, offset, true);
+        htmlEditor->GetNextHTMLNode(container, offset, child, true);
       if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
         rv = htmlEditor->DeleteNode(brNode);
         NS_ENSURE_SUCCESS(rv, rv);
         // We don't need to act on this node any more
         arrayOfNodes.RemoveElement(brNode);
       }
       // Make sure we can put a block here
       rv = SplitAsNeeded(blockType, container, offset);
@@ -4737,17 +4738,17 @@ HTMLEditRules::WillAlign(Selection& aSel
     int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
     nsIContent* child = aSelection.GetRangeAt(0)->GetChildAtStartOffset();
 
     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.
     nsCOMPtr<nsIContent> brContent =
-      htmlEditor->GetNextHTMLNode(parent, offset);
+      htmlEditor->GetNextHTMLNode(parent, offset, child);
     if (brContent && TextEditUtils::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;
       if (child) {
         sibling = htmlEditor->GetNextHTMLSibling(child);
       }
@@ -5317,16 +5318,17 @@ HTMLEditRules::NormalizeSelection(Select
   nsCOMPtr<nsINode> startNode = range->GetStartContainer();
   if (NS_WARN_IF(!startNode)) {
     return NS_ERROR_FAILURE;
   }
   nsCOMPtr<nsINode> endNode = range->GetEndContainer();
   if (NS_WARN_IF(!endNode)) {
     return NS_ERROR_FAILURE;
   }
+  nsIContent* startChild = range->GetChildAtStartOffset();
   nsIContent* endChild = range->GetChildAtEndOffset();
   uint32_t startOffset = range->StartOffset();
   uint32_t endOffset = range->EndOffset();
 
   // adjusted values default to original values
   nsCOMPtr<nsINode> newStartNode = startNode;
   uint32_t newStartOffset = startOffset;
   nsCOMPtr<nsINode> newEndNode = endNode;
@@ -5398,17 +5400,18 @@ HTMLEditRules::NormalizeSelection(Select
         newStartNode = EditorBase::GetNodeLocation(child, &offset);
         newStartOffset = static_cast<uint32_t>(offset);
       }
       // else block is empty - we can leave selection alone here, i think.
     } else if (wsStartObj.mEndReason == WSType::thisBlock) {
       // startpoint is just before end of this block
       nsINode* child =
         htmlEditor->GetNextHTMLNode(startNode,
-                                    static_cast<int32_t>(startOffset));
+                                    static_cast<int32_t>(startOffset),
+                                    startChild);
       if (child) {
         int32_t offset = -1;
         newStartNode = EditorBase::GetNodeLocation(child, &offset);
         newStartOffset = static_cast<uint32_t>(offset);
       }
       // else block is empty - we can leave selection alone here, i think.
     } else if (wsStartObj.mEndReason == WSType::br) {
       // startpoint is just before a break.  lets adjust it to after it.
@@ -5582,17 +5585,17 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
     offset = 1 + node->GetParentNode()->IndexOf(node);
     child = node;
     node = node->GetParentNode();
   }
 
   // look ahead through any further inline nodes that aren't across a <br> from
   // us, and that are enclosed in the same block.
   nsCOMPtr<nsIContent> nextNode =
-    htmlEditor->GetNextHTMLNode(node, offset, true);
+    htmlEditor->GetNextHTMLNode(node, offset, child, true);
 
   while (nextNode && !IsBlockNode(*nextNode) && nextNode->GetParentNode()) {
     offset = 1 + nextNode->GetParentNode()->IndexOf(nextNode);
     child = nextNode->GetNextSibling();
     node = nextNode->GetParentNode();
     if (htmlEditor->IsVisibleBRElement(nextNode)) {
       break;
     }
@@ -5609,24 +5612,24 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
           if (static_cast<uint32_t>(newlinePos) + 1 == tempString.Length()) {
             // No need for special processing if the newline is at the end.
             break;
           }
           return EditorDOMPoint(nextNode, newlinePos + 1);
         }
       }
     }
-    nextNode = htmlEditor->GetNextHTMLNode(node, offset, true);
+    nextNode = htmlEditor->GetNextHTMLNode(node, offset, child, true);
   }
 
   // finding the real end for this point.  look up the tree for as long as we
   // are the last node in the container, and as long as we haven't hit the body
   // node.
   nsCOMPtr<nsIContent> nearNode =
-    htmlEditor->GetNextHTMLNode(node, offset, true);
+    htmlEditor->GetNextHTMLNode(node, offset, child, true);
   while (!nearNode && !node->IsHTMLElement(nsGkAtoms::body) &&
          node->GetParentNode()) {
     int32_t parentOffset = node->GetParentNode()->IndexOf(node);
     nsCOMPtr<nsINode> parent = node->GetParentNode();
 
     // Don't walk past the editable section. Note that we need to check before
     // walking up to a parent because we need to return the parent object, so
     // the parent itself might not be in the editable area, but it's OK.
@@ -5634,17 +5637,17 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
         !htmlEditor->IsDescendantOfEditorRoot(parent)) {
       break;
     }
 
     child = node->GetNextSibling();
     node = parent;
     // we want to be AFTER nearNode
     offset = parentOffset + 1;
-    nearNode = htmlEditor->GetNextHTMLNode(node, offset, true);
+    nearNode = htmlEditor->GetNextHTMLNode(node, offset, child, true);
   }
   return EditorDOMPoint(node, offset);
 }
 
 /**
  * GetPromotedRanges() runs all the selection range endpoint through
  * GetPromotedPoint().
  */
@@ -6528,17 +6531,17 @@ HTMLEditRules::ReturnInParagraph(Selecti
     nsCOMPtr<nsIContent> nearNode;
     NS_ENSURE_STATE(mHTMLEditor);
     nearNode = mHTMLEditor->GetPriorHTMLNode(node, aOffset, aChildAtOffset);
     NS_ENSURE_STATE(mHTMLEditor);
     if (!nearNode || !mHTMLEditor->IsVisibleBRElement(nearNode) ||
         TextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) {
       // is there a BR after it?
       NS_ENSURE_STATE(mHTMLEditor);
-      nearNode = mHTMLEditor->GetNextHTMLNode(node, aOffset);
+      nearNode = mHTMLEditor->GetNextHTMLNode(node, aOffset, aChildAtOffset);
       NS_ENSURE_STATE(mHTMLEditor);
       if (!nearNode || !mHTMLEditor->IsVisibleBRElement(nearNode) ||
           TextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) {
         newBRneeded = true;
         parent = node;
         offset = aOffset;
         newSelNode = true;
       }
@@ -7547,23 +7550,24 @@ HTMLEditRules::AdjustSelection(Selection
 
   // get the (collapsed) selection location
   nsCOMPtr<nsINode> selNode, temp;
   int32_t selOffset;
   nsresult rv =
     EditorBase::GetStartNodeAndOffset(aSelection,
                                       getter_AddRefs(selNode), &selOffset);
   NS_ENSURE_SUCCESS(rv, rv);
-  nsIContent* child = aSelection->GetRangeAt(0)->GetChildAtStartOffset();
+  nsINode* child = aSelection->GetRangeAt(0)->GetChildAtStartOffset();
   temp = selNode;
 
   // are we in an editable node?
   NS_ENSURE_STATE(mHTMLEditor);
   while (!mHTMLEditor->IsEditable(selNode)) {
     // scan up the tree until we find an editable place to be
+    child = temp;
     selNode = EditorBase::GetNodeLocation(temp, &selOffset);
     NS_ENSURE_TRUE(selNode, NS_ERROR_FAILURE);
     temp = selNode;
     NS_ENSURE_STATE(mHTMLEditor);
   }
 
   // make sure we aren't in an empty block - user will see no cursor.  If this
   // is happening, put a <br> in the block if allowed.
@@ -7648,17 +7652,17 @@ HTMLEditRules::AdjustSelection(Selection
   if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
                    EditorBase::IsTextNode(nearNode) ||
                    HTMLEditUtils::IsImage(nearNode) ||
                    nearNode->IsHTMLElement(nsGkAtoms::hr))) {
     // this is a good place for the caret to be
     return NS_OK;
   }
   NS_ENSURE_STATE(mHTMLEditor);
-  nearNode = mHTMLEditor->GetNextHTMLNode(selNode, selOffset, true);
+  nearNode = mHTMLEditor->GetNextHTMLNode(selNode, selOffset, child, true);
   if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
                    EditorBase::IsTextNode(nearNode) ||
                    nearNode->IsAnyOfHTMLElements(nsGkAtoms::img,
                                                  nsGkAtoms::hr))) {
     return NS_OK; // this is a good place for the caret to be
   }
 
   // look for a nearby text node.
@@ -7677,34 +7681,35 @@ HTMLEditRules::AdjustSelection(Selection
   }
   return NS_OK;
 }
 
 
 nsresult
 HTMLEditRules::FindNearSelectableNode(nsINode* aSelNode,
                                       int32_t aSelOffset,
-                                      nsIContent* aChildAtOffset,
+                                      nsINode* aChildAtOffset,
                                       nsIEditor::EDirection& aDirection,
                                       nsCOMPtr<nsIContent>* outSelectableNode)
 {
   NS_ENSURE_TRUE(aSelNode && outSelectableNode, NS_ERROR_NULL_POINTER);
   *outSelectableNode = nullptr;
 
   nsCOMPtr<nsIContent> nearNode, curNode;
   if (aDirection == nsIEditor::ePrevious) {
     NS_ENSURE_STATE(mHTMLEditor);
     nearNode = mHTMLEditor->GetPriorHTMLNode(aSelNode, aSelOffset,
                                              aChildAtOffset);
     if (NS_WARN_IF(!nearNode)) {
       return NS_ERROR_FAILURE;
     }
   } else {
     NS_ENSURE_STATE(mHTMLEditor);
-    nearNode = mHTMLEditor->GetNextHTMLNode(aSelNode, aSelOffset);
+    nearNode = mHTMLEditor->GetNextHTMLNode(aSelNode, aSelOffset,
+                                            aChildAtOffset);
     if (NS_WARN_IF(!nearNode)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   // Try the other direction then.
   if (!nearNode) {
     if (aDirection == nsIEditor::ePrevious) {
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -395,17 +395,17 @@ protected:
   void AdjustSpecialBreaks();
   nsresult AdjustWhitespace(Selection* aSelection);
   nsresult PinSelectionToNewBlock(Selection* aSelection);
   void CheckInterlinePosition(Selection& aSelection);
   nsresult AdjustSelection(Selection* aSelection,
                            nsIEditor::EDirection aAction);
   nsresult FindNearSelectableNode(nsINode* aSelNode,
                                   int32_t aSelOffset,
-                                  nsIContent* aChildAtOffset,
+                                  nsINode* aChildAtOffset,
                                   nsIEditor::EDirection& aDirection,
                                   nsCOMPtr<nsIContent>* outSelectableNode);
   /**
    * Returns true if aNode1 or aNode2 or both is the descendant of some type of
    * table element, but their nearest table element ancestors differ.  "Table
    * element" here includes not just <table> but also <td>, <tbody>, <tr>, etc.
    * The nodes count as being their own descendants for this purpose, so a
    * table element is its own nearest table element ancestor.
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -3938,16 +3938,17 @@ 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);
   if (content && !IsDescendantOfEditorRoot(content)) {
     return nullptr;
   }
   return content;
 }
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -781,16 +781,17 @@ protected:
   nsIContent* GetPriorHTMLNode(nsINode* aParent, int32_t aOffset,
                                nsINode* aChildAtOffset,
                                bool aNoBlockCrossing = false);
 
   nsIContent* GetNextHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false);
   nsresult GetNextHTMLNode(nsIDOMNode* inNode, nsCOMPtr<nsIDOMNode>* outNode,
                            bool bNoBlockCrossing = false);
   nsIContent* GetNextHTMLNode(nsINode* aParent, int32_t aOffset,
+                              nsINode* aChildAtOffset,
                               bool aNoBlockCrossing = false);
 
   bool IsFirstEditableChild(nsINode* aNode);
   bool IsLastEditableChild(nsINode* aNode);
   nsIContent* GetFirstEditableChild(nsINode& aNode);
   nsIContent* GetLastEditableChild(nsINode& aNode);
 
   nsIContent* GetFirstEditableLeaf(nsINode& aNode);