Bug 1009675 part 2. Return WebIDL 'any' values as handles. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 11 Jun 2014 16:26:52 -0400
changeset 188244 35314cd05df3dc9f802e7ab427a442c264674cb9
parent 188243 e394ea8b5171e449a8c2266fe71ea2a617b44624
child 188245 72961f73cb4a1b17cb02fe4300ebe33055a85073
push id26949
push userkwierso@gmail.com
push dateThu, 12 Jun 2014 01:47:02 +0000
treeherdermozilla-central@9e8e3e903484 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1009675
milestone33.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 1009675 part 2. Return WebIDL 'any' values as handles. r=peterv
content/base/public/nsINode.h
content/base/src/nsDOMFileReader.cpp
content/base/src/nsDOMFileReader.h
content/base/src/nsINode.cpp
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsObjectLoadingContent.h
content/base/src/nsXMLHttpRequest.cpp
content/base/src/nsXMLHttpRequest.h
content/canvas/src/CanvasRenderingContext2D.cpp
content/canvas/src/CanvasRenderingContext2D.h
content/canvas/src/CanvasUtils.h
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextState.cpp
content/html/content/src/HTMLPropertiesCollection.cpp
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
dom/base/DOMRequest.cpp
dom/base/DOMRequest.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsHistory.cpp
dom/base/nsHistory.h
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
dom/bindings/test/TestBindingHeader.h
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/BluetoothAdapter.h
dom/bluetooth/BluetoothDevice.cpp
dom/bluetooth/BluetoothDevice.h
dom/bluetooth2/BluetoothAdapter.cpp
dom/bluetooth2/BluetoothAdapter.h
dom/bluetooth2/BluetoothDevice.cpp
dom/bluetooth2/BluetoothDevice.h
dom/camera/DOMCameraCapabilities.cpp
dom/camera/DOMCameraCapabilities.h
dom/datastore/DataStoreDB.cpp
dom/datastore/DataStoreService.cpp
dom/events/DataTransfer.cpp
dom/events/DataTransfer.h
dom/events/JSEventHandler.cpp
dom/events/MessageEvent.cpp
dom/events/MessageEvent.h
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBCursor.h
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBIndex.h
dom/indexedDB/IDBKeyRange.cpp
dom/indexedDB/IDBKeyRange.h
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBObjectStore.h
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IDBRequest.h
dom/indexedDB/ipc/IndexedDBParent.cpp
dom/promise/PromiseCallback.cpp
dom/workers/XMLHttpRequest.cpp
dom/workers/XMLHttpRequest.h
js/xpconnect/src/event_impl_gen.py
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -1612,22 +1612,24 @@ public:
     } else {
       aLocalName.SetStringBuffer(nsStringBuffer::FromString(localName),
                                  localName.Length());
     }
   }
   // HasAttributes is defined inline in Element.h.
   bool HasAttributes() const;
   nsDOMAttributeMap* GetAttributes();
-  JS::Value SetUserData(JSContext* aCx, const nsAString& aKey,
-                        JS::Handle<JS::Value> aData,
-                        nsIDOMUserDataHandler* aHandler,
-                        mozilla::ErrorResult& aError);
-  JS::Value GetUserData(JSContext* aCx, const nsAString& aKey,
-                        mozilla::ErrorResult& aError);
+  void SetUserData(JSContext* aCx, const nsAString& aKey,
+                   JS::Handle<JS::Value> aData,
+                   nsIDOMUserDataHandler* aHandler,
+                   JS::MutableHandle<JS::Value> aRetval,
+                   mozilla::ErrorResult& aError);
+  void GetUserData(JSContext* aCx, const nsAString& aKey,
+                   JS::MutableHandle<JS::Value> aRetval,
+                   mozilla::ErrorResult& aError);
 
   // Helper method to remove this node from its parent. This is not exposed
   // through WebIDL.
   // Only call this if the node has a parent node.
   nsresult RemoveFromParent()
   {
     nsINode* parent = GetParentNode();
     mozilla::ErrorResult rv;
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -141,22 +141,21 @@ nsDOMFileReader::GetInterface(const nsII
 
 NS_IMETHODIMP
 nsDOMFileReader::GetReadyState(uint16_t *aReadyState)
 {
   *aReadyState = ReadyState();
   return NS_OK;
 }
 
-JS::Value
-nsDOMFileReader::GetResult(JSContext* aCx, ErrorResult& aRv)
+void
+nsDOMFileReader::GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                           ErrorResult& aRv)
 {
-  JS::Rooted<JS::Value> result(aCx);
-  aRv = GetResult(aCx, &result);
-  return result;
+  aRv = GetResult(aCx, aResult);
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult)
 {
   JS::Rooted<JS::Value> result(aCx);
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
     if (mReadyState == nsIDOMFileReader::DONE && mResultArrayBuffer) {
--- a/content/base/src/nsDOMFileReader.h
+++ b/content/base/src/nsDOMFileReader.h
@@ -80,17 +80,18 @@ public:
     MOZ_ASSERT(aBlob);
     ReadFileContent(nullptr, aBlob, EmptyString(), FILE_AS_DATAURL, aRv);
   }
 
   using FileIOObject::Abort;
 
   // Inherited ReadyState().
 
-  JS::Value GetResult(JSContext* aCx, ErrorResult& aRv);
+  void GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                 ErrorResult& aRv);
 
   using FileIOObject::GetError;
 
   IMPL_EVENT_HANDLER(loadstart)
   using FileIOObject::GetOnprogress;
   using FileIOObject::SetOnprogress;
   IMPL_EVENT_HANDLER(load)
   using FileIOObject::GetOnabort;
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -774,70 +774,70 @@ nsINode::SetUserData(const nsAString &aK
     DeleteProperty(DOM_USER_DATA_HANDLER, key);
   }
 
   oldData.swap(*aResult);
 
   return NS_OK;
 }
 
-JS::Value
+void
 nsINode::SetUserData(JSContext* aCx, const nsAString& aKey,
                      JS::Handle<JS::Value> aData,
-                     nsIDOMUserDataHandler* aHandler, ErrorResult& aError)
+                     nsIDOMUserDataHandler* aHandler,
+                     JS::MutableHandle<JS::Value> aRetval,
+                     ErrorResult& aError)
 {
   nsCOMPtr<nsIVariant> data;
-  JS::Rooted<JS::Value> dataVal(aCx, aData);
-  aError = nsContentUtils::XPConnect()->JSValToVariant(aCx, dataVal, getter_AddRefs(data));
+  aError = nsContentUtils::XPConnect()->JSValToVariant(aCx, aData, getter_AddRefs(data));
   if (aError.Failed()) {
-    return JS::UndefinedValue();
+    return;
   }
 
   nsCOMPtr<nsIVariant> oldData;
   aError = SetUserData(aKey, data, aHandler, getter_AddRefs(oldData));
   if (aError.Failed()) {
-    return JS::UndefinedValue();
+    return;
   }
 
   if (!oldData) {
-    return JS::NullValue();
+    aRetval.setNull();
+    return;
   }
 
-  JS::Rooted<JS::Value> result(aCx);
   JSAutoCompartment ac(aCx, GetWrapper());
   aError = nsContentUtils::XPConnect()->VariantToJS(aCx, GetWrapper(), oldData,
-                                                    &result);
-  return result;
+                                                    aRetval);
 }
 
 nsIVariant*
 nsINode::GetUserData(const nsAString& aKey)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eGetSetUserData);
   nsCOMPtr<nsIAtom> key = do_GetAtom(aKey);
   if (!key) {
     return nullptr;
   }
 
   return static_cast<nsIVariant*>(GetProperty(DOM_USER_DATA, key));
 }
 
-JS::Value
-nsINode::GetUserData(JSContext* aCx, const nsAString& aKey, ErrorResult& aError)
+void
+nsINode::GetUserData(JSContext* aCx, const nsAString& aKey,
+                     JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError)
 {
   nsIVariant* data = GetUserData(aKey);
   if (!data) {
-    return JS::NullValue();
+    aRetval.setNull();
+    return;
   }
 
-  JS::Rooted<JS::Value> result(aCx);
   JSAutoCompartment ac(aCx, GetWrapper());
   aError = nsContentUtils::XPConnect()->VariantToJS(aCx, GetWrapper(), data,
-                                                    &result);
-  return result;
+                                                    aRetval);
 }
 
 uint16_t
 nsINode::CompareDocumentPosition(nsINode& aOtherNode) const
 {
   if (this == &aOtherNode) {
     return 0;
   }
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -3199,99 +3199,98 @@ nsObjectLoadingContent::GetContentDocume
   // Return null for cross-origin contentDocument.
   if (!nsContentUtils::SubjectPrincipal()->SubsumesConsideringDomain(sub_doc->NodePrincipal())) {
     return nullptr;
   }
 
   return sub_doc;
 }
 
-JS::Value
+void
 nsObjectLoadingContent::LegacyCall(JSContext* aCx,
                                    JS::Handle<JS::Value> aThisVal,
                                    const Sequence<JS::Value>& aArguments,
+                                   JS::MutableHandle<JS::Value> aRetval,
                                    ErrorResult& aRv)
 {
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   JS::Rooted<JSObject*> obj(aCx, thisContent->GetWrapper());
   MOZ_ASSERT(obj, "How did we get called?");
 
   // Make sure we're not dealing with an Xray.  Our DoCall code can't handle
   // random cross-compartment wrappers, so we're going to have to wrap
   // everything up into our compartment, but that means we need to check that
   // this is not an Xray situation by hand.
   if (!JS_WrapObject(aCx, &obj)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
-    return JS::UndefinedValue();
+    return;
   }
 
   if (nsDOMClassInfo::ObjectIsNativeWrapper(aCx, obj)) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
-    return JS::UndefinedValue();
+    return;
   }
 
   obj = thisContent->GetWrapper();
   // Now wrap things up into the compartment of "obj"
   JSAutoCompartment ac(aCx, obj);
   JS::AutoValueVector args(aCx);
   if (!args.append(aArguments.Elements(), aArguments.Length())) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-    return JS::UndefinedValue();
+    return;
   }
 
   for (size_t i = 0; i < args.length(); i++) {
     if (!JS_WrapValue(aCx, args[i])) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
-      return JS::UndefinedValue();
+      return;
     }
   }
 
   JS::Rooted<JS::Value> thisVal(aCx, aThisVal);
   if (!JS_WrapValue(aCx, &thisVal)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
-    return JS::UndefinedValue();
+    return;
   }
 
   nsRefPtr<nsNPAPIPluginInstance> pi;
   nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
-    return JS::UndefinedValue();
+    return;
   }
 
   // if there's no plugin around for this object, throw.
   if (!pi) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
-    return JS::UndefinedValue();
+    return;
   }
 
   JS::Rooted<JSObject*> pi_obj(aCx);
   JS::Rooted<JSObject*> pi_proto(aCx);
 
   rv = GetPluginJSObject(aCx, obj, pi, &pi_obj, &pi_proto);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
-    return JS::UndefinedValue();
+    return;
   }
 
   if (!pi_obj) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
-    return JS::UndefinedValue();
+    return;
   }
 
-  JS::Rooted<JS::Value> retval(aCx);
-  bool ok = JS::Call(aCx, thisVal, pi_obj, args, &retval);
+  bool ok = JS::Call(aCx, thisVal, pi_obj, args, aRetval);
   if (!ok) {
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::UndefinedValue();
+    return;
   }
 
   Telemetry::Accumulate(Telemetry::PLUGIN_CALLED_DIRECTLY, true);
-  return retval;
 }
 
 void
 nsObjectLoadingContent::SetupProtoChain(JSContext* aCx,
                                         JS::Handle<JSObject*> aObject)
 {
   MOZ_ASSERT(nsCOMPtr<nsIContent>(do_QueryInterface(
     static_cast<nsIObjectLoadingContent*>(this)))->IsDOMBinding());
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -209,19 +209,20 @@ class nsObjectLoadingContent : public ns
     void CancelPlayPreview(mozilla::ErrorResult& aRv)
     {
       aRv = CancelPlayPreview();
     }
     void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aRv)
     {
       aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
     }
