IndexedDB 2.0: Clean up more transaction abort behavior, including tweaks to Index...
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 9 Nov 2016 20:23:11 +0000 (20:23 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 9 Nov 2016 20:23:11 +0000 (20:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164466

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

* web-platform-tests/IndexedDB/transaction-abort-index-metadata-revert-expected.txt:
* web-platform-tests/IndexedDB/transaction-abort-multiple-metadata-revert-expected.txt:
* web-platform-tests/IndexedDB/transaction-abort-object-store-metadata-revert-expected.txt:

Source/WebCore:

No new tests (Covered by existing tests that now pass).

Previously, IDBIndex ref/deref didn't track a traditional ref count but instead kept the owning object store alive.
Now, IDBObjectStore ref/deref do the same thing for the owning transaction.

Now when a version change transaction is rolled back, some object stores and indexes get pulled out of the "deleted"
set and get promoted back up into the "referenced" set.

Now deleted object stores/indexes are considered opaque roots, as live objects in the deleted state *can* get back
to the owning objects.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:

* Modules/indexeddb/IDBIndex.cpp:
(WebCore::IDBIndex::rollbackInfoForVersionChangeAbort):

* Modules/indexeddb/IDBObjectStore.cpp:
(WebCore::IDBObjectStore::IDBObjectStore):
(WebCore::IDBObjectStore::indexNames):
(WebCore::IDBObjectStore::transaction):
(WebCore::IDBObjectStore::openCursor):
(WebCore::IDBObjectStore::openKeyCursor):
(WebCore::IDBObjectStore::deleteIndex):
(WebCore::IDBObjectStore::rollbackForVersionChangeAbort):
(WebCore::IDBObjectStore::visitReferencedIndexes):
(WebCore::IDBObjectStore::ref):
(WebCore::IDBObjectStore::deref):
(WebCore::IDBObjectStore::create): Deleted.
* Modules/indexeddb/IDBObjectStore.h:

* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::objectStore):
(WebCore::IDBTransaction::transitionedToFinishing):
(WebCore::IDBTransaction::internalAbort):
(WebCore::IDBTransaction::createObjectStore):
(WebCore::IDBTransaction::deleteObjectStore):
(WebCore::IDBTransaction::visitReferencedObjectStores):
* Modules/indexeddb/IDBTransaction.h:
* Modules/indexeddb/IDBTransaction.idl:

* bindings/js/JSIDBTransactionCustom.cpp: Added.
(WebCore::JSIDBTransaction::visitAdditionalChildren):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208467 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/IndexedDB/transaction-abort-index-metadata-revert-expected.txt
LayoutTests/imported/w3c/web-platform-tests/IndexedDB/transaction-abort-multiple-metadata-revert-expected.txt
LayoutTests/imported/w3c/web-platform-tests/IndexedDB/transaction-abort-object-store-metadata-revert-expected.txt
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBIndex.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStore.h
Source/WebCore/Modules/indexeddb/IDBTransaction.cpp
Source/WebCore/Modules/indexeddb/IDBTransaction.h
Source/WebCore/Modules/indexeddb/IDBTransaction.idl
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSIDBTransactionCustom.cpp [new file with mode: 0644]

index 69ba7bb..b99edab 100644 (file)
@@ -1,3 +1,14 @@
+2016-11-09  Brady Eidson  <beidson@apple.com>
+
+        IndexedDB 2.0: Clean up more transaction abort behavior, including tweaks to Index/ObjectStore lifetime.
+        https://bugs.webkit.org/show_bug.cgi?id=164466
+
+        Reviewed by Alex Christensen.
+
+        * web-platform-tests/IndexedDB/transaction-abort-index-metadata-revert-expected.txt:
+        * web-platform-tests/IndexedDB/transaction-abort-multiple-metadata-revert-expected.txt:
+        * web-platform-tests/IndexedDB/transaction-abort-object-store-metadata-revert-expected.txt:
+
 2016-11-09  Alex Christensen  <achristensen@webkit.org>
 
         Ignore URL.origin in URL web-platform-tests
index 6d6e943..046516b 100644 (file)
@@ -1,8 +1,8 @@
 
 PASS Created stores get their indexes marked as deleted after the transaction that created them aborts 
-FAIL Deleted stores get their indexes marked as not-deleted after the transaction that deleted them aborts assert_array_equals: IDBObjectStore.indexNames should be empty immediately after IDBDatabase.deleteObjectStore() returns lengths differ, expected 0 got 2
-FAIL Created+deleted stores still have their indexes marked as deleted after the transaction aborts assert_array_equals: IDBObjectStore.indexNames should be empty immediately after IDBDatabase.deleteObjectStore() returns lengths differ, expected 0 got 2
+PASS Deleted stores get their indexes marked as not-deleted after the transaction that deleted them aborts 
+PASS Created+deleted stores still have their indexes marked as deleted after the transaction aborts 
 PASS Created indexes get marked as deleted after their transaction aborts 
-FAIL Deleted indexes get marked as not-deleted after the transaction aborts assert_throws: IDBIndex.get should throw TransactionInactiveError, indicating that the index is no longer marked for deletion, immediately after IDBTransaction.abort() returns function "() => index.get('query')" threw object "InvalidStateError (DOM IDBDatabase Exception 11): Failed ..." that is not a DOMException TransactionInactiveError: property "code" is equal to 11, expected 0
+PASS Deleted indexes get marked as not-deleted after the transaction aborts 
 PASS Created+deleted indexes are still marked as deleted after their transaction aborts 
 
index 7b09ca4..0dbea88 100644 (file)
@@ -1,5 +1,5 @@
 
 PASS Deleted indexes in newly created stores are still marked as deleted after the transaction aborts 
-FAIL Deleted indexes in deleted stores are still marked as not-deleted after the transaction aborts assert_array_equals: IDBObjectStore.indexNames for the deleted store should be empty immediately after IDBDatabase.deleteObjectStore() returns lengths differ, expected 0 got 1
-FAIL Deleted indexes in created+deleted stores are still marked as deleted after their transaction aborts assert_array_equals: IDBObjectStore.indexNames should be empty immediately after IDBDatabase.deleteObjectStore() returns lengths differ, expected 0 got 1
+PASS Deleted indexes in deleted stores are still marked as not-deleted after the transaction aborts 
+PASS Deleted indexes in created+deleted stores are still marked as deleted after their transaction aborts 
 
index 3a316bf..f68ce3a 100644 (file)
@@ -1,6 +1,6 @@
 
 PASS Created stores get marked as deleted after their transaction aborts 
-FAIL Deleted stores get marked as not-deleted after the transaction aborts assert_throws: IDBObjectStore.get should throw TransactionInactiveError, indicating that the store is no longer marked for deletion, immediately after IDBTransaction.abort() returns function "() => store.get('query')" threw object "InvalidStateError (DOM IDBDatabase Exception 11): Failed ..." that is not a DOMException TransactionInactiveError: property "code" is equal to 11, expected 0
+PASS Deleted stores get marked as not-deleted after the transaction aborts 
 PASS Created+deleted stores are still marked as deleted after their transaction aborts 
 PASS Un-instantiated deleted stores get marked as not-deleted after the transaction aborts 
 
index 3cd589c..f448436 100644 (file)
@@ -1152,6 +1152,7 @@ set(WebCore_SOURCES
     bindings/js/JSIDBIndexCustom.cpp
     bindings/js/JSIDBObjectStoreCustom.cpp
     bindings/js/JSIDBRequestCustom.cpp
+    bindings/js/JSIDBTransactionCustom.cpp
     bindings/js/JSImageConstructor.cpp
     bindings/js/JSImageDataCustom.cpp
     bindings/js/JSInspectorFrontendHostCustom.cpp
index 7ec7654..0b62345 100644 (file)
@@ -1,3 +1,54 @@
+2016-11-09  Brady Eidson  <beidson@apple.com>
+
+        IndexedDB 2.0: Clean up more transaction abort behavior, including tweaks to Index/ObjectStore lifetime.
+        https://bugs.webkit.org/show_bug.cgi?id=164466
+
+        Reviewed by Alex Christensen.
+
+        No new tests (Covered by existing tests that now pass).
+        
+        Previously, IDBIndex ref/deref didn't track a traditional ref count but instead kept the owning object store alive.
+        Now, IDBObjectStore ref/deref do the same thing for the owning transaction.
+        
+        Now when a version change transaction is rolled back, some object stores and indexes get pulled out of the "deleted"
+        set and get promoted back up into the "referenced" set.
+        
+        Now deleted object stores/indexes are considered opaque roots, as live objects in the deleted state *can* get back
+        to the owning objects.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * Modules/indexeddb/IDBIndex.cpp:
+        (WebCore::IDBIndex::rollbackInfoForVersionChangeAbort):
+
+        * Modules/indexeddb/IDBObjectStore.cpp:
+        (WebCore::IDBObjectStore::IDBObjectStore):
+        (WebCore::IDBObjectStore::indexNames):
+        (WebCore::IDBObjectStore::transaction):
+        (WebCore::IDBObjectStore::openCursor):
+        (WebCore::IDBObjectStore::openKeyCursor):
+        (WebCore::IDBObjectStore::deleteIndex):
+        (WebCore::IDBObjectStore::rollbackForVersionChangeAbort):
+        (WebCore::IDBObjectStore::visitReferencedIndexes):
+        (WebCore::IDBObjectStore::ref):
+        (WebCore::IDBObjectStore::deref):
+        (WebCore::IDBObjectStore::create): Deleted.
+        * Modules/indexeddb/IDBObjectStore.h:
+
+        * Modules/indexeddb/IDBTransaction.cpp:
+        (WebCore::IDBTransaction::objectStore):
+        (WebCore::IDBTransaction::transitionedToFinishing):
+        (WebCore::IDBTransaction::internalAbort):
+        (WebCore::IDBTransaction::createObjectStore):
+        (WebCore::IDBTransaction::deleteObjectStore):
+        (WebCore::IDBTransaction::visitReferencedObjectStores):
+        * Modules/indexeddb/IDBTransaction.h:
+        * Modules/indexeddb/IDBTransaction.idl:
+
+        * bindings/js/JSIDBTransactionCustom.cpp: Added.
+        (WebCore::JSIDBTransaction::visitAdditionalChildren):
+
 2016-11-09  Simon Fraser  <simon.fraser@apple.com>
 
         Allow customization of TextStream-based logging for geometry types
index 3a4578e..5a4e8c8 100644 (file)
@@ -146,6 +146,7 @@ void IDBIndex::rollbackInfoForVersionChangeAbort()
     }
 
     m_info = m_originalInfo;
+    m_deleted = false;
 }
 
 ExceptionOr<Ref<IDBRequest>> IDBIndex::openCursor(ExecState& execState, IDBKeyRange* range, const String& directionString)
