Bug 866450 Part 6: Fix rooting hazards under content/ and dom/ r=bz
☠☠ backed out by 872f39ccacf0 ☠ ☠
authorDavid Zbarsky <dzbarsky@gmail.com>
Thu, 02 May 2013 05:12:47 -0400
changeset 130575 7c0ace2560c4b6949f915c25a60b0ff60e839b3a
parent 130574 c5ba9c0dc252a5046e3500728fd73f8dd2633379
child 130576 e0b51717bb643cd96fe8d29d5840c4388a58d808
push id27434
push userdzbarsky@gmail.com
push dateThu, 02 May 2013 09:12:44 +0000
treeherdermozilla-inbound@e0b51717bb64 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs866450
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 866450 Part 6: Fix rooting hazards under content/ and dom/ r=bz
dom/indexedDB/AsyncConnectionHelper.cpp
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBFactory.cpp
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBKeyRange.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/Key.cpp
dom/indexedDB/KeyPath.cpp
dom/indexedDB/ipc/IndexedDBParent.cpp
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -51,39 +51,39 @@ private:
 // something fails.
 inline
 nsresult
 ConvertCloneReadInfosToArrayInternal(
                                 JSContext* aCx,
                                 nsTArray<StructuredCloneReadInfo>& aReadInfos,
                                 jsval* aResult)
 {
-  JSObject* array = JS_NewArrayObject(aCx, 0, nullptr);
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
   if (!array) {
     NS_WARNING("Failed to make array!");
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   if (!aReadInfos.IsEmpty()) {
     if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) {
       NS_WARNING("Failed to set array length!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     for (uint32_t index = 0, count = aReadInfos.Length(); index < count;
          index++) {
       StructuredCloneReadInfo& readInfo = aReadInfos[index];
 
-      jsval val;
-      if (!IDBObjectStore::DeserializeValue(aCx, readInfo, &val)) {
+      JS::Rooted<JS::Value> val(aCx);
+      if (!IDBObjectStore::DeserializeValue(aCx, readInfo, val.address())) {
         NS_WARNING("Failed to decode!");
         return NS_ERROR_DOM_DATA_CLONE_ERR;
       }
 
-      if (!JS_SetElement(aCx, array, index, &val)) {
+      if (!JS_SetElement(aCx, array, index, val.address())) {
         NS_WARNING("Failed to set array element!");
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
     }
   }
 
   *aResult = OBJECT_TO_JSVAL(array);
   return NS_OK;
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -603,18 +603,18 @@ IDBCursor::GetValue(JSContext* aCx,
   }
 
   if (!mHaveCachedValue) {
     if (!mRooted) {
       NS_HOLD_JS_OBJECTS(this, IDBCursor);
       mRooted = true;
     }
 
-    jsval val;
-    if (!IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, &val)) {
+    JS::Rooted<JS::Value> val(aCx);
+    if (!IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, val.address())) {
       return NS_ERROR_DOM_DATA_CLONE_ERR;
     }
 
     mCloneReadInfo.mCloneBuffer.clear();
 
     mCachedValue = val;
     mHaveCachedValue = true;
   }
@@ -735,18 +735,18 @@ IDBCursor::Update(const jsval& aValue,
     }
 
     rv = mObjectStore->Put(aValue, JSVAL_VOID, aCx, 0, getter_AddRefs(request));
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
   else {
-    jsval keyVal;
-    rv = objectKey.ToJSVal(aCx, &keyVal);
+    JS::Rooted<JS::Value> keyVal(aCx);
+    rv = objectKey.ToJSVal(aCx, keyVal.address());
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = mObjectStore->Put(aValue, keyVal, aCx, 1, getter_AddRefs(request));
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
@@ -806,18 +806,18 @@ IDBCursor::Delete(JSContext* aCx,
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   NS_ASSERTION(mObjectStore, "This cannot be null!");
   NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
 
   Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
 
-  jsval key;
-  nsresult rv = objectKey.ToJSVal(aCx, &key);
+  JS::Rooted<JS::Value> key(aCx);
+  nsresult rv = objectKey.ToJSVal(aCx, key.address());
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIIDBRequest> request;
   rv = mObjectStore->Delete(key, aCx, getter_AddRefs(request));
   if (NS_FAILED(rv)) {
     return rv;
   }
 
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -653,36 +653,36 @@ IDBDatabase::Transaction(const jsval& aS
       return NS_ERROR_TYPE_ERR;
     }
   }
 
   nsresult rv;
   nsTArray<nsString> storesToOpen;
 
   if (!JSVAL_IS_PRIMITIVE(aStoreNames)) {
-    JSObject* obj = JSVAL_TO_OBJECT(aStoreNames);
+    JS::Rooted<JSObject*> obj(aCx, JSVAL_TO_OBJECT(aStoreNames));
 
     // See if this is a JS array.
     if (JS_IsArrayObject(aCx, obj)) {
       uint32_t length;
       if (!JS_GetArrayLength(aCx, obj, &length)) {
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
 
       if (!length) {
         return NS_ERROR_DOM_INVALID_ACCESS_ERR;
       }
 
       storesToOpen.SetCapacity(length);
 
       for (uint32_t index = 0; index < length; index++) {
-        jsval val;
+        JS::Rooted<JS::Value> val(aCx);
         JSString* jsstr;
         nsDependentJSString str;
-        if (!JS_GetElement(aCx, obj, index, &val) ||
+        if (!JS_GetElement(aCx, obj, index, val.address()) ||
             !(jsstr = JS_ValueToString(aCx, val)) ||
             !str.init(aCx, jsstr)) {
           return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
         }
 
         storesToOpen.AppendElement(str);
       }
 
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -213,18 +213,18 @@ IDBFactory::Create(ContentParent* aConte
 
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   NS_ASSERTION(xpc, "This should never be null!");
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
   nsresult rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  JSObject* global;
-  rv = globalHolder->GetJSObject(&global);
+  JS::Rooted<JSObject*> global(cx);
+  rv = globalHolder->GetJSObject(global.address());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The CreateSandbox call returns a proxy to the actual sandbox object. We
   // don't need a proxy here.
   global = js::UncheckedUnwrap(global);
 
   JSAutoCompartment ac(cx, global);
 
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -1488,40 +1488,40 @@ GetAllKeysHelper::GetSuccessResult(JSCon
 {
   NS_ASSERTION(mKeys.Length() <= mLimit, "Too many results!");
 
   nsTArray<Key> keys;
   mKeys.SwapElements(keys);
 
   JSAutoRequest ar(aCx);
 
-  JSObject* array = JS_NewArrayObject(aCx, 0, NULL);
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, NULL));
   if (!array) {
     NS_WARNING("Failed to make array!");
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   if (!keys.IsEmpty()) {
     if (!JS_SetArrayLength(aCx, array, uint32_t(keys.Length()))) {
       NS_WARNING("Failed to set array length!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     for (uint32_t index = 0, count = keys.Length(); index < count; index++) {
       const Key& key = keys[index];
       NS_ASSERTION(!key.IsUnset(), "Bad key!");
 
-      jsval value;
-      nsresult rv = key.ToJSVal(aCx, &value);
+      JS::Rooted<JS::Value> value(aCx);
+      nsresult rv = key.ToJSVal(aCx, value.address());
       if (NS_FAILED(rv)) {
         NS_WARNING("Failed to get jsval for key!");
         return rv;
       }
 
-      if (!JS_SetElement(aCx, array, index, &value)) {
+      if (!JS_SetElement(aCx, array, index, value.address())) {
         NS_WARNING("Failed to set array element!");
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
     }
   }
 
   *aVal = OBJECT_TO_JSVAL(array);
   return NS_OK;
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -47,18 +47,18 @@ ReturnKeyRange(JSContext* aCx,
   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   if (NS_FAILED(xpc->WrapNative(aCx, global, aKeyRange,
                                 NS_GET_IID(nsIIDBKeyRange),
                                 getter_AddRefs(holder)))) {
     JS_ReportError(aCx, "Couldn't wrap IDBKeyRange object.");
     return false;
   }
 
-  JSObject* result;
-  if (NS_FAILED(holder->GetJSObject(&result))) {
+  JS::Rooted<JSObject*> result(aCx);
+  if (NS_FAILED(holder->GetJSObject(result.address()))) {
     JS_ReportError(aCx, "Couldn't get JSObject from wrapper.");
     return false;
   }
 
   JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(result));
   return true;
 }
 
@@ -108,18 +108,18 @@ GetKeyFromJSValOrThrow(JSContext* aCx,
 
 JSBool
 MakeOnlyKeyRange(JSContext* aCx,
                  unsigned aArgc,
                  jsval* aVp)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  jsval val;
-  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &val)) {
+  JS::Rooted<JS::Value> val(aCx);
+  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", val.address())) {
     return false;
   }
 
   nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(false, false, true);
 
   if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Lower())) {
     return false;
   }
@@ -129,19 +129,19 @@ MakeOnlyKeyRange(JSContext* aCx,
 
 JSBool
 MakeLowerBoundKeyRange(JSContext* aCx,
                        unsigned aArgc,
                        jsval* aVp)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  jsval val;
+  JS::Rooted<JS::Value> val(aCx);
   JSBool open = false;
-  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", &val, &open)) {
+  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", val.address(), &open)) {
     return false;
   }
 
   nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(open, true, false);
 
   if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Lower())) {
     return false;
   }
@@ -151,19 +151,19 @@ MakeLowerBoundKeyRange(JSContext* aCx,
 
 JSBool
 MakeUpperBoundKeyRange(JSContext* aCx,
                        unsigned aArgc,
                        jsval* aVp)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  jsval val;
+  JS::Rooted<JS::Value> val(aCx);
   JSBool open = false;
-  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", &val, &open)) {
+  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", val.address(), &open)) {
     return false;
   }
 
   nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(true, open, false);
 
   if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Upper())) {
     return false;
   }
@@ -173,20 +173,20 @@ MakeUpperBoundKeyRange(JSContext* aCx,
 
 JSBool
 MakeBoundKeyRange(JSContext* aCx,
                   unsigned aArgc,
                   jsval* aVp)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  jsval lowerVal, upperVal;
+  JS::Rooted<JS::Value> lowerVal(aCx), upperVal(aCx);
   JSBool lowerOpen = false, upperOpen = false;
-  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "vv/bb", &lowerVal,
-                           &upperVal, &lowerOpen, &upperOpen)) {
+  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "vv/bb", lowerVal.address(),
+                           upperVal.address(), &lowerOpen, &upperOpen)) {
     return false;
   }
 
   nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(lowerOpen, upperOpen, false);
 
   if (!GetKeyFromJSValOrThrow(aCx, lowerVal, keyRange->Lower()) ||
       !GetKeyFromJSValOrThrow(aCx, upperVal, keyRange->Upper())) {
     return false;
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -721,21 +721,21 @@ public:
         }
         domBlob = aFile.mFile;
       }
       else {
         domBlob = new nsDOMFileFile(aData.type, aData.size, nativeFile,
                                     fileInfo);
       }
 
-      jsval wrappedBlob;
+      JS::Rooted<JS::Value> wrappedBlob(aCx);
       JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForScopeChain(aCx));
        rv =
         nsContentUtils::WrapNative(aCx, global, domBlob,
-                                   &NS_GET_IID(nsIDOMBlob), &wrappedBlob);
+                                   &NS_GET_IID(nsIDOMBlob), wrappedBlob.address());
       if (NS_FAILED(rv)) {
         NS_WARNING("Failed to wrap native!");
         return nullptr;
       }
 
       return JSVAL_TO_OBJECT(wrappedBlob);
     }
 
@@ -748,21 +748,21 @@ public:
       domFile = do_QueryInterface(aFile.mFile);
       NS_ASSERTION(domFile, "This should never fail!");
     }
     else {
       domFile = new nsDOMFileFile(aData.name, aData.type, aData.size,
                                   nativeFile, fileInfo);
     }
 
