Title: [192749] trunk
Revision
192749
Author
beid...@apple.com
Date
2015-11-23 11:48:50 -0800 (Mon, 23 Nov 2015)

Log Message

Modern IDB: When a transaction is aborted, call onerror handlers for all in-progress requests.
https://bugs.webkit.org/show_bug.cgi?id=151550

Reviewed by Alex Christensen.

Source/WebCore:

Test: storage/indexeddb/modern/abort-requests-cancelled.html
      storage/indexeddb/modern/idbtransaction-objectstore-failures.html (with changes)
      storage/indexeddb/modern/index-5.html (with changes)
      Various (currently skipped) legacy IDB tests.

* Modules/indexeddb/client/IDBDatabaseImpl.cpp:
(WebCore::IDBClient::IDBDatabase::transaction):
(WebCore::IDBClient::IDBDatabase::startVersionChangeTransaction):
(WebCore::IDBClient::IDBDatabase::didStartTransaction):
(WebCore::IDBClient::IDBDatabase::willCommitTransaction):
(WebCore::IDBClient::IDBDatabase::didCommitTransaction):
(WebCore::IDBClient::IDBDatabase::willAbortTransaction):
(WebCore::IDBClient::IDBDatabase::didAbortTransaction):
(WebCore::IDBClient::IDBDatabase::didCommitOrAbortTransaction):

* Modules/indexeddb/client/IDBTransactionImpl.cpp:
(WebCore::IDBClient::IDBTransaction::abort):
(WebCore::IDBClient::IDBTransaction::abortOnServerAndCancelRequests):
(WebCore::IDBClient::IDBTransaction::didCreateObjectStoreOnServer):
(WebCore::IDBClient::IDBTransaction::didCreateIndexOnServer):
(WebCore::IDBClient::IDBTransaction::didGetRecordOnServer):
(WebCore::IDBClient::IDBTransaction::didDeleteObjectStoreOnServer):
(WebCore::IDBClient::IDBTransaction::didDeleteIndexOnServer):
(WebCore::IDBClient::IDBTransaction::immediateAbort): Deleted.
(WebCore::IDBClient::IDBTransaction::abortOnServer): Deleted.
* Modules/indexeddb/client/IDBTransactionImpl.h:

* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::abortTransaction):
(WebCore::IDBServer::MemoryIDBBackingStore::commitTransaction):

* Modules/indexeddb/shared/IDBError.cpp:
(WebCore::idbErrorName):
(WebCore::idbErrorDescription):
* Modules/indexeddb/shared/IDBError.h:

* Modules/indexeddb/shared/IDBResourceIdentifier.cpp:
(WebCore::IDBResourceIdentifier::loggingString):
* Modules/indexeddb/shared/IDBResourceIdentifier.h:

LayoutTests:

* storage/indexeddb/modern/abort-requests-cancelled-expected.txt: Added.
* storage/indexeddb/modern/abort-requests-cancelled.html: Added.
* storage/indexeddb/modern/idbtransaction-objectstore-failures-expected.txt:
* storage/indexeddb/modern/idbtransaction-objectstore-failures.html:
* storage/indexeddb/modern/index-5-expected.txt:
* storage/indexeddb/modern/index-5.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (192748 => 192749)


--- trunk/LayoutTests/ChangeLog	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/LayoutTests/ChangeLog	2015-11-23 19:48:50 UTC (rev 192749)
@@ -1,5 +1,19 @@
 2015-11-23  Brady Eidson  <beid...@apple.com>
 