index 2f7fb8f..33e70fe 100644 (file)
@@ -53,16 +53,11 @@ using namespace JSC;
 
 namespace WebCore {
 
-Ref<IDBObjectStore> IDBObjectStore::create(ScriptExecutionContext& context, const IDBObjectStoreInfo& info, IDBTransaction& transaction)
-{
-    return adoptRef(*new IDBObjectStore(context, info, transaction));
-}
-
 IDBObjectStore::IDBObjectStore(ScriptExecutionContext& context, const IDBObjectStoreInfo& info, IDBTransaction& transaction)
     : ActiveDOMObject(&context)
     , m_info(info)
     , m_originalInfo(info)
-    , m_transaction(transaction)
+    , m_transaction(&transaction)
 {
     ASSERT(currentThread() == m_transaction->database().originThreadID());
 
@@ -131,9 +126,12 @@ RefPtr<DOMStringList> IDBObjectStore::indexNames() const
     ASSERT(currentThread() == m_transaction->database().originThreadID());
 
     RefPtr<DOMStringList> indexNames = DOMStringList::create();
-    for (auto& name : m_info.indexNames())
-        indexNames->append(name);
-    indexNames->sort();
+
+    if (!m_deleted) {
+        for (auto& name : m_info.indexNames())
+            indexNames->append(name);
+        indexNames->sort();
+    }
 
     return indexNames;
 }
@@ -141,7 +139,7 @@ RefPtr<DOMStringList> IDBObjectStore::indexNames() const
 IDBTransaction& IDBObjectStore::transaction()
 {
     ASSERT(currentThread() == m_transaction->database().originThreadID());
-    return m_transaction.get();
+    return *m_transaction;
 }
 
 bool IDBObjectStore::autoIncrement() const
@@ -165,7 +163,7 @@ ExceptionOr<Ref<IDBRequest>> IDBObjectStore::openCursor(ExecState& execState, Re
     if (!direction)
         return Exception { TypeError };
 
-    auto info = IDBCursorInfo::objectStoreCursor(m_transaction.get(), m_info.identifier(), range.get(), direction.value(), IndexedDB::CursorType::KeyAndValue);
+    auto info = IDBCursorInfo::objectStoreCursor(*m_transaction, m_info.identifier(), range.get(), direction.value(), IndexedDB::CursorType::KeyAndValue);
     return m_transaction->requestOpenCursor(execState, *this, info);
 }
 
@@ -193,7 +191,7 @@ ExceptionOr<Ref<IDBRequest>> IDBObjectStore::openKeyCursor(ExecState& execState,
     if (!direction)
         return Exception { TypeError };
 
-    auto info = IDBCursorInfo::objectStoreCursor(m_transaction.get(), m_info.identifier(), range.get(), direction.value(), IndexedDB::CursorType::KeyOnly);
+    auto info = IDBCursorInfo::objectStoreCursor(*m_transaction, m_info.identifier(), range.get(), direction.value(), IndexedDB::CursorType::KeyOnly);
     return m_transaction->requestOpenCursor(execState, *this, info);
 }
 
@@ -494,9 +492,8 @@ ExceptionOr<void> IDBObjectStore::deleteIndex(const String& name)
         Locker<Lock> locker(m_referencedIndexLock);
         if (auto index = m_referencedIndexes.take(name)) {
             index->markAsDeleted();
-            m_deletedIndexes.add(WTFMove(index));
+            m_deletedIndexes.add(index->info().identifier(), WTFMove(index));
         }
-
     }
 
     m_transaction->deleteIndex(m_info.identifier(), name);
