Bug 866450 Part 6: Fix rooting hazards under content/ and dom/ r=bz
authorDavid Zbarsky <dzbarsky@gmail.com>
Thu, 02 May 2013 05:12:47 -0400
changeset 130669 ae0aac5ce54ef54a24a97737c50466aa88e33f96
parent 130668 4864e9d9a4187b26abf26e1f392ca1d88c5104c4
child 130670 478105be6e91d2608c1a784ec96e3407589e4205
push id1579
push userphilringnalda@gmail.com
push dateSat, 04 May 2013 04:38:04 +0000
treeherderfx-team@a56432a42a41 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs866450
milestone23.0a1
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,20 @@ 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 +152,20 @@ 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 +175,21 @@ 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);
+      rv = nsContentUtils::WrapNative(aCx, global, domBlob,
+                                      &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);
+    rv = nsContentUtils::WrapNative(aCx, global, domFile,
+                                    &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,28 @@ 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::Rooted<JSString*> 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 +926,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 +1814,18 @@ 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 +4025,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,37 @@ 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,21 @@ 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 +228,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 +309,23 @@ 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 +343,55 @@ 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 +456,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());