Bug 618135 - 'IndexedDB: Implement update() on index cursors (not on index key cursors)'. r-sicking, a=blocking.

This commit is contained in:
Ben Turner 2010-12-15 13:21:11 -08:00
Родитель dfd8298239
Коммит ea75742e0c
10 изменённых файлов: 276 добавлений и 319 удалений

Просмотреть файл

@ -145,7 +145,8 @@ AsyncConnectionHelper::Run()
mRequest->SetDone();
}
SetCurrentTransaction(mTransaction);
IDBTransaction* oldTransaction = gCurrentTransaction;
gCurrentTransaction = mTransaction;
// Call OnError if the database had an error or if the OnSuccess handler
// has an error.
@ -154,9 +155,8 @@ AsyncConnectionHelper::Run()
OnError(mRequest, mResultCode);
}
NS_ASSERTION(GetCurrentTransaction() == mTransaction,
"Should be unchanged!");
SetCurrentTransaction(nsnull);
NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!");
gCurrentTransaction = oldTransaction;
if (mDispatched && mTransaction) {
mTransaction->OnRequestFinished();
@ -319,20 +319,6 @@ AsyncConnectionHelper::GetCurrentTransaction()
return gCurrentTransaction;
}
// static
void
AsyncConnectionHelper::SetCurrentTransaction(IDBTransaction* aTransaction)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (aTransaction) {
NS_ASSERTION(!gCurrentTransaction, "Overwriting current transaction!");
}
gCurrentTransaction = aTransaction;
}
nsresult
AsyncConnectionHelper::Init()
{

Просмотреть файл

@ -87,7 +87,6 @@ public:
}
static IDBTransaction* GetCurrentTransaction();
static void SetCurrentTransaction(IDBTransaction* aTransaction);
nsISupports* GetSource()
{

Просмотреть файл

@ -63,57 +63,6 @@ USING_INDEXEDDB_NAMESPACE
namespace {
class UpdateHelper : public AsyncConnectionHelper
{
public:
UpdateHelper(IDBTransaction* aTransaction,
IDBRequest* aRequest,
PRInt64 aObjectStoreID,
const nsAString& aValue,
const Key& aKey,
bool aAutoIncrement,
nsTArray<IndexUpdateInfo>& aIndexUpdateInfo)
: AsyncConnectionHelper(aTransaction, aRequest), mOSID(aObjectStoreID),
mValue(aValue), mKey(aKey), mAutoIncrement(aAutoIncrement)
{
mIndexUpdateInfo.SwapElements(aIndexUpdateInfo);
}
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
nsresult GetSuccessResult(nsIWritableVariant* aResult);
private:
// In-params.
const PRInt64 mOSID;
const nsString mValue;
const Key mKey;
const bool mAutoIncrement;
nsTArray<IndexUpdateInfo> mIndexUpdateInfo;
};
class DeleteHelper : public AsyncConnectionHelper
{
public:
DeleteHelper(IDBTransaction* aTransaction,
IDBRequest* aRequest,
PRInt64 aObjectStoreID,
const Key& aKey,
bool aAutoIncrement)
: AsyncConnectionHelper(aTransaction, aRequest), mOSID(aObjectStoreID),
mKey(aKey), mAutoIncrement(aAutoIncrement)
{ }
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
nsresult GetSuccessResult(nsIWritableVariant* aResult);
private:
// In-params.
const PRInt64 mOSID;
const nsString mValue;
const Key mKey;
const bool mAutoIncrement;
};
inline
already_AddRefed<IDBRequest>
GenerateRequest(IDBCursor* aCursor)
@ -247,7 +196,7 @@ IDBCursor::Create(IDBRequest* aRequest,
NS_ASSERTION(cursor, "This shouldn't fail!");
cursor->mIndex = aIndex;
cursor->mType = INDEX;
cursor->mType = INDEXKEY;
cursor->mKey = aKey,
cursor->mObjectKey = aObjectKey;
@ -452,7 +401,7 @@ IDBCursor::GetValue(JSContext* aCx,
nsresult rv;
if (mType == INDEX) {
if (mType == INDEXKEY) {
NS_ASSERTION(!mObjectKey.IsUnset(), "Bad key!");
rv = IDBObjectStore::GetJSValFromKey(mObjectKey, aCx, aValue);
@ -535,7 +484,7 @@ IDBCursor::Continue(const jsval &aKey,
helper = new ContinueObjectStoreHelper(this);
break;
case INDEX:
case INDEXKEY:
helper = new ContinueIndexHelper(this);
break;
@ -561,239 +510,75 @@ IDBCursor::Update(const jsval& aValue,
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!mTransaction->TransactionIsOpen() || !mTransaction->IsWriteAllowed()) {
if (mType == INDEXKEY) {
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
}
if (mType != OBJECTSTORE) {
NS_WARNING("Update for non-objectStore cursors is not implemented!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
NS_ASSERTION(mObjectStore, "This cannot be null!");
NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
NS_ASSERTION(mType != INDEXOBJECT || !mObjectKey.IsUnset(), "Bad key!");
nsresult rv;
JSAutoRequest ar(aCx);
const Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
if (!mObjectStore->KeyPath().IsEmpty()) {
// This has to be an object.
if (JSVAL_IS_PRIMITIVE(aValue)) {
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
}
// Make sure the object given has the correct keyPath value set on it.
const nsString& keyPath = mObjectStore->KeyPath();
jsval prop;
JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(aValue),
reinterpret_cast<const jschar*>(keyPath.get()),
keyPath.Length(), &prop);
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
Key key;
rv = IDBObjectStore::GetKeyFromJSVal(prop, key);
if (NS_FAILED(rv)) {
return rv;
}
if (key != objectKey) {
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
}
return mObjectStore->Put(aValue, JSVAL_VOID, aCx, 0, _retval);
}
jsval keyVal;
rv = IDBObjectStore::GetJSValFromKey(objectKey, aCx, &keyVal);
NS_ENSURE_SUCCESS(rv, rv);
return mObjectStore->Put(aValue, keyVal, aCx, 1, _retval);
}
NS_IMETHODIMP
IDBCursor::Delete(JSContext* aCx,
nsIIDBRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (mType == INDEXKEY) {
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
}
NS_ASSERTION(mObjectStore, "This cannot be null!");
NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
JSAutoRequest ar(aCx);
const Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
js::AutoValueRooter clone(aCx, aValue);
jsval key;
nsresult rv = IDBObjectStore::GetJSValFromKey(objectKey, aCx, &key);
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv;
if (!mObjectStore->KeyPath().IsEmpty()) {
// Make sure the object given has the correct keyPath value set on it or
// we will add it.
const nsString& keyPath = mObjectStore->KeyPath();
const jschar* keyPathChars = reinterpret_cast<const jschar*>(keyPath.get());
const size_t keyPathLen = keyPath.Length();
js::AutoValueRooter prop(aCx);
JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()),
keyPathChars, keyPathLen, prop.jsval_addr());
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (JSVAL_IS_VOID(prop.jsval_value())) {
rv = IDBObjectStore::GetJSValFromKey(mKey, aCx, prop.jsval_addr());
NS_ENSURE_SUCCESS(rv, rv);
ok = JS_StructuredClone(aCx, clone.jsval_value(), clone.jsval_addr());
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_SERIAL_ERR);
ok = JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()),
keyPathChars, keyPathLen, prop.jsval_value(), nsnull,
nsnull, JSPROP_ENUMERATE);
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
else {
Key newKey;
rv = IDBObjectStore::GetKeyFromJSVal(prop.jsval_value(), newKey);
NS_ENSURE_SUCCESS(rv, rv);
if (newKey.IsUnset() || newKey != mKey) {
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
}
}
}
ObjectStoreInfo* info;
if (!ObjectStoreInfo::Get(mTransaction->Database()->Id(),
mObjectStore->Name(), &info)) {
NS_ERROR("This should never fail!");
}
nsTArray<IndexUpdateInfo> indexUpdateInfo;
rv = IDBObjectStore::GetIndexUpdateInfo(info, aCx, clone.jsval_value(),
indexUpdateInfo);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsCOMPtr<nsIJSON> json(new nsJSON());
nsString jsonValue;
rv = json->EncodeFromJSVal(clone.jsval_addr(), aCx, jsonValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_SERIAL_ERR);
nsRefPtr<IDBRequest> request = GenerateRequest(this);
NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsRefPtr<UpdateHelper> helper =
new UpdateHelper(mTransaction, request, mObjectStore->Id(), jsonValue, mKey,
mObjectStore->IsAutoIncrement(), indexUpdateInfo);
rv = helper->DispatchToTransactionPool();
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
IDBCursor::Delete(nsIIDBRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!mTransaction->TransactionIsOpen() || !mTransaction->IsWriteAllowed()) {
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
}
if (mType != OBJECTSTORE) {
NS_WARNING("Delete for non-objectStore cursors is not implemented!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
NS_ASSERTION(mObjectStore, "This cannot be null!");
NS_ASSERTION(!mKey.IsUnset(), "Bad key!");
nsRefPtr<IDBRequest> request = GenerateRequest(this);
NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsRefPtr<DeleteHelper> helper =
new DeleteHelper(mTransaction, request, mObjectStore->Id(), mKey,
mObjectStore->IsAutoIncrement());
nsresult rv = helper->DispatchToTransactionPool();
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
request.forget(_retval);
return NS_OK;
}
nsresult
UpdateHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
NS_PRECONDITION(aConnection, "Passed a null connection!");
nsresult rv;
NS_ASSERTION(!mKey.IsUnset(), "Badness!");
nsCOMPtr<mozIStorageStatement> stmt =
mTransaction->AddStatement(false, true, mAutoIncrement);
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
mozStorageStatementScoper scoper(stmt);
NS_NAMED_LITERAL_CSTRING(keyValue, "key_value");
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mOSID);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (mKey.IsInt()) {
rv = stmt->BindInt64ByName(keyValue, mKey.IntValue());
}
else if (mKey.IsString()) {
rv = stmt->BindStringByName(keyValue, mKey.StringValue());
}
else {
NS_NOTREACHED("Unknown key type!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("data"), mValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (NS_FAILED(stmt->Execute())) {
return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
}
// Update our indexes if needed.
if (!mIndexUpdateInfo.IsEmpty()) {
PRInt64 objectDataId = mAutoIncrement ? mKey.IntValue() : LL_MININT;
rv = IDBObjectStore::UpdateIndexes(mTransaction, mOSID, mKey,
mAutoIncrement, true,
objectDataId, mIndexUpdateInfo);
if (rv == NS_ERROR_STORAGE_CONSTRAINT) {
return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
return NS_OK;
}
nsresult
UpdateHelper::GetSuccessResult(nsIWritableVariant* aResult)
{
NS_ASSERTION(!mKey.IsUnset(), "Badness!");
if (mKey.IsString()) {
aResult->SetAsAString(mKey.StringValue());
}
else if (mKey.IsInt()) {
aResult->SetAsInt64(mKey.IntValue());
}
else {
NS_NOTREACHED("Bad key!");
}
return NS_OK;
}
nsresult
DeleteHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
NS_PRECONDITION(aConnection, "Passed a null connection!");
nsCOMPtr<mozIStorageStatement> stmt =
mTransaction->DeleteStatement(mAutoIncrement);
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mOSID);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
NS_ASSERTION(!mKey.IsUnset(), "Must have a key here!");
NS_NAMED_LITERAL_CSTRING(key_value, "key_value");
if (mKey.IsInt()) {
rv = stmt->BindInt64ByName(key_value, mKey.IntValue());
}
else if (mKey.IsString()) {
rv = stmt->BindStringByName(key_value, mKey.StringValue());
}
else {
NS_NOTREACHED("Unknown key type!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
// Search for it!
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return NS_OK;
}
nsresult
DeleteHelper::GetSuccessResult(nsIWritableVariant* aResult)
{
NS_ASSERTION(!mKey.IsUnset(), "Badness!");
if (mKey.IsString()) {
aResult->SetAsAString(mKey.StringValue());
}
else if (mKey.IsInt()) {
aResult->SetAsInt64(mKey.IntValue());
}
else {
NS_NOTREACHED("Unknown key type!");
}
return NS_OK;
return mObjectStore->Delete(key, aCx, _retval);
}
nsresult

Просмотреть файл

@ -118,7 +118,7 @@ public:
enum Type
{
OBJECTSTORE = 0,
INDEX,
INDEXKEY,
INDEXOBJECT
};

Просмотреть файл

@ -744,16 +744,24 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
{
nsresult rv;
// Return DATA_ERR if a key was passed in and this objectStore uses inline
// keys.
if (!JSVAL_IS_VOID(aKeyVal) && !mKeyPath.IsEmpty()) {
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
}
JSAutoRequest ar(aCx);
if (mKeyPath.IsEmpty()) {
// Out-of-line keys must be passed in.
rv = GetKeyFromJSVal(aKeyVal, aKey);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
// Inline keys live on the object. Make sure it is an object.
// Inline keys live on the object. Make sure that the value passed in is an
// object.
if (JSVAL_IS_PRIMITIVE(aValue)) {
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
}
rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(aValue), mKeyPath, aKey);
@ -1025,7 +1033,8 @@ IDBObjectStore::Put(const jsval& aValue,
}
NS_IMETHODIMP
IDBObjectStore::Delete(nsIVariant* aKey,
IDBObjectStore::Delete(const jsval& aKey,
JSContext* aCx,
nsIIDBRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -1035,7 +1044,7 @@ IDBObjectStore::Delete(nsIVariant* aKey,
}
Key key;
nsresult rv = GetKeyFromVariant(aKey, key);
nsresult rv = GetKeyFromJSVal(aKey, key);
if (NS_FAILED(rv)) {
return rv;
}
@ -1421,8 +1430,6 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
rv = stmt->Execute();
if (NS_FAILED(rv)) {
if (mayOverwrite && rv == NS_ERROR_STORAGE_CONSTRAINT) {
scoper.Abandon();
stmt = mTransaction->AddStatement(false, true, autoIncrement);
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -1431,20 +1438,18 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (!autoIncrement) {
NS_ASSERTION(!mKey.IsUnset(), "This shouldn't happen!");
NS_ASSERTION(!mKey.IsUnset(), "This shouldn't happen!");
if (mKey.IsInt()) {
rv = stmt->BindInt64ByName(keyValue, mKey.IntValue());
}
else if (mKey.IsString()) {
rv = stmt->BindStringByName(keyValue, mKey.StringValue());
}
else {
NS_NOTREACHED("Unknown key type!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (mKey.IsInt()) {
rv = stmt->BindInt64ByName(keyValue, mKey.IntValue());
}
else if (mKey.IsString()) {
rv = stmt->BindStringByName(keyValue, mKey.StringValue());
}
else {
NS_NOTREACHED("Unknown key type!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("data"), mValue);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@ -1978,7 +1983,9 @@ CreateIndexHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
// Now we need to populate the index with data from the object store.
rv = InsertDataFromObjectStore(aConnection);
NS_ENSURE_TRUE(rv, rv);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}

Просмотреть файл

@ -51,7 +51,7 @@ interface nsIVariant;
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
* information.
*/
[scriptable, uuid(12c99a5b-6e67-4d5c-8ae7-3a58da690375)]
[scriptable, uuid(585d4d50-11a8-4d65-951e-805787f59d89)]
interface nsIIDBCursor : nsISupports
{
const unsigned short NEXT = 0;
@ -77,5 +77,6 @@ interface nsIIDBCursor : nsISupports
nsIIDBRequest update(in jsval value);
// Success fires IDBTransactionEvent, result == null
[implicit_jscontext]
nsIIDBRequest delete();
};

Просмотреть файл

@ -55,7 +55,7 @@ interface nsIDOMDOMStringList;
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
* for more information.
*/
[scriptable, uuid(626fd729-d66a-4b49-bbaf-058f1c375449)]
[scriptable, uuid(64f34805-d3e3-4305-91f8-b2cafac3d33c)]
interface nsIIDBObjectStore : nsISupports
{
readonly attribute DOMString name;
@ -89,8 +89,9 @@ interface nsIIDBObjectStore : nsISupports
[optional /* undefined */] in jsval key);
// Success fires IDBTransactionEvent, result == null
[implicit_jscontext]
nsIIDBRequest
delete(in nsIVariant key);
delete(in jsval key);
// Success fires IDBTransactionEvent, result == null
nsIIDBRequest

Просмотреть файл

@ -68,6 +68,7 @@ TEST_FILES = \
test_global_data.html \
test_index_getAll.html \
test_index_getAllObjects.html \
test_index_object_cursors.html \
test_indexes.html \
test_indexes_bad_values.html \
test_key_requirements.html \

Просмотреть файл

@ -0,0 +1,161 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<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">
function testSteps()
{
const objectStoreData = [
{ name: "3", keyPath: "id", autoIncrement: true },
{ name: "1", keyPath: "ss", autoIncrement: false },
{ name: "2", keyPath: "", autoIncrement: false },
{ name: "4", keyPath: "", autoIncrement: true },
];
const indexData = [
{ name: "name", keyPath: "name", unique: true },
{ name: "height", keyPath: "height", unique: false }
];
const data = [
{ ss: "237-23-7732", name: "Ann", height: 60 },
{ ss: "237-23-7733", name: "Bob", height: 65 }
];
let request = moz_indexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
let db = event.result;
db.onerror = errorHandler;
db.setVersion("1").onsuccess = grabEventAndContinueHandler;
event = yield;
event.result.oncomplete = continueToNextStep;
for (let objectStoreIndex in objectStoreData) {
const objectStoreInfo = objectStoreData[objectStoreIndex];
let objectStore = db.createObjectStore(objectStoreInfo.name,
objectStoreInfo.keyPath,
objectStoreInfo.autoIncrement);
for (let indexIndex in indexData) {
const indexInfo = indexData[indexIndex];
let index = objectStore.createIndex(indexInfo.name,
indexInfo.keyPath,
indexInfo.unique);
}
}
yield;
ok(true, "Initial setup");
for (let objectStoreIndex in objectStoreData) {
const info = objectStoreData[objectStoreIndex];
for (let indexIndex in indexData) {
const objectStoreName = objectStoreData[objectStoreIndex].name;
const indexName = indexData[indexIndex].name;
let objectStore =
db.transaction(objectStoreName, IDBTransaction.READ_WRITE)
.objectStore(objectStoreName);
ok(true, "Got objectStore " + objectStoreName);
for (let dataIndex in data) {
const obj = data[dataIndex];
let key;
if (!info.keyPath && !info.autoIncrement) {
key = obj.ss;
}
objectStore.add(obj, key);
}
let index = objectStore.index(indexName);
ok(true, "Got index " + indexName);
let keyIndex = 0;
index.openCursor().onsuccess = function(event) {
let cursor = event.result;
if (!cursor) {
continueToNextStep();
return;
}
is(cursor.key, data[keyIndex][indexName], "Good key");
is(cursor.value.ss, data[keyIndex].ss, "Correct ss");
is(cursor.value.name, data[keyIndex].name, "Correct name");
is(cursor.value.height, data[keyIndex].height, "Correct height");
if (!keyIndex) {
let obj = cursor.value;
obj.updated = true;
cursor.update(obj).onsuccess = function(event) {
ok(true, "Object updated");
cursor.continue();
keyIndex++
}
return;
}
cursor.delete().onsuccess = function(event) {
ok(true, "Object deleted");
cursor.continue();
keyIndex++
}
};
yield;
is(keyIndex, 2, "Saw all the items");
keyIndex = 0;
db.transaction(objectStoreName).objectStore(objectStoreName)
.openCursor()
.onsuccess = function(event) {
let cursor = event.result;
if (!cursor) {
continueToNextStep();
return;
}
is(cursor.value.ss, data[keyIndex].ss, "Correct ss");
is(cursor.value.name, data[keyIndex].name, "Correct name");
is(cursor.value.height, data[keyIndex].height, "Correct height");
is(cursor.value.updated, true, "Correct updated flag");
cursor.continue();
keyIndex++;
};
yield;
is(keyIndex, 1, "Saw all the items");
db.transaction(objectStoreName, IDBTransaction.READ_WRITE)
.objectStore(objectStoreName).clear()
.onsuccess = continueToNextStep();
yield;
}
}
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

Просмотреть файл

@ -133,6 +133,14 @@
ok(true, "add with no key threw");
}
try {
objectStore.add({id:5}, 5);
ok(false, "add with inline key and passed key should throw!");
}
catch (e) {
ok(true, "add with inline key and passed key threw");
}
try {
objectStore.put({});
ok(false, "put with no key should throw!");
@ -266,6 +274,14 @@
ok(true, "remove with no key threw");
}
try {
objectStore.add({id:5}, 5);
ok(false, "add with inline key and passed key should throw!");
}
catch (e) {
ok(true, "add with inline key and passed key threw");
}
request = objectStore.delete(key2);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;