Backed out 7 changesets (bug 1022773) for build bustage
authorWes Kocher <wkocher@mozilla.com>
Tue, 01 Jul 2014 13:27:31 -0700
changeset 208629 ee727fe51f064d134ed45376e59c6c72a654402d
parent 208628 232abc366696961be38064000c1f49c252d70796
child 208630 c4503546943a709c6bd6fd82f39b418d3bb9b765
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1022773
milestone32.0a2
backs out232abc366696961be38064000c1f49c252d70796
cde190482d72217502f687f17a184e3b955ddf6b
9b5ade54f72aa91f2884f075307bea7f9ad6cae0
2505eb1fd336cb4232e5602788970953facc56e4
127429f7dd1961f41b26a223ed6fe1badfe38227
60e8b99055e9da53abf469ece518f6e61af48008
5b44fa1cea34cbc7218d590b23128bd03a265899
Backed out 7 changesets (bug 1022773) for build bustage Backed out changeset 232abc366696 (bug 1022773) Backed out changeset cde190482d72 (bug 1022773) Backed out changeset 9b5ade54f72a (bug 1022773) Backed out changeset 2505eb1fd336 (bug 1022773) Backed out changeset 127429f7dd19 (bug 1022773) Backed out changeset 60e8b99055e9 (bug 1022773) Backed out changeset 5b44fa1cea34 (bug 1022773)
content/base/src/Element.cpp
content/base/src/nsFrameMessageManager.cpp
content/media/webaudio/AudioDestinationNode.cpp
content/media/webaudio/AudioProcessingEvent.cpp
content/media/webaudio/MediaBufferDecoder.cpp
content/media/webaudio/ScriptProcessorNode.cpp
content/xul/content/src/nsXULElement.cpp
dom/base/nsJSEnvironment.cpp
dom/bindings/Codegen.py
dom/devicestorage/DeviceStorageRequestChild.cpp
dom/devicestorage/nsDeviceStorage.cpp
dom/devicestorage/nsDeviceStorage.h
dom/workers/Navigator.cpp
dom/workers/WorkerPrivate.cpp
js/jsd/jsd_stak.cpp
js/src/builtin/Eval.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsfun.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/vm/Debugger.cpp
js/src/vm/ForkJoin.cpp
js/src/vm/Stack.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.h
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCWrappedNativeScope.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/wrappers/XrayWrapper.cpp
tools/profiler/ProfileEntry.cpp
tools/profiler/TableTicker.cpp
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -474,29 +474,26 @@ Element::WrapObject(JSContext *aCx)
   bool dummy;
 
   nsXBLService* xblService = nsXBLService::GetInstance();
   if (!xblService) {
     dom::Throw(aCx, NS_ERROR_NOT_AVAILABLE);
     return nullptr;
   }
 
