Bug 866450 Part 6: Fix rooting hazards under content/ and dom/ r=bz

This commit is contained in:
David Zbarsky 2013-05-02 05:12:47 -04:00
parent eed350c7d0
commit f6efab93ab
12 changed files with 99 additions and 89 deletions

View File

@ -56,7 +56,7 @@ ConvertCloneReadInfosToArrayInternal(
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;
@ -72,13 +72,13 @@ ConvertCloneReadInfosToArrayInternal(
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;
}

View File

@ -608,8 +608,8 @@ IDBCursor::GetValue(JSContext* aCx,
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;
}
@ -740,8 +740,8 @@ IDBCursor::Update(const jsval& aValue,
}
}
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));
@ -811,8 +811,8 @@ IDBCursor::Delete(JSContext* aCx,
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;

View File

@ -658,7 +658,7 @@ IDBDatabase::Transaction(const jsval& aStoreNames,
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)) {
@ -674,10 +674,10 @@ IDBDatabase::Transaction(const jsval& aStoreNames,
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;

View File

@ -218,8 +218,8 @@ IDBFactory::Create(ContentParent* aContentParent,
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

View File

@ -1493,7 +1493,7 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
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;
@ -1509,14 +1509,14 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
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;
}

View File

@ -52,8 +52,8 @@ ReturnKeyRange(JSContext* aCx,
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;
}
@ -113,8 +113,8 @@ MakeOnlyKeyRange(JSContext* aCx,
{
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;
}
@ -134,9 +134,10 @@ MakeLowerBoundKeyRange(JSContext* aCx,
{
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;
}
@ -156,9 +157,10 @@ MakeUpperBoundKeyRange(JSContext* aCx,
{
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;
}
@ -178,10 +180,11 @@ MakeBoundKeyRange(JSContext* aCx,
{
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;
}

View File

@ -726,11 +726,11 @@ public:
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;
@ -753,11 +753,11 @@ public:
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;
@ -795,7 +795,8 @@ public:
// 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;
@ -804,8 +805,8 @@ public:
// 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),
@ -930,15 +931,15 @@ IDBObjectStore::AppendIndexUpdateInfo(
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;
}
@ -1818,7 +1819,8 @@ IDBObjectStore::AddOrPut(const jsval& aValue,
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;
@ -4028,8 +4030,8 @@ CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
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;
}

View File

@ -114,7 +114,7 @@ IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
return rv;
}
JSObject* global = GetParentObject();
JS::Rooted<JSObject*> global(cx, GetParentObject());
NS_ASSERTION(global, "This should never be null!");
JSAutoRequest ar(cx);

View File

@ -419,7 +419,7 @@ IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx)
// 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;
@ -429,8 +429,8 @@ IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx)
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,
@ -438,7 +438,8 @@ IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx)
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)) {

View File

@ -133,7 +133,7 @@ Key::EncodeJSValInternal(JSContext* aCx, const jsval aVal,
}
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;
@ -151,8 +151,8 @@ Key::EncodeJSValInternal(JSContext* aCx, const jsval aVal,
}
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;
}
@ -191,7 +191,7 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
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;
@ -206,14 +206,14 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
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;
}

View File

@ -91,9 +91,9 @@ GetJSValFromKeyPathString(JSContext* aCx,
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();
@ -116,9 +116,9 @@ GetJSValFromKeyPathString(JSContext* aCx,
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.
@ -203,10 +203,11 @@ GetJSValFromKeyPathString(JSContext* aCx,
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?");
@ -232,7 +233,7 @@ KeyPath::Parse(JSContext* aCx, const JS::Value& aValue, KeyPath* aKeyPath)
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)) {
@ -246,10 +247,10 @@ KeyPath::Parse(JSContext* aCx, const JS::Value& aValue, KeyPath* aKeyPath)
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;
@ -313,12 +314,13 @@ 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)) {
@ -346,23 +348,24 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue,
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;
}
}
@ -378,11 +381,12 @@ KeyPath::ExtractOrCreateKey(JSContext* aCx, const JS::Value& aValue,
{
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)) {
@ -457,20 +461,20 @@ 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;
}
}

View File

@ -384,17 +384,17 @@ IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent,
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));
@ -536,8 +536,8 @@ IndexedDBDatabaseParent::HandleDatabaseEvent(nsIDOMEvent* aEvent,
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;