@@ -608,6 +605,8 @@ void IDBObjectStore::rollbackForVersionChangeAbort()
         m_info.rename(currentName);
         m_deleted = true;
     } else {
+        m_deleted = false;
+        
         HashSet<uint64_t> indexesToRemove;
         for (auto indexIdentifier : objectStoreInfo->indexMap().keys()) {
             if (!objectStoreInfo->hasIndex(indexIdentifier))
@@ -619,6 +618,13 @@ void IDBObjectStore::rollbackForVersionChangeAbort()
     }
 
     Locker<Lock> locker(m_referencedIndexLock);
+    for (auto& iterator : m_deletedIndexes) {
+        if (m_info.hasIndex(iterator.key)) {
+            auto name = iterator.value->info().name();
+            m_referencedIndexes.set(name, WTFMove(iterator.value));
+        }
+    }
+
     for (auto& index : m_referencedIndexes.values())
         index->rollbackInfoForVersionChangeAbort();
 }
@@ -628,6 +634,8 @@ void IDBObjectStore::visitReferencedIndexes(SlotVisitor& visitor) const
     Locker<Lock> locker(m_referencedIndexLock);
     for (auto& index : m_referencedIndexes.values())
         visitor.addOpaqueRoot(index.get());
+    for (auto& index : m_deletedIndexes.values())
+        visitor.addOpaqueRoot(index.get());
 }
 
 void IDBObjectStore::renameReferencedIndex(IDBIndex& index, const String& newName)