-    JS::Value LegacyCall(JSContext* aCx, JS::Handle<JS::Value> aThisVal,
-                         const mozilla::dom::Sequence<JS::Value>& aArguments,
-                         mozilla::ErrorResult& aRv);
+    void LegacyCall(JSContext* aCx, JS::Handle<JS::Value> aThisVal,
+                    const mozilla::dom::Sequence<JS::Value>& aArguments,
+                    JS::MutableHandle<JS::Value> aRetval,
+                    mozilla::ErrorResult& aRv);
 
   protected:
     /**
      * Begins loading the object when called
      *
      * Attributes of |this| QI'd to nsIContent will be inspected, depending on
      * the node type. This function currently assumes it is a <applet>,
      * <object>, or <embed> tag.
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -931,118 +931,125 @@ nsXMLHttpRequest::SetResponseType(nsXMLH
 
 }
 
 /* readonly attribute jsval response; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetResponse(JSContext *aCx, JS::MutableHandle<JS::Value> aResult)
 {
   ErrorResult rv;
-  aResult.set(GetResponse(aCx, rv));
+  GetResponse(aCx, aResult, rv);
   return rv.ErrorCode();
 }
 
-JS::Value
-nsXMLHttpRequest::GetResponse(JSContext* aCx, ErrorResult& aRv)
+void
+nsXMLHttpRequest::GetResponse(JSContext* aCx,
+                              JS::MutableHandle<JS::Value> aResponse,
+                              ErrorResult& aRv)
 {
   switch (mResponseType) {
   case XML_HTTP_RESPONSE_TYPE_DEFAULT:
   case XML_HTTP_RESPONSE_TYPE_TEXT:
   case XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT:
   {
     nsString str;
     aRv = GetResponseText(str);
     if (aRv.Failed()) {
-      return JSVAL_NULL;
+      return;
     }
-    JS::Rooted<JS::Value> result(aCx);
-    if (!xpc::StringToJsval(aCx, str, &result)) {
+    if (!xpc::StringToJsval(aCx, str, aResponse)) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-      return JSVAL_NULL;
     }
-    return result;
+    return;
   }
 
   case XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER:
   case XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER:
   {
     if (!(mResponseType == XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER &&
           mState & XML_HTTP_REQUEST_DONE) &&
         !(mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER &&
           mInLoadProgressEvent)) {
-      return JSVAL_NULL;
+      aResponse.setNull();
+      return;
     }
 
     if (!mResultArrayBuffer) {
       RootJSResultObjects();
 
       mResultArrayBuffer = mArrayBufferBuilder.getArrayBuffer(aCx);
       if (!mResultArrayBuffer) {
         aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-        return JSVAL_NULL;
+        return;
       }
     }
-    return OBJECT_TO_JSVAL(mResultArrayBuffer);
+    JS::ExposeObjectToActiveJS(mResultArrayBuffer);
+    aResponse.setObject(*mResultArrayBuffer);
+    return;
   }
   case XML_HTTP_RESPONSE_TYPE_BLOB:
   case XML_HTTP_RESPONSE_TYPE_MOZ_BLOB:
   {
     if (!(mState & XML_HTTP_REQUEST_DONE)) {
       if (mResponseType != XML_HTTP_RESPONSE_TYPE_MOZ_BLOB) {
-        return JSVAL_NULL;
+        aResponse.setNull();
+        return;
       }
 
       if (!mResponseBlob) {
         CreatePartialBlob();
       }
     }
 
     if (!mResponseBlob) {
-      return JSVAL_NULL;
+      aResponse.setNull();
+      return;
     }
 
-    JS::Rooted<JS::Value> result(aCx);
-    aRv = nsContentUtils::WrapNative(aCx, mResponseBlob, &result);
-    return result;
+    aRv = nsContentUtils::WrapNative(aCx, mResponseBlob, aResponse);
+    return;
   }
   case XML_HTTP_RESPONSE_TYPE_DOCUMENT:
   {
     if (!(mState & XML_HTTP_REQUEST_DONE) || !mResponseXML) {
-      return JSVAL_NULL;
+      aResponse.setNull();
+      return;
     }
 
-    JS::Rooted<JS::Value> result(aCx);
-    aRv = nsContentUtils::WrapNative(aCx, mResponseXML, &result);
-    return result;
+    aRv = nsContentUtils::WrapNative(aCx, mResponseXML, aResponse);
+    return;
   }
   case XML_HTTP_RESPONSE_TYPE_JSON:
   {
     if (!(mState & XML_HTTP_REQUEST_DONE)) {
-      return JSVAL_NULL;
+      aResponse.setNull();
+      return;
     }
 
-    if (mResultJSON == JSVAL_VOID) {
+    if (mResultJSON.isUndefined()) {
       aRv = CreateResponseParsedJSON(aCx);
       mResponseText.Truncate();
       if (aRv.Failed()) {
         // Per spec, errors aren't propagated. null is returned instead.
         aRv = NS_OK;
         // It would be nice to log the error to the console. That's hard to
         // do without calling window.onerror as a side effect, though.
         JS_ClearPendingException(aCx);
-        mResultJSON = JSVAL_NULL;
+        mResultJSON.setNull();
       }
     }
-    return mResultJSON;
+    JS::ExposeValueToActiveJS(mResultJSON);
+    aResponse.set(mResultJSON);
+    return;
   }
   default:
     NS_ERROR("Should not happen");
   }
 
-  return JSVAL_NULL;
+  aResponse.setNull();
 }
 
 bool
 nsXMLHttpRequest::IsDeniedCrossSiteRequest()
 {
   if ((mState & XML_HTTP_REQUEST_USE_XSITE_AC) && mChannel) {
     nsresult rv;
     mChannel->GetStatus(&rv);
@@ -3752,20 +3759,22 @@ nsXMLHttpRequest::GetInterface(const nsI
   else if (aIID.Equals(NS_GET_IID(nsITimerCallback))) {
     *aResult = static_cast<nsITimerCallback*>(EnsureXPCOMifier().take());
     return NS_OK;
   }
 
   return QueryInterface(aIID, aResult);
 }
 
-JS::Value
-nsXMLHttpRequest::GetInterface(JSContext* aCx, nsIJSID* aIID, ErrorResult& aRv)
+void
+nsXMLHttpRequest::GetInterface(JSContext* aCx, nsIJSID* aIID,
+                               JS::MutableHandle<JS::Value> aRetval,
+                               ErrorResult& aRv)
 {
-  return dom::GetInterface(aCx, this, aIID, aRv);
+  dom::GetInterface(aCx, this, aIID, aRetval, aRv);
 }
 
 nsXMLHttpRequestUpload*
 nsXMLHttpRequest::Upload()
 {
   if (!mUpload) {
     mUpload = new nsXMLHttpRequestUpload(this);
   }
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -489,33 +489,35 @@ public:
     // XXX Should we do some validation here?
     mOverrideMimeType = aMimeType;
   }
   XMLHttpRequestResponseType ResponseType()
   {
     return XMLHttpRequestResponseType(mResponseType);
   }
   void SetResponseType(XMLHttpRequestResponseType aType, ErrorResult& aRv);
-  JS::Value GetResponse(JSContext* aCx, ErrorResult& aRv);
+  void GetResponse(JSContext* aCx, JS::MutableHandle<JS::Value> aResponse,
+                   ErrorResult& aRv);
   void GetResponseText(nsString& aResponseText, ErrorResult& aRv);
   nsIDocument* GetResponseXML(ErrorResult& aRv);
 
   bool MozBackgroundRequest();
   void SetMozBackgroundRequest(bool aMozBackgroundRequest, nsresult& aRv);
 
   bool MozAnon();
   bool MozSystem();
 
   nsIChannel* GetChannel()
   {
     return mChannel;
   }
 
   // We need a GetInterface callable from JS for chrome JS
-  JS::Value GetInterface(JSContext* aCx, nsIJSID* aIID, ErrorResult& aRv);
+  void GetInterface(JSContext* aCx, nsIJSID* aIID,
+                    JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
 
   // This creates a trusted readystatechange event, which is not cancelable and
   // doesn't bubble.
   nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
   void DispatchProgressEvent(mozilla::DOMEventTargetHelper* aTarget,
                              const nsAString& aType,
                              bool aLengthComputable,
                              uint64_t aLoaded, uint64_t aTotal);
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -3106,20 +3106,22 @@ CanvasRenderingContext2D::SetMozDash(JSC
     ContextState& state = CurrentState();
     state.dash = dash;
     if (state.dash.IsEmpty()) {
       state.dashOffset = 0;
     }
   }
 }
 
-JS::Value
-CanvasRenderingContext2D::GetMozDash(JSContext* cx, ErrorResult& error)
+void
+CanvasRenderingContext2D::GetMozDash(JSContext* cx,
+                                     JS::MutableHandle<JS::Value> retval,
+                                     ErrorResult& error)
 {
-  return DashArrayToJSVal(CurrentState().dash, cx, error);
+  DashArrayToJSVal(CurrentState().dash, cx, retval, error);
 }
 
 void
 CanvasRenderingContext2D::SetMozDashOffset(double mozDashOffset)
 {
   ContextState& state = CurrentState();
   if (!state.dash.IsEmpty()) {
     state.dashOffset = mozDashOffset;
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -395,17 +395,18 @@ public:
                               mozilla::ErrorResult& error);
   JSObject* GetMozCurrentTransformInverse(JSContext* cx,
                                           mozilla::ErrorResult& error) const;
   void SetMozCurrentTransformInverse(JSContext* cx,
                                      JS::Handle<JSObject*> currentTransform,
                                      mozilla::ErrorResult& error);
   void GetFillRule(nsAString& fillRule);
   void SetFillRule(const nsAString& fillRule);
-  JS::Value GetMozDash(JSContext* cx, mozilla::ErrorResult& error);
+  void GetMozDash(JSContext* cx, JS::MutableHandle<JS::Value> retval,
+		  mozilla::ErrorResult& error);
   void SetMozDash(JSContext* cx, const JS::Value& mozDash,
                   mozilla::ErrorResult& error);
 
   void SetLineDash(const Sequence<double>& mSegments);
   void GetLineDash(nsTArray<double>& mSegments) const;
 
   void SetLineDashOffset(double mOffset);
   double LineDashOffset() const;
--- a/content/canvas/src/CanvasUtils.h
+++ b/content/canvas/src/CanvasUtils.h
@@ -146,26 +146,28 @@ JSValToDashArray(JSContext* cx, const JS
         // random garbage is a type error.
         return NS_ERROR_INVALID_ARG;
     }
 
     return NS_OK;
 }
 
 template<typename T>
-JS::Value
+void
 DashArrayToJSVal(FallibleTArray<T>& dashes,
-                 JSContext* cx, mozilla::ErrorResult& rv)
+                 JSContext* cx,
+                 JS::MutableHandle<JS::Value> retval,
+                 mozilla::ErrorResult& rv)
 {
     if (dashes.IsEmpty()) {
-        return JS::NullValue();
+        retval.setNull();
+        return;
     }
     JS::Rooted<JS::Value> val(cx);
-    if (!mozilla::dom::ToJSValue(cx, dashes, &val)) {
+    if (!mozilla::dom::ToJSValue(cx, dashes, retval)) {
         rv.Throw(NS_ERROR_OUT_OF_MEMORY);
     }
-    return val;
 }
 
 }
 }
 
 #endif /* _CANVASUTILS_H_ */
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -352,56 +352,75 @@ public:
     already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram *prog,
                                                       GLuint index);
     already_AddRefed<WebGLActiveInfo> GetActiveUniform(WebGLProgram *prog,
                                                        GLuint index);
     void GetAttachedShaders(WebGLProgram* prog,
                             dom::Nullable< nsTArray<WebGLShader*> > &retval);
     GLint GetAttribLocation(WebGLProgram* prog, const nsAString& name);
     JS::Value GetBufferParameter(GLenum target, GLenum pname);
