Bug 1009675 - Part 2: Return WebIDL 'any' values as handles. r=peterv, a=sledru
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 11 Jun 2014 16:33:30 -0400
changeset 199515 f69c307f1ebf8be8bd50c5833d12708ae1216fbf
parent 199514 52c63eeaf297deb3bd974709694baeda0d35b754
child 199516 f97b33e8ec223c0e8b6d69f57f5b3d28f7e9c8eb
push id3651
push userryanvm@gmail.com
push dateTue, 17 Jun 2014 17:04:05 +0000
treeherdermozilla-beta@f97b33e8ec22 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv, sledru
bugs1009675
milestone31.0
Bug 1009675 - Part 2: Return WebIDL 'any' values as handles. r=peterv, a=sledru
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/camera/DOMCameraCapabilities.cpp
dom/camera/DOMCameraCapabilities.h
dom/camera/DOMCameraControl.cpp
dom/camera/DOMCameraControl.h
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
@@ -175,22 +175,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
@@ -81,17 +81,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
@@ -728,70 +728,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
@@ -3195,99 +3195,98 @@ nsObjectLoadingContent::GetContentDocume
   // Return null for cross-origin contentDocument.
   if (!nsContentUtils::GetSubjectPrincipal()->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.handleAt(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
@@ -924,118 +924,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();
 }
 
 /* readonly attribute unsigned long status; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetStatus(uint32_t *aStatus)
 {
   *aStatus = Status();
   return NS_OK;
@@ -3669,20 +3676,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
@@ -477,33 +477,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
@@ -3044,20 +3044,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
@@ -324,56 +324,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);
@@ -654,16 +673,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;
 
@@ -703,17 +726,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;
 
@@ -729,16 +757,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
@@ -3035,43 +3035,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
@@ -77,17 +77,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
@@ -43,21 +43,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);
   }
 
   nsISupports* GetError() const
   {
     NS_ASSERTION(mDone || !mError,
                  "Error should be null when pending");
     return mError;
   }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4412,35 +4412,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;
@@ -9005,41 +9005,41 @@ 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));
 
   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.
@@ -10473,20 +10473,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;
@@ -11962,17 +11964,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
@@ -13455,63 +13458,65 @@ 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!");
 
   // 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::GetSubjectPrincipal(),
-                        &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::GetSubjectPrincipal(), 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::GetSubjectPrincipal(),
-                      &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
@@ -823,17 +823,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,
@@ -852,17 +853,21 @@ protected:
                       mozilla::ErrorResult& aError);
 
 public:
   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);
@@ -998,23 +1003,26 @@ public:
   void Restore(mozilla::ErrorResult& aError);
   void NotifyDefaultButtonLoaded(mozilla::dom::Element& aDefaultButton,
                                  mozilla::ErrorResult& aError);
   nsIMessageBroadcaster* GetMessageManager(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
@@ -865,35 +865,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
@@ -1601,25 +1601,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
@@ -5595,17 +5595,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.
@@ -11442,17 +11444,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
@@ -11540,16 +11547,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()
@@ -13398,17 +13408,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
@@ -414,40 +414,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/camera/DOMCameraCapabilities.cpp
+++ b/dom/camera/DOMCameraCapabilities.cpp
@@ -289,20 +289,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
@@ -61,17 +61,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:
   nsresult TranslateToDictionary(ICameraControl* aCameraControl,
                                  uint32_t aKey, nsTArray<CameraSize>& aSizes);
 
   nsTArray<CameraSize> mPreviewSizes;
   nsTArray<CameraSize> mPictureSizes;
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -436,37 +436,37 @@ nsDOMCameraControl::GetZoom(ErrorResult&
 void
 nsDOMCameraControl::SetZoom(double aZoom, ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
   aRv = mCameraControl->Set(CAMERA_PARAM_ZOOM, aZoom);
 }
 
 /* attribute jsval meteringAreas; */
-JS::Value
-nsDOMCameraControl::GetMeteringAreas(JSContext* cx, ErrorResult& aRv)
+void
+nsDOMCameraControl::GetMeteringAreas(JSContext* cx,
+				     JS::MutableHandle<JS::Value> aMeteringAreas,
+				     ErrorResult& aRv)
 {
-  JS::Rooted<JS::Value> areas(cx);
-  aRv = Get(cx, CAMERA_PARAM_METERINGAREAS, areas.address());
-  return areas;
+  aRv = Get(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas.address());
 }
 
 void
 nsDOMCameraControl::SetMeteringAreas(JSContext* cx, JS::Handle<JS::Value> aMeteringAreas, ErrorResult& aRv)
 {
   aRv = Set(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas,
             mCurrentConfiguration->mMaxMeteringAreas);
 }
 
-JS::Value
-nsDOMCameraControl::GetFocusAreas(JSContext* cx, ErrorResult& aRv)
+void
+nsDOMCameraControl::GetFocusAreas(JSContext* cx,
+				  JS::MutableHandle<JS::Value> aFocusAreas,
+				  ErrorResult& aRv)
 {
-  JS::Rooted<JS::Value> value(cx);
-  aRv = Get(cx, CAMERA_PARAM_FOCUSAREAS, value.address());
-  return value;
+  aRv = Get(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas.address());
 }
 void
 nsDOMCameraControl::SetFocusAreas(JSContext* cx, JS::Handle<JS::Value> aFocusAreas, ErrorResult& aRv)
 {
   aRv = Set(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas,
             mCurrentConfiguration->mMaxFocusAreas);
 }
 
@@ -489,57 +489,55 @@ GetSize(JSContext* aCx, JS::Value* aValu
     return NS_ERROR_FAILURE;
   }
 
   *aValue = JS::ObjectValue(*o);
   return NS_OK;
 }
 
 /* attribute any pictureSize */