-    jsval wrappedFile;
+    JS::Rooted<JS::Value> wrappedFile(aCx);
     JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForScopeChain(aCx));
     rv =
       nsContentUtils::WrapNative(aCx, global, domFile,
-                                 &NS_GET_IID(nsIDOMFile), &wrappedFile);
+                                 &NS_GET_IID(nsIDOMFile), wrappedFile.address());
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to wrap native!");
       return nullptr;
     }
 
     return JSVAL_TO_OBJECT(wrappedFile);
   }
 };
@@ -790,27 +790,27 @@ public:
                aData.tag == SCTAG_DOM_BLOB);
 
     // The following properties are available for use in index creation
     //   Blob.size
     //   Blob.type
     //   File.name
     //   File.lastModifiedDate
 
-    JSObject* obj = JS_NewObject(aCx, nullptr, nullptr, nullptr);
+    JS::Rooted<JSObject*> obj(aCx, JS_NewObject(aCx, nullptr, nullptr, nullptr));
     if (!obj) {
       NS_WARNING("Failed to create object!");
       return nullptr;
     }
 
     // Technically these props go on the proto, but this detail won't change
     // the results of index creation.
 
-    JSString* type =
-      JS_NewUCStringCopyN(aCx, aData.type.get(), aData.type.Length());
+    JS::RootedString type(aCx,
+      JS_NewUCStringCopyN(aCx, aData.type.get(), aData.type.Length()));
     if (!type ||
         !JS_DefineProperty(aCx, obj, "size",
                            JS_NumberValue((double)aData.size),
                            nullptr, nullptr, 0) ||
         !JS_DefineProperty(aCx, obj, "type", STRING_TO_JSVAL(type),
                            nullptr, nullptr, 0)) {
       return nullptr;
     }