-    JS::Value GetBufferParameter(JSContext* /* unused */, GLenum target,
-                                 GLenum pname) {
-        return GetBufferParameter(target, pname);
+    void GetBufferParameter(JSContext* /* unused */, GLenum target,
+                            GLenum pname,
+                            JS::MutableHandle<JS::Value> retval) {
+        retval.set(GetBufferParameter(target, pname));
     }
     GLenum GetError();
     JS::Value GetFramebufferAttachmentParameter(JSContext* cx,
                                                 GLenum target,
                                                 GLenum attachment,
                                                 GLenum pname,
                                                 ErrorResult& rv);
+    void GetFramebufferAttachmentParameter(JSContext* cx,
+                                           GLenum target,
+                                           GLenum attachment,
+                                           GLenum pname,
+                                           JS::MutableHandle<JS::Value> retval,
+                                           ErrorResult& rv) {
+        retval.set(GetFramebufferAttachmentParameter(cx, target, attachment,
+                                                     pname, rv));
+    }
     JS::Value GetProgramParameter(WebGLProgram *prog, GLenum pname);
-    JS::Value GetProgramParameter(JSContext* /* unused */, WebGLProgram *prog,
-                                  GLenum pname) {
-        return GetProgramParameter(prog, pname);
+    void  GetProgramParameter(JSContext* /* unused */, WebGLProgram *prog,
+                              GLenum pname,
+                              JS::MutableHandle<JS::Value> retval) {
+        retval.set(GetProgramParameter(prog, pname));
     }
     void GetProgramInfoLog(WebGLProgram *prog, nsACString& retval);
     void GetProgramInfoLog(WebGLProgram *prog, nsAString& retval);
     JS::Value GetRenderbufferParameter(GLenum target, GLenum pname);
-    JS::Value GetRenderbufferParameter(JSContext* /* unused */,
-                                       GLenum target, GLenum pname) {
-        return GetRenderbufferParameter(target, pname);
+    void GetRenderbufferParameter(JSContext* /* unused */,
+                                  GLenum target, GLenum pname,
+                                  JS::MutableHandle<JS::Value> retval) {
+        retval.set(GetRenderbufferParameter(target, pname));
     }
     JS::Value GetShaderParameter(WebGLShader *shader, GLenum pname);
-    JS::Value GetShaderParameter(JSContext* /* unused */, WebGLShader *shader,
-                                 GLenum pname) {
-        return GetShaderParameter(shader, pname);
+    void GetShaderParameter(JSContext* /* unused */, WebGLShader *shader,
+                            GLenum pname,
+                            JS::MutableHandle<JS::Value> retval) {
+        retval.set(GetShaderParameter(shader, pname));
     }
     already_AddRefed<WebGLShaderPrecisionFormat>
       GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
     void GetShaderInfoLog(WebGLShader *shader, nsACString& retval);
     void GetShaderInfoLog(WebGLShader *shader, nsAString& retval);
     void GetShaderSource(WebGLShader *shader, nsAString& retval);
     void GetShaderTranslatedSource(WebGLShader *shader, nsAString& retval);
     JS::Value GetTexParameter(GLenum target, GLenum pname);
-    JS::Value GetTexParameter(JSContext * /* unused */, GLenum target,
-                              GLenum pname) {
-        return GetTexParameter(target, pname);
+    void GetTexParameter(JSContext * /* unused */, GLenum target,
+                         GLenum pname,
+                         JS::MutableHandle<JS::Value> retval) {
+        retval.set(GetTexParameter(target, pname));
     }
     JS::Value GetUniform(JSContext* cx, WebGLProgram *prog,
                          WebGLUniformLocation *location);
+    void GetUniform(JSContext* cx, WebGLProgram *prog,
+                    WebGLUniformLocation *location,
+                    JS::MutableHandle<JS::Value> retval) {
+        retval.set(GetUniform(cx, prog, location));
+    }
     already_AddRefed<WebGLUniformLocation>
       GetUniformLocation(WebGLProgram *prog, const nsAString& name);
     void Hint(GLenum target, GLenum mode);
     bool IsFramebuffer(WebGLFramebuffer *fb);
     bool IsProgram(WebGLProgram *prog);
     bool IsRenderbuffer(WebGLRenderbuffer *rb);
     bool IsShader(WebGLShader *shader);
     bool IsTexture(WebGLTexture *tex);
@@ -686,16 +705,20 @@ public:
 public:
     already_AddRefed<WebGLQuery> CreateQuery();
     void DeleteQuery(WebGLQuery *query);
     void BeginQuery(GLenum target, WebGLQuery *query);
     void EndQuery(GLenum target);
     bool IsQuery(WebGLQuery *query);
     already_AddRefed<WebGLQuery> GetQuery(GLenum target, GLenum pname);
     JS::Value GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname);
+    void GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname,
+                        JS::MutableHandle<JS::Value> retval) {
+        retval.set(GetQueryObject(cx, query, pname));
+    }
 
 private:
     // ANY_SAMPLES_PASSED(_CONSERVATIVE) slot
     WebGLRefPtr<WebGLQuery> mActiveOcclusionQuery;
 
     // LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN slot
     WebGLRefPtr<WebGLQuery> mActiveTransformFeedbackQuery;
 
@@ -735,17 +758,22 @@ private:
     bool ValidateBufferUsageEnum(GLenum target, const char* infos);
 
 // -----------------------------------------------------------------------------
 // State and State Requests (WebGLContextState.cpp)
 public:
     void Disable(GLenum cap);
     void Enable(GLenum cap);
     JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
-    JS::Value GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index);
+    void GetParameter(JSContext* cx, GLenum pname,
+                      JS::MutableHandle<JS::Value> retval, ErrorResult& rv) {
+        retval.set(GetParameter(cx, pname, rv));
+    }
+    void GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
+                             JS::MutableHandle<JS::Value> retval);
     bool IsEnabled(GLenum cap);
 
 private:
     // State tracking slots
     realGLboolean mDitherEnabled;
     realGLboolean mRasterizerDiscardEnabled;
     realGLboolean mScissorTestEnabled;
 
@@ -761,16 +789,21 @@ public:
     void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
                                WebGLintptr byteOffset, GLsizei primcount);
 
     void EnableVertexAttribArray(GLuint index);
     void DisableVertexAttribArray(GLuint index);
 
     JS::Value GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
                               ErrorResult& rv);
+    void GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
+                         JS::MutableHandle<JS::Value> retval,
+                         ErrorResult& rv) {
+        retval.set(GetVertexAttrib(cx, index, pname, rv));
+    }
     WebGLsizeiptr GetVertexAttribOffset(GLuint index, GLenum pname);
 
     void VertexAttrib1f(GLuint index, GLfloat x0);
     void VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1);
     void VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1,
                         GLfloat x2);
     void VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1,
                         GLfloat x2, GLfloat x3);
--- a/content/canvas/src/WebGLContextState.cpp
+++ b/content/canvas/src/WebGLContextState.cpp
@@ -449,40 +449,45 @@ WebGLContext::GetParameter(JSContext* cx
         default:
             break;
     }
 
     ErrorInvalidEnumInfo("getParameter: parameter", pname);
     return JS::NullValue();
 }
 
-JS::Value
-WebGLContext::GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index)
+void
+WebGLContext::GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
+                                  JS::MutableHandle<JS::Value> retval)
 {
-    if (IsContextLost())
-        return JS::NullValue();
+    if (IsContextLost()) {
+        retval.setNull();
+        return;
+    }
 
     MakeContextCurrent();
 
     switch (pname) {
         case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
         {
             if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
                 ErrorInvalidValue("getParameterIndexed: index should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", index);
-                return JS::NullValue();
+                retval.setNull();
+                return;
             }
-            return JS::NullValue(); // See bug 903594
+            retval.setNull(); // See bug 903594
+            return;
         }
 
         default:
             break;
     }
 
     ErrorInvalidEnumInfo("getParameterIndexed: parameter", pname);
-    return JS::NullValue();
+    retval.setNull();
 }
 
 bool
 WebGLContext::IsEnabled(GLenum cap)
 {
     if (IsContextLost())
         return false;
 
--- a/content/html/content/src/HTMLPropertiesCollection.cpp
+++ b/content/html/content/src/HTMLPropertiesCollection.cpp
@@ -421,17 +421,18 @@ PropertyNodeList::GetValues(JSContext* a
                             ErrorResult& aError)
 {
   EnsureFresh();
 
   JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
   JSAutoCompartment ac(aCx, wrapper);
   uint32_t length = mElements.Length();
   for (uint32_t i = 0; i < length; ++i) {
-    JS::Value v = mElements.ElementAt(i)->GetItemValue(aCx, wrapper, aError);
+    JS::Rooted<JS::Value> v(aCx);
+    mElements.ElementAt(i)->GetItemValue(aCx, wrapper, &v, aError);
     if (aError.Failed()) {
       return;
     }
     aResult.AppendElement(v);
   }
 }
 
 void
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -3036,43 +3036,41 @@ nsGenericHTMLFormElementWithState::Resto
 }
 
 void
 nsGenericHTMLFormElementWithState::NodeInfoChanged(nsINodeInfo* aOldNodeInfo)
 {
   mStateKey.SetIsVoid(true);
 }
 
-JS::Value
+void
 nsGenericHTMLElement::GetItemValue(JSContext* aCx, JSObject* aScope,
+                                   JS::MutableHandle<JS::Value> aRetval,
                                    ErrorResult& aError)
 {
   JS::Rooted<JSObject*> scope(aCx, aScope);
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop)) {
-    return JS::NullValue();
+    aRetval.setNull();
+    return;
   }
 
   if (ItemScope()) {
     JS::Rooted<JS::Value> v(aCx);
     JSAutoCompartment ac(aCx, scope);
-    if (!mozilla::dom::WrapObject(aCx, this, &v)) {
+    if (!mozilla::dom::WrapObject(aCx, this, aRetval)) {
       aError.Throw(NS_ERROR_FAILURE);
-      return JS::UndefinedValue();
     }
-    return v;
+    return;
   }
 
   nsString string;
   GetItemValueText(string);
-  JS::Rooted<JS::Value> v(aCx);
-  if (!xpc::NonVoidStringToJsval(aCx, string, &v)) {
+  if (!xpc::NonVoidStringToJsval(aCx, string, aRetval)) {
     aError.Throw(NS_ERROR_FAILURE);
-    return JS::UndefinedValue();
   }
-  return v;
 }
 
 NS_IMETHODIMP
 nsGenericHTMLElement::GetItemValue(nsIVariant** aValue)
 {
   nsCOMPtr<nsIWritableVariant> out = new nsVariant();
 
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop)) {
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -119,21 +119,23 @@ public:
   {
     return GetTokenList(nsGkAtoms::itemref);
   }
   nsDOMSettableTokenList* ItemProp()
   {
     return GetTokenList(nsGkAtoms::itemprop);
   }
   mozilla::dom::HTMLPropertiesCollection* Properties();
-  JS::Value GetItemValue(JSContext* aCx, JSObject* aScope,
-                         mozilla::ErrorResult& aError);
-  JS::Value GetItemValue(JSContext* aCx, mozilla::ErrorResult& aError)
+  void GetItemValue(JSContext* aCx, JSObject* aScope,
+                    JS::MutableHandle<JS::Value> aRetval,
+                    mozilla::ErrorResult& aError);
+  void GetItemValue(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
+                    mozilla::ErrorResult& aError)
   {
-    return GetItemValue(aCx, GetWrapperPreserveColor(), aError);
+    GetItemValue(aCx, GetWrapperPreserveColor(), aRetval, aError);
   }
   void SetItemValue(JSContext* aCx, JS::Value aValue,
                     mozilla::ErrorResult& aError);
   bool Hidden() const
   {
     return GetBoolAttr(nsGkAtoms::hidden);
   }
   void SetHidden(bool aHidden, mozilla::ErrorResult& aError)
--- a/dom/base/DOMRequest.cpp
+++ b/dom/base/DOMRequest.cpp
@@ -78,17 +78,17 @@ DOMRequest::GetReadyState(nsAString& aRe
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMRequest::GetResult(JS::MutableHandle<JS::Value> aResult)
 {
-  aResult.set(Result());
+  GetResult(nullptr, aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMRequest::GetError(nsISupports** aError)
 {
   NS_IF_ADDREF(*aError = GetError());
   return NS_OK;
--- a/dom/base/DOMRequest.h
+++ b/dom/base/DOMRequest.h
@@ -44,21 +44,22 @@ public:
 
   // WebIDL Interface
   DOMRequestReadyState ReadyState() const
   {
     return mDone ? DOMRequestReadyState::Done
                  : DOMRequestReadyState::Pending;
   }
 
-  JS::Value Result(JSContext* = nullptr) const
+  void GetResult(JSContext*, JS::MutableHandle<JS::Value> aRetval) const
   {
     NS_ASSERTION(mDone || mResult == JSVAL_VOID,
-               "Result should be undefined when pending");
-    return mResult;
+                 "Result should be undefined when pending");
+    JS::ExposeValueToActiveJS(mResult);
+    aRetval.set(mResult);
   }
 
   DOMError* GetError() const
   {
     NS_ASSERTION(mDone || !mError,
                  "Error should be null when pending");
     return mError;
   }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4498,35 +4498,35 @@ nsGlobalWindow::GetOpenerWindow(ErrorRes
         return opener;
       }
     }
   }
 
   return nullptr;
 }
 
-JS::Value
-nsGlobalWindow::GetOpener(JSContext* aCx, ErrorResult& aError)
+void
+nsGlobalWindow::GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
+                          ErrorResult& aError)
 {
   nsCOMPtr<nsIDOMWindow> opener = GetOpenerWindow(aError);
   if (aError.Failed() || !opener) {
-    return JS::NullValue();
-  }
-
-  JS::Rooted<JS::Value> val(aCx);
-  aError = nsContentUtils::WrapNative(aCx, opener, &val);
-  return val;
+    aRetval.setNull();
+    return;
+  }
+
+  aError = nsContentUtils::WrapNative(aCx, opener, aRetval);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetScriptableOpener(JSContext* aCx,
                                     JS::MutableHandle<JS::Value> aOpener)
 {
   ErrorResult rv;
-  aOpener.set(GetOpener(aCx, rv));
+  GetOpener(aCx, aOpener, rv);
 
   return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
 {
   ErrorResult rv;
@@ -9105,44 +9105,44 @@ nsGlobalWindow::ShowModalDialog(const ns
 
   nsCOMPtr<nsIVariant> retVal;
   aError = dialog->GetReturnValue(getter_AddRefs(retVal));
   MOZ_ASSERT(!aError.Failed());
 
   return retVal.forget();
 }
 
-JS::Value
+void
 nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
                                 JS::Handle<JS::Value> aArgument,
                                 const nsAString& aOptions,
+                                JS::MutableHandle<JS::Value> aRetval,
                                 ErrorResult& aError)
 {
   nsCOMPtr<nsIVariant> args;
   aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
                                                     aArgument,
                                                     getter_AddRefs(args));
   if (aError.Failed()) {
-    return JS::UndefinedValue();
+    return;
   }
 
   nsCOMPtr<nsIVariant> retVal = ShowModalDialog(aUrl, args, aOptions, aError);
   if (aError.Failed()) {
-    return JS::UndefinedValue();
+    return;
   }
 
   JS::Rooted<JS::Value> result(aCx);
   if (retVal) {
     aError = nsContentUtils::XPConnect()->VariantToJS(aCx,
                                                       FastGetGlobalJSObject(),
-                                                      retVal, &result);
+                                                      retVal, aRetval);
   } else {
-    result = JS::NullValue();
-  }
-  return result;
+    aRetval.setNull();
+  }
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs_,
                                 const nsAString& aOptions, uint8_t aArgc,
                                 nsIVariant **aRetVal)
 {
   // Per-spec the |arguments| parameter is supposed to pass through unmodified.
@@ -10580,20 +10580,22 @@ nsGlobalWindow::GetInterface(const nsIID
   }
   else {
     return QueryInterface(aIID, aSink);
   }
 
   return *aSink ? NS_OK : NS_ERROR_NO_INTERFACE;
 }
 