-JS::Value
-nsDOMCameraControl::GetPictureSize(JSContext* cx, ErrorResult& aRv)
+void
+nsDOMCameraControl::GetPictureSize(JSContext* cx,
+				   JS::MutableHandle<JS::Value> aSize,
+				   ErrorResult& aRv)
 {
-  JS::Rooted<JS::Value> value(cx);
-
   ICameraControl::Size size;
   aRv = mCameraControl->Get(CAMERA_PARAM_PICTURE_SIZE, size);
   if (aRv.Failed()) {
-    return value;
+    return;
   }
 
-  aRv = GetSize(cx, value.address(), size);
-  return value;
+  aRv = GetSize(cx, aSize.address(), size);
 }
 void
 nsDOMCameraControl::SetPictureSize(JSContext* aCx, JS::Handle<JS::Value> aSize, ErrorResult& aRv)
 {
   CameraSize size;
   if (!size.Init(aCx, aSize)) {
     aRv = NS_ERROR_FAILURE;
     return;
   }
 
   ICameraControl::Size s = { size.mWidth, size.mHeight };
   aRv = mCameraControl->Set(CAMERA_PARAM_PICTURE_SIZE, s);
 }
 
 /* attribute any thumbnailSize */
-JS::Value
-nsDOMCameraControl::GetThumbnailSize(JSContext* aCx, ErrorResult& aRv)
+void
+nsDOMCameraControl::GetThumbnailSize(JSContext* aCx,
+				     JS::MutableHandle<JS::Value> aSize,
+				     ErrorResult& aRv)
 {
-  JS::Rooted<JS::Value> value(aCx);
-
   ICameraControl::Size size;
   aRv = mCameraControl->Get(CAMERA_PARAM_THUMBNAILSIZE, size);
   if (aRv.Failed()) {
-    return value;
+    return;
   }
 
-  aRv = GetSize(aCx, value.address(), size);
-  return value;
+  aRv = GetSize(aCx, aSize.address(), size);
 }
 void
 nsDOMCameraControl::SetThumbnailSize(JSContext* aCx, JS::Handle<JS::Value> aSize, ErrorResult& aRv)
 {
   CameraSize size;
   if (!size.Init(aCx, aSize)) {
     aRv = NS_ERROR_FAILURE;
     return;
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -65,23 +65,31 @@ public:
   void GetSceneMode(nsString& aMode, ErrorResult& aRv);
   void SetSceneMode(const nsAString& aMode, ErrorResult& aRv);
   void GetFlashMode(nsString& aMode, ErrorResult& aRv);
   void SetFlashMode(const nsAString& aMode, ErrorResult& aRv);
   void GetFocusMode(nsString& aMode, ErrorResult& aRv);
   void SetFocusMode(const nsAString& aMode, ErrorResult& aRv);
   double GetZoom(ErrorResult& aRv);
   void SetZoom(double aZoom, ErrorResult& aRv);
-  JS::Value GetMeteringAreas(JSContext* aCx, ErrorResult& aRv);
+  void GetMeteringAreas(JSContext* aCx,
+			JS::MutableHandle<JS::Value> aMeteringAreas,
+			ErrorResult& aRv);
   void SetMeteringAreas(JSContext* aCx, JS::Handle<JS::Value> aAreas, ErrorResult& aRv);
-  JS::Value GetFocusAreas(JSContext* aCx, ErrorResult& aRv);
+  void GetFocusAreas(JSContext* aCx,
+		     JS::MutableHandle<JS::Value> aFocusAreas,
+		     ErrorResult& aRv);
   void SetFocusAreas(JSContext* aCx, JS::Handle<JS::Value> aAreas, ErrorResult& aRv);
-  JS::Value GetPictureSize(JSContext* aCx, ErrorResult& aRv);
+  void GetPictureSize(JSContext* aCx,
+		      JS::MutableHandle<JS::Value> aSize,
+		      ErrorResult& aRv);
   void SetPictureSize(JSContext* aCx, JS::Handle<JS::Value> aSize, ErrorResult& aRv);
-  JS::Value GetThumbnailSize(JSContext* aCx, ErrorResult& aRv);
+  void GetThumbnailSize(JSContext* aCx,
+			JS::MutableHandle<JS::Value> aSize,
+			ErrorResult& aRv);
   void SetThumbnailSize(JSContext* aCx, JS::Handle<JS::Value> aSize, ErrorResult& aRv);
   double GetFocalLength(ErrorResult& aRv);
   double GetFocusDistanceNear(ErrorResult& aRv);
   double GetFocusDistanceOptimum(ErrorResult& aRv);
   double GetFocusDistanceFar(ErrorResult& aRv);
   void SetExposureCompensation(const dom::Optional<double>& aCompensation, ErrorResult& aRv);
   double GetExposureCompensation(ErrorResult& aRv);
   int32_t SensorAngle();
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -637,37 +637,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_ASSUME_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 (!JSVAL_IS_VOID(mCachedKeyPath)) {
-    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 (JSVAL_IS_GCTHING(mCachedKeyPath)) {
     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
@@ -2605,34 +2605,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 (!JSVAL_IS_VOID(mCachedKeyPath)) {
-    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 (JSVAL_IS_GCTHING(mCachedKeyPath)) {
     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(JSContext* aCx, mozilla::ErrorResult& aRv) const
+void
+IDBRequest::GetResult(JSContext* aCx, 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,18 +126,19 @@ public:
 
   // WebIDL
   nsPIDOMWindow*
   GetParentObject() const
   {
     return GetOwner();
   }
 
-  JS::Value
-  GetResult(JSContext* aCx, ErrorResult& aRv) const;
+  void
+  GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+            ErrorResult& aRv) const;
 
   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(!JSVAL_IS_PRIMITIVE(result));
 
   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
@@ -215,18 +215,18 @@ WrapperPromiseCallback::Call(JS::Handle<
     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(cx,
-    mCallback->Call(value, rv, CallbackObject::eRethrowExceptions));
+  JS::Rooted<JS::Value> retValue(cx);
+  mCallback->Call(value, &retValue, rv, CallbackObject::eRethrowExceptions);
 
   rv.WouldReportJSException();
 
   if (rv.Failed() && rv.IsJSException()) {
     JS::Rooted<JS::Value> value(cx);
     rv.StealJSException(cx, &value);
 
     if (!JS_WrapValue(cx, &value)) {
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -2265,38 +2265,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) &&
       JSVAL_IS_VOID(mStateData.mResponse)) {
     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
@@ -201,39 +201,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"):