@@ -645,6 +653,16 @@ void IDBObjectStore::renameReferencedIndex(IDBIndex& index, const String& newNam
     m_referencedIndexes.set(newName, m_referencedIndexes.take(index.info().name()));
 }
 
+void IDBObjectStore::ref()
+{
+    m_transaction->ref();
+}
+
+void IDBObjectStore::deref()
+{
+    m_transaction->deref();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index 7b14d0f..32e72fa 100644 (file)
@@ -54,10 +54,9 @@ namespace IndexedDB {
 enum class ObjectStoreOverwriteMode;
 }
 
-class IDBObjectStore final : public RefCounted<IDBObjectStore>, public ActiveDOMObject {
+class IDBObjectStore final : public ActiveDOMObject {
 public:
-    static Ref<IDBObjectStore> create(ScriptExecutionContext&, const IDBObjectStoreInfo&, IDBTransaction&);
-
+    IDBObjectStore(ScriptExecutionContext&, const IDBObjectStoreInfo&, IDBTransaction&);
     ~IDBObjectStore();
 
     const String& name() const;
@@ -102,12 +101,13 @@ public:
 
     void rollbackForVersionChangeAbort();
 
+    void ref();
+    void deref();
+
     void visitReferencedIndexes(JSC::SlotVisitor&) const;
     void renameReferencedIndex(IDBIndex&, const String& newName);
 
 private:
-    IDBObjectStore(ScriptExecutionContext&, const IDBObjectStoreInfo&, IDBTransaction&);
-
     enum class InlineKeyCheck { Perform, DoNotPerform };
     ExceptionOr<Ref<IDBRequest>> putOrAdd(JSC::ExecState&, JSC::JSValue, RefPtr<IDBKey>, IndexedDB::ObjectStoreOverwriteMode, InlineKeyCheck);
     ExceptionOr<Ref<IDBRequest>> doCount(JSC::ExecState&, const IDBKeyRangeData&);
@@ -119,13 +119,20 @@ private:
 
     IDBObjectStoreInfo m_info;
     IDBObjectStoreInfo m_originalInfo;
-    Ref<IDBTransaction> m_transaction;
+
+    // IDBObjectStore objects are always owned by their referencing IDBTransaction.
+    // ObjectStores will never outlive transactions so its okay to keep a raw C++ reference here.
+
+    // FIXME: This should be a reference instead of a pointer (as mentioned by the above comment)
+    // but leaving it a pointer for now makes this patch much easier to review.
+    // I'll make the ptr->ref change right after this patch lands.
+    IDBTransaction* m_transaction;
 
     bool m_deleted { false };
 
     mutable Lock m_referencedIndexLock;
     HashMap<String, std::unique_ptr<IDBIndex>> m_referencedIndexes;
-    HashSet<std::unique_ptr<IDBIndex>> m_deletedIndexes;
+    HashMap<uint64_t, std::unique_ptr<IDBIndex>> m_deletedIndexes;
 };
 
 } // namespace WebCore
index 2d81192..d62f759 100644 (file)
@@ -149,6 +149,8 @@ ExceptionOr<Ref<IDBObjectStore>> IDBTransaction::objectStore(const String& objec
     if (isFinishedOrFinishing())
         return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral("Failed to execute 'objectStore' on 'IDBTransaction': The transaction finished.") };
 
+    Locker<Lock> locker(m_referencedObjectStoreLock);
+
     auto iterator = m_referencedObjectStores.find(objectStoreName);
     if (iterator != m_referencedObjectStores.end())
         return Ref<IDBObjectStore> { *iterator->value };
@@ -169,10 +171,11 @@ ExceptionOr<Ref<IDBObjectStore>> IDBTransaction::objectStore(const String& objec
     if (!info || (!found && !isVersionChange()))
         return Exception { IDBDatabaseException::NotFoundError, ASCIILiteral("Failed to execute 'objectStore' on 'IDBTransaction': The specified object store was not found.") };
 
-    auto objectStore = IDBObjectStore::create(*scriptExecutionContext(), *info, *this);
-    m_referencedObjectStores.set(objectStoreName, objectStore.ptr());
+    auto objectStore = std::make_unique<IDBObjectStore>(*scriptExecutionContext(), *info, *this);
+    auto* rawObjectStore = objectStore.get();
+    m_referencedObjectStores.set(objectStoreName, WTFMove(objectStore));
 
-    return WTFMove(objectStore);
+    return Ref<IDBObjectStore>(*rawObjectStore);
 }
 
 
@@ -195,7 +198,6 @@ void IDBTransaction::transitionedToFinishing(IndexedDB::TransactionState state)
     ASSERT(!isFinishedOrFinishing());
     m_state = state;
     ASSERT(isFinishedOrFinishing());
-    m_referencedObjectStores.clear();
 }
 
 ExceptionOr<void> IDBTransaction::abort()
