bug 825341 - convert range to webidl r=bz, smaug
authorTrevor Saunders <trev.saunders@gmail.com>
Thu, 07 Feb 2013 07:09:41 -0500
changeset 134893 5410bada8645304318a9c85cc647b673488cc094
parent 134892 66483dfa678f846fe70fdedb843a7877a17ea6ba
child 134894 e1538a45f97bb8dbeec9881653e5c0f56d06d296
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, smaug
bugs825341
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 825341 - convert range to webidl r=bz, smaug
CLOBBER
accessible/src/generic/HyperTextAccessible.cpp
accessible/src/windows/msaa/TextLeafAccessibleWrap.cpp
content/base/public/nsContentUtils.h
content/base/public/nsIDocument.h
content/base/src/DocumentFragment.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsCopySupport.cpp
content/base/src/nsDocument.cpp
content/base/src/nsRange.cpp
content/base/src/nsRange.h
content/events/src/nsContentEventHandler.cpp
content/html/content/src/nsHTMLMediaElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/test/unit/test_range.js
dom/bindings/Bindings.conf
dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-comparePoint.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-intersectsNode-binding.html.json
dom/interfaces/core/nsIDOMDocumentFragment.idl
dom/webidl/Document.webidl
dom/webidl/Range.webidl
dom/webidl/WebIDL.mk
editor/libeditor/base/IMETextTxn.cpp
editor/libeditor/html/nsHTMLEditRules.cpp
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsWSRunObject.cpp
editor/libeditor/html/tests/test_bug629845.html
editor/txtsvc/src/nsFilteredContentIterator.cpp
editor/txtsvc/src/nsTextServicesDocument.cpp
embedding/components/find/src/nsFind.cpp
embedding/components/find/src/nsFind.h
embedding/components/find/src/nsWebBrowserFind.cpp
extensions/spellcheck/src/mozInlineSpellChecker.cpp
extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
layout/base/nsPresShell.cpp
layout/forms/nsTextControlFrame.cpp
layout/generic/nsSelection.cpp
layout/printing/nsPrintEngine.cpp
toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
--- a/CLOBBER
+++ b/CLOBBER
@@ -10,9 +10,9 @@
 #                  O   <-- Users coming from both parents need to Clobber
 #               /     \
 #          O               O
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
-Bug 847120 needs a clobber
+Bug 825341 appears to need a clobber
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -1821,17 +1821,17 @@ HyperTextAccessible::SetSelectionBounds(
   NS_ENSURE_STATE(domSel);
 
   uint32_t rangeCount = domSel->GetRangeCount();
   if (rangeCount < static_cast<uint32_t>(aSelectionNum))
     return NS_ERROR_INVALID_ARG;
 
   nsRefPtr<nsRange> range;
   if (aSelectionNum == rangeCount)
-    range = new nsRange();
+    range = new nsRange(mContent);
   else
     range = domSel->GetRangeAt(aSelectionNum);
 
   nsresult rv = HypertextOffsetsToDOMRange(startOffset, endOffset, range);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If new range was created then add it, otherwise notify selection listeners
   // that existing selection range was changed.
@@ -1883,17 +1883,17 @@ HyperTextAccessible::RemoveSelection(int
 //                     in unsigned long scrollType);
 NS_IMETHODIMP
 HyperTextAccessible::ScrollSubstringTo(int32_t aStartIndex, int32_t aEndIndex,
                                        uint32_t aScrollType)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mContent);
   nsresult rv = HypertextOffsetsToDOMRange(aStartIndex, aEndIndex, range);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return nsCoreUtils::ScrollSubstringTo(GetFrame(), range, aScrollType);
 }
 
 // void nsIAccessibleText::
 //   scrollSubstringToPoint(in long startIndex, in long endIndex,
@@ -1907,17 +1907,17 @@ HyperTextAccessible::ScrollSubstringToPo
 {
   nsIFrame *frame = GetFrame();
   if (!frame)
     return NS_ERROR_FAILURE;
 
   nsIntPoint coords = nsAccUtils::ConvertToScreenCoords(aX, aY, aCoordinateType,
                                                         this);
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mContent);
   nsresult rv = HypertextOffsetsToDOMRange(aStartIndex, aEndIndex, range);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsPresContext* presContext = frame->PresContext();
   nsPoint coordsInAppUnits =
     coords.ToAppUnits(presContext->AppUnitsPerDevPixel());
 
   bool initialScrolled = false;
--- a/accessible/src/windows/msaa/TextLeafAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/TextLeafAccessibleWrap.cpp
@@ -153,17 +153,17 @@ TextLeafAccessibleWrap::scrollToSubstrin
     /* [in] */ unsigned int aStartIndex,
     /* [in] */ unsigned int aEndIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (IsDefunct())
     return E_FAIL;
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mContent);
   if (NS_FAILED(range->SetStart(mContent, aStartIndex)))
       return E_FAIL;
 
   if (NS_FAILED(range->SetEnd(mContent, aEndIndex)))
   return E_FAIL;
 
   nsresult rv =
     nsCoreUtils::ScrollSubstringTo(GetFrame(), range,
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -107,16 +107,17 @@ namespace mozilla {
 
 class Selection;
 
 namespace layers {
   class LayerManager;
 } // namespace layers
 
 namespace dom {
+class DocumentFragment;
 class Element;
 } // namespace dom
 
 } // namespace mozilla
 
 extern const char kLoadAsData[];
 
 enum EventNameType {
@@ -361,16 +362,17 @@ public:
    */
   static nsresult CheckSameOrigin(const nsINode* aTrustedNode,
                                   nsIDOMNode* aUnTrustedNode);
   static nsresult CheckSameOrigin(const nsINode* aTrustedNode,
                                   const nsINode* unTrustedNode);
 
   // Check if the (JS) caller can access aNode.
   static bool CanCallerAccess(nsIDOMNode *aNode);
+  static bool CanCallerAccess(nsINode* aNode);
 
   // Check if the (JS) caller can access aWindow.
   // aWindow can be either outer or inner window.
   static bool CanCallerAccess(nsPIDOMWindow* aWindow);
 
   /**
    * Get the window through the JS context that's currently on the stack.
    * If there's no JS context currently on the stack, returns null.
@@ -1079,16 +1081,20 @@ public:
    * @param aFragment the string which is parsed to a DocumentFragment
    * @param aReturn the resulting fragment
    * @param aPreventScriptExecution whether to mark scripts as already started
    */
   static nsresult CreateContextualFragment(nsINode* aContextNode,
                                            const nsAString& aFragment,
                                            bool aPreventScriptExecution,
                                            nsIDOMDocumentFragment** aReturn);
+  static already_AddRefed<mozilla::dom::DocumentFragment>
+  CreateContextualFragment(nsINode* aContextNode, const nsAString& aFragment,
+                           bool aPreventScriptExecution,
+                           mozilla::ErrorResult& aRv);
 
   /**
    * Invoke the fragment parsing algorithm (innerHTML) using the HTML parser.
    *
    * @param aSourceBuffer the string being set as innerHTML
    * @param aTargetNode the target container
    * @param aContextLocalName local name of context node
    * @param aContextNamespace namespace of context node
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -2467,16 +2467,20 @@ NS_NewSVGDocument(nsIDocument** aInstanc
 nsresult
 NS_NewImageDocument(nsIDocument** aInstancePtrResult);
 
 #ifdef MOZ_MEDIA
 nsresult
 NS_NewVideoDocument(nsIDocument** aInstancePtrResult);
 #endif
 
+already_AddRefed<mozilla::dom::DocumentFragment>
+NS_NewDocumentFragment(nsNodeInfoManager* aNodeInfoManager,
+                       mozilla::ErrorResult& aRv);
+
 nsresult
 NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult,
                        nsNodeInfoManager *aNodeInfoManager);
 
 // Note: it's the caller's responsibility to create or get aPrincipal as needed
 // -- this method will not attempt to get a principal based on aDocumentURI.
 // Also, both aDocumentURI and aBaseURI must not be null.
 nsresult
--- a/content/base/src/DocumentFragment.cpp
+++ b/content/base/src/DocumentFragment.cpp
@@ -17,30 +17,43 @@
 #include "nsDOMString.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/DocumentFragmentBinding.h"
 
 nsresult
 NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult,
                        nsNodeInfoManager *aNodeInfoManager)
 {
+  mozilla::ErrorResult rv;
+  *aInstancePtrResult = NS_NewDocumentFragment(aNodeInfoManager, rv).get();
+  return rv.ErrorCode();
+}
+
+already_AddRefed<mozilla::dom::DocumentFragment>
+NS_NewDocumentFragment(nsNodeInfoManager* aNodeInfoManager,
+                       mozilla::ErrorResult& aRv)
+{
   using namespace mozilla::dom;
 
-  NS_ENSURE_ARG(aNodeInfoManager);
+  if (!aNodeInfoManager) {
+    aRv.Throw(NS_ERROR_INVALID_ARG);
+    return nullptr;
+  }
 
-  nsCOMPtr<nsINodeInfo> nodeInfo;
-  nodeInfo = aNodeInfoManager->GetNodeInfo(nsGkAtoms::documentFragmentNodeName,
-                                           nullptr, kNameSpaceID_None,
-                                           nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
-  NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
+  nsCOMPtr<nsINodeInfo> nodeInfo =
+    aNodeInfoManager->GetNodeInfo(nsGkAtoms::documentFragmentNodeName,
+                                  nullptr, kNameSpaceID_None,
+                                  nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
+  if (!nodeInfo) {
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return nullptr;
+  }
 
-  DocumentFragment *it = new DocumentFragment(nodeInfo.forget());
-  NS_ADDREF(*aInstancePtrResult = it);
-
-  return NS_OK;
+  nsRefPtr<DocumentFragment> it = new DocumentFragment(nodeInfo.forget());
+  return it.forget();
 }
 
 namespace mozilla {
 namespace dom {
 
 DocumentFragment::DocumentFragment(already_AddRefed<nsINodeInfo> aNodeInfo)
   : FragmentOrElement(aNodeInfo)
 {
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -163,16 +163,17 @@
 #include "nsIEditor.h"
 #include "mozilla/Attributes.h"
 #include "nsIParserService.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsSandboxFlags.h"
 #include "nsSVGFeatures.h"
 #include "MediaDecoder.h"
 #include "DecoderTraits.h"
+#include "mozilla/dom/DocumentFragment.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "nsViewportInfo.h"
 
 extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
                                       const char** next, PRUnichar* result);
 extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
                                  int ns_aware, const char** colon);
@@ -1584,33 +1585,39 @@ nsContentUtils::CanCallerAccess(nsIPrinc
   // is chrome.
   return IsCallerChrome();
 }
 
 // static
 bool
 nsContentUtils::CanCallerAccess(nsIDOMNode *aNode)
 {
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+  NS_ENSURE_TRUE(node, false);
+  return CanCallerAccess(node);
+}
+
+// static
+bool
+nsContentUtils::CanCallerAccess(nsINode* aNode)
+{
   // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
   // with the system principal games?  But really, there should be a simpler
   // API here, dammit.
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
   nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
   NS_ENSURE_SUCCESS(rv, false);
 
   if (!subjectPrincipal) {
     // we're running as system, grant access to the node.
 
     return true;
   }
 
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  NS_ENSURE_TRUE(node, false);
-
-  return CanCallerAccess(subjectPrincipal, node->NodePrincipal());
+  return CanCallerAccess(subjectPrincipal, aNode->NodePrincipal());
 }
 
 // static
 bool
 nsContentUtils::CanCallerAccess(nsPIDOMWindow* aWindow)
 {
   // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
   // with the system principal games?  But really, there should be a simpler
@@ -4040,75 +4047,87 @@ nsContentUtils::IsValidNodeName(nsIAtom 
 
 /* static */
 nsresult
 nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
                                          const nsAString& aFragment,
                                          bool aPreventScriptExecution,
                                          nsIDOMDocumentFragment** aReturn)
 {
-  *aReturn = nullptr;
-  NS_ENSURE_ARG(aContextNode);
+  ErrorResult rv;
+  *aReturn = CreateContextualFragment(aContextNode, aFragment,
+                                      aPreventScriptExecution, rv).get();
+  return rv.ErrorCode();
+}
+
+already_AddRefed<DocumentFragment>
+nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
+                                         const nsAString& aFragment,
+                                         bool aPreventScriptExecution,
+                                         ErrorResult& aRv)
+{
+  if (!aContextNode) {
+    aRv.Throw(NS_ERROR_INVALID_ARG);
+    return nullptr;
+  }
 
   // If we don't have a document here, we can't get the right security context
   // for compiling event handlers... so just bail out.
   nsCOMPtr<nsIDocument> document = aContextNode->OwnerDoc();
   bool isHTML = document->IsHTML();
 #ifdef DEBUG
   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(document);
   NS_ASSERTION(!isHTML || htmlDoc, "Should have HTMLDocument here!");
 #endif
 
   if (isHTML) {
-    nsCOMPtr<nsIDOMDocumentFragment> frag;
-    NS_NewDocumentFragment(getter_AddRefs(frag), document->NodeInfoManager());
+    nsRefPtr<DocumentFragment> frag =
+      NS_NewDocumentFragment(document->NodeInfoManager(), aRv);
     
     nsCOMPtr<nsIContent> contextAsContent = do_QueryInterface(aContextNode);
     if (contextAsContent && !contextAsContent->IsElement()) {
       contextAsContent = contextAsContent->GetParent();
       if (contextAsContent && !contextAsContent->IsElement()) {
         // can this even happen?
         contextAsContent = nullptr;
       }
     }
     
-    nsresult rv;
-    nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
     if (contextAsContent && !contextAsContent->IsHTML(nsGkAtoms::html)) {
-      rv = ParseFragmentHTML(aFragment,
-                             fragment,
-                             contextAsContent->Tag(),
-                             contextAsContent->GetNameSpaceID(),
-                             (document->GetCompatibilityMode() ==
+      aRv = ParseFragmentHTML(aFragment, frag,
+                              contextAsContent->Tag(),
+                              contextAsContent->GetNameSpaceID(),
+                              (document->GetCompatibilityMode() ==
                                eCompatibility_NavQuirks),
-                             aPreventScriptExecution);
+                              aPreventScriptExecution);
     } else {
-      rv = ParseFragmentHTML(aFragment,
-                             fragment,
-                             nsGkAtoms::body,
-                             kNameSpaceID_XHTML,
-                             (document->GetCompatibilityMode() ==
+      aRv = ParseFragmentHTML(aFragment, frag,
+                              nsGkAtoms::body,
+                              kNameSpaceID_XHTML,
+                              (document->GetCompatibilityMode() ==
                                eCompatibility_NavQuirks),
-                             aPreventScriptExecution);
+                              aPreventScriptExecution);
     }
 
-    frag.forget(aReturn);
-    return rv;
+    return frag.forget();
   }
 
   nsAutoTArray<nsString, 32> tagStack;
   nsAutoString uriStr, nameStr;
   nsCOMPtr<nsIContent> content = do_QueryInterface(aContextNode);
   // just in case we have a text node
   if (content && !content->IsElement())
     content = content->GetParent();
 
   while (content && content->IsElement()) {
     nsString& tagName = *tagStack.AppendElement();
-    NS_ENSURE_TRUE(&tagName, NS_ERROR_OUT_OF_MEMORY);
+    if (!&tagName) {
+      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+      return nullptr;
+    }
 
     tagName = content->NodeInfo()->QualifiedName();
 
     // see if we need to add xmlns declarations
     uint32_t count = content->GetAttrCount();
     bool setDefaultNamespace = false;
     if (count > 0) {
       uint32_t index;
@@ -4144,21 +4163,20 @@ nsContentUtils::CreateContextualFragment
         tagName.Append(NS_LITERAL_STRING(" xmlns=\"") + uriStr +
                        NS_LITERAL_STRING("\""));
       }
     }
 
     content = content->GetParent();
   }
 
-  return ParseFragmentXML(aFragment,
-                          document,
-                          tagStack,
-                          aPreventScriptExecution,
-                          aReturn);
+  nsCOMPtr<nsIDOMDocumentFragment> frag;
+  aRv = ParseFragmentXML(aFragment, document, tagStack,
+                         aPreventScriptExecution, getter_AddRefs(frag));
+  return static_cast<DocumentFragment*>(frag.forget().get());
 }
 
 /* static */
 void
 nsContentUtils::DropFragmentParsers()
 {
   NS_IF_RELEASE(sHTMLFragmentParser);
   NS_IF_RELEASE(sXMLFragmentParser);
--- a/content/base/src/nsCopySupport.cpp
+++ b/content/base/src/nsCopySupport.cpp
@@ -289,17 +289,17 @@ nsCopySupport::GetTransferableForNode(ns
                                       nsITransferable** aTransferable)
 {
   nsCOMPtr<nsISelection> selection;
   // Make a temporary selection with aNode in a single range.
   nsresult rv = NS_NewDomSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(aNode);
   rv = range->SelectNode(node);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = selection->AddRange(range);
   NS_ENSURE_SUCCESS(rv, rv);
   // It's not the primary selection - so don't skip invisible content.
   uint32_t flags = 0;
   return SelectionCopyHelper(selection, aDoc, false, 0, flags,
                              aTransferable);
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5568,17 +5568,17 @@ nsDocument::CreateRange(nsIDOMRange** aR
   ErrorResult rv;
   *aReturn = nsIDocument::CreateRange(rv).get();
   return rv.ErrorCode();
 }
 
 already_AddRefed<nsRange>
 nsIDocument::CreateRange(ErrorResult& rv)
 {
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(this);
   nsresult res = range->Set(this, 0, this, 0);
   if (NS_FAILED(res)) {
     rv.Throw(res);
     return nullptr;
   }
 
   return range.forget();
 }
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -24,37 +24,33 @@
 #include "nsIDOMNodeList.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsGenericDOMDataNode.h"
 #include "nsClientRect.h"
 #include "nsLayoutUtils.h"
 #include "nsTextFrame.h"
 #include "nsFontFaceList.h"
+#include "mozilla/dom/DocumentFragment.h"
+#include "mozilla/dom/RangeBinding.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Likely.h"
 
 using namespace mozilla;
 
+JSObject*
+nsRange::WrapObject(JSContext* aCx, JSObject* aScope)
+{
+  return dom::RangeBinding::Wrap(aCx, aScope, this);
+}
+
 /******************************************************
  * stack based utilty class for managing monitor
  ******************************************************/
 
-// NS_ERROR_DOM_NOT_OBJECT_ERR is not the correct one to throw, but spec doesn't say
-// what is
-#define VALIDATE_ACCESS(node_)                                                     \
-  PR_BEGIN_MACRO                                                                   \
-    if (!node_) {                                                                  \
-      return NS_ERROR_DOM_NOT_OBJECT_ERR;                                          \
-    }                                                                              \
-    if (!nsContentUtils::CanCallerAccess(node_)) {                                 \
-      return NS_ERROR_DOM_SECURITY_ERR;                                            \
-    }                                                                              \
-  PR_END_MACRO
-
 static void InvalidateAllFrames(nsINode* aNode)
 {
   NS_PRECONDITION(aNode, "bad arg");
 
   nsIFrame* frame = nullptr;
   switch (aNode->NodeType()) {
     case nsIDOMNode::TEXT_NODE:
     case nsIDOMNode::ELEMENT_NODE:
@@ -219,19 +215,22 @@ nsRange::~nsRange()
 nsresult
 nsRange::CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
                      nsIDOMNode* aEndParent, int32_t aEndOffset,
                      nsRange** aRange)
 {
   MOZ_ASSERT(aRange);
   *aRange = NULL;
 
-  nsRefPtr<nsRange> range = new nsRange();
-
-  nsresult rv = range->SetStart(aStartParent, aStartOffset);
+  nsCOMPtr<nsINode> startParent = do_QueryInterface(aStartParent);
+  NS_ENSURE_ARG_POINTER(startParent);
+
+  nsRefPtr<nsRange> range = new nsRange(startParent);
+
+  nsresult rv = range->SetStart(startParent, aStartOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = range->SetEnd(aEndParent, aEndOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   range.forget(aRange);
   return NS_OK;
 }
@@ -255,32 +254,42 @@ nsRange::CreateRange(nsIDOMNode* aStartP
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsRange)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsRange)
 
 DOMCI_DATA(Range, nsRange)
 
 // QueryInterface implementation for nsRange
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsRange)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMRange)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMRange)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Range)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsRange)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner);
   tmp->Reset();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStartParent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndParent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsRange)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+
 static void
 RangeHashTableDtor(void* aObject, nsIAtom* aPropertyName, void* aPropertyValue,
                    void* aData)
 {
   nsRange::RangeHashTable* ranges =
     static_cast<nsRange::RangeHashTable*>(aPropertyValue);
   delete ranges;
 }