+        Modern IDB: When a transaction is aborted, call onerror handlers for all in-progress requests.
+        https://bugs.webkit.org/show_bug.cgi?id=151550
+
+        Reviewed by Alex Christensen.
+
+        * storage/indexeddb/modern/abort-requests-cancelled-expected.txt: Added.
+        * storage/indexeddb/modern/abort-requests-cancelled.html: Added.
+        * storage/indexeddb/modern/idbtransaction-objectstore-failures-expected.txt:
+        * storage/indexeddb/modern/idbtransaction-objectstore-failures.html:
+        * storage/indexeddb/modern/index-5-expected.txt:
+        * storage/indexeddb/modern/index-5.html:
+
+2015-11-23  Brady Eidson  <beid...@apple.com>
+
         Modern IDB: Unskip storage/indexeddb/mozilla/global-data.html.
         https://bugs.webkit.org/show_bug.cgi?id=151557
 

Added: trunk/LayoutTests/storage/indexeddb/modern/abort-requests-cancelled-expected.txt (0 => 192749)


--- trunk/LayoutTests/storage/indexeddb/modern/abort-requests-cancelled-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/abort-requests-cancelled-expected.txt	2015-11-23 19:48:50 UTC (rev 192749)
@@ -0,0 +1,24 @@
+This test makes sure that un-handled requests in a transaction receive onerror callbacks when the transaction is aborted.
+Initial upgrade needed: Old version - 0 New version - 1
+Error handling: "objectStore.put({ bar: 'A' }, 1);" (error)
+Error handling: "objectStore.put({ bar: 'B' }, 2);" (error)
+Error handling: "objectStore.put({ bar: 'C' }, 3);" (error)
+Initial upgrade versionchange transaction aborted
+Second upgrade needed: Old version - 0 New version - 1
+Success handling: "objectStore.put({ bar: 'A' }, 1);"
+Success handling: "objectStore.put({ bar: 'B' }, 2);"
+Success handling: "objectStore.put({ bar: 'C' }, 3);"
+Second upgrade versionchange transaction completed
+Error handling: "objectStore.get(1);" (error)
+Error handling: "objectStore.get(2);" (error)
+Error handling: "objectStore.get(3);" (error)
+Error handling: "objectStore.put({ bar: 'D' }, 4);" (error)
+Error handling: "objectStore.put({ bar: 'E' }, 5);" (error)
+Error handling: "objectStore.put({ bar: 'F' }, 6);" (error)
+readwrite transaction aborted
+Error handling: "objectStore.get(1);" (error)
+Error handling: "objectStore.get(2);" (error)
+Error handling: "objectStore.get(3);" (error)
+readonly transaction aborted
+Done
+

Added: trunk/LayoutTests/storage/indexeddb/modern/abort-requests-cancelled.html (0 => 192749)