@@ -220,6 +222,16 @@ void IDBTransaction::internalAbort()
     m_database->willAbortTransaction(*this);
 
     if (isVersionChange()) {
+        Locker<Lock> locker(m_referencedObjectStoreLock);
+
+        auto& info = m_database->info();
+        for (auto& iterator : m_deletedObjectStores) {
+            if (info.infoForExistingObjectStore(iterator.key)) {
+                auto name = iterator.value->info().name();
+                m_referencedObjectStores.set(name, WTFMove(iterator.value));
+            }
+        }
+
         for (auto& objectStore : m_referencedObjectStores.values())
             objectStore->rollbackForVersionChangeAbort();
     }
@@ -517,12 +529,15 @@ Ref<IDBObjectStore> IDBTransaction::createObjectStore(const IDBObjectStoreInfo&
     ASSERT(scriptExecutionContext());
     ASSERT(currentThread() == m_database->originThreadID());
 
-    Ref<IDBObjectStore> objectStore = IDBObjectStore::create(*scriptExecutionContext(), info, *this);
-    m_referencedObjectStores.set(info.name(), &objectStore.get());
+    Locker<Lock> locker(m_referencedObjectStoreLock);
+
+    auto objectStore = std::make_unique<IDBObjectStore>(*scriptExecutionContext(), info, *this);
+    auto* rawObjectStore = objectStore.get();
+    m_referencedObjectStores.set(info.name(), WTFMove(objectStore));
 
     scheduleOperation(IDBClient::createTransactionOperation(*this, &IDBTransaction::didCreateObjectStoreOnServer, &IDBTransaction::createObjectStoreOnServer, info));
 
-    return objectStore;
+    return *rawObjectStore;
 }
 
 void IDBTransaction::createObjectStoreOnServer(IDBClient::TransactionOperation& operation, const IDBObjectStoreInfo& info)