-JS::Value
-nsGlobalWindow::GetInterface(JSContext* aCx, nsIJSID* aIID, ErrorResult& aError)
-{
-  return dom::GetInterface(aCx, this, aIID, aError);
+void
+nsGlobalWindow::GetInterface(JSContext* aCx, nsIJSID* aIID,
+                             JS::MutableHandle<JS::Value> aRetval,
+                             ErrorResult& aError)
+{
+  dom::GetInterface(aCx, this, aIID, aRetval, aError);
 }
 
 void
 nsGlobalWindow::FireOfflineStatusEvent()
 {
   if (!IsCurrentInnerWindow())
     return;
   nsAutoString name;
@@ -12093,17 +12095,18 @@ nsGlobalWindow::RunTimeoutHandler(nsTime
            .setVersion(JSVERSION_DEFAULT);
     JS::Rooted<JSObject*> global(entryScript.cx(), FastGetGlobalJSObject());
     nsJSUtils::EvaluateString(entryScript.cx(), nsDependentString(script),
                               global, options);
   } else {
     // Hold strong ref to ourselves while we call the callback.
     nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow *>(this));
     ErrorResult ignored;
-    callback->Call(me, handler->GetArgs(), ignored);
+    JS::Rooted<JS::Value> ignoredVal(CycleCollectedJSRuntime::Get()->Runtime());
+    callback->Call(me, handler->GetArgs(), &ignoredVal, ignored);
   }
 
   // We ignore any failures from calling EvaluateString() on the context or
   // Call() on a Function here since we're in a loop
   // where we're likely to be running timeouts whose OS timers
   // didn't fire in time and we don't want to not fire those timers
   // now just because execution of one timer failed. We can't
   // propagate the error to anyone who cares about it from this
@@ -13618,68 +13621,71 @@ NS_INTERFACE_MAP_BEGIN(nsGlobalModalWind
   NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow)
 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
 
 NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
 NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
 
 
-JS::Value
-nsGlobalWindow::GetDialogArguments(JSContext* aCx, ErrorResult& aError)
-{
-  FORWARD_TO_OUTER_OR_THROW(GetDialogArguments, (aCx, aError), aError,
-                            JS::UndefinedValue());
+void
+nsGlobalWindow::GetDialogArguments(JSContext* aCx,
+                                   JS::MutableHandle<JS::Value> aRetval,
+                                   ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetDialogArguments, (aCx, aRetval, aError),
+                            aError, );
 
   MOZ_ASSERT(IsModalContentWindow(),
              "This should only be called on modal windows!");
 
   if (!mDialogArguments) {
     MOZ_ASSERT(mIsClosed, "This window should be closed!");
-    return JS::UndefinedValue();
+    aRetval.setUndefined();
+    return;
   }
 
   // This does an internal origin check, and returns undefined if the subject
   // does not subsumes the origin of the arguments.
   JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
   JSAutoCompartment ac(aCx, wrapper);
-  JS::Rooted<JS::Value> args(aCx);
   mDialogArguments->Get(aCx, wrapper, nsContentUtils::SubjectPrincipal(),
-                        &args, aError);
-  return args;
+                        aRetval, aError);
 }
 
 NS_IMETHODIMP
 nsGlobalModalWindow::GetDialogArguments(nsIVariant **aArguments)
 {
   FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetDialogArguments, (aArguments),
                                         NS_ERROR_NOT_INITIALIZED);
 
   // This does an internal origin check, and returns undefined if the subject
   // does not subsumes the origin of the arguments.
   return mDialogArguments->Get(nsContentUtils::SubjectPrincipal(), aArguments);
 }
 
-JS::Value
-nsGlobalWindow::GetReturnValue(JSContext* aCx, ErrorResult& aError)
-{
-  FORWARD_TO_OUTER_OR_THROW(GetReturnValue, (aCx, aError), aError,
-                            JS::UndefinedValue());
+void
+nsGlobalWindow::GetReturnValue(JSContext* aCx,
+                               JS::MutableHandle<JS::Value> aReturnValue,
+                               ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetReturnValue, (aCx, aReturnValue, aError),
+                            aError, );
 
   MOZ_ASSERT(IsModalContentWindow(),
              "This should only be called on modal windows!");
 
-  JS::Rooted<JS::Value> returnValue(aCx);
   if (mReturnValue) {
     JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
     JSAutoCompartment ac(aCx, wrapper);
     mReturnValue->Get(aCx, wrapper, nsContentUtils::SubjectPrincipal(),
-                      &returnValue, aError);
-  }
-  return returnValue;
+                      aReturnValue, aError);
+  } else {
+    aReturnValue.setUndefined();
+  }
 }
 
 NS_IMETHODIMP
 nsGlobalModalWindow::GetReturnValue(nsIVariant **aRetVal)
 {
   FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetReturnValue, (aRetVal), NS_OK);
 
   nsCOMPtr<nsIVariant> result;
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -832,17 +832,18 @@ public:
   {
     nsCOMPtr<nsIDOMWindow> top;
     aError = GetScriptableTop(getter_AddRefs(top));
     return top.forget();
   }
 protected:
   nsIDOMWindow* GetOpenerWindow(mozilla::ErrorResult& aError);
 public:
-  JS::Value GetOpener(JSContext* aCx, mozilla::ErrorResult& aError);
+  void GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
+                 mozilla::ErrorResult& aError);
   void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
                  mozilla::ErrorResult& aError);
   using nsIDOMWindow::GetParent;
   already_AddRefed<nsIDOMWindow> GetParent(mozilla::ErrorResult& aError);
   mozilla::dom::Element* GetFrameElement(mozilla::ErrorResult& aError);
   already_AddRefed<nsIDOMWindow> Open(const nsAString& aUrl,
                                       const nsAString& aName,
                                       const nsAString& aOptions,
@@ -862,17 +863,21 @@ protected:
 
 public:
   void Alert(mozilla::ErrorResult& aError);
   void Alert(const nsAString& aMessage, mozilla::ErrorResult& aError);
   bool Confirm(const nsAString& aMessage, mozilla::ErrorResult& aError);
   void Prompt(const nsAString& aMessage, const nsAString& aInitial,
               nsAString& aReturn, mozilla::ErrorResult& aError);
   void Print(mozilla::ErrorResult& aError);
-  JS::Value ShowModalDialog(JSContext* aCx, const nsAString& aUrl, JS::Handle<JS::Value> aArgument, const nsAString& aOptions, mozilla::ErrorResult& aError);
+  void ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
+                       JS::Handle<JS::Value> aArgument,
+                       const nsAString& aOptions,
+                       JS::MutableHandle<JS::Value> aRetval,
+                       mozilla::ErrorResult& aError);
   void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                       const nsAString& aTargetOrigin,
                       const mozilla::dom::Optional<mozilla::dom::Sequence<JS::Value > >& aTransfer,
                       mozilla::ErrorResult& aError);
   int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction,
                      int32_t aTimeout,
                      const mozilla::dom::Sequence<JS::Value>& aArguments,
                      mozilla::ErrorResult& aError);
@@ -1012,23 +1017,26 @@ public:
                                  mozilla::ErrorResult& aError);
   nsIMessageBroadcaster* GetMessageManager(mozilla::ErrorResult& aError);
   nsIMessageBroadcaster* GetGroupMessageManager(const nsAString& aGroup,
                                                 mozilla::ErrorResult& aError);
   void BeginWindowMove(mozilla::dom::Event& aMouseDownEvent,
                        mozilla::dom::Element* aPanel,
                        mozilla::ErrorResult& aError);
 
-  JS::Value GetDialogArguments(JSContext* aCx, mozilla::ErrorResult& aError);
-  JS::Value GetReturnValue(JSContext* aCx, mozilla::ErrorResult& aError);
+  void GetDialogArguments(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
+                          mozilla::ErrorResult& aError);
+  void GetReturnValue(JSContext* aCx, JS::MutableHandle<JS::Value> aReturnValue,
+                      mozilla::ErrorResult& aError);
   void SetReturnValue(JSContext* aCx, JS::Handle<JS::Value> aReturnValue,
                       mozilla::ErrorResult& aError);
 
-  JS::Value GetInterface(JSContext* aCx, nsIJSID* aIID,
-                         mozilla::ErrorResult& aError);
+  void GetInterface(JSContext* aCx, nsIJSID* aIID,
+                    JS::MutableHandle<JS::Value> aRetval,
+                    mozilla::ErrorResult& aError);
 
 protected:
   // Array of idle observers that are notified of idle events.
   nsTObserverArray<IdleObserverHolder> mIdleObservers;
 
   // Idle timer used for function callbacks to notify idle observers.
   nsCOMPtr<nsITimer> mIdleTimer;
 
--- a/dom/base/nsHistory.cpp
+++ b/dom/base/nsHistory.cpp
@@ -91,60 +91,56 @@ nsHistory::GetLength(ErrorResult& aRv) c
     aRv.Throw(rv);
 
     return 0;
   }
 
   return len >= 0 ? len : 0;
 }
 
-JS::Value
-nsHistory::GetState(JSContext* aCx, ErrorResult& aRv) const
+void
+nsHistory::GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                    ErrorResult& aRv) const
 {
   nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mInnerWindow));
   if (!win) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
-
-    return JS::UndefinedValue();
+    return;
   }
 
   if (!win->HasActiveDocument()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-
-    return JS::UndefinedValue();
+    return;
   }
 
   nsCOMPtr<nsIDocument> doc =
     do_QueryInterface(win->GetExtantDoc());
   if (!doc) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
-
-    return JS::UndefinedValue();
+    return;
   }
 
   nsCOMPtr<nsIVariant> variant;
   doc->GetStateObject(getter_AddRefs(variant));
 
   if (variant) {
-    JS::Rooted<JS::Value> jsData(aCx);
-    aRv = variant->GetAsJSVal(&jsData);
+    aRv = variant->GetAsJSVal(aResult);
 
     if (aRv.Failed()) {
-      return JS::UndefinedValue();
+      return;
     }
 
-    if (!JS_WrapValue(aCx, &jsData)) {
+    if (!JS_WrapValue(aCx, aResult)) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-      return JS::UndefinedValue();
     }
 
-    return jsData;
+    return;
   }
 
