Bug 917798 - Handlify JS exception APIs r=terrence r=bz
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 19 Sep 2013 08:54:01 +0100
changeset 147855 0874c0c422b1ba2fc1fa82e15da81f24ffd9b5ec
parent 147854 f1434323209c058ee75ca60670fec1daa0b902a7
child 147856 020f08616536c164e0bd6712702ea8c9e6d974b4
push id25317
push useremorley@mozilla.com
push dateThu, 19 Sep 2013 14:37:38 +0000
treeherdermozilla-central@70a765607344 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, bz
bugs917798
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 917798 - Handlify JS exception APIs r=terrence r=bz
dom/base/nsDOMClassInfo.cpp
dom/base/nsJSUtils.cpp
dom/bindings/BindingUtils.cpp
dom/bindings/CallbackObject.cpp
dom/bindings/Exceptions.cpp
dom/plugins/base/nsJSNPRuntime.cpp
js/ipc/JavaScriptChild.cpp
js/jsd/jsd_hook.cpp
js/jsd/jsd_stak.cpp
js/jsd/jsd_val.cpp
js/jsd/jsd_xpc.cpp
js/src/ctypes/CTypes.cpp
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsexn.cpp
js/src/shell/js.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -3525,17 +3525,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       JSAutoCompartment ac(my_cx, obj);
 
       ok = JS_ResolveStandardClass(my_cx, obj, id, &did_resolve);
 
       if (!ok) {
         // Trust the JS engine (or the script security manager) to set
         // the exception in the JS engine.
 
-        if (!JS_GetPendingException(my_cx, exn.address())) {
+        if (!JS_GetPendingException(my_cx, &exn)) {
           return NS_ERROR_UNEXPECTED;
         }
 
         // Return NS_OK to avoid stomping over the exception that was passed
         // down from the ResolveStandardClass call.
         // Note that the order of the JS_ClearPendingException and
         // JS_SetPendingException is important in the case that my_cx == cx.
 
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -291,17 +291,21 @@ nsJSUtils::EvaluateString(JSContext* aCx
     if (aEvaluateOptions.reportUncaught) {
       ReportPendingException(aCx);
       if (aRetValue) {
         *aRetValue = JS::UndefinedValue();
       }
     } else {
       rv = JS_IsExceptionPending(aCx) ? NS_ERROR_FAILURE
                                       : NS_ERROR_OUT_OF_MEMORY;
-      JS_GetPendingException(aCx, aRetValue);
+      JS::RootedValue exn(aCx);
+      JS_GetPendingException(aCx, &exn);
+      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;
   return rv;
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -176,17 +176,18 @@ 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_SetPendingException(cx, mJSException);
+    JS::RootedValue exception(cx, mJSException);
+    JS_SetPendingException(cx, 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)
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -181,17 +181,17 @@ CallbackObject::CallSetup::~CallSetup()
     bool dealtWithPendingException = false;
     if (mExceptionHandling == eRethrowContentExceptions ||
         mExceptionHandling == eRethrowExceptions) {
       // Restore the old context options
       JS_SetOptions(mCx, mSavedJSContextOptions);
       mErrorResult.MightThrowJSException();
       if (JS_IsExceptionPending(mCx)) {
         JS::Rooted<JS::Value> exn(mCx);
-        if (JS_GetPendingException(mCx, exn.address()) &&
+        if (JS_GetPendingException(mCx, &exn) &&
             ShouldRethrowException(exn)) {
           mErrorResult.ThrowJSException(mCx, exn);
           JS_ClearPendingException(mCx);
           dealtWithPendingException = true;
         }
       }
     }
 
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -66,17 +66,18 @@ ThrowExceptionObject(JSContext* aCx, nsI
     return false;
   }
 
   JS::RootedObject obj(aCx, holder->GetJSObject());
   if (!obj) {
     return false;
   }
 
-  JS_SetPendingException(aCx, OBJECT_TO_JSVAL(obj));
+  JS::RootedValue exn(aCx, JS::ObjectOrNullValue(obj));
+  JS_SetPendingException(aCx, exn);
 
   return true;
 }
 
 bool
 ThrowExceptionObject(JSContext* aCx, Exception* aException)
 {
   JS::Rooted<JS::Value> thrown(aCx);
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -452,17 +452,18 @@ ThrowJSException(JSContext *cx, const ch
     if (message) {
       AppendASCIItoUTF16("].", ucex);
     }
 
     JSString *str = ::JS_NewUCStringCopyN(cx, (jschar *)ucex.get(),
                                           ucex.Length());
 
     if (str) {
-      ::JS_SetPendingException(cx, STRING_TO_JSVAL(str));
+      JS::RootedValue exn(cx, JS::StringValue(str));
+      ::JS_SetPendingException(cx, exn);
     }
 
     PopException();
   } else {
     ::JS_ReportError(cx, message);
   }
 }
 
--- a/js/ipc/JavaScriptChild.cpp
+++ b/js/ipc/JavaScriptChild.cpp
@@ -113,17 +113,17 @@ JavaScriptChild::fail(JSContext *cx, Ret
     // By default, we set |undefined| unless we can get a more meaningful
     // exception.
     *rs = ReturnStatus(false, JSVariant(void_t()));
 
     // Note we always return true from this function, since this propagates
     // to the IPC code, and we don't want a JS failure to cause the death
     // of the child process.
 
-    jsval exn;
+    RootedValue exn(cx);
     if (!JS_GetPendingException(cx, &exn))
         return true;
 
     // If we don't clear the pending exception, JS will try to wrap it as it
     // leaves the current compartment. Since there is no previous compartment,
     // that would crash.
     JS_ClearPendingException(cx);
 
--- a/js/jsd/jsd_hook.cpp
+++ b/js/jsd/jsd_hook.cpp
@@ -75,17 +75,17 @@ jsd_DebuggerHandler(JSContext *cx, JSScr
 
     return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUGGER_KEYWORD,
                                  hook, hookData, rval);
 }
 
 
 JSTrapStatus
 jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
-                 jsval *rval, void *closure)
+                 jsval *rvalArg, void *closure)
 {
     JSDScript*      jsdscript;
     JSDContext*     jsdc = (JSDContext*) closure;
     JSD_ExecutionHookProc hook;
     void*                 hookData;
 
     if( ! jsdc || ! jsdc->inited )
         return JSTRAP_CONTINUE;
@@ -102,20 +102,23 @@ jsd_ThrowHandler(JSContext *cx, JSScript
         return JSTRAP_CONTINUE;
 
     JSD_LOCK_SCRIPTS(jsdc);
     jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
     JSD_UNLOCK_SCRIPTS(jsdc);
     if( ! jsdscript )
         return JSTRAP_CONTINUE;
 
-    JS_GetPendingException(cx, rval);
+    JS::RootedValue rval(cx);
+    JS_GetPendingException(cx, &rval);
 
-    return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
-                                 hook, hookData, rval);
+    JSTrapStatus result = jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
+                                                hook, hookData, rval.address());
+    *rvalArg = rval;
+    return result;
 }
 
 JSTrapStatus
 jsd_CallExecutionHook(JSDContext* jsdc,
                       JSContext *cx,
                       unsigned type,
                       JSD_ExecutionHookProc hook,
                       void* hookData,
--- a/js/jsd/jsd_stak.cpp
+++ b/js/jsd/jsd_stak.cpp
@@ -519,54 +519,56 @@ jsd_IsValidFrameInThreadState(JSDContext
 
     if( ! jsd_IsValidThreadState(jsdc, jsdthreadstate) )
         return false;
     if( jsdframe->jsdthreadstate != jsdthreadstate )
         return false;
 
     JSD_ASSERT_VALID_THREAD_STATE(jsdthreadstate);
     JSD_ASSERT_VALID_STACK_FRAME(jsdframe);
-    
+
     return true;
 }
 
 static JSContext*
 _getContextForThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
 {
     bool valid;
     JSD_LOCK_THREADSTATES(jsdc);
     valid = jsd_IsValidThreadState(jsdc, jsdthreadstate);
     JSD_UNLOCK_THREADSTATES(jsdc);
     if( valid )
         return jsdthreadstate->context;
     return NULL;
-}        
+}
 
 JSDValue*
 jsd_GetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
 {
     JSContext* cx;
-    jsval val;
+    JS::RootedValue val(cx);
 
     if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate)))
         return NULL;
 
     if(JS_GetPendingException(cx, &val))
         return jsd_NewValue(jsdc, val);
     return NULL;