@@ -544,6 +559,9 @@ void IDBTransaction::didCreateObjectStoreOnServer(const IDBResultData& resultDat
 void IDBTransaction::renameObjectStore(IDBObjectStore& objectStore, const String& newName)
 {
     LOG(IndexedDB, "IDBTransaction::renameObjectStore");
+
+    Locker<Lock> locker(m_referencedObjectStoreLock);
+
     ASSERT(isVersionChange());
     ASSERT(scriptExecutionContext());
     ASSERT(currentThread() == m_database->originThreadID());
@@ -618,6 +636,8 @@ void IDBTransaction::didCreateIndexOnServer(const IDBResultData& resultData)
 void IDBTransaction::renameIndex(IDBIndex& index, const String& newName)
 {
     LOG(IndexedDB, "IDBTransaction::renameIndex");
+    Locker<Lock> locker(m_referencedObjectStoreLock);
+
     ASSERT(isVersionChange());
     ASSERT(scriptExecutionContext());
     ASSERT(currentThread() == m_database->originThreadID());
@@ -1088,8 +1108,13 @@ void IDBTransaction::deleteObjectStore(const String& objectStoreName)
     ASSERT(currentThread() == m_database->originThreadID());
     ASSERT(isVersionChange());
 
-    if (auto objectStore = m_referencedObjectStores.take(objectStoreName))
+    Locker<Lock> locker(m_referencedObjectStoreLock);
+
+    if (auto objectStore = m_referencedObjectStores.take(objectStoreName)) {
         objectStore->markAsDeleted();
+        auto identifier = objectStore->info().identifier();
+        m_deletedObjectStores.set(identifier, WTFMove(objectStore));
+    }
 
     scheduleOperation(IDBClient::createTransactionOperation(*this, &IDBTransaction::didDeleteObjectStoreOnServer, &IDBTransaction::deleteObjectStoreOnServer, objectStoreName));
 }
@@ -1197,6 +1222,15 @@ void IDBTransaction::connectionClosedFromServer(const IDBError& error)
     fireOnAbort();
 }
 
+void IDBTransaction::visitReferencedObjectStores(JSC::SlotVisitor& visitor) const
+{
+    Locker<Lock> locker(m_referencedObjectStoreLock);
+    for (auto& objectStore : m_referencedObjectStores.values())
+        visitor.addOpaqueRoot(objectStore.get());
+    for (auto& objectStore : m_deletedObjectStores.values())
+        visitor.addOpaqueRoot(objectStore.get());
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index 86babb1..7dab116 100644 (file)
@@ -146,6 +146,8 @@ public:
 
     void connectionClosedFromServer(const IDBError&);
 
+    void visitReferencedObjectStores(JSC::SlotVisitor&) const;
+
 private:
     IDBTransaction(IDBDatabase&, const IDBTransactionInfo&, IDBOpenDBRequest*);
 
@@ -234,7 +236,9 @@ private:
     Deque<RefPtr<IDBClient::TransactionOperation>> m_abortQueue;
     HashMap<IDBResourceIdentifier, RefPtr<IDBClient::TransactionOperation>> m_transactionOperationMap;
 
-    HashMap<String, RefPtr<IDBObjectStore>> m_referencedObjectStores;
+    mutable Lock m_referencedObjectStoreLock;
+    HashMap<String, std::unique_ptr<IDBObjectStore>> m_referencedObjectStores;
+    HashMap<uint64_t, std::unique_ptr<IDBObjectStore>> m_deletedObjectStores;
 
     HashSet<RefPtr<IDBRequest>> m_openRequests;
 
index a89b510..348ef3a 100644 (file)
@@ -28,6 +28,7 @@
     ActiveDOMObject,
     Conditional=INDEXED_DATABASE,
     EnabledAtRuntime=IndexedDB,
+    JSCustomMarkFunction,
     SkipVTableValidation,
 ] interface IDBTransaction : EventTarget {
     readonly attribute DOMStringList objectStoreNames;
index eaf0ed1..7818751 100644 (file)
                51E1ECC10C91C90400DC255B /* IconRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E1ECBB0C91C90400DC255B /* IconRecord.h */; };
                51E1ECC20C91C90400DC255B /* PageURLRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51E1ECBC0C91C90400DC255B /* PageURLRecord.cpp */; };
                51E1ECC30C91C90400DC255B /* PageURLRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E1ECBD0C91C90400DC255B /* PageURLRecord.h */; };