@@ -682,108 +691,138 @@ nsRange::ParentChainChanged(nsIContent *
 }
 
 /******************************************************
  * Utilities for comparing points: API from nsIDOMRange
  ******************************************************/
 NS_IMETHODIMP
 nsRange::IsPointInRange(nsIDOMNode* aParent, int32_t aOffset, bool* aResult)
 {
-  int16_t compareResult = 0;
-  nsresult rv = ComparePoint(aParent, aOffset, &compareResult);
-  // If the node isn't in the range's document, it clearly isn't in the range.
-  if (rv == NS_ERROR_DOM_WRONG_DOCUMENT_ERR) {
-    *aResult = false;
-    return NS_OK;
+  nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
+  if (!parent) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
   }
 
-  *aResult = compareResult == 0;
-
-  return rv;
+  ErrorResult rv;
+  *aResult = IsPointInRange(*parent, aOffset, rv);
+  return rv.ErrorCode();
 }
-  
+
+bool
+nsRange::IsPointInRange(nsINode& aParent, uint32_t aOffset, ErrorResult& aRv)
+{
+  uint16_t compareResult = ComparePoint(aParent, aOffset, aRv);
+  // If the node isn't in the range's document, it clearly isn't in the range.
+  if (aRv.ErrorCode() == NS_ERROR_DOM_WRONG_DOCUMENT_ERR) {
+    aRv = NS_OK;
+    return false;
+  }
+
+  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* aParent, int32_t aOffset, int16_t* aResult)
 {
-  // our range is in a good state?
-  if (!mIsPositioned) 
-    return NS_ERROR_NOT_INITIALIZED;
-
   nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
   NS_ENSURE_TRUE(parent, NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
 
-  if (!nsContentUtils::ContentIsDescendantOf(parent, mRoot)) {
-    return NS_ERROR_DOM_WRONG_DOCUMENT_ERR;
+  ErrorResult rv;
+  *aResult = ComparePoint(*parent, aOffset, rv);
+  return rv.ErrorCode();
+}
+
+int16_t
+nsRange::ComparePoint(nsINode& aParent, uint32_t aOffset, ErrorResult& aRv)
+{
+  // our range is in a good state?
+  if (!mIsPositioned) {
+    aRv.Throw(NS_ERROR_NOT_INITIALIZED);
+    return 0;
   }
-  
-  if (parent->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
-    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+
+  if (!nsContentUtils::ContentIsDescendantOf(&aParent, mRoot)) {
+    aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
+    return 0;
   }
 
-  if (aOffset < 0 || uint32_t(aOffset) > parent->Length()) {
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  if (aParent.NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
+    return 0;
   }
-  
+
+  if (aOffset > aParent.Length()) {
+    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    return 0;
+  }
+
   int32_t cmp;
-  if ((cmp = nsContentUtils::ComparePoints(parent, aOffset,
+  if ((cmp = nsContentUtils::ComparePoints(&aParent, aOffset,
                                            mStartParent, mStartOffset)) <= 0) {
-    
-    *aResult = cmp;
+
+    return cmp;
   }
-  else if (nsContentUtils::ComparePoints(mEndParent, mEndOffset,
-                                         parent, aOffset) == -1) {
-    *aResult = 1;
+  if (nsContentUtils::ComparePoints(mEndParent, mEndOffset,
+                                    &aParent, aOffset) == -1) {
+    return 1;
   }
-  else {
-    *aResult = 0;
-  }
-  
-  return NS_OK;
+
+  return 0;
 }
 
 NS_IMETHODIMP
 nsRange::IntersectsNode(nsIDOMNode* aNode, bool* aResult)
 {
   *aResult = false;
 
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   // TODO: This should throw a TypeError.
   NS_ENSURE_ARG(node);
 
-  NS_ENSURE_TRUE(mIsPositioned, NS_ERROR_NOT_INITIALIZED);
+  ErrorResult rv;
+  *aResult = IntersectsNode(*node, rv);
+  return rv.ErrorCode();
+}
+
+bool
+nsRange::IntersectsNode(nsINode& aNode, ErrorResult& aRv)
+{
+  if (!mIsPositioned) {
+    aRv.Throw(NS_ERROR_NOT_INITIALIZED);
+    return false;
+  }
 
   // Step 3.
-  nsINode* parent = node->GetParentNode();
+  nsINode* parent = aNode.GetParentNode();
   if (!parent) {
     // Steps 2 and 4. 
     // |parent| is null, so |node|'s root is |node| itself.
-    *aResult = (GetRoot() == node);
-    return NS_OK;
+    return GetRoot() == &aNode;
   }
 
   // Step 5.
-  int32_t nodeIndex = parent->IndexOf(node);
+  int32_t nodeIndex = parent->IndexOf(&aNode);
 
   // Steps 6-7.
   // Note: if disconnected is true, ComparePoints returns 1.
   bool disconnected = false;
-  *aResult = nsContentUtils::ComparePoints(mStartParent, mStartOffset,
-                                           parent, nodeIndex + 1,
-                                           &disconnected) < 0 &&
-             nsContentUtils::ComparePoints(parent, nodeIndex,
-                                           mEndParent, mEndOffset,
-                                           &disconnected) < 0;
+  bool result = nsContentUtils::ComparePoints(mStartParent, mStartOffset,
+                                             parent, nodeIndex + 1,
+                                             &disconnected) < 0 &&
+               nsContentUtils::ComparePoints(parent, nodeIndex,
+                                             mEndParent, mEndOffset,
+                                             &disconnected) < 0;
 
   // Step 2.
   if (disconnected) {
-    *aResult = false;
+    result = false;
   }
-  return NS_OK;
+  return result;
 }
 
 /******************************************************
  * Private helper routines
  ******************************************************/
 
 // It's important that all setting of the range start/end points 
 // go through this function, which will do all the right voodoo
@@ -851,29 +890,33 @@ nsRange::DoSetRange(nsINode* aStartN, in
   }
 
   // This needs to be the last thing this function does.  See comment
   // in ParentChainChanged.
   mRoot = aRoot;
 }
 
 static int32_t
+IndexOf(nsINode* aChild)
+{
+  nsINode* parent = aChild->GetParentNode();
+
+  return parent ? parent->IndexOf(aChild) : -1;
+}
+
+static int32_t
 IndexOf(nsIDOMNode* aChildNode)
 {
   // convert node to nsIContent, so that we can find the child index
 
   nsCOMPtr<nsINode> child = do_QueryInterface(aChildNode);
   if (!child) {
     return -1;
   }
-
-  nsINode *parent = child->GetParentNode();
-
-  // finally we get the index
-  return parent ? parent->IndexOf(child) : -1;
+  return IndexOf(child);
 }
 
 nsINode*
 nsRange::GetCommonAncestor() const
 {
   return mIsPositioned ?
     nsContentUtils::GetCommonAncestor(mStartParent, mEndParent) :
     nullptr;
@@ -893,71 +936,125 @@ NS_IMETHODIMP
 nsRange::GetStartContainer(nsIDOMNode** aStartParent)
 {
   if (!mIsPositioned)
     return NS_ERROR_NOT_INITIALIZED;
 
   return CallQueryInterface(mStartParent, aStartParent);
 }
 
+nsINode*
+nsRange::GetStartContainer(ErrorResult& aRv) const
+{
+  if (!mIsPositioned) {
+    aRv.Throw(NS_ERROR_NOT_INITIALIZED);
+    return nullptr;
+  }
+
+  return mStartParent;
+}
+
 NS_IMETHODIMP
 nsRange::GetStartOffset(int32_t* aStartOffset)
 {
   if (!mIsPositioned)
     return NS_ERROR_NOT_INITIALIZED;
 
   *aStartOffset = mStartOffset;
 
   return NS_OK;
 }
 
+uint32_t
+nsRange::GetStartOffset(ErrorResult& aRv) const
+{
+  if (!mIsPositioned) {
+    aRv.Throw(NS_ERROR_NOT_INITIALIZED);
+    return 0;
+  }
+
+  return mStartOffset;
+}
+
 NS_IMETHODIMP
 nsRange::GetEndContainer(nsIDOMNode** aEndParent)
 {
   if (!mIsPositioned)
     return NS_ERROR_NOT_INITIALIZED;
 
   return CallQueryInterface(mEndParent, aEndParent);
 }
 
+nsINode*
+nsRange::GetEndContainer(ErrorResult& aRv) const
+{
+  if (!mIsPositioned) {
+    aRv.Throw(NS_ERROR_NOT_INITIALIZED);
+    return nullptr;
+  }
+
+  return mEndParent;
+}
+
 NS_IMETHODIMP
 nsRange::GetEndOffset(int32_t* aEndOffset)
 {
   if (!mIsPositioned)
     return NS_ERROR_NOT_INITIALIZED;
 
   *aEndOffset = mEndOffset;
 
   return NS_OK;
 }
 
+uint32_t
+nsRange::GetEndOffset(ErrorResult& aRv) const
+{
+  if (!mIsPositioned) {
+    aRv.Throw(NS_ERROR_NOT_INITIALIZED);
+    return 0;
+  }
+
+  return mEndOffset;
+}
+
 NS_IMETHODIMP
 nsRange::GetCollapsed(bool* aIsCollapsed)
 {
   if (!mIsPositioned)
     return NS_ERROR_NOT_INITIALIZED;
 
   *aIsCollapsed = Collapsed();
 
   return NS_OK;
 }
 
+nsINode*
+nsRange::GetCommonAncestorContainer(ErrorResult& aRv) const
+{
+  if (!mIsPositioned) {
+    aRv.Throw(NS_ERROR_NOT_INITIALIZED);
+    return nullptr;
+  }
+
+  return nsContentUtils::GetCommonAncestor(mStartParent, mEndParent);
+}
+
 NS_IMETHODIMP
 nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent)
 {
-  *aCommonParent = nullptr;
-  if (!mIsPositioned)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  nsINode* container = nsContentUtils::GetCommonAncestor(mStartParent, mEndParent);
-  if (container) {
-    return CallQueryInterface(container, aCommonParent);
+  ErrorResult rv;
+  nsINode* commonAncestor = GetCommonAncestorContainer(rv);
+  if (commonAncestor) {
+    NS_ADDREF(*aCommonParent = commonAncestor->AsDOMNode());
+  } else {
+    *aCommonParent = nullptr;
   }
 
-  return NS_ERROR_NOT_INITIALIZED;
+  return rv.ErrorCode();
 }
 
 nsINode*
 nsRange::IsValidBoundary(nsINode* aNode)
 {
   if (!aNode) {
     return nullptr;
   }
@@ -998,24 +1095,39 @@ nsRange::IsValidBoundary(nsINode* aNode)
                    root->IsNodeOfType(nsINode::eATTRIBUTE),
                    "Creating a DOM Range using root which isn't in DOM!");
 #endif
 
   // We allow this because of backward compatibility.
   return root;
 }
 
+void
+nsRange::SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
+{
+ if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  AutoInvalidateSelection atEndOfBlock(this);
+  aRv = SetStart(&aNode, aOffset);
+}
+
 NS_IMETHODIMP
 nsRange::SetStart(nsIDOMNode* aParent, int32_t aOffset)
 {
-  VALIDATE_ACCESS(aParent);
-
   nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
-  AutoInvalidateSelection atEndOfBlock(this);
-  return SetStart(parent, aOffset);
+  if (!parent) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
+  }
+
+  ErrorResult rv;
+  SetStart(*parent, aOffset, rv);
+  return rv.ErrorCode();
 }
 
 /* virtual */ nsresult
 nsRange::SetStart(nsINode* aParent, int32_t aOffset)
 {
   nsINode* newRoot = IsValidBoundary(aParent);
   NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
 
@@ -1033,55 +1145,90 @@ nsRange::SetStart(nsINode* aParent, int3
     return NS_OK;
   }
 
   DoSetRange(aParent, aOffset, mEndParent, mEndOffset, mRoot);
   
   return NS_OK;
 }
 
+void
+nsRange::SetStartBefore(nsINode& aNode, ErrorResult& aRv)
+{
+  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  AutoInvalidateSelection atEndOfBlock(this);
+  aRv = SetStart(aNode.GetParentNode(), IndexOf(&aNode));
+}
+
 NS_IMETHODIMP
 nsRange::SetStartBefore(nsIDOMNode* aSibling)
 {
-  VALIDATE_ACCESS(aSibling);
-  
-  nsCOMPtr<nsIDOMNode> parent;
-  nsresult rv = aSibling->GetParentNode(getter_AddRefs(parent));
-  if (NS_FAILED(rv) || !parent) {
-    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+  nsCOMPtr<nsINode> sibling = do_QueryInterface(aSibling);
+  if (!sibling) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
   }
 
-  return SetStart(parent, IndexOf(aSibling));
+  ErrorResult rv;
+  SetStartBefore(*sibling, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsRange::SetStartAfter(nsINode& aNode, ErrorResult& aRv)
+{
+  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  AutoInvalidateSelection atEndOfBlock(this);
+  aRv = SetStart(aNode.GetParentNode(), IndexOf(&aNode) + 1);
 }
 
 NS_IMETHODIMP
 nsRange::SetStartAfter(nsIDOMNode* aSibling)
 {
-  VALIDATE_ACCESS(aSibling);
-
-  nsCOMPtr<nsIDOMNode> nParent;
-  nsresult res = aSibling->GetParentNode(getter_AddRefs(nParent));
-  if (NS_FAILED(res) || !nParent) {
-    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+  nsCOMPtr<nsINode> sibling = do_QueryInterface(aSibling);
+  if (!sibling) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
   }
 
-  return SetStart(nParent, IndexOf(aSibling) + 1);
+  ErrorResult rv;
+  SetStartAfter(*sibling, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsRange::SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
+{
+ if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+  AutoInvalidateSelection atEndOfBlock(this);
+  aRv = SetEnd(&aNode, aOffset);
 }
 
 NS_IMETHODIMP
 nsRange::SetEnd(nsIDOMNode* aParent, int32_t aOffset)
 {
-  VALIDATE_ACCESS(aParent);
-
-  AutoInvalidateSelection atEndOfBlock(this);
   nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
-  return SetEnd(parent, aOffset);
+  if (!parent) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
+  }
+
+  ErrorResult rv;
+  SetEnd(*parent, aOffset, rv);
+  return rv.ErrorCode();
 }
 
-
 /* virtual */ nsresult
 nsRange::SetEnd(nsINode* aParent, int32_t aOffset)
 {
   nsINode* newRoot = IsValidBoundary(aParent);
   NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
 
   if (aOffset < 0 || uint32_t(aOffset) > aParent->Length()) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
@@ -1097,42 +1244,64 @@ nsRange::SetEnd(nsINode* aParent, int32_
     return NS_OK;
   }
 
   DoSetRange(mStartParent, mStartOffset, aParent, aOffset, mRoot);
 
   return NS_OK;
 }
 
+void
+nsRange::SetEndBefore(nsINode& aNode, ErrorResult& aRv)
+{
+  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  AutoInvalidateSelection atEndOfBlock(this);
+  aRv = SetEnd(aNode.GetParentNode(), IndexOf(&aNode));
+}
+
 NS_IMETHODIMP
 nsRange::SetEndBefore(nsIDOMNode* aSibling)
 {
-  VALIDATE_ACCESS(aSibling);
-  
-  nsCOMPtr<nsIDOMNode> nParent;
-  nsresult rv = aSibling->GetParentNode(getter_AddRefs(nParent));
-  if (NS_FAILED(rv) || !nParent) {
-    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+  nsCOMPtr<nsINode> sibling = do_QueryInterface(aSibling);
+  if (!sibling) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
   }
 
-  return SetEnd(nParent, IndexOf(aSibling));
+  ErrorResult rv;
+  SetEndBefore(*sibling, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsRange::SetEndAfter(nsINode& aNode, ErrorResult& aRv)
+{
+  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  AutoInvalidateSelection atEndOfBlock(this);
+  aRv = SetEnd(aNode.GetParentNode(), IndexOf(&aNode) + 1);
 }
 
 NS_IMETHODIMP
 nsRange::SetEndAfter(nsIDOMNode* aSibling)
 {
-  VALIDATE_ACCESS(aSibling);
-  
-  nsCOMPtr<nsIDOMNode> nParent;
-  nsresult res = aSibling->GetParentNode(getter_AddRefs(nParent));
-  if (NS_FAILED(res) || !nParent) {
-    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+  nsCOMPtr<nsINode> sibling = do_QueryInterface(aSibling);
+  if (!sibling) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
   }
 
-  return SetEnd(nParent, IndexOf(aSibling) + 1);
+  ErrorResult rv;
+  SetEndAfter(*sibling, rv);
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsRange::Collapse(bool aToStart)
 {
   if (!mIsPositioned)
     return NS_ERROR_NOT_INITIALIZED;
 
@@ -1143,49 +1312,76 @@ nsRange::Collapse(bool aToStart)
     DoSetRange(mEndParent, mEndOffset, mEndParent, mEndOffset, mRoot);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsRange::SelectNode(nsIDOMNode* aN)
 {
-  VALIDATE_ACCESS(aN);
-  
   nsCOMPtr<nsINode> node = do_QueryInterface(aN);
   NS_ENSURE_TRUE(node, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
 
-  nsINode* parent = node->GetParentNode();
+  ErrorResult rv;
+  SelectNode(*node, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsRange::SelectNode(nsINode& aNode, ErrorResult& aRv)
+{
+  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  nsINode* parent = aNode.GetParentNode();
   nsINode* newRoot = IsValidBoundary(parent);
-  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
-
-  int32_t index = parent->IndexOf(node);
+  if (!newRoot) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
+    return;
+  }
+
+  int32_t index = parent->IndexOf(&aNode);
   if (index < 0) {
-    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
+    return;
   }
 
   AutoInvalidateSelection atEndOfBlock(this);
   DoSetRange(parent, index, parent, index + 1, newRoot);
-  
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsRange::SelectNodeContents(nsIDOMNode* aN)
 {
-  VALIDATE_ACCESS(aN);
-
   nsCOMPtr<nsINode> node = do_QueryInterface(aN);
-  nsINode* newRoot = IsValidBoundary(node);
-  NS_ENSURE_TRUE(newRoot, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
-  
+  NS_ENSURE_TRUE(node, NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
+
+  ErrorResult rv;
+  SelectNodeContents(*node, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsRange::SelectNodeContents(nsINode& aNode, ErrorResult& aRv)
+{
+  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  nsINode* newRoot = IsValidBoundary(&aNode);
+  if (!newRoot) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
+    return;
+  }
+
   AutoInvalidateSelection atEndOfBlock(this);
-  DoSetRange(node, 0, node, node->Length(), newRoot);
-  
-  return NS_OK;
+  DoSetRange(&aNode, 0, &aNode, aNode.Length(), newRoot);
 }
 
 // The Subtree Content Iterator only returns subtrees that are
 // completely within a given range. It doesn't return a CharacterData
 // node that contains either the start or end point of the range.,
 // nor does it return element nodes when nothing in the element is selected.
 // We need an iterator that will also include these start/end points
 // so that our methods/algorithms aren't cluttered with special
@@ -1579,38 +1775,37 @@ ValidateCurrentNode(nsRange* aRange, Ran
   nsCOMPtr<nsINode> node = do_QueryInterface(domNode);
   MOZ_ASSERT(node);
 
   nsresult res = nsRange::CompareNodeToRange(node, aRange, &before, &after);
 
   return NS_SUCCEEDED(res) && !before && !after;
 }
 
-nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
+nsresult
+nsRange::CutContents(dom::DocumentFragment** aFragment)
 { 
   if (aFragment) {
     *aFragment = nullptr;
   }
 
-  nsresult rv;
-
   nsCOMPtr<nsIDocument> doc = mStartParent->OwnerDoc();
 
   nsCOMPtr<nsIDOMNode> commonAncestor;
-  rv = GetCommonAncestorContainer(getter_AddRefs(commonAncestor));
+  nsresult rv = GetCommonAncestorContainer(getter_AddRefs(commonAncestor));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If aFragment isn't null, create a temporary fragment to hold our return.
-  nsCOMPtr<nsIDOMDocumentFragment> retval;
+  nsRefPtr<dom::DocumentFragment> retval;
   if (aFragment) {
-    rv = NS_NewDocumentFragment(getter_AddRefs(retval),
-                                doc->NodeInfoManager());
-    NS_ENSURE_SUCCESS(rv, rv);
+    ErrorResult error;
+    retval = NS_NewDocumentFragment(doc->NodeInfoManager(), error);
+    NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode());
   }
-  nsCOMPtr<nsIDOMNode> commonCloneAncestor(do_QueryInterface(retval));
+  nsCOMPtr<nsIDOMNode> commonCloneAncestor = retval.get();
 
   // 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<nsIDOMNode> startContainer = do_QueryInterface(mStartParent);
@@ -1870,73 +2065,102 @@ nsresult nsRange::CutContents(nsIDOMDocu
 }
 
 NS_IMETHODIMP
 nsRange::DeleteContents()
 {
   return CutContents(nullptr);
 }
 
+void
+nsRange::DeleteContents(ErrorResult& aRv)
+{
+  aRv = CutContents(nullptr);
+}
+
 NS_IMETHODIMP
 nsRange::ExtractContents(nsIDOMDocumentFragment** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
-  return CutContents(aReturn);
+  nsRefPtr<dom::DocumentFragment> fragment;
+  nsresult rv = CutContents(getter_AddRefs(fragment));
+  fragment.forget(aReturn);
+  return rv;
+}
+
+already_AddRefed<dom::DocumentFragment>
+nsRange::ExtractContents(ErrorResult& rv)
+{
+  nsRefPtr<dom::DocumentFragment> fragment;
+  rv = CutContents(getter_AddRefs(fragment));
+  return fragment.forget();
 }
 
 NS_IMETHODIMP
 nsRange::CompareBoundaryPoints(uint16_t aHow, nsIDOMRange* aOtherRange,
                                int16_t* aCmpRet)
 {
   nsRange* otherRange = static_cast<nsRange*>(aOtherRange);
   NS_ENSURE_TRUE(otherRange, NS_ERROR_NULL_POINTER);
 
-  if (!mIsPositioned || !otherRange->IsPositioned())
-    return NS_ERROR_NOT_INITIALIZED;
+  ErrorResult rv;
+  *aCmpRet = CompareBoundaryPoints(aHow, *otherRange, rv);
+  return rv.ErrorCode();
+}
+
+int16_t
+nsRange::CompareBoundaryPoints(uint16_t aHow, nsRange& aOtherRange,
+                               ErrorResult& rv)
+{
+  if (!mIsPositioned || !aOtherRange.IsPositioned()) {
+    rv.Throw(NS_ERROR_NOT_INITIALIZED);
+    return 0;
+  }
 
   nsINode *ourNode, *otherNode;
   int32_t ourOffset, otherOffset;
 
   switch (aHow) {
     case nsIDOMRange::START_TO_START:
       ourNode = mStartParent;
       ourOffset = mStartOffset;
-      otherNode = otherRange->GetStartParent();
-      otherOffset = otherRange->StartOffset();
+      otherNode = aOtherRange.GetStartParent();
+      otherOffset = aOtherRange.StartOffset();
       break;
     case nsIDOMRange::START_TO_END:
       ourNode = mEndParent;
       ourOffset = mEndOffset;
-      otherNode = otherRange->GetStartParent();
-      otherOffset = otherRange->StartOffset();
+      otherNode = aOtherRange.GetStartParent();
+      otherOffset = aOtherRange.StartOffset();
       break;
     case nsIDOMRange::END_TO_START:
       ourNode = mStartParent;
       ourOffset = mStartOffset;
-      otherNode = otherRange->GetEndParent();
-      otherOffset = otherRange->EndOffset();
+      otherNode = aOtherRange.GetEndParent();
+      otherOffset = aOtherRange.EndOffset();
       break;
     case nsIDOMRange::END_TO_END:
       ourNode = mEndParent;
       ourOffset = mEndOffset;
-      otherNode = otherRange->GetEndParent();
-      otherOffset = otherRange->EndOffset();
+      otherNode = aOtherRange.GetEndParent();
+      otherOffset = aOtherRange.EndOffset();
       break;
     default:
       // We were passed an illegal value
-      return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+      rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+      return 0;
   }
 
-  if (mRoot != otherRange->GetRoot())
-    return NS_ERROR_DOM_WRONG_DOCUMENT_ERR;
-
-  *aCmpRet = nsContentUtils::ComparePoints(ourNode, ourOffset,
-                                           otherNode, otherOffset);
-
-  return NS_OK;
+  if (mRoot != aOtherRange.GetRoot()) {
+    rv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
+    return 0;
+  }
+
+  return nsContentUtils::ComparePoints(ourNode, ourOffset,
+                                       otherNode, otherOffset);
 }
 
 /* static */ nsresult
 nsRange::CloneParentsBetween(nsIDOMNode *aAncestor,
                              nsIDOMNode *aNode,
                              nsIDOMNode **aClosestAncestor,
                              nsIDOMNode **aFarthestAncestor)
 {
@@ -1983,55 +2207,68 @@ nsRange::CloneParentsBetween(nsIDOMNode 
   NS_IF_ADDREF(*aFarthestAncestor);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsRange::CloneContents(nsIDOMDocumentFragment** aReturn)
 {
-  nsresult res;
+  ErrorResult rv;
+  *aReturn = CloneContents(rv).get();
+  return rv.ErrorCode();
+}
+
+already_AddRefed<dom::DocumentFragment>
+nsRange::CloneContents(ErrorResult& aRv)
+{
   nsCOMPtr<nsIDOMNode> commonAncestor;
-  res = GetCommonAncestorContainer(getter_AddRefs(commonAncestor));
-  if (NS_FAILED(res)) return res;
+  aRv = GetCommonAncestorContainer(getter_AddRefs(commonAncestor));
+  MOZ_ASSERT(!aRv.Failed(), "GetCommonAncestorContainer() shouldn't fail!");
 
   nsCOMPtr<nsIDOMDocument> document =
     do_QueryInterface(mStartParent->OwnerDoc());
   NS_ASSERTION(document, "CloneContents needs a document to continue.");
-  if (!document) return NS_ERROR_FAILURE;
+  if (!document) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
 
   // Create a new document fragment in the context of this document,
   // which might be null
 
-  nsCOMPtr<nsIDOMDocumentFragment> clonedFrag;
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
 
-  res = NS_NewDocumentFragment(getter_AddRefs(clonedFrag),
-                               doc->NodeInfoManager());
-  if (NS_FAILED(res)) return res;
-
-  nsCOMPtr<nsIDOMNode> commonCloneAncestor(do_QueryInterface(clonedFrag));
-  if (!commonCloneAncestor) return NS_ERROR_FAILURE;
+  nsRefPtr<dom::DocumentFragment> clonedFrag =
+    NS_NewDocumentFragment(doc->NodeInfoManager(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDOMNode> commonCloneAncestor = clonedFrag.get();
+  if (!commonCloneAncestor) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
 
   // Create and initialize a subtree iterator that will give
   // us all the subtrees within the range.
 
   RangeSubtreeIterator iter;
 
-  res = iter.Init(this);
-  if (NS_FAILED(res)) return res;
+  aRv = iter.Init(this);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
   if (iter.IsDone())
   {
     // There's nothing to add to the doc frag, we must be done!
-
-    *aReturn = clonedFrag;
-    NS_IF_ADDREF(*aReturn);
-    return NS_OK;
+    return clonedFrag.forget();
   }
 
   iter.First();
 
   // With the exception of text nodes that contain one of the range
   // end points and elements which don't have any content selected the subtree
   // iterator should only give us back subtrees that are completely contained
   // between the range's end points.
@@ -2049,18 +2286,20 @@ nsRange::CloneContents(nsIDOMDocumentFra
                        (!(iNode == mEndParent && mEndOffset == 0) &&
                         !(iNode == mStartParent &&
                           mStartOffset ==
                             int32_t(iNode->AsElement()->GetChildCount())));
 
     // Clone the current subtree!
 
     nsCOMPtr<nsIDOMNode> clone;
-    res = node->CloneNode(deepClone, 1, getter_AddRefs(clone));
-    if (NS_FAILED(res)) return res;
+    aRv = node->CloneNode(deepClone, 1, getter_AddRefs(clone));
+    if (aRv.Failed()) {
+      return nullptr;
+    }
 
     // If it's CharacterData, make sure we only clone what
     // is in the range.
     //
     // XXX_kin: We need to also handle ProcessingInstruction
     // XXX_kin: according to the spec.
 
     nsCOMPtr<nsIDOMCharacterData> charData(do_QueryInterface(clone));
@@ -2068,124 +2307,150 @@ nsRange::CloneContents(nsIDOMDocumentFra
     if (charData)
     {
       if (iNode == mEndParent)
       {
         // We only need the data before mEndOffset, so get rid of any
         // data after it.
 
         uint32_t dataLength = 0;
-        res = charData->GetLength(&dataLength);
-        if (NS_FAILED(res)) return res;
+        aRv = charData->GetLength(&dataLength);
+        if (aRv.Failed()) {
+          return nullptr;
+        }
 
         if (dataLength > (uint32_t)mEndOffset)
         {
-          res = charData->DeleteData(mEndOffset, dataLength - mEndOffset);
-          if (NS_FAILED(res)) return res;
+          aRv = charData->DeleteData(mEndOffset, dataLength - mEndOffset);
+          if (aRv.Failed()) {
+            return nullptr;
+          }
         }
       }       
 
       if (iNode == mStartParent)
       {
         // We don't need any data before mStartOffset, so just
         // delete it!
 
         if (mStartOffset > 0)
         {
-          res = charData->DeleteData(0, mStartOffset);
-          if (NS_FAILED(res)) return res;
+          aRv = charData->DeleteData(0, mStartOffset);
+          if (aRv.Failed()) {
+            return nullptr;
+          }
         }
       }
     }
 
     // Clone the parent hierarchy between commonAncestor and node.
 
     nsCOMPtr<nsIDOMNode> closestAncestor, farthestAncestor;
 
-    res = CloneParentsBetween(commonAncestor, node,
+    aRv = CloneParentsBetween(commonAncestor, node,
                               getter_AddRefs(closestAncestor),
                               getter_AddRefs(farthestAncestor));
 
-    if (NS_FAILED(res)) return res;
+    if (aRv.Failed()) {
+      return nullptr;
+    }
 
     // Hook the parent hierarchy/context of the subtree into the clone tree.
 
     nsCOMPtr<nsIDOMNode> tmpNode;
 
     if (farthestAncestor)
     {
-      res = commonCloneAncestor->AppendChild(farthestAncestor,
+      aRv = commonCloneAncestor->AppendChild(farthestAncestor,
                                              getter_AddRefs(tmpNode));
 
-      if (NS_FAILED(res)) return res;
+      if (aRv.Failed()) {
+        return nullptr;
+      }
     }
 
     // Place the cloned subtree into the cloned doc frag tree!
 
     if (closestAncestor)
     {
       // Append the subtree under closestAncestor since it is the
       // immediate parent of the subtree.
 
-      res = closestAncestor->AppendChild(clone, getter_AddRefs(tmpNode));
+      aRv = closestAncestor->AppendChild(clone, getter_AddRefs(tmpNode));
     }
     else
     {
       // If we get here, there is no missing parent hierarchy between 
       // commonAncestor and node, so just append clone to commonCloneAncestor.
 
-      res = commonCloneAncestor->AppendChild(clone, getter_AddRefs(tmpNode));
+      aRv = commonCloneAncestor->AppendChild(clone, getter_AddRefs(tmpNode));
     }
-    if (NS_FAILED(res)) return res;
+    if (aRv.Failed()) {
+      return nullptr;
+    }
 
     // Get the next subtree to be processed. The idea here is to setup
     // the parameters for the next iteration of the loop.
 
     iter.Next();
 
     if (iter.IsDone())
       break; // We must be done!
 
     nsCOMPtr<nsIDOMNode> nextNode(iter.GetCurrentNode());
-    if (!nextNode) return NS_ERROR_FAILURE;
+    if (!nextNode) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
 
     // Get node and nextNode's common parent.
     nsContentUtils::GetCommonAncestor(node, nextNode, getter_AddRefs(commonAncestor));
 
-    if (!commonAncestor)
-      return NS_ERROR_FAILURE;
+    if (!commonAncestor) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
 
     // Find the equivalent of commonAncestor in the cloned tree!
 
     while (node && node != commonAncestor)
     {
       tmpNode = node;
-      res = tmpNode->GetParentNode(getter_AddRefs(node));
-      if (NS_FAILED(res)) return res;
-      if (!node) return NS_ERROR_FAILURE;
+      aRv = tmpNode->GetParentNode(getter_AddRefs(node));
+      if (aRv.Failed()) {
+        return nullptr;
+      }
+
+      if (!node) {
+        aRv.Throw(NS_ERROR_FAILURE);
+        return nullptr;
+      }
 
       tmpNode = clone;
-      res = tmpNode->GetParentNode(getter_AddRefs(clone));
-      if (NS_FAILED(res)) return res;
-      if (!clone) return NS_ERROR_FAILURE;
+      aRv = tmpNode->GetParentNode(getter_AddRefs(clone));
+      if (aRv.Failed()) {
+        return nullptr;
+      }
+
+      if (!clone) {
+        aRv.Throw(NS_ERROR_FAILURE);
+        return nullptr;
+      }
     }
 
     commonCloneAncestor = clone;
   }
 
-  *aReturn = clonedFrag;
-  NS_IF_ADDREF(*aReturn);
-
-  return NS_OK;
+  return clonedFrag.forget();
 }
 
 already_AddRefed<nsRange>
 nsRange::CloneRange() const
 {
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mOwner);
 
   range->SetMaySpanAnonymousSubtrees(mMaySpanAnonymousSubtrees);
 
   range->DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset, mRoot);
 
   return range.forget();
 }
 
@@ -2194,169 +2459,232 @@ nsRange::CloneRange(nsIDOMRange** aRetur
 {
   *aReturn = CloneRange().get();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsRange::InsertNode(nsIDOMNode* aNode)
 {
-  VALIDATE_ACCESS(aNode);
-  
-  nsresult res;
-  int32_t tStartOffset;
-  this->GetStartOffset(&tStartOffset);
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+  if (!node) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
+  }
+
+  ErrorResult rv;
+  InsertNode(*node, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsRange::InsertNode(nsINode& aNode, ErrorResult& aRv)
+{
+  if (!nsContentUtils::CanCallerAccess(&aNode)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  int32_t tStartOffset = StartOffset();
 
   nsCOMPtr<nsIDOMNode> tStartContainer;
-  res = this->GetStartContainer(getter_AddRefs(tStartContainer));
-  NS_ENSURE_SUCCESS(res, res);
+  aRv = this->GetStartContainer(getter_AddRefs(tStartContainer));
+  if (aRv.Failed()) {
+    return;
+  }
 
   // This is the node we'll be inserting before, and its parent
   nsCOMPtr<nsIDOMNode> referenceNode;
   nsCOMPtr<nsIDOMNode> referenceParentNode = tStartContainer;
 
   nsCOMPtr<nsIDOMText> startTextNode(do_QueryInterface(tStartContainer));
   nsCOMPtr<nsIDOMNodeList> tChildList;
   if (startTextNode) {
-    res = tStartContainer->GetParentNode(getter_AddRefs(referenceParentNode));
-    NS_ENSURE_SUCCESS(res, res);
-    NS_ENSURE_TRUE(referenceParentNode, NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
+    aRv = tStartContainer->GetParentNode(getter_AddRefs(referenceParentNode));
+    if (aRv.Failed()) {
+      return;
+    }
+
+    if (!referenceParentNode) {
+      aRv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
+      return;
+    }
 
     nsCOMPtr<nsIDOMText> secondPart;
-    res = startTextNode->SplitText(tStartOffset, getter_AddRefs(secondPart));
-    NS_ENSURE_SUCCESS(res, res);
+    aRv = startTextNode->SplitText(tStartOffset, getter_AddRefs(secondPart));
+    if (aRv.Failed()) {
+      return;
+    }
 
     referenceNode = secondPart;
   } else {
-    res = tStartContainer->GetChildNodes(getter_AddRefs(tChildList));
-    NS_ENSURE_SUCCESS(res, res);
+    aRv = tStartContainer->GetChildNodes(getter_AddRefs(tChildList));
+    if (aRv.Failed()) {
+      return;
+    }
 
     // find the insertion point in the DOM and insert the Node
-    res = tChildList->Item(tStartOffset, getter_AddRefs(referenceNode));
-    NS_ENSURE_SUCCESS(res, res);
+    aRv = tChildList->Item(tStartOffset, getter_AddRefs(referenceNode));
+    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;
 
   if (referenceNode) {
     newOffset = IndexOf(referenceNode);
   } else {
     uint32_t length;
-    res = tChildList->GetLength(&length);
-    NS_ENSURE_SUCCESS(res, res);
+    aRv = tChildList->GetLength(&length);
+    if (aRv.Failed()) {
+      return;
+    }
+
     newOffset = length;
   }
 
-  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  NS_ENSURE_STATE(node);
-  if (node->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
-    newOffset += node->GetChildCount();
+  if (aNode.NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+    newOffset += aNode.GetChildCount();
   } else {
     newOffset++;
   }
 
   // Now actually insert the node
   nsCOMPtr<nsIDOMNode> tResultNode;
-  res = referenceParentNode->InsertBefore(aNode, referenceNode, getter_AddRefs(tResultNode));
-  NS_ENSURE_SUCCESS(res, res);
+  nsCOMPtr<nsIDOMNode> node = aNode.AsDOMNode();
+  if (!node) {
+    aRv.Throw(NS_ERROR_DOM_NOT_OBJECT_ERR);
+    return;
+  }
+  aRv = referenceParentNode->InsertBefore(node, referenceNode, getter_AddRefs(tResultNode));
+  if (aRv.Failed()) {
+    return;
+  }
 
   if (Collapsed()) {
-    return SetEnd(referenceParentNode, newOffset);
+    aRv = SetEnd(referenceParentNode, newOffset);
   }
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsRange::SurroundContents(nsIDOMNode* aNewParent)
 {
-  VALIDATE_ACCESS(aNewParent);
-
-  NS_ENSURE_TRUE(mRoot, NS_ERROR_DOM_INVALID_STATE_ERR);
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNewParent);
+  if (!node) {
+    return NS_ERROR_DOM_NOT_OBJECT_ERR;
+  }
+  ErrorResult rv;
+  SurroundContents(*node, rv);
+  return rv.ErrorCode();
+}
+
+void
+nsRange::SurroundContents(nsINode& aNewParent, ErrorResult& aRv)
+{
+  if (!nsContentUtils::CanCallerAccess(&aNewParent)) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  if (!mRoot) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
   // INVALID_STATE_ERROR: Raised if the Range partially selects a non-text
   // node.
   if (mStartParent != mEndParent) {
     bool startIsText = mStartParent->IsNodeOfType(nsINode::eTEXT);
     bool endIsText = mEndParent->IsNodeOfType(nsINode::eTEXT);
     nsINode* startGrandParent = mStartParent->GetParentNode();
     nsINode* endGrandParent = mEndParent->GetParentNode();
-    NS_ENSURE_TRUE((startIsText && endIsText &&
-                    startGrandParent &&
-                    startGrandParent == endGrandParent) ||
-                   (startIsText &&
-                    startGrandParent &&
-                    startGrandParent == mEndParent) ||
-                   (endIsText &&
-                    endGrandParent &&
-                    endGrandParent == mStartParent),
-                   NS_ERROR_DOM_INVALID_STATE_ERR);
+    if (!((startIsText && endIsText &&
+           startGrandParent &&
+           startGrandParent == endGrandParent) ||
+          (startIsText &&
+           startGrandParent &&
+           startGrandParent == mEndParent) ||
+          (endIsText &&
+           endGrandParent &&
+           endGrandParent == mStartParent))) {
+      aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+      return;
+    }
   }
 
   // INVALID_NODE_TYPE_ERROR if aNewParent is something that can't be inserted
   // (Document, DocumentType, DocumentFragment)
-  uint16_t nodeType;
-  nsresult res = aNewParent->GetNodeType(&nodeType);
-  if (NS_FAILED(res)) return res;
+  uint16_t nodeType = aNewParent.NodeType();
   if (nodeType == nsIDOMNode::DOCUMENT_NODE ||
       nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
       nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
-    return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
+    return;
   }
 
   // Extract the contents within the range.
 
   nsCOMPtr<nsIDOMDocumentFragment> docFrag;
 
-  res = ExtractContents(getter_AddRefs(docFrag));
-
-  if (NS_FAILED(res)) return res;
-  if (!docFrag) return NS_ERROR_FAILURE;
+  aRv = ExtractContents(getter_AddRefs(docFrag));
+
+  if (aRv.Failed()) {
+    return;
+  }
+
+  if (!docFrag) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   // Spec says we need to remove all of aNewParent's
   // children prior to insertion.
 
-  nsCOMPtr<nsIDOMNodeList> children;
-  res = aNewParent->GetChildNodes(getter_AddRefs(children));
-
-  if (NS_FAILED(res)) return res;
-  if (!children) return NS_ERROR_FAILURE;
-
-  uint32_t numChildren = 0;
-  res = children->GetLength(&numChildren);
-  if (NS_FAILED(res)) return res;
+  nsCOMPtr<nsINodeList> children = aNewParent.ChildNodes();
+  if (!children) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  uint32_t numChildren = children->Length();
 
   nsCOMPtr<nsIDOMNode> tmpNode;
 
   while (numChildren)
   {
-    nsCOMPtr<nsIDOMNode> child;
-    res = children->Item(--numChildren, getter_AddRefs(child));
-
-    if (NS_FAILED(res)) return res;
-    if (!child) return NS_ERROR_FAILURE;
-
-    res = aNewParent->RemoveChild(child, getter_AddRefs(tmpNode));
-    if (NS_FAILED(res)) return res;
+    nsCOMPtr<nsINode> child = children->Item(--numChildren);
+    if (!child) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
+    }
+
+    aNewParent.RemoveChild(*child, aRv);
+    if (aRv.Failed()) {
+      return;
+    }
   }
 
   // Insert aNewParent at the range's start point.
 
-  res = InsertNode(aNewParent);
-  if (NS_FAILED(res)) return res;
+  InsertNode(aNewParent, aRv);
+  if (aRv.Failed()) {
+    return;
+  }
 
   // Append the content we extracted under aNewParent.
-
-  res = aNewParent->AppendChild(docFrag, getter_AddRefs(tmpNode));
-  if (NS_FAILED(res)) return res;
+  aRv = aNewParent.AsDOMNode()->AppendChild(docFrag, getter_AddRefs(tmpNode));
+  if (aRv.Failed()) {
+    return;
+  }
 
   // Select aNewParent, and its contents.
 
-  return SelectNode(aNewParent);
+  SelectNode(aNewParent, aRv);
 }
 
 NS_IMETHODIMP
 nsRange::ToString(nsAString& aReturn)
 { 
   // clear the string
   aReturn.Truncate();
   
@@ -2457,16 +2785,28 @@ nsRange::CreateContextualFragment(const 
 {
   if (mIsPositioned) {
     return nsContentUtils::CreateContextualFragment(mStartParent, aFragment,
                                                     false, aReturn);
   }
   return NS_ERROR_FAILURE;
 }
 
+already_AddRefed<dom::DocumentFragment>
+nsRange::CreateContextualFragment(const nsAString& aFragment, ErrorResult& aRv)
+{
+  if (!mIsPositioned) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  return nsContentUtils::CreateContextualFragment(mStartParent, aFragment,
+                                                  false, aRv);
+}
+
 static void ExtractRectFromOffset(nsIFrame* aFrame,
                                   const nsIFrame* aRelativeTo, 
                                   const int32_t aOffset, nsRect* aR, bool aKeepLeft)
 {
   nsPoint point;
   aFrame->GetPointFromOffset(aOffset, &point);
 
   point += aFrame->GetOffsetTo(aRelativeTo);
@@ -2589,61 +2929,64 @@ static void CollectClientRects(nsLayoutU
         nsLayoutUtils::GetContainingBlockForClientRect(frame), aCollector);
     }
   } while (!iter.IsDone());
 }
 
 NS_IMETHODIMP
 nsRange::GetBoundingClientRect(nsIDOMClientRect** aResult)
 {
-  *aResult = nullptr;
-
-  // Weak ref, since we addref it below
-  nsClientRect* rect = new nsClientRect();
-  if (!rect)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_ADDREF(*aResult = rect);
-
+  *aResult = GetBoundingClientRect().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMClientRect>
+nsRange::GetBoundingClientRect()
+{
+  nsRefPtr<nsClientRect> rect = new nsClientRect();
   if (!mStartParent)
-    return NS_OK;
+    return rect.forget();
 
   nsLayoutUtils::RectAccumulator accumulator;
-  
   CollectClientRects(&accumulator, this, mStartParent, mStartOffset, 
     mEndParent, mEndOffset);
 
   nsRect r = accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect : 
     accumulator.mResultRect;
   rect->SetLayoutRect(r);
-  return NS_OK;
+  return rect.forget();
 }
 
 NS_IMETHODIMP
 nsRange::GetClientRects(nsIDOMClientRectList** aResult)
 {
-  *aResult = nullptr;
-
+  ErrorResult rv;
+  *aResult = GetClientRects(rv).get();
+  return rv.ErrorCode();
+}
+
+already_AddRefed<nsClientRectList>
+nsRange::GetClientRects(ErrorResult& rv)
+{
   if (!mStartParent)
-    return NS_OK;
+    return nullptr;
 
   nsRefPtr<nsClientRectList> rectList =
     new nsClientRectList(static_cast<nsIDOMRange*>(this));
-  if (!rectList)
-    return NS_ERROR_OUT_OF_MEMORY;
 
   nsLayoutUtils::RectListBuilder builder(rectList);
 
   CollectClientRects(&builder, this, mStartParent, mStartOffset, 
     mEndParent, mEndOffset);
 
-  if (NS_FAILED(builder.mRV))
-    return builder.mRV;
-  rectList.forget(aResult);
-  return NS_OK;
+  if (NS_FAILED(builder.mRV)) {
+    rv.Throw(builder.mRV);
+    return nullptr;
+  }
+  return rectList.forget();
 }
 
 NS_IMETHODIMP
 nsRange::GetUsedFontFaces(nsIDOMFontFaceList** aResult)
 {
   *aResult = nullptr;
 
   NS_ENSURE_TRUE(mStartParent, NS_ERROR_UNEXPECTED);
--- a/content/base/src/nsRange.h
+++ b/content/base/src/nsRange.h
@@ -7,52 +7,71 @@
  * Implementation of the DOM nsIDOMRange object.
  */
 
 #ifndef nsRange_h___
 #define nsRange_h___
 
 #include "nsIDOMRange.h"
 #include "nsCOMPtr.h"
-#include "nsIDOMDocumentFragment.h"
 #include "nsINode.h"
+#include "nsIDocument.h"
 #include "nsIDOMNode.h"
 #include "prmon.h"
 #include "nsStubMutationObserver.h"
+#include "nsWrapperCache.h"
+#include "mozilla/Attributes.h"
 
-class nsRange : public nsIDOMRange,
-                public nsStubMutationObserver
+class nsClientRectList;
+class nsIDOMDocumentFragment;
+
+namespace mozilla {
+class ErrorResult;
+namespace dom {
+class DocumentFragment;
+}
+}
+
+class nsRange MOZ_FINAL : public nsIDOMRange,
+                          public nsStubMutationObserver,
+                          public nsWrapperCache
 {
+  typedef mozilla::ErrorResult ErrorResult;
+
 public:
-  nsRange()
+  nsRange(nsINode* aNode)
     : mRoot(nullptr)
     , mStartOffset(0)
     , mEndOffset(0)
     , mIsPositioned(false)
     , mIsDetached(false)
     , mMaySpanAnonymousSubtrees(false)
     , mInSelection(false)
     , mStartOffsetWasIncremented(false)
     , mEndOffsetWasIncremented(false)
 #ifdef DEBUG
     , mAssertNextInsertOrAppendIndex(-1)
     , mAssertNextInsertOrAppendNode(nullptr)
 #endif
-  {}
+  {
+    SetIsDOMBinding();
+    MOZ_ASSERT(aNode, "range isn't in a document!");
+    mOwner = aNode->OwnerDoc();
+  }
   virtual ~nsRange();
 
   static nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
                               nsIDOMNode* aEndParent, int32_t aEndOffset,
                               nsRange** aRange);
   static nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
                               nsIDOMNode* aEndParent, int32_t aEndOffset,
                               nsIDOMRange** aRange);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
 
   // nsIDOMRange interface
   NS_DECL_NSIDOMRANGE
   
   nsINode* GetRoot() const
   {
     return mRoot;
   }
@@ -77,22 +96,16 @@ public:
     return mEndOffset;
   }
   
   bool IsPositioned() const
   {
     return mIsPositioned;
   }
 
-  bool Collapsed() const
-  {
-    return mIsPositioned && mStartParent == mEndParent &&
-           mStartOffset == mEndOffset;
-  }
-
   void SetMaySpanAnonymousSubtrees(bool aMaySpanAnonymousSubtrees)
   {
     mMaySpanAnonymousSubtrees = aMaySpanAnonymousSubtrees;
   }
   
   /**
    * Return true iff this range is part of at least one Selection object
    * and isn't detached.
@@ -141,28 +154,67 @@ public:
 
   // nsIMutationObserver methods
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
   NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
 
+  // WebIDL
+  bool Collapsed() const
+  {
+    return mIsPositioned && mStartParent == mEndParent &&
+           mStartOffset == mEndOffset;
+  }
+  already_AddRefed<mozilla::dom::DocumentFragment>
+  CreateContextualFragment(const nsAString& aString, ErrorResult& aError);
+  already_AddRefed<mozilla::dom::DocumentFragment>
+  CloneContents(ErrorResult& aErr);
+  int16_t CompareBoundaryPoints(uint16_t aHow, nsRange& aOther,
+                                ErrorResult& aErr);
+  int16_t ComparePoint(nsINode& aParent, uint32_t aOffset, ErrorResult& aErr);
+  void DeleteContents(ErrorResult& aRv);
+  already_AddRefed<mozilla::dom::DocumentFragment>
+    ExtractContents(ErrorResult& aErr);
+  nsINode* GetCommonAncestorContainer(ErrorResult& aRv) const;
+  nsINode* GetStartContainer(ErrorResult& aRv) const;
+  uint32_t GetStartOffset(ErrorResult& aRv) const;
+  nsINode* GetEndContainer(ErrorResult& aRv) const;
+  uint32_t GetEndOffset(ErrorResult& aRv) const;
+  void InsertNode(nsINode& aNode, ErrorResult& aErr);
+  bool IntersectsNode(nsINode& aNode, ErrorResult& aRv);
+  bool IsPointInRange(nsINode& aParent, uint32_t aOffset, ErrorResult& aErr);
+  void SelectNode(nsINode& aNode, ErrorResult& aErr);
+  void SelectNodeContents(nsINode& aNode, ErrorResult& aErr);
+  void SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
+  void SetEndAfter(nsINode& aNode, ErrorResult& aErr);
+  void SetEndBefore(nsINode& aNode, ErrorResult& aErr);
+  void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
+  void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
+  void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
+  void SurroundContents(nsINode& aNode, ErrorResult& aErr);
+  already_AddRefed<nsIDOMClientRect> GetBoundingClientRect();
+  already_AddRefed<nsClientRectList> GetClientRects(ErrorResult& aErr);
+
+  nsINode* GetParentObject() const { return mOwner; }
+  virtual JSObject* WrapObject(JSContext* cx, JSObject* scope) MOZ_OVERRIDE MOZ_FINAL;
+
 private:
   // no copy's or assigns
   nsRange(const nsRange&);
   nsRange& operator=(const nsRange&);
 
   /**
    * Cut or delete the range's contents.
    *
    * @param aFragment nsIDOMDocumentFragment containing the nodes.
    *                  May be null to indicate the caller doesn't want a fragment.
    */
-  nsresult CutContents(nsIDOMDocumentFragment** frag);
+  nsresult CutContents(mozilla::dom::DocumentFragment** frag);
 
   static nsresult CloneParentsBetween(nsIDOMNode *aAncestor,
                                       nsIDOMNode *aNode,
                                       nsIDOMNode **aClosestAncestor,
                                       nsIDOMNode **aFarthestAncestor);
 
 public:
 /******************************************************************************
@@ -219,17 +271,18 @@ protected:
     ~AutoInvalidateSelection();
     nsRange* mRange;
     nsRefPtr<nsINode> mCommonAncestor;
 #ifdef DEBUG
     bool mWasInSelection;
 #endif
     static bool mIsNested;
   };
-  
+
+  nsCOMPtr<nsIDocument> mOwner;
   nsCOMPtr<nsINode> mRoot;
   nsCOMPtr<nsINode> mStartParent;
   nsCOMPtr<nsINode> mEndParent;
   int32_t mStartOffset;
   int32_t mEndOffset;
 
   bool mIsPositioned;
   bool mIsDetached;
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -510,17 +510,17 @@ nsContentEventHandler::OnQueryTextConten
 {
   nsresult rv = Init(aEvent);
   if (NS_FAILED(rv))
     return rv;
 
   NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
                "The reply string must be empty");
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mRootContent);
   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
                                   aEvent->mInput.mLength, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aEvent->mSucceeded = true;
@@ -567,17 +567,17 @@ static nsresult GetFrameForTextRect(nsIN
 
 nsresult
 nsContentEventHandler::OnQueryTextRect(nsQueryContentEvent* aEvent)
 {
   nsresult rv = Init(aEvent);
   if (NS_FAILED(rv))
     return rv;
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mRootContent);
   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
                                   aEvent->mInput.mLength, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // used to iterate over all contents and their frames
   nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
   iter->Init(range);
 
@@ -711,17 +711,17 @@ nsContentEventHandler::OnQueryCaretRect(
       aEvent->mReply.mRect =
         rect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel());
       aEvent->mSucceeded = true;
       return NS_OK;
     }
   }
 
   // Otherwise, we should set the guessed caret rect.
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mRootContent);
   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   int32_t offsetInFrame;
   nsIFrame* frame;
   rv = GetStartFrameAndOffset(range, &frame, &offsetInFrame);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -894,19 +894,20 @@ nsContentEventHandler::OnQueryDOMWidgetH
 }
 
 nsresult
 nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
                                                 nsINode* aNode,
                                                 int32_t aNodeOffset,
                                                 uint32_t* aNativeOffset)
 {
+  NS_ENSURE_STATE(aRootContent);
   NS_ASSERTION(aNativeOffset, "param is invalid");
 
-  nsRefPtr<nsRange> prev = new nsRange();
+  nsRefPtr<nsRange> prev = new nsRange(aRootContent);
   nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(aRootContent));
   prev->SetStart(rootDOMNode, 0);
 
   nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(aNode));
   NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
   prev->SetEnd(startDOMNode, aNodeOffset);
 
   nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
@@ -1028,17 +1029,17 @@ nsContentEventHandler::OnSelectionEvent(
   if (rv != NS_ERROR_NOT_AVAILABLE) {
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
     rv = Init(aEvent);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Get range from offset and length
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mRootContent);
   NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
   rv = SetRangeFromFlatTextOffset(range, aEvent->mOffset, aEvent->mLength,
                                   aEvent->mExpandToClusterBoundary);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsINode* startNode = range->GetStartParent();
   nsINode* endNode = range->GetEndParent();
   int32_t startOffset = range->StartOffset();
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -3156,17 +3156,17 @@ nsIContent* nsHTMLMediaElement::GetNextS
 {
   nsCOMPtr<nsIDOMNode> thisDomNode = do_QueryObject(this);
 
   mSourceLoadCandidate = nullptr;
 
   nsresult rv = NS_OK;
   if (!mSourcePointer) {
     // First time this has been run, create a selection to cover children.
-    mSourcePointer = new nsRange();
+    mSourcePointer = new nsRange(this);
 
     rv = mSourcePointer->SelectNodeContents(thisDomNode);
     if (NS_FAILED(rv)) return nullptr;
 
     rv = mSourcePointer->Collapse(true);
     if (NS_FAILED(rv)) return nullptr;
   }
 
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2600,17 +2600,17 @@ nsHTMLDocument::DeferredContentEditableC
 
       nsIDocShell *docshell = window->GetDocShell();
       if (!docshell)
         return;
 
       nsCOMPtr<nsIEditor> editor;
       docshell->GetEditor(getter_AddRefs(editor));
       if (editor) {
-        nsRefPtr<nsRange> range = new nsRange();
+        nsRefPtr<nsRange> range = new nsRange(aElement);
         rv = range->SelectNode(node);
         if (NS_FAILED(rv)) {
           // The node might be detached from the document at this point,
           // which would cause this call to fail.  In this case, we can
           // safely ignore the contenteditable count change.
           return;
         }
 
--- a/content/test/unit/test_range.js
+++ b/content/test/unit/test_range.js
@@ -358,25 +358,25 @@ function run_miscellaneous_tests() {
   if ((endOffset > startOffset) &&
       (startContainer == endContainer) &&
       (startContainer instanceof C_i.nsIDOMText)) {
     // Invalid start node
     try {
       baseRange.setStart(null, 0);
       do_throw("Should have thrown NOT_OBJECT_ERR!");
     } catch (e) {
-      do_check_eq(e.name, "NS_ERROR_DOM_NOT_OBJECT_ERR");
+      do_check_eq(e instanceof TypeError, true);
     }
 
     // Invalid start node
     try {
       baseRange.setStart({}, 0);
       do_throw("Should have thrown SecurityError!");
     } catch (e) {
-      do_check_eq(e.name, "SecurityError");
+      do_check_true(e instanceof TypeError);
     }
 
     // Invalid index
     try {
       baseRange.setStart(startContainer, -1);
       do_throw("Should have thrown IndexSizeError!");
     } catch (e) {
       do_check_eq(e.name, "IndexSizeError");
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -567,16 +567,24 @@ DOMInterfaces = {
     'nativeOwnership': 'refcounted'
 },
 
 'PropertyNodeList': {
     'headerFile': 'HTMLPropertiesCollection.h',
     'resultNotAddRefed': [ 'item' ]
 },
 
+'Range': {
+    'nativeType': 'nsRange',
+    'resultNotAddRefed': [ 'startContainer', 'endContainer', 'commonAncestorContainer' ],
+    'binaryNames': {
+        '__stringifier': 'ToString'
+    }
+},
+
 'Rect': {
     'nativeType': 'nsDOMCSSRect',
     'resultNotAddRefed': [ 'top', 'right', 'bottom', 'left' ]
 },
 
 'RGBColor': {
     'nativeOwnership': 'refcounted',
     'nativeType': 'nsDOMCSSRGBColor',
@@ -1221,17 +1229,16 @@ addExternalIface('MozXULTemplateBuilder'
 addExternalIface('MozNamedAttrMap')
 addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsISupports', nativeType='nsISupports')
 addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
 addExternalIface('OutputStream', nativeType='nsIOutputStream',
                  notflattened=True)
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
-addExternalIface('Range', nativeType='nsRange')
 addExternalIface('Selection', nativeType='nsISelection')
 addExternalIface('StyleSheet', nativeType='nsIStyleSheet')
 addExternalIface('StyleSheetList')
 addExternalIface('SVGAnimatedEnumeration', headerFile='nsIDOMSVGAnimatedEnum.h')
 addExternalIface('SVGAnimatedNumber')
 addExternalIface('SVGAnimatedString')
 addExternalIface('SVGLength')
 addExternalIface('SVGNumber')
--- a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
+++ b/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
@@ -70,55 +70,16 @@
   "Attr interface: existence and properties of interface prototype object's \"constructor\" property": true,
   "Attr interface: attribute name": true,
   "Attr interface: attribute value": true,
   "Stringification of document.querySelector(\"[id]\").attributes[0]": "debug",
   "CharacterData interface: operation remove()": true,
   "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"remove\" with the proper type (7)": true,
   "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"remove\" with the proper type (7)": true,
   "CharacterData interface: document.createComment(\"abc\") must inherit property \"remove\" with the proper type (7)": true,
-  "Range interface: existence and properties of interface object": true,
-  "Range interface: existence and properties of interface prototype object": true,
-  "Range interface: existence and properties of interface prototype object's \"constructor\" property": true,
-  "Range interface: attribute startContainer": true,
-  "Range interface: attribute startOffset": true,
-  "Range interface: attribute endContainer": true,
-  "Range interface: attribute endOffset": true,
-  "Range interface: attribute collapsed": true,
-  "Range interface: attribute commonAncestorContainer": true,
-  "Range interface: calling setStart(Node,unsigned long) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling setEnd(Node,unsigned long) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling setStartBefore(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling setStartAfter(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling setEndBefore(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling setEndAfter(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling collapse(boolean) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling selectNode(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling selectNodeContents(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling compareBoundaryPoints(unsigned short,Range) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling insertNode(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling surroundContents(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling isPointInRange(Node,unsigned long) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling comparePoint(Node,unsigned long) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling intersectsNode(Node) on document.createRange() with too few arguments must throw TypeError": true,
-  "Range interface: calling setStart(Node,unsigned long) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling setEnd(Node,unsigned long) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling setStartBefore(Node) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling setStartAfter(Node) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling setEndBefore(Node) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling setEndAfter(Node) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling collapse(boolean) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling selectNode(Node) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling selectNodeContents(Node) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling compareBoundaryPoints(unsigned short,Range) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling insertNode(Node) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling surroundContents(Node) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling isPointInRange(Node,unsigned long) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling comparePoint(Node,unsigned long) on detachedRange with too few arguments must throw TypeError": true,
-  "Range interface: calling intersectsNode(Node) on detachedRange with too few arguments must throw TypeError": true,
   "NodeFilter interface: existence and properties of interface object": true,
   "NodeFilter interface: existence and properties of interface prototype object": true,
   "NodeFilter interface: existence and properties of interface prototype object's \"constructor\" property": true,
   "NodeFilter interface: constant FILTER_ACCEPT on interface prototype object": true,
   "NodeFilter interface: constant FILTER_REJECT on interface prototype object": true,
   "NodeFilter interface: constant FILTER_SKIP on interface prototype object": true,
   "NodeFilter interface: constant SHOW_ALL on interface prototype object": true,
   "NodeFilter interface: constant SHOW_ELEMENT on interface prototype object": true,
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in
+++ b/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in
@@ -20,15 +20,14 @@ MOCHITEST_FILES := \
   test_Event-defaultPrevented.html.json \
   test_EventTarget-dispatchEvent.html.json \
   test_Node-isEqualNode.xhtml.json \
   test_NodeFilter-constants.html.json \
   test_Range-attributes.html.json \
   test_Range-commonAncestorContainer.html.json \
   test_Range-comparePoint.html.json \
   test_Range-detach.html.json \
-  test_Range-intersectsNode-binding.html.json \
   test_attributes.html.json \
   test_case.html.json \
   test_historical.html.json \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-comparePoint.html.json
+++ b/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-comparePoint.html.json
@@ -1,4 +1,3 @@
 {
-  "Range.comparePoint": true,
-  "Range.comparePoint 1": true
+  "Range.comparePoint": true
 }
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-intersectsNode-binding.html.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "Calling intersectsNode without an argument or with an invalid argument should throw a TypeError.": true
-}
--- a/dom/interfaces/core/nsIDOMDocumentFragment.idl
+++ b/dom/interfaces/core/nsIDOMDocumentFragment.idl
@@ -9,12 +9,12 @@
  * DocumentFragment is a "lightweight" or "minimal" Document object.
  * nsIDOMDocumentFragment is used in situations where the Document
  * interface can potentially be a heavyweight interface.
  *
  * For more information on this interface please see 
  * http://www.w3.org/TR/DOM-Level-2-Core/
  */
 
-[scriptable, uuid(b098fc8f-9ef4-4de8-bbd0-4a0fc712dd6e)]
+[scriptable, builtinclass, uuid(b098fc8f-9ef4-4de8-bbd0-4a0fc712dd6e)]
 interface nsIDOMDocumentFragment : nsIDOMNode
 {
 };
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -12,17 +12,16 @@
  * http://dev.w3.org/csswg/cssom/#extensions-to-the-document-interface
  * http://dev.w3.org/csswg/cssom-view/#extensions-to-the-document-interface
  *
  * http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/core/nsIDOMDocument.idl
  */
 
 interface Attr;
 interface Comment;
-interface Range;
 interface StyleSheetList;
 interface Touch;
 interface TouchList;
 interface WindowProxy;
 interface nsISupports;
 
 enum VisibilityState { "hidden", "visible" };
 
--- a/dom/webidl/Range.webidl
+++ b/dom/webidl/Range.webidl
@@ -1,52 +1,90 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
- * http://www.w3.org/TR/2012/WD-dom-20120105/
+ * http://dom.spec.whatwg.org/#range
+ * http://domparsing.spec.whatwg.org/#dom-range-createcontextualfragment
+ * http://dvcs.w3.org/hg/csswg/raw-file/tip/cssom-view/Overview.html#extensions-to-the-range-interface
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
+interface ClientRect;
+
 interface Range {
+  [Throws]
   readonly attribute Node startContainer;
+  [Throws]
   readonly attribute unsigned long startOffset;
+  [Throws]
   readonly attribute Node endContainer;
+  [Throws]
   readonly attribute unsigned long endOffset;
   readonly attribute boolean collapsed;
+  [Throws]
   readonly attribute Node commonAncestorContainer;
 
+  [Throws]
   void setStart(Node refNode, unsigned long offset);
+  [Throws]
   void setEnd(Node refNode, unsigned long offset);
+  [Throws]
   void setStartBefore(Node refNode);
+  [Throws]
   void setStartAfter(Node refNode);
+  [Throws]
   void setEndBefore(Node refNode);
+  [Throws]
   void setEndAfter(Node refNode);
   void collapse(boolean toStart);
+  [Throws]
   void selectNode(Node refNode);
+  [Throws]
   void selectNodeContents(Node refNode);
 
   const unsigned short START_TO_START = 0;
   const unsigned short START_TO_END = 1;
   const unsigned short END_TO_END = 2;
   const unsigned short END_TO_START = 3;
+  [Throws]
   short compareBoundaryPoints(unsigned short how, Range sourceRange);
-
+  [Throws]
   void deleteContents();
+  [Throws]
   DocumentFragment extractContents();
+  [Throws]
   DocumentFragment cloneContents();
+  [Throws]
   void insertNode(Node node);
+  [Throws]
   void surroundContents(Node newParent);
 
   Range cloneRange();
   void detach();
 
+  [Throws]
   boolean isPointInRange(Node node, unsigned long offset);
+  [Throws]
   short comparePoint(Node node, unsigned long offset);
 
+  [Throws]
   boolean intersectsNode(Node node);
 
   stringifier;
 };
+
+// http://domparsing.spec.whatwg.org/#dom-range-createcontextualfragment
+partial interface Range {
+  [Throws]
+  DocumentFragment createContextualFragment(DOMString fragment);
+};
+
+// http://dvcs.w3.org/hg/csswg/raw-file/tip/cssom-view/Overview.html#extensions-to-the-range-interface
+partial interface Range {
+  [Throws]
+  ClientRectList getClientRects();
+  ClientRect getBoundingClientRect();
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -128,16 +128,17 @@ webidl_files = \
   NodeList.webidl \
   PaintRequest.webidl \
   PaintRequestList.webidl \
   PannerNode.webidl \
   Performance.webidl \
   PerformanceNavigation.webidl \
   PerformanceTiming.webidl \
   ProcessingInstruction.webidl \
+  Range.webidl \
   Rect.webidl \
   RGBColor.webidl \
   RTCConfiguration.webidl \
   Screen.webidl \
   SVGAElement.webidl \
   SVGAltGlyphElement.webidl \
   SVGAngle.webidl \
   SVGAnimatedAngle.webidl \
--- a/editor/libeditor/base/IMETextTxn.cpp
+++ b/editor/libeditor/base/IMETextTxn.cpp
@@ -309,18 +309,23 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSe
                 continue;
 
              result= selCon->GetSelection(TextRangeToSelection(textRangeType),
                      getter_AddRefs(imeSel));
              NS_ASSERTION(NS_SUCCEEDED(result), "Cannot get selction");
              if(NS_FAILED(result))
                 break;
 
-             nsRefPtr<nsRange> newRange = new nsRange();
-             result = newRange->SetStart(mElement,mOffset+selectionStart);
+             nsCOMPtr<nsIContent> content = do_QueryInterface(mElement);
+             if (!content) {
+               break;
+          }
+
+             nsRefPtr<nsRange> newRange = new nsRange(content);
+             result = newRange->SetStart(content, mOffset+selectionStart);
              NS_ASSERTION(NS_SUCCEEDED(result), "Cannot SetStart");
              if(NS_FAILED(result))
                 break;
 
              result = newRange->SetEnd(mElement,mOffset+selectionEnd);
              NS_ASSERTION(NS_SUCCEEDED(result), "Cannot SetEnd");
              if(NS_FAILED(result))
                 break;
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -242,30 +242,36 @@ nsHTMLEditRules::Init(nsPlaintextEditor 
   nsAdoptingCString returnInEmptyLIKillsList =
     Preferences::GetCString(kPrefName);
 
   // only when "false", becomes FALSE.  Otherwise (including empty), TRUE.
   // XXX Why was this pref designed as a string and not bool?
   mReturnInEmptyLIKillsList = !returnInEmptyLIKillsList.EqualsLiteral("false");
 
   // make a utility range for use by the listenter
-  mUtilRange = new nsRange();
+  nsCOMPtr<nsINode> node = mHTMLEditor->GetRoot();
+  if (!node) {
+    node = mHTMLEditor->GetDocument();
+  }
+
+  NS_ENSURE_STATE(node);
+
+  mUtilRange = new nsRange(node);
    
   // set up mDocChangeRange to be whole doc
-  nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(mHTMLEditor->GetRoot());
-  if (rootElem)
-  {
-    // temporarily turn off rules sniffing
-    nsAutoLockRulesSniffing lockIt((nsTextEditRules*)this);
-    if (!mDocChangeRange)
-    {
-      mDocChangeRange = new nsRange();
-    }
-    mDocChangeRange->SelectNode(rootElem);
-    res = AdjustSpecialBreaks();
+  // temporarily turn off rules sniffing
+  nsAutoLockRulesSniffing lockIt((nsTextEditRules*)this);
+  if (!mDocChangeRange) {
+    mDocChangeRange = new nsRange(node);
+  }
+
+  if (node->IsElement()) {
+    ErrorResult rv;
+    mDocChangeRange->SelectNode(*node, rv);
+    res = AdjustSpecialBreaks(node);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   // add ourselves as a listener to edit actions
   res = mHTMLEditor->AddEditActionListener(this);
 
   return res;
 }
@@ -1435,17 +1441,19 @@ nsHTMLEditRules::WillInsertText(EditActi
     nsCOMPtr<nsISelection> selection(aSelection);
     nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
     selPriv->SetInterlinePosition(false);
     if (curNode) aSelection->Collapse(curNode, curOffset);
     // manually update the doc changed range so that AfterEdit will clean up
     // the correct portion of the document.
     if (!mDocChangeRange)
     {
-      mDocChangeRange = new nsRange();
+      nsCOMPtr<nsINode> node = do_QueryInterface(selNode);
+      NS_ENSURE_STATE(node);
+      mDocChangeRange = new nsRange(node);
     }
     res = mDocChangeRange->SetStart(selNode, selOffset);
     NS_ENSURE_SUCCESS(res, res);
     if (curNode)
       res = mDocChangeRange->SetEnd(curNode, curOffset);
     else
       res = mDocChangeRange->SetEnd(selNode, selOffset);
     NS_ENSURE_SUCCESS(res, res);
@@ -5064,17 +5072,19 @@ nsHTMLEditRules::ExpandSelectionForDelet
   {
     // find block node containing br
     nsCOMPtr<nsIDOMNode> brBlock = firstBRParent;
     if (!IsBlockNode(brBlock))
       brBlock = nsHTMLEditor::GetBlockNodeParent(brBlock);
     bool nodeBefore=false, nodeAfter=false;
     
     // create a range that represents expanded selection
-    nsRefPtr<nsRange> range = new nsRange();
+    nsCOMPtr<nsINode> node = do_QueryInterface(selStartNode);
+    NS_ENSURE_STATE(node);
+    nsRefPtr<nsRange> range = new nsRange(node);
     res = range->SetStart(selStartNode, selStartOffset);
     NS_ENSURE_SUCCESS(res, res);
     res = range->SetEnd(selEndNode, selEndOffset);
     NS_ENSURE_SUCCESS(res, res);
     
     // check if block is entirely inside range
     nsCOMPtr<nsIContent> brContentBlock = do_QueryInterface(brBlock);
     res = nsRange::CompareNodeToRange(brContentBlock, range, &nodeBefore, &nodeAfter);
@@ -6111,17 +6121,19 @@ nsHTMLEditRules::GetNodesFromPoint(DOMPo
   nsresult res;
 
   // get our point
   nsCOMPtr<nsIDOMNode> node;
   int32_t offset;
   point.GetPoint(node, offset);
   
   // use it to make a range
-  nsRefPtr<nsRange> range = new nsRange();
+  nsCOMPtr<nsINode> nativeNode = do_QueryInterface(node);
+  NS_ENSURE_STATE(nativeNode);
+  nsRefPtr<nsRange> range = new nsRange(nativeNode);
   res = range->SetStart(node, offset);
   NS_ENSURE_SUCCESS(res, res);
   /* SetStart() will also set the end for this new range
   res = range->SetEnd(node, offset);
   NS_ENSURE_SUCCESS(res, res); */
   
   // expand the range to include adjacent inlines
   res = PromoteRange(range, operation);
@@ -7291,17 +7303,19 @@ nsHTMLEditRules::PinSelectionToNewBlock(
   // get the (collapsed) selection location
   nsCOMPtr<nsIDOMNode> selNode, temp;
   int32_t selOffset;
   nsresult res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(selNode), &selOffset);
   NS_ENSURE_SUCCESS(res, res);
   temp = selNode;
   
   // use ranges and sRangeHelper to compare sel point to new block
-  nsRefPtr<nsRange> range = new nsRange();
+  nsCOMPtr<nsINode> node = do_QueryInterface(selNode);
+  NS_ENSURE_STATE(node);
+  nsRefPtr<nsRange> range = new nsRange(node);
   res = range->SetStart(selNode, selOffset);
   NS_ENSURE_SUCCESS(res, res);
   res = range->SetEnd(selNode, selOffset);
   NS_ENSURE_SUCCESS(res, res);
   nsCOMPtr<nsIContent> block (do_QueryInterface(mNewBlock));
   NS_ENSURE_TRUE(block, NS_ERROR_NO_INTERFACE);
   bool nodeBefore, nodeAfter;
   res = nsRange::CompareNodeToRange(block, range, &nodeBefore, &nodeAfter);
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -3248,17 +3248,17 @@ nsHTMLEditor::ContentInserted(nsIDocumen
     if (IsMozEditorBogusNode(aChild)) {
       // Ignore insertion of the bogus node
       return;
     }
     mRules->DocumentModified();
 
     // Update spellcheck for only the newly-inserted node (bug 743819)
     if (mInlineSpellChecker) {
-      nsRefPtr<nsRange> range = new nsRange();
+      nsRefPtr<nsRange> range = new nsRange(aChild);
       nsresult res = range->Set(aContainer, aIndexInContainer,
                                 aContainer, aIndexInContainer + 1);
       if (NS_SUCCEEDED(res)) {
         mInlineSpellChecker->SpellCheckRange(range);
       }
     }
   }
 }
--- a/editor/libeditor/html/nsWSRunObject.cpp
+++ b/editor/libeditor/html/nsWSRunObject.cpp
@@ -1479,18 +1479,20 @@ nsWSRunObject::DeleteChars(nsIDOMNode *a
         NS_ENSURE_SUCCESS(res, res);
       }
       break;
     }
     else
     {
       if (!range)
       {
-        range = new nsRange();
-        res = range->SetStart(aStartNode, aStartOffset);
+        nsCOMPtr<nsINode> startNode = do_QueryInterface(aStartNode);
+        NS_ENSURE_STATE(startNode);
+        range = new nsRange(startNode);
+        res = range->SetStart(startNode, aStartOffset);
         NS_ENSURE_SUCCESS(res, res);
         res = range->SetEnd(aEndNode, aEndOffset);
         NS_ENSURE_SUCCESS(res, res);
       }
       bool nodeBefore, nodeAfter;
       nsCOMPtr<nsIContent> content (do_QueryInterface(node));
       res = nsRange::CompareNodeToRange(content, range, &nodeBefore, &nodeAfter);
       NS_ENSURE_SUCCESS(res, res);
--- a/editor/libeditor/html/tests/test_bug629845.html
+++ b/editor/libeditor/html/tests/test_bug629845.html
@@ -21,20 +21,22 @@ function initFrame(frame)
 
   document.getElementsByTagName('button')[0].click();
 }
 
 function command(aName)
 {
   var frame = document.getElementsByTagName('iframe')[0];
 
+  is(frame.contentDocument.designMode, "on", "design mode should be on!");
   var caught = false;
   try {
     frame.contentDocument.execCommand(aName, false, null);
   } catch (e) {
+    ok(false, "exception " + e + " was thrown");
     caught = true;
   }
 
   ok(!caught, "No exception should have been thrown.");
 
   // Stop the document load before finishing, just to be clean.
   document.getElementsByTagName('iframe')[0].contentWindow.document.close();
   SimpleTest.finish();
--- a/editor/txtsvc/src/nsFilteredContentIterator.cpp
+++ b/editor/txtsvc/src/nsFilteredContentIterator.cpp
@@ -52,23 +52,24 @@ NS_IMPL_CYCLE_COLLECTION_5(nsFilteredCon
                            mPreIterator,
                            mFilter,
                            mRange)
 
 //------------------------------------------------------------
 nsresult
 nsFilteredContentIterator::Init(nsINode* aRoot)
 {
+  NS_ENSURE_ARG_POINTER(aRoot);
   NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
   NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
   mIsOutOfRange    = false;
   mDirection       = eForward;
   mCurrentIterator = mPreIterator;
 
-  mRange = new nsRange();
+  mRange = new nsRange(aRoot);
   nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(aRoot));
   if (domNode) {
     mRange->SelectNode(domNode);
   }
 
   nsresult rv = mPreIterator->Init(mRange);
   NS_ENSURE_SUCCESS(rv, rv);
   return mIterator->Init(mRange);
--- a/editor/txtsvc/src/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/src/nsTextServicesDocument.cpp
@@ -2065,17 +2065,20 @@ nsTextServicesDocument::CreateDocumentCo
 {
   *aRange = NULL;
 
   nsCOMPtr<nsIDOMNode> node;
   nsresult rv = GetDocumentContentRootNode(getter_AddRefs(node));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsCOMPtr<nsINode> nativeNode = do_QueryInterface(node);
+  NS_ENSURE_STATE(nativeNode);
+
+  nsRefPtr<nsRange> range = new nsRange(nativeNode);
 
   rv = range->SelectNodeContents(node);
   NS_ENSURE_SUCCESS(rv, rv);
 
   range.forget(aRange);
   return NS_OK;
 }
 
--- a/embedding/components/find/src/nsFind.cpp
+++ b/embedding/components/find/src/nsFind.cpp
@@ -142,16 +142,18 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFindC
 NS_IMPL_CYCLE_COLLECTION_6(nsFindContentIterator, mOuterIterator, mInnerIterator,
                            mStartOuterContent, mEndOuterContent, mEndNode, mStartNode)
 
 
 nsresult
 nsFindContentIterator::Init(nsIDOMNode* aStartNode, int32_t aStartOffset,
                             nsIDOMNode* aEndNode, int32_t aEndOffset)
 {
+  NS_ENSURE_ARG_POINTER(aStartNode);
+  NS_ENSURE_ARG_POINTER(aEndNode);
   if (!mOuterIterator) {
     if (mFindBackward) {
       // Use post-order in the reverse case, so we get parents
       // before children in case we want to prevent descending
       // into a node.
       mOuterIterator = do_CreateInstance(kCContentIteratorCID);
     }
     else {
@@ -269,17 +271,20 @@ nsFindContentIterator::Reset()
   nsCOMPtr<nsIContent> endContent(do_QueryInterface(mEndNode));
   if (endContent) {
     mEndOuterContent = endContent->FindFirstNonChromeOnlyAccessContent();
   }
 
   // Note: OK to just set up the outer iterator here; if our range has a native
   // anonymous endpoint we'll end up setting up an inner iterator, and
   // reset the outer one in the process.
-  nsCOMPtr<nsIDOMRange> range = nsFind::CreateRange();
+  nsCOMPtr<nsINode> node = do_QueryInterface(mStartNode);
+  NS_ENSURE_TRUE_VOID(node);
+
+  nsCOMPtr<nsIDOMRange> range = nsFind::CreateRange(node);
   range->SetStart(mStartNode, mStartOffset);
   range->SetEnd(mEndNode, mEndOffset);
   mOuterIterator->Init(range);
 
   if (!mFindBackward) {
     if (mStartOuterContent != startContent) {
       // the start node was an anonymous text node
       SetupInnerIterator(mStartOuterContent);
@@ -361,20 +366,19 @@ nsFindContentIterator::SetupInnerIterato
   // don't mess with disabled input fields
   uint32_t editorFlags = 0;
   editor->GetFlags(&editorFlags);
   if (editorFlags & nsIPlaintextEditor::eEditorDisabledMask)
     return;
 
   nsCOMPtr<nsIDOMElement> rootElement;
   editor->GetRootElement(getter_AddRefs(rootElement));
-  nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElement));
 
-  nsCOMPtr<nsIDOMRange> innerRange = nsFind::CreateRange();
-  nsCOMPtr<nsIDOMRange> outerRange = nsFind::CreateRange();
+  nsCOMPtr<nsIDOMRange> innerRange = nsFind::CreateRange(aContent);
+  nsCOMPtr<nsIDOMRange> outerRange = nsFind::CreateRange(aContent);
   if (!innerRange || !outerRange) {
     return;
   }
 
   // now create the inner-iterator
   mInnerIterator = do_CreateInstance(kCPreContentIteratorCID);
 
   if (mInnerIterator) {
@@ -1136,17 +1140,17 @@ nsFind::Find(const PRUnichar *aPatText, 
       {
 #ifdef DEBUG_FIND
         printf("Found a match!\n");
 #endif
 
         // Make the range:
         nsCOMPtr<nsIDOMNode> startParent;
         nsCOMPtr<nsIDOMNode> endParent;
-        nsCOMPtr<nsIDOMRange> range = CreateRange();
+        nsCOMPtr<nsIDOMRange> range = CreateRange(tc);
         if (range)
         {
           int32_t matchStartOffset, matchEndOffset;
           // convert char index to range point:
           int32_t mao = matchAnchorOffset + (mFindBackward ? 1 : 0);
           if (mFindBackward)
           {
             startParent = do_QueryInterface(tc);
@@ -1250,14 +1254,14 @@ nsFind::Find(const PRUnichar *aPatText, 
 
   // Out of nodes, and didn't match.
   ResetAll();
   return NS_OK;
 }
 
 /* static */
 already_AddRefed<nsIDOMRange>
-nsFind::CreateRange()
+nsFind::CreateRange(nsINode* aNode)
 {
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(aNode);
   range->SetMaySpanAnonymousSubtrees(true);
   return range.forget();
 }
--- a/embedding/components/find/src/nsFind.h
+++ b/embedding/components/find/src/nsFind.h
@@ -30,17 +30,17 @@ class nsFind : public nsIFind
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIFIND
   NS_DECL_CYCLE_COLLECTION_CLASS(nsFind)
 
   nsFind();
   virtual ~nsFind();
 
-  static already_AddRefed<nsIDOMRange> CreateRange();
+  static already_AddRefed<nsIDOMRange> CreateRange(nsINode* aNode);
 
 protected:
   // Parameters set from the interface:
   //nsCOMPtr<nsIDOMRange> mRange;   // search only in this range
   bool mFindBackward;
   bool mCaseSensitive;
 
   nsCOMPtr<nsIWordBreaker> mWordBreaker;
--- a/embedding/components/find/src/nsWebBrowserFind.cpp
+++ b/embedding/components/find/src/nsWebBrowserFind.cpp
@@ -722,21 +722,21 @@ nsresult nsWebBrowserFind::SearchInFrame
     // Now make sure the content (for actual finding) and frame (for
     // selection) models are up to date.
     theDoc->FlushPendingNotifications(Flush_Frames);
 
     nsCOMPtr<nsISelection> sel;
     GetFrameSelection(aWindow, getter_AddRefs(sel));
     NS_ENSURE_ARG_POINTER(sel);
 
-    nsCOMPtr<nsIDOMRange> searchRange = nsFind::CreateRange();
+    nsCOMPtr<nsIDOMRange> searchRange = nsFind::CreateRange(theDoc);
     NS_ENSURE_ARG_POINTER(searchRange);
-    nsCOMPtr<nsIDOMRange> startPt  = nsFind::CreateRange();
+    nsCOMPtr<nsIDOMRange> startPt  = nsFind::CreateRange(theDoc);
     NS_ENSURE_ARG_POINTER(startPt);
-    nsCOMPtr<nsIDOMRange> endPt  = nsFind::CreateRange();
+    nsCOMPtr<nsIDOMRange> endPt  = nsFind::CreateRange(theDoc);
     NS_ENSURE_ARG_POINTER(endPt);
 
     nsCOMPtr<nsIDOMRange> foundRange;
 
     // If !aWrapping, search from selection to end
     if (!aWrapping)
         rv = GetSearchLimits(searchRange, startPt, endPt, domDoc, sel,
                              false);
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -127,17 +127,20 @@ mozInlineSpellStatus::InitForEditorChang
     mOp = eOpChangeDelete;
     mRange = nullptr;
     return NS_OK;
   }
 
   mOp = eOpChange;
 
   // range to check
-  mRange = new nsRange();
+  nsCOMPtr<nsINode> prevNode = do_QueryInterface(aPreviousNode);
+  NS_ENSURE_STATE(prevNode);
+
+  mRange = new nsRange(prevNode);
 
   // ...we need to put the start and end in the correct order
   int16_t cmpResult;
   rv = mAnchorRange->ComparePoint(aPreviousNode, aPreviousOffset, &cmpResult);
   NS_ENSURE_SUCCESS(rv, rv);
   if (cmpResult < 0) {
     // previous anchor node is before the current anchor
     rv = mRange->SetStart(aPreviousNode, aPreviousOffset);
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -312,20 +312,21 @@ mozInlineSpellWordUtil::GetNextWord(nsAS
 // mozInlineSpellWordUtil::MakeRange
 //
 //    Convenience function for creating a range over the current document.
 
 nsresult
 mozInlineSpellWordUtil::MakeRange(NodeOffset aBegin, NodeOffset aEnd,
                                   nsRange** aRange)
 {
+  NS_ENSURE_ARG_POINTER(aBegin.mNode);
   if (!mDOMDocument)
     return NS_ERROR_NOT_INITIALIZED;
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(aBegin.mNode);
   nsresult rv = range->Set(aBegin.mNode, aBegin.mOffset,
                            aEnd.mNode, aEnd.mOffset);
   NS_ENSURE_SUCCESS(rv, rv);
   range.forget(aRange);
 
   return NS_OK;
 }
 
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2909,17 +2909,17 @@ PresShell::GoToAnchor(const nsAString& a
 
     // Should we select the target? This action is controlled by a
     // preference: the default is to not select.
     bool selectAnchor = Preferences::GetBool("layout.selectanchor");
 
     // Even if select anchor pref is false, we must still move the
     // caret there. That way tabbing will start from the new
     // location
-    nsRefPtr<nsIDOMRange> jumpToRange = new nsRange();
+    nsRefPtr<nsIDOMRange> jumpToRange = new nsRange(mDocument);
     while (content && content->GetFirstChild()) {
       content = content->GetFirstChild();
     }
     nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
     NS_ASSERTION(node, "No nsIDOMNode for descendant of anchor");
     jumpToRange->SelectNodeContents(node);
     // Select the anchor
     nsISelection* sel = mSelection->
@@ -4811,17 +4811,17 @@ PresShell::RenderNode(nsIDOMNode* aNode,
   nsRect area;
   nsTArray<nsAutoPtr<RangePaintInfo> > rangeItems;
 
   // nothing to draw if the node isn't in a document
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   if (!node->IsInDoc())
     return nullptr;
   
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(node);
   if (NS_FAILED(range->SelectNode(aNode)))
     return nullptr;
 
   RangePaintInfo* info = CreateRangePaintInfo(range, area, false);
   if (info && !rangeItems.AppendElement(info)) {
     delete info;
     return nullptr;
   }
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -773,17 +773,17 @@ nsTextControlFrame::SetSelectionInternal
                                          nsIDOMNode *aEndNode,
                                          int32_t aEndOffset,
                                          nsITextControlFrame::SelectionDirection aDirection)
 {
   // Create a new range to represent the new selection.
   // Note that we use a new range to avoid having to do
   // isIncreasing checks to avoid possible errors.
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(mContent);
   nsresult rv = range->SetStart(aStartNode, aStartOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = range->SetEnd(aEndNode, aEndOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the selection, clear it and add the new range to it!
   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -1461,17 +1461,17 @@ nsFrameSelection::TakeFocus(nsIContent *
     bool changes = mChangesDuringBatching;
     mBatching = 1;
 
     if (aMultipleSelection) {
       // Remove existing collapsed ranges as there's no point in having 
       // non-anchor/focus collapsed ranges.
       mDomSelections[index]->RemoveCollapsedRanges();
 
-      nsRefPtr<nsRange> newRange = new nsRange();
+      nsRefPtr<nsRange> newRange = new nsRange(aNewFocus);
 
       newRange->SetStart(aNewFocus, aContentOffset);
       newRange->SetEnd(aNewFocus, aContentOffset);
       mDomSelections[index]->AddRange(newRange);
       mBatching = batching;
       mChangesDuringBatching = changes;
     }
     else
@@ -2861,17 +2861,17 @@ Selection::GetTableSelectionType(nsIDOMR
   return NS_OK;
 }
 
 nsresult
 nsFrameSelection::CreateAndAddRange(nsINode *aParentNode, int32_t aOffset)
 {
   if (!aParentNode) return NS_ERROR_NULL_POINTER;
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(aParentNode);
 
   // Set range around child at given offset
   nsresult result = range->SetStart(aParentNode, aOffset);
   if (NS_FAILED(result)) return result;
   result = range->SetEnd(aParentNode, aOffset+1);
   if (NS_FAILED(result)) return result;
   
   int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
@@ -3271,17 +3271,17 @@ Selection::SubtractRange(RangeData* aRan
   // If the existing range left overlaps the new range (aSubtract) then
   // cmp < 0, and cmp2 < 0
   // If it right overlaps the new range then cmp > 0 and cmp2 > 0
   // If it fully contains the new range, then cmp < 0 and cmp2 > 0
 
   if (cmp2 > 0) {
     // We need to add a new RangeData to the output, running from
     // the end of aSubtract to the end of range
-    nsRefPtr<nsRange> postOverlap = new nsRange();
+    nsRefPtr<nsRange> postOverlap = new nsRange(aSubtract->GetEndParent());
 
     rv =
       postOverlap->SetStart(aSubtract->GetEndParent(), aSubtract->EndOffset());
     NS_ENSURE_SUCCESS(rv, rv);
     rv =
      postOverlap->SetEnd(range->GetEndParent(), range->EndOffset());
     NS_ENSURE_SUCCESS(rv, rv);
     if (!postOverlap->Collapsed()) {
@@ -3289,17 +3289,17 @@ Selection::SubtractRange(RangeData* aRan
         return NS_ERROR_OUT_OF_MEMORY;
       (*aOutput)[0].mTextRangeStyle = aRange->mTextRangeStyle;
     }
   }
 
   if (cmp < 0) {
     // We need to add a new RangeData to the output, running from
     // the start of the range to the start of aSubtract
-    nsRefPtr<nsRange> preOverlap = new nsRange();
+    nsRefPtr<nsRange> preOverlap = new nsRange(range->GetStartParent());
 
     nsresult rv =
      preOverlap->SetStart(range->GetStartParent(), range->StartOffset());
     NS_ENSURE_SUCCESS(rv, rv);
     rv =
      preOverlap->SetEnd(aSubtract->GetStartParent(), aSubtract->StartOffset());
     NS_ENSURE_SUCCESS(rv, rv);
     
@@ -4393,17 +4393,17 @@ Selection::Collapse(nsINode* aParentNode
   nsresult result;
   // Delete all of the current ranges
   nsRefPtr<nsPresContext>  presContext = GetPresContext();
   Clear(presContext);
 
   // Turn off signal for table selection
   mFrameSelection->ClearTableCellSelection();
 
-  nsRefPtr<nsRange> range = new nsRange();
+  nsRefPtr<nsRange> range = new nsRange(aParentNode);
   result = range->SetEnd(aParentNode, aOffset);
   if (NS_FAILED(result))
     return result;
   result = range->SetStart(aParentNode, aOffset);
   if (NS_FAILED(result))
     return result;
 
 #ifdef DEBUG_SELECTION
@@ -4649,17 +4649,17 @@ Selection::Extend(nsINode* aParentNode, 
                                                   aParentNode, aOffset,
                                                   &disconnected);
   //compare anchor to new cursor
   int32_t result3 = nsContentUtils::ComparePoints(anchorNode, anchorOffset,
                                                   aParentNode, aOffset,
                                                   &disconnected);
 
   nsRefPtr<nsPresContext>  presContext = GetPresContext();
-  nsRefPtr<nsRange> difRange = new nsRange();
+  nsRefPtr<nsRange> difRange = new nsRange(aParentNode);
   if ((result1 == 0 && result3 < 0) || (result1 <= 0 && result2 < 0)){//a1,2  a,1,2
     //select from 1 to 2 unless they are collapsed
     res = range->SetEnd(aParentNode, aOffset);
     if (NS_FAILED(res))
       return res;
     dir = eDirNext;
     res = difRange->SetEnd(range->GetEndParent(), range->EndOffset());
     nsresult tmp = difRange->SetStart(focusNode, focusOffset);
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -2425,18 +2425,21 @@ CloneRangeToSelection(nsRange* aRange, n
   aRange->GetEndContainer(getter_AddRefs(endContainer));
   int32_t endOffset = aRange->EndOffset();
   NS_ENSURE_TRUE_VOID(startContainer && endContainer);
 
   nsCOMPtr<nsIDOMNode> newStart = GetEqualNodeInCloneTree(startContainer, aDoc);
   nsCOMPtr<nsIDOMNode> newEnd = GetEqualNodeInCloneTree(endContainer, aDoc);
   NS_ENSURE_TRUE_VOID(newStart && newEnd);
 
-  nsRefPtr<nsRange> range = new nsRange();
-  nsresult rv = range->SetStart(newStart, startOffset);
+  nsCOMPtr<nsINode> newStartNode = do_QueryInterface(newStart);
+  NS_ENSURE_TRUE_VOID(newStartNode);
+
+  nsRefPtr<nsRange> range = new nsRange(newStartNode);
+  nsresult rv = range->SetStart(newStartNode, startOffset);
   NS_ENSURE_SUCCESS_VOID(rv);
   rv = range->SetEnd(newEnd, endOffset);
   NS_ENSURE_SUCCESS_VOID(rv);
 
   aSelection->AddRange(range);
 }
 
 static nsresult CloneSelection(nsIDocument* aOrigDoc, nsIDocument* aDoc)
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -89,19 +89,20 @@ nsTypeAheadFind::~nsTypeAheadFind()
     prefInternal->RemoveObserver("accessibility.browsewithcaret", this);
   }
 }
 
 nsresult
 nsTypeAheadFind::Init(nsIDocShell* aDocShell)
 {
   nsCOMPtr<nsIPrefBranch> prefInternal(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  mSearchRange = new nsRange();
-  mStartPointRange = new nsRange();
-  mEndPointRange = new nsRange();
+
+  mSearchRange = nullptr;
+  mStartPointRange = nullptr;
+  mEndPointRange = nullptr;
   if (!prefInternal || !EnsureFind())
     return NS_ERROR_FAILURE;
 
   SetDocShell(aDocShell);
 
   // ----------- Listen to prefs ------------------
   nsresult rv = prefInternal->AddObserver("accessibility.browsewithcaret", this, true);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -161,22 +162,22 @@ nsTypeAheadFind::SetDocShell(nsIDocShell
 {
   mDocShell = do_GetWeakReference(aDocShell);
 
   mWebBrowserFind = do_GetInterface(aDocShell);
   NS_ENSURE_TRUE(mWebBrowserFind, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIPresShell> presShell;
   presShell = aDocShell->GetPresShell();
-  mPresShell = do_GetWeakReference(presShell);      
+  mPresShell = do_GetWeakReference(presShell);
 
   mStartFindRange = nullptr;
-  mStartPointRange = new nsRange();
-  mSearchRange = new nsRange();
-  mEndPointRange = new nsRange();
+  mStartPointRange = nullptr;
+  mSearchRange = nullptr;
+  mEndPointRange = nullptr;
 
   mFoundLink = nullptr;
   mFoundEditable = nullptr;
   mCurrentWindow = nullptr;
 
   mSelectionController = nullptr;
 
   mFind = nullptr;
@@ -356,16 +357,20 @@ nsTypeAheadFind::FindItNow(nsIPresShell 
                                     selectionController.get() : nullptr,
                                     aIsFirstVisiblePreferred,  aFindPrev,
                                     getter_AddRefs(presShell),
                                     getter_AddRefs(presContext)))) {
     return NS_ERROR_FAILURE;
   }
 
   int16_t rangeCompareResult = 0;
+  if (!mStartPointRange) {
+    mStartPointRange = new nsRange(presShell->GetDocument());
+  }
+
   mStartPointRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, mSearchRange, &rangeCompareResult);
   // No need to wrap find in doc if starting at beginning
   bool hasWrapped = (rangeCompareResult < 0);
 
   if (mTypeAheadBuffer.IsEmpty() || !EnsureFind())
     return NS_ERROR_FAILURE;
 
   mFind->SetFindBackwards(aFindPrev);
@@ -616,16 +621,20 @@ nsTypeAheadFind::FindItNow(nsIPresShell 
         continue;
       }
 
       if (aFindPrev) {
         // Reverse mode: swap start and end points, so that we start
         // at end of document and go to beginning
         nsCOMPtr<nsIDOMRange> tempRange;
         mStartPointRange->CloneRange(getter_AddRefs(tempRange));
+        if (!mEndPointRange) {
+          mEndPointRange = new nsRange(presShell->GetDocument());
+        }
+
         mStartPointRange = mEndPointRange;
         mEndPointRange = tempRange;
       }
 
       continue;
     }
 
     // ------------- Failed --------------
@@ -714,16 +723,24 @@ nsTypeAheadFind::GetSearchContainers(nsI
  
   nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootContent));
 
   if (!rootNode)
     return NS_ERROR_FAILURE;
 
   uint32_t childCount = rootContent->GetChildCount();
 
+  if (!mSearchRange) {
+    mSearchRange = new nsRange(rootContent);
+  }
+
+  if (!mEndPointRange) {
+    mEndPointRange = new nsRange(rootContent);
+  }
+
   mSearchRange->SelectNodeContents(rootNode);
 
   mEndPointRange->SetEnd(rootNode, childCount);
   mEndPointRange->Collapse(false); // collapse to end
 
   // Consider current selection as null if
   // it's not in the currently focused document
   nsCOMPtr<nsIDOMRange> currentSelectionRange;
@@ -731,16 +748,20 @@ nsTypeAheadFind::GetSearchContainers(nsI
   if (aSelectionController && selectionPresShell && selectionPresShell == presShell) {
     nsCOMPtr<nsISelection> selection;
     aSelectionController->GetSelection(
       nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
     if (selection)
       selection->GetRangeAt(0, getter_AddRefs(currentSelectionRange));
   }
 
+  if (!mStartPointRange) {
+    mStartPointRange = new nsRange(doc);
+  }
+
   if (!currentSelectionRange) {
     // 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);
   }