Bug 930782 - Handlify JS_WrapValue. r=terrence
authorTom Schuster <evilpies@gmail.com>
Sat, 26 Oct 2013 18:19:05 +0200
changeset 152699 05c31c03a8dd7ca613840e8de25ad37f5487b1af
parent 152698 1268bd66a094596cc4cda46c1903c9a027fd76fe
child 152700 fa5301bdb5aca2ec846e3335b3e7be676741cbb2
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersterrence
bugs930782
milestone27.0a1
Bug 930782 - Handlify JS_WrapValue. r=terrence
content/base/src/nsDOMFileReader.cpp
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsObjectLoadingContent.cpp
content/events/src/nsDOMMessageEvent.cpp
content/html/content/src/UndoManager.cpp
content/xbl/src/nsXBLProtoImplField.cpp
dom/base/Navigator.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsHistory.cpp
dom/base/nsJSEnvironment.cpp
dom/base/nsJSUtils.cpp
dom/base/nsStructuredCloneContainer.cpp
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
dom/bindings/Exceptions.cpp
dom/src/jsurl/nsJSProtocolHandler.cpp
js/jsd/jsd_val.cpp
js/jsd/jsd_xpc.cpp
js/src/jsapi-tests/testChromeBuffer.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/js.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCVariant.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/XPCWrappedNativeScope.cpp
js/xpconnect/src/XPCWrapper.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/qsgen.py
js/xpconnect/src/xpcprivate.h
js/xpconnect/wrappers/WaiveXrayWrapper.cpp
js/xpconnect/wrappers/WrapperFactory.cpp
js/xpconnect/wrappers/WrapperFactory.h
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -179,39 +179,39 @@ nsDOMFileReader::GetReadyState(uint16_t 
 {
   *aReadyState = ReadyState();
   return NS_OK;
 }
 
 JS::Value
 nsDOMFileReader::GetResult(JSContext* aCx, ErrorResult& aRv)
 {
-  JS::Rooted<JS::Value> result(aCx, JS::UndefinedValue());
+  JS::Rooted<JS::Value> result(aCx);
   aRv = GetResult(aCx, result.address());
   return result;
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::GetResult(JSContext* aCx, JS::Value* aResult)
 {
+  JS::Rooted<JS::Value> result(aCx);
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
     if (mReadyState == nsIDOMFileReader::DONE && mResultArrayBuffer) {
-      JSObject* tmp = mResultArrayBuffer;
-      *aResult = OBJECT_TO_JSVAL(tmp);
+      result.setObject(*mResultArrayBuffer);
     } else {
-      *aResult = JSVAL_NULL;
+      result.setNull();
     }
-    if (!JS_WrapValue(aCx, aResult)) {
+    if (!JS_WrapValue(aCx, &result)) {
       return NS_ERROR_FAILURE;
     }
+    *aResult = result;
     return NS_OK;
   }
- 
+
   nsString tmpResult = mResult;
-  JS::Rooted<JS::Value> result(aCx);
   if (!xpc::StringToJsval(aCx, tmpResult, &result)) {
     return NS_ERROR_FAILURE;
   }
   *aResult = result;
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -949,17 +949,17 @@ nsFrameMessageManager::ReceiveMessage(ns
 
       JS::Rooted<JS::Value> rval(ctx, JSVAL_VOID);
       JS::Rooted<JS::Value> argv(ctx, JS::ObjectValue(*param));
 
       {
         JS::Rooted<JSObject*> thisObject(ctx, thisValue.toObjectOrNull());
 
         JSAutoCompartment tac(ctx, thisObject);
-        if (!JS_WrapValue(ctx, argv.address())) {
+        if (!JS_WrapValue(ctx, &argv)) {
           return NS_ERROR_UNEXPECTED;
         }
 
         JS_CallFunctionValue(ctx, thisObject,
                              funval, 1, argv.address(), rval.address());
         if (aJSONRetVal) {
           nsString json;
           if (JS_Stringify(ctx, &rval, JS::NullPtr(), JS::NullHandleValue,
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -3141,27 +3141,25 @@ nsObjectLoadingContent::LegacyCall(JSCon
     return JS::UndefinedValue();
   }
 
   obj = thisContent->GetWrapper();
   // Now wrap things up into the compartment of "obj"
   JSAutoCompartment ac(aCx, obj);
   nsTArray<JS::Value> args(aArguments);
   JS::AutoArrayRooter rooter(aCx, args.Length(), args.Elements());
-  for (JS::Value *arg = args.Elements(), *arg_end = arg + args.Length();
-       arg != arg_end;
-       ++arg) {
-    if (!JS_WrapValue(aCx, arg)) {
+  for (size_t i = 0; i < args.Length(); i++) {
+    if (!JS_WrapValue(aCx, rooter.handleAt(i))) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return JS::UndefinedValue();
     }
   }
 
   JS::Rooted<JS::Value> thisVal(aCx, aThisVal);
-  if (!JS_WrapValue(aCx, thisVal.address())) {
+  if (!JS_WrapValue(aCx, &thisVal)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return JS::UndefinedValue();
   }
 
   nsRefPtr<nsNPAPIPluginInstance> pi;
   nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
@@ -3184,17 +3182,17 @@ nsObjectLoadingContent::LegacyCall(JSCon
   }
 
   if (!pi_obj) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return JS::UndefinedValue();
   }
 
   JS::Rooted<JS::Value> retval(aCx);
-  bool ok = JS::Call(aCx, thisVal, pi_obj, args.Length(), args.Elements(),
+  bool ok = JS::Call(aCx, thisVal, pi_obj, args.Length(), rooter.array,
                      &retval);
   if (!ok) {
     aRv.Throw(NS_ERROR_FAILURE);
     return JS::UndefinedValue();
   }
 
   Telemetry::Accumulate(Telemetry::PLUGIN_CALLED_DIRECTLY, true);
   return retval;
--- a/content/events/src/nsDOMMessageEvent.cpp
+++ b/content/events/src/nsDOMMessageEvent.cpp
@@ -62,17 +62,17 @@ nsDOMMessageEvent::GetData(JSContext* aC
   *aData = GetData(aCx, rv);
   return rv.ErrorCode();
 }
 
 JS::Value
 nsDOMMessageEvent::GetData(JSContext* aCx, ErrorResult& aRv)
 {
   JS::Rooted<JS::Value> data(aCx, mData);
-  if (!JS_WrapValue(aCx, data.address())) {
+  if (!JS_WrapValue(aCx, &data)) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
   return data;
 }
 
 NS_IMETHODIMP
 nsDOMMessageEvent::GetOrigin(nsAString& aOrigin)
 {
--- a/content/html/content/src/UndoManager.cpp
+++ b/content/html/content/src/UndoManager.cpp
@@ -1151,17 +1151,17 @@ UndoManager::DispatchTransactionEvent(JS
   nsCOMPtr<nsIWritableVariant> transactions = new nsVariant();
 
   // Unwrap the DOMTransactions into jsvals, then convert
   // to nsIVariant then put into a nsIVariant array. Arrays in XPIDL suck.
   nsCOMArray<nsIVariant> keepAlive;
   nsTArray<nsIVariant*> transactionItems;
   for (uint32_t i = 0; i < items.Length(); i++) {
     JS::Rooted<JS::Value> txVal(aCx, JS::ObjectValue(*items[i]->Callback()));
-    if (!JS_WrapValue(aCx, txVal.address())) {
+    if (!JS_WrapValue(aCx, &txVal)) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     nsCOMPtr<nsIVariant> txVariant;
     nsresult rv =
       nsContentUtils::XPConnect()->JSToVariant(aCx, txVal,
                                                getter_AddRefs(txVariant));
     if (NS_SUCCEEDED(rv)) {
--- a/content/xbl/src/nsXBLProtoImplField.cpp
+++ b/content/xbl/src/nsXBLProtoImplField.cpp
@@ -340,17 +340,17 @@ nsXBLProtoImplField::InstallAccessors(JS
     return NS_OK;
 
   // FieldGetter and FieldSetter need to run in the XBL scope so that they can
   // see through any SOWs on their targets.
 
   // First, enter the XBL scope, and compile the functions there.
   JSAutoCompartment ac(aCx, scopeObject);
   JS::Rooted<JS::Value> wrappedClassObj(aCx, JS::ObjectValue(*aTargetClassObject));
-  if (!JS_WrapValue(aCx, wrappedClassObj.address()) || !JS_WrapId(aCx, id.address()))
+  if (!JS_WrapValue(aCx, &wrappedClassObj) || !JS_WrapId(aCx, id.address()))
     return NS_ERROR_OUT_OF_MEMORY;
 
   JS::Rooted<JSObject*> get(aCx,
     JS_GetFunctionObject(js::NewFunctionByIdWithReserved(aCx, FieldGetter,
                                                          0, 0, scopeObject, id)));
   if (!get) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -440,19 +440,19 @@ nsXBLProtoImplField::InstallField(nsIScr
     return rv;
   }
 
 
   // Now, enter the node's compartment, wrap the eval result, and define it on
   // the bound node.
   JSAutoCompartment ac2(cx, aBoundNode);
   nsDependentString name(mName);
-  if (!JS_WrapValue(cx, result.address()) ||
+  if (!JS_WrapValue(cx, &result) ||
       !::JS_DefineUCProperty(cx, aBoundNode,
-                             reinterpret_cast<const jschar*>(mName), 
+                             reinterpret_cast<const jschar*>(mName),
                              name.Length(), result, nullptr, nullptr,
                              mJSAttributes)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   *aDidInstall = true;
   return NS_OK;
 }
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1586,17 +1586,17 @@ Navigator::DoNewResolve(JSContext* aCx, 
     rv = nsContentUtils::WrapNative(aCx, aObject, native, &prop_val,
                                     getter_AddRefs(holder), true);
 
     if (NS_FAILED(rv)) {
       return Throw(aCx, rv);
     }
   }
 
-  if (!JS_WrapValue(aCx, prop_val.address())) {
+  if (!JS_WrapValue(aCx, &prop_val)) {
     return Throw(aCx, NS_ERROR_UNEXPECTED);
   }
 
   aValue.set(prop_val);
   return true;
 }
 
 static PLDHashOperator
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -2224,22 +2224,22 @@ BaseStubConstructor(nsIWeakReference* aW
         unsigned argc = args.length() + 1;
         JS::AutoValueVector argv(cx);
         argv.resize(argc);
 
         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
         nsCOMPtr<nsIDOMWindow> currentWin(do_GetInterface(currentInner));
         rv = WrapNative(cx, obj, currentWin, &NS_GET_IID(nsIDOMWindow),
                         true, argv.handleAt(0), getter_AddRefs(holder));
-        if (!JS_WrapValue(cx, &argv[0]))
+        if (!JS_WrapValue(cx, argv.handleAt(0)))
           return NS_ERROR_FAILURE;
 
         for (size_t i = 1; i < argc; ++i) {
           argv[i] = args[i - 1];
-          if (!JS_WrapValue(cx, &argv[i]))
+          if (!JS_WrapValue(cx, argv.handleAt(i)))
             return NS_ERROR_FAILURE;
         }
 
         JS::Rooted<JS::Value> frval(cx);
         bool ret = JS_CallFunctionValue(cx, thisObject, funval,
                                         argc, argv.begin(),
                                         frval.address());
 
@@ -2366,17 +2366,17 @@ public:
                        JS::Handle<JSObject*> obj, const jsval &val, bool *bp,
                        bool *_retval);
 
   nsresult Install(JSContext *cx, JS::Handle<JSObject*> target,
                    JS::Handle<JS::Value> aThisAsVal)
   {
     JS::Rooted<JS::Value> thisAsVal(cx, aThisAsVal);
     // The 'attrs' argument used to be JSPROP_PERMANENT. See bug 628612.
-    bool ok = JS_WrapValue(cx, thisAsVal.address()) &&
+    bool ok = JS_WrapValue(cx, &thisAsVal) &&
       ::JS_DefineUCProperty(cx, target,
                             reinterpret_cast<const jschar *>(mClassName),
                             NS_strlen(mClassName), thisAsVal, JS_PropertyStub,
                             JS_StrictPropertyStub, 0);
 
     return ok ? NS_OK : NS_ERROR_UNEXPECTED;
   }
 
@@ -2940,17 +2940,17 @@ ResolvePrototype(nsIXPConnect *aXPConnec
     }
   }
 
   v = OBJECT_TO_JSVAL(dot_prototype);
 
   JSAutoCompartment ac(cx, class_obj);
 
   // Per ECMA, the prototype property is {DontEnum, DontDelete, ReadOnly}
-  if (!JS_WrapValue(cx, v.address()) ||
+  if (!JS_WrapValue(cx, &v) ||
       !JS_DefineProperty(cx, class_obj, "prototype", v,
                          JS_PropertyStub, JS_StrictPropertyStub,
                          JSPROP_PERMANENT | JSPROP_READONLY)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   *did_resolve = true;
 
@@ -3252,17 +3252,17 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
       }
 
       rv = WrapNative(cx, scope, native, true, &prop_val,
                       getter_AddRefs(holder));
     }
 
     NS_ENSURE_SUCCESS(rv, rv);
 
-    if (!JS_WrapValue(cx, prop_val.address())) {
+    if (!JS_WrapValue(cx, &prop_val)) {
       return NS_ERROR_UNEXPECTED;
     }
 
     bool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val,
                                       JS_PropertyStub, JS_StrictPropertyStub,
                                       JSPROP_ENUMERATE);
 
     *did_resolve = true;
@@ -3563,17 +3563,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
     JS::Rooted<JSObject*> scope(cx, wrapper->GetJSObject());
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     JS::Rooted<JS::Value> v(cx);
     rv = WrapNative(cx, scope, location, &NS_GET_IID(nsIDOMLocation), true,
                     &v, getter_AddRefs(holder));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    bool ok = JS_WrapValue(cx, v.address()) &&
+    bool ok = JS_WrapValue(cx, &v) &&
                 JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub,
                                       LocationSetterUnwrapper,
                                       JSPROP_PERMANENT | JSPROP_ENUMERATE);
 
     if (!ok) {
       return NS_ERROR_FAILURE;
     }
 
@@ -3687,17 +3687,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       // property
       *objp = obj;
 
       // NB: We need to do this for any Xray wrapper.
       if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
         // Unless our object is a native wrapper, in which case we have to
         // define it ourselves.
 
-        *_retval = JS_WrapValue(cx, v.address()) &&
+        *_retval = JS_WrapValue(cx, &v) &&
                    JS_DefineProperty(cx, obj, "document", v,
                                      JS_PropertyStub, JS_StrictPropertyStub,
                                      JSPROP_READONLY | JSPROP_ENUMERATE);
         if (!*_retval) {
           return NS_ERROR_UNEXPECTED;
         }
       }
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -617,17 +617,18 @@ protected:
     return nsGlobalWindow::FromSupports(
       static_cast<nsISupports*>(js::GetProxyExtra(proxy, 0).toPrivate()));
   }
 
   // False return value means we threw an exception.  True return value
   // but false "found" means we didn't have a subframe at that index.
   bool GetSubframeWindow(JSContext *cx, JS::Handle<JSObject*> proxy,
                          JS::Handle<jsid> id,
-                         JS::Value *vp, bool &found);
+                         JS::MutableHandle<JS::Value> vp,
+                         bool &found);
 
   // Returns a non-null window only if id is an index and we have a
   // window at that index.
   already_AddRefed<nsIDOMWindow> GetSubframeWindow(JSContext *cx,
                                                    JS::Handle<JSObject*> proxy,
                                                    JS::Handle<jsid> id);
 
   bool AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
@@ -703,17 +704,17 @@ nsOuterWindowProxy::getPropertyDescripto
 bool
 nsOuterWindowProxy::getOwnPropertyDescriptor(JSContext* cx,
                                              JS::Handle<JSObject*> proxy,
                                              JS::Handle<jsid> id,
                                              JS::MutableHandle<JSPropertyDescriptor> desc,
                                              unsigned flags)
 {
   bool found;
-  if (!GetSubframeWindow(cx, proxy, id, desc.value().address(), found)) {
+  if (!GetSubframeWindow(cx, proxy, id, desc.value(), found)) {
     return false;
   }
   if (found) {
     FillPropertyDescriptor(desc, proxy, true);
     return true;
   }
   // else fall through to js::Wrapper
 
@@ -824,17 +825,17 @@ nsOuterWindowProxy::get(JSContext *cx, J
 {
   if (id == nsDOMClassInfo::sWrappedJSObject_id &&
       xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
     vp.set(JS::ObjectValue(*proxy));
     return true;
   }
 
   bool found;
-  if (!GetSubframeWindow(cx, proxy, id, vp.address(), found)) {
+  if (!GetSubframeWindow(cx, proxy, id, vp, found)) {
     return false;
   }
   if (found) {
     return true;
   }
   // Else fall through to js::Wrapper
 
   return js::Wrapper::get(cx, proxy, receiver, id, vp);
@@ -875,17 +876,18 @@ nsOuterWindowProxy::iterate(JSContext *c
   // BaseProxyHandler::iterate seems to do what we want here: fall
   // back on the property names returned from keys() and enumerate().
   return js::BaseProxyHandler::iterate(cx, proxy, flags, vp);
 }
 
 bool
 nsOuterWindowProxy::GetSubframeWindow(JSContext *cx,
                                       JS::Handle<JSObject*> proxy,
-                                      JS::Handle<jsid> id, JS::Value* vp,
+                                      JS::Handle<jsid> id,
+                                      JS::MutableHandle<JS::Value> vp,
                                       bool& found)
 {
   nsCOMPtr<nsIDOMWindow> frame = GetSubframeWindow(cx, proxy, id);
   if (!frame) {
     found = false;
     return true;
   }
 
@@ -895,17 +897,18 @@ nsOuterWindowProxy::GetSubframeWindow(JS
   global->EnsureInnerWindow();
   JSObject* obj = global->FastGetGlobalJSObject();
   // This null check fixes a hard-to-reproduce crash that occurs when we
   // get here when we're mid-call to nsDocShell::Destroy. See bug 640904
   // comment 105.
   if (MOZ_UNLIKELY(!obj)) {
     return xpc::Throw(cx, NS_ERROR_FAILURE);
   }
-  *vp = JS::ObjectValue(*obj);
+
+  vp.setObject(*obj);
   return JS_WrapValue(cx, vp);
 }
 
 already_AddRefed<nsIDOMWindow>
 nsOuterWindowProxy::GetSubframeWindow(JSContext *cx,
                                       JS::Handle<JSObject*> proxy,
                                       JS::Handle<jsid> id)
 {
--- a/dom/base/nsHistory.cpp
+++ b/dom/base/nsHistory.cpp
@@ -126,17 +126,17 @@ nsHistory::GetState(JSContext* aCx, Erro
   if (variant) {
     JS::Rooted<JS::Value> jsData(aCx);
     aRv = variant->GetAsJSVal(jsData.address());
 
     if (aRv.Failed()) {
       return JS::UndefinedValue();
     }
 
-    if (!JS_WrapValue(aCx, jsData.address())) {
+    if (!JS_WrapValue(aCx, &jsData)) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return JS::UndefinedValue();
     }
 
     return jsData;
   }
 
   return JS::UndefinedValue();
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1201,25 +1201,30 @@ nsJSContext::SetProperty(JS::Handle<JSOb
 
   Maybe<nsRootedJSValueArray> tempStorage;
 
   JS::Rooted<JSObject*> global(mContext, GetWindowProxy());
   nsresult rv =
     ConvertSupportsTojsvals(aArgs, global, &argc, &argv, tempStorage);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  JS::AutoArrayRooter array(mContext, argc, argv);
+
   // got the arguments, now attach them.
 
   for (uint32_t i = 0; i < argc; ++i) {
-    if (!JS_WrapValue(mContext, &argv[i])) {
+    if (!JS_WrapValue(mContext, array.handleAt(i))) {
       return NS_ERROR_FAILURE;
     }
   }
 
-  JSObject *args = ::JS_NewArrayObject(mContext, argc, argv);
+  JSObject *args = ::JS_NewArrayObject(mContext, argc, array.array);
+  if (!args) {
+    return NS_ERROR_FAILURE;
+  }
   JS::Value vargs = OBJECT_TO_JSVAL(args);
 
   return JS_DefineProperty(mContext, aTarget, aPropName, vargs, NULL, NULL, 0)
     ? NS_OK
     : NS_ERROR_FAILURE;
 }
 
 nsresult
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -301,18 +301,23 @@ nsJSUtils::EvaluateString(JSContext* aCx
       if (aRetValue) {
         *aRetValue = exn;
       }
       JS_ClearPendingException(aCx);
     }
   }
 
   // Wrap the return value into whatever compartment aCx was in.
-  if (aRetValue && !JS_WrapValue(aCx, aRetValue))
-    return NS_ERROR_OUT_OF_MEMORY;
+  if (aRetValue) {
+    JS::Rooted<JS::Value> v(aCx, *aRetValue);
+    if (!JS_WrapValue(aCx, &v)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    *aRetValue = v;
+  }
   return rv;
 }
 
 //
 // nsDOMJSUtils.h
 //
 
 JSObject* GetDefaultScopeFromJSContext(JSContext *cx)
--- a/dom/base/nsStructuredCloneContainer.cpp
+++ b/dom/base/nsStructuredCloneContainer.cpp
@@ -43,22 +43,23 @@ nsStructuredCloneContainer::InitFromJSVa
                                           JSContext* aCx)
 {
   NS_ENSURE_STATE(!mData);
   NS_ENSURE_ARG_POINTER(aCx);
 
   // Make sure that we serialize in the right context.
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   JS::Rooted<JS::Value> jsData(aCx, aData);
-  JS_WrapValue(aCx, jsData.address());
+  bool success = JS_WrapValue(aCx, &jsData);
+  NS_ENSURE_STATE(success);
 
   uint64_t* jsBytes = nullptr;
-  bool success = JS_WriteStructuredClone(aCx, jsData, &jsBytes, &mSize,
-                                         nullptr, nullptr,
-                                         JS::UndefinedHandleValue);
+  success = JS_WriteStructuredClone(aCx, jsData, &jsBytes, &mSize,
+                                    nullptr, nullptr,
+                                    JS::UndefinedHandleValue);
   NS_ENSURE_STATE(success);
   NS_ENSURE_STATE(jsBytes);
 
   // Copy jsBytes into our own buffer.
   mData = (uint64_t*) malloc(mSize);
   if (!mData) {
     mSize = 0;
     mVersion = 0;
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -176,20 +176,22 @@ ErrorResult::ThrowJSException(JSContext*
   }
 }
 
 void
 ErrorResult::ReportJSException(JSContext* cx)
 {
   MOZ_ASSERT(!mMightHaveUnreportedJSException,
              "Why didn't you tell us you planned to handle JS exceptions?");
-  if (JS_WrapValue(cx, &mJSException)) {
-    JS::RootedValue exception(cx, mJSException);
+
+  JS::Rooted<JS::Value> exception(cx, mJSException);
+  if (JS_WrapValue(cx, &exception)) {
     JS_SetPendingException(cx, exception);
   }
+  mJSException = exception;
   // If JS_WrapValue failed, not much we can do about it...  No matter
   // what, go ahead and unroot mJSException.
   JS_RemoveValueRoot(cx, &mJSException);
 }
 
 void
 ErrorResult::ReportJSExceptionFromJSImplementation(JSContext* aCx)
 {
@@ -1558,17 +1560,18 @@ ConcatJSString(JSContext* cx, const char
   }
 
   return JS_ConcatStrings(cx, preString, postString);
 }
 
 bool
 NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
                JS::Handle<JSObject*> obj, const char* pre,
-               const char* post, JS::Value* v)
+               const char* post,
+               JS::MutableHandle<JS::Value> v)
 {
   JS::Rooted<JSPropertyDescriptor> toStringDesc(cx);
   toStringDesc.object().set(nullptr);
   toStringDesc.setAttributes(0);
   toStringDesc.setShortId(0);
   toStringDesc.setGetter(nullptr);
   toStringDesc.setSetter(nullptr);
   toStringDesc.value().set(JS::UndefinedValue());
@@ -1578,17 +1581,17 @@ NativeToString(JSContext* cx, JS::Handle
     return false;
   }
 
   JS::Rooted<JSString*> str(cx);
   {
     JSAutoCompartment ac(cx, obj);
     if (toStringDesc.object()) {
       JS::Rooted<JS::Value> toString(cx, toStringDesc.value());
-      if (!JS_WrapValue(cx, toString.address())) {
+      if (!JS_WrapValue(cx, &toString)) {
         return false;
       }
       MOZ_ASSERT(JS_ObjectIsCallable(cx, &toString.toObject()));
       JS::Rooted<JS::Value> toStringResult(cx);
       if (JS_CallFunctionValue(cx, obj, toString, 0, nullptr,
                                toStringResult.address())) {
         str = toStringResult.toString();
       } else {
@@ -1614,17 +1617,17 @@ NativeToString(JSContext* cx, JS::Handle
       str = ConcatJSString(cx, pre, str, post);
     }
   }
 
   if (!str) {
     return false;
   }
 
-  v->setString(str);
+  v.setString(str);
   return JS_WrapValue(cx, v);
 }
 
 // Dynamically ensure that two objects don't end up with the same reserved slot.
 class MOZ_STACK_CLASS AutoCloneDOMObjectSlotGuard
 {
 public:
   AutoCloneDOMObjectSlotGuard(JSContext* aCx, JSObject* aOld, JSObject* aNew)
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -506,45 +506,45 @@ SetSystemOnlyWrapper(JSObject* obj, nsWr
 // needed.
 MOZ_ALWAYS_INLINE
 bool
 MaybeWrapStringValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(rval.isString());
   JSString* str = rval.toString();
   if (JS::GetGCThingZone(str) != js::GetContextZone(cx)) {
-    return JS_WrapValue(cx, rval.address());
+    return JS_WrapValue(cx, rval);
   }
   return true;
 }
 
 // Make sure to wrap the given object value into the right compartment as
 // needed.  This will work correctly, but possibly slowly, on all objects.
 MOZ_ALWAYS_INLINE
 bool
 MaybeWrapObjectValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(rval.isObject());
 
   JSObject* obj = &rval.toObject();
   if (js::GetObjectCompartment(obj) != js::GetContextCompartment(cx)) {
-    return JS_WrapValue(cx, rval.address());
+    return JS_WrapValue(cx, rval);
   }
 
   // We're same-compartment, but even then we might need to wrap
   // objects specially.  Check for that.
   if (GetSameCompartmentWrapperForDOMBinding(obj)) {
     // We're a new-binding object, and "obj" now points to the right thing
     rval.set(JS::ObjectValue(*obj));
     return true;
   }
 
   // It's not a WebIDL object.  But it might be an XPConnect one, in which case
   // we may need to outerize here, so make sure to call JS_WrapValue.
-  return JS_WrapValue(cx, rval.address());
+  return JS_WrapValue(cx, rval);
 }
 
 // Like MaybeWrapObjectValue, but also allows null
 MOZ_ALWAYS_INLINE
 bool
 MaybeWrapObjectOrNullValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(rval.isObjectOrNull());
@@ -563,17 +563,17 @@ MaybeWrapNonDOMObjectValue(JSContext* cx
   MOZ_ASSERT(!GetDOMClass(&rval.toObject()));
   MOZ_ASSERT(!(js::GetObjectClass(&rval.toObject())->flags &
                JSCLASS_PRIVATE_IS_NSISUPPORTS));
 
   JSObject* obj = &rval.toObject();
   if (js::GetObjectCompartment(obj) == js::GetContextCompartment(cx)) {
     return true;
   }
-  return JS_WrapValue(cx, rval.address());
+  return JS_WrapValue(cx, rval);
 }
 
 // Like MaybeWrapNonDOMObjectValue but allows null
 MOZ_ALWAYS_INLINE
 bool
 MaybeWrapNonDOMObjectOrNullValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(rval.isObjectOrNull());
@@ -677,17 +677,17 @@ WrapNewBindingObject(JSContext* cx, JS::
   bool sameCompartment =
     js::GetObjectCompartment(obj) == js::GetContextCompartment(cx);
   if (sameCompartment && couldBeDOMBinding) {
     WrapNewBindingForSameCompartment(cx, obj, value, rval);
     return true;
   }
 
   rval.set(JS::ObjectValue(*obj));
-  return JS_WrapValue(cx, rval.address());
+  return JS_WrapValue(cx, rval);
 }
 
 // Create a JSObject wrapping "value", for cases when "value" is a
 // non-wrapper-cached object using WebIDL bindings.  "value" must implement a
 // WrapObject() method taking a JSContext and a scope.
 template <class T>
 inline bool
 WrapNewBindingNonWrapperCachedObject(JSContext* cx,
@@ -718,17 +718,17 @@ WrapNewBindingNonWrapperCachedObject(JSC
 
   if (!obj) {
     return false;
   }
 
   // We can end up here in all sorts of compartments, per above.  Make
   // sure to JS_WrapValue!
   rval.set(JS::ObjectValue(*obj));
-  return JS_WrapValue(cx, rval.address());
+  return JS_WrapValue(cx, rval);
 }
 
 // Create a JSObject wrapping "value", for cases when "value" is a
 // non-wrapper-cached owned object using WebIDL bindings.  "value" must implement a
 // WrapObject() method taking a JSContext, a scope, and a boolean outparam that
 // is true if the JSObject took ownership
 template <class T>
 inline bool
@@ -769,17 +769,17 @@ WrapNewBindingNonWrapperCachedOwnedObjec
 
   if (!obj) {
     return false;
   }
 
   // We can end up here in all sorts of compartments, per above.  Make
   // sure to JS_WrapValue!
   rval.set(JS::ObjectValue(*obj));
-  return JS_WrapValue(cx, rval.address());
+  return JS_WrapValue(cx, rval);
 }
 
 // Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
 template <template <typename> class SmartPtr, typename T>
 inline bool
 WrapNewBindingNonWrapperCachedObject(JSContext* cx, JS::Handle<JSObject*> scope,
                                      const SmartPtr<T>& value,
                                      JS::MutableHandle<JS::Value> rval)
@@ -1938,17 +1938,18 @@ void SetXrayExpandoChain(JSObject *obj, 
  *     interface or interface prototype object.
  * pre is a string that should be prefixed to the value.
  * post is a string that should be prefixed to the value.
  * v contains the JSString for the value if the function returns true.
  */
 bool
 NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
                JS::Handle<JSObject*> obj, const char* pre,
-               const char* post, JS::Value* v);
+               const char* post,
+               JS::MutableHandle<JS::Value> v);
 
 HAS_MEMBER(JSBindingFinalized)
 
 template<class T, bool hasCallback=HasJSBindingFinalizedMember<T>::Value>
 struct JSBindingFinalized
 {
   static void Finalized(T* self)
   {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4600,19 +4600,19 @@ def wrapTypeIntoCurrentCompartment(type,
     """
     Take the thing named by "value" and if it contains "any",
     "object", or spidermonkey-interface types inside return a CGThing
     that will wrap them into the current compartment.
     """
     if type.isAny():
         assert not type.nullable()
         if isMember:
+            value = "JS::MutableHandleValue::fromMarkedLocation(&%s)" % value
+        else:
             value = "&" + value
-        else:
-            value = value + ".address()"
         return CGGeneric("if (!JS_WrapValue(cx, %s)) {\n"
                          "  return false;\n"
                          "}" % value)
 
     if type.isObject():
         if isMember:
             value = "JS::MutableHandleObject::fromMarkedLocation(&%s)" % value
         else:
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -75,17 +75,17 @@ ThrowExceptionObject(JSContext* aCx, Exc
 
   // If we stored the original thrown JS value in the exception
   // (see XPCConvert::ConstructException) and we are in a web context
   // (i.e., not chrome), rethrow the original value. This only applies to JS
   // implemented components so we only need to check for this on the main
   // thread.
   if (NS_IsMainThread() && !IsCallerChrome() &&
       aException->StealJSVal(thrown.address())) {
-    if (!JS_WrapValue(aCx, thrown.address())) {
+    if (!JS_WrapValue(aCx, &thrown)) {
       return false;
     }
     JS_SetPendingException(aCx, thrown);
     return true;
   }
 
   JS::Rooted<JSObject*> glob(aCx, JS::CurrentGlobalOrNull(aCx));
   if (!glob) {
--- a/dom/src/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/src/jsurl/nsJSProtocolHandler.cpp
@@ -324,17 +324,17 @@ nsresult nsJSThunk::EvaluateScript(nsICh
         // lose the error), or it might be JS that then proceeds to
         // cause an error of its own (which will also make us lose
         // this error).
         ::JS_ReportPendingException(cx);
     }
 
     // If we took the sandbox path above, v might be in the sandbox
     // compartment.
-    if (!JS_WrapValue(cx, v.address())) {
+    if (!JS_WrapValue(cx, &v)) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
     if (NS_FAILED(rv) || !(v.isString() || v.isUndefined())) {
         return NS_ERROR_MALFORMED_URI;
     } else if (v.isUndefined()) {
         return NS_ERROR_DOM_RETVAL_UNDEFINED;
     } else {
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -191,17 +191,17 @@ jsd_GetValueString(JSDContext* jsdc, JSD
         AutoSaveExceptionState as(cx);
         string = JS_ValueToString(cx, jsdval->val);
     }
 
     JSAutoCompartment ac2(cx, jsdc->glob);
     if(string) {
         stringval = STRING_TO_JSVAL(string);
     }
-    if(!string || !JS_WrapValue(cx, stringval.address())) {
+    if(!string || !JS_WrapValue(cx, &stringval)) {
         return nullptr;
     }
 
     jsdval->string = JSVAL_TO_STRING(stringval);
     if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
         jsdval->string = nullptr;
 
     return jsdval->string;
@@ -248,17 +248,17 @@ jsd_NewValue(JSDContext* jsdc, jsval val
 
     if(JSVAL_IS_GCTHING(val))
     {
         bool ok;
         JSAutoCompartment ac(cx, jsdc->glob);
 
         ok = JS_AddNamedValueRoot(cx, &jsdval->val, "JSDValue");
         if(ok && JSVAL_IS_STRING(val)) {
-            if(!JS_WrapValue(cx, val.address())) {
+            if(!JS_WrapValue(cx, &val)) {
                 ok = false;
             }
         }
 
         if(!ok)
         {
             free(jsdval);
             return nullptr;
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -2315,21 +2315,22 @@ jsdValue::Refresh()
     return NS_OK;
 }
 
 NS_IMETHODIMP
 jsdValue::GetWrappedValue(JSContext* aCx, JS::Value* aRetval)
 {
     ASSERT_VALID_EPHEMERAL;
 
-    *aRetval = JSD_GetValueWrappedJSVal(mCx, mValue);
-    if (!JS_WrapValue(aCx, aRetval)) {
+    JS::RootedValue value(aCx, JSD_GetValueWrappedJSVal(mCx, mValue));
+    if (!JS_WrapValue(aCx, &value)) {
         return NS_ERROR_FAILURE;
     }
 
+    *aRetval = value;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 jsdValue::GetScript(jsdIScript **_rval)
 {
     ASSERT_VALID_EPHEMERAL;
     JSDScript *script = JSD_GetScriptForValue(mCx, mValue);
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -68,17 +68,17 @@ BEGIN_TEST(testChromeBuffer)
                                                         "trusted", 1, &paramName, bytes, strlen(bytes),
                                                         "", 0));
             trusted_fun = JS_GetFunctionObject(fun);
             if (!JS_AddNamedObjectRoot(cx, &trusted_fun, "trusted-function"))
                 return false;
         }
 
         JS::RootedValue v(cx, JS::ObjectValue(*trusted_fun));
-        CHECK(JS_WrapValue(cx, v.address()));
+        CHECK(JS_WrapValue(cx, &v));
 
         const char *paramName = "trusted";
         const char *bytes = "try {                                      "
                             "    return untrusted(trusted);             "
                             "} catch (e) {                              "
                             "    try {                                  "
                             "        return trusted(100);               "
                             "    } catch(e) {                           "
@@ -109,17 +109,17 @@ BEGIN_TEST(testChromeBuffer)
             JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&trusted_glob);
             CHECK(fun = JS_CompileFunctionForPrincipals(cx, global, &system_principals,
                                                         "trusted", 1, &paramName, bytes, strlen(bytes),
                                                         "", 0));
             trusted_fun = JS_GetFunctionObject(fun);
         }
 
         JS::RootedValue v(cx, JS::ObjectValue(*trusted_fun));
-        CHECK(JS_WrapValue(cx, v.address()));
+        CHECK(JS_WrapValue(cx, &v));
 
         const char *paramName = "trusted";
         const char *bytes = "try {                                      "
                             "  return untrusted(trusted);               "
                             "} catch (e) {                              "
                             "  return trusted(untrusted);               "
                             "}                                          ";
         CHECK(fun = JS_CompileFunction(cx, global, "untrusted", 1, &paramName,
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1150,26 +1150,22 @@ JS_WrapObject(JSContext *cx, MutableHand
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     if (objp)
         JS::ExposeGCThingToActiveJS(objp, JSTRACE_OBJECT);
     return cx->compartment()->wrap(cx, objp);
 }
 
 JS_PUBLIC_API(bool)
-JS_WrapValue(JSContext *cx, jsval *vp)
+JS_WrapValue(JSContext *cx, MutableHandleValue vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    if (vp)
-        JS::ExposeValueToActiveJS(*vp);
-    RootedValue value(cx, *vp);
-    bool ok = cx->compartment()->wrap(cx, &value);
-    *vp = value.get();
-    return ok;
+    JS::ExposeValueToActiveJS(vp);
+    return cx->compartment()->wrap(cx, vp);
 }
 
 JS_PUBLIC_API(bool)
 JS_WrapId(JSContext *cx, jsid *idp)
 {
   AssertHeapIsIdle(cx);
   CHECK_REQUEST(cx);
   if (idp) {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1756,17 +1756,17 @@ JS_SetCompartmentPrivate(JSCompartment *
 
 extern JS_PUBLIC_API(void *)
 JS_GetCompartmentPrivate(JSCompartment *compartment);
 
 extern JS_PUBLIC_API(bool)
 JS_WrapObject(JSContext *cx, JS::MutableHandleObject objp);
 
 extern JS_PUBLIC_API(bool)
-JS_WrapValue(JSContext *cx, jsval *vp);
+JS_WrapValue(JSContext *cx, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
 JS_WrapId(JSContext *cx, jsid *idp);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_TransplantObject(JSContext *cx, JS::Handle<JSObject*> origobj, JS::Handle<JSObject*> target);
 
 extern JS_PUBLIC_API(bool)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1099,17 +1099,17 @@ Evaluate(JSContext *cx, unsigned argc, j
                     return false;
                 args.rval().setString(str);
                 return true;
             }
             return false;
         }
     }
 
-    return JS_WrapValue(cx, vp);
+    return JS_WrapValue(cx, args.rval());
 }
 
 static JSString *
 FileAsString(JSContext *cx, const char *pathname)
 {
     FILE *file;
     RootedString str(cx);
     size_t len, cc;
@@ -3772,17 +3772,17 @@ DecompileThisScript(JSContext *cx, unsig
     {
         JSAutoCompartment ac(cx, script);
         JSString *result = JS_DecompileScript(cx, script, "test", 0);
         if (!result)
             return false;
         args.rval().setString(result);
     }
 
-    return JS_WrapValue(cx, vp);
+    return JS_WrapValue(cx, args.rval());
 }
 
 static bool
 ThisFilename(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedScript script (cx);
     if (!JS_DescribeScriptedCaller(cx, &script, nullptr) || !script->filename()) {
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -1069,17 +1069,17 @@ mozJSComponentLoader::Import(const nsACS
         if (targetVal.isObject()) {
             // If we're passing in something like a content DOM window, chances
             // are the caller expects the properties to end up on the object
             // proper and not on the Xray holder. This is dubious, but can be used
             // during testing. Given that dumb callers can already leak JSMs into
             // content by passing a raw content JS object (where Xrays aren't
             // possible), we aim for consistency here. Waive xray.
             if (WrapperFactory::IsXrayWrapper(&targetVal.toObject()) &&
-                !WrapperFactory::WaiveXrayAndWrap(cx, targetVal.address()))
+                !WrapperFactory::WaiveXrayAndWrap(cx, &targetVal))
             {
                 return NS_ERROR_FAILURE;
             }
             targetObject = &targetVal.toObject();
         } else if (!targetVal.isNull()) {
             // If targetVal isNull(), we actually want to leave targetObject null.
             // Not doing so breaks |make package|.
             return ReportOnCaller(cx, ERROR_SCOPE_OBJ,
@@ -1202,17 +1202,17 @@ mozJSComponentLoader::ImportInto(const n
                                &newEntry->location, true, &exception);
 
         mInProgressImports.Remove(key);
 
         if (NS_FAILED(rv)) {
             if (!exception.isUndefined()) {
                 // An exception was thrown during compilation. Propagate it
                 // out to our caller so they can report it.
-                if (!JS_WrapValue(callercx, exception.address()))
+                if (!JS_WrapValue(callercx, &exception))
                     return NS_ERROR_OUT_OF_MEMORY;
                 JS_SetPendingException(callercx, exception);
                 return NS_OK;
             }
 
             // Something failed, but we don't know what it is, guess.
             return NS_ERROR_FILE_NOT_FOUND;
         }
@@ -1276,17 +1276,17 @@ mozJSComponentLoader::ImportInto(const n
                     return NS_ERROR_FAILURE;
                 return ReportOnCaller(cxhelper, ERROR_GETTING_SYMBOL,
                                       PromiseFlatCString(aLocation).get(),
                                       bytes.ptr());
             }
 
             JSAutoCompartment target_ac(mContext, targetObj);
 
-            if (!JS_WrapValue(mContext, value.address()) ||
+            if (!JS_WrapValue(mContext, &value) ||
                 !JS_SetPropertyById(mContext, targetObj, symbolId, value)) {
                 JSAutoByteString bytes(mContext, JSID_TO_STRING(symbolId));
                 if (!bytes)
                     return NS_ERROR_FAILURE;
                 return ReportOnCaller(cxhelper, ERROR_SETTING_SYMBOL,
                                       PromiseFlatCString(aLocation).get(),
                                       bytes.ptr());
             }
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -305,27 +305,29 @@ mozJSSubScriptLoader::LoadSubScript(cons
         return rv;
 
     if (function) {
         script = JS_GetFunctionScript(cx, function);
     }
 
     loader->NoteSubScript(script, targetObj);
 
+    RootedValue rval(cx);
     bool ok = false;
     if (function) {
-        ok = JS_CallFunction(cx, targetObj, function, 0, nullptr, retval);
+        ok = JS_CallFunction(cx, targetObj, function, 0, nullptr, rval.address());
     } else {
-        ok = JS_ExecuteScriptVersion(cx, targetObj, script, retval, version);
+        ok = JS_ExecuteScriptVersion(cx, targetObj, script, rval.address(), version);
     }
 
     if (ok) {
         JSAutoCompartment rac(cx, result_obj);
-        if (!JS_WrapValue(cx, retval))
+        if (!JS_WrapValue(cx, &rval))
             return NS_ERROR_UNEXPECTED;
+        *retval = rval;
     }
 
     if (cache && ok && writeScript) {
         WriteCachedScript(cache, cachePath, cx, mSystemPrincipal, script);
     }
 
     return NS_OK;
 }
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -300,17 +300,17 @@ ExportFunction(JSContext *cx, unsigned a
         // we have to add it to the target scope as a property.
         if (!JS_DefinePropertyById(cx, targetScope, id, args.rval(),
                                    JS_PropertyStub, JS_StrictPropertyStub,
                                    JSPROP_ENUMERATE))
             return false;
     }
 
     // Finally we have to re-wrap the exported function back to the caller compartment.
-    if (!JS_WrapValue(cx, args.rval().address()))
+    if (!JS_WrapValue(cx, args.rval()))
         return false;
 
     return true;
 }
 
 static bool
 GetFilenameAndLineNumber(JSContext *cx, nsACString &filename, unsigned &lineno)
 {
@@ -977,17 +977,18 @@ xpc::GlobalProperties::Define(JSContext 
     if (btoa &&
         !JS_DefineFunction(cx, obj, "btoa", Btoa, 1, 0))
         return false;
 
     return true;
 }
 
 nsresult
-xpc::CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, SandboxOptions& options)
+xpc::CreateSandboxObject(JSContext *cx, MutableHandleValue vp, nsISupports *prinOrSop,
+                         SandboxOptions& options)
 {
     // Create the sandbox global object
     nsresult rv;
     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
     if (NS_FAILED(rv))
         return NS_ERROR_XPC_UNEXPECTED;
 
     nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(prinOrSop);
@@ -1037,17 +1038,17 @@ xpc::CreateSandboxObject(JSContext *cx, 
 
         if (options.proto) {
             bool ok = JS_WrapObject(cx, &options.proto);
             if (!ok)
                 return NS_ERROR_XPC_UNEXPECTED;
 
             if (xpc::WrapperFactory::IsXrayWrapper(options.proto) && !options.wantXrays) {
                 RootedValue v(cx, ObjectValue(*options.proto));
-                if (!xpc::WrapperFactory::WaiveXrayAndWrap(cx, v.address()))
+                if (!xpc::WrapperFactory::WaiveXrayAndWrap(cx, &v))
                     return NS_ERROR_FAILURE;
                 options.proto = &v.toObject();
             }
 
             // Now check what sort of thing we've got in |proto|
             JSObject *unwrappedProto = js::UncheckedUnwrap(options.proto, false);
             const js::Class *unwrappedClass = js::GetObjectClass(unwrappedProto);
             if (IS_WN_CLASS(unwrappedClass) ||
@@ -1089,26 +1090,25 @@ xpc::CreateSandboxObject(JSContext *cx, 
              !JS_DefineFunction(cx, sandbox, "evalInWindow", EvalInWindow, 2, 0) ||
              !JS_DefineFunction(cx, sandbox, "createObjectIn", CreateObjectIn, 2, 0)))
             return NS_ERROR_XPC_UNEXPECTED;
 
         if (!options.globalProperties.Define(cx, sandbox))
             return NS_ERROR_XPC_UNEXPECTED;
     }
 
-    if (vp) {
-        // We have this crazy behavior where wantXrays=false also implies that the
-        // returned sandbox is implicitly waived. We've stopped advertising it, but
-        // keep supporting it for now.
-        *vp = OBJECT_TO_JSVAL(sandbox);
-        if (options.wantXrays && !JS_WrapValue(cx, vp))
-            return NS_ERROR_UNEXPECTED;
-        if (!options.wantXrays && !xpc::WrapperFactory::WaiveXrayAndWrap(cx, vp))
-            return NS_ERROR_UNEXPECTED;
-    }
+
+    // We have this crazy behavior where wantXrays=false also implies that the
+    // returned sandbox is implicitly waived. We've stopped advertising it, but
+    // keep supporting it for now.
+    vp.setObject(*sandbox);
+    if (options.wantXrays && !JS_WrapValue(cx, vp))
+        return NS_ERROR_UNEXPECTED;
+    if (!options.wantXrays && !xpc::WrapperFactory::WaiveXrayAndWrap(cx, vp))
+        return NS_ERROR_UNEXPECTED;
 
     // Set the location information for the new global, so that tools like
     // about:memory may use that information
     xpc::SetLocationForGlobal(sandbox, options.sandboxName);
 
     xpc::SetSandboxMetadata(cx, sandbox, options.metadata);
 
     JS_FireOnNewGlobalObject(cx, sandbox);
@@ -1504,17 +1504,17 @@ nsXPCComponents_utils_Sandbox::CallOrCon
 
     SandboxOptions options(cx, optionsObject);
     if (calledWithOptions && !options.Parse())
         return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
 
     if (NS_FAILED(AssembleSandboxMemoryReporterName(cx, options.sandboxName)))
         return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
 
-    rv = CreateSandboxObject(cx, args.rval().address(), prinOrSop, options);
+    rv = CreateSandboxObject(cx, args.rval(), prinOrSop, options);
 
     if (NS_FAILED(rv))
         return ThrowAndFail(rv, cx, _retval);
 
     *_retval = true;
     return NS_OK;
 }
 
@@ -1642,29 +1642,29 @@ xpc::EvalInSandbox(JSContext *cx, Handle
     //
     // Alright, we're back on the caller's cx. If an error occured, try to
     // wrap and set the exception. Otherwise, wrap the return value.
     //
 
     if (!ok) {
         // If we end up without an exception, it was probably due to OOM along
         // the way, in which case we thow. Otherwise, wrap it.
-        if (exn.isUndefined() || !JS_WrapValue(cx, exn.address()))
+        if (exn.isUndefined() || !JS_WrapValue(cx, &exn))
             return NS_ERROR_OUT_OF_MEMORY;
 
         // Set the exception on our caller's cx.
         JS_SetPendingException(cx, exn);
         return NS_ERROR_FAILURE;
     }
 
     // Transitively apply Xray waivers if |sb| was waived.
     if (waiveXray) {
-        ok = xpc::WrapperFactory::WaiveXrayAndWrap(cx, v.address());
+        ok = xpc::WrapperFactory::WaiveXrayAndWrap(cx, &v);
     } else {
-        ok = JS_WrapValue(cx, v.address());
+        ok = JS_WrapValue(cx, &v);
     }
     NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
 
     // Whew!
     rval.set(v);
     return NS_OK;
 }
 
@@ -1705,22 +1705,23 @@ CloningFunctionForwarder(JSContext *cx, 
             }
         }
 
         // JS API does not support any JSObject to JSFunction conversion,
         // so let's use JS_CallFunctionValue instead.
         RootedValue functionVal(cx);
         functionVal.setObject(*origFunObj);
 
-        if (!JS_CallFunctionValue(cx, nullptr, functionVal, args.length(), args.array(), vp))
+        if (!JS_CallFunctionValue(cx, nullptr, functionVal, args.length(), args.array(),
+                                  args.rval().address()))
             return false;
     }
 
     // Return value must be wrapped.
-    return JS_WrapValue(cx, vp);
+    return JS_WrapValue(cx, args.rval());
 }
 
 bool
 xpc::NewFunctionForwarder(JSContext *cx, HandleId id, HandleObject callable, bool doclone,
                           MutableHandleValue vp)
 {
     JSFunction *fun = js::NewFunctionByIdWithReserved(cx, doclone ? CloningFunctionForwarder :
                                                                     NonCloningFunctionForwarder,
@@ -1743,17 +1744,17 @@ xpc::GetSandboxMetadata(JSContext *cx, H
     MOZ_ASSERT(IsSandbox(sandbox));
 
     RootedValue metadata(cx);
     {
       JSAutoCompartment ac(cx, sandbox);
       metadata = JS_GetReservedSlot(sandbox, XPCONNECT_SANDBOX_CLASS_METADATA_SLOT);
     }
 
-    if (!JS_WrapValue(cx, metadata.address()))
+    if (!JS_WrapValue(cx, &metadata))
         return NS_ERROR_UNEXPECTED;
 
     rval.set(metadata);
     return NS_OK;
 }
 
 nsresult
 xpc::SetSandboxMetadata(JSContext *cx, HandleObject sandbox, HandleValue metadataArg)
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3208,38 +3208,38 @@ nsXPCComponents_Utils::SetWantXrays(cons
 NS_IMETHODIMP
 nsXPCComponents_Utils::GetComponentsForScope(const jsval &vscope, JSContext *cx,
                                              jsval *rval)
 {
     if (!vscope.isObject())
         return NS_ERROR_INVALID_ARG;
     JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
     XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
-    JSObject *components = scope->GetComponentsJSObject();
+    RootedObject components(cx, scope->GetComponentsJSObject());
     if (!components)
         return NS_ERROR_FAILURE;
+    if (!JS_WrapObject(cx, &components))
+        return NS_ERROR_FAILURE;
     *rval = ObjectValue(*components);
-    if (!JS_WrapValue(cx, rval))
-        return NS_ERROR_FAILURE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::Dispatch(const jsval &runnableArg, const jsval &scope,
                                 JSContext *cx)
 {
     // Enter the given compartment, if any, and rewrap runnable.
     Maybe<JSAutoCompartment> ac;
     RootedValue runnable(cx, runnableArg);
     if (scope.isObject()) {
         JSObject *scopeObj = js::UncheckedUnwrap(&scope.toObject());
         if (!scopeObj)
             return NS_ERROR_FAILURE;
         ac.construct(cx, scopeObj);
-        if (!JS_WrapValue(cx, runnable.address()))
+        if (!JS_WrapValue(cx, &runnable))
             return NS_ERROR_FAILURE;
     }
 
     // Get an XPCWrappedJS for |runnable|.
     if (!runnable.isObject())
         return NS_ERROR_INVALID_ARG;
 
     nsCOMPtr<nsIRunnable> run;
@@ -3338,33 +3338,35 @@ nsXPCComponents_Utils::IsXrayWrapper(con
     *aRetval =
         obj.isObject() && xpc::WrapperFactory::IsXrayWrapper(&obj.toObject());
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::WaiveXrays(const Value &aVal, JSContext *aCx, jsval *aRetval)
 {
-    *aRetval = aVal;
-    if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, aRetval))
+    RootedValue value(aCx, aVal);
+    if (!xpc::WrapperFactory::WaiveXrayAndWrap(aCx, &value))
         return NS_ERROR_FAILURE;
+    *aRetval = value;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::UnwaiveXrays(const Value &aVal, JSContext *aCx, jsval *aRetval)
 {
     if (!aVal.isObject()) {
         *aRetval = aVal;
         return NS_OK;
     }
 
-    *aRetval = ObjectValue(*js::UncheckedUnwrap(&aVal.toObject()));
-    if (!JS_WrapValue(aCx, aRetval))
+    RootedObject obj(aCx, js::UncheckedUnwrap(&aVal.toObject()));
+    if (!JS_WrapObject(aCx, &obj))
         return NS_ERROR_FAILURE;
+    *aRetval = ObjectValue(*obj);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::GetClassName(const Value &aObj, bool aUnwrap, JSContext *aCx, char **aRv)
 {
     if (!aObj.isObject())
         return NS_ERROR_INVALID_ARG;
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -150,17 +150,17 @@ XPCConvert::NativeData2JS(MutableHandleV
                 return false;
             d.setString(str);
             break;
         }
 
     case nsXPTType::T_JSVAL :
         {
             d.set(*((Value*)s));
-            if (!JS_WrapValue(cx, d.address()))
+            if (!JS_WrapValue(cx, d))
                 return false;
             break;
         }
 
     default:
 
         // set the default result
         d.setNull();
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -3373,20 +3373,17 @@ XPCJSRuntime::RemoveContextCallback(xpcC
 JSObject *
 XPCJSRuntime::GetJunkScope()
 {
     if (!mJunkScope) {
         AutoSafeJSContext cx;
         SandboxOptions options;
         options.sandboxName.AssignASCII("XPConnect Junk Compartment");
         RootedValue v(cx);
-        nsresult rv = CreateSandboxObject(cx, v.address(),
-                                          nsContentUtils::GetSystemPrincipal(),
-                                          options);
-
+        nsresult rv = CreateSandboxObject(cx, &v, nsContentUtils::GetSystemPrincipal(), options);
         NS_ENSURE_SUCCESS(rv, nullptr);
 
         mJunkScope = js::UncheckedUnwrap(&v.toObject());
         JS_AddNamedObjectRoot(cx, &mJunkScope, "XPConnect Junk Compartment");
     }
     return mJunkScope;
 }
 
--- a/js/xpconnect/src/XPCVariant.cpp
+++ b/js/xpconnect/src/XPCVariant.cpp
@@ -386,29 +386,29 @@ XPCVariant::VariantDataToJS(nsIVariant* 
     RootedValue realVal(cx);
     nsresult rv = variant->GetAsJSVal(realVal.address());
 
     if (NS_SUCCEEDED(rv) &&
         (JSVAL_IS_PRIMITIVE(realVal) ||
          type == nsIDataType::VTYPE_ARRAY ||
          type == nsIDataType::VTYPE_EMPTY_ARRAY ||
          type == nsIDataType::VTYPE_ID)) {
-        if (!JS_WrapValue(cx, realVal.address()))
+        if (!JS_WrapValue(cx, &realVal))
             return false;
         pJSVal.set(realVal);
         return true;
     }
 
     nsCOMPtr<XPCVariant> xpcvariant = do_QueryInterface(variant);
     if (xpcvariant && xpcvariant->mReturnRawObject) {
         MOZ_ASSERT(type == nsIDataType::VTYPE_INTERFACE ||
                    type == nsIDataType::VTYPE_INTERFACE_IS,
                    "Weird variant");
 
-        if (!JS_WrapValue(cx, realVal.address()))
+        if (!JS_WrapValue(cx, &realVal))
             return false;
         pJSVal.set(realVal);
         return true;
     }
 
     // else, it's an object and we really need to double wrap it if we've
     // already decided that its 'natural' type is as some sort of interface.
 
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -129,32 +129,34 @@ GetDoubleWrappedJSObject(XPCCallContext&
 }
 
 // This is the getter native function we use to handle 'wrappedJSObject' for
 // double wrapped JSObjects.
 
 static bool
 XPC_WN_DoubleWrappedGetter(JSContext *cx, unsigned argc, jsval *vp)
 {
+    CallArgs args = CallArgsFromVp(argc, vp);
+
     RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
     if (!obj)
         return false;
 
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     MOZ_ASSERT(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
 
     RootedObject realObject(cx, GetDoubleWrappedJSObject(ccx, wrapper));
     if (!realObject) {
         // This is pretty unexpected at this point. The object originally
         // responded to this get property call and now gives no object.
         // XXX Should this throw something at the caller?
-        *vp = JSVAL_NULL;
+        args.rval().setNull();
         return true;
     }
 
     // It is a double wrapped object. Figure out if the caller
     // is allowed to see it.
 
     nsIXPCSecurityManager* sm = nsXPConnect::XPConnect()->GetDefaultSecurityManager();
     if (sm) {
@@ -173,18 +175,19 @@ XPC_WN_DoubleWrappedGetter(JSContext *cx
                                     wrapper->GetIdentityObject(),
                                     wrapper->GetClassInfo(), id,
                                     wrapper->GetSecurityInfoAddr()))) {
                 // The SecurityManager should have set an exception.
                 return false;
             }
         }
     }
-    *vp = OBJECT_TO_JSVAL(realObject);
-    return JS_WrapValue(cx, vp);
+
+    args.rval().setObject(*realObject);
+    return JS_WrapValue(cx, args.rval());
 }
 
 /***************************************************************************/
 
 // This is our shared function to define properties on our JSObjects.
 
 /*
  * NOTE:
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -255,18 +255,18 @@ XPCWrappedNativeScope::EnsureXBLScope(JS
     nsIPrincipal *principal = GetPrincipal();
     nsCOMPtr<nsIExpandedPrincipal> ep;
     MOZ_ASSERT(!(ep = do_QueryInterface(principal)));
     nsTArray< nsCOMPtr<nsIPrincipal> > principalAsArray(1);
     principalAsArray.AppendElement(principal);
     ep = new nsExpandedPrincipal(principalAsArray);
 
     // Create the sandbox.
-    JS::RootedValue v(cx, JS::UndefinedValue());
-    nsresult rv = CreateSandboxObject(cx, v.address(), ep, options);
+    RootedValue v(cx);
+    nsresult rv = CreateSandboxObject(cx, &v, ep, options);
     NS_ENSURE_SUCCESS(rv, nullptr);
     mXBLScope = &v.toObject();
 
     // Tag it.
     EnsureCompartmentPrivate(js::UncheckedUnwrap(mXBLScope))->scope->mIsXBLScope = true;
 
     // Good to go!
     return mXBLScope;
--- a/js/xpconnect/src/XPCWrapper.cpp
+++ b/js/xpconnect/src/XPCWrapper.cpp
@@ -32,39 +32,39 @@ UnwrapNW(JSContext *cx, unsigned argc, j
 
   JS::RootedValue v(cx, JS_ARGV(cx, vp)[0]);
   if (!v.isObject() || !js::IsWrapper(&v.toObject())) {
     JS_SET_RVAL(cx, vp, v);
     return true;
   }
 
   if (AccessCheck::wrapperSubsumes(&v.toObject())) {
-    bool ok = xpc::WrapperFactory::WaiveXrayAndWrap(cx, v.address());
+    bool ok = xpc::WrapperFactory::WaiveXrayAndWrap(cx, &v);
     NS_ENSURE_TRUE(ok, false);
   }
 
   JS_SET_RVAL(cx, vp, v);
   return true;
 }
 
 static bool
 XrayWrapperConstructor(JSContext *cx, unsigned argc, jsval *vp)
 {
-  if (argc == 0) {
+  JS::CallArgs args = CallArgsFromVp(argc, vp);
+  if (args.length() == 0) {
     return ThrowException(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx);
   }
 
-  JS::RootedValue v(cx, JS_ARGV(cx, vp)[0]);
-  if (!v.isObject()) {
-    JS_SET_RVAL(cx, vp, v);
+  if (!args[0].isObject()) {
+    args.rval().set(args[0]);
     return true;
   }
 
-  *vp = JS::ObjectValue(*js::UncheckedUnwrap(&v.toObject()));
-  return JS_WrapValue(cx, vp);
+  args.rval().setObject(*js::UncheckedUnwrap(&args[0].toObject()));
+  return JS_WrapValue(cx, args.rval());
 }
 // static
 bool
 AttachNewConstructorObject(JSContext *aCx, JS::HandleObject aGlobalObject)
 {
   // Pushing a JSContext calls ActivateDebugger which calls this function, so
   // we can't use an AutoJSContext here until JSD is gone.
   JSAutoCompartment ac(aCx, aGlobalObject);
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -908,20 +908,19 @@ nsXPConnect::ClearAllWrappedNativeSecuri
 }
 
 NS_IMETHODIMP
 nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal,
                            nsIXPConnectJSObjectHolder **_retval)
 {
     *_retval = nullptr;
 
-    RootedValue rval(cx, JSVAL_VOID);
-
+    RootedValue rval(cx);
     SandboxOptions options;
-    nsresult rv = CreateSandboxObject(cx, rval.address(), principal, options);
+    nsresult rv = CreateSandboxObject(cx, &rval, principal, options);
     MOZ_ASSERT(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
                "Bad return value from xpc_CreateSandboxObject()!");
 
     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(rval)) {
         *_retval = XPCJSObjectHolder::newHolder(JSVAL_TO_OBJECT(rval));
         NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
 
         NS_ADDREF(*_retval);
--- a/js/xpconnect/src/qsgen.py
+++ b/js/xpconnect/src/qsgen.py
@@ -674,17 +674,17 @@ resultConvTemplates = {
     '[astring]':
         "    return xpc::StringToJsval(cx, result, ${jsvalPtr});\n",
 
     '[domstring]':
         "    return xpc::StringToJsval(cx, result, ${jsvalPtr});\n",
 
     '[jsval]':
         "    ${jsvalPtr}.set(result);\n"
-        "    return JS_WrapValue(cx, ${jsvalPtr}.address());\n"
+        "    return JS_WrapValue(cx, ${jsvalPtr});\n"
     }
 
 def isVariantType(t):
     return isSpecificInterfaceType(t, 'nsIVariant')
 
 def writeResultConv(f, type, jsvalPtr, jsvalRef):
     """ Emit code to convert the C++ variable `result` to a jsval.
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3687,17 +3687,17 @@ CreateGlobalObject(JSContext *cx, const 
 // system using EvalInSandbox(). Takes the JSContext on which to
 // do setup etc on, puts the sandbox object in *vp (which must be
 // rooted by the caller), and uses the principal that's either
 // directly passed in prinOrSop or indirectly as an
 // nsIScriptObjectPrincipal holding the principal. If no principal is
 // reachable through prinOrSop, a new null principal will be created
 // and used.
 nsresult
-CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop,
+CreateSandboxObject(JSContext *cx, JS::MutableHandleValue vp, nsISupports *prinOrSop,
                     xpc::SandboxOptions& options);
 // Helper for evaluating scripts in a sandbox object created with
 // CreateSandboxObject(). The caller is responsible of ensuring
 // that *rval doesn't get collected during the call or usage after the
 // call. This helper will use filename and lineNo for error reporting,
 // and if no filename is provided it will use the codebase from the
 // principal and line number 1 as a fallback. if returnStringOnly is
 // true, then the result in *rval, or the exception in cx->exception
--- a/js/xpconnect/wrappers/WaiveXrayWrapper.cpp
+++ b/js/xpconnect/wrappers/WaiveXrayWrapper.cpp
@@ -13,24 +13,24 @@ using namespace JS;
 
 namespace xpc {
 
 static bool
 WaiveAccessors(JSContext *cx, JS::MutableHandle<JSPropertyDescriptor> desc)
 {
     if (desc.hasGetterObject() && desc.getterObject()) {
         RootedValue v(cx, JS::ObjectValue(*desc.getterObject()));
-        if (!WrapperFactory::WaiveXrayAndWrap(cx, v.address()))
+        if (!WrapperFactory::WaiveXrayAndWrap(cx, &v))
             return false;
         desc.setGetterObject(&v.toObject());
     }
 
     if (desc.hasSetterObject() && desc.setterObject()) {
         RootedValue v(cx, JS::ObjectValue(*desc.setterObject()));
-        if (!WrapperFactory::WaiveXrayAndWrap(cx, v.address()))
+        if (!WrapperFactory::WaiveXrayAndWrap(cx, &v))
             return false;
         desc.setSetterObject(&v.toObject());
     }
     return true;
 }
 
 WaiveXrayWrapper::WaiveXrayWrapper(unsigned flags) : js::CrossCompartmentWrapper(flags)
 {
@@ -41,54 +41,54 @@ WaiveXrayWrapper::~WaiveXrayWrapper()
 }
 
 bool
 WaiveXrayWrapper::getPropertyDescriptor(JSContext *cx, HandleObject wrapper,
                                         HandleId id, JS::MutableHandle<JSPropertyDescriptor> desc,
                                         unsigned flags)
 {
     return CrossCompartmentWrapper::getPropertyDescriptor(cx, wrapper, id, desc, flags) &&
-           WrapperFactory::WaiveXrayAndWrap(cx, desc.value().address()) && WaiveAccessors(cx, desc);
+           WrapperFactory::WaiveXrayAndWrap(cx, desc.value()) && WaiveAccessors(cx, desc);
 }
 
 bool
 WaiveXrayWrapper::getOwnPropertyDescriptor(JSContext *cx, HandleObject wrapper,
                                            HandleId id, JS::MutableHandle<JSPropertyDescriptor> desc,
                                            unsigned flags)
 {
     return CrossCompartmentWrapper::getOwnPropertyDescriptor(cx, wrapper, id, desc, flags) &&
-           WrapperFactory::WaiveXrayAndWrap(cx, desc.value().address()) && WaiveAccessors(cx, desc);
+           WrapperFactory::WaiveXrayAndWrap(cx, desc.value()) && WaiveAccessors(cx, desc);
 }
 
 bool
 WaiveXrayWrapper::get(JSContext *cx, HandleObject wrapper,
                       HandleObject receiver, HandleId id,
                       MutableHandleValue vp)
 {
     return CrossCompartmentWrapper::get(cx, wrapper, receiver, id, vp) &&
-           WrapperFactory::WaiveXrayAndWrap(cx, vp.address());
+           WrapperFactory::WaiveXrayAndWrap(cx, vp);
 }
 
 bool
 WaiveXrayWrapper::call(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
 {
     return CrossCompartmentWrapper::call(cx, wrapper, args) &&
-           WrapperFactory::WaiveXrayAndWrap(cx, args.rval().address());
+           WrapperFactory::WaiveXrayAndWrap(cx, args.rval());
 }
 
 bool
 WaiveXrayWrapper::construct(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
 {
     return CrossCompartmentWrapper::construct(cx, wrapper, args) &&
-           WrapperFactory::WaiveXrayAndWrap(cx, args.rval().address());
+           WrapperFactory::WaiveXrayAndWrap(cx, args.rval());
 }
 
 // NB: This is important as the other side of a handshake with FieldGetter. See
 // nsXBLProtoImplField.cpp.
 bool
 WaiveXrayWrapper::nativeCall(JSContext *cx, JS::IsAcceptableThis test,
                              JS::NativeImpl impl, JS::CallArgs args)
 {
     return CrossCompartmentWrapper::nativeCall(cx, test, impl, args) &&
-           WrapperFactory::WaiveXrayAndWrap(cx, args.rval().address());
+           WrapperFactory::WaiveXrayAndWrap(cx, args.rval());
 }
 
 }
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -539,25 +539,25 @@ WrapperFactory::WrapForSameCompartment(J
     return wrapper;
 }
 
 // Call WaiveXrayAndWrap when you have a JS object that you don't want to be
 // wrapped in an Xray wrapper. cx->compartment is the compartment that will be
 // using the returned object. If the object to be wrapped is already in the
 // correct compartment, then this returns the unwrapped object.
 bool
-WrapperFactory::WaiveXrayAndWrap(JSContext *cx, jsval *vp)
+WrapperFactory::WaiveXrayAndWrap(JSContext *cx, MutableHandleValue vp)
 {
-    if (JSVAL_IS_PRIMITIVE(*vp))
+    if (vp.isPrimitive())
         return JS_WrapValue(cx, vp);
 
-    JSObject *obj = js::UncheckedUnwrap(JSVAL_TO_OBJECT(*vp));
+    JSObject *obj = js::UncheckedUnwrap(&vp.toObject());
     MOZ_ASSERT(!js::IsInnerObject(obj));
     if (js::IsObjectInContextCompartment(obj, cx)) {
-        *vp = OBJECT_TO_JSVAL(obj);
+        vp.setObject(*obj);
         return true;
     }
 
     // Even though waivers have no effect on access by scopes that don't subsume
     // the underlying object, good defense-in-depth dictates that we should avoid
     // handing out waivers to callers that can't use them. The transitive waiving
     // machinery unconditionally calls WaiveXrayAndWrap on return values from
     // waived functions, even though the return value might be not be same-origin
@@ -565,17 +565,17 @@ WrapperFactory::WaiveXrayAndWrap(JSConte
     // |cx|, we should check whether the caller has any business with waivers
     // to things in |obj|'s compartment.
     JSCompartment *target = js::GetContextCompartment(cx);
     JSCompartment *origin = js::GetObjectCompartment(obj);
     obj = AccessCheck::subsumes(target, origin) ? WaiveXray(cx, obj) : obj;
     if (!obj)
         return false;
 
-    *vp = OBJECT_TO_JSVAL(obj);
+    vp.setObject(*obj);
     return JS_WrapValue(cx, vp);
 }
 
 JSObject *
 WrapperFactory::WrapSOWObject(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     RootedObject proto(cx);
--- a/js/xpconnect/wrappers/WrapperFactory.h
+++ b/js/xpconnect/wrappers/WrapperFactory.h
@@ -58,17 +58,17 @@ class WrapperFactory {
                             JS::HandleObject parent,
                             unsigned flags);
 
     // Wrap an object for same-compartment access.
     static JSObject *WrapForSameCompartment(JSContext *cx,
                                             JS::HandleObject obj);
 
     // Wrap wrapped object into a waiver wrapper and then re-wrap it.
-    static bool WaiveXrayAndWrap(JSContext *cx, jsval *vp);
+    static bool WaiveXrayAndWrap(JSContext *cx, JS::MutableHandleValue vp);
 
     // Wrap a (same compartment) object in a SOW.
     static JSObject *WrapSOWObject(JSContext *cx, JSObject *obj);
 
     // Return true if this is a Components object.
     static bool IsComponentsObject(JSObject *obj);
 
     // Wrap a (same compartment) Components object.
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -765,17 +765,17 @@ XPCWrappedNativeXrayTraits::resolveNativ
         // Without a wrapper the function would live on the prototype. Since we
         // don't have one, we have to avoid calling the scriptable helper's
         // GetProperty method for this property, so stub out the getter and
         // setter here explicitly.
         desc.setGetter(JS_PropertyStub);
         desc.setSetter(JS_StrictPropertyStub);
     }
 
-    if (!JS_WrapValue(cx, desc.value().address()) || !JS_WrapValue(cx, fval.address()))
+    if (!JS_WrapValue(cx, desc.value()) || !JS_WrapValue(cx, &fval))
         return false;
 
     if (desc.hasGetterObject())
         desc.setGetterObject(&fval.toObject());
     if (desc.hasSetterObject())
         desc.setSetterObject(&fval.toObject());
 
     // Define the property.
@@ -788,17 +788,17 @@ wrappedJSObject_getter(JSContext *cx, Ha
 {
     if (!IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper)) {
         JS_ReportError(cx, "Unexpected object");
         return false;
     }
 
     vp.set(OBJECT_TO_JSVAL(wrapper));
 
-    return WrapperFactory::WaiveXrayAndWrap(cx, vp.address());
+    return WrapperFactory::WaiveXrayAndWrap(cx, vp);
 }
 
 bool
 XrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper,
                                HandleObject wrapper, HandleObject holder, HandleId id,
                                MutableHandle<JSPropertyDescriptor> desc, unsigned flags)
 {
     desc.object().set(nullptr);
@@ -1100,17 +1100,17 @@ DOMXrayTraits::call(JSContext *cx, Handl
         if (!clasp->call(cx, args.length(), args.base()))
             return false;
     } else {
         // This is only reached for WebIDL instance objects, and in practice
         // only for plugins.  Just call them on the content compartment.
         if (!baseInstance.call(cx, wrapper, args))
             return false;
     }
-    return JS_WrapValue(cx, args.rval().address());
+    return JS_WrapValue(cx, args.rval());
 }
 
 bool
 DOMXrayTraits::construct(JSContext *cx, HandleObject wrapper,
                          const JS::CallArgs &args, js::Wrapper& baseInstance)
 {
     RootedObject obj(cx, getTargetObject(wrapper));
     MOZ_ASSERT(mozilla::dom::HasConstructor(obj));
@@ -1122,17 +1122,17 @@ DOMXrayTraits::construct(JSContext *cx, 
             return false;
         }
         if (!clasp->construct(cx, args.length(), args.base()))
             return false;
     } else {
         if (!baseInstance.construct(cx, wrapper, args))
             return false;
     }
-    if (!args.rval().isObject() || !JS_WrapValue(cx, args.rval().address()))
+    if (!args.rval().isObject() || !JS_WrapValue(cx, args.rval()))
         return false;
     return true;
 }
 
 void
 DOMXrayTraits::preserveWrapper(JSObject *target)
 {
     nsISupports *identity = mozilla::dom::UnwrapDOMObjectToISupports(target);
@@ -1225,36 +1225,43 @@ HasNativeProperty(JSContext *cx, HandleO
         return false;
     *hasProp = !!desc.object();
     return true;
 }
 
 } // namespace XrayUtils
 
 static bool
-XrayToString(JSContext *cx, unsigned argc, jsval *vp)
+XrayToString(JSContext *cx, unsigned argc, Value *vp)
 {
-    RootedObject  wrapper(cx, JS_THIS_OBJECT(cx, vp));
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    if (!args.thisv().isObject()) {
+        JS_ReportError(cx, "XrayToString called on an incompatible object");
+        return false;
+    }
+
+    RootedObject wrapper(cx, &args.thisv().toObject());
     if (!wrapper)
         return false;
     if (IsWrapper(wrapper) &&
         GetProxyHandler(wrapper) == &sandboxCallableProxyHandler) {
         wrapper = xpc::SandboxCallableProxyHandler::wrappedObject(wrapper);
     }
     if (!IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper)) {
         JS_ReportError(cx, "XrayToString called on an incompatible object");
         return false;
     }
 
     RootedObject obj(cx, XrayTraits::getTargetObject(wrapper));
 
     static const char start[] = "[object XrayWrapper ";
     static const char end[] = "]";
     if (UseDOMXray(obj))
-        return NativeToString(cx, wrapper, obj, start, end, vp);
+        return NativeToString(cx, wrapper, obj, start, end, args.rval());
 
     nsAutoString result;
     result.AppendASCII(start);
 
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
     char *wrapperStr = wn->ToString();
     if (!wrapperStr) {
@@ -1266,17 +1273,17 @@ XrayToString(JSContext *cx, unsigned arg
 
     result.AppendASCII(end);
 
     JSString *str = JS_NewUCStringCopyN(cx, reinterpret_cast<const jschar *>(result.get()),
                                         result.Length());
     if (!str)
         return false;
 
-    *vp = STRING_TO_JSVAL(str);
+    args.rval().setString(str);
     return true;
 }
 
 #ifdef DEBUG
 
 static void
 DEBUG_CheckXBLCallable(JSContext *cx, JSObject *obj)
 {