Bug 706762: Ensure that object stores and indexes are removed from caches when they are deleted. r=bent
authorJonas Sicking <jonas@sicking.cc>
Sun, 04 Dec 2011 09:39:01 -0800
changeset 81996 b3a301279d1c3ccd4d94c57089eeafaafdaf3a83
parent 81995 0de28e40259f83d5e29613f6a7946ff3147e81c7
child 81997 82e7bc80eb4971a41cacc067274d6403df0b0fe5
push idunknown
push userunknown
push dateunknown
reviewersbent
bugs706762
milestone11.0a1
Bug 706762: Ensure that object stores and indexes are removed from caches when they are deleted. r=bent
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBTransaction.cpp
dom/indexedDB/IDBTransaction.h
dom/indexedDB/test/test_remove_index.html
dom/indexedDB/test/test_remove_objectStore.html
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -494,16 +494,19 @@ IDBDatabase::DeleteObjectStore(const nsA
   }
 
   nsRefPtr<DeleteObjectStoreHelper> helper =
     new DeleteObjectStoreHelper(transaction, objectStoreInfo->id);
   nsresult rv = helper->DispatchToTransactionPool();
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   info->RemoveObjectStore(aName);
+
+  transaction->ReleaseCachedObjectStore(aName);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBDatabase::Transaction(const jsval& aStoreNames,
                          PRUint16 aMode,
                          JSContext* aCx,
                          PRUint8 aOptionalArgCount,
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1545,16 +1545,24 @@ IDBObjectStore::DeleteIndex(const nsAStr
 
   nsRefPtr<DeleteIndexHelper> helper =
     new DeleteIndexHelper(mTransaction, aName, this);
 
   nsresult rv = helper->DispatchToTransactionPool();
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   info->indexes.RemoveElementAt(index);
+
+  for (PRUint32 i = 0; i < mCreatedIndexes.Length(); i++) {
+    if (mCreatedIndexes[i]->Name() == aName) {
+      mCreatedIndexes.RemoveElementAt(i);
+      break;
+    }
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IDBObjectStore::Count(const jsval& aKey,
                       JSContext* aCx,
                       PRUint8 aOptionalArgCount,
                       nsIIDBRequest** _retval)
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -209,16 +209,27 @@ IDBTransaction::OnRequestFinished()
     NS_ASSERTION(mAborted || mReadyState == nsIIDBTransaction::LOADING,
                  "Bad state!");
     mReadyState = IDBTransaction::COMMITTING;
     CommitOrRollback();
   }
 }
 
 void
+IDBTransaction::ReleaseCachedObjectStore(const nsAString& aName)
+{
+  for (PRUint32 i = 0; i < mCreatedObjectStores.Length(); i++) {
+    if (mCreatedObjectStores[i]->Name() == aName) {
+      mCreatedObjectStores.RemoveElementAt(i);
+      break;
+    }
+  }
+}
+
+void
 IDBTransaction::SetTransactionListener(IDBTransactionListener* aListener)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!mListener, "Shouldn't already have a listener!");
   mListener = aListener;
 }
 
 nsresult
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -98,16 +98,18 @@ public:
          bool aDispatchDelayed);
 
   // nsIDOMEventTarget
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
   void OnNewRequest();
   void OnRequestFinished();
 
+  void ReleaseCachedObjectStore(const nsAString& aName);
+
   void SetTransactionListener(IDBTransactionListener* aListener);
 
   bool StartSavepoint();
   nsresult ReleaseSavepoint();
   void RollbackSavepoint();
 
   // Only meant to be called on mStorageThread!
   nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
--- a/dom/indexedDB/test/test_remove_index.html
+++ b/dom/indexedDB/test/test_remove_index.html
@@ -27,24 +27,40 @@
       is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
 
       let objectStore = db.createObjectStore("test store", { keyPath: "foo" });
       is(db.objectStoreNames.length, 1, "Correct objectStoreNames list");
       is(db.objectStoreNames.item(0), objectStore.name, "Correct name");
 
       is(objectStore.indexNames.length, 0, "Correct indexNames list");
 
-      objectStore.createIndex(indexName, "foo");
+      let index = objectStore.createIndex(indexName, "foo");
 
       is(objectStore.indexNames.length, 1, "Correct indexNames list");
       is(objectStore.indexNames.item(0), indexName, "Correct name");
+      is(objectStore.index(indexName), index, "Correct instance");
 
       objectStore.deleteIndex(indexName);
 
       is(objectStore.indexNames.length, 0, "Correct indexNames list");
+      try {
+        objectStore.index(indexName);
+        ok(false, "should have thrown");
+      }
+      catch(ex) {
+        ok(ex instanceof IDBDatabaseException, "Got a IDBDatabaseException");
+        is(ex.code, IDBDatabaseException.NOT_FOUND_ERR, "expect a NOT_FOUND_ERR");
+      }
+
+      let index2 = objectStore.createIndex(indexName, "foo");
+      isnot(index, index2, "New instance should be created");
+
+      is(objectStore.indexNames.length, 1, "Correct recreacted indexNames list");
+      is(objectStore.indexNames.item(0), indexName, "Correct recreacted name");
+      is(objectStore.index(indexName), index2, "Correct instance");
 
       finishTest();
       yield;
     }
   </script>
   <script type="text/javascript;version=1.7" src="helpers.js"></script>
 
 </head>
--- a/dom/indexedDB/test/test_remove_objectStore.html
+++ b/dom/indexedDB/test/test_remove_objectStore.html
@@ -50,23 +50,36 @@
       db.close();
 
       let request = mozIndexedDB.open(name, 2, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
+      let trans = event.target.transaction;
 
-      db.deleteObjectStore(objectStore.name);
+      let oldObjectStore = trans.objectStore(objectStoreName);
+      isnot(oldObjectStore, null, "Correct object store prior to deleting");
+      db.deleteObjectStore(objectStoreName);
       is(db.objectStoreNames.length, 0, "Correct objectStores list");
+      try {
+        trans.objectStore(objectStoreName);
+        ok(false, "should have thrown");
+      }
+      catch(ex) {
+        ok(ex instanceof IDBDatabaseException, "Got a IDBDatabaseException");
+        is(ex.code, IDBDatabaseException.NOT_FOUND_ERR, "expect a NOT_FOUND_ERR");
+      }
 
       objectStore = db.createObjectStore(objectStoreName, { keyPath: "foo" });
       is(db.objectStoreNames.length, 1, "Correct objectStoreNames list");
       is(db.objectStoreNames.item(0), objectStoreName, "Correct name");
+      is(trans.objectStore(objectStoreName), objectStore, "Correct new objectStore");
+      isnot(oldObjectStore, objectStore, "Old objectStore is not new objectStore");
 
       request = objectStore.openCursor();
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
         is(event.target.result, undefined, "ObjectStore shouldn't have any items");
         testGenerator.send(event);
       }
       event = yield;