-  {
-    // Make a scope so that ~nsRefPtr can GC before returning obj.
-    nsRefPtr<nsXBLBinding> binding;
-    xblService->LoadBindings(this, uri, principal, getter_AddRefs(binding), &dummy);
-
-    if (binding) {
-      if (nsContentUtils::IsSafeToRunScript()) {
-        binding->ExecuteAttachedHandler();
-      }
-      else {
-        nsContentUtils::AddScriptRunner(
-          NS_NewRunnableMethod(binding, &nsXBLBinding::ExecuteAttachedHandler));
-      }
+  nsRefPtr<nsXBLBinding> binding;
+  xblService->LoadBindings(this, uri, principal, getter_AddRefs(binding), &dummy);
+  
+  if (binding) {
+    if (nsContentUtils::IsSafeToRunScript()) {
+      binding->ExecuteAttachedHandler();
+    }
+    else {
+      nsContentUtils::AddScriptRunner(
+        NS_NewRunnableMethod(binding, &nsXBLBinding::ExecuteAttachedHandler));
     }
   }
 
   return obj;
 }
 
 nsDOMTokenList*
 Element::ClassList()
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -1526,25 +1526,23 @@ nsFrameScriptExecutor::TryCacheLoadAndCo
     if (global) {
       JSAutoCompartment ac(cx, global);
       JS::CompileOptions options(cx);
       options.setFileAndLine(url.get(), 1);
       JS::Rooted<JSScript*> script(cx);
       JS::Rooted<JSObject*> funobj(cx);
       if (aRunInGlobalScope) {
         options.setNoScriptRval(true);
-        if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
-          return;
-        }
+        script = JS::Compile(cx, JS::NullPtr(), options, srcBuf);
       } else {
         JS::Rooted<JSFunction *> fun(cx);
-        if (!JS::CompileFunction(cx, JS::NullPtr(), options,
-                                 nullptr, 0, nullptr, /* name, nargs, args */
-                                 srcBuf, &fun))
-        {
+        fun = JS::CompileFunction(cx, JS::NullPtr(), options,
+                                  nullptr, 0, nullptr, /* name, nargs, args */
+                                  srcBuf);
+        if (!fun) {
           return;
         }
         funobj = JS_GetFunctionObject(fun);
       }
 
       if (!script && !funobj) {
         return;
       }
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -121,24 +121,24 @@ public:
   void FireOfflineCompletionEvent(AudioDestinationNode* aNode)
   {
     AudioContext* context = aNode->Context();
     context->Shutdown();
     // Shutdown drops self reference, but the context is still referenced by aNode,
     // which is strongly referenced by the runnable that called
     // AudioDestinationNode::FireOfflineCompletionEvent.
 
-    AutoJSAPI jsapi;
-    JSContext* cx = jsapi.cx();
-
     // We need the global for the context so that we can enter its compartment.
-    JS::Rooted<JSObject*> global(cx, context->GetGlobalJSObject());
+    JSObject* global = context->GetGlobalJSObject();
     if (NS_WARN_IF(!global)) {
       return;
     }
+
+    AutoJSAPI jsapi;
+    JSContext* cx = jsapi.cx();
     JSAutoCompartment ac(cx, global);
 
     // Create the input buffer
     ErrorResult rv;
     nsRefPtr<AudioBuffer> renderedBuffer =
       AudioBuffer::Create(context, mInputChannels.Length(),
                           mLength, mSampleRate, cx, rv);
     if (rv.Failed()) {
--- a/content/media/webaudio/AudioProcessingEvent.cpp
+++ b/content/media/webaudio/AudioProcessingEvent.cpp
@@ -36,25 +36,25 @@ AudioProcessingEvent::WrapObject(JSConte
 {
   return AudioProcessingEventBinding::Wrap(aCx, this);
 }
 
 already_AddRefed<AudioBuffer>
 AudioProcessingEvent::LazilyCreateBuffer(uint32_t aNumberOfChannels,
                                          ErrorResult& aRv)
 {
-  AutoJSAPI jsapi;
-  JSContext* cx = jsapi.cx();
-
   // We need the global for the context so that we can enter its compartment.
-  JS::Rooted<JSObject*> global(cx, mNode->Context()->GetGlobalJSObject());
+  JSObject* global = mNode->Context()->GetGlobalJSObject();
   if (NS_WARN_IF(!global)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
+
+  AutoJSAPI jsapi;
+  JSContext* cx = jsapi.cx();
   JSAutoCompartment ac(cx, global);
 
   nsRefPtr<AudioBuffer> buffer =
     AudioBuffer::Create(mNode->Context(), aNumberOfChannels,
                         mNode->BufferSize(),
                         mNode->Context()->SampleRate(), cx, aRv);
   MOZ_ASSERT(buffer || aRv.ErrorCode() == NS_ERROR_OUT_OF_MEMORY);
   return buffer.forget();
--- a/content/media/webaudio/MediaBufferDecoder.cpp
+++ b/content/media/webaudio/MediaBufferDecoder.cpp
@@ -394,24 +394,24 @@ MediaDecodeTask::CallbackTheResult()
 }
 
 bool
 WebAudioDecodeJob::AllocateBuffer()
 {
   MOZ_ASSERT(!mOutput);
   MOZ_ASSERT(NS_IsMainThread());
 
-  AutoJSAPI jsapi;
-  JSContext* cx = jsapi.cx();
-
   // We need the global for the context so that we can enter its compartment.
-  JS::Rooted<JSObject*> global(cx, mContext->GetGlobalJSObject());
+  JSObject* global = mContext->GetGlobalJSObject();
   if (NS_WARN_IF(!global)) {
     return false;
   }
+
+  AutoJSAPI jsapi;
+  JSContext* cx = jsapi.cx();
   JSAutoCompartment ac(cx, global);
 
   // Now create the AudioBuffer
   ErrorResult rv;
   mOutput = AudioBuffer::Create(mContext, mChannelBuffers.Length(),
                                 mWriteIndex, mContext->SampleRate(), cx, rv);
   if (rv.Failed()) {
     return false;
--- a/content/media/webaudio/ScriptProcessorNode.cpp
+++ b/content/media/webaudio/ScriptProcessorNode.cpp
@@ -397,24 +397,24 @@ private:
           // this function.
           MutexAutoLock lock(mStream->Engine()->NodeMutex());
           node = static_cast<ScriptProcessorNode*>(mStream->Engine()->Node());
         }
         if (!node || !node->Context()) {
           return NS_OK;
         }
 
-        AutoJSAPI jsapi;
-        JSContext* cx = jsapi.cx();
-
         // Get the global for the context so that we can enter its compartment.
-        JS::Rooted<JSObject*> global(cx, node->Context()->GetGlobalJSObject());
+        JSObject* global = node->Context()->GetGlobalJSObject();
         if (NS_WARN_IF(!global)) {
           return NS_OK;
         }
+
+        AutoJSAPI jsapi;
+        JSContext* cx = jsapi.cx();
         JSAutoCompartment ac(cx, global);
 
         // Create the input buffer
         nsRefPtr<AudioBuffer> inputBuffer;
         if (!mNullInput) {
           ErrorResult rv;
           inputBuffer =
             AudioBuffer::Create(node->Context(), mInputChannels.Length(),
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2753,18 +2753,18 @@ nsXULPrototypeScript::Compile(JS::Source
                                   aSrcBuf.get(), aSrcBuf.length(),
                                   OffThreadScriptReceiverCallback,
                                   static_cast<void*>(aOffThreadReceiver))) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
         // This reference will be consumed by the NotifyOffThreadScriptCompletedRunnable.
         NS_ADDREF(aOffThreadReceiver);
     } else {
-        JS::Rooted<JSScript*> script(cx);
-        if (!JS::Compile(cx, scope, options, aSrcBuf, &script))
+        JSScript* script = JS::Compile(cx, scope, options, aSrcBuf);
+        if (!script)
             return NS_ERROR_OUT_OF_MEMORY;
         Set(script);
     }
     return NS_OK;
 }
 
 nsresult
 nsXULPrototypeScript::Compile(const char16_t* aText,
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2812,43 +2812,33 @@ NS_DOMReadStructuredClone(JSContext* cx,
     uint32_t width, height;
     JS::Rooted<JS::Value> dataArray(cx);
     if (!JS_ReadUint32Pair(reader, &width, &height) ||
         !JS_ReadTypedArray(reader, &dataArray)) {
       return nullptr;
     }
     MOZ_ASSERT(dataArray.isObject());
 
-    // Protect the result from a moving GC in ~nsRefPtr.
-    JS::Rooted<JSObject*> result(cx);
-    {
-      // Construct the ImageData.
-      nsRefPtr<ImageData> imageData = new ImageData(width, height,
-                                                    dataArray.toObject());
-      // Wrap it in a JS::Value.
-      result = imageData->WrapObject(cx);
-    }
-    return result;
+    // Construct the ImageData.
+    nsRefPtr<ImageData> imageData = new ImageData(width, height,
+                                                  dataArray.toObject());
+    // Wrap it in a JS::Value.
+    return imageData->WrapObject(cx);
   } else if (tag == SCTAG_DOM_WEBCRYPTO_KEY) {
     nsIGlobalObject *global = xpc::GetNativeForGlobal(JS::CurrentGlobalOrNull(cx));
     if (!global) {
       return nullptr;
     }
 
-    // Prevent the return value from being trashed by a GC during ~nsRefPtr.
-    JS::Rooted<JSObject*> result(cx);
-    {
-      nsRefPtr<Key> key = new Key(global);
-      if (!key->ReadStructuredClone(reader)) {
-        result = nullptr;
-      } else {
-        result = key->WrapObject(cx);
-      }
+    nsRefPtr<Key> key = new Key(global);
+    if (!key->ReadStructuredClone(reader)) {
+      return nullptr;
     }
-    return result;
+
+    return key->WrapObject(cx);
   }
 
   // Don't know what this is. Bail.
   xpc::Throw(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return nullptr;
 }
 
 bool
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1595,29 +1595,27 @@ class CGConstructNavigatorObject(CGAbstr
                             "on navigator. See bug 856820.")
         return fill(
             """
             GlobalObject global(aCx, aObj);
             if (global.Failed()) {
               return nullptr;
             }
             ErrorResult rv;
+            nsRefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
+            rv.WouldReportJSException();
+            if (rv.Failed()) {
+              ThrowMethodFailedWithDetails(aCx, rv, "${descriptorName}", "navigatorConstructor");
+              return nullptr;
+            }
             JS::Rooted<JS::Value> v(aCx);
-            {  // Scope to make sure |result| goes out of scope while |v| is rooted
-              nsRefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
-              rv.WouldReportJSException();
-              if (rv.Failed()) {
-                ThrowMethodFailedWithDetails(aCx, rv, "${descriptorName}", "navigatorConstructor");
-                return nullptr;
-              }
-              if (!WrapNewBindingObject(aCx, result, &v)) {
-                //XXX Assertion disabled for now, see bug 991271.
-                MOZ_ASSERT(true || JS_IsExceptionPending(aCx));
-                return nullptr;
-              }
+            if (!WrapNewBindingObject(aCx, result, &v)) {
+              //XXX Assertion disabled for now, see bug 991271.
+              MOZ_ASSERT(true || JS_IsExceptionPending(aCx));
+              return nullptr;
             }
             return &v.toObject();
             """,
             descriptorName=self.descriptor.name)
 
 
 class CGClassConstructHookHolder(CGGeneric):
     def __init__(self, descriptor):
--- a/dom/devicestorage/DeviceStorageRequestChild.cpp
+++ b/dom/devicestorage/DeviceStorageRequestChild.cpp
@@ -67,31 +67,31 @@ DeviceStorageRequestChild::
       break;
     }
 
     case DeviceStorageResponseValue::TSuccessResponse:
     {
       nsString fullPath;
       mDSFile->GetFullPath(fullPath);
       AutoJSContext cx;
-      JS::Rooted<JS::Value> result(cx);
-      StringToJsval(mRequest->GetOwner(), fullPath, &result);
+      JS::Rooted<JS::Value> result(cx,
+        StringToJsval(mRequest->GetOwner(), fullPath));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TFileDescriptorResponse:
     {
       FileDescriptorResponse r = aValue;
 
       nsString fullPath;
       mDSFile->GetFullPath(fullPath);
       AutoJSContext cx;
-      JS::Rooted<JS::Value> result(cx);
-      StringToJsval(mRequest->GetOwner(), fullPath, &result);
+      JS::Rooted<JS::Value> result(cx,
+        StringToJsval(mRequest->GetOwner(), fullPath));
 
       mDSFileDescriptor->mDSFile = mDSFile;
       mDSFileDescriptor->mFileDescriptor = r.fileDescriptor();
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TBlobResponse:
@@ -125,58 +125,58 @@ DeviceStorageRequestChild::
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TAvailableStorageResponse:
     {
       AvailableStorageResponse r = aValue;
       AutoJSContext cx;
-      JS::Rooted<JS::Value> result(cx);
-      StringToJsval(mRequest->GetOwner(), r.mountState(), &result);
+      JS::Rooted<JS::Value> result(
+        cx, StringToJsval(mRequest->GetOwner(), r.mountState()));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TStorageStatusResponse:
     {
       StorageStatusResponse r = aValue;
       AutoJSContext cx;
-      JS::Rooted<JS::Value> result(cx);
-      StringToJsval(mRequest->GetOwner(), r.storageStatus(), &result);
+      JS::Rooted<JS::Value> result(
+        cx, StringToJsval(mRequest->GetOwner(), r.storageStatus()));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TFormatStorageResponse:
     {
       FormatStorageResponse r = aValue;
       AutoJSContext cx;
-      JS::Rooted<JS::Value> result(cx);
-      StringToJsval(mRequest->GetOwner(), r.mountState(), &result);
+      JS::Rooted<JS::Value> result(
+        cx, StringToJsval(mRequest->GetOwner(), r.mountState()));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TMountStorageResponse:
     {
       MountStorageResponse r = aValue;
       AutoJSContext cx;
-      JS::Rooted<JS::Value> result(cx);
-      StringToJsval(mRequest->GetOwner(), r.storageStatus(), &result);
+      JS::Rooted<JS::Value> result(
+        cx, StringToJsval(mRequest->GetOwner(), r.storageStatus()));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TUnmountStorageResponse:
     {
       UnmountStorageResponse r = aValue;
       AutoJSContext cx;
-      JS::Rooted<JS::Value> result(cx);
-      StringToJsval(mRequest->GetOwner(), r.storageStatus(), &result);
+      JS::Rooted<JS::Value> result(
+        cx, StringToJsval(mRequest->GetOwner(), r.storageStatus()));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TEnumerationResponse:
     {
       EnumerationResponse r = aValue;
       nsDOMDeviceStorageCursor* cursor
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -1635,37 +1635,31 @@ nsDOMDeviceStorage::SetRootDirectoryForT
   mStorageName = aStorageName;
 }
 
 JS::Value
 InterfaceToJsval(nsPIDOMWindow* aWindow,
                  nsISupports* aObject,
                  const nsIID* aIID)
 {
+  AutoJSContext cx;
   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
   if (!sgo) {
-    return JS::NullValue();
-  }
-
-  JSObject *unrootedScopeObj = sgo->GetGlobalJSObject();
-  NS_ENSURE_TRUE(unrootedScopeObj, JS::NullValue());
-  JSRuntime *runtime = JS_GetObjectRuntime(unrootedScopeObj);
-  JS::Rooted<JS::Value> someJsVal(runtime);
-  nsresult rv;
-
-  { // Protect someJsVal from moving GC in ~JSAutoCompartment
-    AutoJSContext cx;
-
-    JS::Rooted<JSObject*> scopeObj(cx, unrootedScopeObj);
-    JSAutoCompartment ac(cx, scopeObj);
-
-    rv = nsContentUtils::WrapNative(cx, aObject, aIID, &someJsVal);
-  }
+    return JSVAL_NULL;
+  }
+
+  JS::Rooted<JSObject*> scopeObj(cx, sgo->GetGlobalJSObject());
+  NS_ENSURE_TRUE(scopeObj, JSVAL_NULL);
+  JSAutoCompartment ac(cx, scopeObj);
+
+
+  JS::Rooted<JS::Value> someJsVal(cx);
+  nsresult rv = nsContentUtils::WrapNative(cx, aObject, aIID, &someJsVal);
   if (NS_FAILED(rv)) {
-    return JS::NullValue();
+    return JSVAL_NULL;
   }
 
   return someJsVal;
 }
 
 JS::Value
 nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile)
 {
@@ -1691,43 +1685,42 @@ nsIFileToJsval(nsPIDOMWindow* aWindow, D
   MOZ_ASSERT(aFile->mLastModifiedDate != UINT64_MAX);
 
   nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(fullPath, aFile->mMimeType,
                                                 aFile->mLength, aFile->mFile,
                                                 aFile->mLastModifiedDate);
   return InterfaceToJsval(aWindow, blob, &NS_GET_IID(nsIDOMBlob));
 }
 
-bool
-StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString,
-              JS::MutableHandle<JS::Value> result)
+JS::Value StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aWindow);
 
   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
   if (!sgo) {
-    return false;
+    return JSVAL_NULL;
   }
 
   nsIScriptContext *scriptContext = sgo->GetScriptContext();
   if (!scriptContext) {
     return JSVAL_NULL;
   }
 
   AutoPushJSContext cx(scriptContext->GetNativeContext());
   if (!cx) {
     return JSVAL_NULL;
   }
 
-  if (!xpc::StringToJsval(cx, aString, result)) {
-    return false;
-  }
-
-  return true;
+  JS::Rooted<JS::Value> result(cx);
+  if (!xpc::StringToJsval(cx, aString, &result)) {
+    return JSVAL_NULL;
+  }
+
+  return result;
 }
 
 class DeviceStorageCursorRequest MOZ_FINAL
   : public nsIContentPermissionRequest
   , public PCOMContentPermissionRequestChild
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -2116,18 +2109,18 @@ public:
     MOZ_ASSERT(NS_IsMainThread());
 
     nsString state = NS_LITERAL_STRING("unavailable");
     if (mFile) {
       mFile->GetStatus(state);
     }
 
     AutoJSContext cx;
-    JS::Rooted<JS::Value> result(cx);
-    StringToJsval(mRequest->GetOwner(), state, &result);
+    JS::Rooted<JS::Value> result(cx,
+                                 StringToJsval(mRequest->GetOwner(), state));
     mRequest->FireSuccess(result);
     mRequest = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
@@ -2150,18 +2143,18 @@ public:
     MOZ_ASSERT(NS_IsMainThread());
 
     nsString state = NS_LITERAL_STRING("undefined");
     if (mFile) {
       mFile->GetStorageStatus(state);
     }
 
     AutoJSContext cx;
-    JS::Rooted<JS::Value> result(cx);
-    StringToJsval(mRequest->GetOwner(), state, &result);
+    JS::Rooted<JS::Value> result(cx,
+                                 StringToJsval(mRequest->GetOwner(), state));
     mRequest->FireSuccess(result);
     mRequest = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
@@ -2184,18 +2177,18 @@ public:
     MOZ_ASSERT(NS_IsMainThread());
 
     nsString state = NS_LITERAL_STRING("unavailable");
     if (mFile) {
       mFile->DoFormat(state);
     }
 
     AutoJSContext cx;
-    JS::Rooted<JS::Value> result(cx);
-    StringToJsval(mRequest->GetOwner(), state, &result);
+    JS::Rooted<JS::Value> result(cx,
+                                 StringToJsval(mRequest->GetOwner(), state));
     mRequest->FireSuccess(result);
     mRequest = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
@@ -2218,18 +2211,18 @@ public:
     MOZ_ASSERT(NS_IsMainThread());
 
     nsString state = NS_LITERAL_STRING("unavailable");
     if (mFile) {
       mFile->DoMount(state);
     }
 
     AutoJSContext cx;
-    JS::Rooted<JS::Value> result(cx);
-    StringToJsval(mRequest->GetOwner(), state, &result);
+    JS::Rooted<JS::Value> result(cx,
+                                 StringToJsval(mRequest->GetOwner(), state));
     mRequest->FireSuccess(result);
     mRequest = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
@@ -2252,18 +2245,18 @@ public:
     MOZ_ASSERT(NS_IsMainThread());
 
     nsString state = NS_LITERAL_STRING("unavailable");
     if (mFile) {
       mFile->DoUnmount(state);
     }
 
     AutoJSContext cx;
-    JS::Rooted<JS::Value> result(cx);
-    StringToJsval(mRequest->GetOwner(), state, &result);
+    JS::Rooted<JS::Value> result(cx,
+                                 StringToJsval(mRequest->GetOwner(), state));
     mRequest->FireSuccess(result);
     mRequest = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
@@ -2304,17 +2297,17 @@ public:
 
     AutoJSContext cx;
     JS::Rooted<JS::Value> result(cx, JSVAL_NULL);
     nsPIDOMWindow* window = mRequest->GetOwner();
 
     if (mFile) {
       result = nsIFileToJsval(window, mFile);
     } else if (mPath.Length()) {
-      StringToJsval(window, mPath, &result);
+      result = StringToJsval(window, mPath);
     }
     else {
       result = JS_NumberValue(double(mValue));
     }
 
     mRequest->FireSuccess(result);
     mRequest = nullptr;
     return NS_OK;
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -219,19 +219,18 @@ public:
 private:
   ~nsDOMDeviceStorageCursor();
 
   nsRefPtr<DeviceStorageFile> mFile;
   nsCOMPtr<nsIPrincipal> mPrincipal;
 };
 
 //helpers
-bool
-StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString,
-              JS::MutableHandle<JS::Value> result);
+JS::Value
+StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString);
 
 JS::Value
 nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile);
 
 JS::Value
 InterfaceToJsval(nsPIDOMWindow* aWindow, nsISupports* aObject, const nsIID* aIID);
 
 #endif
--- a/dom/workers/Navigator.cpp
+++ b/dom/workers/Navigator.cpp
@@ -112,47 +112,44 @@ GetDataStoresStructuredCloneCallbacksRea
 
   // Read the holder from the buffer, which points to the data store.
   nsMainThreadPtrHolder<DataStore>* dataStoreholder;
   if (!JS_ReadBytes(aReader, &dataStoreholder, sizeof(dataStoreholder))) {
     MOZ_ASSERT(false, "cannot read bytes for dataStoreholder!");
     return nullptr;
   }
 
-  // Protect workerStoreObj from moving GC during ~nsRefPtr.
-  JS::Rooted<JSObject*> workerStoreObj(aCx, nullptr);
-  {
-    nsRefPtr<WorkerDataStore> workerStore =
-      new WorkerDataStore(workerPrivate->GlobalScope());
-    nsMainThreadPtrHandle<DataStore> backingStore = dataStoreholder;
+  nsRefPtr<WorkerDataStore> workerStore =
+    new WorkerDataStore(workerPrivate->GlobalScope());
+  nsMainThreadPtrHandle<DataStore> backingStore = dataStoreholder;
 
-    // When we're on the worker thread, prepare a DataStoreChangeEventProxy.
-    nsRefPtr<DataStoreChangeEventProxy> eventProxy =
-      new DataStoreChangeEventProxy(workerPrivate, workerStore);
+  // When we're on the worker thread, prepare a DataStoreChangeEventProxy.
+  nsRefPtr<DataStoreChangeEventProxy> eventProxy =
+    new DataStoreChangeEventProxy(workerPrivate, workerStore);
 
-    // Add the DataStoreChangeEventProxy as an event listener on the main thread.
-    nsRefPtr<DataStoreAddEventListenerRunnable> runnable =
-      new DataStoreAddEventListenerRunnable(workerPrivate,
-                                            backingStore,
-                                            eventProxy);
-    runnable->Dispatch(aCx);
+  // Add the DataStoreChangeEventProxy as an event listener on the main thread.
+  nsRefPtr<DataStoreAddEventListenerRunnable> runnable =
+    new DataStoreAddEventListenerRunnable(workerPrivate,
+                                          backingStore,
+                                          eventProxy);
+  runnable->Dispatch(aCx);
 
-    // Point WorkerDataStore to DataStore.
-    workerStore->SetBackingDataStore(backingStore);
+  // Point WorkerDataStore to DataStore.
+  workerStore->SetBackingDataStore(backingStore);
 
-    JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
-    if (!global) {
-      MOZ_ASSERT(false, "cannot get global!");
-    } else {
-      workerStoreObj = workerStore->WrapObject(aCx);
-      if (!JS_WrapObject(aCx, &workerStoreObj)) {
-        MOZ_ASSERT(false, "cannot wrap object for workerStoreObj!");
-        workerStoreObj = nullptr;
-      }
-    }
+  JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
+  if (!global) {
+    MOZ_ASSERT(false, "cannot get global!");
+    return nullptr;
+  }
+
+  JS::Rooted<JSObject*> workerStoreObj(aCx, workerStore->WrapObject(aCx));
+  if (!JS_WrapObject(aCx, &workerStoreObj)) {
+    MOZ_ASSERT(false, "cannot wrap object for workerStoreObj!");
+    return nullptr;
   }
 
   return workerStoreObj;
 }
 
 static bool
 GetDataStoresStructuredCloneCallbacksWrite(JSContext* aCx,
                                            JSStructuredCloneWriter* aWriter,
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -359,25 +359,21 @@ struct WorkerStructuredCloneCallbacks
       JS::Rooted<JS::Value> dataArray(aCx);
       if (!JS_ReadUint32Pair(aReader, &width, &height) ||
           !JS_ReadTypedArray(aReader, &dataArray))
       {
         return nullptr;
       }
       MOZ_ASSERT(dataArray.isObject());
 
-      JS::Rooted<JSObject*> result(aCx);
-      {
-        // Construct the ImageData.
-        nsRefPtr<ImageData> imageData = new ImageData(width, height,
-                                                      dataArray.toObject());
-        // Wrap it in a JS::Value, protected from a moving GC during ~nsRefPtr.
-        result = imageData->WrapObject(aCx);
-      }
-      return result;
+      // Construct the ImageData.
+      nsRefPtr<ImageData> imageData = new ImageData(width, height,
+                                                    dataArray.toObject());
+      // Wrap it in a JS::Value.
+      return imageData->WrapObject(aCx);
     }
 
     Error(aCx, 0);
     return nullptr;
   }
 
   static bool
   Write(JSContext* aCx, JSStructuredCloneWriter* aWriter,
--- a/js/jsd/jsd_stak.cpp
+++ b/js/jsd/jsd_stak.cpp
@@ -465,34 +465,32 @@ jsd_EvaluateScriptInStackFrame(JSDContex
 
 JSString*
 jsd_ValToStringInStackFrame(JSDContext* jsdc, 
                             JSDThreadState* jsdthreadstate,
                             JSDStackFrameInfo* jsdframe,
                             jsval val)
 {
     bool valid;
+    JSString* retval;
     JSExceptionState* exceptionState;
-    JSContext *cx = jsdthreadstate->context;
 
     JSD_LOCK_THREADSTATES(jsdc);
     valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
     JSD_UNLOCK_THREADSTATES(jsdc);
 
     if( ! valid )
         return nullptr;
 
-    JS::RootedString retval(cx);
+    AutoPushJSContext cx(jsdthreadstate->context);
+
     JS::RootedValue v(cx, val);
-    {
-        AutoPushJSContext cx(jsdthreadstate->context);
-        exceptionState = JS_SaveExceptionState(cx);
-        retval = JS::ToString(cx, v);
-        JS_RestoreExceptionState(cx, exceptionState);
-    }
+    exceptionState = JS_SaveExceptionState(cx);
+    retval = JS::ToString(cx, v);
+    JS_RestoreExceptionState(cx, exceptionState);
 
     return retval;
 }
 
 bool
 jsd_IsValidThreadState(JSDContext*        jsdc, 
                        JSDThreadState*    jsdthreadstate)
 {
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -266,17 +266,17 @@ EvalKernel(JSContext *cx, const CallArgs
         return ejr == EvalJSON_Success;
 
     EvalScriptGuard esg(cx);
 
     if (evalType == DIRECT_EVAL && caller.isNonEvalFunctionFrame())
         esg.lookupInEvalCache(flatStr, callerScript, pc);
 
     if (!esg.foundScript()) {
-        RootedScript maybeScript(cx);
+        JSScript *maybeScript;
         unsigned lineno;
         const char *filename;
         JSPrincipals *originPrincipals;
         uint32_t pcOffset;
         DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                              &originPrincipals,
                                              evalType == DIRECT_EVAL
                                              ? CALLED_FROM_JSOP_EVAL
@@ -336,17 +336,17 @@ js::DirectEvalStringFromIon(JSContext *c
     if (ejr != EvalJSON_NotJSON)
         return ejr == EvalJSON_Success;
 
     EvalScriptGuard esg(cx);
 
     esg.lookupInEvalCache(flatStr, callerScript, pc);
 
     if (!esg.foundScript()) {
-        RootedScript maybeScript(cx);
+        JSScript *maybeScript;
         const char *filename;
         unsigned lineno;
         JSPrincipals *originPrincipals;
         uint32_t pcOffset;
         DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                               &originPrincipals, CALLED_FROM_JSOP_EVAL);
 
         const char *introducerFilename = filename;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1085,68 +1085,64 @@ JS_WrapId(JSContext *cx, JS::MutableHand
 JS_PUBLIC_API(JSObject *)
 JS_TransplantObject(JSContext *cx, HandleObject origobj, HandleObject target)
 {
     AssertHeapIsIdle(cx);
     JS_ASSERT(origobj != target);
     JS_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
     JS_ASSERT(!target->is<CrossCompartmentWrapperObject>());
 
+    AutoMaybeTouchDeadZones agc(cx);
+    AutoDisableProxyCheck adpc(cx->runtime());
+
+    JSCompartment *destination = target->compartment();
     RootedValue origv(cx, ObjectValue(*origobj));
     RootedObject newIdentity(cx);
 
-    {
-        // Scope to make ~AutoMaybeTouchDeadZones do its GC before the return value is on the stack.
-        AutoMaybeTouchDeadZones agc(cx);
-        AutoDisableProxyCheck adpc(cx->runtime());
-
-        JSCompartment *destination = target->compartment();
-
-        if (origobj->compartment() == destination) {
-            // If the original object is in the same compartment as the
-            // destination, then we know that we won't find a wrapper in the
-            // destination's cross compartment map and that the same
-            // object will continue to work.
-            if (!JSObject::swap(cx, origobj, target))
-                MOZ_CRASH();
-            newIdentity = origobj;
-        } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
-            // There might already be a wrapper for the original object in
-            // the new compartment. If there is, we use its identity and swap
-            // in the contents of |target|.
-            newIdentity = &p->value().get().toObject();
-
-            // When we remove origv from the wrapper map, its wrapper, newIdentity,
-            // must immediately cease to be a cross-compartment wrapper. Neuter it.
-            destination->removeWrapper(p);
-            NukeCrossCompartmentWrapper(cx, newIdentity);
-
-            if (!JSObject::swap(cx, newIdentity, target))
-                MOZ_CRASH();
-        } else {
-            // Otherwise, we use |target| for the new identity object.
-            newIdentity = target;
-        }
-
-        // Now, iterate through other scopes looking for references to the
-        // old object, and update the relevant cross-compartment wrappers.
-        if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
+    if (origobj->compartment() == destination) {
+        // If the original object is in the same compartment as the
+        // destination, then we know that we won't find a wrapper in the
+        // destination's cross compartment map and that the same
+        // object will continue to work.
+        if (!JSObject::swap(cx, origobj, target))
+            MOZ_CRASH();
+        newIdentity = origobj;
+    } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
+        // There might already be a wrapper for the original object in
+        // the new compartment. If there is, we use its identity and swap
+        // in the contents of |target|.
+        newIdentity = &p->value().get().toObject();
+
+        // When we remove origv from the wrapper map, its wrapper, newIdentity,
+        // must immediately cease to be a cross-compartment wrapper. Neuter it.
+        destination->removeWrapper(p);
+        NukeCrossCompartmentWrapper(cx, newIdentity);
+
+        if (!JSObject::swap(cx, newIdentity, target))
             MOZ_CRASH();
-
-        // Lastly, update the original object to point to the new one.
-        if (origobj->compartment() != destination) {
-            RootedObject newIdentityWrapper(cx, newIdentity);
-            AutoCompartment ac(cx, origobj);
-            if (!JS_WrapObject(cx, &newIdentityWrapper))
-                MOZ_CRASH();
-            JS_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
-            if (!JSObject::swap(cx, origobj, newIdentityWrapper))
-                MOZ_CRASH();
-            origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv);
-        }
+    } else {
+        // Otherwise, we use |target| for the new identity object.
+        newIdentity = target;
+    }
+
+    // Now, iterate through other scopes looking for references to the
+    // old object, and update the relevant cross-compartment wrappers.
+    if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
+        MOZ_CRASH();
+
+    // Lastly, update the original object to point to the new one.
+    if (origobj->compartment() != destination) {
+        RootedObject newIdentityWrapper(cx, newIdentity);
+        AutoCompartment ac(cx, origobj);
+        if (!JS_WrapObject(cx, &newIdentityWrapper))
+            MOZ_CRASH();
+        JS_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
+        if (!JSObject::swap(cx, origobj, newIdentityWrapper))
+            MOZ_CRASH();
+        origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv);
     }
 
     // The new identity object might be one of several things. Return it to avoid
     // ambiguity.
     return newIdentity;
 }
 
 /*
@@ -4611,39 +4607,35 @@ JS::CompileOptions::wrap(JSContext *cx, 
     if (introductionScriptRoot) {
         if (introductionScriptRoot->compartment() != compartment)
             introductionScriptRoot = nullptr;
     }
 
     return true;
 }
 
-bool
+JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
-            SourceBufferHolder &srcBuf, MutableHandleScript script)
+            SourceBufferHolder &srcBuf)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     AutoLastFrameCheck lfc(cx);
 
-    script.set(frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, srcBuf));
-    return !!script;
+    return frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, srcBuf);
 }
 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
             const jschar *chars, size_t length)
 {
     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    RootedScript script(cx);
-    if (!Compile(cx, obj, options, srcBuf, &script))
-        return nullptr;
-    return script;
+    return Compile(cx, obj, options, srcBuf);
 }
 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
             const char *bytes, size_t length)
 {
     jschar *chars;
     if (options.utf8)
@@ -4672,17 +4664,18 @@ JS::Compile(JSContext *cx, HandleObject 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg, const char *filename)
 {
     AutoFile file;
     if (!file.open(cx, filename))
         return nullptr;
     CompileOptions options(cx, optionsArg);
     options.setFileAndLine(filename, 1);
-    return Compile(cx, obj, options, file.fp());
+    JSScript *script = Compile(cx, obj, options, file.fp());
+    return script;
 }
 
 JS_PUBLIC_API(bool)
 JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length)
 {
     static const size_t TINY_LENGTH = 1000;
     static const size_t HUGE_LENGTH = 100 * 1000;
 
@@ -4716,26 +4709,21 @@ JS::CompileOffThread(JSContext *cx, cons
 }
 
 JS_PUBLIC_API(JSScript *)
 JS::FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token)
 {
 #ifdef JS_THREADSAFE
     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
 
-    if (maybecx) {
-        RootedScript script(maybecx);
-        {
-            AutoLastFrameCheck lfc(maybecx);
-            script = HelperThreadState().finishParseTask(maybecx, rt, token);
-        }
-        return script;
-    } else {
-        return HelperThreadState().finishParseTask(maybecx, rt, token);
-    }
+    Maybe<AutoLastFrameCheck> lfc;
+    if (maybecx)
+        lfc.construct(maybecx);
+
+    return HelperThreadState().finishParseTask(maybecx, rt, token);
 #else
     MOZ_ASSUME_UNREACHABLE("Off thread compilation is not available.");
 #endif
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_CompileScript(JSContext *cx, JS::HandleObject obj, const char *ascii,
                  size_t length, const JS::CompileOptions &options)
@@ -4790,69 +4778,66 @@ JS_BufferIsCompilableUnit(JSContext *cx,
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalFromScript(JSScript *script)
 {
     JS_ASSERT(!script->isCachedEval());
     return &script->global();
 }
 
-JS_PUBLIC_API(bool)
+JS_PUBLIC_API(JSFunction *)
 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
-                    SourceBufferHolder &srcBuf, MutableHandleFunction fun)
+                    SourceBufferHolder &srcBuf)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
+    AutoLastFrameCheck lfc(cx);
+
     RootedAtom funAtom(cx);
-    AutoLastFrameCheck lfc(cx);
-
     if (name) {
         funAtom = Atomize(cx, name, strlen(name));
         if (!funAtom)
-            return false;
+            return nullptr;
     }
 
     AutoNameVector formals(cx);
     for (unsigned i = 0; i < nargs; i++) {
         RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
         if (!argAtom || !formals.append(argAtom->asPropertyName()))
-            return false;
+            return nullptr;
     }
 
-    fun.set(NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED, obj,
-                        funAtom, JSFunction::FinalizeKind, TenuredObject));
+    RootedFunction fun(cx, NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED, obj,
+                                       funAtom, JSFunction::FinalizeKind, TenuredObject));
     if (!fun)
-        return false;
-
-    if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf))
-        return false;
+        return nullptr;
+
+    if (!frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf))
+        return nullptr;
 
     if (obj && funAtom && options.defineOnScope) {
         Rooted<jsid> id(cx, AtomToId(funAtom));
         RootedValue value(cx, ObjectValue(*fun));
         if (!JSObject::defineGeneric(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE))
-            return false;
+            return nullptr;
     }
 
-    return true;
+    return fun;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
                     const jschar *chars, size_t length)
 {
-    RootedFunction fun(cx);
-    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    if (!JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf, &fun))
-        return nullptr;
-    return fun;
+  SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
+  return JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf);
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
                     const char *bytes, size_t length)
 {
     jschar *chars;
@@ -5210,22 +5195,23 @@ JS::Call(JSContext *cx, HandleValue this
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, thisv, fval, args);
     AutoLastFrameCheck lfc(cx);
 
     return Invoke(cx, thisv, fval, args.length(), args.begin(), rval);
 }
 
-static JSObject *
-JS_NewHelper(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
+JS_PUBLIC_API(JSObject *)
+JS_New(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, ctor, inputArgs);
+    AutoLastFrameCheck lfc(cx);
 
     // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
     // is not a simple variation of JSOP_CALL. We have to determine what class
     // of object to create, create it, and clamp the return value to an object,
     // among other details. InvokeConstructor does the hard work.
     InvokeArgs args(cx);
     if (!args.init(inputArgs.length()))
         return nullptr;
@@ -5248,27 +5234,16 @@ JS_NewHelper(JSContext *cx, HandleObject
                                  bytes.ptr());
         }
         return nullptr;
     }
 
     return &args.rval().toObject();
 }
 
-JS_PUBLIC_API(JSObject *)
-JS_New(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
-{
-    RootedObject obj(cx);
-    {
-        AutoLastFrameCheck lfc(cx);
-        obj = JS_NewHelper(cx, ctor, inputArgs);
-    }
-    return obj;
-}
-
 JS_PUBLIC_API(JSInterruptCallback)
 JS_SetInterruptCallback(JSRuntime *rt, JSInterruptCallback callback)
 {
     JSInterruptCallback old = rt->interruptCallback;
     rt->interruptCallback = callback;
     return old;
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3742,32 +3742,29 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Comp
     }
 
     virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE;
 
   private:
     void operator=(const CompileOptions &rhs) MOZ_DELETE;
 };
 
-/*
- * |script| will always be set. On failure, it will be set to nullptr.
- */
-extern JS_PUBLIC_API(bool)
-Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
-        SourceBufferHolder &srcBuf, JS::MutableHandleScript script);
-
 extern JS_PUBLIC_API(JSScript *)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
         const char *bytes, size_t length);
 
 extern JS_PUBLIC_API(JSScript *)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
         const jschar *chars, size_t length);
 
 extern JS_PUBLIC_API(JSScript *)
+Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
+        SourceBufferHolder &srcBuf);
+
+extern JS_PUBLIC_API(JSScript *)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, FILE *file);
 
 extern JS_PUBLIC_API(JSScript *)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *filename);
 
 extern JS_PUBLIC_API(bool)
 CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length);
 
@@ -3790,31 +3787,31 @@ CanCompileOffThread(JSContext *cx, const
 extern JS_PUBLIC_API(bool)
 CompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options,
                  const jschar *chars, size_t length,
                  OffThreadCompileCallback callback, void *callbackData);
 
 extern JS_PUBLIC_API(JSScript *)
 FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token);
 
-extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
-                const char *name, unsigned nargs, const char *const *argnames,
-                SourceBufferHolder &srcBuf, JS::MutableHandleFunction fun);
-
 extern JS_PUBLIC_API(JSFunction *)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
                 const char *bytes, size_t length);
 
 extern JS_PUBLIC_API(JSFunction *)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
                 const jschar *chars, size_t length);
 
