Bug 1081703, r=khuey.

This commit is contained in:
Ben Turner 2014-11-07 16:42:53 -08:00
parent 9ffe3e11d4
commit 38b2675dc9
8 changed files with 165 additions and 98 deletions

View File

@ -2027,7 +2027,6 @@ BackgroundCursorChild::SendContinueInternal(const CursorRequestParams& aParams)
MOZ_ASSERT(!mStrongCursor);
// Make sure all our DOM objects stay alive.
mStrongRequest = mRequest;
mStrongCursor = mCursor;
MOZ_ASSERT(mRequest->ReadyState() == IDBRequestReadyState::Done);
@ -2119,9 +2118,7 @@ BackgroundCursorChild::HandleResponse(
if (mCursor) {
mCursor->Reset(Move(response.key()), Move(cloneReadInfo));
} else {
newCursor = IDBCursor::Create(mObjectStore,
this,
mDirection,
newCursor = IDBCursor::Create(this,
Move(response.key()),
Move(cloneReadInfo));
mCursor = newCursor;
@ -2150,10 +2147,7 @@ BackgroundCursorChild::HandleResponse(
if (mCursor) {
mCursor->Reset(Move(response.key()));
} else {
newCursor = IDBCursor::Create(mObjectStore,
this,
mDirection,
Move(response.key()));
newCursor = IDBCursor::Create(this, Move(response.key()));
mCursor = newCursor;
}
@ -2187,9 +2181,7 @@ BackgroundCursorChild::HandleResponse(const IndexCursorResponse& aResponse)
Move(response.objectKey()),
Move(cloneReadInfo));
} else {
newCursor = IDBCursor::Create(mIndex,
this,
mDirection,
newCursor = IDBCursor::Create(this,
Move(response.key()),
Move(response.objectKey()),
Move(cloneReadInfo));
@ -2218,9 +2210,7 @@ BackgroundCursorChild::HandleResponse(const IndexKeyCursorResponse& aResponse)
if (mCursor) {
mCursor->Reset(Move(response.key()), Move(response.objectKey()));
} else {
newCursor = IDBCursor::Create(mIndex,
this,
mDirection,
newCursor = IDBCursor::Create(this,
Move(response.key()),
Move(response.objectKey()));
mCursor = newCursor;
@ -2265,8 +2255,8 @@ BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse)
MOZ_ASSERT(aResponse.type() != CursorResponse::T__None);
MOZ_ASSERT(mRequest);
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(mStrongRequest);
MOZ_ASSERT_IF(mCursor, mStrongCursor);
MOZ_ASSERT_IF(!mCursor, mStrongRequest);
MaybeCollectGarbageOnIPCMessage();

View File

@ -568,6 +568,38 @@ public:
void
SendDeleteMeInternal();
IDBRequest*
GetRequest() const
{
AssertIsOnOwningThread();
return mRequest;
}
IDBObjectStore*
GetObjectStore() const
{
AssertIsOnOwningThread();
return mObjectStore;
}
IDBIndex*
GetIndex() const
{
AssertIsOnOwningThread();
return mIndex;
}
Direction
GetDirection() const
{
AssertIsOnOwningThread();
return mDirection;
}
private:
// Only destroyed by BackgroundTransactionChild or
// BackgroundVersionChangeTransactionChild.

View File

@ -27,23 +27,20 @@ namespace dom {
namespace indexedDB {
IDBCursor::IDBCursor(Type aType,
IDBObjectStore* aSourceObjectStore,
IDBIndex* aSourceIndex,
IDBTransaction* aTransaction,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aKey)
: mSourceObjectStore(aSourceObjectStore)
, mSourceIndex(aSourceIndex)
, mTransaction(aTransaction)
, mBackgroundActor(aBackgroundActor)
, mScriptOwner(aTransaction->Database()->GetScriptOwner())
: mBackgroundActor(aBackgroundActor)
, mRequest(aBackgroundActor->GetRequest())
, mSourceObjectStore(aBackgroundActor->GetObjectStore())
, mSourceIndex(aBackgroundActor->GetIndex())
, mTransaction(mRequest->GetTransaction())
, mScriptOwner(mTransaction->Database()->GetScriptOwner())
, mCachedKey(JSVAL_VOID)
, mCachedPrimaryKey(JSVAL_VOID)
, mCachedValue(JSVAL_VOID)
, mKey(aKey)
, mType(aType)
, mDirection(aDirection)
, mDirection(aBackgroundActor->GetDirection())
, mHaveCachedKey(false)
, mHaveCachedPrimaryKey(false)
, mHaveCachedValue(false)
@ -51,12 +48,13 @@ IDBCursor::IDBCursor(Type aType,
, mContinueCalled(false)
, mHaveValue(true)
{
MOZ_ASSERT_IF(aType == Type_ObjectStore || aType == Type_ObjectStoreKey,
aSourceObjectStore);
MOZ_ASSERT_IF(aType == Type_Index || aType == Type_IndexKey, aSourceIndex);
MOZ_ASSERT(aTransaction);
aTransaction->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
MOZ_ASSERT_IF(aType == Type_ObjectStore || aType == Type_ObjectStoreKey,
mSourceObjectStore);
MOZ_ASSERT_IF(aType == Type_Index || aType == Type_IndexKey, mSourceIndex);
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(!aKey.IsUnset());
MOZ_ASSERT(mScriptOwner);
@ -80,25 +78,18 @@ IDBCursor::~IDBCursor()
// static
already_AddRefed<IDBCursor>
IDBCursor::Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
StructuredCloneReadInfo&& aCloneInfo)
{
MOZ_ASSERT(aObjectStore);
aObjectStore->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aBackgroundActor->GetIndex());
MOZ_ASSERT(!aKey.IsUnset());
nsRefPtr<IDBCursor> cursor =
new IDBCursor(Type_ObjectStore,
aObjectStore,
nullptr,
aObjectStore->Transaction(),
aBackgroundActor,
aDirection,
aKey);
new IDBCursor(Type_ObjectStore, aBackgroundActor, aKey);
cursor->mCloneInfo = Move(aCloneInfo);
@ -107,51 +98,37 @@ IDBCursor::Create(IDBObjectStore* aObjectStore,
// static
already_AddRefed<IDBCursor>
IDBCursor::Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey)
{
MOZ_ASSERT(aObjectStore);
aObjectStore->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aBackgroundActor->GetIndex());
MOZ_ASSERT(!aKey.IsUnset());
nsRefPtr<IDBCursor> cursor =
new IDBCursor(Type_ObjectStoreKey,
aObjectStore,
nullptr,
aObjectStore->Transaction(),
aBackgroundActor,
aDirection,
aKey);
new IDBCursor(Type_ObjectStoreKey, aBackgroundActor, aKey);
return cursor.forget();
}
// static
already_AddRefed<IDBCursor>
IDBCursor::Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
const Key& aPrimaryKey,
StructuredCloneReadInfo&& aCloneInfo)
{
MOZ_ASSERT(aIndex);
aIndex->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetIndex());
MOZ_ASSERT(!aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aKey.IsUnset());
MOZ_ASSERT(!aPrimaryKey.IsUnset());
nsRefPtr<IDBCursor> cursor =
new IDBCursor(Type_Index,
nullptr,
aIndex,
aIndex->ObjectStore()->Transaction(),
aBackgroundActor,
aDirection,
aKey);
new IDBCursor(Type_Index, aBackgroundActor, aKey);
cursor->mPrimaryKey = Move(aPrimaryKey);
cursor->mCloneInfo = Move(aCloneInfo);
@ -161,26 +138,19 @@ IDBCursor::Create(IDBIndex* aIndex,
// static
already_AddRefed<IDBCursor>
IDBCursor::Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
const Key& aPrimaryKey)
{
MOZ_ASSERT(aIndex);
aIndex->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetIndex());
MOZ_ASSERT(!aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aKey.IsUnset());
MOZ_ASSERT(!aPrimaryKey.IsUnset());
nsRefPtr<IDBCursor> cursor =
new IDBCursor(Type_IndexKey,
nullptr,
aIndex,
aIndex->ObjectStore()->Transaction(),
aBackgroundActor,
aDirection,
aKey);
new IDBCursor(Type_IndexKey, aBackgroundActor, aKey);
cursor->mPrimaryKey = Move(aPrimaryKey);
@ -800,9 +770,9 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceObjectStore)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceIndex)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
@ -819,7 +789,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
// Don't unlink mSourceObjectStore or mSourceIndex or mTransaction!
// Don't unlink mRequest, mSourceObjectStore, or mSourceIndex!
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->DropJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

View File

@ -59,11 +59,14 @@ private:
Type_IndexKey,
};
BackgroundCursorChild* mBackgroundActor;
nsRefPtr<IDBRequest> mRequest;
nsRefPtr<IDBObjectStore> mSourceObjectStore;
nsRefPtr<IDBIndex> mSourceIndex;
nsRefPtr<IDBTransaction> mTransaction;
BackgroundCursorChild* mBackgroundActor;
// mSourceObjectStore or mSourceIndex will hold this alive.
IDBTransaction* mTransaction;
JS::Heap<JSObject*> mScriptOwner;
@ -88,30 +91,22 @@ private:
public:
static already_AddRefed<IDBCursor>
Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
StructuredCloneReadInfo&& aCloneInfo);
static already_AddRefed<IDBCursor>
Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey);
static already_AddRefed<IDBCursor>
Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
const Key& aPrimaryKey,
StructuredCloneReadInfo&& aCloneInfo);
static already_AddRefed<IDBCursor>
Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
const Key& aPrimaryKey);
@ -194,11 +189,7 @@ public:
private:
IDBCursor(Type aType,
IDBObjectStore* aSourceObjectStore,
IDBIndex* aSourceIndex,
IDBTransaction* aTransaction,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aKey);
~IDBCursor();