-  return JS::NullValue();
+  aResult.setNull();
 }
 
 void
 nsHistory::Go(int32_t aDelta, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mInnerWindow));
   if (!win || !win->HasActiveDocument()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
--- a/dom/base/nsHistory.h
+++ b/dom/base/nsHistory.h
@@ -32,17 +32,18 @@ public:
 public:
   nsHistory(nsPIDOMWindow* aInnerWindow);
   virtual ~nsHistory();
 
   nsPIDOMWindow* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   uint32_t GetLength(mozilla::ErrorResult& aRv) const;
-  JS::Value GetState(JSContext* aCx, mozilla::ErrorResult& aRv) const;
+  void GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                mozilla::ErrorResult& aRv) const;
   void Go(int32_t aDelta, mozilla::ErrorResult& aRv);
   void Back(mozilla::ErrorResult& aRv);
   void Forward(mozilla::ErrorResult& aRv);
   void PushState(JSContext* aCx, JS::Handle<JS::Value> aData,
                  const nsAString& aTitle, const nsAString& aUrl,
                  mozilla::ErrorResult& aRv);
   void ReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
                     const nsAString& aTitle, const nsAString& aUrl,
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -879,35 +879,32 @@ QueryInterface(JSContext* cx, unsigned a
   if (NS_FAILED(rv)) {
     return Throw(cx, rv);
   }
 
   *vp = thisv;
   return true;
 }
 
-JS::Value
+void
 GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
-                 nsWrapperCache* aCache, nsIJSID* aIID, ErrorResult& aError)
+                 nsWrapperCache* aCache, nsIJSID* aIID,
+                 JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError)
 {
   const nsID* iid = aIID->GetID();
 
   nsRefPtr<nsISupports> result;
   aError = aRequestor->GetInterface(*iid, getter_AddRefs(result));
   if (aError.Failed()) {
-    return JS::NullValue();
+    return;
   }
 
-  JS::Rooted<JS::Value> v(aCx, JSVAL_NULL);
-  if (!WrapObject(aCx, result, iid, &v)) {
+  if (!WrapObject(aCx, result, iid, aRetval)) {
     aError.Throw(NS_ERROR_FAILURE);
-    return JS::NullValue();
   }
-
-  return v;
 }
 
 bool
 ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
 {
   return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
 }
 
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1644,25 +1644,27 @@ WantsQueryInterface
   static_assert(IsBaseOf<nsISupports, T>::value,
                 "QueryInterface can't work without an nsISupports.");
   static bool Enabled(JSContext* aCx, JSObject* aGlobal)
   {
     return NS_IsMainThread() && IsChromeOrXBL(aCx, aGlobal);
   }
 };
 
-JS::Value
+void
 GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
-                 nsWrapperCache* aCache, nsIJSID* aIID, ErrorResult& aError);
+                 nsWrapperCache* aCache, nsIJSID* aIID,
+                 JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError);
 
 template<class T>
-JS::Value
-GetInterface(JSContext* aCx, T* aThis, nsIJSID* aIID, ErrorResult& aError)
+void
+GetInterface(JSContext* aCx, T* aThis, nsIJSID* aIID,
+             JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError)
 {
-  return GetInterfaceImpl(aCx, aThis, aThis, aIID, aError);
+  GetInterfaceImpl(aCx, aThis, aThis, aIID, aRetval, aError);
 }
 
 bool
 ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
 
 bool
 ThrowConstructorWithoutNew(JSContext* cx, const char* name);
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5633,17 +5633,19 @@ def getRetvalDeclarationForType(returnTy
             result = CGTemplatedType("nsRefPtr", result)
         else:
             result = CGWrapper(result, post="*")
         return result, None, None, None
     if returnType.isCallback():
         name = returnType.unroll().identifier.name
         return CGGeneric("nsRefPtr<%s>" % name), None, None, None
     if returnType.isAny():
-        return CGGeneric("JS::Value"), None, None, None
+        if isMember:
+            return CGGeneric("JS::Value"), None, None, None
+        return CGGeneric("JS::Rooted<JS::Value>"), "ptr", None, "cx"
     if returnType.isObject() or returnType.isSpiderMonkeyInterface():
         return CGGeneric("JSObject*"), None, None, None
     if returnType.isSequence():
         nullable = returnType.nullable()
         if nullable:
             returnType = returnType.inner
         # If our result is already addrefed, use the right type in the
         # sequence argument here.
@@ -11574,17 +11576,22 @@ class CGNativeMember(ClassMethod):
             # Since we always force an owning type for callback return values,
             # our ${declName} is an OwningNonNull or nsRefPtr.  So we can just
             # .forget() to get our already_AddRefed.
             return result.define(), "nullptr", "return ${declName}.forget();\n"
         if type.isCallback():
             return ("already_AddRefed<%s>" % type.unroll().identifier.name,
                     "nullptr", "return ${declName}.forget();\n")
         if type.isAny():
-            return "JS::Value", "JS::UndefinedValue()", "return ${declName};\n"
+            if isMember:
+                # No need for a third element in the isMember case
+                return "JS::Value", None, None
+            # Outparam
+            return "void", "", "aRetVal.set(${declName});\n"
+
         if type.isObject():
             return "JSObject*", "nullptr", "return ${declName};\n"
         if type.isSpiderMonkeyInterface():
             if type.nullable():
                 returnCode = "return ${declName}.IsNull() ? nullptr : ${declName}.Value().Obj();\n"
             else:
                 returnCode = "return ${declName}.Obj();\n"
             return "JSObject*", "nullptr", returnCode
@@ -11672,16 +11679,19 @@ class CGNativeMember(ClassMethod):
             dictType = CGGeneric(CGDictionary.makeDictionaryName(returnType.inner))
             if nullable:
                 dictType = CGTemplatedType("Nullable", dictType)
             args.append(Argument("%s&" % dictType.define(), "aRetVal"))
         elif returnType.isUnion():
             args.append(Argument("%s&" %
                                  CGUnionStruct.unionTypeDecl(returnType, True),
                                  "aRetVal"))
+        elif returnType.isAny():
+            args.append(Argument("JS::MutableHandle<JS::Value>", "aRetVal"))
+
         # And the ErrorResult
         if 'infallible' not in self.extendedAttrs:
             # Use aRv so it won't conflict with local vars named "rv"
             args.append(Argument("ErrorResult&", "aRv"))
         # The legacycaller thisval
         if self.member.isMethod() and self.member.isLegacycaller():
             # If it has an identifier, we can't deal with it yet
             assert self.member.isIdentifierLess()
@@ -13558,17 +13568,18 @@ class CGEventGetter(CGNativeMember):
                 }
                 return ${memberName};
                 """,
                 memberName=memberName)
         if type.isAny():
             return fill(
                 """
                 JS::ExposeValueToActiveJS(${memberName});