+extern JS_PUBLIC_API(JSFunction *)
+CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
+                const char *name, unsigned nargs, const char *const *argnames,
+                SourceBufferHolder &srcBuf);
+
 } /* namespace JS */
 
 extern JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JS::Handle<JSScript*> script, const char *name, unsigned indent);
 
 /*
  * API extension: OR this into indent to avoid pretty-printing the decompiled
  * source resulting from JS_DecompileFunction{,Body}.
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -920,17 +920,17 @@ JSCompartment::removeDebuggeeUnderGC(Fre
     if (debuggees.empty()) {
         debugModeBits &= ~DebugFromJS;
         if (wasEnabled && !debugMode())
             DebugScopes::onCompartmentLeaveDebugMode(this);
     }
 }
 
 void
-JSCompartment::clearBreakpointsIn(FreeOp *fop, js::Debugger *dbg, HandleObject handler)
+JSCompartment::clearBreakpointsIn(FreeOp *fop, js::Debugger *dbg, JSObject *handler)
 {
     for (gc::ZoneCellIter i(zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
         if (script->compartment() == this && script->hasAnyBreakpointsOrStepMode())
             script->clearBreakpointsIn(fop, dbg, handler);
     }
 }
 
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -418,17 +418,17 @@ struct JSCompartment
     void removeDebuggeeUnderGC(js::FreeOp *fop, js::GlobalObject *global,
                                js::GlobalObjectSet::Enum *debuggeesEnum = nullptr);
     void removeDebuggeeUnderGC(js::FreeOp *fop, js::GlobalObject *global,
                                js::AutoDebugModeInvalidation &invalidate,
                                js::GlobalObjectSet::Enum *debuggeesEnum = nullptr);
     bool setDebugModeFromC(JSContext *cx, bool b,
                            js::AutoDebugModeInvalidation &invalidate);
 
-    void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JS::HandleObject handler);
+    void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JSObject *handler);
     void clearTraps(js::FreeOp *fop);
 
   private:
     void sweepBreakpoints(js::FreeOp *fop);
 
   public:
     js::WatchpointMap *watchpointMap;
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1528,17 +1528,17 @@ FunctionConstructor(JSContext *cx, unsig
     AutoKeepAtoms keepAtoms(cx->perThreadData);
     AutoNameVector formals(cx);
 
     bool hasRest = false;
 
     bool isStarGenerator = generatorKind == StarGenerator;
     JS_ASSERT(generatorKind != LegacyGenerator);
 
-    RootedScript maybeScript(cx);
+    JSScript *maybeScript = nullptr;
     const char *filename;
     unsigned lineno;
     JSPrincipals *originPrincipals;
     uint32_t pcOffset;
     DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                          &originPrincipals);
 
     const char *introductionType = "Function";
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -2805,57 +2805,57 @@ js_GetScriptLineExtent(JSScript *script)
         if (maxLineNo < lineno)
             maxLineNo = lineno;
     }
 
     return 1 + maxLineNo - script->lineno();
 }
 
 void
-js::DescribeScriptedCallerForCompilation(JSContext *cx, MutableHandleScript maybeScript,
+js::DescribeScriptedCallerForCompilation(JSContext *cx, JSScript **maybeScript,
                                          const char **file, unsigned *linenop,
                                          uint32_t *pcOffset, JSPrincipals **origin,
                                          LineOption opt)
 {
     if (opt == CALLED_FROM_JSOP_EVAL) {
         jsbytecode *pc = nullptr;
-        maybeScript.set(cx->currentScript(&pc));
+        *maybeScript = cx->currentScript(&pc);
         JS_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_SPREADEVAL);
         JS_ASSERT(*(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH
                                                  : JSOP_SPREADEVAL_LENGTH)) == JSOP_LINENO);
-        *file = maybeScript->filename();
+        *file = (*maybeScript)->filename();
         *linenop = GET_UINT16(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH
                                                            : JSOP_SPREADEVAL_LENGTH));
-        *pcOffset = pc - maybeScript->code();
-        *origin = maybeScript->originPrincipals();
+        *pcOffset = pc - (*maybeScript)->code();
+        *origin = (*maybeScript)->originPrincipals();
         return;
     }
 
     NonBuiltinFrameIter iter(cx);
 
     if (iter.done()) {
-        maybeScript.set(nullptr);
+        *maybeScript = nullptr;
         *file = nullptr;
         *linenop = 0;
         *pcOffset = 0;
         *origin = cx->compartment()->principals;
         return;
     }
 
     *file = iter.scriptFilename();
     *linenop = iter.computeLine();
     *origin = iter.originPrincipals();
 
     // These values are only used for introducer fields which are debugging
     // information and can be safely left null for asm.js frames.
     if (iter.hasScript()) {
-        maybeScript.set(iter.script());
-        *pcOffset = iter.pc() - maybeScript->code();
+        *maybeScript = iter.script();
+        *pcOffset = iter.pc() - (*maybeScript)->code();
     } else {
-        maybeScript.set(nullptr);
+        *maybeScript = nullptr;
         *pcOffset = 0;
     }
 }
 
 template <class T>
 static inline T *
 Rebase(JSScript *dst, JSScript *src, T *srcp)
 {
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1977,17 +1977,17 @@ PCToLineNumber(unsigned startLine, jssrc
  */
 
 enum LineOption {
     CALLED_FROM_JSOP_EVAL,
     NOT_CALLED_FROM_JSOP_EVAL
 };
 
 extern void