View File

@ -46,6 +46,7 @@ support-files =
unit/test_indexes.js
unit/test_indexes_bad_values.js
unit/test_indexes_funny_things.js
unit/test_invalid_cursor.js
unit/test_invalid_version.js
unit/test_invalidate.js
unit/test_key_requirements.js
@ -267,6 +268,8 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_indexes_funny_things.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_invalid_cursor.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_invalid_version.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_invalidate.html]

View File

@ -0,0 +1,18 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>IndexedDB Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7" src="unit/test_invalid_cursor.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -0,0 +1,62 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
let testGenerator = testSteps();
function testSteps()
{
const dbName = ("window" in this) ? window.location.pathname : "test";
const dbVersion = 1;
const objectStoreName = "foo";
const data = 0;
let req = indexedDB.open(dbName, dbVersion);
req.onerror = errorHandler;
req.onupgradeneeded = grabEventAndContinueHandler;
req.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "upgradeneeded", "Got upgradeneeded event");
let db = event.target.result;
let objectStore =
db.createObjectStore(objectStoreName, { autoIncrement: true });
objectStore.add(data);
event = yield undefined;
is(event.type, "success", "Got success event for open");
objectStore = db.transaction(objectStoreName).objectStore(objectStoreName);
objectStore.openCursor().onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.type, "success", "Got success event for openCursor");
let cursor = event.target.result;
is(cursor.value, data, "Got correct cursor value");
objectStore.get(cursor.key).onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.target.result, data, "Got correct get value");
info("Collecting garbage");
gc();
info("Done collecting garbage");
cursor.continue();
event = yield undefined;
is(event.target.result, null, "No more entries");
finishTest();
yield undefined;
}

View File

@ -36,6 +36,7 @@ skip-if = toolkit == 'android' # bug 1079278
[test_indexes.js]
[test_indexes_bad_values.js]
[test_indexes_funny_things.js]
[test_invalid_cursor.js]
[test_invalid_version.js]
[test_key_requirements.js]
[test_keys.js]