Bug 1377978 - Make nsRange use uint32_t to offset r?smaug draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 19 Jul 2017 22:49:52 +0900
changeset 611945 4c3ffaf0c35b0490da8f9b96c33e532132630acf
parent 611714 eb1d92b2b6a4161492561250f51bae5bafeda68a
child 612059 962ba326cd3ed67ae15423773a1ad59d73a60fad
push id69329
push usermasayuki@d-toybox.com
push dateThu, 20 Jul 2017 05:32:16 +0000
reviewerssmaug
bugs1377978
milestone56.0a1
Bug 1377978 - Make nsRange use uint32_t to offset r?smaug DOM Standard defines that offset of Range is unsigned long. However, nsRange uses int32_t to them. This patch makes nsRange use uint32_t instead. However, this patch does NOT allow to set over INT32_MAX as offset values since a lot of users of nsRange cannot treat the values as over INT32_MAX because a lot of internal APIs take int32_t as offsets. For easier to search such points, this patch adds static_cast<int32_t> to uint32_t variables when they are used for int32_t arguments. And note that nsContentUtils::ComparePoints() behaves odd. It accepts negative offset and compares such value with valid offset simply. This patch still uses int32_t offset variables in nsRange::CompareNodeToRange() even though it may be negative value if nsINode::IndexOf() returns -1 because the caller of it depends on this behavior. MozReview-Commit-ID: 8RbOgA86JuT
dom/base/Selection.cpp
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsDocumentEncoder.cpp
dom/base/nsFocusManager.cpp
dom/base/nsRange.cpp
dom/base/nsRange.h
dom/interfaces/range/nsIDOMRange.idl
editor/libeditor/EditorBase.cpp
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditorDataTransfer.cpp
editor/libeditor/HTMLStyleEditor.cpp
editor/libeditor/HTMLTableEditor.cpp
editor/txtsvc/nsFilteredContentIterator.cpp
editor/txtsvc/nsTextServicesDocument.cpp
extensions/spellcheck/src/mozInlineSpellChecker.cpp
layout/base/PresShell.cpp
layout/generic/nsImageFrame.cpp
toolkit/components/find/nsFind.cpp
toolkit/components/find/nsWebBrowserFind.cpp
toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -1397,23 +1397,24 @@ Selection::GetType(int16_t* aType)
 //
 //    Compares the range beginning or ending point, and returns true if it
 //    exactly matches the given DOM point.
 
 static inline bool
 RangeMatchesBeginPoint(nsRange* aRange, nsINode* aNode, int32_t aOffset)
 {
   return aRange->GetStartContainer() == aNode &&
-         aRange->StartOffset() == aOffset;
+         static_cast<int32_t>(aRange->StartOffset()) == aOffset;
 }
 
 static inline bool
 RangeMatchesEndPoint(nsRange* aRange, nsINode* aNode, int32_t aOffset)
 {
-  return aRange->GetEndContainer() == aNode && aRange->EndOffset() == aOffset;
+  return aRange->GetEndContainer() == aNode &&
+         static_cast<int32_t>(aRange->EndOffset()) == aOffset;
 }
 
 // Selection::EqualsRangeAtPoint
 //
 //    Utility method for checking equivalence of two ranges.
 
 bool
 Selection::EqualsRangeAtPoint(
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -2769,16 +2769,19 @@ nsContentUtils::PositionIsBefore(nsINode
 
 /* static */
 int32_t
 nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
                               nsINode* aParent2, int32_t aOffset2,
                               bool* aDisconnected)
 {
   if (aParent1 == aParent2) {
+    // XXX This is odd.  aOffset1 and/or aOffset2 may be -1, e.g., it's result
+    //     of nsINode::IndexOf(), but this compares such invalid offset with
+    //     valid offset.
     return aOffset1 < aOffset2 ? -1 :
            aOffset1 > aOffset2 ? 1 :
            0;
   }
 
   AutoTArray<nsINode*, 32> parents1, parents2;
   nsINode* node1 = aParent1;
   nsINode* node2 = aParent2;
@@ -2819,20 +2822,24 @@ nsContentUtils::ComparePoints(nsINode* a
   // The parent chains never differed, so one of the nodes is an ancestor of
   // the other
 
   NS_ASSERTION(!pos1 || !pos2,
                "should have run out of parent chain for one of the nodes");
 
   if (!pos1) {
     nsINode* child2 = parents2.ElementAt(--pos2);
+    // XXX aOffset1 may be -1 as mentioned above.  So, why does this return
+    //     it's *before* of the valid DOM point?
     return aOffset1 <= parent->IndexOf(child2) ? -1 : 1;
   }
 
   nsINode* child1 = parents1.ElementAt(--pos1);
+  // XXX aOffset2 may be -1 as mentioned above.  So, why does this return it's
+  //     *after* of the valid DOM point?
   return parent->IndexOf(child1) < aOffset2 ? -1 : 1;
 }
 
 /* static */
 int32_t
 nsContentUtils::ComparePoints(nsIDOMNode* aParent1, int32_t aOffset1,
                               nsIDOMNode* aParent2, int32_t aOffset2,
                               bool* aDisconnected)
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -399,16 +399,23 @@ public:
   /**
    *  Utility routine to compare two "points", where a point is a
    *  node/offset pair
    *  Returns -1 if point1 < point2, 1, if point1 > point2,
    *  0 if error or if point1 == point2.
    *  NOTE! If the two nodes aren't in the same connected subtree,
    *  the result is 1, and the optional aDisconnected parameter
    *  is set to true.
+   *
+   *  XXX aOffset1 and aOffset2 should be uint32_t since valid offset value is
+   *      between 0 - UINT32_MAX.  However, these methods work even with
+   *      negative offset values!  E.g., when aOffset1 is -1 and aOffset is 0,
+   *      these methods return -1.  Some root callers depend on this behavior.
+   *      On the other hand, nsINode can have ATTRCHILD_ARRAY_MAX_CHILD_COUN
+   *      (0x3FFFFF) at most.  Therefore, they can be int32_t for now.
    */
   static int32_t ComparePoints(nsINode* aParent1, int32_t aOffset1,
                                nsINode* aParent2, int32_t aOffset2,
                                bool* aDisconnected = nullptr);
   static int32_t ComparePoints(nsIDOMNode* aParent1, int32_t aOffset1,
                                nsIDOMNode* aParent2, int32_t aOffset2,
                                bool* aDisconnected = nullptr);
 
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -1564,20 +1564,23 @@ nsHTMLCopyEncoder::IncludeInContext(nsIN
                                       nsGkAtoms::h5,
                                       nsGkAtoms::h6);
 }
 
 
 nsresult
 nsHTMLCopyEncoder::PromoteRange(nsIDOMRange *inRange)
 {
-  if (!inRange) return NS_ERROR_NULL_POINTER;
+  RefPtr<nsRange> range = static_cast<nsRange*>(inRange);
+  if (!range) {
+    return NS_ERROR_NULL_POINTER;
+  }
   nsresult rv;
   nsCOMPtr<nsIDOMNode> startNode, endNode, common;
-  int32_t startOffset, endOffset;
+  uint32_t startOffset, endOffset;
 
   rv = inRange->GetCommonAncestorContainer(getter_AddRefs(common));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = inRange->GetStartContainer(getter_AddRefs(startNode));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = inRange->GetStartOffset(&startOffset);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = inRange->GetEndContainer(getter_AddRefs(endNode));
@@ -1585,33 +1588,35 @@ nsHTMLCopyEncoder::PromoteRange(nsIDOMRa
   rv = inRange->GetEndOffset(&endOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMNode> opStartNode;
   nsCOMPtr<nsIDOMNode> opEndNode;
   int32_t opStartOffset, opEndOffset;
 
   // examine range endpoints.
-  rv = GetPromotedPoint( kStart, startNode, startOffset, address_of(opStartNode), &opStartOffset, common);
+  rv = GetPromotedPoint(kStart, startNode, static_cast<int32_t>(startOffset),
+                        address_of(opStartNode), &opStartOffset, common);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = GetPromotedPoint( kEnd, endNode, endOffset, address_of(opEndNode), &opEndOffset, common);
+  rv = GetPromotedPoint(kEnd, endNode, static_cast<int32_t>(endOffset),
+                        address_of(opEndNode), &opEndOffset, common);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // if both range endpoints are at the common ancestor, check for possible inclusion of ancestors
   if ( (opStartNode == common) && (opEndNode == common) )
   {
     rv = PromoteAncestorChain(address_of(opStartNode), &opStartOffset, &opEndOffset);
     NS_ENSURE_SUCCESS(rv, rv);
     opEndNode = opStartNode;
   }
 
   // set the range to the new values
-  rv = inRange->SetStart(opStartNode, opStartOffset);
+  rv = inRange->SetStart(opStartNode, static_cast<uint32_t>(opStartOffset));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = inRange->SetEnd(opEndNode, opEndOffset);
+  rv = inRange->SetEnd(opEndNode, static_cast<uint32_t>(opEndOffset));
   return rv;
 }
 
 
 // PromoteAncestorChain will promote a range represented by [{*ioNode,*ioStartOffset} , {*ioNode,*ioEndOffset}]
 // The promotion is different from that found in getPromotedPoint: it will only promote one endpoint if it can
 // promote the other.  Thus, instead of having a startnode/endNode, there is just the one ioNode.
 nsresult
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -2507,42 +2507,40 @@ nsFocusManager::GetSelectionLocation(nsI
   nsCOMPtr<nsISelection> domSelection;
   if (frameSelection) {
     domSelection = frameSelection->GetSelection(SelectionType::eNormal);
   }
 
   nsCOMPtr<nsIDOMNode> startNode, endNode;
   bool isCollapsed = false;
   nsCOMPtr<nsIContent> startContent, endContent;
-  int32_t startOffset = 0;
+  uint32_t startOffset = 0;
   if (domSelection) {
     domSelection->GetIsCollapsed(&isCollapsed);
     nsCOMPtr<nsIDOMRange> domRange;
     rv = domSelection->GetRangeAt(0, getter_AddRefs(domRange));
     if (domRange) {
       domRange->GetStartContainer(getter_AddRefs(startNode));
       domRange->GetEndContainer(getter_AddRefs(endNode));
       domRange->GetStartOffset(&startOffset);
 
       nsIContent *childContent = nullptr;
 
       startContent = do_QueryInterface(startNode);
       if (startContent && startContent->IsElement()) {
-        NS_ASSERTION(startOffset >= 0, "Start offset cannot be negative");
         childContent = startContent->GetChildAt(startOffset);
         if (childContent) {
           startContent = childContent;
         }
       }
 
       endContent = do_QueryInterface(endNode);
       if (endContent && endContent->IsElement()) {
-        int32_t endOffset = 0;
+        uint32_t endOffset = 0;
         domRange->GetEndOffset(&endOffset);
-        NS_ASSERTION(endOffset >= 0, "End offset cannot be negative");
         childContent = endContent->GetChildAt(endOffset);
         if (childContent) {
           endContent = childContent;
         }
       }
     }
   }
   else {
@@ -2560,17 +2558,17 @@ nsFocusManager::GetSelectionLocation(nsI
 
       if (startContent->NodeType() == nsIDOMNode::TEXT_NODE) {
         nsAutoString nodeValue;
         startContent->AppendTextTo(nodeValue);
 
         bool isFormControl =
           startContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL);
 
-        if (nodeValue.Length() == (uint32_t)startOffset && !isFormControl &&
+        if (nodeValue.Length() == startOffset && !isFormControl &&
             startContent != aDocument->GetRootElement()) {
           // Yes, indeed we were at the end of the last node
           nsCOMPtr<nsIFrameEnumerator> frameTraversal;
           nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
                                              presContext, startFrame,
                                              eLeaf,
                                              false, // aVisual
                                              false, // aLockInScrollView
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -106,41 +106,47 @@ nsRange::CompareNodeToRange(nsINode* aNo
   int32_t nodeStart, nodeEnd;
   nsINode* parent = aNode->GetParentNode();
   if (!parent) {
     // can't make a parent/offset pair to represent start or
     // end of the root node, because it has no parent.
     // so instead represent it by (node,0) and (node,numChildren)
     parent = aNode;
     nodeStart = 0;
-    nodeEnd = aNode->GetChildCount();
+    uint32_t childCount = aNode->GetChildCount();
+    MOZ_ASSERT(childCount <= INT32_MAX,
+               "There shouldn't be over INT32_MAX children");
+    nodeEnd = static_cast<int32_t>(childCount);
   }
   else {
     nodeStart = parent->IndexOf(aNode);
     nodeEnd = nodeStart + 1;
+    MOZ_ASSERT(nodeStart < nodeEnd, "nodeStart shouldn't be INT32_MAX");
   }
 
   nsINode* rangeStartContainer = aRange->GetStartContainer();
   nsINode* rangeEndContainer = aRange->GetEndContainer();
-  int32_t rangeStartOffset = aRange->StartOffset();
-  int32_t rangeEndOffset = aRange->EndOffset();
+  uint32_t rangeStartOffset = aRange->StartOffset();
+  uint32_t rangeEndOffset = aRange->EndOffset();
 
   // is RANGE(start) <= NODE(start) ?
   bool disconnected = false;
-  *outNodeBefore = nsContentUtils::ComparePoints(rangeStartContainer,
-                                                 rangeStartOffset,
-                                                 parent, nodeStart,
-                                                 &disconnected) > 0;
+  *outNodeBefore =
+    nsContentUtils::ComparePoints(rangeStartContainer,
+                                  static_cast<int32_t>(rangeStartOffset),
+                                  parent, nodeStart,
+                                  &disconnected) > 0;
   NS_ENSURE_TRUE(!disconnected, NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
 
   // is RANGE(end) >= NODE(end) ?
-  *outNodeAfter = nsContentUtils::ComparePoints(rangeEndContainer,
-                                                rangeEndOffset,
-                                                parent, nodeEnd,
-                                                &disconnected) < 0;
+  *outNodeAfter =
+    nsContentUtils::ComparePoints(rangeEndContainer,
+                                  static_cast<int32_t>(rangeEndOffset),
+                                  parent, nodeEnd,
+                                  &disconnected) < 0;
   NS_ENSURE_TRUE(!disconnected, NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
   return NS_OK;
 }
 
 static nsINode*
 GetNextRangeCommonAncestor(nsINode* aNode)
 {
   while (aNode && !aNode->IsCommonAncestorForRangeInSelection()) {
@@ -159,23 +165,27 @@ GetNextRangeCommonAncestor(nsINode* aNod
 struct IsItemInRangeComparator
 {
   nsINode* mNode;
   uint32_t mStartOffset;
   uint32_t mEndOffset;
 
   int operator()(const nsRange* const aRange) const
   {
-    int32_t cmp = nsContentUtils::ComparePoints(mNode, mEndOffset,
-                                                aRange->GetStartContainer(),
-                                                aRange->StartOffset());
+    int32_t cmp =
+      nsContentUtils::ComparePoints(
+        mNode, static_cast<int32_t>(mEndOffset),
+        aRange->GetStartContainer(),
+        static_cast<int32_t>(aRange->StartOffset()));
     if (cmp == 1) {
-      cmp = nsContentUtils::ComparePoints(mNode, mStartOffset,
-                                          aRange->GetEndContainer(),
-                                          aRange->EndOffset());
+      cmp =
+        nsContentUtils::ComparePoints(
+          mNode, static_cast<int32_t>(mStartOffset),
+          aRange->GetEndContainer(),
+          static_cast<int32_t>(aRange->EndOffset()));
       if (cmp == -1) {
         return 0;
       }
       return 1;
     }
     return -1;
   }
 };
@@ -261,18 +271,18 @@ nsRange::nsRange(nsINode* aNode)
 #endif
 {
   MOZ_ASSERT(aNode, "range isn't in a document!");
   mOwner = aNode->OwnerDoc();
 }
 
 /* static */
 nsresult
-nsRange::CreateRange(nsINode* aStartContainer, int32_t aStartOffset,
-                     nsINode* aEndParent, int32_t aEndOffset,
+nsRange::CreateRange(nsINode* aStartContainer, uint32_t aStartOffset,
+                     nsINode* aEndParent, uint32_t aEndOffset,
                      nsRange** aRange)
 {
   MOZ_ASSERT(aRange);
   *aRange = nullptr;
 
   RefPtr<nsRange> range = new nsRange(aStartContainer);
   nsresult rv = range->SetStartAndEnd(aStartContainer, aStartOffset,
                                       aEndParent, aEndOffset);
@@ -280,30 +290,30 @@ nsRange::CreateRange(nsINode* aStartCont
     return rv;
   }
   range.forget(aRange);
   return NS_OK;
 }
 
 /* static */
 nsresult
-nsRange::CreateRange(nsIDOMNode* aStartContainer, int32_t aStartOffset,
-                     nsIDOMNode* aEndParent, int32_t aEndOffset,
+nsRange::CreateRange(nsIDOMNode* aStartContainer, uint32_t aStartOffset,
+                     nsIDOMNode* aEndParent, uint32_t aEndOffset,
                      nsRange** aRange)
 {
   nsCOMPtr<nsINode> startContainer = do_QueryInterface(aStartContainer);
   nsCOMPtr<nsINode> endContainer = do_QueryInterface(aEndParent);
   return CreateRange(startContainer, aStartOffset,
                      endContainer, aEndOffset, aRange);
 }
 
 /* static */
 nsresult
-nsRange::CreateRange(nsIDOMNode* aStartContainer, int32_t aStartOffset,
-                     nsIDOMNode* aEndParent, int32_t aEndOffset,
+nsRange::CreateRange(nsIDOMNode* aStartContainer, uint32_t aStartOffset,
+                     nsIDOMNode* aEndParent, uint32_t aEndOffset,
                      nsIDOMRange** aRange)
 {
   RefPtr<nsRange> range;
   nsresult rv = nsRange::CreateRange(aStartContainer, aStartOffset, aEndParent,
                                      aEndOffset, getter_AddRefs(range));
   range.forget(aRange);
   return rv;
 }
@@ -451,49 +461,58 @@ nsRange::CharacterDataChanged(nsIDocumen
     // If the splitted text node is immediately before a range boundary point
     // that refers to a child index (i.e. its parent is the boundary container)
     // then we need to increment the corresponding offset to account for the new
     // text node that will be inserted.  If so, we need to prevent the next
     // ContentInserted or ContentAppended for this range from incrementing it
     // again (when the new text node is notified).
     nsINode* parentNode = aContent->GetParentNode();
     int32_t index = -1;
-    if (parentNode == mEndContainer && mEndOffset > 0 &&
-        (index = parentNode->IndexOf(aContent)) + 1 == mEndOffset) {
-      newEndNode = mEndContainer;
-      newEndOffset = mEndOffset + 1;
-      mEndOffsetWasIncremented = true;
+    if (parentNode == mEndContainer && mEndOffset > 0) {
+      index = parentNode->IndexOf(aContent);
+      NS_WARNING_ASSERTION(index >= 0,
+        "Shouldn't be called during removing the node or something");
+      if (static_cast<uint32_t>(index + 1) == mEndOffset) {
+        newEndNode = mEndContainer;
+        newEndOffset = mEndOffset + 1;
+        MOZ_ASSERT(IsValidOffset(newEndOffset));
+        mEndOffsetWasIncremented = true;
+      }
     }
-    if (parentNode == mStartContainer && mStartOffset > 0 &&
-        (index != -1 ? index : parentNode->IndexOf(aContent)) + 1 == mStartOffset) {
-      newStartNode = mStartContainer;
-      newStartOffset = mStartOffset + 1;
-      mStartOffsetWasIncremented = true;
+    if (parentNode == mStartContainer && mStartOffset > 0) {
+      if (index <= 0) {
+        index = parentNode->IndexOf(aContent);
+      }
+      if (static_cast<uint32_t>(index + 1) == mStartOffset) {
+        newStartNode = mStartContainer;
+        newStartOffset = mStartOffset + 1;
+        MOZ_ASSERT(IsValidOffset(newStartOffset));
+        mStartOffsetWasIncremented = true;
+      }
     }
 #ifdef DEBUG
     if (mStartOffsetWasIncremented || mEndOffsetWasIncremented) {
       mAssertNextInsertOrAppendIndex =
         (mStartOffsetWasIncremented ? newStartOffset : newEndOffset) - 1;
       mAssertNextInsertOrAppendNode = aInfo->mDetails->mNextSibling;
     }
 #endif
   }
 
   // If the changed node contains our start boundary and the change starts
   // before the boundary we'll need to adjust the offset.
-  if (aContent == mStartContainer &&
-      aInfo->mChangeStart < static_cast<uint32_t>(mStartOffset)) {
+  if (aContent == mStartContainer && aInfo->mChangeStart < mStartOffset) {
     if (aInfo->mDetails) {
       // splitText(), aInfo->mDetails->mNextSibling is the new text node
       NS_ASSERTION(aInfo->mDetails->mType ==
                    CharacterDataChangeInfo::Details::eSplit,
                    "only a split can start before the end");
-      NS_ASSERTION(static_cast<uint32_t>(mStartOffset) <= aInfo->mChangeEnd + 1,
+      NS_ASSERTION(mStartOffset <= aInfo->mChangeEnd + 1,
                    "mStartOffset is beyond the end of this node");
-      newStartOffset = static_cast<uint32_t>(mStartOffset) - aInfo->mChangeStart;
+      newStartOffset = mStartOffset - aInfo->mChangeStart;
       newStartNode = aInfo->mDetails->mNextSibling;
       if (MOZ_UNLIKELY(aContent == mRoot)) {
         newRoot = IsValidBoundary(newStartNode);
       }
 
       bool isCommonAncestor =
         IsInSelection() && mStartContainer == mEndContainer;
       if (isCommonAncestor) {
@@ -502,92 +521,91 @@ nsRange::CharacterDataChanged(nsIDocumen
       }
       if (mStartContainer->IsDescendantOfCommonAncestorForRangeInSelection()) {
         newStartNode->SetDescendantOfCommonAncestorForRangeInSelection();
       }
     } else {
       // If boundary is inside changed text, position it before change
       // else adjust start offset for the change in length.
       newStartNode = mStartContainer;
-      newStartOffset = static_cast<uint32_t>(mStartOffset) <= aInfo->mChangeEnd ?
+      newStartOffset = mStartOffset <= aInfo->mChangeEnd ?
         aInfo->mChangeStart :
         mStartOffset + aInfo->mChangeStart - aInfo->mChangeEnd +
           aInfo->mReplaceLength;
     }
   }
 
   // Do the same thing for the end boundary, except for splitText of a node
   // with no parent then only switch to the new node if the start boundary
   // did so too (otherwise the range would end up with disconnected nodes).
-  if (aContent == mEndContainer &&
-      aInfo->mChangeStart < static_cast<uint32_t>(mEndOffset)) {
+  if (aContent == mEndContainer && aInfo->mChangeStart < mEndOffset) {
     if (aInfo->mDetails && (aContent->GetParentNode() || newStartNode)) {
       // splitText(), aInfo->mDetails->mNextSibling is the new text node
       NS_ASSERTION(aInfo->mDetails->mType ==
                    CharacterDataChangeInfo::Details::eSplit,
                    "only a split can start before the end");
-      NS_ASSERTION(static_cast<uint32_t>(mEndOffset) <= aInfo->mChangeEnd + 1,
+      NS_ASSERTION(mEndOffset <= aInfo->mChangeEnd + 1,
                    "mEndOffset is beyond the end of this node");
-      newEndOffset = static_cast<uint32_t>(mEndOffset) - aInfo->mChangeStart;
+      newEndOffset = mEndOffset - aInfo->mChangeStart;
       newEndNode = aInfo->mDetails->mNextSibling;
 
       bool isCommonAncestor =
         IsInSelection() && mStartContainer == mEndContainer;
       if (isCommonAncestor && !newStartNode) {
         // The split occurs inside the range.
         UnregisterCommonAncestor(mStartContainer);
         RegisterCommonAncestor(mStartContainer->GetParentNode());
         newEndNode->SetDescendantOfCommonAncestorForRangeInSelection();
       } else if (mEndContainer->
                    IsDescendantOfCommonAncestorForRangeInSelection()) {
         newEndNode->SetDescendantOfCommonAncestorForRangeInSelection();
       }
     } else {
       newEndNode = mEndContainer;
-      newEndOffset = static_cast<uint32_t>(mEndOffset) <= aInfo->mChangeEnd ?
+      newEndOffset = mEndOffset <= aInfo->mChangeEnd ?
         aInfo->mChangeStart :
         mEndOffset + aInfo->mChangeStart - aInfo->mChangeEnd +
           aInfo->mReplaceLength;
     }
   }
 
   if (aInfo->mDetails &&
       aInfo->mDetails->mType == CharacterDataChangeInfo::Details::eMerge) {
     // normalize(), aInfo->mDetails->mNextSibling is the merged text node
     // that will be removed
     nsIContent* removed = aInfo->mDetails->mNextSibling;
     if (removed == mStartContainer) {
-      newStartOffset = static_cast<uint32_t>(mStartOffset) + aInfo->mChangeStart;
+      newStartOffset = mStartOffset + aInfo->mChangeStart;
       newStartNode = aContent;
       if (MOZ_UNLIKELY(removed == mRoot)) {
         newRoot = IsValidBoundary(newStartNode);
       }
     }
     if (removed == mEndContainer) {
-      newEndOffset = static_cast<uint32_t>(mEndOffset) + aInfo->mChangeStart;
+      newEndOffset = mEndOffset + aInfo->mChangeStart;
       newEndNode = aContent;
       if (MOZ_UNLIKELY(removed == mRoot)) {
         newRoot = IsValidBoundary(newEndNode);
       }
     }
     // When the removed text node's parent is one of our boundary nodes we may
     // need to adjust the offset to account for the removed node. However,
     // there will also be a ContentRemoved notification later so the only cases
     // we need to handle here is when the removed node is the text node after
     // the boundary.  (The m*Offset > 0 check is an optimization - a boundary
     // point before the first child is never affected by normalize().)
     nsINode* parentNode = aContent->GetParentNode();
     if (parentNode == mStartContainer && mStartOffset > 0 &&
-        uint32_t(mStartOffset) < parentNode->GetChildCount() &&
+        mStartOffset < parentNode->GetChildCount() &&
         removed == parentNode->GetChildAt(mStartOffset)) {
       newStartNode = aContent;
       newStartOffset = aInfo->mChangeStart;
     }
     if (parentNode == mEndContainer && mEndOffset > 0 &&
-        uint32_t(mEndOffset) < parentNode->GetChildCount() &&
+        mEndOffset < parentNode->GetChildCount() &&
         removed == parentNode->GetChildAt(mEndOffset)) {
       newEndNode = aContent;
       newEndOffset = aInfo->mChangeEnd;
     }
   }
 
   if (newStartNode || newEndNode) {
     if (!newStartNode) {
@@ -645,24 +663,30 @@ nsRange::ContentInserted(nsIDocument* aD
   NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
 
   bool rangeChanged = false;
   uint32_t newStartOffset = mStartOffset;
   uint32_t newEndOffset = mEndOffset;
   nsINode* container = NODE_FROM(aContainer, aDocument);
 
   // Adjust position if a sibling was inserted.
-  if (container == mStartContainer && aIndexInContainer < mStartOffset &&
+  if (container == mStartContainer &&
+      (NS_WARN_IF(aIndexInContainer < 0) ||
+       static_cast<uint32_t>(aIndexInContainer) < mStartOffset) &&
       !mStartOffsetWasIncremented) {
     ++newStartOffset;
+    MOZ_ASSERT(IsValidOffset(newStartOffset));
     rangeChanged = true;
   }
-  if (container == mEndContainer && aIndexInContainer < mEndOffset &&
+  if (container == mEndContainer &&
+      (NS_WARN_IF(aIndexInContainer < 0) ||
+       static_cast<uint32_t>(aIndexInContainer) < mEndOffset) &&
       !mEndOffsetWasIncremented) {
     ++newEndOffset;
+    MOZ_ASSERT(IsValidOffset(newEndOffset));
     rangeChanged = true;
   }
   if (container->IsSelectionDescendant() &&
       !aChild->IsDescendantOfCommonAncestorForRangeInSelection()) {
     MarkDescendants(aChild);
     aChild->SetDescendantOfCommonAncestorForRangeInSelection();
   }
 
@@ -700,29 +724,29 @@ nsRange::ContentRemoved(nsIDocument* aDo
   bool gravitateEnd = false;
   bool didCheckStartParentDescendant = false;
   bool rangeChanged = false;
   uint32_t newStartOffset = mStartOffset;
   uint32_t newEndOffset = mEndOffset;
 
   // Adjust position if a sibling was removed...
   if (container == mStartContainer) {
-    if (aIndexInContainer < mStartOffset) {
+    if (aIndexInContainer < static_cast<int32_t>(mStartOffset)) {
       --newStartOffset;
       rangeChanged = true;
     }
   } else { // ...or gravitate if an ancestor was removed.
     didCheckStartParentDescendant = true;
     gravitateStart =
       nsContentUtils::ContentIsDescendantOf(mStartContainer, aChild);
   }
 
   // Do same thing for end boundry.
   if (container == mEndContainer) {
-    if (aIndexInContainer < mEndOffset) {
+    if (aIndexInContainer < static_cast<int32_t>(mEndOffset)) {
       --newEndOffset;
       rangeChanged = true;
     }
   } else if (didCheckStartParentDescendant &&
              mStartContainer == mEndContainer) {
     gravitateEnd = gravitateStart;
   } else {
     gravitateEnd = nsContentUtils::ContentIsDescendantOf(mEndContainer, aChild);
@@ -768,22 +792,25 @@ nsRange::ParentChainChanged(nsIContent *
   // of mRoot is the last thing in DoSetRange.
   DoSetRange(mStartContainer, mStartOffset, mEndContainer, mEndOffset, newRoot);
 }
 
 /******************************************************
  * Utilities for comparing points: API from nsIDOMRange
  ******************************************************/
 NS_IMETHODIMP
-nsRange::IsPointInRange(nsIDOMNode* aContainer, int32_t aOffset, bool* aResult)
+nsRange::IsPointInRange(nsIDOMNode* aContainer, uint32_t aOffset, bool* aResult)
 {
   nsCOMPtr<nsINode> container = do_QueryInterface(aContainer);
   if (!container) {
     return NS_ERROR_DOM_NOT_OBJECT_ERR;
   }
+  if (NS_WARN_IF(!IsValidOffset(aOffset))) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  }
 
   ErrorResult rv;
   *aResult = IsPointInRange(*container, aOffset, rv);
   return rv.StealNSResult();
 }
 
 bool
 nsRange::IsPointInRange(nsINode& aContainer, uint32_t aOffset, ErrorResult& aRv)
@@ -796,17 +823,18 @@ nsRange::IsPointInRange(nsINode& aContai
   }
 
   return compareResult == 0;
 }
 
 // returns -1 if point is before range, 0 if point is in range,
 // 1 if point is after range.
 NS_IMETHODIMP
-nsRange::ComparePoint(nsIDOMNode* aContainer, int32_t aOffset, int16_t* aResult)
+nsRange::ComparePoint(nsIDOMNode* aContainer, uint32_t aOffset,
+                      int16_t* aResult)
 {
   nsCOMPtr<nsINode> container = do_QueryInterface(aContainer);
   NS_ENSURE_TRUE(container, NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
 
   ErrorResult rv;
   *aResult = ComparePoint(*container, aOffset, rv);
   return rv.StealNSResult();
 }
@@ -830,25 +858,28 @@ nsRange::ComparePoint(nsINode& aContaine
     return 0;
   }
 
   if (aOffset > aContainer.Length()) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return 0;
   }
 
-  int32_t cmp;
-  if ((cmp = nsContentUtils::ComparePoints(&aContainer, aOffset,
-                                           mStartContainer,
-                                           mStartOffset)) <= 0) {
-
+  int32_t cmp =
+    nsContentUtils::ComparePoints(&aContainer,
+                                  static_cast<int32_t>(aOffset),
+                                  mStartContainer,
+                                  static_cast<int32_t>(mStartOffset));
+  if (cmp <= 0) {
     return cmp;
   }
-  if (nsContentUtils::ComparePoints(mEndContainer, mEndOffset,
-                                    &aContainer, aOffset) == -1) {
+  if (nsContentUtils::ComparePoints(mEndContainer,
+                                    static_cast<int32_t>(mEndOffset),
+                                    &aContainer,
+                                    static_cast<int32_t>(aOffset)) == -1) {
     return 1;
   }
 
   return 0;
 }
 
 NS_IMETHODIMP
 nsRange::IntersectsNode(nsIDOMNode* aNode, bool* aResult)
@@ -881,22 +912,25 @@ nsRange::IntersectsNode(nsINode& aNode, 
   }
 
   // Step 5.
   int32_t nodeIndex = parent->IndexOf(&aNode);
 
   // Steps 6-7.
   // Note: if disconnected is true, ComparePoints returns 1.
   bool disconnected = false;
-  bool result = nsContentUtils::ComparePoints(mStartContainer, mStartOffset,
-                                             parent, nodeIndex + 1,
-                                             &disconnected) < 0 &&
-               nsContentUtils::ComparePoints(parent, nodeIndex,
-                                             mEndContainer, mEndOffset,
-                                             &disconnected) < 0;
+  bool result =
+    nsContentUtils::ComparePoints(mStartContainer,
+                                  static_cast<int32_t>(mStartOffset),
+                                  parent, nodeIndex + 1,
+                                  &disconnected) < 0 &&
+    nsContentUtils::ComparePoints(parent, nodeIndex,
+                                  mEndContainer,
+                                  static_cast<int32_t>(mEndOffset),
+                                  &disconnected) < 0;
 
   // Step 2.
   if (disconnected) {
     result = false;
   }
   return result;
 }
 
@@ -905,18 +939,18 @@ nsRange::IntersectsNode(nsINode& aNode, 
  ******************************************************/
 
 // It's important that all setting of the range start/end points
 // go through this function, which will do all the right voodoo
 // for content notification of range ownership.
 // Calling DoSetRange with either parent argument null will collapse
 // the range to have both endpoints point to the other node
 void
-nsRange::DoSetRange(nsINode* aStartN, int32_t aStartOffset,
-                    nsINode* aEndN, int32_t aEndOffset,
+nsRange::DoSetRange(nsINode* aStartN, uint32_t aStartOffset,
+                    nsINode* aEndN, uint32_t aEndOffset,
                     nsINode* aRoot, bool aNotInsertedYet)
 {
   NS_PRECONDITION((aStartN && aEndN && aRoot) ||
                   (!aStartN && !aEndN && !aRoot),
                   "Set all or none");
   NS_PRECONDITION(!aRoot || aNotInsertedYet ||
                   (nsContentUtils::ContentIsDescendantOf(aStartN, aRoot) &&
                    nsContentUtils::ContentIsDescendantOf(aEndN, aRoot) &&
@@ -932,16 +966,18 @@ nsRange::DoSetRange(nsINode* aStartN, in
                     static_cast<nsIContent*>(aEndN)->GetBindingParent()) ||
                   (!aRoot->GetParentNode() &&
                    (aRoot->IsNodeOfType(nsINode::eDOCUMENT) ||
                     aRoot->IsNodeOfType(nsINode::eATTRIBUTE) ||
                     aRoot->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) ||
                      /*For backward compatibility*/
                     aRoot->IsNodeOfType(nsINode::eCONTENT))),
                   "Bad root");
+  MOZ_ASSERT(IsValidOffset(aStartOffset));
+  MOZ_ASSERT(IsValidOffset(aEndOffset));
 
   if (mRoot != aRoot) {
     if (mRoot) {
       mRoot->RemoveMutationObserver(this);
     }
     if (aRoot) {
       aRoot->AddMutationObserver(this);
     }
@@ -1054,17 +1090,17 @@ nsRange::GetStartContainer(ErrorResult& 
     aRv.Throw(NS_ERROR_NOT_INITIALIZED);
     return nullptr;
   }
 
   return mStartContainer;
 }
 
 NS_IMETHODIMP
-nsRange::GetStartOffset(int32_t* aStartOffset)
+nsRange::GetStartOffset(uint32_t* aStartOffset)
 {
   if (!mIsPositioned)
     return NS_ERROR_NOT_INITIALIZED;
 
   *aStartOffset = mStartOffset;
 
   return NS_OK;
 }
@@ -1096,17 +1132,17 @@ nsRange::GetEndContainer(ErrorResult& aR
     aRv.Throw(NS_ERROR_NOT_INITIALIZED);
     return nullptr;
   }
 
   return mEndContainer;
 }
 
 NS_IMETHODIMP
-nsRange::GetEndOffset(int32_t* aEndOffset)
+nsRange::GetEndOffset(uint32_t* aEndOffset)
 {
   if (!mIsPositioned)
     return NS_ERROR_NOT_INITIALIZED;
 
   *aEndOffset = mEndOffset;
 
   return NS_OK;
 }
@@ -1155,20 +1191,20 @@ nsRange::GetCommonAncestorContainer(nsID
     *aCommonParent = nullptr;
   }
 
   return rv.StealNSResult();
 }
 
 /* static */
 bool
-nsRange::IsValidOffset(nsINode* aNode, int32_t aOffset)
+nsRange::IsValidOffset(nsINode* aNode, uint32_t aOffset)
 {
   return aNode &&
-         aOffset >= 0 &&
+         IsValidOffset(aOffset) &&
          static_cast<size_t>(aOffset) <= aNode->Length();
 }
 
 nsINode*
 nsRange::IsValidBoundary(nsINode* aNode)
 {
   if (!aNode) {
     return nullptr;
@@ -1230,45 +1266,47 @@ nsRange::SetStart(nsINode& aNode, uint32
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   aRv = SetStart(&aNode, aOffset);
 }
 
 NS_IMETHODIMP
-nsRange::SetStart(nsIDOMNode* aContainer, int32_t aOffset)
+nsRange::SetStart(nsIDOMNode* aContainer, uint32_t aOffset)
 {
   nsCOMPtr<nsINode> container = do_QueryInterface(aContainer);
   if (!container) {
     return NS_ERROR_DOM_NOT_OBJECT_ERR;
   }
 
   ErrorResult rv;
   SetStart(*container, aOffset, rv);
   return rv.StealNSResult();
 }
 
 /* virtual */ nsresult
-nsRange::SetStart(nsINode* aContainer, int32_t aOffset)
+nsRange::SetStart(nsINode* aContainer, uint32_t aOffset)
 {
   nsINode* newRoot = IsValidBoundary(aContainer);
   if (!newRoot) {
     return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
   }
 
   if (!IsValidOffset(aContainer, aOffset)) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   // Collapse if not positioned yet, if positioned in another doc or
   // if the new start is after end.
   if (!mIsPositioned || newRoot != mRoot ||
-      nsContentUtils::ComparePoints(aContainer, aOffset,
-                                    mEndContainer, mEndOffset) == 1) {
+      nsContentUtils::ComparePoints(aContainer,
+                                    static_cast<int32_t>(aOffset),
+                                    mEndContainer,
+                                    static_cast<int32_t>(mEndOffset)) == 1) {
     DoSetRange(aContainer, aOffset, aContainer, aOffset, newRoot);
 
     return NS_OK;
   }
 
   DoSetRange(aContainer, aOffset, mEndContainer, mEndOffset, mRoot);
 
   return NS_OK;
@@ -1287,17 +1325,20 @@ nsRange::SetStartBefore(nsINode& aNode, 
 {
   if (!nsContentUtils::LegacyIsCallerNativeCode() &&
       !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
-  int32_t offset = -1;
+  // If the node is being removed from its parent, GetContainerAndOffsetBefore()
+  // returns nullptr.  Then, SetStart() will throw
+  // NS_ERROR_DOM_INVALID_NODE_TYPE_ERR.
+  uint32_t offset = UINT32_MAX;
   nsINode* container = GetContainerAndOffsetBefore(&aNode, &offset);
   aRv = SetStart(container, offset);
 }
 
 NS_IMETHODIMP
 nsRange::SetStartBefore(nsIDOMNode* aSibling)
 {
   nsCOMPtr<nsINode> sibling = do_QueryInterface(aSibling);
@@ -1323,17 +1364,20 @@ nsRange::SetStartAfter(nsINode& aNode, E
 {
   if (!nsContentUtils::LegacyIsCallerNativeCode() &&
       !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
-  int32_t offset = -1;
+  // If the node is being removed from its parent, GetContainerAndOffsetAfter()
+  // returns nullptr.  Then, SetStart() will throw
+  // NS_ERROR_DOM_INVALID_NODE_TYPE_ERR.
+  uint32_t offset = UINT32_MAX;
   nsINode* container = GetContainerAndOffsetAfter(&aNode, &offset);
   aRv = SetStart(container, offset);
 }
 
 NS_IMETHODIMP
 nsRange::SetStartAfter(nsIDOMNode* aSibling)
 {
   nsCOMPtr<nsINode> sibling = do_QueryInterface(aSibling);
@@ -1362,58 +1406,60 @@ nsRange::SetEnd(nsINode& aNode, uint32_t
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
   AutoInvalidateSelection atEndOfBlock(this);
   aRv = SetEnd(&aNode, aOffset);
 }
 
 NS_IMETHODIMP
-nsRange::SetEnd(nsIDOMNode* aContainer, int32_t aOffset)
+nsRange::SetEnd(nsIDOMNode* aContainer, uint32_t aOffset)
 {
   nsCOMPtr<nsINode> container = do_QueryInterface(aContainer);
   if (!container) {
     return NS_ERROR_DOM_NOT_OBJECT_ERR;
   }
 
   ErrorResult rv;
   SetEnd(*container, aOffset, rv);
   return rv.StealNSResult();
 }
 
 /* virtual */ nsresult
-nsRange::SetEnd(nsINode* aContainer, int32_t aOffset)
+nsRange::SetEnd(nsINode* aContainer, uint32_t aOffset)
 {
   nsINode* newRoot = IsValidBoundary(aContainer);
   if (!newRoot) {
     return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
   }
 
   if (!IsValidOffset(aContainer, aOffset)) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   // Collapse if not positioned yet, if positioned in another doc or
   // if the new end is before start.
   if (!mIsPositioned || newRoot != mRoot ||
-      nsContentUtils::ComparePoints(mStartContainer, mStartOffset,
-                                    aContainer, aOffset) == 1) {
+      nsContentUtils::ComparePoints(mStartContainer,
+                                    static_cast<int32_t>(mStartOffset),
+                                    aContainer,
+                                    static_cast<int32_t>(aOffset)) == 1) {
     DoSetRange(aContainer, aOffset, aContainer, aOffset, newRoot);
 
     return NS_OK;
   }
 
   DoSetRange(mStartContainer, mStartOffset, aContainer, aOffset, mRoot);
 
   return NS_OK;
 }
 
 nsresult
-nsRange::SetStartAndEnd(nsINode* aStartContainer, int32_t aStartOffset,
-                        nsINode* aEndContainer, int32_t aEndOffset)
+nsRange::SetStartAndEnd(nsINode* aStartContainer, uint32_t aStartOffset,
+                        nsINode* aEndContainer, uint32_t aEndOffset)
 {
   if (NS_WARN_IF(!aStartContainer) || NS_WARN_IF(!aEndContainer)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsINode* newStartRoot = IsValidBoundary(aStartContainer);
   if (!newStartRoot) {
     return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
@@ -1450,18 +1496,20 @@ nsRange::SetStartAndEnd(nsINode* aStartC
   if (newStartRoot != newEndRoot) {
     DoSetRange(aEndContainer, aEndOffset,
                aEndContainer, aEndOffset, newEndRoot);
     return NS_OK;
   }
 
   // If the end point is before the start point, this should be collapsed at
   // the end point.
-  if (nsContentUtils::ComparePoints(aStartContainer, aStartOffset,
-                                    aEndContainer, aEndOffset) == 1) {
+  if (nsContentUtils::ComparePoints(aStartContainer,
+                                    static_cast<int32_t>(aStartOffset),
+                                    aEndContainer,
+                                    static_cast<int32_t>(aEndOffset)) == 1) {
     DoSetRange(aEndContainer, aEndOffset,
                aEndContainer, aEndOffset, newEndRoot);
     return NS_OK;
   }
 
   // Otherwise, set the range as specified.
   DoSetRange(aStartContainer, aStartOffset,
              aEndContainer, aEndOffset, newStartRoot);
@@ -1481,17 +1529,20 @@ nsRange::SetEndBefore(nsINode& aNode, Er
 {
   if (!nsContentUtils::LegacyIsCallerNativeCode() &&
       !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
-  int32_t offset = -1;
+  // If the node is being removed from its parent, GetContainerAndOffsetBefore()
+  // returns nullptr.  Then, SetEnd() will throw
+  // NS_ERROR_DOM_INVALID_NODE_TYPE_ERR.
+  uint32_t offset = UINT32_MAX;
   nsINode* container = GetContainerAndOffsetBefore(&aNode, &offset);
   aRv = SetEnd(container, offset);
 }
 
 NS_IMETHODIMP
 nsRange::SetEndBefore(nsIDOMNode* aSibling)
 {
   nsCOMPtr<nsINode> sibling = do_QueryInterface(aSibling);
@@ -1517,17 +1568,20 @@ nsRange::SetEndAfter(nsINode& aNode, Err
 {
   if (!nsContentUtils::LegacyIsCallerNativeCode() &&
       !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
-  int32_t offset = -1;
+  // If the node is being removed from its parent, GetContainerAndOffsetAfter()
+  // returns nullptr.  Then, SetEnd() will throw
+  // NS_ERROR_DOM_INVALID_NODE_TYPE_ERR.
+  uint32_t offset = UINT32_MAX;
   nsINode* container = GetContainerAndOffsetAfter(&aNode, &offset);
   aRv = SetEnd(container, offset);
 }
 
 NS_IMETHODIMP
 nsRange::SetEndAfter(nsIDOMNode* aSibling)
 {
   nsCOMPtr<nsINode> sibling = do_QueryInterface(aSibling);
@@ -1597,17 +1651,19 @@ nsRange::SelectNode(nsINode& aNode, Erro
   nsINode* container = aNode.GetParentNode();
   nsINode* newRoot = IsValidBoundary(container);
   if (!newRoot) {
     aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
     return;
   }
 
   int32_t index = container->IndexOf(&aNode);
-  if (index < 0) {
+  if (NS_WARN_IF(index < 0) ||
+      !IsValidOffset(static_cast<uint32_t>(index)) ||
+      !IsValidOffset(static_cast<uint32_t>(index) + 1)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
     return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   DoSetRange(container, index, container, index + 1, newRoot);
 }
 
@@ -2054,33 +2110,35 @@ nsRange::CutContents(DocumentFragment** 
 
   // Batch possible DOMSubtreeModified events.
   mozAutoSubtreeModified subtree(mRoot ? mRoot->OwnerDoc(): nullptr, nullptr);
 
   // Save the range end points locally to avoid interference
   // of Range gravity during our edits!
 
   nsCOMPtr<nsINode> startContainer = mStartContainer;
-  int32_t              startOffset = mStartOffset;
+  uint32_t startOffset = mStartOffset;
   nsCOMPtr<nsINode> endContainer = mEndContainer;
-  int32_t              endOffset = mEndOffset;
+  uint32_t endOffset = mEndOffset;
 
   if (retval) {
     // For extractContents(), abort early if there's a doctype (bug 719533).
     // This can happen only if the common ancestor is a document, in which case
     // we just need to find its doctype child and check if that's in the range.
     nsCOMPtr<nsIDocument> commonAncestorDocument = do_QueryInterface(commonAncestor);
     if (commonAncestorDocument) {
       RefPtr<DocumentType> doctype = commonAncestorDocument->GetDoctype();
 
       if (doctype &&
-          nsContentUtils::ComparePoints(startContainer, startOffset,
+          nsContentUtils::ComparePoints(startContainer,
+                                        static_cast<int32_t>(startOffset),
                                         doctype, 0) < 0 &&
           nsContentUtils::ComparePoints(doctype, 0,
-                                        endContainer, endOffset) < 0) {
+                                        endContainer,
+                                        static_cast<int32_t>(endOffset)) < 0) {
         return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
       }
     }
   }
 
   // Create and initialize a subtree iterator that will give
   // us all the subtrees within the range.
 
@@ -2165,60 +2223,53 @@ nsRange::CutContents(DocumentFragment** 
         }
         else
         {
           // Delete or extract everything after startOffset.
 
           rv = charData->GetLength(&dataLength);
           NS_ENSURE_SUCCESS(rv, rv);
 
-          if (dataLength >= (uint32_t)startOffset)
-          {
+          if (dataLength >= startOffset) {
             nsMutationGuard guard;
             nsCOMPtr<nsIDOMCharacterData> cutNode;
             rv = SplitDataNode(charData, startOffset, getter_AddRefs(cutNode));
             NS_ENSURE_SUCCESS(rv, rv);
             NS_ENSURE_STATE(!guard.Mutated(1) ||
                             ValidateCurrentNode(this, iter));
             nodeToResult = do_QueryInterface(cutNode);
           }
 
           handled = true;
         }
       }
       else if (node == endContainer)
       {
         // Delete or extract everything before endOffset.
-
-        if (endOffset >= 0)
-        {
-          nsMutationGuard guard;
-          nsCOMPtr<nsIDOMCharacterData> cutNode;
-          /* The Range spec clearly states clones get cut and original nodes
-             remain behind, so use false as the last parameter.
-          */
-          rv = SplitDataNode(charData, endOffset, getter_AddRefs(cutNode),
-                             false);
-          NS_ENSURE_SUCCESS(rv, rv);
-          NS_ENSURE_STATE(!guard.Mutated(1) ||
-                          ValidateCurrentNode(this, iter));
-          nodeToResult = do_QueryInterface(cutNode);
-        }
-
+        nsMutationGuard guard;
+        nsCOMPtr<nsIDOMCharacterData> cutNode;
+        /* The Range spec clearly states clones get cut and original nodes
+           remain behind, so use false as the last parameter.
+        */
+        rv = SplitDataNode(charData, endOffset, getter_AddRefs(cutNode),
+                           false);
+        NS_ENSURE_SUCCESS(rv, rv);
+        NS_ENSURE_STATE(!guard.Mutated(1) ||
+                        ValidateCurrentNode(this, iter));
+        nodeToResult = do_QueryInterface(cutNode);
         handled = true;
       }
     }
 
     if (!handled && (node == endContainer || node == startContainer))
     {
       if (node && node->IsElement() &&
           ((node == endContainer && endOffset == 0) ||
            (node == startContainer &&
-            int32_t(node->AsElement()->GetChildCount()) == startOffset)))
-      {
+            node->AsElement()->GetChildCount() == startOffset))) {
         if (retval) {
           ErrorResult rv;
           nodeToResult = node->CloneNode(false, rv);
           NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
         }
         handled = true;
       }
     }
@@ -2353,17 +2404,17 @@ nsRange::CompareBoundaryPoints(uint16_t 
                                ErrorResult& rv)
 {
   if (!mIsPositioned || !aOtherRange.IsPositioned()) {
     rv.Throw(NS_ERROR_NOT_INITIALIZED);
     return 0;
   }
 
   nsINode *ourNode, *otherNode;
-  int32_t ourOffset, otherOffset;
+  uint32_t ourOffset, otherOffset;
 
   switch (aHow) {
     case nsIDOMRange::START_TO_START:
       ourNode = mStartContainer;
       ourOffset = mStartOffset;
       otherNode = aOtherRange.GetStartContainer();
       otherOffset = aOtherRange.StartOffset();
       break;
@@ -2391,18 +2442,20 @@ nsRange::CompareBoundaryPoints(uint16_t 
       return 0;
   }
 
   if (mRoot != aOtherRange.GetRoot()) {
     rv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
     return 0;
   }
 
-  return nsContentUtils::ComparePoints(ourNode, ourOffset,
-                                       otherNode, otherOffset);
+  return nsContentUtils::ComparePoints(ourNode,
+                                       static_cast<int32_t>(ourOffset),
+                                       otherNode,
+                                       static_cast<int32_t>(otherOffset));
 }
 
 /* static */ nsresult
 nsRange::CloneParentsBetween(nsINode *aAncestor,
                              nsINode *aNode,
                              nsINode **aClosestAncestor,
                              nsINode **aFarthestAncestor)
 {
@@ -2509,18 +2562,17 @@ nsRange::CloneContents(ErrorResult& aRv)
   // correctly places this new subtree into the doc fragment.
 
   while (!iter.IsDone())
   {
     nsCOMPtr<nsINode> node = iter.GetCurrentNode();
     bool deepClone = !node->IsElement() ||
                        (!(node == mEndContainer && mEndOffset == 0) &&
                         !(node == mStartContainer &&
-                          mStartOffset ==
-                            int32_t(node->AsElement()->GetChildCount())));
+                          mStartOffset == node->AsElement()->GetChildCount()));
 
     // Clone the current subtree!
 
     nsCOMPtr<nsINode> clone = node->CloneNode(deepClone, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
 
@@ -2539,18 +2591,17 @@ nsRange::CloneContents(ErrorResult& aRv)
         // data after it.
 
         uint32_t dataLength = 0;
         aRv = charData->GetLength(&dataLength);
         if (aRv.Failed()) {
           return nullptr;
         }
 
-        if (dataLength > (uint32_t)mEndOffset)
-        {
+        if (dataLength > mEndOffset) {
           aRv = charData->DeleteData(mEndOffset, dataLength - mEndOffset);
           if (aRv.Failed()) {
             return nullptr;
           }
         }
       }
 
       if (node == mStartContainer) {
@@ -2697,17 +2748,17 @@ void
 nsRange::InsertNode(nsINode& aNode, ErrorResult& aRv)
 {
   if (!nsContentUtils::LegacyIsCallerNativeCode() &&
       !nsContentUtils::CanCallerAccess(&aNode)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
-  int32_t tStartOffset = StartOffset();
+  uint32_t tStartOffset = StartOffset();
 
   nsCOMPtr<nsINode> tStartContainer = GetStartContainer(aRv);
   if (aRv.Failed()) {
     return;
   }
 
   if (&aNode == tStartContainer) {
     aRv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
@@ -2758,28 +2809,30 @@ nsRange::InsertNode(nsINode& aNode, Erro
     if (aRv.Failed()) {
       return;
     }
   }
 
   // We might need to update the end to include the new node (bug 433662).
   // Ideally we'd only do this if needed, but it's tricky to know when it's
   // needed in advance (bug 765799).
-  int32_t newOffset;
+  uint32_t newOffset;
 
   if (referenceNode) {
-    newOffset = IndexOf(referenceNode);
+    int32_t indexInParent = IndexOf(referenceNode);
+    if (NS_WARN_IF(indexInParent < 0)) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
+    }
+    newOffset = static_cast<uint32_t>(indexInParent);
   } else {
-    uint32_t length;
-    aRv = tChildList->GetLength(&length);
+    aRv = tChildList->GetLength(&newOffset);
     if (aRv.Failed()) {
       return;
     }
-
-    newOffset = length;
   }
 
   if (aNode.NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
     newOffset += aNode.GetChildCount();
   } else {
     newOffset++;
   }
 
@@ -3115,21 +3168,26 @@ static nsresult GetPartialTextRect(nsLay
   return NS_OK;
 }
 
 /* static */ void
 nsRange::CollectClientRectsAndText(nsLayoutUtils::RectCallback* aCollector,
                                    Sequence<nsString>* aTextList,
                                    nsRange* aRange,
                                    nsINode* aStartContainer,
-                                   int32_t aStartOffset,
+                                   uint32_t aStartOffset,
                                    nsINode* aEndContainer,
-                                   int32_t aEndOffset,
+                                   uint32_t aEndOffset,
                                    bool aClampToEdge, bool aFlushLayout)
 {
+  // Currently, this method is called with start of end offset of nsRange.
+  // So, they must be between 0 - INT32_MAX.
+  MOZ_ASSERT(IsValidOffset(aStartOffset));
+  MOZ_ASSERT(IsValidOffset(aEndOffset));
+
   // Hold strong pointers across the flush
   nsCOMPtr<nsINode> startContainer = aStartContainer;
   nsCOMPtr<nsINode> endContainer = aEndContainer;
 
   // Flush out layout so our frames are up to date.
   if (!aStartContainer->IsInUncomposedDoc()) {
     return;
   }
@@ -3150,23 +3208,25 @@ nsRange::CollectClientRectsAndText(nsLay
   if (iter.IsDone()) {
     // the range is collapsed, only continue if the cursor is in a text node
     nsCOMPtr<nsIContent> content = do_QueryInterface(aStartContainer);
     if (content && content->IsNodeOfType(nsINode::eTEXT)) {
       nsTextFrame* textFrame = GetTextFrameForContent(content, aFlushLayout);
       if (textFrame) {
         int32_t outOffset;
         nsIFrame* outFrame;
-        textFrame->GetChildFrameContainingOffset(aStartOffset, false,
-          &outOffset, &outFrame);
+        textFrame->GetChildFrameContainingOffset(
+                     static_cast<int32_t>(aStartOffset), false,
+                     &outOffset, &outFrame);
         if (outFrame) {
            nsIFrame* relativeTo =
              nsLayoutUtils::GetContainingBlockForClientRect(outFrame);
            nsRect r = outFrame->GetRectRelativeToSelf();
-           ExtractRectFromOffset(outFrame, aStartOffset, &r, false, aClampToEdge);
+           ExtractRectFromOffset(outFrame, static_cast<int32_t>(aStartOffset),
+                                 &r, false, aClampToEdge);
            r.width = 0;
            r = nsLayoutUtils::TransformFrameRectToAncestor(outFrame, r, relativeTo);
            aCollector->AddRect(r);
         }
       }
     }
     return;
   }
@@ -3175,22 +3235,24 @@ nsRange::CollectClientRectsAndText(nsLay
     nsCOMPtr<nsINode> node = iter.GetCurrentNode();
     iter.Next();
     nsCOMPtr<nsIContent> content = do_QueryInterface(node);
     if (!content)
       continue;
     if (content->IsNodeOfType(nsINode::eTEXT)) {
        if (node == startContainer) {
          int32_t offset = startContainer == endContainer ?
-           aEndOffset : content->GetText()->GetLength();
-         GetPartialTextRect(aCollector, aTextList, content, aStartOffset, offset,
+           static_cast<int32_t>(aEndOffset) : content->GetText()->GetLength();
+         GetPartialTextRect(aCollector, aTextList, content,
+                            static_cast<int32_t>(aStartOffset), offset,
                             aClampToEdge, aFlushLayout);
          continue;
        } else if (node == endContainer) {
-         GetPartialTextRect(aCollector, aTextList, content, 0, aEndOffset,
+         GetPartialTextRect(aCollector, aTextList, content,
+                            0, static_cast<int32_t>(aEndOffset),
                             aClampToEdge, aFlushLayout);
          continue;
        }
     }
 
     nsIFrame* frame = content->GetPrimaryFrame();
     if (frame) {
       nsLayoutUtils::GetAllInFlowRectsAndTexts(frame,
@@ -3555,17 +3617,17 @@ ElementIsVisibleNoFlush(Element* aElemen
   RefPtr<nsStyleContext> sc =
     nsComputedDOMStyle::GetStyleContextNoFlush(aElement, nullptr, nullptr);
   return sc && sc->StyleVisibility()->IsVisible();
 }
 
 static void
 AppendTransformedText(InnerTextAccumulator& aResult,
                       nsGenericDOMDataNode* aTextNode,
-                      int32_t aStart, int32_t aEnd)
+                      uint32_t aStart, uint32_t aEnd)
 {
   nsIFrame* frame = aTextNode->GetPrimaryFrame();
   if (!IsVisibleAndNotInReplacedElement(frame)) {
     return;
   }
   nsIFrame::RenderedText text = frame->GetRenderedText(aStart, aEnd);
   aResult.Append(text.mString);
 }
@@ -3664,17 +3726,17 @@ nsRange::GetInnerTextNoFlush(DOMString& 
     }
   }
 
   nsIContent* endNode = aEndContainer;
   TreeTraversalState endState = AFTER_NODE;
   if (aEndContainer->IsNodeOfType(nsINode::eTEXT)) {
     endState = AT_NODE;
   } else {
-    if (uint32_t(aEndOffset) < aEndContainer->GetChildCount()) {
+    if (aEndOffset < aEndContainer->GetChildCount()) {
       endNode = aEndContainer->GetChildAt(aEndOffset);
       endState = AT_NODE;
     }
   }
 
   while (currentNode != endNode || currentState != endState) {
     nsIFrame* f = currentNode->GetPrimaryFrame();
     bool isVisibleAndNotReplaced = IsVisibleAndNotInReplacedElement(f);
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -42,24 +42,30 @@ class nsRange final : public nsIDOMRange
   typedef mozilla::dom::DOMRect DOMRect;
   typedef mozilla::dom::DOMRectList DOMRectList;
 
   virtual ~nsRange();
 
 public:
   explicit nsRange(nsINode* aNode);
 
-  static nsresult CreateRange(nsIDOMNode* aStartContainer, int32_t aStartOffset,
-                              nsIDOMNode* aEndContainer, int32_t aEndOffset,
+  static nsresult CreateRange(nsIDOMNode* aStartContainer,
+                              uint32_t aStartOffset,
+                              nsIDOMNode* aEndContainer,
+                              uint32_t aEndOffset,
                               nsRange** aRange);
-  static nsresult CreateRange(nsIDOMNode* aStartContainer, int32_t aStartOffset,
-                              nsIDOMNode* aEndContainer, int32_t aEndOffset,
+  static nsresult CreateRange(nsIDOMNode* aStartContainer,
+                              uint32_t aStartOffset,
+                              nsIDOMNode* aEndContainer,
+                              uint32_t aEndOffset,
                               nsIDOMRange** aRange);
-  static nsresult CreateRange(nsINode* aStartContainer, int32_t aStartOffset,
-                              nsINode* aEndContainer, int32_t aEndOffset,
+  static nsresult CreateRange(nsINode* aStartContainer,
+                              uint32_t aStartOffset,
+                              nsINode* aEndContainer,
+                              uint32_t aEndOffset,
                               nsRange** aRange);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
 
   nsrefcnt GetRefCount() const
   {
     return mRefCnt;
@@ -78,22 +84,22 @@ public:
     return mStartContainer;
   }
 
   nsINode* GetEndContainer() const
   {
     return mEndContainer;
   }
 
-  int32_t StartOffset() const
+  uint32_t StartOffset() const
   {
     return mStartOffset;
   }
 
-  int32_t EndOffset() const
+  uint32_t EndOffset() const
   {
     return mEndOffset;
   }
 
   bool IsPositioned() const
   {
     return mIsPositioned;
   }
@@ -142,63 +148,76 @@ public:
   void Reset();
 
   /**
    * SetStart() and SetEnd() sets start point or end point separately.
    * However, this is expensive especially when it's a range of Selection.
    * When you set both start and end of a range, you should use
    * SetStartAndEnd() instead.
    */
-  nsresult SetStart(nsINode* aContainer, int32_t aOffset);
-  nsresult SetEnd(nsINode* aContainer, int32_t aOffset);
+  nsresult SetStart(nsINode* aContainer, uint32_t aOffset);
+  nsresult SetEnd(nsINode* aContainer, uint32_t aOffset);
 
   already_AddRefed<nsRange> CloneRange() const;
 
   /**
    * SetStartAndEnd() works similar to call both SetStart() and SetEnd().
    * Different from calls them separately, this does nothing if either
    * the start point or the end point is invalid point.
    * If the specified start point is after the end point, the range will be
    * collapsed at the end point.  Similarly, if they are in different root,
    * the range will be collapsed at the end point.
    */
-  nsresult SetStartAndEnd(nsINode* aStartContainer, int32_t aStartOffset,
-                          nsINode* aEndContainer, int32_t aEndOffset);
+  nsresult SetStartAndEnd(nsINode* aStartContainer, uint32_t aStartOffset,
+                          nsINode* aEndContainer, uint32_t aEndOffset);
 
   /**
    * CollapseTo() works similar to call both SetStart() and SetEnd() with
    * same node and offset.  This just calls SetStartAndParent() to set
    * collapsed range at aContainer and aOffset.
    */
-  nsresult CollapseTo(nsINode* aContainer, int32_t aOffset)
+  nsresult CollapseTo(nsINode* aContainer, uint32_t aOffset)
   {
     return SetStartAndEnd(aContainer, aOffset, aContainer, aOffset);
   }
 
   /**
    * Retrieves node and offset for setting start or end of a range to
    * before or after aNode.
    */
-  static nsINode* GetContainerAndOffsetAfter(nsINode* aNode, int32_t* aOffset)
+  static nsINode* GetContainerAndOffsetAfter(nsINode* aNode, uint32_t* aOffset)
   {
     MOZ_ASSERT(aNode);
     MOZ_ASSERT(aOffset);
+    *aOffset = 0;
     nsINode* parentNode = aNode->GetParentNode();
-    *aOffset = parentNode ? parentNode->IndexOf(aNode) : -1;
-    if (*aOffset >= 0) {
-      (*aOffset)++;
+    if (!parentNode) {
+      return nullptr;
     }
+    int32_t indexInParent = parentNode->IndexOf(aNode);
+    if (NS_WARN_IF(indexInParent < 0)) {
+      return nullptr;
+    }
+    *aOffset = static_cast<uint32_t>(indexInParent) + 1;
     return parentNode;
   }
-  static nsINode* GetContainerAndOffsetBefore(nsINode* aNode, int32_t* aOffset)
+  static nsINode* GetContainerAndOffsetBefore(nsINode* aNode, uint32_t* aOffset)
   {
     MOZ_ASSERT(aNode);
     MOZ_ASSERT(aOffset);
+    *aOffset = 0;
     nsINode* parentNode = aNode->GetParentNode();
-    *aOffset = parentNode ? parentNode->IndexOf(aNode) : -1;
+    if (!parentNode) {
+      return nullptr;
+    }
+    int32_t indexInParent = parentNode->IndexOf(aNode);
+    if (NS_WARN_IF(indexInParent < 0)) {
+      return nullptr;
+    }
+    *aOffset = static_cast<uint32_t>(indexInParent);
     return parentNode;
   }
 
   NS_IMETHOD GetUsedFontFaces(nsIDOMFontFaceList** aResult);
 
   // nsIMutationObserver methods
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
@@ -322,19 +341,19 @@ public:
   /**
    * This helper function gets rects and correlated text for the given range.
    * @param aTextList optional where nullptr = don't retrieve text
    */
   static void CollectClientRectsAndText(nsLayoutUtils::RectCallback* aCollector,
                                         mozilla::dom::Sequence<nsString>* aTextList,
                                         nsRange* aRange,
                                         nsINode* aStartContainer,
-                                        int32_t aStartOffset,
+                                        uint32_t aStartOffset,
                                         nsINode* aEndContainer,
-                                        int32_t aEndOffset,
+                                        uint32_t aEndOffset,
                                         bool aClampToEdge, bool aFlushLayout);
 
   /**
    * Scan this range for -moz-user-select:none nodes and split it up into
    * multiple ranges to exclude those nodes.  The resulting ranges are put
    * in aOutRanges.  If no -moz-user-select:none node is found in the range
    * then |this| is unmodified and is the only range in aOutRanges.
    * Otherwise, |this| will be modified so that it ends before the first
@@ -345,24 +364,35 @@ public:
    */
   void ExcludeNonSelectableNodes(nsTArray<RefPtr<nsRange>>* aOutRanges);
 
   typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
 protected:
   void RegisterCommonAncestor(nsINode* aNode);
   void UnregisterCommonAncestor(nsINode* aNode);
   nsINode* IsValidBoundary(nsINode* aNode);
-  static bool IsValidOffset(nsINode* aNode, int32_t aOffset);
+
+  /**
+   * XXX nsRange should accept 0 - UINT32_MAX as offset.  However, users of
+   *     nsRange treat offset as int32_t.  Additionally, some other internal
+   *     APIs like nsINode::IndexOf() use int32_t.  Therefore, nsRange should
+   *     accept only 0 - INT32_MAX as valid offset for now.
+   */
+  static bool IsValidOffset(uint32_t aOffset)
+  {
+    return aOffset <= INT32_MAX;
+  }
+  static bool IsValidOffset(nsINode* aNode, uint32_t aOffset);
 
   // CharacterDataChanged set aNotInsertedYet to true to disable an assertion
   // and suppress re-registering a range common ancestor node since
   // the new text node of a splitText hasn't been inserted yet.
   // CharacterDataChanged does the re-registering when needed.
-  void DoSetRange(nsINode* aStartN, int32_t aStartOffset,
-                  nsINode* aEndN, int32_t aEndOffset,
+  void DoSetRange(nsINode* aStartN, uint32_t aStartOffset,
+                  nsINode* aEndN, uint32_t aEndOffset,
                   nsINode* aRoot, bool aNotInsertedYet = false);
 
   /**
    * For a range for which IsInSelection() is true, return the common
    * ancestor for the range.  This method uses the selection bits and
    * nsGkAtoms::range property on the nodes to quickly find the ancestor.
    * That is, it's a faster version of GetCommonAncestor that only works
    * for ranges in a Selection.  The method will assert and the behavior
@@ -425,18 +455,18 @@ protected:
     static bool mIsNested;
   };
 
   nsCOMPtr<nsIDocument> mOwner;
   nsCOMPtr<nsINode> mRoot;
   nsCOMPtr<nsINode> mStartContainer;
   nsCOMPtr<nsINode> mEndContainer;
   RefPtr<mozilla::dom::Selection> mSelection;
-  int32_t mStartOffset;
-  int32_t mEndOffset;
+  uint32_t mStartOffset;
+  uint32_t mEndOffset;
 
   bool mIsPositioned : 1;
   bool mMaySpanAnonymousSubtrees : 1;
   bool mIsGenerated : 1;
   bool mStartOffsetWasIncremented : 1;
   bool mEndOffsetWasIncremented : 1;
   bool mCalledByJS : 1;
 #ifdef DEBUG
--- a/dom/interfaces/range/nsIDOMRange.idl
+++ b/dom/interfaces/range/nsIDOMRange.idl
@@ -11,24 +11,24 @@
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Traversal-Range/
  */
 
 [builtinclass, uuid(1f94055c-42e7-4a30-96a1-6a804f1c2d1e)]
 interface nsIDOMRange : nsISupports
 {
   readonly attribute nsIDOMNode       startContainer;
-  readonly attribute long             startOffset;
+  readonly attribute unsigned long    startOffset;
   readonly attribute nsIDOMNode       endContainer;
-  readonly attribute long             endOffset;
+  readonly attribute unsigned long    endOffset;
   readonly attribute boolean          collapsed;
   readonly attribute nsIDOMNode       commonAncestorContainer;
 
-  void               setStart(in nsIDOMNode refNode, in long offset);
-  void               setEnd(in nsIDOMNode refNode, in long offset);
+  void               setStart(in nsIDOMNode refNode, in unsigned long offset);
+  void               setEnd(in nsIDOMNode refNode, in unsigned long offset);
   void               setStartBefore(in nsIDOMNode refNode);
   void               setStartAfter(in nsIDOMNode refNode);
   void               setEndBefore(in nsIDOMNode refNode);
   void               setEndAfter(in nsIDOMNode refNode);
   void               collapse(in boolean toStart);
   void               selectNode(in nsIDOMNode refNode);
   void               selectNodeContents(in nsIDOMNode refNode);
 
@@ -51,24 +51,24 @@ interface nsIDOMRange : nsISupports
   
   // This method comes from
   // http://html5.org/specs/dom-parsing.html#extensions-to-the-range-interface
   nsIDOMDocumentFragment    createContextualFragment(in DOMString fragment);
 
   // This returns true if parent+offset equals either
   // of the boundary points or is between them.
   boolean                   isPointInRange(in nsIDOMNode parent,
-                                           in long offset);
+                                           in unsigned long offset);
 
   // comparePoint returns
   //   -1 if point is before the start boundary point,
   //    0 if point is either of the boundary points or between them,
   //    1 if point is after the end boundary point.
   // Sort of a strcmp for ranges.
-  short                     comparePoint(in nsIDOMNode parent, in long offset);
+  short comparePoint(in nsIDOMNode parent, in unsigned long offset);
 
   /**
    * Returns whether the range intersects node.
    */
   boolean                   intersectsNode(in nsIDOMNode node);
 
   // These methods come from 
   // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-range-interface
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -5314,17 +5314,17 @@ EditorBase::GetIMESelectionStartOffsetIn
   MOZ_ASSERT(aTextNode, "aTextNode must not be nullptr");
 
   nsCOMPtr<nsISelectionController> selectionController =
     GetSelectionController();
   if (NS_WARN_IF(!selectionController)) {
     return -1;
   }
 
-  int32_t minOffset = INT32_MAX;
+  uint32_t minOffset = UINT32_MAX;
   static const SelectionType kIMESelectionTypes[] = {
     SelectionType::eIMERawClause,
     SelectionType::eIMESelectedRawClause,
     SelectionType::eIMEConvertedClause,
     SelectionType::eIMESelectedClause
   };
   for (auto selectionType : kIMESelectionTypes) {
     RefPtr<Selection> selection = GetSelection(selectionType);
@@ -5334,25 +5334,21 @@ EditorBase::GetIMESelectionStartOffsetIn
     for (uint32_t i = 0; i < selection->RangeCount(); i++) {
       RefPtr<nsRange> range = selection->GetRangeAt(i);
       if (NS_WARN_IF(!range)) {
         continue;
       }
       if (NS_WARN_IF(range->GetStartContainer() != aTextNode)) {
         // ignore the start offset...
       } else {
-        MOZ_ASSERT(range->StartOffset() >= 0,
-                   "start offset shouldn't be negative");
         minOffset = std::min(minOffset, range->StartOffset());
       }
       if (NS_WARN_IF(range->GetEndContainer() != aTextNode)) {
         // ignore the end offset...
       } else {
-        MOZ_ASSERT(range->EndOffset() >= 0,
-                   "start offset shouldn't be negative");
         minOffset = std::min(minOffset, range->EndOffset());
       }
     }
   }
   return minOffset < INT32_MAX ? minOffset : -1;
 }
 
 void
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -453,17 +453,17 @@ HTMLEditRules::AfterEditInner(EditAction
     return NS_OK;
   }
 
   NS_ENSURE_STATE(mHTMLEditor);
   RefPtr<Selection> selection = mHTMLEditor->GetSelection();
   NS_ENSURE_STATE(selection);
 
   nsCOMPtr<nsIDOMNode> rangeStartContainer, rangeEndContainer;
-  int32_t rangeStartOffset = 0, rangeEndOffset = 0;
+  uint32_t rangeStartOffset = 0, rangeEndOffset = 0;
   // do we have a real range to act on?
   bool bDamagedRange = false;
   if (mDocChangeRange) {
     mDocChangeRange->GetStartContainer(getter_AddRefs(rangeStartContainer));
     mDocChangeRange->GetEndContainer(getter_AddRefs(rangeEndContainer));
     mDocChangeRange->GetStartOffset(&rangeStartOffset);
     mDocChangeRange->GetEndOffset(&rangeEndOffset);
     if (rangeStartContainer && rangeEndContainer) {
@@ -563,18 +563,18 @@ HTMLEditRules::AfterEditInner(EditAction
 
   NS_ENSURE_STATE(mHTMLEditor);
 
   nsresult rv =
     mHTMLEditor->HandleInlineSpellCheck(
                    action, selection,
                    GetAsDOMNode(mRangeItem->mStartContainer),
                    mRangeItem->mStartOffset,
-                   rangeStartContainer, rangeStartOffset,
-                   rangeEndContainer, rangeEndOffset);
+                   rangeStartContainer, static_cast<int32_t>(rangeStartOffset),
+                   rangeEndContainer, static_cast<int32_t>(rangeEndOffset));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // detect empty doc
   rv = CreateBogusNodeIfNeeded(selection);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // adjust selection HINT if needed
   if (!mDidExplicitlySetInterline) {
@@ -5312,113 +5312,127 @@ HTMLEditRules::NormalizeSelection(Select
   // we don't need to mess with cell selections, and we assume multirange selections are those.
   if (rangeCount != 1) {
     return NS_OK;
   }
 
   RefPtr<nsRange> range = inSelection->GetRangeAt(0);
   NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDOMNode> startNode, endNode;
-  int32_t startOffset, endOffset;
+  uint32_t startOffset, endOffset;
   nsCOMPtr<nsIDOMNode> newStartNode, newEndNode;
-  int32_t newStartOffset, newEndOffset;
 
   rv = range->GetStartContainer(getter_AddRefs(startNode));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = range->GetStartOffset(&startOffset);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = range->GetEndContainer(getter_AddRefs(endNode));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = range->GetEndOffset(&endOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // adjusted values default to original values
   newStartNode = startNode;
-  newStartOffset = startOffset;
+  uint32_t newStartOffset = startOffset;
   newEndNode = endNode;
-  newEndOffset = endOffset;
+  uint32_t newEndOffset = endOffset;
 
   // some locals we need for whitespace code
   nsCOMPtr<nsINode> unused;
-  int32_t offset;
+  int32_t offset = -1;
   WSType wsType;
 
   // let the whitespace code do the heavy lifting
-  WSRunObject wsEndObj(mHTMLEditor, endNode, endOffset);
+  WSRunObject wsEndObj(mHTMLEditor, 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
   nsCOMPtr<nsINode> endNode_(do_QueryInterface(endNode));
-  wsEndObj.PriorVisibleNode(endNode_, endOffset, address_of(unused),
-                            &offset, &wsType);
+  wsEndObj.PriorVisibleNode(endNode_, static_cast<int32_t>(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.
       nsCOMPtr<nsIDOMNode> child =
         GetAsDOMNode(mHTMLEditor->GetRightmostChild(wsEndObj.mStartReasonNode,
                                                     true));
       if (child) {
-        newEndNode = EditorBase::GetNodeLocation(child, &newEndOffset);
-        ++newEndOffset; // offset *after* child
+        int32_t offset = -1;
+        newEndNode = EditorBase::GetNodeLocation(child, &offset);
+        // offset *after* child
+        newEndOffset = static_cast<uint32_t>(offset + 1);
       }
       // else block is empty - we can leave selection alone here, i think.
     } else if (wsEndObj.mStartReason == WSType::thisBlock) {
       // endpoint is just after start of this block
       nsCOMPtr<nsIDOMNode> child;
       NS_ENSURE_STATE(mHTMLEditor);
-      mHTMLEditor->GetPriorHTMLNode(endNode, endOffset, address_of(child));
+      mHTMLEditor->GetPriorHTMLNode(endNode, static_cast<int32_t>(endOffset),
+                                    address_of(child));
       if (child) {
-        newEndNode = EditorBase::GetNodeLocation(child, &newEndOffset);
-        ++newEndOffset; // offset *after* child
+        int32_t offset = -1;
+        newEndNode = EditorBase::GetNodeLocation(child, &offset);
+        // offset *after* child
+        newEndOffset = static_cast<uint32_t>(offset + 1);
       }
       // else block is empty - we can leave selection alone here, i think.
     } else if (wsEndObj.mStartReason == WSType::br) {
       // endpoint is just after break.  lets adjust it to before it.
+      int32_t offset = -1;
       newEndNode =
         EditorBase::GetNodeLocation(GetAsDOMNode(wsEndObj.mStartReasonNode),
-                                    &newEndOffset);
+                                    &offset);
+      newEndOffset = static_cast<uint32_t>(offset);;
     }
   }
 
 
   // similar dealio for start of range
-  WSRunObject wsStartObj(mHTMLEditor, startNode, startOffset);
+  WSRunObject wsStartObj(mHTMLEditor, 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
   nsCOMPtr<nsINode> startNode_(do_QueryInterface(startNode));
-  wsStartObj.NextVisibleNode(startNode_, startOffset, address_of(unused),
-                             &offset, &wsType);
+  wsStartObj.NextVisibleNode(startNode_, static_cast<int32_t>(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.
       nsCOMPtr<nsIDOMNode> child =
         GetAsDOMNode(mHTMLEditor->GetLeftmostChild(wsStartObj.mEndReasonNode,
                                                    true));
       if (child) {
-        newStartNode = EditorBase::GetNodeLocation(child, &newStartOffset);
+        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::thisBlock) {
       // startpoint is just before end of this block
       nsCOMPtr<nsIDOMNode> child;
       NS_ENSURE_STATE(mHTMLEditor);
-      mHTMLEditor->GetNextHTMLNode(startNode, startOffset, address_of(child));
+      mHTMLEditor->GetNextHTMLNode(startNode, static_cast<int32_t>(startOffset),
+                                   address_of(child));
       if (child) {
-        newStartNode = EditorBase::GetNodeLocation(child, &newStartOffset);
+        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.
+      int32_t offset = -1;
       newStartNode =
         EditorBase::GetNodeLocation(GetAsDOMNode(wsStartObj.mEndReasonNode),
-                                    &newStartOffset);
-      ++newStartOffset; // offset *after* break
+                                    &offset);
+      // offset *after* break
+      newStartOffset = static_cast<uint32_t>(offset + 1);
     }
   }
 
   // there is a demented possiblity we have to check for.  We might have a very strange selection
   // that is not collapsed and yet does not contain any editable content, and satisfies some of the
   // above conditions that cause tweaking.  In this case we don't want to tweak the selection into
   // a block it was never in, etc.  There are a variety of strategies one might use to try to
   // detect these cases, but I think the most straightforward is to see if the adjusted locations
@@ -8188,33 +8202,33 @@ HTMLEditRules::UpdateDocChangeRange(nsRa
       // The same test won't be needed further down since after we've set
       // the start the range will be collapsed to that point.
       result = 1;
       rv = NS_OK;
     }
     NS_ENSURE_SUCCESS(rv, rv);
     // Positive result means mDocChangeRange start is after aRange start.
     if (result > 0) {
-      int32_t startOffset;
+      uint32_t startOffset;
       rv = aRange->GetStartOffset(&startOffset);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = mDocChangeRange->SetStart(startNode, startOffset);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     // compare ends of ranges
     rv = mDocChangeRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END,
                                                 aRange, &result);
     NS_ENSURE_SUCCESS(rv, rv);
     // Negative result means mDocChangeRange end is before aRange end.
     if (result < 0) {
       nsCOMPtr<nsIDOMNode> endNode;
-      int32_t endOffset;
       rv = aRange->GetEndContainer(getter_AddRefs(endNode));
       NS_ENSURE_SUCCESS(rv, rv);
+      uint32_t endOffset;
       rv = aRange->GetEndOffset(&endOffset);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = mDocChangeRange->SetEnd(endNode, endOffset);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
   return NS_OK;
 }
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -2413,32 +2413,30 @@ HTMLEditor::GetSelectedElement(const nsA
   bool isLinkTag = IsLinkTag(TagName);
   bool isNamedAnchorTag = IsNamedAnchorTag(TagName);
 
   nsCOMPtr<nsIDOMElement> selectedElement;
   RefPtr<nsRange> range = selection->GetRangeAt(0);
   NS_ENSURE_STATE(range);
 
   nsCOMPtr<nsIDOMNode> startContainer;
-  int32_t startOffset, endOffset;
   nsresult rv = range->GetStartContainer(getter_AddRefs(startContainer));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = range->GetStartOffset(&startOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+  uint32_t startOffset = range->StartOffset();
 
   nsCOMPtr<nsIDOMNode> endContainer;
   rv = range->GetEndContainer(getter_AddRefs(endContainer));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = range->GetEndOffset(&endOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+  uint32_t endOffset = range->EndOffset();
 
   // Optimization for a single selected element
   if (startContainer && startContainer == endContainer &&
       endOffset - startOffset == 1) {
-    nsCOMPtr<nsIDOMNode> selectedNode = GetChildAt(startContainer, startOffset);
+    nsCOMPtr<nsIDOMNode> selectedNode =
+      GetChildAt(startContainer, static_cast<int32_t>(startOffset));
     NS_ENSURE_SUCCESS(rv, NS_OK);
     if (selectedNode) {
       selectedNode->GetNodeName(domTagName);
       ToLowerCase(domTagName);
 
       // Test for appropriate node type requested
       if (anyTag || (TagName == domTagName) ||
           (isLinkTag && HTMLEditUtils::IsLink(selectedNode)) ||
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -136,24 +136,23 @@ HTMLEditor::LoadHTML(const nsAString& aI
     nsCOMPtr<nsIDOMDocumentFragment> docfrag;
     rv = range->CreateContextualFragment(aInputString, getter_AddRefs(docfrag));
     NS_ENSURE_SUCCESS(rv, rv);
     // put the fragment into the document
     nsCOMPtr<nsIDOMNode> parent;
     rv = range->GetStartContainer(getter_AddRefs(parent));
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
-    int32_t childOffset;
-    rv = range->GetStartOffset(&childOffset);
-    NS_ENSURE_SUCCESS(rv, rv);
+    uint32_t childOffset = range->StartOffset();
 
     nsCOMPtr<nsIDOMNode> nodeToInsert;
     docfrag->GetFirstChild(getter_AddRefs(nodeToInsert));
     while (nodeToInsert) {
-      rv = InsertNode(nodeToInsert, parent, childOffset++);
+      rv = InsertNode(nodeToInsert, parent,
+                      static_cast<int32_t>(childOffset++));
       NS_ENSURE_SUCCESS(rv, rv);
       docfrag->GetFirstChild(getter_AddRefs(nodeToInsert));
     }
   }
 
   return rules->DidDoAction(selection, &ruleInfo, rv);
 }
 
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -1068,17 +1068,17 @@ HTMLEditor::GetInlinePropertyBase(nsIAto
       // just ignore any non-editable nodes
       if (content->GetAsText() && (!IsEditable(content) ||
                                    IsEmptyTextNode(this, content))) {
         continue;
       }
       if (content->GetAsText()) {
         if (!isCollapsed && first && firstNodeInRange) {
           firstNodeInRange = false;
-          if (range->StartOffset() == (int32_t)content->Length()) {
+          if (range->StartOffset() == content->Length()) {
             continue;
           }
         } else if (content == endNode && !endOffset) {
           continue;
         }
       } else if (content->IsElement()) {
         // handle non-text leaf nodes here
         continue;
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -2922,40 +2922,35 @@ HTMLEditor::GetCellFromRange(nsRange* aR
 
   *aCell = nullptr;
 
   nsCOMPtr<nsIDOMNode> startContainer;
   nsresult rv = aRange->GetStartContainer(getter_AddRefs(startContainer));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(startContainer, NS_ERROR_FAILURE);
 
-  int32_t startOffset;
-  rv = aRange->GetStartOffset(&startOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIDOMNode> childNode = GetChildAt(startContainer, startOffset);
+  uint32_t startOffset = aRange->StartOffset();
+
+  nsCOMPtr<nsIDOMNode> childNode =
+    GetChildAt(startContainer, static_cast<int32_t>(startOffset));
   // This means selection is probably at a text node (or end of doc?)
   if (!childNode) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIDOMNode> endContainer;
   rv = aRange->GetEndContainer(getter_AddRefs(endContainer));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(startContainer, NS_ERROR_FAILURE);
 
-  int32_t endOffset;
-  rv = aRange->GetEndOffset(&endOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // If a cell is deleted, the range is collapse
-  //   (startOffset == endOffset)
+  //   (startOffset == aRange->EndOffset())
   //   so tell caller the cell wasn't found
   if (startContainer == endContainer &&
-      endOffset == startOffset+1 &&
+      aRange->EndOffset() == startOffset+1 &&
       HTMLEditUtils::IsTableCell(childNode)) {
     // Should we also test if frame is selected? (Use GetCellDataAt())
     // (Let's not for now -- more efficient)
     nsCOMPtr<nsIDOMElement> cellElement = do_QueryInterface(childNode);
     *aCell = cellElement.get();
     NS_ADDREF(*aCell);
     return NS_OK;
   }
--- a/editor/txtsvc/nsFilteredContentIterator.cpp
+++ b/editor/txtsvc/nsFilteredContentIterator.cpp
@@ -236,23 +236,25 @@ ContentIsInTraversalRange(nsIContent *aC
 static bool
 ContentIsInTraversalRange(nsRange* aRange, nsIDOMNode* aNextNode, bool aIsPreMode)
 {
   nsCOMPtr<nsIContent> content(do_QueryInterface(aNextNode));
   NS_ENSURE_TRUE(content && aRange, false);
 
   nsCOMPtr<nsIDOMNode> sNode;
   nsCOMPtr<nsIDOMNode> eNode;
-  int32_t sOffset;
-  int32_t eOffset;
+  uint32_t sOffset;
+  uint32_t eOffset;
   aRange->GetStartContainer(getter_AddRefs(sNode));
   aRange->GetStartOffset(&sOffset);
   aRange->GetEndContainer(getter_AddRefs(eNode));
   aRange->GetEndOffset(&eOffset);
-  return ContentIsInTraversalRange(content, aIsPreMode, sNode, sOffset, eNode, eOffset);
+  return ContentIsInTraversalRange(content, aIsPreMode,
+                                   sNode, static_cast<int32_t>(sOffset),
+                                   eNode, static_cast<int32_t>(eOffset));
 }
 
 //------------------------------------------------------------
 // Helper function to advance to the next or previous node
 nsresult
 nsFilteredContentIterator::AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir)
 {
   nsCOMPtr<nsIDOMNode> nextNode;
--- a/editor/txtsvc/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/nsTextServicesDocument.cpp
@@ -505,17 +505,16 @@ nsTextServicesDocument::LastSelectedBloc
 
   RefPtr<Selection> selection = domSelection->AsSelection();
 
   bool isCollapsed = selection->IsCollapsed();
 
   nsCOMPtr<nsIContentIterator> iter;
   RefPtr<nsRange> range;
   nsCOMPtr<nsIDOMNode>         parent;
-  int32_t rangeCount, offset;
 
   if (isCollapsed) {
     // We have a caret. Check if the caret is in a text node.
     // If it is, make the text node's block the current block.
     // If the caret isn't in a text node, search forwards in
     // the document, till we find a text node.
 
     range = selection->GetRangeAt(0);
@@ -532,16 +531,17 @@ nsTextServicesDocument::LastSelectedBloc
       return rv;
     }
 
     if (!parent) {
       UNLOCK_DOC(this);
       return NS_ERROR_FAILURE;
     }
 
+    uint32_t offset;
     rv = range->GetStartOffset(&offset);
 
     if (NS_FAILED(rv)) {
       UNLOCK_DOC(this);
       return rv;
     }
 
     if (IsTextNode(parent)) {
@@ -591,18 +591,19 @@ nsTextServicesDocument::LastSelectedBloc
         rv = SetSelectionInternal(*aSelOffset, *aSelLength, false);
       }
     } else {
       // The caret isn't in a text node. Create an iterator
       // based on a range that extends from the current caret
       // position to the end of the document, then walk forwards
       // till you find a text node, then find the beginning of it's block.
 
-      rv = CreateDocumentContentRootToNodeOffsetRange(parent, offset, false,
-                                                      getter_AddRefs(range));
+      rv = CreateDocumentContentRootToNodeOffsetRange(
+             parent, static_cast<int32_t>(offset), false,
+             getter_AddRefs(range));
 
       if (NS_FAILED(rv)) {
         UNLOCK_DOC(this);
         return rv;
       }
 
       rv = range->GetCollapsed(&isCollapsed);
 
@@ -685,16 +686,17 @@ nsTextServicesDocument::LastSelectedBloc
   }
 
   // If we get here, we have an uncollapsed selection!
   // Look backwards through each range in the selection till you
   // find the first text node. If you find one, find the
   // beginning of its text block, and make it the current
   // block.
 
+  int32_t rangeCount;
   rv = selection->GetRangeCount(&rangeCount);
 
   if (NS_FAILED(rv)) {
     UNLOCK_DOC(this);
     return rv;
   }
 
   NS_ASSERTION(rangeCount > 0, "Unexpected range count!");
@@ -792,25 +794,26 @@ nsTextServicesDocument::LastSelectedBloc
     return rv;
   }
 
   if (!parent) {
     UNLOCK_DOC(this);
     return NS_ERROR_FAILURE;
   }
 
+  uint32_t offset;
   rv = range->GetEndOffset(&offset);
 
   if (NS_FAILED(rv)) {
     UNLOCK_DOC(this);
     return rv;
   }
 
-  rv = CreateDocumentContentRootToNodeOffsetRange(parent, offset, false,
-                                                  getter_AddRefs(range));
+  rv = CreateDocumentContentRootToNodeOffsetRange(
+         parent, static_cast<int32_t>(offset), false, getter_AddRefs(range));
 
   if (NS_FAILED(rv)) {
     UNLOCK_DOC(this);
     return rv;
   }
 
   rv = range->GetCollapsed(&isCollapsed);
 
@@ -2372,42 +2375,44 @@ nsTextServicesDocument::GetCollapsedSele
 
   nsCOMPtr<nsIDOMNode> domParent;
   rv = range->GetStartContainer(getter_AddRefs(domParent));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsINode> parent = do_QueryInterface(domParent);
   MOZ_ASSERT(parent);
 
-  int32_t offset;
+  uint32_t offset;
   rv = range->GetStartOffset(&offset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   int32_t e1s1 = nsContentUtils::ComparePoints(eStart->mNode, eStartOffset,
-                                               domParent, offset);
+                                               domParent,
+                                               static_cast<int32_t>(offset));
   int32_t e2s1 = nsContentUtils::ComparePoints(eEnd->mNode, eEndOffset,
-                                               domParent, offset);
+                                               domParent,
+                                               static_cast<int32_t>(offset));
 
   if (e1s1 > 0 || e2s1 < 0) {
     // We're done if the caret is outside the current text block.
     return NS_OK;
   }
 
   if (parent->NodeType() == nsIDOMNode::TEXT_NODE) {
     // Good news, the caret is in a text node. Look
     // through the offset table for the entry that
     // matches its parent and offset.
 
     for (int32_t i = 0; i < tableCount; i++) {
       OffsetEntry* entry = mOffsetTable[i];
       NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE);
 
       if (entry->mNode == domParent.get() &&
-          entry->mNodeOffset <= offset &&
-          offset <= entry->mNodeOffset + entry->mLength) {
+          entry->mNodeOffset <= static_cast<int32_t>(offset) &&
+          static_cast<int32_t>(offset) <= entry->mNodeOffset + entry->mLength) {
         *aSelStatus = nsITextServicesDocument::eBlockContains;
         *aSelOffset = entry->mStrOffset + (offset - entry->mNodeOffset);
         *aSelLength = 0;
 
         return NS_OK;
       }
     }
 
@@ -2435,17 +2440,17 @@ nsTextServicesDocument::GetCollapsedSele
   nsIContent* saveNode;
   if (parent->HasChildren()) {
     // XXX: We need to make sure that all of parent's
     //      children are in the text block.
 
     // If the parent has children, position the iterator
     // on the child that is to the left of the offset.
 
-    uint32_t childIndex = (uint32_t)offset;
+    uint32_t childIndex = offset;
 
     if (childIndex > 0) {
       uint32_t numChildren = parent->GetChildCount();
       NS_ASSERTION(childIndex <= numChildren, "Invalid selection offset!");
 
       if (childIndex > numChildren) {
         childIndex = numChildren;
       }
@@ -2521,18 +2526,18 @@ nsTextServicesDocument::GetCollapsedSele
     offset = 0;
   }
 
   for (int32_t i = 0; i < tableCount; i++) {
     OffsetEntry* entry = mOffsetTable[i];
     NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE);
 
     if (entry->mNode == node->AsDOMNode() &&
-        entry->mNodeOffset <= offset &&
-        offset <= entry->mNodeOffset + entry->mLength) {
+        entry->mNodeOffset <= static_cast<int32_t>(offset) &&
+        static_cast<int32_t>(offset) <= entry->mNodeOffset + entry->mLength) {
       *aSelStatus = nsITextServicesDocument::eBlockContains;
       *aSelOffset = entry->mStrOffset + (offset - entry->mNodeOffset);
       *aSelLength = 0;
 
       // Now move the caret so that it is actually in the text node.
       // We do this to keep things in sync.
       //
       // In most cases, the user shouldn't see any movement in the caret
@@ -2815,27 +2820,35 @@ nsTextServicesDocument::GetRangeEndPoint
                  aEndContainer && aEndOffset, NS_ERROR_NULL_POINTER);
 
   nsresult rv = aRange->GetStartContainer(aStartContainer);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ENSURE_TRUE(aStartContainer, NS_ERROR_FAILURE);
 
-  rv = aRange->GetStartOffset(aStartOffset);
-
-  NS_ENSURE_SUCCESS(rv, rv);
+  uint32_t offset;
+  rv = aRange->GetStartOffset(&offset);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  *aStartOffset = static_cast<int32_t>(offset);
 
   rv = aRange->GetEndContainer(aEndContainer);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ENSURE_TRUE(aEndContainer, NS_ERROR_FAILURE);
 
-  return aRange->GetEndOffset(aEndOffset);
+  rv = aRange->GetEndOffset(&offset);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  *aEndOffset = static_cast<int32_t>(offset);
+  return NS_OK;
 }
 
 nsresult
 nsTextServicesDocument::CreateRange(nsIDOMNode* aStartContainer,
                                     int32_t aStartOffset,
                                     nsIDOMNode* aEndContainer,
                                     int32_t aEndOffset,
                                     nsRange** aRange)
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -347,49 +347,49 @@ nsresult
 mozInlineSpellStatus::FinishNavigationEvent(mozInlineSpellWordUtil& aWordUtil)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryReferent(mSpellChecker->mEditor);
   if (! editor)
     return NS_ERROR_FAILURE; // editor is gone
 
   NS_ASSERTION(mAnchorRange, "No anchor for navigation!");
   nsCOMPtr<nsIDOMNode> newAnchorNode, oldAnchorNode;
-  int32_t newAnchorOffset, oldAnchorOffset;
 
   // get the DOM position of the old caret, the range should be collapsed
   nsresult rv = mOldNavigationAnchorRange->GetStartContainer(
       getter_AddRefs(oldAnchorNode));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = mOldNavigationAnchorRange->GetStartOffset(&oldAnchorOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+  uint32_t oldAnchorOffset = mOldNavigationAnchorRange->StartOffset();
 
   // find the word on the old caret position, this is the one that we MAY need
   // to check
   RefPtr<nsRange> oldWord;
-  rv = aWordUtil.GetRangeForWord(oldAnchorNode, oldAnchorOffset,
+  rv = aWordUtil.GetRangeForWord(oldAnchorNode,
+                                 static_cast<int32_t>(oldAnchorOffset),
                                  getter_AddRefs(oldWord));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // aWordUtil.GetRangeForWord flushes pending notifications, check editor again.
   editor = do_QueryReferent(mSpellChecker->mEditor);
   if (! editor)
     return NS_ERROR_FAILURE; // editor is gone
 
   // get the DOM position of the new caret, the range should be collapsed
   rv = mAnchorRange->GetStartContainer(getter_AddRefs(newAnchorNode));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = mAnchorRange->GetStartOffset(&newAnchorOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+  uint32_t newAnchorOffset = mAnchorRange->StartOffset();
 
   // see if the new cursor position is in the word of the old cursor position
   bool isInRange = false;
   if (! mForceNavigationWordCheck) {
-    rv = oldWord->IsPointInRange(newAnchorNode,
-                                 newAnchorOffset + mNewNavigationPositionOffset,
-                                 &isInRange);
+    rv = oldWord->IsPointInRange(
+                    newAnchorNode,
+                    static_cast<int32_t>(
+                      newAnchorOffset + mNewNavigationPositionOffset),
+                    &isInRange);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (isInRange) {
     // caller should give up
     mRange = nullptr;
   } else {
     // check the old word
@@ -412,21 +412,19 @@ mozInlineSpellStatus::FinishNavigationEv
 nsresult
 mozInlineSpellStatus::FillNoCheckRangeFromAnchor(
     mozInlineSpellWordUtil& aWordUtil)
 {
   nsCOMPtr<nsIDOMNode> anchorNode;
   nsresult rv = mAnchorRange->GetStartContainer(getter_AddRefs(anchorNode));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  int32_t anchorOffset;
-  rv = mAnchorRange->GetStartOffset(&anchorOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return aWordUtil.GetRangeForWord(anchorNode, anchorOffset,
+  uint32_t anchorOffset = mAnchorRange->StartOffset();
+  return aWordUtil.GetRangeForWord(anchorNode,
+                                   static_cast<int32_t>(anchorOffset),
                                    getter_AddRefs(mNoCheckRange));
 }
 
 // mozInlineSpellStatus::GetDocument
 //
 //    Returns the nsIDOMDocument object for the document for the
 //    current spellchecker.
 
@@ -1211,17 +1209,17 @@ mozInlineSpellChecker::MakeSpellCheckRan
   nsCOMPtr<nsINode> startNode = do_QueryInterface(aStartNode);
   nsCOMPtr<nsINode> endNode = do_QueryInterface(aEndNode);
   if (aEndOffset) {
     rv = range->SetStartAndEnd(startNode, aStartOffset, endNode, aEndOffset);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
-    int32_t endOffset = -1;
+    uint32_t endOffset;
     endNode = nsRange::GetContainerAndOffsetAfter(endNode, &endOffset);
     rv = range->SetStartAndEnd(startNode, aStartOffset, endNode, endOffset);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   range.swap(*aRange);
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -4790,19 +4790,21 @@ PresShell::ClipListToRange(nsDisplayList
     if (content) {
       bool atStart = (content == aRange->GetStartContainer());
       bool atEnd = (content == aRange->GetEndContainer());
       if ((atStart || atEnd) && frame->IsTextFrame()) {
         int32_t frameStartOffset, frameEndOffset;
         frame->GetOffsets(frameStartOffset, frameEndOffset);
 
         int32_t hilightStart =
-          atStart ? std::max(aRange->StartOffset(), frameStartOffset) : frameStartOffset;
+          atStart ? std::max(static_cast<int32_t>(aRange->StartOffset()),
+                             frameStartOffset) : frameStartOffset;
         int32_t hilightEnd =
-          atEnd ? std::min(aRange->EndOffset(), frameEndOffset) : frameEndOffset;
+          atEnd ? std::min(static_cast<int32_t>(aRange->EndOffset()),
+                           frameEndOffset) : frameEndOffset;
         if (hilightStart < hilightEnd) {
           // determine the location of the start and end edges of the range.
           nsPoint startPoint, endPoint;
           frame->GetPointFromOffset(hilightStart, &startPoint);
           frame->GetPointFromOffset(hilightEnd, &endPoint);
 
           // The clip rectangle is determined by taking the the start and
           // end points of the range, offset from the reference frame.
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1891,30 +1891,34 @@ nsImageFrame::ShouldDisplaySelection()
         if (rangeCount == 1) //if not one then let code drop to nsFrame::Paint
         {
           nsCOMPtr<nsIContent> parentContent = mContent->GetParent();
           if (parentContent)
           {
             int32_t thisOffset = parentContent->IndexOf(mContent);
             nsCOMPtr<nsIDOMNode> parentNode = do_QueryInterface(parentContent);
             nsCOMPtr<nsIDOMNode> rangeNode;
-            int32_t rangeOffset;
+            uint32_t rangeOffset;
             nsCOMPtr<nsIDOMRange> range;
             selection->GetRangeAt(0,getter_AddRefs(range));
             if (range)
             {
               range->GetStartContainer(getter_AddRefs(rangeNode));
               range->GetStartOffset(&rangeOffset);
 
-              if (parentNode && rangeNode && (rangeNode == parentNode) && rangeOffset == thisOffset)
-              {
+              if (parentNode && rangeNode && rangeNode == parentNode &&
+                  static_cast<int32_t>(rangeOffset) == thisOffset) {
                 range->GetEndContainer(getter_AddRefs(rangeNode));
                 range->GetEndOffset(&rangeOffset);
-                if ((rangeNode == parentNode) && (rangeOffset == (thisOffset +1))) //+1 since that would mean this whole content is selected only
-                  return false; //do not allow nsFrame do draw any further selection
+                // +1 since that would mean this whole content is selected only
+                if (rangeNode == parentNode &&
+                    static_cast<int32_t>(rangeOffset) == thisOffset + 1) {
+                  // Do not allow nsFrame do draw any further selection
+                  return false;
+                }
               }
             }
           }
         }
       }
     }
   }
 #endif
--- a/toolkit/components/find/nsFind.cpp
+++ b/toolkit/components/find/nsFind.cpp
@@ -596,17 +596,17 @@ nsFind::NextNode(nsIDOMRange* aSearchRan
   nsCOMPtr<nsIContent> content;
 
   if (!mIterator || aContinueOk) {
     // If we are continuing, that means we have a match in progress. In that
     // case, we want to continue from the end point (where we are now) to the
     // beginning/end of the search range.
     nsCOMPtr<nsIDOMNode> startNode;
     nsCOMPtr<nsIDOMNode> endNode;
-    int32_t startOffset, endOffset;
+    uint32_t startOffset, endOffset;
     if (aContinueOk) {
 #ifdef DEBUG_FIND
       printf("Match in progress: continuing past endpoint\n");
 #endif
       if (mFindBackward) {
         aSearchRange->GetStartContainer(getter_AddRefs(startNode));
         aSearchRange->GetStartOffset(&startOffset);
         aEndPoint->GetStartContainer(getter_AddRefs(endNode));
@@ -632,17 +632,18 @@ nsFind::NextNode(nsIDOMRange* aSearchRan
       } else { // forward
         aStartPoint->GetStartContainer(getter_AddRefs(startNode));
         aStartPoint->GetStartOffset(&startOffset);
         aEndPoint->GetEndContainer(getter_AddRefs(endNode));
         aEndPoint->GetEndOffset(&endOffset);
       }
     }
 
-    rv = InitIterator(startNode, startOffset, endNode, endOffset);
+    rv = InitIterator(startNode, static_cast<int32_t>(startOffset),
+                      endNode, static_cast<int32_t>(endOffset));
     NS_ENSURE_SUCCESS(rv, rv);
     if (!aStartPoint) {
       aStartPoint = aSearchRange;
     }
 
     content = do_QueryInterface(mIterator->GetCurrentNode());
 #ifdef DEBUG_FIND
     nsCOMPtr<nsIDOMNode> dnode(do_QueryInterface(content));
@@ -652,24 +653,28 @@ nsFind::NextNode(nsIDOMRange* aSearchRan
     if (content && content->IsNodeOfType(nsINode::eTEXT) &&
         !SkipNode(content)) {
       mIterNode = do_QueryInterface(content);
       // Also set mIterOffset if appropriate:
       nsCOMPtr<nsIDOMNode> node;
       if (mFindBackward) {
         aStartPoint->GetEndContainer(getter_AddRefs(node));
         if (mIterNode.get() == node.get()) {
-          aStartPoint->GetEndOffset(&mIterOffset);
+          uint32_t endOffset;
+          aStartPoint->GetEndOffset(&endOffset);
+          mIterOffset = static_cast<int32_t>(endOffset);
         } else {
           mIterOffset = -1; // sign to start from end
         }
       } else {
         aStartPoint->GetStartContainer(getter_AddRefs(node));
         if (mIterNode.get() == node.get()) {
-          aStartPoint->GetStartOffset(&mIterOffset);
+          uint32_t startOffset;
+          aStartPoint->GetStartOffset(&startOffset);
+          mIterOffset = static_cast<int32_t>(startOffset);
         } else {
           mIterOffset = 0;
         }
       }
 #ifdef DEBUG_FIND
       printf("Setting initial offset to %d\n", mIterOffset);
 #endif
       return NS_OK;
@@ -983,17 +988,17 @@ nsFind::Find(const char16_t* aPatText, n
   bool wordBreakPrev = false;
 
   // Place to save the range start point in case we find a match:
   nsCOMPtr<nsIDOMNode> matchAnchorNode;
   int32_t matchAnchorOffset = 0;
 
   // Get the end point, so we know when to end searches:
   nsCOMPtr<nsIDOMNode> endNode;
-  int32_t endOffset;
+  uint32_t endOffset;
   aEndPoint->GetEndContainer(getter_AddRefs(endNode));
   aEndPoint->GetEndOffset(&endOffset);
 
   char16_t c = 0;
   char16_t patc = 0;
   char16_t prevChar = 0;
   char16_t prevCharInMatch = 0;
   while (1) {
@@ -1118,18 +1123,18 @@ nsFind::Find(const char16_t* aPatText, n
         frag = nullptr;
         continue;
       }
     }
 
     // Have we gone past the endpoint yet? If we have, and we're not in the
     // middle of a match, return.
     if (mIterNode == endNode &&
-        ((mFindBackward && findex < endOffset) ||
-         (!mFindBackward && findex > endOffset))) {
+        ((mFindBackward && findex < static_cast<int32_t>(endOffset)) ||
+         (!mFindBackward && findex > static_cast<int32_t>(endOffset)))) {
       ResetAll();
       return NS_OK;
     }
 
     // Save the previous character for word boundary detection
     prevChar = c;
     // The two characters we'll be comparing:
     c = (t2b ? t2b[findex] : CHAR_TO_UNICHAR(t1b[findex]));
--- a/toolkit/components/find/nsWebBrowserFind.cpp
+++ b/toolkit/components/find/nsWebBrowserFind.cpp
@@ -511,17 +511,17 @@ nsWebBrowserFind::GetSearchLimits(nsIDOM
 
   uint32_t childCount = bodyContent->GetChildCount();
 
   // There are four possible range endpoints we might use:
   // DocumentStart, SelectionStart, SelectionEnd, DocumentEnd.
 
   nsCOMPtr<nsIDOMRange> range;
   nsCOMPtr<nsIDOMNode> node;
-  int32_t offset;
+  uint32_t offset;
 
   // Forward, not wrapping: SelEnd to DocEnd
   if (!mFindBackwards && !aWrap) {
     // This isn't quite right, since the selection's ranges aren't
     // necessarily in order; but they usually will be.
     aSel->GetRangeAt(count - 1, getter_AddRefs(range));
     if (!range) {
       return NS_ERROR_UNEXPECTED;
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -843,17 +843,17 @@ nsTypeAheadFind::GetSearchContainers(nsI
     // Ensure visible range, move forward if necessary
     // This uses ignores the return value, but usese the side effect of
     // IsRangeVisible. It returns the first visible range after searchRange
     IsRangeVisible(presShell, presContext, mSearchRange,
                    aIsFirstVisiblePreferred, true,
                    getter_AddRefs(mStartPointRange), nullptr);
   }
   else {
-    int32_t startOffset;
+    uint32_t startOffset;
     nsCOMPtr<nsIDOMNode> startNode;
     if (aFindPrev) {
       currentSelectionRange->GetStartContainer(getter_AddRefs(startNode));
       currentSelectionRange->GetStartOffset(&startOffset);
     } else {
       currentSelectionRange->GetEndContainer(getter_AddRefs(startNode));
       currentSelectionRange->GetEndOffset(&startOffset);
     }
@@ -881,17 +881,17 @@ nsTypeAheadFind::RangeStartsInsideLink(n
 {
   *aIsInsideLink = false;
   *aIsStartingLink = true;
 
   // ------- Get nsIContent to test -------
   nsCOMPtr<nsIDOMNode> startNode;
   nsCOMPtr<nsIContent> startContent, origContent;
   aRange->GetStartContainer(getter_AddRefs(startNode));
-  int32_t startOffset;
+  uint32_t startOffset;
   aRange->GetStartOffset(&startOffset);
 
   startContent = do_QueryInterface(startNode);
   if (!startContent) {
     NS_NOTREACHED("startContent should never be null");
     return;
   }
   origContent = startContent;
@@ -901,19 +901,20 @@ nsTypeAheadFind::RangeStartsInsideLink(n
     if (childContent) {
       startContent = childContent;
     }
   }
   else if (startOffset > 0) {
     const nsTextFragment *textFrag = startContent->GetText();
     if (textFrag) {
       // look for non whitespace character before start offset
-      for (int32_t index = 0; index < startOffset; index++) {
+      for (uint32_t index = 0; index < startOffset; index++) {
         // FIXME: take content language into account when deciding whitespace.
-        if (!mozilla::dom::IsSpaceCharacter(textFrag->CharAt(index))) {
+        if (!mozilla::dom::IsSpaceCharacter(
+                             textFrag->CharAt(static_cast<int32_t>(index)))) {
           *aIsStartingLink = false;  // not at start of a node
 
           break;
         }
       }
     }
   }
 
@@ -1230,22 +1231,24 @@ nsTypeAheadFind::IsRangeVisible(nsIPresS
       (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
   }
 
   // ---- We have a frame ----
   if (!aMustBeInViewPort)
     return true; //  Don't need it to be on screen, just in rendering tree
 
   // Get the next in flow frame that contains the range start
-  int32_t startRangeOffset, startFrameOffset, endFrameOffset;
+  int32_t startFrameOffset, endFrameOffset;
+  uint32_t startRangeOffset;
   aRange->GetStartOffset(&startRangeOffset);
   while (true) {
     frame->GetOffsets(startFrameOffset, endFrameOffset);
-    if (startRangeOffset < endFrameOffset)
+    if (static_cast<int32_t>(startRangeOffset) < endFrameOffset) {
       break;
+    }
 
     nsIFrame *nextContinuationFrame = frame->GetNextContinuation();
     if (nextContinuationFrame)
       frame = nextContinuationFrame;
     else
       break;
   }