--- trunk/LayoutTests/storage/indexeddb/modern/abort-requests-cancelled.html	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/abort-requests-cancelled.html	2015-11-23 19:48:50 UTC (rev 192749)
@@ -0,0 +1,157 @@
+This test makes sure that un-handled requests in a transaction receive onerror callbacks when the transaction is aborted.<br>
+<div id="logger"></div>
+<script>
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log("Done");
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById("logger").innerHTML += message + "<br>";
+}
+
+var database;
+var objectStore;
+
+function setupRequest(code)
+{
+    var request = eval(code);
+    request._onsuccess_ = function()
+    {
+        log ("Success handling: \"" + code + "\"");
+    }
+    request._onerror_ = function(e)
+    {
+        log ("Error handling: \"" + code + "\" (" + e.type + ")");
+        e.stopPropagation();
+    }   
+}
+
+startTest();
+
+function startTest() {
+    var createRequest = window.indexedDB.open("AbortRequestsCancelledDatabase", 1);
+    createRequest._onupgradeneeded_ = function(event) {
+        log("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+        var versionTransaction = createRequest.transaction;
+        var database = event.target.result;
+        objectStore = database.createObjectStore("TestObjectStore");
+        setupRequest("objectStore.put({ bar: 'A' }, 1);");
+        setupRequest("objectStore.put({ bar: 'B' }, 2);");
+        setupRequest("objectStore.put({ bar: 'C' }, 3);");
+
+        versionTransaction.abort();
+
+        versionTransaction._onabort_ = function(event) {
+            log("Initial upgrade versionchange transaction aborted");
+            database.close();
+            continueTest1();
+        }
+
+        versionTransaction._oncomplete_ = function(event) {
+            log("Initial upgrade versionchange transaction unexpected complete");
+            done();
+        }
+
+        versionTransaction._onerror_ = function(event) {
+            log("Initial upgrade versionchange transaction unexpected error" + event);
+            done();
+        }
+    }
+}
+
+function continueTest1() {
+    var createRequest = window.indexedDB.open("AbortRequestsCancelledDatabase", 1);
+    createRequest._onupgradeneeded_ = function(event) {
+        log("Second upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+        var versionTransaction = createRequest.transaction;
+        database = event.target.result;
+        objectStore = database.createObjectStore("TestObjectStore");
+    
+        setupRequest("objectStore.put({ bar: 'A' }, 1);");
+        setupRequest("objectStore.put({ bar: 'B' }, 2);");
+        setupRequest("objectStore.put({ bar: 'C' }, 3);");
+    
+        versionTransaction._onabort_ = function(event) {
+            log("Second upgrade versionchange transaction unexpected abort");
+            done();
+        }
+
+        versionTransaction._oncomplete_ = function(event) {
+            log("Second upgrade versionchange transaction completed");
+            continueTest2();
+        }
+
+        versionTransaction._onerror_ = function(event) {
+            log("Second upgrade versionchange transaction unexpected error" + event);
+            done();
+        }
+    }
+}
+
+function continueTest2() {
+    var transaction = database.transaction("TestObjectStore", "readwrite");
+    objectStore = transaction.objectStore("TestObjectStore");
+
+    setupRequest("objectStore.get(1);");
+    setupRequest("objectStore.get(2);");
+    setupRequest("objectStore.get(3);");
+    setupRequest("objectStore.put({ bar: 'D' }, 4);");
+    setupRequest("objectStore.put({ bar: 'E' }, 5);");
+    setupRequest("objectStore.put({ bar: 'F' }, 6);");
+
+    transaction.abort();
+
+    transaction._onabort_ = function(event) {
+        log("readwrite transaction aborted");
+        continueTest3();
+    }
+
+    transaction._oncomplete_ = function(event) {
+        log("readwrite transaction unexpected complete");
+        done();
+    }
+
+    transaction._onerror_ = function(event) {
+        log("readwrite transaction unexpected error" + event);
+        done();
+    }
+}
+
+function continueTest3() {
+    var transaction = database.transaction("TestObjectStore", "readonly");
+    objectStore = transaction.objectStore("TestObjectStore");
+
+    setupRequest("objectStore.get(1);");
+    setupRequest("objectStore.get(2);");
+    setupRequest("objectStore.get(3);");
+
+    transaction.abort();
+
+    transaction._onabort_ = function(event) {
+        log("readonly transaction aborted");
+        done();
+    }
+
+    transaction._oncomplete_ = function(event) {
+        log("readwrite transaction unexpected complete");
+        done();
+    }
+
+    transaction._onerror_ = function(event) {
+        log("readwrite transaction unexpected error" + event);
+        done();
+    }
+}
+</script>

Modified: trunk/LayoutTests/storage/indexeddb/modern/idbtransaction-objectstore-failures-expected.txt (192748 => 192749)


--- trunk/LayoutTests/storage/indexeddb/modern/idbtransaction-objectstore-failures-expected.txt	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/LayoutTests/storage/indexeddb/modern/idbtransaction-objectstore-failures-expected.txt	2015-11-23 19:48:50 UTC (rev 192749)
@@ -5,7 +5,8 @@
 ALERT: Caught attempt to access null-named object store on the transaction
 ALERT: Caught attempt to access non-existant object store on the transaction
 ALERT: Caught attempt to access valid object store on a transaction that is already finishing
-ALERT: First version change transaction abort
+ALERT: put failed (because transaction was aborted)
+ALERT: First version change transaction unexpected error - [object Event]
 ALERT: Done
 This tests some obvious failures that can happen while calling transaction.objectStore()
 

Modified: trunk/LayoutTests/storage/indexeddb/modern/idbtransaction-objectstore-failures.html (192748 => 192749)


--- trunk/LayoutTests/storage/indexeddb/modern/idbtransaction-objectstore-failures.html	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/LayoutTests/storage/indexeddb/modern/idbtransaction-objectstore-failures.html	2015-11-23 19:48:50 UTC (rev 192749)
@@ -30,9 +30,8 @@
 
     var putRequest = os1.put("bar", "foo");
     
-    putRequest._onerror_ = function(event) {
-        alert("put unexpectedly failed - " + event);
-        done();
+    putRequest._onerror_ = function() {
+        alert("put failed (because transaction was aborted)");
     }
     
     try {

Modified: trunk/LayoutTests/storage/indexeddb/modern/index-5-expected.txt (192748 => 192749)


--- trunk/LayoutTests/storage/indexeddb/modern/index-5-expected.txt	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-5-expected.txt	2015-11-23 19:48:50 UTC (rev 192749)
@@ -1,6 +1,8 @@
 This tests creating an index on an object store that already has records, and those records would violate the unique constraint of the index.
 (The index creation should fail).
 Initial upgrade needed: Old version - 0 New version - 1
+Error getting cursor count
+Error opening or iterating cursor
 Initial upgrade versionchange transaction aborted (expected because index creation failed, and that should've caused transaction abort)
 Done
 

Modified: trunk/LayoutTests/storage/indexeddb/modern/index-5.html (192748 => 192749)


--- trunk/LayoutTests/storage/indexeddb/modern/index-5.html	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-5.html	2015-11-23 19:48:50 UTC (rev 192749)
@@ -29,6 +29,10 @@
     countRequest._onsuccess_ = function() {
         log("Count is: " + countRequest.result);
     }
+    countRequest._onerror_ = function(e) {
+        log("Error getting cursor count");
+        e.stopPropagation();
+    }
 
     var cursorRequest = index.openCursor();
     cursorRequest._onsuccess_ = function() {
@@ -41,9 +45,8 @@
             done();
     }
     cursorRequest._onerror_ = function(e) {
-        log("Unexpected error opening or iterating cursor");
-        logCursor(cursorRequest.result);
-        done();
+        log("Error opening or iterating cursor");
+        e.stopPropagation();
     } 
 }
 

Modified: trunk/Source/WebCore/ChangeLog (192748 => 192749)


--- trunk/Source/WebCore/ChangeLog	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/ChangeLog	2015-11-23 19:48:50 UTC (rev 192749)
@@ -1,5 +1,52 @@
 2015-11-23  Brady Eidson  <beid...@apple.com>
 
+        Modern IDB: When a transaction is aborted, call onerror handlers for all in-progress requests.
+        https://bugs.webkit.org/show_bug.cgi?id=151550
+
+        Reviewed by Alex Christensen.
+
+        Test: storage/indexeddb/modern/abort-requests-cancelled.html
+              storage/indexeddb/modern/idbtransaction-objectstore-failures.html (with changes)
+              storage/indexeddb/modern/index-5.html (with changes)
+              Various (currently skipped) legacy IDB tests.
+
+        * Modules/indexeddb/client/IDBDatabaseImpl.cpp:
+        (WebCore::IDBClient::IDBDatabase::transaction):
+        (WebCore::IDBClient::IDBDatabase::startVersionChangeTransaction):
+        (WebCore::IDBClient::IDBDatabase::didStartTransaction):
+        (WebCore::IDBClient::IDBDatabase::willCommitTransaction):
+        (WebCore::IDBClient::IDBDatabase::didCommitTransaction):
+        (WebCore::IDBClient::IDBDatabase::willAbortTransaction):
+        (WebCore::IDBClient::IDBDatabase::didAbortTransaction):
+        (WebCore::IDBClient::IDBDatabase::didCommitOrAbortTransaction):
+        
+        * Modules/indexeddb/client/IDBTransactionImpl.cpp:
+        (WebCore::IDBClient::IDBTransaction::abort):
+        (WebCore::IDBClient::IDBTransaction::abortOnServerAndCancelRequests):
+        (WebCore::IDBClient::IDBTransaction::didCreateObjectStoreOnServer):
+        (WebCore::IDBClient::IDBTransaction::didCreateIndexOnServer):
+        (WebCore::IDBClient::IDBTransaction::didGetRecordOnServer):
+        (WebCore::IDBClient::IDBTransaction::didDeleteObjectStoreOnServer):
+        (WebCore::IDBClient::IDBTransaction::didDeleteIndexOnServer):
+        (WebCore::IDBClient::IDBTransaction::immediateAbort): Deleted.
+        (WebCore::IDBClient::IDBTransaction::abortOnServer): Deleted.
+        * Modules/indexeddb/client/IDBTransactionImpl.h:
+        
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::abortTransaction):
+        (WebCore::IDBServer::MemoryIDBBackingStore::commitTransaction):
+        
+        * Modules/indexeddb/shared/IDBError.cpp:
+        (WebCore::idbErrorName):
+        (WebCore::idbErrorDescription):
+        * Modules/indexeddb/shared/IDBError.h:
+        
+        * Modules/indexeddb/shared/IDBResourceIdentifier.cpp:
+        (WebCore::IDBResourceIdentifier::loggingString):
+        * Modules/indexeddb/shared/IDBResourceIdentifier.h:
+
+2015-11-23  Brady Eidson  <beid...@apple.com>
+
         Modern IDB: Unskip storage/indexeddb/mozilla/global-data.html.
         https://bugs.webkit.org/show_bug.cgi?id=151557
 

Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp (192748 => 192749)


--- trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp	2015-11-23 19:48:50 UTC (rev 192749)
@@ -171,6 +171,8 @@
     auto info = IDBTransactionInfo::clientTransaction(m_serverConnection.get(), objectStores, mode);
     auto transaction = IDBTransaction::create(*this, info);
 
+    LOG(IndexedDB, "IDBDatabase::transaction - Added active transaction %s", info.identifier().loggingString().utf8().data());
+
     m_activeTransactions.set(info.identifier(), &transaction.get());
 
     return adoptRef(&transaction.leakRef());
@@ -241,7 +243,7 @@
 
 Ref<IDBTransaction> IDBDatabase::startVersionChangeTransaction(const IDBTransactionInfo& info, IDBOpenDBRequest& request)
 {
-    LOG(IndexedDB, "IDBDatabase::startVersionChangeTransaction");
+    LOG(IndexedDB, "IDBDatabase::startVersionChangeTransaction %s", info.identifier().loggingString().utf8().data());
 
     ASSERT(!m_versionChangeTransaction);
     ASSERT(info.mode() == IndexedDB::TransactionMode::VersionChange);
@@ -256,15 +258,19 @@
 
 void IDBDatabase::didStartTransaction(IDBTransaction& transaction)
 {
-    LOG(IndexedDB, "IDBDatabase::didStartTransaction");
+    LOG(IndexedDB, "IDBDatabase::didStartTransaction %s", transaction.info().identifier().loggingString().utf8().data());
     ASSERT(!m_versionChangeTransaction);
 
+    // It is possible for the client to have aborted a transaction before the server replies back that it has started.
+    if (m_abortingTransactions.contains(transaction.info().identifier()))
+        return;
+
     m_activeTransactions.set(transaction.info().identifier(), &transaction);
 }
 
 void IDBDatabase::willCommitTransaction(IDBTransaction& transaction)
 {
-    LOG(IndexedDB, "IDBDatabase::willCommitTransaction");
+    LOG(IndexedDB, "IDBDatabase::willCommitTransaction %s", transaction.info().identifier().loggingString().utf8().data());
 
     auto refTransaction = m_activeTransactions.take(transaction.info().identifier());
     ASSERT(refTransaction);
@@ -273,7 +279,7 @@
 
 void IDBDatabase::didCommitTransaction(IDBTransaction& transaction)
 {
-    LOG(IndexedDB, "IDBDatabase::didCommitTransaction");
+    LOG(IndexedDB, "IDBDatabase::didCommitTransaction %s", transaction.info().identifier().loggingString().utf8().data());
 
     if (m_versionChangeTransaction == &transaction)
         m_info.setVersion(transaction.info().newVersion());
@@ -283,7 +289,7 @@
 
 void IDBDatabase::willAbortTransaction(IDBTransaction& transaction)
 {
-    LOG(IndexedDB, "IDBDatabase::willAbortTransaction");
+    LOG(IndexedDB, "IDBDatabase::willAbortTransaction %s", transaction.info().identifier().loggingString().utf8().data());
 
     auto refTransaction = m_activeTransactions.take(transaction.info().identifier());
     ASSERT(refTransaction);
@@ -292,7 +298,7 @@
 
 void IDBDatabase::didAbortTransaction(IDBTransaction& transaction)
 {
-    LOG(IndexedDB, "IDBDatabase::didAbortTransaction");
+    LOG(IndexedDB, "IDBDatabase::didAbortTransaction %s", transaction.info().identifier().loggingString().utf8().data());
 
     if (transaction.isVersionChange()) {
         ASSERT(transaction.originalDatabaseInfo());
@@ -304,7 +310,7 @@
 
 void IDBDatabase::didCommitOrAbortTransaction(IDBTransaction& transaction)
 {
-    LOG(IndexedDB, "IDBDatabase::didCommitOrAbortTransaction");
+    LOG(IndexedDB, "IDBDatabase::didCommitOrAbortTransaction %s", transaction.info().identifier().loggingString().utf8().data());
 
     if (m_versionChangeTransaction == &transaction)
         m_versionChangeTransaction = nullptr;

Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp (192748 => 192749)


--- trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp	2015-11-23 19:48:50 UTC (rev 192749)
@@ -165,20 +165,6 @@
     return adoptRef(&objectStore.leakRef());
 }
 
-void IDBTransaction::immediateAbort()
-{
-    LOG(IndexedDB, "IDBTransaction::immediateAbort");
-
-    if (isFinishedOrFinishing())
-        return;
-
-    m_state = IndexedDB::TransactionState::Aborting;
-    m_database->willAbortTransaction(*this);
-
-    auto operation = createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServer);
-    abortOnServer(*operation);
-}
-
 void IDBTransaction::abort(ExceptionCode& ec)
 {
     LOG(IndexedDB, "IDBTransaction::abort");
@@ -191,14 +177,28 @@
     m_state = IndexedDB::TransactionState::Aborting;
     m_database->willAbortTransaction(*this);
 
-    auto operation = createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServer);
+    m_abortQueue.swap(m_transactionOperationQueue);
+
+    auto operation = createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServerAndCancelRequests);
     scheduleOperation(WTF::move(operation));
 }
 
-void IDBTransaction::abortOnServer(TransactionOperation&)
+void IDBTransaction::abortOnServerAndCancelRequests(TransactionOperation&)
 {
-    LOG(IndexedDB, "IDBTransaction::abortOnServer");
+    LOG(IndexedDB, "IDBTransaction::abortOnServerAndCancelRequests");
+
+    ASSERT(m_transactionOperationQueue.isEmpty());
+
     serverConnection().abortTransaction(*this);
+
+    IDBError error(IDBExceptionCode::AbortError);
+    for (auto& operation : m_abortQueue)
+        operation->completed(IDBResultData::error(operation->identifier(), error));
+
+    // Since we're aborting, this abortOnServerAndCancelRequests() operation should be the only
+    // in-progress operation, and it should be impossible to have queued any further operations.
+    ASSERT(m_transactionOperationMap.size() == 1);
+    ASSERT(m_transactionOperationQueue.isEmpty());
 }
 
 const char* IDBTransaction::activeDOMObjectName() const
@@ -426,7 +426,7 @@
 {
     LOG(IndexedDB, "IDBTransaction::didCreateObjectStoreOnServer");
 
-    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::CreateObjectStoreSuccess);
+    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::CreateObjectStoreSuccess || resultData.type() == IDBResultType::Error);
 }
 
 Ref<IDBIndex> IDBTransaction::createIndex(IDBObjectStore& objectStore, const IDBIndexInfo& info)
@@ -458,8 +458,15 @@
     if (resultData.type() == IDBResultType::CreateIndexSuccess)
         return;
 
-    // If index creation failed, the transaction is aborted.
-    immediateAbort();
+    ASSERT(resultData.type() == IDBResultType::Error);
+
+    // This operation might have failed because the transaction is already aborting.
+    if (m_state == IndexedDB::TransactionState::Aborting)
+        return;
+
+    // Otherwise, failure to create an index forced abortion of the transaction.
+    ExceptionCode ec;
+    abort(ec);
 }
 
 Ref<IDBRequest> IDBTransaction::requestOpenCursor(ScriptExecutionContext& context, IDBObjectStore& objectStore, const IDBCursorInfo& info)
@@ -585,6 +592,13 @@
 {
     LOG(IndexedDB, "IDBTransaction::didGetRecordOnServer");
 
+    if (resultData.type() == IDBResultType::Error) {
+        request.requestCompleted(resultData);
+        return;
+    }
+
+    ASSERT(resultData.type() == IDBResultType::GetRecordSuccess);
+
     const IDBGetResult& result = resultData.getResult();
 
     if (request.sourceIndexIdentifier() && request.requestedIndexRecordType() == IndexedDB::IndexRecordType::Key) {
@@ -760,7 +774,7 @@
 void IDBTransaction::didDeleteObjectStoreOnServer(const IDBResultData& resultData)
 {
     LOG(IndexedDB, "IDBTransaction::didDeleteObjectStoreOnServer");
-    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteObjectStoreSuccess);
+    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteObjectStoreSuccess || resultData.type() == IDBResultType::Error);
 }
 
 void IDBTransaction::deleteIndex(uint64_t objectStoreIdentifier, const String& indexName)
@@ -784,7 +798,7 @@
 void IDBTransaction::didDeleteIndexOnServer(const IDBResultData& resultData)
 {
     LOG(IndexedDB, "IDBTransaction::didDeleteIndexOnServer");
-    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteIndexSuccess);
+    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteIndexSuccess || resultData.type() == IDBResultType::Error);
 }
 
 void IDBTransaction::operationDidComplete(TransactionOperation& operation)

Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h (192748 => 192749)


--- trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h	2015-11-23 19:48:50 UTC (rev 192749)
@@ -142,7 +142,7 @@
     Ref<IDBRequest> requestIndexRecord(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, const IDBKeyRangeData&);
 
     void commitOnServer(TransactionOperation&);
-    void abortOnServer(TransactionOperation&);
+    void abortOnServerAndCancelRequests(TransactionOperation&);
 
     void createObjectStoreOnServer(TransactionOperation&, const IDBObjectStoreInfo&);
     void didCreateObjectStoreOnServer(const IDBResultData&);
@@ -182,8 +182,6 @@
 
     void scheduleOperationTimer();
 
-    void immediateAbort();
-
     Ref<IDBDatabase> m_database;
     IDBTransactionInfo m_info;
     std::unique_ptr<IDBDatabaseInfo> m_originalDatabaseInfo;
@@ -199,6 +197,7 @@
     RefPtr<IDBOpenDBRequest> m_openDBRequest;
 
     Deque<RefPtr<TransactionOperation>> m_transactionOperationQueue;
+    Deque<RefPtr<TransactionOperation>> m_abortQueue;
     HashMap<IDBResourceIdentifier, RefPtr<TransactionOperation>> m_transactionOperationMap;
 
     HashMap<String, RefPtr<IDBObjectStore>> m_referencedObjectStores;

Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp (192748 => 192749)


--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp	2015-11-23 19:48:50 UTC (rev 192749)
@@ -95,7 +95,7 @@
 
 IDBError MemoryIDBBackingStore::abortTransaction(const IDBResourceIdentifier& transactionIdentifier)
 {
-    LOG(IndexedDB, "MemoryIDBBackingStore::abortTransaction");
+    LOG(IndexedDB, "MemoryIDBBackingStore::abortTransaction - %s", transactionIdentifier.loggingString().utf8().data());
 
     auto transaction = m_transactions.take(transactionIdentifier);
     if (!transaction)
@@ -108,7 +108,7 @@
 
 IDBError MemoryIDBBackingStore::commitTransaction(const IDBResourceIdentifier& transactionIdentifier)
 {
-    LOG(IndexedDB, "MemoryIDBBackingStore::commitTransaction");
+    LOG(IndexedDB, "MemoryIDBBackingStore::commitTransaction - %s", transactionIdentifier.loggingString().utf8().data());
 
     auto transaction = m_transactions.take(transactionIdentifier);
     if (!transaction)

Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBError.cpp (192748 => 192749)


--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBError.cpp	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBError.cpp	2015-11-23 19:48:50 UTC (rev 192749)
@@ -67,6 +67,10 @@
         static NeverDestroyed<String> entry = ASCIILiteral("DataCloneError");
         return entry;
     }
+    case IDBExceptionCode::AbortError: {
+        static NeverDestroyed<String> entry = ASCIILiteral("AbortError");
+        return entry;
+    }
     case IDBExceptionCode::None:
         RELEASE_ASSERT_NOT_REACHED();
     }
@@ -109,6 +113,10 @@
         static NeverDestroyed<String> entry = ASCIILiteral("Data being stored could not be cloned by the structured cloning algorithm.");
         return entry;
     }