+               51E269331DD3BC4E006B6A58 /* JSIDBTransactionCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51E269321DD3BC43006B6A58 /* JSIDBTransactionCustom.cpp */; };
                51E399001D6E4750009C8831 /* GameControllerGamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E398FC1D6E474B009C8831 /* GameControllerGamepad.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51E399011D6E4750009C8831 /* GameControllerGamepad.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51E398FD1D6E474B009C8831 /* GameControllerGamepad.mm */; };
                51E399021D6E4750009C8831 /* GameControllerGamepadProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E398FE1D6E474B009C8831 /* GameControllerGamepadProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51E1ECBB0C91C90400DC255B /* IconRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconRecord.h; sourceTree = "<group>"; };
                51E1ECBC0C91C90400DC255B /* PageURLRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageURLRecord.cpp; sourceTree = "<group>"; };
                51E1ECBD0C91C90400DC255B /* PageURLRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageURLRecord.h; sourceTree = "<group>"; };
+               51E269321DD3BC43006B6A58 /* JSIDBTransactionCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBTransactionCustom.cpp; sourceTree = "<group>"; };
                51E398FC1D6E474B009C8831 /* GameControllerGamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameControllerGamepad.h; sourceTree = "<group>"; };
                51E398FD1D6E474B009C8831 /* GameControllerGamepad.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GameControllerGamepad.mm; sourceTree = "<group>"; };
                51E398FE1D6E474B009C8831 /* GameControllerGamepadProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameControllerGamepadProvider.h; sourceTree = "<group>"; };
                                5141299A1C6C166D0059E714 /* JSIDBIndexCustom.cpp */,
                                511EF2CE17F0FDF100E4FA16 /* JSIDBObjectStoreCustom.cpp */,
                                934F31B41CC0737200DB43DC /* JSIDBRequestCustom.cpp */,
+                               51E269321DD3BC43006B6A58 /* JSIDBTransactionCustom.cpp */,
                                A7D0318D0E93540300E24ACD /* JSImageDataCustom.cpp */,
                                7A74ECBC101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp */,
                                BCE1C43F0D9830F4003B02F2 /* JSLocationCustom.cpp */,
                                FD6ED2C3136B8E42003CF072 /* DynamicsCompressorNode.cpp in Sources */,
                                93309DE3099E64920056E581 /* EditCommand.cpp in Sources */,
                                9BAB6C6D12550631001626D4 /* EditingStyle.cpp in Sources */,
+                               51E269331DD3BC4E006B6A58 /* JSIDBTransactionCustom.cpp in Sources */,
                                4B3043CC0AE0373B00A82647 /* Editor.cpp in Sources */,
                                9B55EEE91B3E8898005342BC /* EditorCocoa.mm in Sources */,
                                93A38B4B0D0E5808006872C2 /* EditorCommand.cpp in Sources */,
diff --git a/Source/WebCore/bindings/js/JSIDBTransactionCustom.cpp b/Source/WebCore/bindings/js/JSIDBTransactionCustom.cpp
new file mode 100644 (file)
index 0000000..0e6d383
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSIDBTransaction.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "JSDOMBinding.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSIDBTransaction::visitAdditionalChildren(SlotVisitor& visitor)
+{
+    static_cast<IDBTransaction&>(wrapped()).visitReferencedObjectStores(visitor);
+}
+
+}
+
+#endif