-DescribeScriptedCallerForCompilation(JSContext *cx, MutableHandleScript maybeScript,
+DescribeScriptedCallerForCompilation(JSContext *cx, JSScript **maybeScript,
                                      const char **file, unsigned *linenop,
                                      uint32_t *pcOffset, JSPrincipals **origin,
                                      LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
 
 bool
 CloneFunctionScript(JSContext *cx, HandleFunction original, HandleFunction clone,
                     NewObjectKind newKind = GenericObject);
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2192,17 +2192,17 @@ Debugger::getNewestFrame(JSContext *cx, 
 }
 
 bool
 Debugger::clearAllBreakpoints(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGGER(cx, argc, vp, "clearAllBreakpoints", args, dbg);
     for (GlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront())
         r.front()->compartment()->clearBreakpointsIn(cx->runtime()->defaultFreeOp(),
-                                                     dbg, NullPtr());
+                                                     dbg, nullptr);
     return true;
 }
 
 bool
 Debugger::construct(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
--- a/js/src/vm/ForkJoin.cpp
+++ b/js/src/vm/ForkJoin.cpp
@@ -1927,17 +1927,17 @@ class ParallelSpewer
     }
 
     void beginOp(JSContext *cx, const char *name) {
         if (!active[SpewOps])
             return;
 
         if (cx) {
             jsbytecode *pc;
-            RootedScript script(cx, cx->currentScript(&pc));
+            JSScript *script = cx->currentScript(&pc);
             if (script && pc) {
                 NonBuiltinScriptFrameIter iter(cx);
                 if (iter.done()) {
                     spew(SpewOps, "%sBEGIN %s%s (%s:%u)", bold(), name, reset(),
                          script->filename(), PCToLineNumber(script, pc));
                 } else {
                     spew(SpewOps, "%sBEGIN %s%s (%s:%u -> %s:%u)", bold(), name, reset(),
                          iter.script()->filename(), PCToLineNumber(iter.script(), iter.pc()),
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -11,33 +11,32 @@
 #include "jscntxt.h"
 
 #include "gc/Marking.h"
 #ifdef JS_ION
 #include "jit/AsmJSModule.h"
 #include "jit/BaselineFrame.h"
 #include "jit/JitCompartment.h"
 #endif
-#include "js/GCAPI.h"
 #include "vm/Opcodes.h"
 
 #include "jit/JitFrameIterator-inl.h"
 #include "vm/Interpreter-inl.h"
 #include "vm/Probes-inl.h"
 #include "vm/ScopeObject-inl.h"
 
 using namespace js;
 
 using mozilla::PodCopy;
 
 /*****************************************************************************/
 
 void
 InterpreterFrame::initExecuteFrame(JSContext *cx, JSScript *script, AbstractFramePtr evalInFramePrev,
-                                   const Value &thisv, JSObject &scopeChain, ExecuteType type)
+                             const Value &thisv, JSObject &scopeChain, ExecuteType type)
 {
     /*
      * See encoding of ExecuteType. When GLOBAL isn't set, we are executing a
      * script in the context of another frame and the frame type is determined
      * by the context.
      */
     flags_ = type | HAS_SCOPECHAIN;
 
@@ -664,30 +663,26 @@ FrameIter::Data::Data(const FrameIter::D
 }
 
 FrameIter::FrameIter(ThreadSafeContext *cx, SavedOption savedOption)
   : data_(cx, savedOption, CURRENT_CONTEXT, nullptr)
 #ifdef JS_ION
   , ionInlineFrames_(cx, (js::jit::JitFrameIterator*) nullptr)
 #endif
 {
-    // settleOnActivation can only GC if principals are given.
-    JS::AutoSuppressGCAnalysis nogc;
     settleOnActivation();
 }
 
 FrameIter::FrameIter(ThreadSafeContext *cx, ContextOption contextOption,
                      SavedOption savedOption)
   : data_(cx, savedOption, contextOption, nullptr)
 #ifdef JS_ION
   , ionInlineFrames_(cx, (js::jit::JitFrameIterator*) nullptr)
 #endif
 {
-    // settleOnActivation can only GC if principals are given.
-    JS::AutoSuppressGCAnalysis nogc;
     settleOnActivation();
 }
 
 FrameIter::FrameIter(JSContext *cx, ContextOption contextOption,
                      SavedOption savedOption, JSPrincipals *principals)
   : data_(cx, savedOption, contextOption, principals)
 #ifdef JS_ION
   , ionInlineFrames_(cx, (js::jit::JitFrameIterator*) nullptr)
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -90,23 +90,23 @@ ReportError(JSContext *cx, const char *m
     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, JS::MutableHandleScript script,
-                                 JS::MutableHandleFunction function)
+                                 bool reuseGlobal, JSScript **scriptp,
+                                 JSFunction **functionp)
 {
     RootedObject target_obj(cx, targetObjArg);
 
-    script.set(nullptr);
-    function.set(nullptr);
+    *scriptp = nullptr;
+    *functionp = nullptr;
 
     // Instead of calling NS_OpenURI, we create the channel ourselves and call
     // SetContentType, to avoid expensive MIME type lookups (bug 632490).
     nsCOMPtr<nsIChannel> chan;
     nsCOMPtr<nsIInputStream> instream;
     nsresult rv = NS_NewChannel(getter_AddRefs(chan), uri, serv,
                                 nullptr, nullptr, nsIRequest::LOAD_NORMAL);
     if (NS_SUCCEEDED(rv)) {
@@ -150,33 +150,32 @@ mozJSSubScriptLoader::ReadScript(nsIURI 
         JS::SourceBufferHolder srcBuf(scriptBuf, scriptLength,
                                       JS::SourceBufferHolder::GiveOwnership);
 
         if (NS_FAILED(rv)) {
             return ReportError(cx, LOAD_ERROR_BADCHARSET);
         }
 
         if (!reuseGlobal) {
-            JS::Compile(cx, target_obj, options, srcBuf, script);
+            *scriptp = JS::Compile(cx, target_obj, options, srcBuf);
         } else {
-            JS::CompileFunction(cx, target_obj, options,
-                                nullptr, 0, nullptr,
-                                srcBuf,
-                                function);
+            *functionp = JS::CompileFunction(cx, target_obj, options,
+                                             nullptr, 0, nullptr,
+                                             srcBuf);
         }
     } else {
         // We only use lazy source when no special encoding is specified because
         // the lazy source loader doesn't know the encoding.
         if (!reuseGlobal) {
             options.setSourceIsLazy(true);
-            script.set(JS::Compile(cx, target_obj, options, buf.get(), len));
+            *scriptp = JS::Compile(cx, target_obj, options, buf.get(), len);
         } else {
-            function.set(JS::CompileFunction(cx, target_obj, options,
+            *functionp = JS::CompileFunction(cx, target_obj, options,
                                              nullptr, 0, nullptr, buf.get(),
-                                             len));
+                                             len);
         }
     }
 
     /* repent for our evil deeds */
     JS_SetErrorReporter(cx, er);
 
     return NS_OK;
 }
@@ -329,17 +328,17 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
 
     RootedFunction function(cx);
     RootedScript script(cx);
     if (cache && !options.ignoreCache)
         rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script);
     if (!script) {
         rv = ReadScript(uri, cx, targetObj, options.charset,
                         static_cast<const char*>(uriStr.get()), serv,
-                        principal, reusingGlobal, &script, &function);
+                        principal, reusingGlobal, script.address(), function.address());
         writeScript = !!script;
     }
 
     if (NS_FAILED(rv) || (!script && !function))
         return rv;
 
     if (function) {
         script = JS_GetFunctionScript(cx, function);
--- a/js/xpconnect/loader/mozJSSubScriptLoader.h
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.h
@@ -30,18 +30,18 @@ public:
     // all the interface method declarations...
     NS_DECL_ISUPPORTS
     NS_DECL_MOZIJSSUBSCRIPTLOADER
 
 private:
     nsresult ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_obj,
                         const nsAString &charset, const char *uriStr,
                         nsIIOService *serv, nsIPrincipal *principal,
-                        bool reuseGlobal, JS::MutableHandleScript script,
-                        JS::MutableHandleFunction function);
+                        bool reuseGlobal, JSScript **scriptp,
+                        JSFunction **functionp);
 
     nsresult DoLoadSubScriptWithOptions(const nsAString &url,
                                         LoadSubScriptOptions  &options,
                                         JSContext *cx,
                                         JS::MutableHandle<JS::Value> retval);
 
     nsCOMPtr<nsIPrincipal> mSystemPrincipal;
 };
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3174,18 +3174,18 @@ nsXPCComponents_Utils::ForcePrivilegedCo
 NS_IMETHODIMP
 nsXPCComponents_Utils::GetComponentsForScope(HandleValue vscope, JSContext *cx,
                                              MutableHandleValue rval)
 {
     if (!vscope.isObject())
         return NS_ERROR_INVALID_ARG;
     JSObject *scopeObj = js::UncheckedUnwrap(&vscope.toObject());
     XPCWrappedNativeScope *scope = GetObjectScope(scopeObj);
-    RootedObject components(cx);
-    if (!scope->GetComponentsJSObject(&components))
+    RootedObject components(cx, scope->GetComponentsJSObject());
+    if (!components)
         return NS_ERROR_FAILURE;
     if (!JS_WrapObject(cx, &components))
         return NS_ERROR_FAILURE;
     rval.setObject(*components);
     return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -122,44 +122,44 @@ XPCWrappedNativeScope::IsDyingScope(XPCW
 {
     for (XPCWrappedNativeScope *cur = gDyingScopes; cur; cur = cur->mNext) {
         if (scope == cur)
             return true;
     }
     return false;
 }
 
-bool
-XPCWrappedNativeScope::GetComponentsJSObject(JS::MutableHandleObject obj)
+JSObject*
+XPCWrappedNativeScope::GetComponentsJSObject()
 {
     AutoJSContext cx;
     if (!mComponents) {
         nsIPrincipal *p = GetPrincipal();
         bool system = nsXPConnect::SecurityManager()->IsSystemPrincipal(p);
         mComponents = system ? new nsXPCComponents(this)
                              : new nsXPCComponentsBase(this);
     }
 
     RootedValue val(cx);
     xpcObjectHelper helper(mComponents);
     bool ok = XPCConvert::NativeInterface2JSObject(&val, nullptr, helper,
                                                    nullptr, nullptr, false,
                                                    nullptr);
     if (NS_WARN_IF(!ok))
-        return false;
+        return nullptr;
 
     if (NS_WARN_IF(!val.isObject()))
-        return false;
+        return nullptr;
 
     // The call to wrap() here is necessary even though the object is same-
     // compartment, because it applies our security wrapper.
-    obj.set(&val.toObject());
-    if (NS_WARN_IF(!JS_WrapObject(cx, obj)))
-        return false;
-    return true;
+    JS::RootedObject obj(cx, &val.toObject());
+    if (NS_WARN_IF(!JS_WrapObject(cx, &obj)))
+        return nullptr;
+    return obj;
 }
 
 void
 XPCWrappedNativeScope::ForcePrivilegedComponents()
 {
     // This may only be called on unprivileged scopes during automation where
     // we allow insecure things.
     MOZ_RELEASE_ASSERT(Preferences::GetBool("security.turn_off_all_security_so_"
@@ -168,18 +168,18 @@ XPCWrappedNativeScope::ForcePrivilegedCo
     nsCOMPtr<nsIXPCComponents> c = do_QueryInterface(mComponents);
     if (!c)
         mComponents = new nsXPCComponents(this);
 }
 
 bool
 XPCWrappedNativeScope::AttachComponentsObject(JSContext* aCx)
 {
-    RootedObject components(aCx);
-    if (!GetComponentsJSObject(&components))
+    RootedObject components(aCx, GetComponentsJSObject());
+    if (!components)
         return false;
 
     RootedObject global(aCx, GetGlobalJSObject());
     MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx));
 
     RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS));
     return JS_DefinePropertyById(aCx, global, id, components,
                                  JSPROP_PERMANENT | JSPROP_READONLY);
@@ -595,17 +595,17 @@ WNProtoRemover(PLDHashTable *table, PLDH
 void
 XPCWrappedNativeScope::RemoveWrappedNativeProtos()
 {
     mWrappedNativeProtoMap->Enumerate(WNProtoRemover,
                                       GetRuntime()->GetDetachedWrappedNativeProtoMap());
 }
 
 JSObject *
-XPCWrappedNativeScope::GetExpandoChain(HandleObject target)
+XPCWrappedNativeScope::GetExpandoChain(JSObject *target)
 {
     MOZ_ASSERT(GetObjectScope(target) == this);
     if (!mXrayExpandos.initialized())
         return nullptr;
     return mXrayExpandos.lookup(target);
 }
 
 bool
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -979,18 +979,18 @@ public:
     // Forces the creation of a privileged |Components| object, even in
     // content scopes. This will crash if used outside of automation.
     void
     ForcePrivilegedComponents();
 
     bool AttachComponentsObject(JSContext *aCx);
 
     // Returns the JS object reflection of the Components object.
-    bool
-    GetComponentsJSObject(JS::MutableHandleObject obj);
+    JSObject*
+    GetComponentsJSObject();
 
     JSObject*
     GetGlobalJSObject() const {
         JS::ExposeObjectToActiveJS(mGlobalJSObject);
         return mGlobalJSObject;
     }
 
     JSObject*
@@ -998,17 +998,17 @@ public:
 
     nsIPrincipal*
     GetPrincipal() const {
         JSCompartment *c = js::GetObjectCompartment(mGlobalJSObject);
         return nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
     }
 
     JSObject*
-    GetExpandoChain(JS::HandleObject target);
+    GetExpandoChain(JSObject *target);
 
     bool
     SetExpandoChain(JSContext *cx, JS::HandleObject target, JS::HandleObject chain);
 
     void RemoveWrappedNativeProtos();
 
     static void
     SystemIsBeingShutDown();
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -176,17 +176,17 @@ public:
                                HandleObject consumer);
     JSObject* ensureExpandoObject(JSContext *cx, HandleObject wrapper,
                                   HandleObject target);
 
     JSObject* getHolder(JSObject *wrapper);
     JSObject* ensureHolder(JSContext *cx, HandleObject wrapper);
     virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) = 0;
 
-    JSObject* getExpandoChain(HandleObject obj) {
+    JSObject* getExpandoChain(JSObject *obj) {
       return GetObjectScope(obj)->GetExpandoChain(obj);
     }
 
     bool setExpandoChain(JSContext *cx, HandleObject obj, HandleObject chain) {
       return GetObjectScope(obj)->SetExpandoChain(cx, obj, chain);
     }
     bool cloneExpandoChain(JSContext *cx, HandleObject dst, HandleObject src);
 
--- a/tools/profiler/ProfileEntry.cpp
+++ b/tools/profiler/ProfileEntry.cpp
@@ -476,24 +476,20 @@ void ThreadProfile::StreamJSObject(JSStr
     b.EndArray();
   b.EndObject();
 }
 
 JSObject* ThreadProfile::ToJSObject(JSContext *aCx)
 {
   JS::RootedValue val(aCx);
   std::stringstream ss;
-  {
-    // Define a scope to prevent a moving GC during ~JSStreamWriter from
-    // trashing the return value.
-    JSStreamWriter b(ss);
-    StreamJSObject(b);
-    NS_ConvertUTF8toUTF16 js_string(nsDependentCString(ss.str().c_str()));
-    JS_ParseJSON(aCx, static_cast<const jschar*>(js_string.get()), js_string.Length(), &val);
-  }
+  JSStreamWriter b(ss);
+  StreamJSObject(b);
+  NS_ConvertUTF8toUTF16 js_string(nsDependentCString(ss.str().c_str()));
+  JS_ParseJSON(aCx, static_cast<const jschar*>(js_string.get()), js_string.Length(), &val);
   return &val.toObject();
 }
 
 PseudoStack* ThreadProfile::GetPseudoStack()
 {
   return mPseudoStack;
 }
 
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -165,24 +165,20 @@ void TableTicker::ToStreamAsJSON(std::os
   JSStreamWriter b(stream);
   StreamJSObject(b);
 }
 
 JSObject* TableTicker::ToJSObject(JSContext *aCx)
 {
   JS::RootedValue val(aCx);
   std::stringstream ss;
-  {
-    // Define a scope to prevent a moving GC during ~JSStreamWriter from
-    // trashing the return value.
-    JSStreamWriter b(ss);
-    StreamJSObject(b);
-    NS_ConvertUTF8toUTF16 js_string(nsDependentCString(ss.str().c_str()));
-    JS_ParseJSON(aCx, static_cast<const jschar*>(js_string.get()), js_string.Length(), &val);
-  }
+  JSStreamWriter b(ss);
+  StreamJSObject(b);
+  NS_ConvertUTF8toUTF16 js_string(nsDependentCString(ss.str().c_str()));
+  JS_ParseJSON(aCx, static_cast<const jschar*>(js_string.get()), js_string.Length(), &val);
   return &val.toObject();
 }
 
 struct SubprocessClosure {
   SubprocessClosure(JSStreamWriter *aWriter)
     : mWriter(aWriter)
   {}