-}        
+}
 
 bool
-jsd_SetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate, 
+jsd_SetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate,
                  JSDValue* jsdval)
 {
     JSContext* cx;
 
     if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate)))
         return false;
 
-    if(jsdval)
-        JS_SetPendingException(cx, JSD_GetValueWrappedJSVal(jsdc, jsdval));
-    else
+    if(jsdval) {
+        JS::RootedValue exn(cx, JSD_GetValueWrappedJSVal(jsdc, jsdval));
+        JS_SetPendingException(cx, exn);
+    } else {
         JS_ClearPendingException(cx);
+    }
     return true;
 }
 
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -521,17 +521,17 @@ jsd_GetValueProperty(JSDContext* jsdc, J
             return NULL;
 
         JS_ClearPendingException(cx);
 
         if(!JS_GetPropertyById(cx, obj, id, &val))
         {
             if (JS_IsExceptionPending(cx))
             {
-                if (!JS_GetPendingException(cx, propValue.address()))
+                if (!JS_GetPendingException(cx, &propValue))
                 {
                     return NULL;
                 }
                 propFlags = JSPD_EXCEPTION;
             }
             else
             {
                 propFlags = JSPD_ERROR;
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -490,27 +490,27 @@ jsds_ErrorHookProc (JSDContext *jsdc, JS
 
     nsCOMPtr<jsdIErrorHook> hook;
     gJsds->GetErrorHook(getter_AddRefs(hook));
     if (!hook)
         return JSD_ERROR_REPORTER_PASS_ALONG;
 
     if (running)
         return JSD_ERROR_REPORTER_PASS_ALONG;
-    
+
     running = true;
-    
+
     nsCOMPtr<jsdIValue> val;
     if (JS_IsExceptionPending(cx)) {
-        jsval jv;
+        JS::RootedValue jv(cx);
         JS_GetPendingException(cx, &jv);
         JSDValue *jsdv = JSD_NewValue (jsdc, jv);
         val = dont_AddRef(jsdValue::FromPtr(jsdc, jsdv));
     }
-    
+
     nsAutoCString fileName;
     uint32_t    line;
     uint32_t    pos;
     uint32_t    flags;
     uint32_t    errnum;
     bool        rval;
     if (report) {
         fileName.Assign(report->filename);
@@ -1994,17 +1994,17 @@ jsdStackFrame::Eval (const nsAString &by
 
     *_rval = JSD_AttemptUCScriptInStackFrame (mCx, mThreadState,
                                               mStackFrameInfo,
                                               char_bytes, bytes.Length(),
                                               PromiseFlatCString(fileName).get(),
                                               line, &jv);
     if (!*_rval) {
         if (JS_IsExceptionPending(cx))
-            JS_GetPendingException (cx, jv.address());
+            JS_GetPendingException (cx, &jv);
         else
             jv = JSVAL_NULL;
     }
 
     JS_RestoreExceptionState (cx, estate);
 
     JSDValue *jsdv = JSD_NewValue (mCx, jv);
     if (!jsdv)
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -2585,17 +2585,17 @@ ExplicitConvert(JSContext* cx, HandleVal
   // If ImplicitConvert succeeds, use that result.
   if (ImplicitConvert(cx, val, targetType, buffer, false, NULL))
     return true;
 
   // If ImplicitConvert failed, and there is no pending exception, then assume
   // hard failure (out of memory, or some other similarly serious condition).
   // We store any pending exception in case we need to re-throw it.
   RootedValue ex(cx);
-  if (!JS_GetPendingException(cx, ex.address()))
+  if (!JS_GetPendingException(cx, &ex))
     return false;
 
   // Otherwise, assume soft failure. Clear the pending exception so that we
   // can throw a different one as required.
   JS_ClearPendingException(cx);
 
   TypeCode type = CType::GetTypeCode(targetType);
 
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -204,17 +204,17 @@ class JSAPITest
         if (!(expr)) \
             return fail("CHECK failed: " #expr, __FILE__, __LINE__); \
     } while (false)
 
     bool fail(JSAPITestString msg = JSAPITestString(), const char *filename = "-", int lineno = 0) {
         if (JS_IsExceptionPending(cx)) {
             js::gc::AutoSuppressGC gcoff(cx);
             JS::RootedValue v(cx);
-            JS_GetPendingException(cx, v.address());
+            JS_GetPendingException(cx, &v);
             JS_ClearPendingException(cx);
             JSString *s = JS_ValueToString(cx, v);
             if (s) {
                 JSAutoByteString bytes(cx, s);
                 if (!!bytes)
                     msg += bytes.ptr();
             }
         }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5919,31 +5919,30 @@ JS_GetLocaleCallbacks(JSRuntime *rt)
 JS_PUBLIC_API(bool)
 JS_IsExceptionPending(JSContext *cx)
 {
     /* This function can be called by a finalizer. */
     return (bool) cx->isExceptionPending();
 }
 
 JS_PUBLIC_API(bool)
-JS_GetPendingException(JSContext *cx, jsval *vp)
+JS_GetPendingException(JSContext *cx, MutableHandleValue vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     if (!cx->isExceptionPending())
         return false;
-    *vp = cx->getPendingException();
-    assertSameCompartment(cx, *vp);
+    vp.set(cx->getPendingException());
+    assertSameCompartment(cx, vp);
     return true;
 }
 
 JS_PUBLIC_API(void)
-JS_SetPendingException(JSContext *cx, jsval valueArg)
-{
-    RootedValue value(cx, valueArg);
+JS_SetPendingException(JSContext *cx, HandleValue value)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
     cx->setPendingException(value);
 }
 
 JS_PUBLIC_API(void)
 JS_ClearPendingException(JSContext *cx)
@@ -5970,31 +5969,32 @@ JS_PUBLIC_API(JSExceptionState *)
 JS_SaveExceptionState(JSContext *cx)
 {
     JSExceptionState *state;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     state = cx->pod_malloc<JSExceptionState>();
     if (state) {
-        state->throwing = JS_GetPendingException(cx, &state->exception);
+        state->throwing =
+            JS_GetPendingException(cx, MutableHandleValue::fromMarkedLocation(&state->exception));
         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
             AddValueRoot(cx, &state->exception, "JSExceptionState.exception");
     }
     return state;
 }
 
 JS_PUBLIC_API(void)
 JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     if (state) {
         if (state->throwing)
-            JS_SetPendingException(cx, state->exception);
+            JS_SetPendingException(cx, HandleValue::fromMarkedLocation(&state->exception));
         else
             JS_ClearPendingException(cx);
         JS_DropExceptionState(cx, state);
     }
 }
 
 JS_PUBLIC_API(void)
 JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
@@ -6006,19 +6006,18 @@ JS_DropExceptionState(JSContext *cx, JSE
             assertSameCompartment(cx, state->exception);
             JS_RemoveValueRoot(cx, &state->exception);
         }
         js_free(state);
     }
 }
 
 JS_PUBLIC_API(JSErrorReport *)
-JS_ErrorFromException(JSContext *cx, jsval valueArg)
-{
-    RootedValue value(cx, valueArg);
+JS_ErrorFromException(JSContext *cx, HandleValue value)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
     return js_ErrorFromException(value);
 }
 
 JS_PUBLIC_API(bool)
 JS_ThrowReportedError(JSContext *cx, const char *message,
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4123,20 +4123,20 @@ extern JS_PUBLIC_API(JSString *)
 JS_GetRegExpSource(JSContext *cx, JS::HandleObject obj);
 
 /************************************************************************/
 
 extern JS_PUBLIC_API(bool)
 JS_IsExceptionPending(JSContext *cx);
 
 extern JS_PUBLIC_API(bool)
-JS_GetPendingException(JSContext *cx, jsval *vp);
+JS_GetPendingException(JSContext *cx, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(void)
-JS_SetPendingException(JSContext *cx, jsval v);
+JS_SetPendingException(JSContext *cx, JS::HandleValue v);
 
 extern JS_PUBLIC_API(void)
 JS_ClearPendingException(JSContext *cx);
 
 extern JS_PUBLIC_API(bool)
 JS_ReportPendingException(JSContext *cx);
 
 /*
@@ -4162,17 +4162,17 @@ JS_DropExceptionState(JSContext *cx, JSE
 /*
  * If the given value is an exception object that originated from an error,
  * the exception will contain an error report struct, and this API will return
  * the address of that struct.  Otherwise, it returns NULL.  The lifetime of
  * the error report struct that might be returned is the same as the lifetime
  * of the exception object.
  */
 extern JS_PUBLIC_API(JSErrorReport *)
-JS_ErrorFromException(JSContext *cx, jsval v);
+JS_ErrorFromException(JSContext *cx, JS::HandleValue v);
 
 /*
  * Given a reported error's message and JSErrorReport struct pointer, throw
  * the corresponding exception on cx.
  */
 extern JS_PUBLIC_API(bool)
 JS_ThrowReportedError(JSContext *cx, const char *message,
                       JSErrorReport *reportp);
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -976,17 +976,18 @@ js_ErrorToException(JSContext *cx, const
         return false;
     tv[3] = STRING_TO_JSVAL(filenameStr);
 
     if (!InitExnPrivate(cx, errObject, messageStr, filenameStr,
                         reportp->lineno, reportp->column, reportp, exn)) {
         return false;
     }
 
-    JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));
+    RootedValue errValue(cx, OBJECT_TO_JSVAL(errObject));
+    JS_SetPendingException(cx, errValue);
 
     /* Flag the error report passed in to indicate an exception was raised. */
     reportp->flags |= JSREPORT_EXCEPTION;
     return true;
 }
 
 static bool
 IsDuckTypedErrorObject(JSContext *cx, HandleObject exnObject, const char **filename_strp)
@@ -1014,17 +1015,17 @@ bool
 js_ReportUncaughtException(JSContext *cx)
 {
     JSErrorReport *reportp, report;
 
     if (!JS_IsExceptionPending(cx))
         return true;
 
     RootedValue exn(cx);
-    if (!JS_GetPendingException(cx, exn.address()))
+    if (!JS_GetPendingException(cx, &exn))
         return false;
 
     AutoValueVector roots(cx);
     roots.resize(6);
 
     /*
      * Because ToString below could error and an exception object could become
      * unrooted, we must root exnObject.  Later, if exnObject is non-null, we
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -845,17 +845,17 @@ class AutoNewContext
 
     JSContext *get() { return newcx; }
 
     ~AutoNewContext() {
         if (newcx) {
             RootedValue exc(oldcx);
             bool throwing = JS_IsExceptionPending(newcx);
             if (throwing)
-                JS_GetPendingException(newcx, exc.address());
+                JS_GetPendingException(newcx, &exc);
             newCompartment.destroy();
             newRequest.destroy();
             if (throwing)
                 JS_SetPendingException(oldcx, exc);
             DestroyContext(newcx, false);
         }
     }
 };
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -962,17 +962,17 @@ mozJSComponentLoader::ObjectForLocation(
                                                nullptr, 0, nullptr,
                                                buf, bytesRead);
             }
         }
         // Propagate the exception, if one exists. Also, don't leave the stale
         // exception on this context.
         JS_SetOptions(cx, oldopts);
         if (!script && !function && aPropagateExceptions) {
-            JS_GetPendingException(cx, aException.address());
+            JS_GetPendingException(cx, aException);
             JS_ClearPendingException(cx);
         }
     }
 
     if (!script && !function) {
         return NS_ERROR_FAILURE;
     }
 
@@ -1015,17 +1015,17 @@ mozJSComponentLoader::ObjectForLocation(
     } else {
         jsval rval;
         ok = JS_CallFunction(cx, obj, function, 0, nullptr, &rval);
     }
     JS_SetOptions(cx, oldopts);
 
     if (!ok) {
         if (aPropagateExceptions) {
-            JS_GetPendingException(cx, aException.address());
+            JS_GetPendingException(cx, aException);
             JS_ClearPendingException(cx);
         }
         *aObject = nullptr;
         return NS_ERROR_FAILURE;
     }
 
     /* Freed when we remove from the table. */
     *aLocation = ToNewCString(nativePath);
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -57,17 +57,18 @@ mozJSSubScriptLoader::~mozJSSubScriptLoa
     /* empty */
 }
 
 NS_IMPL_ISUPPORTS1(mozJSSubScriptLoader, mozIJSSubScriptLoader)
 
 static nsresult
 ReportError(JSContext *cx, const char *msg)
 {
-    JS_SetPendingException(cx, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, msg)));
+    RootedValue exn(cx, JS::StringValue(JS_NewStringCopyZ(cx, msg)));
+    JS_SetPendingException(cx, exn);
     return NS_OK;
 }
 
 nsresult
 mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *targetObjArg,
                                  const nsAString& charset, const char *uriStr,
                                  nsIIOService *serv, nsIPrincipal *principal,
                                  bool reuseGlobal, JSScript **scriptp,
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1547,17 +1547,17 @@ xpc::EvalInSandbox(JSContext *cx, Handle
                           v.address());
         if (ok && returnStringOnly && !v.isUndefined()) {
             JSString *str = JS_ValueToString(sandcx, v);
             ok = !!str;
             v = ok ? JS::StringValue(str) : JS::UndefinedValue();
         }
 
         // If the sandbox threw an exception, grab it off the context.
-        if (JS_GetPendingException(sandcx, exn.address())) {
+        if (JS_GetPendingException(sandcx, &exn)) {
             MOZ_ASSERT(!ok);
             JS_ClearPendingException(sandcx);
             if (returnStringOnly) {
                 // The caller asked for strings only, convert the
                 // exception into a string.
                 JSString *str = JS_ValueToString(sandcx, exn);
                 exn = str ? JS::StringValue(str) : JS::UndefinedValue();
             }
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -250,17 +250,17 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
         jsval args[1] = {OBJECT_TO_JSVAL(id)};
         success = JS_CallFunctionValue(cx, jsobj, fun, 1, args, retval.address());
 
         JS_SetOptions(cx, oldOpts);
 
         if (!success && JS_IsExceptionPending(cx)) {
             RootedValue jsexception(cx, NullValue());
 
-            if (JS_GetPendingException(cx, jsexception.address())) {
+            if (JS_GetPendingException(cx, &jsexception)) {
                 nsresult rv;
                 if (jsexception.isObject()) {
                     // XPConnect may have constructed an object to represent a
                     // C++ QI failure. See if that is the case.
                     using namespace mozilla::dom;
                     Exception *e = nullptr;
                     UNWRAP_OBJECT(Exception, cx, &jsexception.toObject(), e);
 
@@ -936,17 +936,17 @@ nsXPCWrappedJSClass::CheckForException(X
     if (xpc_exception)
         xpcc->SetException(nullptr);
 
     // get this right away in case we do something below to cause JS code
     // to run on this JSContext
     nsresult pending_result = xpcc->GetPendingResult();
 
     RootedValue js_exception(cx);
-    bool is_js_exception = JS_GetPendingException(cx, js_exception.address());
+    bool is_js_exception = JS_GetPendingException(cx, &js_exception);
 
     /* JS might throw an expection whether the reporter was called or not */
     if (is_js_exception) {
         if (!xpc_exception)
             XPCConvert::JSValToXPCException(&js_exception, anInterfaceName,
                                             aPropertyName,
                                             getter_AddRefs(xpc_exception));