+    case IDBExceptionCode::AbortError: {
+        static NeverDestroyed<String> entry = ASCIILiteral("Transaction was aborted");
+        return entry;
+    }
     case IDBExceptionCode::None:
         RELEASE_ASSERT_NOT_REACHED();
     }

Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBError.h (192748 => 192749)


--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBError.h	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBError.h	2015-11-23 19:48:50 UTC (rev 192749)
@@ -44,6 +44,7 @@
     // Indexed DB existing exception codes with IDB-specific error messages:
     InvalidStateError,
     DataCloneError,
+    AbortError,
 };
 
 class IDBError {

Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.cpp (192748 => 192749)


--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.cpp	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.cpp	2015-11-23 19:48:50 UTC (rev 192749)
@@ -94,6 +94,12 @@
         && m_resourceNumber == std::numeric_limits<uint64_t>::max();
 }
 
+#ifndef NDEBUG
+String IDBResourceIdentifier::loggingString() const
+{
+    return String::format("<%" PRIu64", %" PRIu64">", m_idbConnectionIdentifier, m_resourceNumber);
+}
+#endif
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)

Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.h (192748 => 192749)


--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.h	2015-11-23 19:41:05 UTC (rev 192748)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.h	2015-11-23 19:48:50 UTC (rev 192749)
@@ -72,6 +72,10 @@
 
     IDBResourceIdentifier isolatedCopy() const;
 
+#ifndef NDEBUG
+    String loggingString() const;
+#endif
+
 private:
     IDBResourceIdentifier() = delete;
     IDBResourceIdentifier(uint64_t connectionIdentifier, uint64_t resourceIdentifier);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to