Bug 1399626 - Part 2: Add overloads of nsRange::{CreateRange, SetStartAndEnd} which take RangeBoundaries, r=masayuki draft
authorMichael Layzell <michael@thelayzells.com>
Wed, 13 Sep 2017 16:52:18 -0400
changeset 672781 c28fe5cd1c2b4936e2884116a7f252616d9b321d
parent 672780 208a2e1f766954b292de85f34f740c5a10d224db
child 672782 41507a50a158951342fc68925c0866df07f2a968
push id82373
push userbmo:nika@thelayzells.com
push dateFri, 29 Sep 2017 19:23:28 +0000
reviewersmasayuki
bugs1399626
milestone58.0a1
Bug 1399626 - Part 2: Add overloads of nsRange::{CreateRange, SetStartAndEnd} which take RangeBoundaries, r=masayuki
dom/base/nsRange.cpp
dom/base/nsRange.h
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -312,16 +312,31 @@ nsRange::CreateRange(nsIDOMNode* aStartC
 {
   RefPtr<nsRange> range;
   nsresult rv = nsRange::CreateRange(aStartContainer, aStartOffset, aEndParent,
                                      aEndOffset, getter_AddRefs(range));
   range.forget(aRange);
   return rv;
 }
 
+/* static */
+nsresult
+nsRange::CreateRange(const RawRangeBoundary& aStart,
+                     const RawRangeBoundary& aEnd,
+                     nsRange** aRange)
+{
+  RefPtr<nsRange> range = new nsRange(aStart.Container());
+  nsresult rv = range->SetStartAndEnd(aStart, aEnd);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  range.forget(aRange);
+  return NS_OK;
+}
+
 /******************************************************
  * nsISupports
  ******************************************************/
 
 NS_IMPL_MAIN_THREAD_ONLY_CYCLE_COLLECTING_ADDREF(nsRange)
 NS_IMPL_MAIN_THREAD_ONLY_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(
   nsRange, DoSetRange(RawRangeBoundary(), RawRangeBoundary(), nullptr))
 
@@ -1525,77 +1540,82 @@ nsRange::SelectNodesInContainer(nsINode*
   }
 
   RawRangeBoundary start(aContainer, aStartContent->GetPreviousSibling());
   RawRangeBoundary end(aContainer, aEndContent);
   DoSetRange(start, end, newRoot);
 }
 
 nsresult
+nsRange::SetStartAndEnd(const RawRangeBoundary& aStart,
+                        const RawRangeBoundary& aEnd)
+{
+  if (NS_WARN_IF(!aStart.IsSet()) || NS_WARN_IF(!aEnd.IsSet())) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  nsINode* newStartRoot = IsValidBoundary(aStart.Container());
+  if (!newStartRoot) {
+    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+  }
+  if (!aStart.IsSetAndValid()) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  }
+
+  if (aStart.Container() == aEnd.Container()) {
+    if (!aEnd.IsSetAndValid()) {
+      return NS_ERROR_DOM_INDEX_SIZE_ERR;
+    }
+    // XXX: Offsets - handle this more efficiently.
+    // If the end offset is less than the start offset, this should be
+    // collapsed at the end offset.
+    if (aStart.Offset() > aEnd.Offset()) {
+      DoSetRange(aEnd, aEnd, newStartRoot);
+    } else {
+      DoSetRange(aStart, aEnd, newStartRoot);
+    }
+    return NS_OK;
+  }
+
+  nsINode* newEndRoot = IsValidBoundary(aEnd.Container());
+  if (!newEndRoot) {
+    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+  }
+  if (!aEnd.IsSetAndValid()) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  }
+
+  // If they have different root, this should be collapsed at the end point.
+  if (newStartRoot != newEndRoot) {
+    DoSetRange(aEnd, aEnd, newEndRoot);
+    return NS_OK;
+  }
+
+  // If the end point is before the start point, this should be collapsed at
+  // the end point.
+  if (nsContentUtils::ComparePoints(aStart, aEnd) == 1) {
+    DoSetRange(aEnd, aEnd, newEndRoot);
+    return NS_OK;
+  }
+
+  // Otherwise, set the range as specified.
+  DoSetRange(aStart, aEnd, newStartRoot);
+  return NS_OK;
+}
+
+nsresult
 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;
-  }
-  if (!IsValidOffset(aStartContainer, aStartOffset)) {
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
-  }
-
-  if (aStartContainer == aEndContainer) {
-    if (!IsValidOffset(aEndContainer, aEndOffset)) {
-      return NS_ERROR_DOM_INDEX_SIZE_ERR;
-    }
-    // If the end offset is less than the start offset, this should be
-    // collapsed at the end offset.
-    if (aStartOffset > aEndOffset) {
-      DoSetRange(aEndContainer, aEndOffset,
-                 aEndContainer, aEndOffset, newStartRoot);
-    } else {
-      DoSetRange(aStartContainer, aStartOffset,
-                 aEndContainer, aEndOffset, newStartRoot);
-    }
-    return NS_OK;
-  }
-
-  nsINode* newEndRoot = IsValidBoundary(aEndContainer);
-  if (!newEndRoot) {
-    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
-  }
-  if (!IsValidOffset(aEndContainer, aEndOffset)) {
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
-  }
-
-  // If they have different root, this should be collapsed at the end point.
-  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,
-                                    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);
-  return NS_OK;
+  return SetStartAndEnd(RawRangeBoundary(aStartContainer, aStartOffset),
+                        RawRangeBoundary(aEndContainer, aEndOffset));
 }
 
 void
 nsRange::SetEndBeforeJS(nsINode& aNode, ErrorResult& aErr)
 {
   AutoCalledByJSRestore calledByJSRestorer(*this);
   mCalledByJS = true;
   SetEndBefore(aNode, aErr);
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -63,16 +63,19 @@ public:
                               nsIDOMNode* aEndContainer,
                               uint32_t aEndOffset,
                               nsIDOMRange** aRange);
   static nsresult CreateRange(nsINode* aStartContainer,
                               uint32_t aStartOffset,
                               nsINode* aEndContainer,
                               uint32_t aEndOffset,
                               nsRange** aRange);
+  static nsresult CreateRange(const RawRangeBoundary& aStart,
+                              const RawRangeBoundary& aEnd,
+                              nsRange** aRange);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
 
   nsrefcnt GetRefCount() const
   {
     return mRefCnt;
   }
@@ -189,16 +192,18 @@ public:
    * 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, uint32_t aStartOffset,
                           nsINode* aEndContainer, uint32_t aEndOffset);
+  nsresult SetStartAndEnd(const RawRangeBoundary& aStart,
+                          const RawRangeBoundary& aEnd);
 
   /**
    * Adds all nodes between |aStartContent| and |aEndContent| to the range.
    * The start offset will be set before |aStartContent|,
    * while the end offset will be set immediately after |aEndContent|.
    *
    * Caller must guarantee both nodes are non null and
    * children of |aContainer| and that |aEndContent| is after |aStartContent|.