-                return ${memberName};
+                aRetVal.set(${memberName});
+                return;
                 """,
                 memberName=memberName)
         if type.isUnion():
             return "aRetVal = " + memberName + ";\n"
         raise TypeError("Event code generator does not support this type!")
 
     def declare(self, cgClass):
         if getattr(self.member, "originatingInterface",
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -518,17 +518,17 @@ public:
   void PassOptionalNullableMozMapOfAny(JSContext*, const Optional<Nullable<MozMap<JS::Value> > >&);
   void PassOptionalMozMapOfAnyWithDefaultValue(JSContext*, const Nullable<MozMap<JS::Value> >&);
   void PassMozMapOfMozMapOfAny(JSContext*, const MozMap<MozMap<JS::Value> >&);
   void PassMozMapOfNullableMozMapOfAny(JSContext*, const MozMap<Nullable<MozMap<JS::Value> > >&);
   void PassNullableMozMapOfNullableMozMapOfAny(JSContext*, const Nullable<MozMap<Nullable<MozMap<JS::Value> > > >&);
   void PassOptionalNullableMozMapOfNullableMozMapOfAny(JSContext*, const Optional<Nullable<MozMap<Nullable<MozMap<JS::Value>>>>>&);
   void PassOptionalNullableMozMapOfNullableSequenceOfAny(JSContext*, const Optional<Nullable<MozMap<Nullable<Sequence<JS::Value>>>>>&);
   void PassOptionalNullableSequenceOfNullableMozMapOfAny(JSContext*, const Optional<Nullable<Sequence<Nullable<MozMap<JS::Value>>>>>&);
-  JS::Value ReceiveAny(JSContext*);
+  void ReceiveAny(JSContext*, JS::MutableHandle<JS::Value>);
 
   // object types
   void PassObject(JSContext*, JS::Handle<JSObject*>);
   void PassVariadicObject(JSContext*, const Sequence<JSObject*>&);
   void PassNullableObject(JSContext*, JS::Handle<JSObject*>);
   void PassVariadicNullableObject(JSContext*, const Sequence<JSObject*>&);
   void PassOptionalObject(JSContext*, const Optional<JS::Handle<JSObject*> >&);
   void PassOptionalNullableObject(JSContext*, const Optional<JS::Handle<JSObject*> >&);
@@ -762,17 +762,17 @@ public:
   void SetAttrWithLenientThis(int32_t);
   uint32_t UnforgeableAttr();
   uint32_t UnforgeableAttr2();
   void Stringify(nsString&);
   void PassRenamedInterface(nsRenamedInterface&);
   TestInterface* PutForwardsAttr();
   TestInterface* PutForwardsAttr2();
   TestInterface* PutForwardsAttr3();
-  JS::Value JsonifierShouldSkipThis(JSContext*);
+  void GetJsonifierShouldSkipThis(JSContext*, JS::MutableHandle<JS::Value>);
   void SetJsonifierShouldSkipThis(JSContext*, JS::Rooted<JS::Value>&);
   TestParentInterface* JsonifierShouldSkipThis2();
   void SetJsonifierShouldSkipThis2(TestParentInterface&);
   TestCallbackInterface* JsonifierShouldSkipThis3();
   void SetJsonifierShouldSkipThis3(TestCallbackInterface&);
   void ThrowingMethod(ErrorResult& aRv);
   bool GetThrowingAttr(ErrorResult& aRv) const;
   void SetThrowingAttr(bool arg, ErrorResult& aRv);
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -424,40 +424,44 @@ BluetoothAdapter::StartDiscovery(ErrorRe
 }
 
 already_AddRefed<DOMRequest>
 BluetoothAdapter::StopDiscovery(ErrorResult& aRv)
 {
   return StartStopDiscovery(false, aRv);
 }
 
-JS::Value
-BluetoothAdapter::GetDevices(JSContext* aContext, ErrorResult& aRv)
+void
+BluetoothAdapter::GetDevices(JSContext* aContext,
+                             JS::MutableHandle<JS::Value> aDevices,
+                             ErrorResult& aRv)
 {
   if (!mJsDeviceAddresses) {
     BT_WARNING("Devices not yet set!\n");
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::NullValue();
+    return;
   }
 
   JS::ExposeObjectToActiveJS(mJsDeviceAddresses);
-  return JS::ObjectValue(*mJsDeviceAddresses);
+  aDevices.setObject(*mJsDeviceAddresses);
 }
 
-JS::Value
-BluetoothAdapter::GetUuids(JSContext* aContext, ErrorResult& aRv)
+void
+BluetoothAdapter::GetUuids(JSContext* aContext,
+                           JS::MutableHandle<JS::Value> aUuids,
+                           ErrorResult& aRv)
 {
   if (!mJsUuids) {
     BT_WARNING("UUIDs not yet set!\n");
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::NullValue();
+    return;
   }
 
   JS::ExposeObjectToActiveJS(mJsUuids);
-  return JS::ObjectValue(*mJsUuids);
+  aUuids.setObject(*mJsUuids);
 }
 
 already_AddRefed<DOMRequest>
 BluetoothAdapter::SetName(const nsAString& aName, ErrorResult& aRv)
 {
   if (mName.Equals(aName)) {
     return FirePropertyAlreadySet(GetOwner(), aRv);
   }
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -78,18 +78,20 @@ public:
   }
 
   uint32_t
   DiscoverableTimeout() const
   {
     return mDiscoverableTimeout;
   }
 
-  JS::Value GetDevices(JSContext* aContext, ErrorResult& aRv);
-  JS::Value GetUuids(JSContext* aContext, ErrorResult& aRv);
+  void GetDevices(JSContext* aContext, JS::MutableHandle<JS::Value> aDevices,
+                  ErrorResult& aRv);
+  void GetUuids(JSContext* aContext, JS::MutableHandle<JS::Value> aUuids,
+                ErrorResult& aRv);
 
   already_AddRefed<mozilla::dom::DOMRequest>
     SetName(const nsAString& aName, ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
     SetDiscoverable(bool aDiscoverable, ErrorResult& aRv);
   already_AddRefed<DOMRequest>
     SetDiscoverableTimeout(uint32_t aTimeout, ErrorResult& aRv);
--- a/dom/bluetooth/BluetoothDevice.cpp
+++ b/dom/bluetooth/BluetoothDevice.cpp
@@ -201,39 +201,43 @@ BluetoothDevice::Notify(const BluetoothS
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling device signal: ");
     warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
     BT_WARNING(warningMsg.get());
 #endif
   }
 }
 
-JS::Value
-BluetoothDevice::GetUuids(JSContext* aCx, ErrorResult& aRv)
+void
+BluetoothDevice::GetUuids(JSContext* aContext,
+                           JS::MutableHandle<JS::Value> aUuids,
+                           ErrorResult& aRv)
 {
   if (!mJsUuids) {
     BT_WARNING("UUIDs not yet set!");
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::NullValue();
+    return;
   }
 
   JS::ExposeObjectToActiveJS(mJsUuids);
-  return JS::ObjectValue(*mJsUuids);
+  aUuids.setObject(*mJsUuids);
 }
 
-JS::Value
-BluetoothDevice::GetServices(JSContext* aCx, ErrorResult& aRv)
+void
+BluetoothDevice::GetServices(JSContext* aCx,
+                             JS::MutableHandle<JS::Value> aServices,
+                             ErrorResult& aRv)
 {
   if (!mJsServices) {
     BT_WARNING("Services not yet set!");
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::Value(JSVAL_NULL);
+    return;
   }
 
   JS::ExposeObjectToActiveJS(mJsServices);
-  return JS::ObjectValue(*mJsServices);
+  aServices.setObject(*mJsServices);
 }
 
 JSObject*
 BluetoothDevice::WrapObject(JSContext* aContext)
 {
   return BluetoothDeviceBinding::Wrap(aContext, this);
 }
--- a/dom/bluetooth/BluetoothDevice.h
+++ b/dom/bluetooth/BluetoothDevice.h
@@ -61,18 +61,20 @@ public:
     return mPaired;
   }
 
   bool Connected() const
   {
     return mConnected;
   }
 
-  JS::Value GetUuids(JSContext* aContext, ErrorResult& aRv);
-  JS::Value GetServices(JSContext* aContext, ErrorResult& aRv);
+  void GetUuids(JSContext* aContext, JS::MutableHandle<JS::Value> aUuids,
+                ErrorResult& aRv);
+  void GetServices(JSContext* aContext, JS::MutableHandle<JS::Value> aServices,
+                   ErrorResult& aRv);
 
   nsISupports*
   ToISupports()
   {
     return static_cast<EventTarget*>(this);
   }
 
   void SetPropertyByValue(const BluetoothNamedValue& aValue) MOZ_OVERRIDE;
--- a/dom/bluetooth2/BluetoothAdapter.cpp
+++ b/dom/bluetooth2/BluetoothAdapter.cpp
@@ -452,40 +452,44 @@ BluetoothAdapter::StartDiscovery(ErrorRe
 }
 
 already_AddRefed<DOMRequest>
 BluetoothAdapter::StopDiscovery(ErrorResult& aRv)
 {
   return StartStopDiscovery(false, aRv);
 }
 
-JS::Value
-BluetoothAdapter::GetDevices(JSContext* aContext, ErrorResult& aRv)
+void
+BluetoothAdapter::GetDevices(JSContext* aContext,
+                             JS::MutableHandle<JS::Value> aDevices,
+                             ErrorResult& aRv)
 {
   if (!mJsDeviceAddresses) {
     BT_WARNING("Devices not yet set!\n");
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::NullValue();
+    return;
   }
 
   JS::ExposeObjectToActiveJS(mJsDeviceAddresses);
-  return JS::ObjectValue(*mJsDeviceAddresses);
+  aDevices.setObject(*mJsDeviceAddresses);
 }
 
-JS::Value
-BluetoothAdapter::GetUuids(JSContext* aContext, ErrorResult& aRv)
+void
+BluetoothAdapter::GetUuids(JSContext* aContext,
+                           JS::MutableHandle<JS::Value> aUuids,
+                           ErrorResult& aRv)
 {
   if (!mJsUuids) {
     BT_WARNING("UUIDs not yet set!\n");
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::NullValue();
+    return;
   }
 
   JS::ExposeObjectToActiveJS(mJsUuids);
-  return JS::ObjectValue(*mJsUuids);
+  aUuids.setObject(*mJsUuids);
 }
 
 already_AddRefed<DOMRequest>
 BluetoothAdapter::SetName(const nsAString& aName, ErrorResult& aRv)
 {
   if (mName.Equals(aName)) {
     return FirePropertyAlreadySet(GetOwner(), aRv);
   }
--- a/dom/bluetooth2/BluetoothAdapter.h
+++ b/dom/bluetooth2/BluetoothAdapter.h
@@ -85,18 +85,20 @@ public:
   }
 
   uint32_t
   DiscoverableTimeout() const
   {
     return mDiscoverableTimeout;
   }
 
-  JS::Value GetDevices(JSContext* aContext, ErrorResult& aRv);
-  JS::Value GetUuids(JSContext* aContext, ErrorResult& aRv);
+  void GetDevices(JSContext* aContext, JS::MutableHandle<JS::Value> aDevices,
+                  ErrorResult& aRv);
+  void GetUuids(JSContext* aContext, JS::MutableHandle<JS::Value> aUuids,
+                ErrorResult& aRv);
 
   already_AddRefed<mozilla::dom::DOMRequest>
     SetName(const nsAString& aName, ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
     SetDiscoverable(bool aDiscoverable, ErrorResult& aRv);
   already_AddRefed<DOMRequest>
     SetDiscoverableTimeout(uint32_t aTimeout, ErrorResult& aRv);
--- a/dom/bluetooth2/BluetoothDevice.cpp
+++ b/dom/bluetooth2/BluetoothDevice.cpp
@@ -201,39 +201,43 @@ BluetoothDevice::Notify(const BluetoothS
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling device signal: ");
     warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
     BT_WARNING(warningMsg.get());
 #endif
   }
 }
 
-JS::Value
-BluetoothDevice::GetUuids(JSContext* aCx, ErrorResult& aRv)
+void
+BluetoothDevice::GetUuids(JSContext* aContext,
+                           JS::MutableHandle<JS::Value> aUuids,
+                           ErrorResult& aRv)
 {
   if (!mJsUuids) {
     BT_WARNING("UUIDs not yet set!");
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::NullValue();
+    return;
   }
 
   JS::ExposeObjectToActiveJS(mJsUuids);
-  return JS::ObjectValue(*mJsUuids);
+  aUuids.setObject(*mJsUuids);
 }
 
-JS::Value
-BluetoothDevice::GetServices(JSContext* aCx, ErrorResult& aRv)
+void
+BluetoothDevice::GetServices(JSContext* aCx,
+                             JS::MutableHandle<JS::Value> aServices,
+                             ErrorResult& aRv)
 {
   if (!mJsServices) {
     BT_WARNING("Services not yet set!");
     aRv.Throw(NS_ERROR_FAILURE);
-    return JS::Value(JSVAL_NULL);
+    return;
   }
 
   JS::ExposeObjectToActiveJS(mJsServices);
-  return JS::ObjectValue(*mJsServices);
+  aServices.setObject(*mJsServices);
 }
 
 JSObject*
 BluetoothDevice::WrapObject(JSContext* aContext)
 {
   return BluetoothDeviceBinding::Wrap(aContext, this);
 }
--- a/dom/bluetooth2/BluetoothDevice.h
+++ b/dom/bluetooth2/BluetoothDevice.h
@@ -61,18 +61,20 @@ public:
     return mPaired;
   }
 
   bool Connected() const
   {
     return mConnected;
   }
 
-  JS::Value GetUuids(JSContext* aContext, ErrorResult& aRv);
-  JS::Value GetServices(JSContext* aContext, ErrorResult& aRv);
+  void GetUuids(JSContext* aContext, JS::MutableHandle<JS::Value> aUuids,
+                ErrorResult& aRv);
+  void GetServices(JSContext* aContext, JS::MutableHandle<JS::Value> aServices,
+                   ErrorResult& aRv);
 
   nsISupports*
   ToISupports()
   {
     return static_cast<EventTarget*>(this);
   }
 
   void SetPropertyByValue(const BluetoothNamedValue& aValue) MOZ_OVERRIDE;
--- a/dom/camera/DOMCameraCapabilities.cpp
+++ b/dom/camera/DOMCameraCapabilities.cpp
@@ -288,20 +288,22 @@ CameraCapabilities::MaxExposureCompensat
 }
 
 double
 CameraCapabilities::ExposureCompensationStep() const
 {
   return mExposureCompensationStep;
 }
 
-JS::Value
-CameraCapabilities::RecorderProfiles(JSContext* aCx) const
+void
+CameraCapabilities::GetRecorderProfiles(JSContext* aCx,
+                                        JS::MutableHandle<JS::Value> aRetval) const
 {
-  return mRecorderProfiles;
+  JS::ExposeValueToActiveJS(mRecorderProfiles);
+  aRetval.set(mRecorderProfiles);
 }
 
 void
 CameraCapabilities::GetIsoModes(nsTArray<nsString>& retval) const
 {
   retval = mIsoModes;
 }
 
--- a/dom/camera/DOMCameraCapabilities.h
+++ b/dom/camera/DOMCameraCapabilities.h
@@ -66,17 +66,17 @@ public:
   void GetFocusModes(nsTArray<nsString>& aRetVal) const;
   void GetZoomRatios(nsTArray<double>& aRetVal) const;
   uint32_t MaxFocusAreas() const;
   uint32_t MaxMeteringAreas() const;
   uint32_t MaxDetectedFaces() const;
   double MinExposureCompensation() const;
   double MaxExposureCompensation() const;
   double ExposureCompensationStep() const;
-  JS::Value RecorderProfiles(JSContext* cx) const;
+  void GetRecorderProfiles(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval) const;
   void GetIsoModes(nsTArray<nsString>& aRetVal) const;
 
 protected:
   ~CameraCapabilities();
 
   nsresult TranslateToDictionary(ICameraControl* aCameraControl,
                                  uint32_t aKey, nsTArray<CameraSize>& aSizes);
 
--- a/dom/datastore/DataStoreDB.cpp
+++ b/dom/datastore/DataStoreDB.cpp
@@ -124,17 +124,18 @@ DataStoreDB::HandleEvent(nsIDOMEvent* aE
 nsresult
 DataStoreDB::UpgradeSchema()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   AutoSafeJSContext cx;
 
   ErrorResult error;
-  JS::Rooted<JS::Value> result(cx, mRequest->GetResult(error));
+  JS::Rooted<JS::Value> result(cx);
+  mRequest->GetResult(&result, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.ErrorCode();
   }
 
   MOZ_ASSERT(result.isObject());
 
   IDBDatabase* database = nullptr;
   nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database);
@@ -185,17 +186,18 @@ DataStoreDB::UpgradeSchema()
 nsresult
 DataStoreDB::DatabaseOpened()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   AutoSafeJSContext cx;
 
   ErrorResult error;
-  JS::Rooted<JS::Value> result(cx, mRequest->GetResult(error));
+  JS::Rooted<JS::Value> result(cx);
+  mRequest->GetResult(&result, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.ErrorCode();
   }
 
   MOZ_ASSERT(result.isObject());
 
   nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), mDatabase);
   if (NS_FAILED(rv)) {
--- a/dom/datastore/DataStoreService.cpp
+++ b/dom/datastore/DataStoreService.cpp
@@ -582,17 +582,18 @@ public:
 
     mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), this, false);
 
     // Note: this cx is only used for rooting and AddRevision, neither of which
     // actually care which compartment we're in.
     AutoSafeJSContext cx;
 
     ErrorResult error;
-    JS::Rooted<JS::Value> result(cx, mRequest->GetResult(error));
+    JS::Rooted<JS::Value> result(cx);
+    mRequest->GetResult(cx, &result, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.ErrorCode();
     }
 
     // This means that the content is a IDBCursor, so the first revision already
     // exists.
     if (result.isObject()) {
       nsRefPtr<DataStoreService> service = DataStoreService::Get();
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -635,37 +635,37 @@ DataTransfer::MozGetDataAt(const nsAStri
       NS_IF_ADDREF(*aData);
       return NS_OK;
     }
   }
 
   return NS_OK;
 }
 
-JS::Value
+void
 DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
-                           uint32_t aIndex, mozilla::ErrorResult& aRv)
+                           uint32_t aIndex,
+                           JS::MutableHandle<JS::Value> aRetval,
+                           mozilla::ErrorResult& aRv)
 {
   nsCOMPtr<nsIVariant> data;
   aRv = MozGetDataAt(aFormat, aIndex, getter_AddRefs(data));
   if (aRv.Failed()) {
-    return JS::UndefinedValue();
+    return;
   }
 
   if (!data) {
-    return JS::NullValue();
+    return;
   }
 
   JS::Rooted<JS::Value> result(aCx);
-  if (!VariantToJsval(aCx, data, &result)) {
+  if (!VariantToJsval(aCx, data, aRetval)) {
     aRv = NS_ERROR_FAILURE;
-    return JS::UndefinedValue();
+    return;
   }
-
-  return result;
 }
 
 NS_IMETHODIMP
 DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
                            uint32_t aIndex)
 {
   if (aFormat.IsEmpty()) {
     return NS_OK;
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -159,18 +159,19 @@ public:
   }
   already_AddRefed<DOMStringList> MozTypesAt(uint32_t aIndex,
                                              mozilla::ErrorResult& aRv);
   void MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
                       mozilla::ErrorResult& aRv);
   void MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
                     JS::Handle<JS::Value> aData, uint32_t aIndex,
                     mozilla::ErrorResult& aRv);
-  JS::Value MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
-                         uint32_t aIndex, mozilla::ErrorResult& aRv);
+  void MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
+                    uint32_t aIndex, JS::MutableHandle<JS::Value> aRetval,
+                    mozilla::ErrorResult& aRv);
   bool MozUserCancelled()
   {
     return mUserCancelled;
   }
   already_AddRefed<nsINode> GetMozSourceNode();
 
   mozilla::dom::Element* GetDragTarget()
   {
--- a/dom/events/JSEventHandler.cpp
+++ b/dom/events/JSEventHandler.cpp
@@ -13,16 +13,17 @@
 #include "nsVariant.h"
 #include "nsIDOMBeforeUnloadEvent.h"
 #include "nsGkAtoms.h"
 #include "xpcpublic.h"
 #include "nsJSEnvironment.h"
 #include "nsDOMJSUtils.h"
 #include "WorkerPrivate.h"
 #include "mozilla/ContentEvents.h"
+#include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/JSEventHandler.h"
 #include "mozilla/Likely.h"
 #include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/UnionTypes.h"
 
 namespace mozilla {
 
@@ -150,17 +151,17 @@ JSEventHandler::HandleEvent(nsIDOMEvent*
       lineNumber.Construct();
       lineNumber.Value() = scriptEvent->Lineno();
 
       columnNumber.Construct();
       columnNumber.Value() = scriptEvent->Colno();
 
       ThreadsafeAutoJSContext cx;
       error.Construct(cx);
-      error.Value() = scriptEvent->Error(cx);
+      scriptEvent->GetError(cx, &error.Value());
     } else {
       msgOrEvent.SetAsEvent() = aEvent->InternalDOMEvent();
     }
 
     nsRefPtr<OnErrorEventHandlerNonNull> handler =
       mTypedHandler.OnErrorEventHandler();
     ErrorResult rv;
     bool handled = handler->Call(mTarget, msgOrEvent, fileName, lineNumber,
@@ -205,18 +206,18 @@ JSEventHandler::HandleEvent(nsIDOMEvent*
     }
 
     return NS_OK;
   }
 
   MOZ_ASSERT(mTypedHandler.Type() == TypedEventHandler::eNormal);
   ErrorResult rv;
   nsRefPtr<EventHandlerNonNull> handler = mTypedHandler.NormalEventHandler();
-  JS::Value retval =
-    handler->Call(mTarget, *(aEvent->InternalDOMEvent()), rv);
+  JS::Rooted<JS::Value> retval(CycleCollectedJSRuntime::Get()->Runtime());
+  handler->Call(mTarget, *(aEvent->InternalDOMEvent()), &retval, rv);
   if (rv.Failed()) {
     return rv.ErrorCode();
   }
 
   // If the handler returned false and its sense is not reversed,
   // or the handler returned true and its sense is reversed from
   // the usual (false means cancel), then prevent default.
   if (retval.isBoolean() &&
--- a/dom/events/MessageEvent.cpp
+++ b/dom/events/MessageEvent.cpp
@@ -61,28 +61,29 @@ MessageEvent::WrapObject(JSContext* aCx)
 {
   return mozilla::dom::MessageEventBinding::Wrap(aCx, this);
 }
 
 NS_IMETHODIMP
 MessageEvent::GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData)
 {
   ErrorResult rv;
-  aData.set(GetData(aCx, rv));
+  GetData(aCx, aData, rv);
   return rv.ErrorCode();
 }
 
-JS::Value
-MessageEvent::GetData(JSContext* aCx, ErrorResult& aRv)
+void
+MessageEvent::GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData,
+                      ErrorResult& aRv)
 {
-  JS::Rooted<JS::Value> data(aCx, mData);
-  if (!JS_WrapValue(aCx, &data)) {
+  JS::ExposeValueToActiveJS(mData);
+  aData.set(mData);
+  if (!JS_WrapValue(aCx, aData)) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
-  return data;
 }
 
 NS_IMETHODIMP
 MessageEvent::GetOrigin(nsAString& aOrigin)
 {
   aOrigin = mOrigin;
   return NS_OK;
 }
--- a/dom/events/MessageEvent.h
+++ b/dom/events/MessageEvent.h
@@ -41,17 +41,18 @@ public:
 
   NS_DECL_NSIDOMMESSAGEEVENT
 
   // Forward to base class
   NS_FORWARD_TO_EVENT
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
-  JS::Value GetData(JSContext* aCx, ErrorResult& aRv);
+  void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData,
+               ErrorResult& aRv);
 
   void GetSource(Nullable<OwningWindowProxyOrMessagePort>& aValue) const;
 
   MessagePortList* GetPorts()
   {
     return mPorts;
   }
 
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -605,98 +605,111 @@ IDBCursor::GetSource(OwningIDBObjectStor
       aSource.SetAsIDBIndex() = mIndex;
       break;
 
     default:
       MOZ_ASSERT_UNREACHABLE("Bad type!");
   }
 }
 
-JS::Value
-IDBCursor::GetKey(JSContext* aCx, ErrorResult& aRv)
+void
+IDBCursor::GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                  ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mKey.IsUnset() || !mHaveValue);
 
   if (!mHaveValue) {
-    return JSVAL_VOID;
+    aResult.setUndefined();
+    return;
   }
 
   if (!mHaveCachedKey) {
     if (!mRooted) {
       mozilla::HoldJSObjects(this);
       mRooted = true;
     }
 
     aRv = mKey.ToJSVal(aCx, mCachedKey);
-    ENSURE_SUCCESS(aRv, JSVAL_VOID);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return;
+    }
 
     mHaveCachedKey = true;
   }
 
-  return mCachedKey;
+  JS::ExposeValueToActiveJS(mCachedKey);
+  aResult.set(mCachedKey);
 }
 
-JS::Value
-IDBCursor::GetPrimaryKey(JSContext* aCx, ErrorResult& aRv)
+void
+IDBCursor::GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                         ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mHaveValue) {
-    return JSVAL_VOID;
+    aResult.setUndefined();
+    return;
   }
 
   if (!mHaveCachedPrimaryKey) {
     if (!mRooted) {
       mozilla::HoldJSObjects(this);
       mRooted = true;
     }
 
     const Key& key =
       (mType == OBJECTSTORE || mType == OBJECTSTOREKEY) ? mKey : mObjectKey;
     MOZ_ASSERT(!key.IsUnset());
 
     aRv = key.ToJSVal(aCx, mCachedPrimaryKey);
-    ENSURE_SUCCESS(aRv, JSVAL_VOID);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return;
+    }
 
     mHaveCachedPrimaryKey = true;
   }
 
-  return mCachedPrimaryKey;
+  JS::ExposeValueToActiveJS(mCachedPrimaryKey);
+  aResult.set(mCachedPrimaryKey);
 }
 
-JS::Value
-IDBCursor::GetValue(JSContext* aCx, ErrorResult& aRv)
+void
+IDBCursor::GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                    ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mType == OBJECTSTORE || mType == INDEXOBJECT);
 
   if (!mHaveValue) {
-    return JSVAL_VOID;
+    aResult.setUndefined();
+    return;
   }
 
   if (!mHaveCachedValue) {
     if (!mRooted) {
       mozilla::HoldJSObjects(this);
       mRooted = true;
     }
 
     JS::Rooted<JS::Value> val(aCx);
     if (!IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, &val)) {
       aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
-      return JSVAL_VOID;
+      return;
     }
 
     mCloneReadInfo.mCloneBuffer.clear();
 
     mCachedValue = val;
     mHaveCachedValue = true;
   }
 
-  return mCachedValue;
+  JS::ExposeValueToActiveJS(mCachedValue);
+  aResult.set(mCachedValue);
 }
 
 void
 IDBCursor::Continue(JSContext* aCx,
                     JS::Handle<JS::Value> aKey,
                     ErrorResult &aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -179,36 +179,39 @@ public:
   }
 
   void
   GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const;
 
   IDBCursorDirection
   GetDirection() const;
 
-  JS::Value
-  GetKey(JSContext* aCx, ErrorResult& aRv);
+  void
+  GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+         ErrorResult& aRv);
 
-  JS::Value
-  GetPrimaryKey(JSContext* aCx, ErrorResult& aRv);
+  void
+  GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   void
   Advance(uint32_t aCount, ErrorResult& aRv);
 
   void
   Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Delete(JSContext* aCx, ErrorResult& aRv);
 
-  JS::Value
-  GetValue(JSContext* aCx, ErrorResult& aRv);
+  void
+  GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+           ErrorResult& aRv);
 
 protected:
   IDBCursor();
   ~IDBCursor();
 
   void DropJSObjects();
 
   static
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -821,34 +821,40 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex)
 
 JSObject*
 IDBIndex::WrapObject(JSContext* aCx)
 {
   return IDBIndexBinding::Wrap(aCx, this);
 }
 
-JS::Value
-IDBIndex::GetKeyPath(JSContext* aCx, ErrorResult& aRv)
+void
+IDBIndex::GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                     ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mCachedKeyPath.isUndefined()) {
-    return mCachedKeyPath;
+    JS::ExposeValueToActiveJS(mCachedKeyPath);
+    aResult.set(mCachedKeyPath);
+    return;
   }
 
   aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
-  ENSURE_SUCCESS(aRv, JSVAL_VOID);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
 
   if (mCachedKeyPath.isGCThing()) {
     mozilla::HoldJSObjects(this);
     mRooted = true;
   }
 
-  return mCachedKeyPath;
+  JS::ExposeValueToActiveJS(mCachedKeyPath);
+  aResult.set(mCachedKeyPath);
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
--- a/dom/indexedDB/IDBIndex.h
+++ b/dom/indexedDB/IDBIndex.h
@@ -171,18 +171,19 @@ public:
 
   IDBObjectStore*
   ObjectStore() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return mObjectStore;
   }
 
-  JS::Value
-  GetKeyPath(JSContext* aCx, ErrorResult& aRv);
+  void
+  GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+             ErrorResult& aRv);
 
   bool
   MultiEntry() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return mMultiEntry;
   }
 
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -159,58 +159,62 @@ IDBKeyRange::~IDBKeyRange()
 }
 
 JSObject*
 IDBKeyRange::WrapObject(JSContext* aCx)
 {
   return IDBKeyRangeBinding::Wrap(aCx, this);
 }
 
-JS::Value
-IDBKeyRange::GetLower(JSContext* aCx, ErrorResult& aRv)
+void
+IDBKeyRange::GetLower(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                      ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveCachedLowerVal) {
     if (!mRooted) {
       mozilla::HoldJSObjects(this);
       mRooted = true;
     }
 
     aRv = Lower().ToJSVal(aCx, mCachedLowerVal);
     if (aRv.Failed()) {
-      return JS::UndefinedValue();
+      return;
     }
 
     mHaveCachedLowerVal = true;
   }
 
-  return mCachedLowerVal;
+  JS::ExposeValueToActiveJS(mCachedLowerVal);
+  aResult.set(mCachedLowerVal);
 }
 
-JS::Value
-IDBKeyRange::GetUpper(JSContext* aCx, ErrorResult& aRv)
+void
+IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                      ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveCachedUpperVal) {
     if (!mRooted) {
       mozilla::HoldJSObjects(this);
       mRooted = true;
     }
 
     aRv = Upper().ToJSVal(aCx, mCachedUpperVal);
     if (aRv.Failed()) {
-      return JS::UndefinedValue();
+      return;
     }
 
     mHaveCachedUpperVal = true;
   }
 
-  return mCachedUpperVal;
+  JS::ExposeValueToActiveJS(mCachedUpperVal);
+  aResult.set(mCachedUpperVal);
 }
 
 // static
 already_AddRefed<IDBKeyRange>
 IDBKeyRange::Only(const GlobalObject& aGlobal, JSContext* aCx,
                   JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
--- a/dom/indexedDB/IDBKeyRange.h
+++ b/dom/indexedDB/IDBKeyRange.h
@@ -151,21 +151,23 @@ public:
   WrapObject(JSContext* aCx);
 
   nsISupports*
   GetParentObject() const
   {
     return mGlobal;
   }
 
-  JS::Value
-  GetLower(JSContext* aCx, ErrorResult& aRv);
+  void
+  GetLower(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+           ErrorResult& aRv);
 
-  JS::Value
-  GetUpper(JSContext* aCx, ErrorResult& aRv);
+  void
+  GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+           ErrorResult& aRv);
 
   bool
   LowerOpen() const
   {
     return mLowerOpen;
   }
 
   bool
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -2617,34 +2617,40 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBObjec
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBObjectStore)
 
 JSObject*
 IDBObjectStore::WrapObject(JSContext* aCx)
 {
   return IDBObjectStoreBinding::Wrap(aCx, this);
 }
 
-JS::Value
-IDBObjectStore::GetKeyPath(JSContext* aCx, ErrorResult& aRv)
+void
+IDBObjectStore::GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+                           ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mCachedKeyPath.isUndefined()) {
-    return mCachedKeyPath;
+    JS::ExposeValueToActiveJS(mCachedKeyPath);
+    aResult.set(mCachedKeyPath);
+    return;
   }
 
   aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
-  ENSURE_SUCCESS(aRv, JSVAL_VOID);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
 
   if (mCachedKeyPath.isGCThing()) {
     mozilla::HoldJSObjects(this);
     mRooted = true;
   }
 
-  return mCachedKeyPath;
+  JS::ExposeValueToActiveJS(mCachedKeyPath);
+  aResult.set(mCachedKeyPath);
 }
 
 already_AddRefed<DOMStringList>
 IDBObjectStore::GetIndexNames(ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsRefPtr<DOMStringList> list(new DOMStringList());
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -277,18 +277,19 @@ public:
 
   void
   GetName(nsString& aName) const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     aName.Assign(mName);
   }
 
-  JS::Value
-  GetKeyPath(JSContext* aCx, ErrorResult& aRv);
+  void
+  GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+             ErrorResult& aRv);
 
   already_AddRefed<DOMStringList>
   GetIndexNames(ErrorResult& aRv);
 
   IDBTransaction*
   Transaction() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -321,27 +321,29 @@ IDBRequest::ReadyState() const
 }
 
 JSObject*
 IDBRequest::WrapObject(JSContext* aCx)
 {
   return IDBRequestBinding::Wrap(aCx, this);
 }
 
-JS::Value
-IDBRequest::GetResult(mozilla::ErrorResult& aRv) const
+void
+IDBRequest::GetResult(JS::MutableHandle<JS::Value> aResult,
+                      ErrorResult& aRv) const
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveResultOrErrorCode) {
     // XXX Need a real error code here.
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
   }
 
-  return mResultVal;
+  JS::ExposeValueToActiveJS(mResultVal);
+  aResult.set(mResultVal);
 }
 
 mozilla::dom::DOMError*
 IDBRequest::GetError(mozilla::ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveResultOrErrorCode) {
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -126,23 +126,24 @@ public:
 
   // WebIDL
   nsPIDOMWindow*
   GetParentObject() const
   {
     return GetOwner();
   }
 
-  JS::Value
-  GetResult(ErrorResult& aRv) const;
+  void
+  GetResult(JS::MutableHandle<JS::Value> aResult, ErrorResult& aRv) const;
 
-  JS::Value
-  GetResult(JSContext* aCx, ErrorResult& aRv) const
+  void
+  GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+            ErrorResult& aRv) const
   {
-    return GetResult(aRv);
+    GetResult(aResult, aRv);
   }
 
   IDBTransaction*
   GetTransaction() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return mTransaction;
   }
--- a/dom/indexedDB/ipc/IndexedDBParent.cpp
+++ b/dom/indexedDB/ipc/IndexedDBParent.cpp
@@ -403,17 +403,18 @@ IndexedDBDatabaseParent::HandleRequestEv
     }
 
     return NS_OK;
   }
 
   AutoSafeJSContext cx;
 
   ErrorResult error;
-  JS::Rooted<JS::Value> result(cx, mOpenRequest->GetResult(cx, error));
+  JS::Rooted<JS::Value> result(cx);
+  mOpenRequest->GetResult(cx, &result, error);
   ENSURE_SUCCESS(error, error.ErrorCode());
 
   MOZ_ASSERT(!result.isPrimitive());
 
   IDBDatabase *database;
   rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database);
   if (NS_FAILED(rv)) {
     NS_WARNING("Didn't get the object we expected!");
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -214,18 +214,18 @@ WrapperPromiseCallback::Call(JSContext* 
     NS_WARNING("Failed to wrap value into the right compartment.");
     return;
   }
 
   ErrorResult rv;
 
   // If invoking callback threw an exception, run resolver's reject with the
   // thrown exception as argument and the synchronous flag set.
-  JS::Rooted<JS::Value> retValue(aCx,
-    mCallback->Call(value, rv, CallbackObject::eRethrowExceptions));
+  JS::Rooted<JS::Value> retValue(aCx);
+  mCallback->Call(value, &retValue, rv, CallbackObject::eRethrowExceptions);
 
   rv.WouldReportJSException();
 
   if (rv.Failed() && rv.IsJSException()) {
     JS::Rooted<JS::Value> value(aCx);
     rv.StealJSException(aCx, &value);
 
     if (!JS_WrapValue(aCx, &value)) {
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -2312,38 +2312,41 @@ XMLHttpRequest::SetResponseType(XMLHttpR
   }
 
   nsString acceptedResponseTypeString;
   runnable->GetResponseType(acceptedResponseTypeString);
 
   mResponseType = ConvertStringToResponseType(acceptedResponseTypeString);
 }
 
-jsval
-XMLHttpRequest::GetResponse(JSContext* /* unused */, ErrorResult& aRv)
+void
+XMLHttpRequest::GetResponse(JSContext* /* unused */,
+                            JS::MutableHandle<JS::Value> aResponse,
+                            ErrorResult& aRv)
 {
   if (NS_SUCCEEDED(mStateData.mResponseTextResult) &&
       mStateData.mResponse.isUndefined()) {
     MOZ_ASSERT(mStateData.mResponseText.Length());
     MOZ_ASSERT(NS_SUCCEEDED(mStateData.mResponseResult));
 
     JSString* str =
       JS_NewUCStringCopyN(mWorkerPrivate->GetJSContext(),
                           mStateData.mResponseText.get(),
                           mStateData.mResponseText.Length());
     if (!str) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-      return JSVAL_VOID;
+      return;
     }
 
     mStateData.mResponse = STRING_TO_JSVAL(str);
   }
 
+  JS::ExposeValueToActiveJS(mStateData.mResponse);
   aRv = mStateData.mResponseResult;
-  return mStateData.mResponse;
+  aResponse.set(mStateData.mResponse);
 }
 
 void
 XMLHttpRequest::GetResponseText(nsAString& aResponseText, ErrorResult& aRv)
 {
   aRv = mStateData.mResponseTextResult;
   aResponseText = mStateData.mResponseText;
 }
--- a/dom/workers/XMLHttpRequest.h
+++ b/dom/workers/XMLHttpRequest.h
@@ -208,39 +208,40 @@ public:
   ResponseType() const
   {
     return mResponseType;
   }
 
   void
   SetResponseType(XMLHttpRequestResponseType aResponseType, ErrorResult& aRv);
 
-  jsval
-  GetResponse(JSContext* /* unused */, ErrorResult& aRv);
+  void
+  GetResponse(JSContext* /* unused */, JS::MutableHandle<JS::Value> aResponse,
+              ErrorResult& aRv);
 
   void
   GetResponseText(nsAString& aResponseText, ErrorResult& aRv);
 
   JSObject*
   GetResponseXML() const
   {
     return nullptr;
   }
 
   JSObject*
   GetChannel() const
   {
     return nullptr;
   }
 
-  JS::Value
-  GetInterface(JSContext* cx, JS::Handle<JSObject*> aIID, ErrorResult& aRv)
+  void
+  GetInterface(JSContext* cx, JS::Handle<JSObject*> aIID,
+               JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)
   {
     aRv.Throw(NS_ERROR_FAILURE);
-    return JSVAL_NULL;
   }
 
   XMLHttpRequestUpload*
   GetUploadObjectNoCreate() const
   {
     return mUpload;
   }
 
--- a/js/xpconnect/src/event_impl_gen.py
+++ b/js/xpconnect/src/event_impl_gen.py
@@ -178,17 +178,17 @@ def print_class_declaration(eventname, i
 
     for a in attributes:
         """xpidl methods take care of string member variables!"""
         firstCapName = firstCap(a.name)
         cleanNativeType = a.realtype.nativeType('in').strip('* ')
         if a.realtype.nativeType('in').count("nsAString"):
             continue
         elif a.realtype.nativeType('in').count("nsIVariant"):
-            fd.write("  JS::Value Get%s(JSContext* aCx, ErrorResult& aRv);\n\n" % firstCapName);
+            fd.write("  void Get%s(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);\n\n" % firstCapName);
         elif a.realtype.nativeType('in').endswith('*'):
             fd.write("  already_AddRefed<%s> Get%s()\n" % (xpidl_to_native(cleanNativeType, conf), firstCapName))
             fd.write("  {\n");
             fd.write("    nsCOMPtr<%s> %s = do_QueryInterface(m%s);\n" % (xpidl_to_canonical(cleanNativeType, conf), a.name, firstCapName))
             fd.write("    return %s.forget().downcast<%s>();\n" % (a.name, xpidl_to_native(cleanNativeType, conf)))
             fd.write("  }\n\n");
         else:
             fd.write("  %s %s()\n" % (cleanNativeType, firstCapName))
@@ -300,25 +300,25 @@ def writeAttributeGetter(fd, classname, 
         fd.write("  a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
     elif a.realtype.nativeType('in').count("nsACString"):
         fd.write("  a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
     else:
         fd.write("  *a%s = %s();\n" % (firstCap(a.name), firstCap(a.name)))
     fd.write("  return NS_OK;\n");
     fd.write("}\n\n");
     if a.realtype.nativeType('in').count("nsIVariant"):
-        fd.write("JS::Value\n")
-        fd.write("%s::Get%s(JSContext* aCx, ErrorResult& aRv)\n" % (classname, firstCap(a.name)))
+        fd.write("void\n")
+        fd.write("%s::Get%s(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv)\n" % (classname, firstCap(a.name)))
         fd.write("{\n")
-        fd.write("  JS::Rooted<JS::Value> retVal(aCx, JS::NullValue());\n");
         fd.write("  nsresult rv = NS_ERROR_UNEXPECTED;\n")
-        fd.write("  if (m%s && !XPCVariant::VariantDataToJS(m%s, &rv, &retVal)) {\n" % (firstCap(a.name), firstCap(a.name)))
+        fd.write("  if (!m%s) {\n" % firstCap(a.name))
+        fd.write("    aRetval.setNull();\n")
+        fd.write("  } else if (!XPCVariant::VariantDataToJS(m%s, &rv, aRetval)) {\n" % (firstCap(a.name)))
         fd.write("    aRv.Throw(NS_ERROR_FAILURE);\n")
         fd.write("  }\n")
-        fd.write("  return retVal;\n");
         fd.write("}\n\n")
 
 def writeAttributeParams(fd, a):
     if a.realtype.nativeType('in').endswith('*'):
         fd.write(", %s* a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name)))
     elif a.realtype.nativeType('in').count("nsAString"):
         fd.write(", const nsAString& a%s" % firstCap(a.name))
     elif a.realtype.nativeType('in').count("nsACString"):