--- 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|.