@@ -925,25 +925,25 @@ IDBObjectStore::AppendIndexUpdateInfo(
 
   JS::Value val;
   if (NS_FAILED(aKeyPath.ExtractKeyAsJSVal(aCx, aVal, &val))) {
     return NS_OK;
   }
 
   if (!JSVAL_IS_PRIMITIVE(val) &&
       JS_IsArrayObject(aCx, JSVAL_TO_OBJECT(val))) {
-    JSObject* array = JSVAL_TO_OBJECT(val);
+    JS::Rooted<JSObject*> array(aCx, JSVAL_TO_OBJECT(val));
     uint32_t arrayLength;
     if (!JS_GetArrayLength(aCx, array, &arrayLength)) {
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     for (uint32_t arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) {
-      jsval arrayItem;
-      if (!JS_GetElement(aCx, array, arrayIndex, &arrayItem)) {
+      JS::Rooted<JS::Value> arrayItem(aCx);
+      if (!JS_GetElement(aCx, array, arrayIndex, arrayItem.address())) {
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
 
       Key value;
       if (NS_FAILED(value.SetFromJSVal(aCx, arrayItem)) ||
           value.IsUnset()) {
         // Not a value we can do anything with, ignore it.
         continue;
@@ -1813,17 +1813,17 @@ IDBObjectStore::AddOrPut(const jsval& aV
   if (!mTransaction->IsOpen()) {
     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
   }
 
   if (!IsWriteAllowed()) {
     return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR;
   }
 
-  jsval keyval = (aOptionalArgCount >= 1) ? aKey : JSVAL_VOID;
+  JS::Rooted<JS::Value> keyval(aCx, (aOptionalArgCount >= 1) ? aKey : JSVAL_VOID);
 
   StructuredCloneWriteInfo cloneWriteInfo;
   Key key;
   nsTArray<IndexUpdateInfo> updateInfo;
 
   nsresult rv = GetAddInfo(aCx, aValue, keyval, cloneWriteInfo, key,
                            updateInfo);
   if (NS_FAILED(rv)) {
@@ -4023,18 +4023,18 @@ CreateIndexHelper::InsertDataFromObjectS
     JSAutoStructuredCloneBuffer& buffer = cloneReadInfo.mCloneBuffer;
 
     JSStructuredCloneCallbacks callbacks = {
       IDBObjectStore::StructuredCloneReadCallback<CreateIndexDeserializationTraits>,
       nullptr,
       nullptr
     };
 
-    jsval clone;
-    if (!buffer.read(cx, &clone, &callbacks, &cloneReadInfo)) {
+    JS::Rooted<JS::Value> clone(cx);
+    if (!buffer.read(cx, clone.address(), &callbacks, &cloneReadInfo)) {
       NS_WARNING("Failed to deserialize structured clone data!");
       return NS_ERROR_DOM_DATA_CLONE_ERR;
     }
 
     nsTArray<IndexUpdateInfo> updateInfo;
     rv = IDBObjectStore::AppendIndexUpdateInfo(mIndex->Id(),
                                                mIndex->GetKeyPath(),
                                                mIndex->IsUnique(),
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -109,17 +109,17 @@ IDBRequest::NotifyHelperCompleted(Helper
   AutoPushJSContext cx(GetJSContext());
   if (!cx) {
     NS_WARNING("Failed to get safe JSContext!");
     rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     SetError(rv);
     return rv;
   }
 
-  JSObject* global = GetParentObject();
+  JS::Rooted<JSObject*> global(cx, GetParentObject());
   NS_ASSERTION(global, "This should never be null!");
 
   JSAutoRequest ar(cx);
   JSAutoCompartment ac(cx, global);
   AssertIsRooted();
 
   rv = aHelper->GetSuccessResult(cx, &mResultVal);
   if (NS_FAILED(rv)) {
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -414,36 +414,36 @@ IndexedDatabaseManager::InitWindowless(c
     return NS_ERROR_FAILURE;
   }
 
   // Instantiating this class will register exception providers so even 
   // in xpcshell we will get typed (dom) exceptions, instead of general
   // exceptions.
   nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID));
 
-  JSObject* global = JS_GetGlobalForObject(aCx, obj);
+  JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj));
   NS_ASSERTION(global, "What?! No global!");
 
   nsRefPtr<IDBFactory> factory;
   nsresult rv =
     IDBFactory::Create(aCx, global, nullptr, getter_AddRefs(factory));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   NS_ASSERTION(factory, "This should never fail for chrome!");
 
-  jsval indexedDBVal;
-  rv = nsContentUtils::WrapNative(aCx, obj, factory, &indexedDBVal);
+  JS::Rooted<JS::Value> indexedDBVal(aCx);
+  rv = nsContentUtils::WrapNative(aCx, obj, factory, indexedDBVal.address());
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!JS_DefineProperty(aCx, obj, "indexedDB", indexedDBVal, nullptr,
                          nullptr, JSPROP_ENUMERATE)) {
     return NS_ERROR_FAILURE;
   }
 
-  JSObject* keyrangeObj = JS_NewObject(aCx, nullptr, nullptr, nullptr);
+  JS::Rooted<JSObject*> keyrangeObj(aCx, JS_NewObject(aCx, nullptr, nullptr, nullptr));
   NS_ENSURE_TRUE(keyrangeObj, NS_ERROR_OUT_OF_MEMORY);
 
   if (!IDBKeyRange::DefineConstructors(aCx, keyrangeObj)) {
     return NS_ERROR_FAILURE;
   }
 
   if (!JS_DefineProperty(aCx, obj, "IDBKeyRange", OBJECT_TO_JSVAL(keyrangeObj),
                          nullptr, nullptr, JSPROP_ENUMERATE)) {
--- a/dom/indexedDB/Key.cpp
+++ b/dom/indexedDB/Key.cpp
@@ -128,17 +128,17 @@ Key::EncodeJSValInternal(JSContext* aCx,
     if (MOZ_DOUBLE_IS_NaN(d)) {
       return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
     }
     EncodeNumber(d, eFloat + aTypeOffset);
     return NS_OK;
   }
 
   if (!JSVAL_IS_PRIMITIVE(aVal)) {
-    JSObject* obj = JSVAL_TO_OBJECT(aVal);
+    JS::Rooted<JSObject*> obj(aCx, JSVAL_TO_OBJECT(aVal));
     if (JS_IsArrayObject(aCx, obj)) {
       aTypeOffset += eMaxType;
 
       if (aTypeOffset == eMaxType * MaxArrayCollapse) {
         mBuffer.Append(aTypeOffset);
         aTypeOffset = 0;
       }
       NS_ASSERTION((aTypeOffset % eMaxType) == 0 &&
@@ -146,18 +146,18 @@ Key::EncodeJSValInternal(JSContext* aCx,
                    "Wrong typeoffset");
 
       uint32_t length;
       if (!JS_GetArrayLength(aCx, obj, &length)) {
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
 
       for (uint32_t index = 0; index < length; index++) {
-        jsval val;
-        if (!JS_GetElement(aCx, obj, index, &val)) {
+        JS::Rooted<JS::Value> val(aCx);
+        if (!JS_GetElement(aCx, obj, index, val.address())) {
           return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
         }
 
         nsresult rv = EncodeJSValInternal(aCx, val, aTypeOffset,
                                           aRecursionDepth + 1);
         if (NS_FAILED(rv)) {
           return rv;
         }
@@ -186,39 +186,39 @@ Key::EncodeJSValInternal(JSContext* aCx,
 nsresult
 Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
                          JSContext* aCx, uint8_t aTypeOffset, jsval* aVal,
                          uint16_t aRecursionDepth)
 {
   NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
 
   if (*aPos - aTypeOffset >= eArray) {
-    JSObject* array = JS_NewArrayObject(aCx, 0, nullptr);
+    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr));
     if (!array) {
       NS_WARNING("Failed to make array!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     aTypeOffset += eMaxType;
 
     if (aTypeOffset == eMaxType * MaxArrayCollapse) {
       ++aPos;
       aTypeOffset = 0;
     }
 
     uint32_t index = 0;
     while (aPos < aEnd && *aPos - aTypeOffset != eTerminator) {
-      jsval val;
+      JS::Rooted<JS::Value> val(aCx);
       nsresult rv = DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset,
-                                        &val, aRecursionDepth + 1);
+                                        val.address(), aRecursionDepth + 1);
       NS_ENSURE_SUCCESS(rv, rv);
 
       aTypeOffset = 0;
 
-      if (!JS_SetElement(aCx, array, index++, &val)) {
+      if (!JS_SetElement(aCx, array, index++, val.address())) {
         NS_WARNING("Failed to set array element!");
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
     }
 
     NS_ASSERTION(aPos >= aEnd || (*aPos % eMaxType) == eTerminator,
                  "Should have found end-of-array marker");
     ++aPos;
--- a/dom/indexedDB/KeyPath.cpp
+++ b/dom/indexedDB/KeyPath.cpp
@@ -86,19 +86,19 @@ GetJSValFromKeyPathString(JSContext* aCx
                "If properties are created, there must be a callback!");
 
   nsresult rv = NS_OK;
   *aKeyJSVal = aValue;
 
   KeyPathTokenizer tokenizer(aKeyPathString, '.');
 
   nsString targetObjectPropName;
-  JSObject* targetObject = nullptr;
-  JSObject* obj = JSVAL_IS_PRIMITIVE(aValue) ? nullptr : 
-                                               JSVAL_TO_OBJECT(aValue);
+  JS::Rooted<JSObject*> targetObject(aCx, nullptr);
+  JS::Rooted<JSObject*> obj(aCx, JSVAL_IS_PRIMITIVE(aValue) ? nullptr :
+                                                         JSVAL_TO_OBJECT(aValue));
 
   while (tokenizer.hasMoreTokens()) {
     const nsDependentSubstring& token = tokenizer.nextToken();
 
     NS_ASSERTION(!token.IsEmpty(), "Should be a valid keypath");
 
     const jschar* keyPathChars = token.BeginReading();
     const size_t keyPathLen = token.Length();
@@ -111,19 +111,19 @@ GetJSValFromKeyPathString(JSContext* aCx
       }
 
       JSBool ok = JS_HasUCProperty(aCx, obj, keyPathChars, keyPathLen,
                                    &hasProp);
       NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
       if (hasProp) {
         // Get if the property exists...
-        jsval intermediate;
+        JS::Rooted<JS::Value> intermediate(aCx);
         JSBool ok = JS_GetUCProperty(aCx, obj, keyPathChars, keyPathLen,
-                                     &intermediate);
+                                     intermediate.address());
         NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
         // Treat explicitly undefined as an error.
         if (intermediate == JSVAL_VOID) {
           return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
         }
         if (tokenizer.hasMoreTokens()) {
           // ...and walk to it if there are more steps...
@@ -198,20 +198,20 @@ GetJSValFromKeyPathString(JSContext* aCx
   // deletion code below even if we should not be running the callback.
   if (NS_SUCCEEDED(rv) && aCallback) {
     rv = (*aCallback)(aCx, aClosure);
   }
 
   if (targetObject) {
     // If this fails, we lose, and the web page sees a magical property
     // appear on the object :-(
-    jsval succeeded;
+    JS::Rooted<JS::Value> succeeded(aCx);
     if (!JS_DeleteUCProperty2(aCx, targetObject,
                               targetObjectPropName.get(),
-                              targetObjectPropName.Length(), &succeeded)) {
+                              targetObjectPropName.Length(), succeeded.address())) {
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
     NS_ASSERTION(JSVAL_IS_BOOLEAN(succeeded), "Wtf?");
     NS_ENSURE_TRUE(JSVAL_TO_BOOLEAN(succeeded),
                    NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
@@ -227,34 +227,34 @@ KeyPath::Parse(JSContext* aCx, const JS:
   KeyPath keyPath(0);
 
   aKeyPath->SetType(NONEXISTENT);
 
   // See if this is a JS array.
   if (!JSVAL_IS_PRIMITIVE(aValue) &&
       JS_IsArrayObject(aCx, JSVAL_TO_OBJECT(aValue))) {
 
-    JSObject* obj = JSVAL_TO_OBJECT(aValue);
+    JS::Rooted<JSObject*> obj(aCx, JSVAL_TO_OBJECT(aValue));
 
     uint32_t length;
     if (!JS_GetArrayLength(aCx, obj, &length)) {
       return NS_ERROR_FAILURE;
     }
 
     if (!length) {
       return NS_ERROR_FAILURE;
     }
 
     keyPath.SetType(ARRAY);
 
     for (uint32_t index = 0; index < length; index++) {
-      jsval val;
+      JS::Rooted<JS::Value> val(aCx);
       JSString* jsstr;
       nsDependentJSString str;
-      if (!JS_GetElement(aCx, obj, index, &val) ||
+      if (!JS_GetElement(aCx, obj, index, val.address()) ||
           !(jsstr = JS_ValueToString(aCx, val)) ||
           !str.init(aCx, jsstr)) {
         return NS_ERROR_FAILURE;
       }
 
       if (!keyPath.AppendStringWithValidation(aCx, str)) {
         return NS_ERROR_FAILURE;
       }
@@ -308,22 +308,22 @@ KeyPath::AppendStringWithValidation(JSCo
   NS_NOTREACHED("What?!");
   return false;
 }
 
 nsresult
 KeyPath::ExtractKey(JSContext* aCx, const JS::Value& aValue, Key& aKey) const
 {
   uint32_t len = mStrings.Length();
-  JS::Value value;
+  JS::Rooted<JS::Value> value(aCx);
 
   aKey.Unset();
 
   for (uint32_t i = 0; i < len; ++i) {
-    nsresult rv = GetJSValFromKeyPathString(aCx, aValue, mStrings[i], &value,
+    nsresult rv = GetJSValFromKeyPathString(aCx, aValue, mStrings[i], value.address(),
                                             DoNotCreateProperties, nullptr,
                                             nullptr);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     if (NS_FAILED(aKey.AppendItem(aCx, IsArray() && i == 0, value))) {
       NS_ASSERTION(aKey.IsUnset(), "Encoding error should unset");
@@ -341,53 +341,53 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aC
                            JS::Value* aOutVal) const
 {
   NS_ASSERTION(IsValid(), "This doesn't make sense!");
 
   if (IsString()) {
     return GetJSValFromKeyPathString(aCx, aValue, mStrings[0], aOutVal,
                                      DoNotCreateProperties, nullptr, nullptr);
   }
- 
+
   const uint32_t len = mStrings.Length();
   JS::RootedObject arrayObj(aCx, JS_NewArrayObject(aCx, len, nullptr));
   if (!arrayObj) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  JS::Value value;
+  JS::Rooted<JS::Value> value(aCx);
   for (uint32_t i = 0; i < len; ++i) {
-    nsresult rv = GetJSValFromKeyPathString(aCx, aValue, mStrings[i], &value,
+    nsresult rv = GetJSValFromKeyPathString(aCx, aValue, mStrings[i], value.address(),
                                             DoNotCreateProperties, nullptr,
                                             nullptr);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
-    if (!JS_SetElement(aCx, arrayObj, i, &value)) {
+    if (!JS_SetElement(aCx, arrayObj, i, value.address())) {
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
   }
 
   *aOutVal = OBJECT_TO_JSVAL(arrayObj);
   return NS_OK;
 }
 
 nsresult
 KeyPath::ExtractOrCreateKey(JSContext* aCx, const JS::Value& aValue,
                             Key& aKey, ExtractOrCreateKeyCallback aCallback,
                             void* aClosure) const
 {
   NS_ASSERTION(IsString(), "This doesn't make sense!");
 
-  JS::Value value;
+  JS::Rooted<JS::Value> value(aCx);
 
   aKey.Unset();
 
-  nsresult rv = GetJSValFromKeyPathString(aCx, aValue, mStrings[0], &value,
+  nsresult rv = GetJSValFromKeyPathString(aCx, aValue, mStrings[0], value.address(),
                                           CreateProperties, aCallback,
                                           aClosure);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (NS_FAILED(aKey.AppendItem(aCx, false, value))) {
     NS_ASSERTION(aKey.IsUnset(), "Should be unset");
@@ -452,30 +452,30 @@ KeyPath::DeserializeFromString(const nsA
   return keyPath;
 }
 
 nsresult
 KeyPath::ToJSVal(JSContext* aCx, JS::Value* aValue) const
 {
   if (IsArray()) {
     uint32_t len = mStrings.Length();
-    JSObject* array = JS_NewArrayObject(aCx, len, nullptr);
+    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, len, nullptr));
     if (!array) {
       NS_WARNING("Failed to make array!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     for (uint32_t i = 0; i < len; ++i) {
-      jsval val;
+      JS::Rooted<JS::Value> val(aCx);
       nsString tmp(mStrings[i]);
-      if (!xpc::StringToJsval(aCx, tmp, &val)) {
+      if (!xpc::StringToJsval(aCx, tmp, val.address())) {
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
 
-      if (!JS_SetElement(aCx, array, i, &val)) {
+      if (!JS_SetElement(aCx, array, i, val.address())) {
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
     }
 
     *aValue = OBJECT_TO_JSVAL(array);
     return NS_OK;
   }
 
--- a/dom/indexedDB/ipc/IndexedDBParent.cpp
+++ b/dom/indexedDB/ipc/IndexedDBParent.cpp
@@ -379,27 +379,27 @@ IndexedDBDatabaseParent::HandleRequestEv
 
     if (!SendBlocked(oldVersion)) {
       return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
   }
 
-  jsval result;
-  rv = mOpenRequest->GetResult(&result);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  MOZ_ASSERT(!JSVAL_IS_PRIMITIVE(result));
-
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   MOZ_ASSERT(xpc);
 
   SafeAutoJSContext cx;
 
+  JS::Rooted<JS::Value> result(cx);
+  rv = mOpenRequest->GetResult(result.address());
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  MOZ_ASSERT(!JSVAL_IS_PRIMITIVE(result));
+
   nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
   rv = xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(result),
                                        getter_AddRefs(wrapper));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIIDBDatabase> database;
   if (!wrapper || !(database = do_QueryInterface(wrapper->Native()))) {
     NS_WARNING("Didn't get the object we expected!");
@@ -531,18 +531,18 @@ IndexedDBDatabaseParent::HandleDatabaseE
 
     nsCOMPtr<nsIIDBVersionChangeEvent> changeEvent = do_QueryInterface(aEvent);
     NS_ENSURE_TRUE(changeEvent, NS_ERROR_FAILURE);
 
     uint64_t oldVersion;
     rv = changeEvent->GetOldVersion(&oldVersion);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    JS::Value newVersionVal;
-    rv = changeEvent->GetNewVersion(cx, &newVersionVal);
+    JS::Rooted<JS::Value> newVersionVal(cx);
+    rv = changeEvent->GetNewVersion(cx, newVersionVal.address());
     NS_ENSURE_SUCCESS(rv, rv);
 
     uint64_t newVersion;
     if (newVersionVal.isNull()) {
       newVersion = 0;
     }
     else {
       MOZ_ASSERT(newVersionVal.isNumber());