Bug 1445569 - part 2: Make WSRunObject::PriorVisibleNode() and WSRunObject::NextVisibleNode() take |const Editor(Raw)DOMPoint&| instead of a pair of |nsINode*| and offset in it r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 15 Mar 2018 18:23:50 +0900
changeset 768341 f98da05ecfd7aed13427c1607bebd90d75d51a7c
parent 768340 5ff91c2ffad82fd63b441d2cdacb545258cd0e68
child 768342 1fd7ffcc3f5a1e926278ff3e91bef91d6512ad06
push id102858
push usermasayuki@d-toybox.com
push dateFri, 16 Mar 2018 03:57:40 +0000
reviewersm_kato
bugs1445569
milestone61.0a1
Bug 1445569 - part 2: Make WSRunObject::PriorVisibleNode() and WSRunObject::NextVisibleNode() take |const Editor(Raw)DOMPoint&| instead of a pair of |nsINode*| and offset in it r?m_kato Similar to the constructor of WSRunObject, PriorVisibleNode() and NextVisibleNode() callers may become ugly if the callers start to use Editor(Raw)DOMPoint. So, let's make them take Editor(Raw)DOMPoint instead of a pair of nsINode* and offset in it. Note that a lot of callers of them already use Editor(Raw)DOMPoint. So, we don't need to keep maintain overloads which takes nsINode* and offset in it directly. MozReview-Commit-ID: 3avMtL000nd
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditorDataTransfer.cpp
editor/libeditor/WSRunObject.cpp
editor/libeditor/WSRunObject.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -1854,22 +1854,22 @@ HTMLEditRules::InsertBRElement(Selection
       return NS_ERROR_FAILURE;
     }
   } else {
     EditorDOMPoint pointToBreak(aPointToBreak);
     WSRunObject wsObj(htmlEditor, pointToBreak);
     int32_t visOffset = 0;
     WSType wsType;
     nsCOMPtr<nsINode> visNode;
-    wsObj.PriorVisibleNode(pointToBreak.GetContainer(), pointToBreak.Offset(),
+    wsObj.PriorVisibleNode(pointToBreak,
                            address_of(visNode), &visOffset, &wsType);
     if (wsType & WSType::block) {
       brElementIsAfterBlock = true;
     }
-    wsObj.NextVisibleNode(pointToBreak.GetContainer(), pointToBreak.Offset(),
+    wsObj.NextVisibleNode(pointToBreak,
                           address_of(visNode), &visOffset, &wsType);
     if (wsType & WSType::block) {
       brElementIsBeforeBlock = true;
     }
     // If the container of the break is a link, we need to split it and
     // insert new <br> between the split links.
     nsCOMPtr<nsINode> linkDOMNode;
     if (htmlEditor->IsInLink(pointToBreak.GetContainer(),
@@ -1919,17 +1919,17 @@ HTMLEditRules::InsertBRElement(Selection
   EditorDOMPoint afterBRElement(brElement);
   DebugOnly<bool> advanced = afterBRElement.AdvanceOffset();
   NS_WARNING_ASSERTION(advanced,
     "Failed to advance offset after the new <br> element");
   WSRunObject wsObj(htmlEditor, afterBRElement);
   nsCOMPtr<nsINode> maybeSecondBRNode;
   int32_t visOffset = 0;
   WSType wsType;
-  wsObj.NextVisibleNode(afterBRElement.GetContainer(), afterBRElement.Offset(),
+  wsObj.NextVisibleNode(afterBRElement,
                         address_of(maybeSecondBRNode), &visOffset, &wsType);
   if (wsType == WSType::br) {
     // The next thing after the break we inserted is another break.  Move the
     // second break to be the first break's sibling.  This will prevent them
     // from being in different inline nodes, which would break
     // SetInterlinePosition().  It will also assure that if the user clicks
     // away and then clicks back on their new blank line, they will still get
     // the style from the line above.
@@ -1999,18 +1999,18 @@ HTMLEditRules::SplitMailCites(Selection*
     // it means the break won't end up making an empty line that happens to be inside a
     // mailquote (in either inline or block case).
     // The latter can confuse a user if they click there and start typing,
     // because being in the mailquote may affect wrapping behavior, or font color, etc.
     WSRunObject wsObj(htmlEditor, selNode, selOffset);
     nsCOMPtr<nsINode> visNode;
     int32_t visOffset=0;
     WSType wsType;
-    wsObj.NextVisibleNode(selNode, selOffset, address_of(visNode),
-                          &visOffset, &wsType);
+    wsObj.NextVisibleNode(EditorRawDOMPoint(selNode, selOffset),
+                          address_of(visNode), &visOffset, &wsType);
     if (wsType == WSType::br) {
       // ok, we are just before a break.  is it inside the mailquote?
       if (visNode != citeNode && citeNode->Contains(visNode)) {
         // it is.  so lets reset our selection to be just after it.
         selNode = EditorBase::GetNodeLocation(visNode, &selOffset);
         ++selOffset;
       }
     }
@@ -2077,22 +2077,22 @@ HTMLEditRules::SplitMailCites(Selection*
     // We need to examine the content both before the br we just added and also
     // just after it.  If we don't have another br or block boundary adjacent,
     // then we will need a 2nd br added to achieve blank line that user expects.
     if (IsInlineNode(*citeNode)) {
       WSRunObject wsObj(htmlEditor, selNode, selOffset);
       nsCOMPtr<nsINode> visNode;
       int32_t visOffset=0;
       WSType wsType;
-      wsObj.PriorVisibleNode(selNode, selOffset, address_of(visNode),
-                             &visOffset, &wsType);
+      wsObj.PriorVisibleNode(EditorRawDOMPoint(selNode, selOffset),
+                             address_of(visNode), &visOffset, &wsType);
       if (wsType == WSType::normalWS || wsType == WSType::text ||
           wsType == WSType::special) {
         WSRunObject wsObjAfterBR(htmlEditor, selNode, selOffset + 1);
-        wsObjAfterBR.NextVisibleNode(selNode, selOffset + 1,
+        wsObjAfterBR.NextVisibleNode(EditorRawDOMPoint(selNode, selOffset + 1),
                                      address_of(visNode), &visOffset, &wsType);
         if (wsType == WSType::normalWS || wsType == WSType::text ||
             wsType == WSType::special ||
             // In case we're at the very end.
             wsType == WSType::thisBlock) {
           brNode = htmlEditor->CreateBR(EditorRawDOMPoint(selNode, selOffset));
           NS_ENSURE_STATE(brNode);
         }
@@ -2232,21 +2232,21 @@ HTMLEditRules::WillDeleteSelection(Selec
     NS_ENSURE_STATE(mHTMLEditor);
     WSRunObject wsObj(mHTMLEditor, startNode, startOffset);
     nsCOMPtr<nsINode> visNode;
     int32_t visOffset;
     WSType wsType;
 
     // Find next visible node
     if (aAction == nsIEditor::eNext) {
-      wsObj.NextVisibleNode(startNode, startOffset, address_of(visNode),
-                            &visOffset, &wsType);
+      wsObj.NextVisibleNode(EditorRawDOMPoint(startNode, startOffset),
+                            address_of(visNode), &visOffset, &wsType);
     } else {
-      wsObj.PriorVisibleNode(startNode, startOffset, address_of(visNode),
-                             &visOffset, &wsType);
+      wsObj.PriorVisibleNode(EditorRawDOMPoint(startNode, startOffset),
+                             address_of(visNode), &visOffset, &wsType);
     }
 
     if (!visNode) {
       // Can't find anything to delete!
       *aCancel = true;
       // XXX This is the result of mHTMLEditor->GetFirstSelectedCell().
       //     The value could be both an error and NS_OK.
       return rv;
@@ -2392,17 +2392,18 @@ HTMLEditRules::WillDeleteSelection(Selec
 
           // There is one exception to the move only case.  If the <hr> is
           // followed by a <br> we want to delete the <br>.
 
           WSType otherWSType;
           nsCOMPtr<nsINode> otherNode;
           int32_t otherOffset;
 
-          wsObj.NextVisibleNode(startNode, startOffset, address_of(otherNode),
+          wsObj.NextVisibleNode(EditorRawDOMPoint(startNode, startOffset),
+                                address_of(otherNode),
                                 &otherOffset, &otherWSType);
 
           if (otherWSType == WSType::br) {
             // Delete the <br>
 
             NS_ENSURE_STATE(mHTMLEditor);
             nsCOMPtr<nsIContent> otherContent(do_QueryInterface(otherNode));
             rv = WSRunObject::PrepareToDeleteNode(mHTMLEditor, otherContent);
@@ -2466,20 +2467,22 @@ HTMLEditRules::WillDeleteSelection(Selec
       // block.
       bool bDeletedBR = false;
       WSType otherWSType;
       nsCOMPtr<nsINode> otherNode;
       int32_t otherOffset;
 
       // Find node in other direction
       if (aAction == nsIEditor::eNext) {
-        wsObj.PriorVisibleNode(startNode, startOffset, address_of(otherNode),
+        wsObj.PriorVisibleNode(EditorRawDOMPoint(startNode, startOffset),
+                               address_of(otherNode),
                                &otherOffset, &otherWSType);
       } else {
-        wsObj.NextVisibleNode(startNode, startOffset, address_of(otherNode),
+        wsObj.NextVisibleNode(EditorRawDOMPoint(startNode, startOffset),
+                              address_of(otherNode),
                               &otherOffset, &otherWSType);
       }
 
       // First find the adjacent node in the block
       nsCOMPtr<nsIContent> leafNode;
       nsCOMPtr<nsINode> leftNode, rightNode;
       if (aAction == nsIEditor::ePrevious) {
         NS_ENSURE_STATE(mHTMLEditor);
@@ -5541,18 +5544,18 @@ HTMLEditRules::ExpandSelectionForDeletio
   WSType wsType;
   nsCOMPtr<Element> root = mHTMLEditor->GetActiveEditingHost();
   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
   // Find previous visible thingy before start of selection
   if (selStartNode != selCommon && selStartNode != root) {
     while (true) {
       WSRunObject wsObj(mHTMLEditor, selStartNode, selStartOffset);
-      wsObj.PriorVisibleNode(selStartNode, selStartOffset, address_of(unused),
-                             &visOffset, &wsType);
+      wsObj.PriorVisibleNode(EditorRawDOMPoint(selStartNode, selStartOffset),
+                             address_of(unused), &visOffset, &wsType);
       if (wsType != WSType::thisBlock) {
         break;
       }
       // We want to keep looking up.  But stop if we are crossing table
       // element boundaries, or if we hit the root.
       if (HTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) ||
           selCommon == wsObj.mStartReasonNode ||
           root == wsObj.mStartReasonNode) {
@@ -5563,18 +5566,18 @@ HTMLEditRules::ExpandSelectionForDeletio
         selStartNode->ComputeIndexOf(wsObj.mStartReasonNode) : -1;
     }
   }
 
   // Find next visible thingy after end of selection
   if (selEndNode != selCommon && selEndNode != root) {
     for (;;) {
       WSRunObject wsObj(mHTMLEditor, selEndNode, selEndOffset);
-      wsObj.NextVisibleNode(selEndNode, selEndOffset, address_of(unused),
-                            &visOffset, &wsType);
+      wsObj.NextVisibleNode(EditorRawDOMPoint(selEndNode, selEndOffset),
+                            address_of(unused), &visOffset, &wsType);
       if (wsType == WSType::br) {
         if (mHTMLEditor->IsVisibleBRElement(wsObj.mEndReasonNode)) {
           break;
         }
         if (!firstBRParent) {
           firstBRParent = selEndNode;
           firstBROffset = selEndOffset;
         }
@@ -5690,17 +5693,17 @@ HTMLEditRules::NormalizeSelection(Select
   nsCOMPtr<nsINode> unused;
   int32_t offset = -1;
   WSType wsType;
 
   // let the whitespace code do the heavy lifting
   WSRunObject wsEndObj(htmlEditor, endNode, static_cast<int32_t>(endOffset));
   // is there any intervening visible whitespace?  if so we can't push selection past that,
   // it would visibly change maening of users selection
-  wsEndObj.PriorVisibleNode(endNode, static_cast<int32_t>(endOffset),
+  wsEndObj.PriorVisibleNode(EditorRawDOMPoint(endNode, endOffset),
                             address_of(unused), &offset, &wsType);
   if (wsType != WSType::text && wsType != WSType::normalWS) {
     // eThisBlock and eOtherBlock conveniently distinquish cases
     // of going "down" into a block and "up" out of a block.
     if (wsEndObj.mStartReason == WSType::otherBlock) {
       // endpoint is just after the close of a block.
       nsINode* child =
         htmlEditor->GetRightmostChild(wsEndObj.mStartReasonNode, true);
@@ -5732,17 +5735,17 @@ HTMLEditRules::NormalizeSelection(Select
   }
 
 
   // similar dealio for start of range
   WSRunObject wsStartObj(htmlEditor, startNode,
                          static_cast<int32_t>(startOffset));
   // is there any intervening visible whitespace?  if so we can't push selection past that,
   // it would visibly change maening of users selection
-  wsStartObj.NextVisibleNode(startNode, static_cast<int32_t>(startOffset),
+  wsStartObj.NextVisibleNode(EditorRawDOMPoint(startNode, startOffset),
                              address_of(unused), &offset, &wsType);
   if (wsType != WSType::text && wsType != WSType::normalWS) {
     // eThisBlock and eOtherBlock conveniently distinquish cases
     // of going "down" into a block and "up" out of a block.
     if (wsStartObj.mEndReason == WSType::otherBlock) {
       // startpoint is just before the start of a block.
       nsINode* child =
         htmlEditor->GetLeftmostChild(wsStartObj.mEndReasonNode, true);
@@ -7300,18 +7303,18 @@ HTMLEditRules::ReturnInListItem(Selectio
           }
           return NS_OK;
         }
       } else {
         WSRunObject wsObj(htmlEditor, &aListItem, 0);
         nsCOMPtr<nsINode> visNode;
         int32_t visOffset = 0;
         WSType wsType;
-        wsObj.NextVisibleNode(&aListItem, 0, address_of(visNode),
-                              &visOffset, &wsType);
+        wsObj.NextVisibleNode(EditorRawDOMPoint(&aListItem, 0),
+                              address_of(visNode), &visOffset, &wsType);
         if (wsType == WSType::special || wsType == WSType::br ||
             visNode->IsHTMLElement(nsGkAtoms::hr)) {
           EditorRawDOMPoint atVisNode(visNode);
           if (NS_WARN_IF(!atVisNode.IsSetAndValid())) {
             return NS_ERROR_FAILURE;
           }
           ErrorResult error;
           aSelection.Collapse(atVisNode, error);
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -591,18 +591,17 @@ HTMLEditor::MaybeCollapseSelectionAtFirs
   // Find first editable and visible node.
   EditorRawDOMPoint pointToPutCaret(editingHost, 0);
   for (;;) {
     WSRunObject wsObj(this, pointToPutCaret.GetContainer(),
                       pointToPutCaret.Offset());
     int32_t visOffset = 0;
     WSType visType;
     nsCOMPtr<nsINode> visNode;
-    wsObj.NextVisibleNode(pointToPutCaret.GetContainer(),
-                          pointToPutCaret.Offset(),
+    wsObj.NextVisibleNode(pointToPutCaret,
                           address_of(visNode), &visOffset, &visType);
 
     // If we meet a non-editable node first, we should move caret to start of
     // the editing host (perhaps, user may want to insert something before
     // the first non-editable node? Chromium behaves so).
     if (visNode && !visNode->IsEditable()) {
       pointToPutCaret.Set(editingHost, 0);
       break;
@@ -1002,18 +1001,18 @@ HTMLEditor::IsVisibleBRElement(nsINode* 
   int32_t selOffset;
   nsCOMPtr<nsINode> selNode = GetNodeLocation(aNode, &selOffset);
   // Let's look after the break
   selOffset++;
   WSRunObject wsObj(this, selNode, selOffset);
   nsCOMPtr<nsINode> unused;
   int32_t visOffset = 0;
   WSType visType;
-  wsObj.NextVisibleNode(selNode, selOffset, address_of(unused),
-                        &visOffset, &visType);
+  wsObj.NextVisibleNode(EditorRawDOMPoint(selNode, selOffset),
+                        address_of(unused), &visOffset, &visType);
   if (visType & WSType::block) {
     return false;
   }
 
   return true;
 }
 
 NS_IMETHODIMP
@@ -1471,35 +1470,33 @@ HTMLEditor::GetBetterInsertionPointFor(n
                     aPointToInsert.Offset());
 
   // If the insertion position is after the last visible item in a line,
   // i.e., the insertion position is just before a visible line break <br>,
   // we want to skip to the position just after the line break (see bug 68767).
   nsCOMPtr<nsINode> nextVisibleNode;
   int32_t nextVisibleOffset = 0;
   WSType nextVisibleType;
-  wsObj.NextVisibleNode(aPointToInsert.GetContainer(), aPointToInsert.Offset(),
-                        address_of(nextVisibleNode),
+  wsObj.NextVisibleNode(aPointToInsert, address_of(nextVisibleNode),
                         &nextVisibleOffset, &nextVisibleType);
   // So, if the next visible node isn't a <br> element, we can insert the block
   // level element to the point.
   if (!nextVisibleNode ||
       !(nextVisibleType & WSType::br)) {
     return aPointToInsert;
   }
 
   // However, we must not skip next <br> element when the caret appears to be
   // positioned at the beginning of a block, in that case skipping the <br>
   // would not insert the <br> at the caret position, but after the current
   // empty line.
   nsCOMPtr<nsINode> previousVisibleNode;
   int32_t previousVisibleOffset = 0;
   WSType previousVisibleType;
-  wsObj.PriorVisibleNode(aPointToInsert.GetContainer(), aPointToInsert.Offset(),
-                         address_of(previousVisibleNode),
+  wsObj.PriorVisibleNode(aPointToInsert, address_of(previousVisibleNode),
                          &previousVisibleOffset, &previousVisibleType);
   // So, if there is no previous visible node,
   // or, if both nodes of the insertion point is <br> elements,
   // or, if the previous visible node is different block,
   // we need to skip the following <br>.  So, otherwise, we can insert the
   // block at the insertion point.
   if (!previousVisibleNode ||
       (previousVisibleType & WSType::br) ||
@@ -4002,17 +3999,18 @@ HTMLEditor::IsVisibleTextNode(Text& aTex
   if (!aText.TextIsOnlyWhitespace()) {
     return true;
   }
 
   WSRunObject wsRunObj(this, &aText, 0);
   nsCOMPtr<nsINode> nextVisibleNode;
   int32_t unused = 0;
   WSType visibleNodeType;
-  wsRunObj.NextVisibleNode(&aText, 0, address_of(nextVisibleNode),
+  wsRunObj.NextVisibleNode(EditorRawDOMPoint(&aText, 0),
+                           address_of(nextVisibleNode),
                            &unused, &visibleNodeType);
   return (visibleNodeType == WSType::normalWS ||
           visibleNodeType == WSType::text) &&
          &aText == nextVisibleNode;
 }
 
 /**
  * IsEmptyNode() figures out if aNode is an empty node.  A block can have
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -618,32 +618,33 @@ HTMLEditor::DoInsertHTMLWithContext(cons
         selOffset = pointAtContainer.Offset() + 1;
       }
 
       // make sure we don't end up with selection collapsed after an invisible break node
       WSRunObject wsRunObj(this, selNode, selOffset);
       nsCOMPtr<nsINode> visNode;
       int32_t outVisOffset=0;
       WSType visType;
-      wsRunObj.PriorVisibleNode(selNode, selOffset, address_of(visNode),
-                                &outVisOffset, &visType);
+      wsRunObj.PriorVisibleNode(EditorRawDOMPoint(selNode, selOffset),
+                                address_of(visNode), &outVisOffset, &visType);
       if (visType == WSType::br) {
         // we are after a break.  Is it visible?  Despite the name,
         // PriorVisibleNode does not make that determination for breaks.
         // It also may not return the break in visNode.  We have to pull it
         // out of the WSRunObject's state.
         if (!IsVisibleBRElement(wsRunObj.mStartReasonNode)) {
           // don't leave selection past an invisible break;
           // reset {selNode,selOffset} to point before break
           EditorRawDOMPoint atStartReasonNode(wsRunObj.mStartReasonNode);
           selNode = atStartReasonNode.GetContainer();
           selOffset = atStartReasonNode.Offset();
           // we want to be inside any inline style prior to break
           WSRunObject wsRunObj(this, selNode, selOffset);
-          wsRunObj.PriorVisibleNode(selNode, selOffset, address_of(visNode),
+          wsRunObj.PriorVisibleNode(EditorRawDOMPoint(selNode, selOffset),
+                                    address_of(visNode),
                                     &outVisOffset, &visType);
           if (visType == WSType::text || visType == WSType::normalWS) {
             selNode = visNode;
             selOffset = outVisOffset;  // PriorVisibleNode already set offset to _after_ the text or ws
           } else if (visType == WSType::special) {
             // prior visible thing is an image or some other non-text thingy.
             // We want to be right after it.
             atStartReasonNode.Set(wsRunObj.mStartReasonNode);
--- a/editor/libeditor/WSRunObject.cpp
+++ b/editor/libeditor/WSRunObject.cpp
@@ -33,16 +33,32 @@ namespace mozilla {
 using namespace dom;
 
 const char16_t kNBSP = 160;
 
 template WSRunObject::WSRunObject(HTMLEditor* aHTMLEditor,
                                   const EditorDOMPoint& aPoint);
 template WSRunObject::WSRunObject(HTMLEditor* aHTMLEditor,
                                   const EditorRawDOMPoint& aPoint);
+template void WSRunObject::PriorVisibleNode(const EditorDOMPoint& aPoint,
+                                            nsCOMPtr<nsINode>* outVisNode,
+                                            int32_t* outVisOffset,
+                                            WSType* outType);
+template void WSRunObject::PriorVisibleNode(const EditorRawDOMPoint& aPoint,
+                                            nsCOMPtr<nsINode>* outVisNode,
+                                            int32_t* outVisOffset,
+                                            WSType* outType);
+template void WSRunObject::NextVisibleNode(const EditorDOMPoint& aPoint,
+                                           nsCOMPtr<nsINode>* outVisNode,
+                                           int32_t* outVisOffset,
+                                           WSType* outType);
+template void WSRunObject::NextVisibleNode(const EditorRawDOMPoint& aPoint,
+                                           nsCOMPtr<nsINode>* outVisNode,
+                                           int32_t* outVisOffset,
+                                           WSType* outType);
 
 template<typename PT, typename CT>
 WSRunObject::WSRunObject(HTMLEditor* aHTMLEditor,
                          const EditorDOMPointBase<PT, CT>& aPoint)
   : WSRunObject(aHTMLEditor, aPoint.GetContainer(), aPoint.Offset())
 {
 }
 
@@ -511,34 +527,34 @@ WSRunObject::DeleteWSForward()
       return rv;
     }
     return NS_OK;
   }
 
   return NS_OK;
 }
 
+template<typename PT, typename CT>
 void
-WSRunObject::PriorVisibleNode(nsINode* aNode,
-                              int32_t aOffset,
+WSRunObject::PriorVisibleNode(const EditorDOMPointBase<PT, CT>& aPoint,
                               nsCOMPtr<nsINode>* outVisNode,
                               int32_t* outVisOffset,
                               WSType* outType)
 {
   // Find first visible thing before the point.  Position
   // outVisNode/outVisOffset just _after_ that thing.  If we don't find
   // anything return start of ws.
-  MOZ_ASSERT(aNode && outVisNode && outVisOffset && outType);
+  MOZ_ASSERT(aPoint.IsSet() && outVisNode && outVisOffset && outType);
 
-  WSFragment* run = FindNearestRun(EditorRawDOMPoint(aNode, aOffset), false);
+  WSFragment* run = FindNearestRun(aPoint, false);
 
   // Is there a visible run there or earlier?
   for (; run; run = run->mLeft) {
     if (run->mType == WSType::normalWS) {
-      WSPoint point = GetPreviousCharPoint(EditorRawDOMPoint(aNode, aOffset));
+      WSPoint point = GetPreviousCharPoint(aPoint);
       // When it's a non-empty text node, return it.
       if (point.mTextNode && point.mTextNode->Length()) {
         *outVisNode = point.mTextNode;
         *outVisOffset = point.mOffset + 1;
         if (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == kNBSP) {
           *outType = WSType::normalWS;
         } else {
           *outType = WSType::text;
@@ -551,35 +567,34 @@ WSRunObject::PriorVisibleNode(nsINode* a
 
   // If we get here, then nothing in ws data to find.  Return start reason.
   *outVisNode = mStartReasonNode;
   // This really isn't meaningful if mStartReasonNode != mStartNode
   *outVisOffset = mStartOffset;
   *outType = mStartReason;
 }
 
-
+template<typename PT, typename CT>
 void
-WSRunObject::NextVisibleNode(nsINode* aNode,
-                             int32_t aOffset,
+WSRunObject::NextVisibleNode(const EditorDOMPointBase<PT, CT>& aPoint,
                              nsCOMPtr<nsINode>* outVisNode,
                              int32_t* outVisOffset,
                              WSType* outType)
 {
   // Find first visible thing after the point.  Position
   // outVisNode/outVisOffset just _before_ that thing.  If we don't find
   // anything return end of ws.
-  MOZ_ASSERT(aNode && outVisNode && outVisOffset && outType);
+  MOZ_ASSERT(aPoint.IsSet() && outVisNode && outVisOffset && outType);
 
-  WSFragment* run = FindNearestRun(EditorRawDOMPoint(aNode, aOffset), true);
+  WSFragment* run = FindNearestRun(aPoint, true);
 
   // Is there a visible run there or later?
   for (; run; run = run->mRight) {
     if (run->mType == WSType::normalWS) {
-      WSPoint point = GetNextCharPoint(EditorRawDOMPoint(aNode, aOffset));
+      WSPoint point = GetNextCharPoint(aPoint);
       // When it's a non-empty text node, return it.
       if (point.mTextNode && point.mTextNode->Length()) {
         *outVisNode = point.mTextNode;
         *outVisOffset = point.mOffset;
         if (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == kNBSP) {
           *outType = WSType::normalWS;
         } else {
           *outType = WSType::text;
@@ -1394,32 +1409,34 @@ WSRunObject::DeleteRange(const EditorRaw
         --count;
         --idx;
       }
     }
   }
   return NS_OK;
 }
 
+template<typename PT, typename CT>
 WSRunObject::WSPoint
-WSRunObject::GetNextCharPoint(const EditorRawDOMPoint& aPoint)
+WSRunObject::GetNextCharPoint(const EditorDOMPointBase<PT, CT>& aPoint)
 {
   MOZ_ASSERT(aPoint.IsSetAndValid());
 
   int32_t idx = mNodeArray.IndexOf(aPoint.GetContainer());
   if (idx == -1) {
     // Use range comparisons to get next text node which is in mNodeArray.
     return GetNextCharPointInternal(aPoint);
   }
   // Use WSPoint version of GetNextCharPoint()
   return GetNextCharPoint(WSPoint(mNodeArray[idx], aPoint.Offset(), 0));
 }
 
+template<typename PT, typename CT>
 WSRunObject::WSPoint
-WSRunObject::GetPreviousCharPoint(const EditorRawDOMPoint& aPoint)
+WSRunObject::GetPreviousCharPoint(const EditorDOMPointBase<PT, CT>& aPoint)
 {
   MOZ_ASSERT(aPoint.IsSetAndValid());
 
   int32_t idx = mNodeArray.IndexOf(aPoint.GetContainer());
   if (idx == -1) {
     // Use range comparisons to get previous text node which is in mNodeArray.
     return GetPreviousCharPointInternal(aPoint);
   }
@@ -1599,18 +1616,19 @@ WSRunObject::GetASCIIWhitespacesBounds(i
   }
 
   startNode.forget(outStartNode);
   *outStartOffset = startOffset;
   endNode.forget(outEndNode);
   *outEndOffset = endOffset;
 }
 
+template<typename PT, typename CT>
 WSRunObject::WSFragment*
-WSRunObject::FindNearestRun(const EditorRawDOMPoint& aPoint,
+WSRunObject::FindNearestRun(const EditorDOMPointBase<PT, CT>& aPoint,
                             bool aForward)
 {
   MOZ_ASSERT(aPoint.IsSetAndValid());
 
   for (WSFragment* run = mStartRun; run; run = run->mRight) {
     int32_t comp = run->mStartNode ?
       nsContentUtils::ComparePoints(aPoint, run->StartPoint()) : -1;
     if (comp <= 0) {
@@ -1652,18 +1670,19 @@ WSRunObject::GetCharAt(Text* aTextNode,
 
   int32_t len = int32_t(aTextNode->TextLength());
   if (aOffset < 0 || aOffset >= len) {
     return 0;
   }
   return aTextNode->GetText()->CharAt(aOffset);
 }
 
+template<typename PT, typename CT>
 WSRunObject::WSPoint
-WSRunObject::GetNextCharPointInternal(const EditorRawDOMPoint& aPoint)
+WSRunObject::GetNextCharPointInternal(const EditorDOMPointBase<PT, CT>& aPoint)
 {
   // Note: only to be called if aPoint.GetContainer() is not a ws node.
 
   // Binary search on wsnodes
   uint32_t numNodes = mNodeArray.Length();
 
   if (!numNodes) {
     // Do nothing if there are no nodes to search
@@ -1700,18 +1719,20 @@ WSRunObject::GetNextCharPointInternal(co
   }
 
   // The char after the point is the first character of our range.
   RefPtr<Text> textNode(mNodeArray[curNum]);
   WSPoint point(textNode, 0, 0);
   return GetNextCharPoint(point);
 }
 
+template<typename PT, typename CT>
 WSRunObject::WSPoint
-WSRunObject::GetPreviousCharPointInternal(const EditorRawDOMPoint& aPoint)
+WSRunObject::GetPreviousCharPointInternal(
+               const EditorDOMPointBase<PT, CT>& aPoint)
 {
   // Note: only to be called if aNode is not a ws node.
 
   // Binary search on wsnodes
   uint32_t numNodes = mNodeArray.Length();
 
   if (!numNodes) {
     // Do nothing if there are no nodes to search
--- a/editor/libeditor/WSRunObject.h
+++ b/editor/libeditor/WSRunObject.h
@@ -267,32 +267,32 @@ public:
   // significance.
   nsresult DeleteWSBackward();
 
   // DeleteWSForward deletes a single visible piece of ws after the ws point
   // (the point to create the wsRunObject, passed to its constructor).  It
   // makes any needed conversion to adjacent ws to retain its significance.
   nsresult DeleteWSForward();
 
-  // PriorVisibleNode returns the first piece of visible thing before
-  // {aNode,aOffset}.  If there is no visible ws qualifying it returns what
-  // is before the ws run.  Note that {outVisNode,outVisOffset} is set to
-  // just AFTER the visible object.
-  void PriorVisibleNode(nsINode* aNode,
-                        int32_t aOffset,
+  // PriorVisibleNode() returns the first piece of visible thing before aPoint.
+  // If there is no visible ws qualifying it returns what is before the ws run.
+  // Note that {outVisNode,outVisOffset} is set to just AFTER the visible
+  // object.
+  template<typename PT, typename CT>
+  void PriorVisibleNode(const EditorDOMPointBase<PT, CT>& aPoint,
                         nsCOMPtr<nsINode>* outVisNode,
                         int32_t* outVisOffset,
                         WSType* outType);
 
-  // NextVisibleNode returns the first piece of visible thing after
-  // {aNode,aOffset}.  If there is no visible ws qualifying it returns what
-  // is after the ws run.  Note that {outVisNode,outVisOffset} is set to just
-  // BEFORE the visible object.
-  void NextVisibleNode(nsINode* aNode,
-                       int32_t aOffset,
+  // NextVisibleNode() returns the first piece of visible thing after aPoint.
+  // If there is no visible ws qualifying it returns what is after the ws run.
+  // Note that {outVisNode,outVisOffset} is set to just BEFORE the visible
+  // object.
+  template<typename PT, typename CT>
+  void NextVisibleNode(const EditorDOMPointBase<PT, CT>& aPoint,
                        nsCOMPtr<nsINode>* outVisNode,
                        int32_t* outVisOffset,
                        WSType* outType);
 
   // AdjustWhitespace examines the ws object for nbsp's that can
   // be safely converted to regular ascii space and converts them.
   nsresult AdjustWhitespace();
 
@@ -383,37 +383,42 @@ protected:
    */
   nsresult DeleteRange(const EditorRawDOMPoint& aStartPoint,
                        const EditorRawDOMPoint& aEndPoint);
 
   /**
    * GetNextCharPoint() returns next character's point of aPoint.  If there is
    * no character after aPoint, mTextNode is set to nullptr.
    */
-  WSPoint GetNextCharPoint(const EditorRawDOMPoint& aPoint);
+  template<typename PT, typename CT>
+  WSPoint GetNextCharPoint(const EditorDOMPointBase<PT, CT>& aPoint);
   WSPoint GetNextCharPoint(const WSPoint& aPoint);
 
   /**
    * GetPreviousCharPoint() returns previous character's point of of aPoint.
    * If there is no character before aPoint, mTextNode is set to nullptr.
    */
-  WSPoint GetPreviousCharPoint(const EditorRawDOMPoint& aPoint);
+  template<typename PT, typename CT>
+  WSPoint GetPreviousCharPoint(const EditorDOMPointBase<PT, CT>& aPoint);
   WSPoint GetPreviousCharPoint(const WSPoint& aPoint);
 
   /**
    * GetNextCharPointInternal() and GetPreviousCharPointInternal() are
    * helper methods of GetNextCharPoint(const EditorRawDOMPoint&) and
    * GetPreviousCharPoint(const EditorRawDOMPoint&).  When the container
    * isn't in mNodeArray, they call one of these methods.  Then, these
    * methods look for nearest text node in mNodeArray from aPoint.
    * Then, will call GetNextCharPoint(const WSPoint&) or
    * GetPreviousCharPoint(const WSPoint&) and returns its result.
    */
-  WSPoint GetNextCharPointInternal(const EditorRawDOMPoint& aPoint);
-  WSPoint GetPreviousCharPointInternal(const EditorRawDOMPoint& aPoint);
+  template<typename PT, typename CT>
+  WSPoint GetNextCharPointInternal(const EditorDOMPointBase<PT, CT>& aPoint);
+  template<typename PT, typename CT>
+  WSPoint
+  GetPreviousCharPointInternal(const EditorDOMPointBase<PT, CT>& aPoint);
 
   /**
    * InsertNBSPAndRemoveFollowingASCIIWhitespaces() inserts an NBSP first.
    * Then, if following characters are ASCII whitespaces, will remove them.
    */
   nsresult InsertNBSPAndRemoveFollowingASCIIWhitespaces(WSPoint aPoint);
 
   /**
@@ -461,17 +466,19 @@ protected:
    *                      run.
    *                      If aPoint is after the last run, returns nullptr.
    *                    If aForward is false and:
    *                      if aPoint is end of a run, returns the run.
    *                      if aPoint is start of a run, returns its next run.
    *                      if aPoint is before the first run, returns nullptr.
    *                      if aPoint is after the last run, returns the last run.
    */
-  WSFragment* FindNearestRun(const EditorRawDOMPoint& aPoint, bool aForward);
+  template<typename PT, typename CT>
+  WSFragment* FindNearestRun(const EditorDOMPointBase<PT, CT>& aPoint,
+                             bool aForward);
 
   char16_t GetCharAt(dom::Text* aTextNode, int32_t aOffset);
   nsresult CheckTrailingNBSPOfRun(WSFragment *aRun);
 
   /**
    * ReplacePreviousNBSPIfUnncessary() replaces previous character of aPoint
    * if it's a NBSP and it's unnecessary.
    *