Bug 918373 - GC: Handlify various public APIs r=sfink r=bholley r=smaug
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 20 Sep 2013 10:22:59 +0100
changeset 148394 2d2709188afac3eab21a78b14910b71abecedbc7
parent 148393 289fcfb608d6c1ce6dc86df359179870362e43af
child 148395 44952b2191fce23952f02577e0883c19f40f401f
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewerssfink, bholley, smaug
bugs918373
milestone27.0a1
Bug 918373 - GC: Handlify various public APIs r=sfink r=bholley r=smaug
caps/src/nsScriptSecurityManager.cpp
content/base/src/WebSocket.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
dom/base/nsJSUtils.cpp
dom/workers/EventListenerManager.cpp
dom/workers/RuntimeService.cpp
dom/workers/Worker.cpp
dom/workers/WorkerPrivate.cpp
js/jsd/jsd_val.cpp
js/src/ctypes/CTypes.cpp
js/src/jsapi-tests/testCloneScript.cpp
js/src/jsapi-tests/testDebugger.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/js-gdb.gdb
js/src/shell/js.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSLoaderUtils.cpp
js/xpconnect/loader/mozJSLoaderUtils.h
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -475,17 +475,17 @@ nsScriptSecurityManager::ContentSecurity
         return true; // fail open to not break sites.
     }
 
     if (reportViolation) {
         nsAutoString fileName;
         unsigned lineNum = 0;
         NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP");
 
-        JSScript *script;
+        JS::RootedScript script(cx);
         if (JS_DescribeScriptedCaller(cx, &script, &lineNum)) {
             if (const char *file = JS_GetScriptFilename(cx, script)) {
                 CopyUTF8toUTF16(nsDependentCString(file), fileName);
             }
         }
         csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
                                  fileName,
                                  scriptSample,
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -666,17 +666,17 @@ WebSocket::Init(JSContext* aCx,
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   NS_ENSURE_STATE(os);
   rv = os->AddObserver(this, DOM_WINDOW_DESTROYED_TOPIC, true);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = os->AddObserver(this, DOM_WINDOW_FROZEN_TOPIC, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   unsigned lineno;
-  JSScript* script;
+  JS::RootedScript script(aCx);
   if (JS_DescribeScriptedCaller(aCx, &script, &lineno)) {
     mScriptFile = JS_GetScriptFilename(aCx, script);
     mScriptLine = lineno;
   }
 
   // Get WindowID
   mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(aCx);
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9432,17 +9432,17 @@ nsGlobalWindow::ShowSlowScriptDialog()
   nsCOMPtr<nsIDocShell> ds = GetDocShell();
   NS_ENSURE_TRUE(ds, KillSlowScript);
   nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ds);
   NS_ENSURE_TRUE(prompt, KillSlowScript);
 
   // Check if we should offer the option to debug
   JS::RootedScript script(cx);
   unsigned lineno;
-  bool hasFrame = JS_DescribeScriptedCaller(cx, script.address(), &lineno);
+  bool hasFrame = JS_DescribeScriptedCaller(cx, &script, &lineno);
 
   bool debugPossible = hasFrame && js::CanCallContextDebugHandler(cx);
 #ifdef MOZ_JSDEBUGGER
   // Get the debugger service if necessary.
   if (debugPossible) {
     bool jsds_IsOn = false;
     const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
     nsCOMPtr<jsdIExecutionHook> jsdHook;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -504,17 +504,18 @@ void
 NS_ScriptErrorReporter(JSContext *cx,
                        const char *message,
                        JSErrorReport *report)
 {
   // We don't want to report exceptions too eagerly, but warnings in the
   // absence of werror are swallowed whole, so report those now.
   if (!JSREPORT_IS_WARNING(report->flags)) {
     nsIXPConnect* xpc = nsContentUtils::XPConnect();
-    if (JS_DescribeScriptedCaller(cx, nullptr, nullptr)) {
+    JS::RootedScript script(cx);
+    if (JS_DescribeScriptedCaller(cx, &script, nullptr)) {
       xpc->MarkErrorUnreported(cx);
       return;
     }
 
     if (xpc) {
       nsAXPCNativeCallContext *cc = nullptr;
       xpc->GetCurrentNativeCallContext(&cc);
       if (cc) {
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -26,17 +26,17 @@
 #include "nsJSPrincipals.h"
 #include "xpcpublic.h"
 #include "nsContentUtils.h"
 
 bool
 nsJSUtils::GetCallingLocation(JSContext* aContext, const char* *aFilename,
                               uint32_t* aLineno)
 {
-  JSScript* script = nullptr;
+  JS::RootedScript script(aContext);
   unsigned lineno = 0;
 
   if (!JS_DescribeScriptedCaller(aContext, &script, &lineno)) {
     return false;
   }
 
   *aFilename = ::JS_GetScriptFilename(aContext, script);
   *aLineno = lineno;
--- a/dom/workers/EventListenerManager.cpp
+++ b/dom/workers/EventListenerManager.cpp
@@ -382,17 +382,17 @@ EventListenerManager::DispatchEvent(JSCo
     // to the next listener rather than bailing out. If something fails and
     // does not set an exception then we bail out entirely as we've either run
     // out of memory or the operation callback has indicated that we should
     // stop running.
 
     JS::Rooted<JS::Value> listenerVal(aCx, listeners[index]);
 
     JS::Rooted<JSObject*> listenerObj(aCx);
-    if (!JS_ValueToObject(aCx, listenerVal, listenerObj.address())) {
+    if (!JS_ValueToObject(aCx, listenerVal, &listenerObj)) {
       if (!JS_ReportPendingException(aCx)) {
         aRv.Throw(NS_ERROR_FAILURE);
         return false;
       }
       continue;
     }
 
     static const char sHandleEventChars[] = "handleEvent";
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -693,17 +693,17 @@ ContentSecurityPolicyAllows(JSContext* a
 {
   WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
   worker->AssertIsOnWorkerThread();
 
   if (worker->GetReportCSPViolations()) {
     nsString fileName;
     uint32_t lineNum = 0;
 
-    JSScript* script;
+    JS::RootedScript script(aCx);
     const char* file;
     if (JS_DescribeScriptedCaller(aCx, &script, &lineNum) &&
         (file = JS_GetScriptFilename(aCx, script))) {
       fileName.AssignASCII(file);
     } else {
       JS_ReportPendingException(aCx);
     }
 
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -227,17 +227,17 @@ private:
                    const nsAString& aNameStr)
   {
     WorkerPrivate* worker =
       GetInstancePrivate(aCx, &aArgs.thisv().toObject(),
                          NS_ConvertUTF16toUTF8(aNameStr).get());
     MOZ_ASSERT(worker);
 
     JS::Rooted<JSObject*> listener(aCx);
-    if (!JS_ValueToObject(aCx, aArgs.get(0), listener.address())) {
+    if (!JS_ValueToObject(aCx, aArgs.get(0), &listener)) {
       return false;
     }
 
     nsRefPtr<EventHandlerNonNull> handler;
     if (listener && JS_ObjectIsCallable(aCx, listener)) {
       handler = new EventHandlerNonNull(listener);
     } else {
       handler = nullptr;
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -2682,17 +2682,17 @@ WorkerPrivate::Create(JSContext* aCx, JS
     else {
       // Not a window
       NS_ASSERTION(isChrome, "Should be chrome only!");
 
       parentContext = nullptr;
 
       // We're being created outside of a window. Need to figure out the script
       // that is creating us in order for us to use relative URIs later on.
-      JSScript *script;
+      JS::RootedScript script(aCx);
       if (JS_DescribeScriptedCaller(aCx, &script, nullptr)) {
         if (NS_FAILED(NS_NewURI(getter_AddRefs(baseURI),
                                 JS_GetScriptFilename(aCx, script)))) {
           JS_ReportError(aCx, "Failed to construct base URI!");
           return nullptr;
         }
       }
 
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -567,17 +567,18 @@ jsd_GetValueFunction(JSDContext* jsdc, J
     JS::RootedObject obj(cx);
     JS::RootedFunction fun(cx);
 
     if (JSVAL_IS_PRIMITIVE(jsdval->val))
         return nullptr;
 
     obj = js::UncheckedUnwrap(JSVAL_TO_OBJECT(jsdval->val));
     JSAutoCompartment ac(cx, obj);
-    fun = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj));
+    JS::RootedValue funval(cx, JS::ObjectValue(*obj));
+    fun = JS_ValueToFunction(cx, funval);
 
     return fun;
 }
 
 JSDValue*
 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
 {
     AutoSafeJSContext cx;
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -3969,17 +3969,17 @@ PointerType::ConstructData(JSContext* cx
   // the given js function. Callers may leave this blank, or pass null if they
   // wish to pass the third argument.
   RootedObject thisObj(cx, NULL);
   if (args.length() >= 2) {
     if (args[1].isNull()) {
       thisObj = NULL;
     } else if (!JSVAL_IS_PRIMITIVE(args[1])) {
       thisObj = &args[1].toObject();
-    } else if (!JS_ValueToObject(cx, args[1], thisObj.address())) {
+    } else if (!JS_ValueToObject(cx, args[1], &thisObj)) {
       return false;
     }
   }
 
   // The third argument is an optional error sentinel that js-ctypes will return
   // if an exception is raised while executing the closure. The type must match
   // the return type of the callback.
   jsval errVal = JSVAL_VOID;
--- a/js/src/jsapi-tests/testCloneScript.cpp
+++ b/js/src/jsapi-tests/testCloneScript.cpp
@@ -117,17 +117,18 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
 
     // Clone into B
     {
         JSAutoCompartment b(cx, B);
         JS::RootedObject cloned(cx);
         CHECK(cloned = JS_CloneFunctionObject(cx, obj, B));
 
         JSFunction *fun;
-        CHECK(fun = JS_ValueToFunction(cx, JS::ObjectValue(*cloned)));
+        JS::RootedValue clonedValue(cx, JS::ObjectValue(*cloned));
+        CHECK(fun = JS_ValueToFunction(cx, clonedValue));
 
         JSScript *script;
         CHECK(script = JS_GetFunctionScript(cx, fun));
 
         CHECK(JS_GetScriptPrincipals(script) == principalsB);
 
         JS::RootedValue v(cx);
         JS::Value args[] = { JS::Int32Value(1) };
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -249,17 +249,17 @@ BEGIN_TEST(testDebugger_singleStepThrow)
              "try { f(); }\n"
              "catch (x) { e = x; }\n");
         return true;
     }
 
     static bool
     setStepMode(JSContext *cx, unsigned argc, jsval *vp)
     {
-        JSScript *script;
+        JS::RootedScript script(cx);
         JS_DescribeScriptedCaller(cx, &script, NULL);
         JS_ASSERT(script);
 
         if (!JS_SetSingleStepMode(cx, script, true))
             return false;
         JS_SET_RVAL(cx, vp, JSVAL_VOID);
         return true;
     }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -307,95 +307,87 @@ JS_ConvertArgumentsVA(JSContext *cx, uns
             return false;
         }
         sp++;
     }
     return true;
 }
 
 JS_PUBLIC_API(bool)
-JS_ConvertValue(JSContext *cx, jsval valueArg, JSType type, jsval *vp)
-{
-    RootedValue value(cx, valueArg);
+JS_ConvertValue(JSContext *cx, HandleValue value, JSType type, MutableHandleValue vp)
+{
     bool ok;
     RootedObject obj(cx);
     JSString *str;
     double d;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
     switch (type) {
       case JSTYPE_VOID:
-        *vp = JSVAL_VOID;
+        vp.setUndefined();
         ok = true;
         break;
       case JSTYPE_OBJECT:
         ok = js_ValueToObjectOrNull(cx, value, &obj);
         if (ok)
-            *vp = OBJECT_TO_JSVAL(obj);
+            vp.setObjectOrNull(obj);
         break;
       case JSTYPE_FUNCTION:
-        *vp = value;
-        obj = ReportIfNotFunction(cx, *vp);
+        vp.set(value);
+        obj = ReportIfNotFunction(cx, vp);
         ok = (obj != NULL);
         break;
       case JSTYPE_STRING:
         str = ToString<CanGC>(cx, value);
         ok = (str != NULL);
         if (ok)
-            *vp = STRING_TO_JSVAL(str);
+            vp.setString(str);
         break;
       case JSTYPE_NUMBER:
         ok = JS_ValueToNumber(cx, value, &d);
         if (ok)
-            *vp = DOUBLE_TO_JSVAL(d);
+            vp.setDouble(d);
         break;
       case JSTYPE_BOOLEAN:
-        *vp = BooleanValue(ToBoolean(value));
+        vp.setBoolean(ToBoolean(value));
         return true;
       default: {
         char numBuf[12];
         JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE, numBuf);
         ok = false;
         break;
       }
     }
     return ok;
 }
 
 JS_PUBLIC_API(bool)
-JS_ValueToObject(JSContext *cx, jsval valueArg, JSObject **objpArg)
-{
-    RootedValue value(cx, valueArg);
-    RootedObject objp(cx, *objpArg);
+JS_ValueToObject(JSContext *cx, HandleValue value, MutableHandleObject objp)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
-    if (!js_ValueToObjectOrNull(cx, value, &objp))
-        return false;
-    *objpArg = objp;
-    return true;
+    return js_ValueToObjectOrNull(cx, value, objp);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_ValueToFunction(JSContext *cx, jsval valueArg)
-{
-    RootedValue value(cx, valueArg);
+JS_ValueToFunction(JSContext *cx, HandleValue value)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
     return ReportIfNotFunction(cx, value);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_ValueToConstructor(JSContext *cx, jsval valueArg)
-{
-    RootedValue value(cx, valueArg);
+JS_ValueToConstructor(JSContext *cx, HandleValue value)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
     return ReportIfNotFunction(cx, value);
 }
 
 JS_PUBLIC_API(JSString *)
 JS_ValueToString(JSContext *cx, jsval valueArg)
@@ -6154,29 +6146,27 @@ JS_IsIdentifier(JSContext *cx, HandleStr
     if (!linearStr)
         return false;
 
     *isIdentifier = js::frontend::IsIdentifier(linearStr);
     return true;
 }
 
 JS_PUBLIC_API(bool)
-JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno)
-{
-    if (script)
-        *script = NULL;
+JS_DescribeScriptedCaller(JSContext *cx, MutableHandleScript script, unsigned *lineno)
+{
+    script.set(NULL);
     if (lineno)
         *lineno = 0;
 
     NonBuiltinScriptFrameIter i(cx);
     if (i.done())
         return false;
 
-    if (script)
-        *script = i.script();
+    script.set(i.script());
     if (lineno)
         *lineno = js::PCToLineNumber(i.script(), i.pc());
     return true;
 }
 
 #ifdef JS_THREADSAFE
 static PRStatus
 CallOnce(void *func)
@@ -6225,27 +6215,27 @@ JS::AssertArgumentsAreSane(JSContext *cx
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
 }
 #endif /* DEBUG */
 
 JS_PUBLIC_API(void *)
-JS_EncodeScript(JSContext *cx, JSScript *scriptArg, uint32_t *lengthp)
+JS_EncodeScript(JSContext *cx, HandleScript scriptArg, uint32_t *lengthp)
 {
     XDREncoder encoder(cx);
     RootedScript script(cx, scriptArg);
     if (!encoder.codeScript(&script))
         return NULL;
     return encoder.forgetData(lengthp);
 }
 
 JS_PUBLIC_API(void *)
-JS_EncodeInterpretedFunction(JSContext *cx, JSObject *funobjArg, uint32_t *lengthp)
+JS_EncodeInterpretedFunction(JSContext *cx, HandleObject funobjArg, uint32_t *lengthp)
 {
     XDREncoder encoder(cx);
     RootedObject funobj(cx, funobjArg);
     if (!encoder.codeFunction(&funobj))
         return NULL;
     return encoder.forgetData(lengthp);
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1019,26 +1019,26 @@ JS_ConvertArguments(JSContext *cx, unsig
 
 #ifdef va_start
 extern JS_PUBLIC_API(bool)
 JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv,
                       const char *format, va_list ap);
 #endif
 
 extern JS_PUBLIC_API(bool)
-JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp);
+JS_ConvertValue(JSContext *cx, JS::HandleValue v, JSType type, JS::MutableHandleValue vp);
 
 extern JS_PUBLIC_API(bool)
-JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
+JS_ValueToObject(JSContext *cx, JS::HandleValue v, JS::MutableHandleObject objp);
 
 extern JS_PUBLIC_API(JSFunction *)
-JS_ValueToFunction(JSContext *cx, jsval v);
+JS_ValueToFunction(JSContext *cx, JS::HandleValue v);
 
 extern JS_PUBLIC_API(JSFunction *)
-JS_ValueToConstructor(JSContext *cx, jsval v);
+JS_ValueToConstructor(JSContext *cx, JS::HandleValue v);
 
 extern JS_PUBLIC_API(JSString *)
 JS_ValueToString(JSContext *cx, jsval v);
 
 extern JS_PUBLIC_API(JSString *)
 JS_ValueToSource(JSContext *cx, jsval v);
 
 extern JS_PUBLIC_API(bool)
@@ -4209,17 +4209,18 @@ JS_AbortIfWrongThread(JSRuntime *rt);
  * JS_THIS may be used.
  */
 static JS_ALWAYS_INLINE bool
 JS_IsConstructing(JSContext *cx, const jsval *vp)
 {
 #ifdef DEBUG
     JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
     if (JS_ObjectIsFunction(cx, callee)) {
-        JSFunction *fun = JS_ValueToFunction(cx, JS_CALLEE(cx, vp));
+        JS::RootedValue calleeValue(cx, JS_CALLEE(cx, vp));
+        JSFunction *fun = JS_ValueToFunction(cx, calleeValue);
         JS_ASSERT(JS_IsConstructor(fun));
     } else {
         JS_ASSERT(JS_GetClass(callee)->construct != NULL);
     }
 #else
     (void)cx;
 #endif
 
@@ -4289,28 +4290,28 @@ JS_CharsToId(JSContext* cx, JS::TwoByteC
 extern JS_PUBLIC_API(bool)
 JS_IsIdentifier(JSContext *cx, JS::HandleString str, bool *isIdentifier);
 
 /*
  * Return the current script and line number of the most currently running
  * frame. Returns true if a scripted frame was found, false otherwise.
  */
 extern JS_PUBLIC_API(bool)
-JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno);
+JS_DescribeScriptedCaller(JSContext *cx, JS::MutableHandleScript script, unsigned *lineno);
 
 
 /*
  * Encode/Decode interpreted scripts and functions to/from memory.
  */
 
 extern JS_PUBLIC_API(void *)
-JS_EncodeScript(JSContext *cx, JSScript *script, uint32_t *lengthp);
+JS_EncodeScript(JSContext *cx, JS::HandleScript script, uint32_t *lengthp);
 
 extern JS_PUBLIC_API(void *)
-JS_EncodeInterpretedFunction(JSContext *cx, JSObject *funobj, uint32_t *lengthp);
+JS_EncodeInterpretedFunction(JSContext *cx, JS::HandleObject funobj, uint32_t *lengthp);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
                 JSPrincipals *principals, JSPrincipals *originPrincipals);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
                              JSPrincipals *principals, JSPrincipals *originPrincipals);
--- a/js/src/shell/js-gdb.gdb
+++ b/js/src/shell/js-gdb.gdb
@@ -1,9 +1,9 @@
-define hookpost-run
+afe9b1f9b180define hookpost-run
     if ($sigaction)
         call free($sigaction)
         set $sigaction = 0
     end
 end
 
 catch signal SIGSEGV
 commands
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -640,17 +640,17 @@ Version(JSContext *cx, unsigned argc, js
     }
     return true;
 }
 
 static JSScript *
 GetTopScript(JSContext *cx)
 {
     RootedScript script(cx);
-    JS_DescribeScriptedCaller(cx, script.address(), NULL);
+    JS_DescribeScriptedCaller(cx, &script, NULL);
     return script;
 }
 
 /*
  * Resolve a (possibly) relative filename to an absolute path. If
  * |scriptRelative| is true, then the result will be relative to the directory
  * containing the currently-running script, or the current working directory if
  * the currently-running script is "-e" (namely, you're using it from the
@@ -1412,18 +1412,19 @@ AssertEq(JSContext *cx, unsigned argc, j
         }
         return false;
     }
     args.rval().setUndefined();
     return true;
 }
 
 static JSScript *
-ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL)
+ValueToScript(JSContext *cx, jsval vArg, JSFunction **funp = NULL)
 {
+    RootedValue v(cx, vArg);
     RootedFunction fun(cx, JS_ValueToFunction(cx, v));
     if (!fun)
         return NULL;
 
     // Unwrap bound functions.
     while (fun->isBoundFunction()) {
         JSObject *target = fun->getBoundFunctionTarget();
         if (target && target->is<JSFunction>())
@@ -2327,17 +2328,17 @@ Clone(JSContext *cx, unsigned argc, jsva
         if (fun->hasScript() && fun->nonLazyScript()->compileAndGo) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
                                  "function", "compile-and-go");
             return false;
         }
     }
 
     if (argc > 1) {
-        if (!JS_ValueToObject(cx, args[1], parent.address()))
+        if (!JS_ValueToObject(cx, args[1], &parent))
             return false;
     } else {
         parent = JS_GetParent(JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
     }
 
     JSObject *clone = JS_CloneFunctionObject(cx, funobj, parent);
     if (!clone)
         return false;
@@ -2348,27 +2349,28 @@ Clone(JSContext *cx, unsigned argc, jsva
 static bool
 GetPDA(JSContext *cx, unsigned argc, jsval *vp)
 {
     RootedObject vobj(cx);
     bool ok;
     JSPropertyDescArray pda;
     JSPropertyDesc *pd;
 
-    if (!JS_ValueToObject(cx, argc == 0 ? UndefinedValue() : vp[2], vobj.address()))
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (!JS_ValueToObject(cx, args[0], &vobj))
         return false;
     if (!vobj) {
-        JS_SET_RVAL(cx, vp, UndefinedValue());
+        args.rval().setUndefined();
         return true;
     }
 
     RootedObject aobj(cx, JS_NewArrayObject(cx, 0, NULL));
     if (!aobj)
         return false;
-    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(aobj));
+    args.rval().setObject(*aobj);
 
     ok = !!JS_GetPropertyDescArray(cx, vobj, &pda);
     if (!ok)
         return false;
     pd = pda.array;
 
     RootedObject pdobj(cx);
     RootedValue id(cx);
@@ -2547,17 +2549,17 @@ EvalInContext(JSContext *cx, unsigned ar
     if (srclen == 0) {
         JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sobj));
         return true;
     }
 
     RootedScript script(cx);
     unsigned lineno;
 
-    JS_DescribeScriptedCaller(cx, script.address(), &lineno);
+    JS_DescribeScriptedCaller(cx, &script, &lineno);
     RootedValue rval(cx);
     {
         Maybe<JSAutoCompartment> ac;
         unsigned flags;
         JSObject *unwrapped = UncheckedUnwrap(sobj, true, &flags);
         if (flags & Wrapper::CROSS_COMPARTMENT) {
             sobj = unwrapped;
             ac.construct(cx, sobj);
@@ -3459,33 +3461,33 @@ DecompileFunction(JSContext *cx, unsigne
     return DecompileFunctionSomehow(cx, argc, vp, JS_DecompileFunction);
 }
 
 static bool
 DecompileThisScript(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedScript script (cx);
-    if (!JS_DescribeScriptedCaller(cx, script.address(), NULL)) {
+    if (!JS_DescribeScriptedCaller(cx, &script, NULL)) {
         args.rval().setString(cx->runtime()->emptyString);
         return true;
     }
     JSString *result = JS_DecompileScript(cx, script, "test", 0);
     if (!result)
         return false;
     args.rval().setString(result);
     return true;
 }
 
 static bool
 ThisFilename(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedScript script (cx);
-    if (!JS_DescribeScriptedCaller(cx, script.address(), NULL) || !script->filename()) {
+    if (!JS_DescribeScriptedCaller(cx, &script, NULL) || !script->filename()) {
         args.rval().setString(cx->runtime()->emptyString);
         return true;
     }
     JSString *filename = JS_NewStringCopyZ(cx, script->filename());
     if (!filename)
         return false;
     args.rval().setString(filename);
     return true;
@@ -4165,17 +4167,18 @@ Exec(JSContext *cx, unsigned argc, jsval
     unsigned i, nargc;
     JSString *str;
     bool ok;
     pid_t pid;
     int status;
 
     JS_SET_RVAL(cx, vp, UndefinedValue());
 
-    fun = JS_ValueToFunction(cx, vp[0]);
+    RootedValue arg(cx, vp[0]);
+    fun = JS_ValueToFunction(cx, arg);
     if (!fun)
         return false;
     if (!fun->atom)
         return true;
 
     nargc = 1 + argc;
 
     /* nargc + 1 accounts for the terminating NULL. */
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -508,17 +508,17 @@ mozJSComponentLoader::LoadModule(FileLoc
         nsAutoCString spec;
         uri->GetSpec(spec);
         JS_ReportError(cx, "%s has NSGetFactory property that is not a function",
                        spec.get());
         return NULL;
     }
 
     RootedObject jsGetFactoryObj(cx);
-    if (!JS_ValueToObject(cx, NSGetFactory_val, jsGetFactoryObj.address()) ||
+    if (!JS_ValueToObject(cx, NSGetFactory_val, &jsGetFactoryObj) ||
         !jsGetFactoryObj) {
         /* XXX report error properly */
         return NULL;
     }
 
     rv = xpc->WrapJS(cx, jsGetFactoryObj,
                      NS_GET_IID(xpcIJSGetFactory), getter_AddRefs(entry->getfactoryobj));
     if (NS_FAILED(rv)) {
@@ -771,18 +771,17 @@ mozJSComponentLoader::ObjectForLocation(
     StartupCache* cache = StartupCache::GetSingleton();
 
     nsAutoCString cachePath(kJSCachePrefix);
     rv = PathifyURI(aURI, cachePath);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (cache) {
         if (!mReuseLoaderGlobal) {
-            rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal,
-                                  script.address());
+            rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script);
         } else {
             rv = ReadCachedFunction(cache, cachePath, cx, mSystemPrincipal,
                                     function.address());
         }
 
         if (NS_SUCCEEDED(rv)) {
             LOG(("Successfully loaded %s from startupcache\n", nativePath.get()));
         } else {
--- a/js/xpconnect/loader/mozJSLoaderUtils.cpp
+++ b/js/xpconnect/loader/mozJSLoaderUtils.cpp
@@ -6,36 +6,36 @@
 
 #include "jsapi.h"
 #include "js/OldDebugAPI.h"
 
 #include "nsJSPrincipals.h"
 
 #include "mozilla/scache/StartupCache.h"
 
+using namespace JS;
 using namespace mozilla::scache;
 
 // We only serialize scripts with system principals. So we don't serialize the
 // principals when writing a script. Instead, when reading it back, we set the
 // principals to the system principals.
 nsresult
 ReadCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx,
-                 nsIPrincipal *systemPrincipal, JSScript **scriptp)
+                 nsIPrincipal *systemPrincipal, MutableHandleScript scriptp)
 {
     nsAutoArrayPtr<char> buf;
     uint32_t len;
     nsresult rv = cache->GetBuffer(PromiseFlatCString(uri).get(),
                                    getter_Transfers(buf), &len);
     if (NS_FAILED(rv))
         return rv; // don't warn since NOT_AVAILABLE is an ok error
 
-    JSScript *script = JS_DecodeScript(cx, buf, len, nsJSPrincipals::get(systemPrincipal), nullptr);
-    if (!script)
+    scriptp.set(JS_DecodeScript(cx, buf, len, nsJSPrincipals::get(systemPrincipal), nullptr));
+    if (!scriptp)
         return NS_ERROR_OUT_OF_MEMORY;
-    *scriptp = script;
     return NS_OK;
 }
 
 nsresult
 ReadCachedFunction(StartupCache* cache, nsACString &uri, JSContext *cx,
                    nsIPrincipal *systemPrincipal, JSFunction **functionp)
 {
     return NS_ERROR_FAILURE;
@@ -52,17 +52,17 @@ ReadCachedFunction(StartupCache* cache, 
         return NS_ERROR_OUT_OF_MEMORY;
     JSFunction* function = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj));
     *functionp = function;
     return NS_OK;*/
 }
 
 nsresult
 WriteCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx,
-                  nsIPrincipal *systemPrincipal, JSScript *script)
+                  nsIPrincipal *systemPrincipal, HandleScript script)
 {
     MOZ_ASSERT(JS_GetScriptPrincipals(script) == nsJSPrincipals::get(systemPrincipal));
     MOZ_ASSERT(JS_GetScriptOriginPrincipals(script) == nsJSPrincipals::get(systemPrincipal));
 
     uint32_t size;
     void *data = JS_EncodeScript(cx, script, &size);
     if (!data)
         return NS_ERROR_OUT_OF_MEMORY;
--- a/js/xpconnect/loader/mozJSLoaderUtils.h
+++ b/js/xpconnect/loader/mozJSLoaderUtils.h
@@ -14,25 +14,25 @@ namespace mozilla {
 namespace scache {
 class StartupCache;
 }
 }
 
 nsresult
 ReadCachedScript(mozilla::scache::StartupCache* cache, nsACString &uri,
                  JSContext *cx, nsIPrincipal *systemPrincipal,
-                 JSScript **script);
+                 JS::MutableHandleScript scriptp);
 
 nsresult
 ReadCachedFunction(mozilla::scache::StartupCache* cache, nsACString &uri,
                    JSContext *cx, nsIPrincipal *systemPrincipal,
                    JSFunction **function);
 
 nsresult
 WriteCachedScript(mozilla::scache::StartupCache* cache, nsACString &uri,
                   JSContext *cx, nsIPrincipal *systemPrincipal,
-                  JSScript *script);
+                  JS::HandleScript script);
 nsresult
 WriteCachedFunction(mozilla::scache::StartupCache* cache, nsACString &uri,
                     JSContext *cx, nsIPrincipal *systemPrincipal,
                     JSFunction *function);
 
 #endif /* mozJSLoaderUtils_h */
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -155,20 +155,20 @@ mozJSSubScriptLoader::ReadScript(nsIURI 
     /* repent for our evil deeds */
     JS_SetErrorReporter(cx, er);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 mozJSSubScriptLoader::LoadSubScript(const nsAString& url,
-                                    const JS::Value& target,
+                                    const Value& targetArg,
                                     const nsAString& charset,
                                     JSContext* cx,
-                                    JS::Value* retval)
+                                    Value* retval)
 {
     /*
      * Loads a local url and evals it into the current cx
      * Synchronous (an async version would be cool too.)
      *   url: The url to load.  Must be local so that it can be loaded
      *        synchronously.
      *   target_obj: Optional object to eval the script onto (defaults to context
      *               global)
@@ -194,18 +194,19 @@ mozJSSubScriptLoader::LoadSubScript(cons
     mozJSComponentLoader* loader = mozJSComponentLoader::Get();
     rv = loader->FindTargetObject(cx, &targetObj);
     NS_ENSURE_SUCCESS(rv, rv);
 
     bool reusingGlobal = !JS_IsGlobalObject(targetObj);
 
     // We base reusingGlobal off of what the loader told us, but we may not
     // actually be using that object.
+    RootedValue target(cx, targetArg);
     RootedObject passedObj(cx);
-    if (!JS_ValueToObject(cx, target, passedObj.address()))
+    if (!JS_ValueToObject(cx, target, &passedObj))
         return NS_ERROR_ILLEGAL_VALUE;
 
     if (passedObj)
         targetObj = passedObj;
 
     // Remember an object out of the calling compartment so that we
     // can properly wrap the result later.
     nsCOMPtr<nsIPrincipal> principal = mSystemPrincipal;
@@ -230,17 +231,17 @@ mozJSSubScriptLoader::LoadSubScript(cons
      * js exceptions */
     nsCOMPtr<nsIURI> uri;
     nsAutoCString uriStr;
     nsAutoCString scheme;
 
     RootedScript script(cx);
 
     // Figure out who's calling us
-    if (!JS_DescribeScriptedCaller(cx, script.address(), nullptr)) {
+    if (!JS_DescribeScriptedCaller(cx, &script, nullptr)) {
         // No scripted frame means we don't know who's calling, bail.
         return NS_ERROR_FAILURE;
     }
 
     // Suppress caching if we're compiling as content.
     StartupCache* cache = (principal == mSystemPrincipal)
                           ? StartupCache::GetSingleton()
                           : nullptr;
@@ -287,17 +288,17 @@ mozJSSubScriptLoader::LoadSubScript(cons
     JSVersion version = JS_GetVersion(cx);
     nsAutoCString cachePath;
     cachePath.AppendPrintf("jssubloader/%d", version);
     PathifyURI(uri, cachePath);
 
     RootedFunction function(cx);
     script = nullptr;
     if (cache)
-        rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, script.address());
+        rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script);
     if (!script) {
         rv = ReadScript(uri, cx, targetObj, charset,
                         static_cast<const char*>(uriStr.get()), serv,
                         principal, reusingGlobal, script.address(), function.address());
         writeScript = !!script;
     }
 
     if (NS_FAILED(rv) || (!script && !function))
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -138,17 +138,17 @@ nsAutoString *gWorkingDirectory = nullpt
 
 static bool
 GetLocationProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
 {
 #if !defined(XP_WIN) && !defined(XP_UNIX)
     //XXX: your platform should really implement this
     return false;
 #else
-    JSScript *script;
+    JS::RootedScript script(cx);
     JS_DescribeScriptedCaller(cx, &script, NULL);
     const char *filename = JS_GetScriptFilename(cx, script);
 
     if (filename) {
         nsresult rv;
         nsCOMPtr<nsIXPConnect> xpc =
             do_GetService(kXPConnectServiceContractID, &rv);
 
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -142,17 +142,18 @@ SandboxImport(JSContext *cx, unsigned ar
         // NB: funobj must only be used to get the JSFunction out.
         RootedObject funobj(cx, &args[0].toObject());
         if (js::IsProxy(funobj)) {
             funobj = XPCWrapper::UnsafeUnwrapSecurityWrapper(funobj);
         }
 
         JSAutoCompartment ac(cx, funobj);
 
-        JSFunction *fun = JS_ValueToFunction(cx, ObjectValue(*funobj));
+        RootedValue funval(cx, ObjectValue(*funobj));
+        JSFunction *fun = JS_ValueToFunction(cx, funval);
         if (!fun) {
             XPCThrower::Throw(NS_ERROR_INVALID_ARG, cx);
             return false;
         }
 
         // Use the actual function name as the name.
         funname = JS_GetFunctionId(fun);
         if (!funname) {
@@ -303,17 +304,17 @@ ExportFunction(JSContext *cx, unsigned a
         return false;
 
     return true;
 }
 
 static bool
 GetFilenameAndLineNumber(JSContext *cx, nsACString &filename, unsigned &lineno)
 {
-    JSScript *script;
+    JS::RootedScript script(cx);
     if (JS_DescribeScriptedCaller(cx, &script, &lineno)) {
         if (const char *cfilename = JS_GetScriptFilename(cx, script)) {
             filename.Assign(nsDependentCString(cfilename));
             return true;
         }
     }
     return false;
 }
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2692,26 +2692,27 @@ nsXPCComponents_Utils::ReportError(const
 
     console->LogMessage(scripterr);
     return NS_OK;
 }
 
 /* void evalInSandbox(in AString source, in nativeobj sandbox); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::EvalInSandbox(const nsAString& source,
-                                     const JS::Value& sandboxVal,
+                                     const JS::Value& sandboxValArg,
                                      const JS::Value& version,
                                      const JS::Value& filenameVal,
                                      int32_t lineNumber,
                                      JSContext *cx,
                                      uint8_t optionalArgc,
                                      JS::Value *retval)
 {
+    RootedValue sandboxVal(cx, sandboxValArg);
     RootedObject sandbox(cx);
-    if (!JS_ValueToObject(cx, sandboxVal, sandbox.address()) || !sandbox)
+    if (!JS_ValueToObject(cx, sandboxVal, &sandbox) || !sandbox)
         return NS_ERROR_INVALID_ARG;
 
     // Optional third argument: JS version, as a string.
     JSVersion jsVersion = JSVERSION_DEFAULT;
     if (optionalArgc >= 1) {
         JSString *jsVersionStr = JS_ValueToString(cx, version);
         if (!jsVersionStr)
             return NS_ERROR_INVALID_ARG;
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -288,17 +288,17 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
             if (!(oldOpts & JSOPTION_DONT_REPORT_UNCAUGHT))
                 JS_ReportPendingException(cx);
         } else if (!success) {
             NS_WARNING("QI hook ran OOMed - this is probably a bug!");
         }
     }
 
     if (success)
-        success = JS_ValueToObject(cx, retval, retObj.address());
+        success = JS_ValueToObject(cx, retval, &retObj);
 
     return success ? retObj.get() : nullptr;
 }
 
 /***************************************************************************/
 
 static bool
 GetNamedPropertyAsVariantRaw(XPCCallContext& ccx,
@@ -973,17 +973,18 @@ nsXPCWrappedJSClass::CheckForException(X
                 // that a user pref was set indicating that we should report all
                 // exceptions.
                 if (!reportable)
                     reportable = nsXPConnect::ReportAllJSExceptions();
 
                 // Finally, check to see if this is the last JS frame on the
                 // stack. If so then we always want to report it.
                 if (!reportable) {
-                    reportable = !JS_DescribeScriptedCaller(cx, nullptr, nullptr);
+                    RootedScript ignored(cx);
+                    reportable = !JS_DescribeScriptedCaller(cx, &ignored, nullptr);
                 }
 
                 // Ugly special case for GetInterface. It's "special" in the
                 // same way as QueryInterface in that a failure is not
                 // exceptional and shouldn't be reported. We have to do this
                 // check here instead of in xpcwrappedjs (like we do for QI) to
                 // avoid adding extra code to all xpcwrappedjs objects.
                 if (reportable && e_result == NS_ERROR_NO_INTERFACE &&