Modern IDB: Implement IDBIndex get/getKey/count requests.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Nov 2015 20:23:02 +0000 (20:23 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Nov 2015 20:23:02 +0000 (20:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=150910

Reviewed by Alex Christensen.

Source/WebCore:

Tests: storage/indexeddb/modern/index-get-count-basic.html
       storage/indexeddb/modern/index-get-count-failures.html

* Modules/indexeddb/IndexedDB.h:

* Modules/indexeddb/client/IDBAnyImpl.cpp:
(WebCore::IDBClient::IDBAny::IDBAny):
(WebCore::IDBClient::IDBAny::modernIDBIndex):
* Modules/indexeddb/client/IDBAnyImpl.h:
(WebCore::IDBClient::IDBAny::create):
(WebCore::IDBClient::IDBAny::createUndefined):

* Modules/indexeddb/client/IDBIndexImpl.cpp:
(WebCore::IDBClient::IDBIndex::count):
(WebCore::IDBClient::IDBIndex::doCount):
(WebCore::IDBClient::IDBIndex::get):
(WebCore::IDBClient::IDBIndex::doGet):
(WebCore::IDBClient::IDBIndex::getKey):
(WebCore::IDBClient::IDBIndex::doGetKey):
* Modules/indexeddb/client/IDBIndexImpl.h:
(WebCore::IDBClient::IDBIndex::info):

* Modules/indexeddb/client/IDBObjectStoreImpl.h:
(WebCore::IDBClient::IDBObjectStore::isDeleted):
(WebCore::IDBClient::IDBObjectStore::modernTransaction):

* Modules/indexeddb/client/IDBRequestImpl.cpp:
(WebCore::IDBClient::IDBRequest::createCount):
(WebCore::IDBClient::IDBRequest::createGet):
(WebCore::IDBClient::IDBRequest::IDBRequest):
(WebCore::IDBClient::IDBRequest::sourceObjectStoreIdentifier):
(WebCore::IDBClient::IDBRequest::sourceIndexIdentifier):
(WebCore::IDBClient::IDBRequest::requestedIndexRecordType):
(WebCore::IDBClient::IDBRequest::setResultToUndefined):
* Modules/indexeddb/client/IDBRequestImpl.h:

* Modules/indexeddb/client/IDBTransactionImpl.cpp:
(WebCore::IDBClient::IDBTransaction::requestGetValue):
(WebCore::IDBClient::IDBTransaction::requestGetKey):
(WebCore::IDBClient::IDBTransaction::didGetRecordOnServer):
(WebCore::IDBClient::IDBTransaction::requestCount):
* Modules/indexeddb/client/IDBTransactionImpl.h:

* Modules/indexeddb/client/TransactionOperation.cpp:
(WebCore::IDBClient::TransactionOperation::TransactionOperation):
* Modules/indexeddb/client/TransactionOperation.h:
(WebCore::IDBClient::TransactionOperation::indexIdentifier):
(WebCore::IDBClient::TransactionOperation::indexRecordType):

* Modules/indexeddb/server/IDBBackingStore.h:

* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::getRecord):
(WebCore::IDBServer::MemoryIDBBackingStore::getIndexRecord):
(WebCore::IDBServer::MemoryIDBBackingStore::getCount):
* Modules/indexeddb/server/MemoryIDBBackingStore.h:

* Modules/indexeddb/server/MemoryIndex.cpp:
(WebCore::IDBServer::MemoryIndex::valueForKeyRange):
(WebCore::IDBServer::MemoryIndex::countForKeyRange):
* Modules/indexeddb/server/MemoryIndex.h:

* Modules/indexeddb/server/MemoryObjectStore.cpp:
(WebCore::IDBServer::MemoryObjectStore::createIndex):
(WebCore::IDBServer::MemoryObjectStore::countForKeyRange):
(WebCore::IDBServer::MemoryObjectStore::indexValueForKeyRange):
* Modules/indexeddb/server/MemoryObjectStore.h:

* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::getRecord):
(WebCore::IDBServer::UniqueIDBDatabase::performGetIndexRecord):
(WebCore::IDBServer::UniqueIDBDatabase::getCount):
(WebCore::IDBServer::UniqueIDBDatabase::performGetCount):
(WebCore::IDBServer::UniqueIDBDatabase::performGetRecord): Deleted.
* Modules/indexeddb/server/UniqueIDBDatabase.h:

* Modules/indexeddb/shared/IDBRequestData.cpp:
(WebCore::IDBRequestData::IDBRequestData):
(WebCore::IDBRequestData::objectStoreIdentifier):
(WebCore::IDBRequestData::indexIdentifier):
(WebCore::IDBRequestData::indexRecordType):
* Modules/indexeddb/shared/IDBRequestData.h:

LayoutTests:

* storage/indexeddb/modern/index-get-count-basic-expected.txt: Added.
* storage/indexeddb/modern/index-get-count-basic.html: Added.
* storage/indexeddb/modern/index-get-count-failures-expected.txt: Added.
* storage/indexeddb/modern/index-get-count-failures.html: Added.

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

29 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/modern/index-get-count-basic-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/index-get-count-basic.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/index-get-count-failures-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/index-get-count-failures.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IndexedDB.h
Source/WebCore/Modules/indexeddb/client/IDBAnyImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBAnyImpl.h
Source/WebCore/Modules/indexeddb/client/IDBIndexImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBIndexImpl.h
Source/WebCore/Modules/indexeddb/client/IDBObjectStoreImpl.h
Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.h
Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h
Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp
Source/WebCore/Modules/indexeddb/client/TransactionOperation.h
Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp
Source/WebCore/Modules/indexeddb/server/MemoryIndex.h
Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp
Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
Source/WebCore/Modules/indexeddb/shared/IDBRequestData.cpp
Source/WebCore/Modules/indexeddb/shared/IDBRequestData.h

index e47b2cd..da58b70 100644 (file)
@@ -1,3 +1,15 @@
+2015-11-05  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: Implement IDBIndex get/getKey/count requests.
+        https://bugs.webkit.org/show_bug.cgi?id=150910
+
+        Reviewed by Alex Christensen.
+
+        * storage/indexeddb/modern/index-get-count-basic-expected.txt: Added.
+        * storage/indexeddb/modern/index-get-count-basic.html: Added.
+        * storage/indexeddb/modern/index-get-count-failures-expected.txt: Added.
+        * storage/indexeddb/modern/index-get-count-failures.html: Added.
+
 2015-11-05  Ryan Haddad  <ryanhaddad@apple.com>
 
         Rebaselining fast/text/tatechuyoko.html on win
diff --git a/LayoutTests/storage/indexeddb/modern/index-get-count-basic-expected.txt b/LayoutTests/storage/indexeddb/modern/index-get-count-basic-expected.txt
new file mode 100644 (file)
index 0000000..13e1f63
--- /dev/null
@@ -0,0 +1,9 @@
+ALERT: Initial upgrade needed: Old version - 0 New version - 1
+ALERT: get result is: undefined
+ALERT: getKey result is: undefined
+ALERT: count result is: 0
+ALERT: Initial upgrade versionchange transaction complete
+ALERT: Done
+This tests the most basic operation of the IDBIndex methods get(), getKey(), and count().
+It doesn't actually do anything other than exercise the requests themselves because we don't actually index yet.
+
diff --git a/LayoutTests/storage/indexeddb/modern/index-get-count-basic.html b/LayoutTests/storage/indexeddb/modern/index-get-count-basic.html
new file mode 100644 (file)
index 0000000..955bc9d
--- /dev/null
@@ -0,0 +1,66 @@
+This tests the most basic operation of the IDBIndex methods get(), getKey(), and count().<br>
+It doesn't actually do anything other than exercise the requests themselves because we don't actually index yet.<br>
+<div id="logger"></div>
+<script>
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert("Done");
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function gol(message)
+{
+    document.getElementById("logger").innerHTML += message + "<br>";
+}
+
+var createRequest = window.indexedDB.open("IndexGetCountBasicDatabase", 1);
+
+createRequest.onupgradeneeded = function(event) {
+    alert("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    var objectStore = database.createObjectStore("TestObjectStore");
+    var index = objectStore.createIndex("TestIndex", "foo");
+
+    objectStore.put("bar", "foo");
+    
+    var request1 = index.get("bar");
+    request1.onsuccess = function() {
+        alert("get result is: " + request1.result);
+    }
+
+    request2 = index.getKey("bar");
+    request2.onsuccess = function() {
+        alert("getKey result is: " + request2.result);
+    }
+    
+    var request3 = index.count();
+    request3.onsuccess = function() {
+        alert("count result is: " + request3.result);
+    }
+        
+    versionTransaction.onabort = function(event) {
+        alert("Initial upgrade versionchange transaction unexpected aborted");
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert("Initial upgrade versionchange transaction complete");
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert("Initial upgrade versionchange transaction unexpected error" + event);
+        done();
+    }
+}
+
+</script>
diff --git a/LayoutTests/storage/indexeddb/modern/index-get-count-failures-expected.txt b/LayoutTests/storage/indexeddb/modern/index-get-count-failures-expected.txt
new file mode 100644 (file)
index 0000000..bcf00a5
--- /dev/null
@@ -0,0 +1,15 @@
+This tests some obvious failures that can happen while calling the IDBIndex methods get(), getKey(), and count().
+Initial upgrade needed: Old version - 0 New version - 1
+Failed to get with a null key
+Failed to getKey with a null key
+Failed to count with a null range
+Failed to get with deleted IDBObjectStore
+Failed to getKey with deleted IDBObjectStore
+Failed to count with deleted IDBObjectStore
+Initial upgrade versionchange transaction complete
+Failed to get while transaction inactive
+Failed to getKey while transaction inactive
+Failed to count while transaction inactive
+readonly transaction complete
+Done
+
diff --git a/LayoutTests/storage/indexeddb/modern/index-get-count-failures.html b/LayoutTests/storage/indexeddb/modern/index-get-count-failures.html
new file mode 100644 (file)
index 0000000..e429e1a
--- /dev/null
@@ -0,0 +1,167 @@
+This tests some obvious failures that can happen while calling the IDBIndex methods get(), getKey(), and count().<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 createRequest = window.indexedDB.open("IndexGetCountFailuresDatabase", 1);
+var database;
+var index;
+
+createRequest.onupgradeneeded = function(event) {
+    log("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    database = event.target.result;
+    var objectStore = database.createObjectStore("TestObjectStore");
+    index = objectStore.createIndex("TestIndex", "foo");
+    
+    try {
+        index.get(null);
+    } catch(e) {
+        log("Failed to get with a null key");
+    }
+
+    try {
+        index.getKey(null);
+    } catch(e) {
+        log("Failed to getKey with a null key");
+    }
+
+    try {
+        index.count(null);
+    } catch(e) {
+        log("Failed to count with a null range");
+    }
+    
+    // FIXME: once IDBObjectStore.deleteIndex() is implemented, try these
+    // https://bugs.webkit.org/show_bug.cgi?id=150911
+    // objectStore.deleteIndex("TestIndex");
+    // 
+    // try {
+    //     index.get("test");
+    // } catch(e) {
+    //     log("Failed to get with deleted IDBIndex");
+    // }
+    // 
+    // try {
+    //     index.getKey("test");
+    // } catch(e) {
+    //     log("Failed to getKey with deleted IDBIndex");
+    // }
+    // 
+    // try {
+    //     index.count();
+    // } catch(e) {
+    //     log("Failed to count with deleted IDBIndex");
+    // }
+
+    database.deleteObjectStore("TestObjectStore");
+    try {
+        index.get(null);
+    } catch(e) {
+         log("Failed to get with deleted IDBObjectStore");
+    }
+
+    try {
+        index.getKey(null);
+    } catch(e) {
+         log("Failed to getKey with deleted IDBObjectStore");
+    }
+
+    try {
+        index.count(null);
+    } catch(e) {
+         log("Failed to count with deleted IDBObjectStore");
+    }
+
+    var objectStore = database.createObjectStore("TestObjectStore2");
+    objectStore.createIndex("TestIndex", "foo");
+        
+    versionTransaction.onabort = function(event) {
+        log("Initial upgrade versionchange transaction unexpected aborted");
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log("Initial upgrade versionchange transaction complete");
+        continueTest1();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log("Initial upgrade versionchange transaction unexpected error" + event);
+        done();
+    }
+}
+
+function continueTest1()
+{
+    var transaction = database.transaction("TestObjectStore2", "readonly");
+    var objectStore = transaction.objectStore("TestObjectStore2");
+    index = objectStore.index("TestIndex");
+
+    // Spin the transaction with get requests to keep it alive long enough for the setTimeout to fire.
+    var canFinish = false;
+    var spinGet = function() { 
+        objectStore.get("foo").onsuccess = function() {
+            if (!canFinish)
+                spinGet();
+        }
+    }
+    spinGet();
+
+    var testWhileInactive = function() {
+        try {
+            index.get(null);
+        } catch(e) {
+             log("Failed to get while transaction inactive");
+        }
+
+        try {
+            index.getKey(null);
+        } catch(e) {
+             log("Failed to getKey while transaction inactive");
+        }
+
+        try {
+            index.count(null);
+        } catch(e) {
+             log("Failed to count while transaction inactive");
+        }
+        canFinish = true;
+    }
+    
+    setTimeout(testWhileInactive, 0);
+    
+    transaction.onabort = function(event) {
+        log("readonly transaction unexpected abort" + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        log("readonly transaction complete");
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        log("readonly transaction unexpected error" + event);
+        done();
+    }
+}
+
+</script>
index 02c3291..dd45784 100644 (file)
@@ -1,3 +1,93 @@
+2015-11-05  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: Implement IDBIndex get/getKey/count requests.
+        https://bugs.webkit.org/show_bug.cgi?id=150910
+
+        Reviewed by Alex Christensen.
+
+        Tests: storage/indexeddb/modern/index-get-count-basic.html
+               storage/indexeddb/modern/index-get-count-failures.html
+
+        * Modules/indexeddb/IndexedDB.h:
+
+        * Modules/indexeddb/client/IDBAnyImpl.cpp:
+        (WebCore::IDBClient::IDBAny::IDBAny):
+        (WebCore::IDBClient::IDBAny::modernIDBIndex):
+        * Modules/indexeddb/client/IDBAnyImpl.h:
+        (WebCore::IDBClient::IDBAny::create):
+        (WebCore::IDBClient::IDBAny::createUndefined):
+
+        * Modules/indexeddb/client/IDBIndexImpl.cpp:
+        (WebCore::IDBClient::IDBIndex::count):
+        (WebCore::IDBClient::IDBIndex::doCount):
+        (WebCore::IDBClient::IDBIndex::get):
+        (WebCore::IDBClient::IDBIndex::doGet):
+        (WebCore::IDBClient::IDBIndex::getKey):
+        (WebCore::IDBClient::IDBIndex::doGetKey):
+        * Modules/indexeddb/client/IDBIndexImpl.h:
+        (WebCore::IDBClient::IDBIndex::info):
+        
+        * Modules/indexeddb/client/IDBObjectStoreImpl.h:
+        (WebCore::IDBClient::IDBObjectStore::isDeleted):
+        (WebCore::IDBClient::IDBObjectStore::modernTransaction):
+        
+        * Modules/indexeddb/client/IDBRequestImpl.cpp:
+        (WebCore::IDBClient::IDBRequest::createCount):
+        (WebCore::IDBClient::IDBRequest::createGet):
+        (WebCore::IDBClient::IDBRequest::IDBRequest):
+        (WebCore::IDBClient::IDBRequest::sourceObjectStoreIdentifier):
+        (WebCore::IDBClient::IDBRequest::sourceIndexIdentifier):
+        (WebCore::IDBClient::IDBRequest::requestedIndexRecordType):
+        (WebCore::IDBClient::IDBRequest::setResultToUndefined):
+        * Modules/indexeddb/client/IDBRequestImpl.h:
+        
+        * Modules/indexeddb/client/IDBTransactionImpl.cpp:
+        (WebCore::IDBClient::IDBTransaction::requestGetValue):
+        (WebCore::IDBClient::IDBTransaction::requestGetKey):
+        (WebCore::IDBClient::IDBTransaction::didGetRecordOnServer):
+        (WebCore::IDBClient::IDBTransaction::requestCount):
+        * Modules/indexeddb/client/IDBTransactionImpl.h:
+        
+        * Modules/indexeddb/client/TransactionOperation.cpp:
+        (WebCore::IDBClient::TransactionOperation::TransactionOperation):
+        * Modules/indexeddb/client/TransactionOperation.h:
+        (WebCore::IDBClient::TransactionOperation::indexIdentifier):
+        (WebCore::IDBClient::TransactionOperation::indexRecordType):
+        
+        * Modules/indexeddb/server/IDBBackingStore.h:
+        
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::getRecord):
+        (WebCore::IDBServer::MemoryIDBBackingStore::getIndexRecord):
+        (WebCore::IDBServer::MemoryIDBBackingStore::getCount):
+        * Modules/indexeddb/server/MemoryIDBBackingStore.h:
+        
+        * Modules/indexeddb/server/MemoryIndex.cpp:
+        (WebCore::IDBServer::MemoryIndex::valueForKeyRange):
+        (WebCore::IDBServer::MemoryIndex::countForKeyRange):
+        * Modules/indexeddb/server/MemoryIndex.h:
+        
+        * Modules/indexeddb/server/MemoryObjectStore.cpp:
+        (WebCore::IDBServer::MemoryObjectStore::createIndex):
+        (WebCore::IDBServer::MemoryObjectStore::countForKeyRange):
+        (WebCore::IDBServer::MemoryObjectStore::indexValueForKeyRange):
+        * Modules/indexeddb/server/MemoryObjectStore.h:
+        
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::getRecord):
+        (WebCore::IDBServer::UniqueIDBDatabase::performGetIndexRecord):
+        (WebCore::IDBServer::UniqueIDBDatabase::getCount):
+        (WebCore::IDBServer::UniqueIDBDatabase::performGetCount):
+        (WebCore::IDBServer::UniqueIDBDatabase::performGetRecord): Deleted.
+        * Modules/indexeddb/server/UniqueIDBDatabase.h:
+        
+        * Modules/indexeddb/shared/IDBRequestData.cpp:
+        (WebCore::IDBRequestData::IDBRequestData):
+        (WebCore::IDBRequestData::objectStoreIdentifier):
+        (WebCore::IDBRequestData::indexIdentifier):
+        (WebCore::IDBRequestData::indexRecordType):
+        * Modules/indexeddb/shared/IDBRequestData.h:
+
 2015-11-05  Zhuo Li  <zachli@apple.com>
 
         Rename the variable to avoid conflict between the variable and the parameter.
index 46a4a3d..5b8b00e 100644 (file)
@@ -77,6 +77,11 @@ enum class ObjectStoreOverwriteMode {
     NoOverwrite,
 };
 
+enum class IndexRecordType {
+    Key,
+    Value,
+};
+
 // In order of the least to the highest precedent in terms of sort order.
 enum KeyType {
     Max = -1,
index 0b54601..0c84453 100644 (file)
 namespace WebCore {
 namespace IDBClient {
 
+IDBAny::IDBAny(IDBAny::Type type)
+    : m_type(type)
+{
+}
+
 IDBAny::IDBAny(Ref<IDBDatabase>&& database)
     : m_type(IDBAny::Type::IDBDatabase)
     , m_database(adoptRef(&database.leakRef()))
@@ -44,7 +49,13 @@ IDBAny::IDBAny(Ref<IDBDatabase>&& database)
 
 IDBAny::IDBAny(Ref<IDBObjectStore>&& objectStore)
     : m_type(IDBAny::Type::IDBObjectStore)
-    , m_objectStore(adoptRef(&objectStore.leakRef()))
+    , m_objectStore(WTF::move(objectStore))
+{
+}
+
+IDBAny::IDBAny(Ref<IDBIndex>&& index)
+    : m_type(IDBAny::Type::IDBIndex)
+    , m_index(WTF::move(index))
 {
 }
 
@@ -106,6 +117,12 @@ IDBObjectStore* IDBAny::modernIDBObjectStore()
     return m_objectStore.get();
 }
 
+IDBIndex* IDBAny::modernIDBIndex()
+{
+    ASSERT(m_type == IDBAny::Type::IDBIndex);
+    return m_index.get();
+}
+
 RefPtr<WebCore::IDBTransaction> IDBAny::idbTransaction()
 {
     return nullptr;
index 9031d36..63a1f7a 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "IDBAny.h"
 #include "IDBDatabaseImpl.h"
+#include "IDBIndexImpl.h"
 #include "IDBObjectStoreImpl.h"
 
 namespace WebCore {
@@ -47,6 +48,11 @@ public:
         return adoptRef(new IDBAny(WTF::move(objectStore)));
     }
 
+    static RefPtr<IDBAny> create(Ref<IDBIndex>&& index)
+    {
+        return adoptRef(new IDBAny(WTF::move(index)));
+    }
+
     static RefPtr<IDBAny> create(const IDBKeyPath& keyPath)
     {
         return adoptRef(new IDBAny(keyPath));
@@ -57,6 +63,11 @@ public:
         return adoptRef(new IDBAny(value));
     }
 
+    static RefPtr<IDBAny> createUndefined()
+    {
+        return adoptRef(new IDBAny(IDBAny::Type::Undefined));
+    }
+
     virtual ~IDBAny();
 
     virtual Type type() const override final { return m_type; }
@@ -74,16 +85,20 @@ public:
     virtual const IDBKeyPath& keyPath() override final;
 
     IDBObjectStore* modernIDBObjectStore();
+    IDBIndex* modernIDBIndex();
 
 private:
+    explicit IDBAny(IDBAny::Type);
     explicit IDBAny(Ref<IDBDatabase>&&);
     explicit IDBAny(Ref<IDBObjectStore>&&);
+    explicit IDBAny(Ref<IDBIndex>&&);
     explicit IDBAny(const IDBKeyPath&);
     explicit IDBAny(const Deprecated::ScriptValue&);
 
     IDBAny::Type m_type { IDBAny::Type::Undefined };
     RefPtr<IDBDatabase> m_database;
     RefPtr<IDBObjectStore> m_objectStore;
+    RefPtr<IDBIndex> m_index;
 
     const IDBKeyPath m_idbKeyPath;
     const Deprecated::ScriptValue m_scriptValue;
index cecf933..f69b2a7 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "DOMRequestState.h"
 #include "IDBAnyImpl.h"
+#include "IDBBindingUtilities.h"
+#include "IDBKeyRangeData.h"
 #include "IDBObjectStoreImpl.h"
+#include "IDBTransactionImpl.h"
+#include "Logging.h"
 
 namespace WebCore {
 namespace IDBClient {
@@ -89,19 +94,69 @@ RefPtr<WebCore::IDBRequest> IDBIndex::openCursor(ScriptExecutionContext*, const
     RELEASE_ASSERT_NOT_REACHED();
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::count(ScriptExecutionContext*, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::count(ScriptExecutionContext* context, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::count");
+
+    if (!context) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    IDBKeyRangeData range;
+    range.isNull = false;
+    return doCount(*context, range, ec);}
+
+RefPtr<WebCore::IDBRequest> IDBIndex::count(ScriptExecutionContext* context, IDBKeyRange* range, ExceptionCode& ec)
+{
+    LOG(IndexedDB, "IDBIndex::count");
+
+    if (!context) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    return doCount(*context, IDBKeyRangeData(range), ec);
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::count(ScriptExecutionContext*, IDBKeyRange*, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::count(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::count");
+
+    if (!context) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    DOMRequestState requestState(context);
+    RefPtr<IDBKey> idbKey = scriptValueToIDBKey(&requestState, key);
+    if (!idbKey || idbKey->type() == KeyType::Invalid) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError);
+        return nullptr;
+    }
+
+    return doCount(*context, IDBKeyRangeData(idbKey.get()), ec);
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::count(ScriptExecutionContext*, const Deprecated::ScriptValue&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::doCount(ScriptExecutionContext& context, const IDBKeyRangeData& range, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    if (m_deleted || m_objectStore->isDeleted()) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    if (range.isNull) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError);
+        return nullptr;
+    }
+
+    auto& transaction = m_objectStore->modernTransaction();
+    if (!transaction.isActive()) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::TransactionInactiveError);
+        return nullptr;
+    }
+
+    return transaction.requestCount(context, *this, range);
 }
 
 RefPtr<WebCore::IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext*, IDBKeyRange*, const String&, ExceptionCode&)
@@ -114,24 +169,108 @@ RefPtr<WebCore::IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext*, con
     RELEASE_ASSERT_NOT_REACHED();
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::get(ScriptExecutionContext*, IDBKeyRange*, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::get(ScriptExecutionContext* context, IDBKeyRange* range, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::get");
+
+    if (!context) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    return doGet(*context, IDBKeyRangeData(range), ec);
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::get(ScriptExecutionContext*, const Deprecated::ScriptValue&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::get(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::get");
+
+    if (!context) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    DOMRequestState requestState(context);
+    RefPtr<IDBKey> idbKey = scriptValueToIDBKey(&requestState, key);
+    if (!idbKey || idbKey->type() == KeyType::Invalid) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError);
+        return nullptr;
+    }
+
+    return doGet(*context, IDBKeyRangeData(idbKey.get()), ec);
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::getKey(ScriptExecutionContext*, IDBKeyRange*, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::doGet(ScriptExecutionContext& context, const IDBKeyRangeData& range, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    if (m_deleted || m_objectStore->isDeleted()) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    if (range.isNull) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError);
+        return nullptr;
+    }
+
+    auto& transaction = m_objectStore->modernTransaction();
+    if (!transaction.isActive()) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::TransactionInactiveError);
+        return nullptr;
+    }
+
+    return transaction.requestGetValue(context, *this, range);
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::getKey(ScriptExecutionContext*, const Deprecated::ScriptValue&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::getKey(ScriptExecutionContext* context, IDBKeyRange* range, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::getKey");
+
+    if (!context) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    return doGetKey(*context, IDBKeyRangeData(range), ec);
+}
+
+RefPtr<WebCore::IDBRequest> IDBIndex::getKey(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
+{
+    LOG(IndexedDB, "IDBIndex::getKey");
+
+    if (!context) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    DOMRequestState requestState(context);
+    RefPtr<IDBKey> idbKey = scriptValueToIDBKey(&requestState, key);
+    if (!idbKey || idbKey->type() == KeyType::Invalid) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError);
+        return nullptr;
+    }
+
+    return doGetKey(*context, IDBKeyRangeData(idbKey.get()), ec);
+}
+
+RefPtr<WebCore::IDBRequest> IDBIndex::doGetKey(ScriptExecutionContext& context, const IDBKeyRangeData& range, ExceptionCode& ec)
+{
+    if (m_deleted || m_objectStore->isDeleted()) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    if (range.isNull) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError);
+        return nullptr;
+    }
+
+    auto& transaction = m_objectStore->modernTransaction();
+    if (!transaction.isActive()) {
+        ec = static_cast<ExceptionCode>(IDBExceptionCode::TransactionInactiveError);
+        return nullptr;
+    }
+
+    return transaction.requestGetKey(context, *this, range);
 }
 
 } // namespace IDBClient
index 0f61b80..50809c3 100644 (file)
@@ -33,6 +33,9 @@
 #include "IDBIndexInfo.h"
 
 namespace WebCore {
+
+struct IDBKeyRangeData;
+
 namespace IDBClient {
 
 class IDBObjectStore;
@@ -72,11 +75,19 @@ public:
     virtual RefPtr<WebCore::IDBRequest> getKey(ScriptExecutionContext*, IDBKeyRange*, ExceptionCode&) override final;
     virtual RefPtr<WebCore::IDBRequest> getKey(ScriptExecutionContext*, const Deprecated::ScriptValue& key, ExceptionCode&) override final;
 
+    const IDBIndexInfo& info() const { return m_info; }
+
 private:
     IDBIndex(const IDBIndexInfo&, IDBObjectStore&);
 
+    RefPtr<WebCore::IDBRequest> doCount(ScriptExecutionContext&, const IDBKeyRangeData&, ExceptionCode&);
+    RefPtr<WebCore::IDBRequest> doGet(ScriptExecutionContext&, const IDBKeyRangeData&, ExceptionCode&);
+    RefPtr<WebCore::IDBRequest> doGetKey(ScriptExecutionContext&, const IDBKeyRangeData&, ExceptionCode&);
+
     IDBIndexInfo m_info;
     Ref<IDBObjectStore> m_objectStore;
+
+    bool m_deleted { false };
 };
 
 } // namespace IDBClient
index d9ad7da..92e7daf 100644 (file)
@@ -79,9 +79,14 @@ public:
     virtual RefPtr<WebCore::IDBRequest> count(ScriptExecutionContext*, const Deprecated::ScriptValue& key, ExceptionCode&) override final;
 
     void markAsDeleted();
+    bool isDeleted() const { return m_deleted; }
 
     const IDBObjectStoreInfo& info() const { return m_info; }
 
+    // FIXME: After removing LegacyIDB and folding abstract/implementation classes together,
+    // this will no longer be necessary.
+    IDBTransaction& modernTransaction() { return m_transaction.get(); }
+
 private:
     IDBObjectStore(const IDBObjectStoreInfo&, IDBTransaction&);
 
index dbd2d7a..75b965d 100644 (file)
@@ -47,6 +47,16 @@ Ref<IDBRequest> IDBRequest::create(ScriptExecutionContext& context, IDBObjectSto
     return adoptRef(*new IDBRequest(context, objectStore, transaction));
 }
 
+Ref<IDBRequest> IDBRequest::createCount(ScriptExecutionContext& context, IDBIndex& index, IDBTransaction& transaction)
+{
+    return adoptRef(*new IDBRequest(context, index, transaction));
+}
+
+Ref<IDBRequest> IDBRequest::createGet(ScriptExecutionContext& context, IDBIndex& index, IndexedDB::IndexRecordType requestedRecordType, IDBTransaction& transaction)
+{
+    return adoptRef(*new IDBRequest(context, index, requestedRecordType, transaction));
+}
+
 IDBRequest::IDBRequest(IDBConnectionToServer& connection, ScriptExecutionContext* context)
     : IDBOpenDBRequest(context)
     , m_connection(connection)
@@ -60,11 +70,27 @@ IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBObjectStore& objectSt
     , m_transaction(&transaction)
     , m_connection(transaction.serverConnection())
     , m_resourceIdentifier(transaction.serverConnection())
-    , m_source(adoptRef(*IDBAny::create(objectStore).leakRef()))
+    , m_source(IDBAny::create(objectStore))
+{
+    suspendIfNeeded();
+}
+
+IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBIndex& index, IDBTransaction& transaction)
+    : IDBOpenDBRequest(&context)
+    , m_transaction(&transaction)
+    , m_connection(transaction.serverConnection())
+    , m_resourceIdentifier(transaction.serverConnection())
+    , m_source(IDBAny::create(index))
 {
     suspendIfNeeded();
 }
 
+IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBIndex& index, IndexedDB::IndexRecordType requestedRecordType, IDBTransaction& transaction)
+    : IDBRequest(context, index, transaction)
+{
+    m_requestedIndexRecordType = requestedRecordType;
+}
+
 IDBRequest::~IDBRequest()
 {
 }
@@ -104,12 +130,42 @@ uint64_t IDBRequest::sourceObjectStoreIdentifier() const
 {
     if (!m_source)
         return 0;
-    if (m_source->type() != IDBAny::Type::IDBObjectStore)
+
+    if (m_source->type() == IDBAny::Type::IDBObjectStore) {
+        auto* objectStore = m_source->modernIDBObjectStore();
+        if (!objectStore)
+            return 0;
+        return objectStore->info().identifier();
+    }
+
+    if (m_source->type() == IDBAny::Type::IDBIndex) {
+        auto* index = m_source->modernIDBIndex();
+        if (!index)
+            return 0;
+        return index->info().objectStoreIdentifier();
+    }
+
+    return 0;
+}
+
+uint64_t IDBRequest::sourceIndexIdentifier() const
+{
+    if (!m_source)
+        return 0;
+    if (m_source->type() != IDBAny::Type::IDBIndex)
         return 0;
-    if (!m_source->modernIDBObjectStore())
+    if (!m_source->modernIDBIndex())
         return 0;
 
-    return m_source->modernIDBObjectStore()->info().identifier();
+    return m_source->modernIDBIndex()->info().identifier();
+}
+
+IndexedDB::IndexRecordType IDBRequest::requestedIndexRecordType() const
+{
+    ASSERT(m_source);
+    ASSERT(m_source->type() == IDBAny::Type::IDBIndex);
+
+    return m_requestedIndexRecordType;
 }
 
 EventTargetInterface IDBRequest::eventTargetInterface() const
@@ -204,13 +260,7 @@ void IDBRequest::setResultToStructuredClone(const ThreadSafeDataBuffer& valueDat
 
 void IDBRequest::setResultToUndefined()
 {
-    auto context = scriptExecutionContext();
-    if (!context)
-        return;
-
-    DOMRequestState state(context);
-    if (auto* execState = state.exec())
-        m_result = IDBAny::create(Deprecated::ScriptValue(execState->vm(), JSC::jsUndefined()));
+    m_result = IDBAny::createUndefined();
 }
 
 void IDBRequest::requestCompleted(const IDBResultData& resultData)
index 14561ed..a42b17b 100644 (file)
@@ -41,6 +41,9 @@ class IDBKeyData;
 class IDBResultData;
 class ThreadSafeDataBuffer;
 
+namespace IndexedDB {
+enum class IndexRecordType;
+}
 
 namespace IDBClient {
 
@@ -49,6 +52,8 @@ class IDBConnectionToServer;
 class IDBRequest : public WebCore::IDBOpenDBRequest, public RefCounted<IDBRequest> {
 public:
     static Ref<IDBRequest> create(ScriptExecutionContext&, IDBObjectStore&, IDBTransaction&);
+    static Ref<IDBRequest> createCount(ScriptExecutionContext&, IDBIndex&, IDBTransaction&);
+    static Ref<IDBRequest> createGet(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, IDBTransaction&);
 
     const IDBResourceIdentifier& resourceIdentifier() const { return m_resourceIdentifier; }
 
@@ -62,6 +67,8 @@ public:
     virtual const String& readyState() const override;
 
     uint64_t sourceObjectStoreIdentifier() const;
+    uint64_t sourceIndexIdentifier() const;
+    IndexedDB::IndexRecordType requestedIndexRecordType() const;
 
     // EventTarget
     virtual EventTargetInterface eventTargetInterface() const override;
@@ -85,6 +92,8 @@ public:
 protected:
     IDBRequest(IDBConnectionToServer&, ScriptExecutionContext*);
     IDBRequest(ScriptExecutionContext&, IDBObjectStore&, IDBTransaction&);
+    IDBRequest(ScriptExecutionContext&, IDBIndex&, IDBTransaction&);
+    IDBRequest(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, IDBTransaction&);
 
     // ActiveDOMObject.
     virtual const char* activeDOMObjectName() const override final;
@@ -109,6 +118,7 @@ private:
     IDBResourceIdentifier m_resourceIdentifier;
     RefPtr<IDBAny> m_source;
     bool m_hasPendingActivity { true };
+    IndexedDB::IndexRecordType m_requestedIndexRecordType;
 };
 
 } // namespace IDBClient
index cfe04c3..fb801a2 100644 (file)
@@ -446,6 +446,33 @@ Ref<IDBRequest> IDBTransaction::requestGetRecord(ScriptExecutionContext& context
     return WTF::move(request);
 }
 
+Ref<IDBRequest> IDBTransaction::requestGetValue(ScriptExecutionContext& context, IDBIndex& index, const IDBKeyRangeData& range)
+{
+    LOG(IndexedDB, "IDBTransaction::requestGetValue");
+    return requestIndexRecord(context, index, IndexedDB::IndexRecordType::Value, range);
+}
+
+Ref<IDBRequest> IDBTransaction::requestGetKey(ScriptExecutionContext& context, IDBIndex& index, const IDBKeyRangeData& range)
+{
+    LOG(IndexedDB, "IDBTransaction::requestGetValue");
+    return requestIndexRecord(context, index, IndexedDB::IndexRecordType::Key, range);
+}
+
+Ref<IDBRequest> IDBTransaction::requestIndexRecord(ScriptExecutionContext& context, IDBIndex& index, IndexedDB::IndexRecordType type, const IDBKeyRangeData&range)
+{
+    LOG(IndexedDB, "IDBTransaction::requestGetValue");
+    ASSERT(isActive());
+    ASSERT(!range.isNull);
+
+    Ref<IDBRequest> request = IDBRequest::createGet(context, index, type, *this);
+    addRequest(request.get());
+
+    auto operation = createTransactionOperation(*this, request.get(), &IDBTransaction::didGetRecordOnServer, &IDBTransaction::getRecordOnServer, range);
+    scheduleOperation(WTF::move(operation));
+
+    return WTF::move(request);
+}
+
 void IDBTransaction::getRecordOnServer(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
 {
     LOG(IndexedDB, "IDBTransaction::getRecordOnServer");
@@ -457,13 +484,24 @@ void IDBTransaction::didGetRecordOnServer(IDBRequest& request, const IDBResultDa
 {
     LOG(IndexedDB, "IDBTransaction::didGetRecordOnServer");
 
-    request.setResultToStructuredClone(resultData.resultData());
+    if (request.sourceIndexIdentifier() && request.requestedIndexRecordType() == IndexedDB::IndexRecordType::Key) {
+        if (resultData.resultKey())
+            request.setResult(resultData.resultKey());
+        else
+            request.setResultToUndefined();
+    } else {
+        if (resultData.resultData().data())
+            request.setResultToStructuredClone(resultData.resultData());
+        else
+            request.setResultToUndefined();
+    }
+
     request.requestCompleted(resultData);
 }
 
 Ref<IDBRequest> IDBTransaction::requestCount(ScriptExecutionContext& context, IDBObjectStore& objectStore, const IDBKeyRangeData& range)
 {
-    LOG(IndexedDB, "IDBTransaction::requestCount");
+    LOG(IndexedDB, "IDBTransaction::requestCount (IDBObjectStore)");
     ASSERT(isActive());
     ASSERT(!range.isNull);
 
@@ -475,6 +513,20 @@ Ref<IDBRequest> IDBTransaction::requestCount(ScriptExecutionContext& context, ID
     return request;
 }
 
+Ref<IDBRequest> IDBTransaction::requestCount(ScriptExecutionContext& context, IDBIndex& index, const IDBKeyRangeData& range)
+{
+    LOG(IndexedDB, "IDBTransaction::requestCount (IDBIndex)");
+    ASSERT(isActive());
+    ASSERT(!range.isNull);
+
+    Ref<IDBRequest> request = IDBRequest::createCount(context, index, *this);
+    addRequest(request.get());
+
+    scheduleOperation(createTransactionOperation(*this, request.get(), &IDBTransaction::didGetCountOnServer, &IDBTransaction::getCountOnServer, range));
+
+    return request;
+}
+
 void IDBTransaction::getCountOnServer(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
 {
     LOG(IndexedDB, "IDBTransaction::getCountOnServer");
index 9ecaef8..b3d7b3c 100644 (file)
@@ -50,6 +50,7 @@ struct IDBKeyRangeData;
 namespace IDBClient {
 
 class IDBDatabase;
+class IDBIndex;
 class TransactionOperation;
 
 class IDBTransaction : public WebCore::IDBTransaction {
@@ -97,6 +98,9 @@ public:
     Ref<IDBRequest> requestDeleteRecord(ScriptExecutionContext&, IDBObjectStore&, const IDBKeyRangeData&);
     Ref<IDBRequest> requestClearObjectStore(ScriptExecutionContext&, IDBObjectStore&);
     Ref<IDBRequest> requestCount(ScriptExecutionContext&, IDBObjectStore&, const IDBKeyRangeData&);
+    Ref<IDBRequest> requestCount(ScriptExecutionContext&, IDBIndex&, const IDBKeyRangeData&);
+    Ref<IDBRequest> requestGetValue(ScriptExecutionContext&, IDBIndex&, const IDBKeyRangeData&);
+    Ref<IDBRequest> requestGetKey(ScriptExecutionContext&, IDBIndex&, const IDBKeyRangeData&);
 
     void deleteObjectStore(const String& objectStoreName);
 
@@ -126,6 +130,8 @@ private:
     void fireOnAbort();
     void enqueueEvent(Ref<Event>);
 
+    Ref<IDBRequest> requestIndexRecord(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, const IDBKeyRangeData&);
+
     void commitOnServer(TransactionOperation&);
     void abortOnServer(TransactionOperation&);
 
index 465649f..fe84cbc 100644 (file)
@@ -35,6 +35,9 @@ TransactionOperation::TransactionOperation(IDBTransaction& transaction, IDBReque
     : TransactionOperation(transaction)
 {
     m_objectStoreIdentifier = request.sourceObjectStoreIdentifier();
+    m_indexIdentifier = request.sourceIndexIdentifier();
+    if (m_indexIdentifier)
+        m_indexRecordType = request.requestedIndexRecordType();
 }
 
 } // namespace IDBClient
index ac606c9..10a6754 100644 (file)
@@ -36,6 +36,10 @@ namespace WebCore {
 
 class IDBResultData;
 
+namespace IndexedDB {
+enum class IndexRecordType;
+}
+
 namespace IDBClient {
 
 class TransactionOperation : public RefCounted<TransactionOperation> {
@@ -54,7 +58,9 @@ public:
     const IDBResourceIdentifier& identifier() const { return m_identifier; }
     IDBResourceIdentifier transactionIdentifier() const { return m_transaction->info().identifier(); }
     uint64_t objectStoreIdentifier() const { return m_objectStoreIdentifier; }
+    uint64_t indexIdentifier() const { return m_indexIdentifier; }
     IDBTransaction& transaction() { return m_transaction.get(); }
+    IndexedDB::IndexRecordType indexRecordType() const { return m_indexRecordType; }
 
 protected:
     TransactionOperation(IDBTransaction& transaction)
@@ -68,6 +74,8 @@ protected:
     Ref<IDBTransaction> m_transaction;
     IDBResourceIdentifier m_identifier;
     uint64_t m_objectStoreIdentifier { 0 };
+    uint64_t m_indexIdentifier { 0 };
+    IndexedDB::IndexRecordType m_indexRecordType;
     std::function<void ()> m_performFunction;
     std::function<void (const IDBResultData&)> m_completeFunction;
 };
index 389b1fa..7a8c24d 100644 (file)
@@ -42,6 +42,10 @@ class ThreadSafeDataBuffer;
 
 struct IDBKeyRangeData;
 
+namespace IndexedDB {
+enum class IndexRecordType;
+}
+
 namespace IDBServer {
 
 class IDBBackingStore {
@@ -62,7 +66,8 @@ public:
     virtual IDBError deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&) = 0;
     virtual IDBError putRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const ThreadSafeDataBuffer& value) = 0;
     virtual IDBError getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, ThreadSafeDataBuffer& outValue) = 0;
-    virtual IDBError getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, uint64_t& outCount) = 0;
+    virtual IDBError getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&, ThreadSafeDataBuffer& outValue) = 0;
+    virtual IDBError getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&, uint64_t& outCount) = 0;
     virtual IDBError generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber) = 0;
 
 };
index f2e0a77..0fedb89 100644 (file)
@@ -262,7 +262,7 @@ IDBError MemoryIDBBackingStore::putRecord(const IDBResourceIdentifier& transacti
     return IDBError();
 }
 
-IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData, ThreadSafeDataBuffer& outValue)
+IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, ThreadSafeDataBuffer& outValue)
 {
     LOG(IndexedDB, "MemoryIDBBackingStore::getRecord");
 
@@ -275,11 +275,28 @@ IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transacti
     if (!objectStore)
         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found"));
 
-    outValue = objectStore->valueForKeyRange(keyRangeData);
+    outValue = objectStore->valueForKeyRange(range);
     return IDBError();
 }
 
-IDBError MemoryIDBBackingStore::getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, uint64_t& outCount)
+IDBError MemoryIDBBackingStore::getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range, ThreadSafeDataBuffer& outValue)
+{
+    LOG(IndexedDB, "MemoryIDBBackingStore::getIndexRecord");
+
+    ASSERT(objectStoreIdentifier);
+
+    if (!m_transactions.contains(transactionIdentifier))
+        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to get record"));
+
+    MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
+    if (!objectStore)
+        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found"));
+
+    outValue = objectStore->indexValueForKeyRange(indexIdentifier, recordType, range);
+    return IDBError();
+}
+
+IDBError MemoryIDBBackingStore::getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& range, uint64_t& outCount)
 {
     LOG(IndexedDB, "MemoryIDBBackingStore::getCount");
 
@@ -292,7 +309,8 @@ IDBError MemoryIDBBackingStore::getCount(const IDBResourceIdentifier& transactio
     if (!objectStore)
         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found"));
 
-    outCount = objectStore->countForKeyRange(range);
+    outCount = objectStore->countForKeyRange(indexIdentifier, range);
+
     return IDBError();
 }
 
index 666f5d7..d8504fa 100644 (file)
@@ -60,7 +60,8 @@ public:
     virtual IDBError deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&) override final;
     virtual IDBError putRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const ThreadSafeDataBuffer& value) override final;
     virtual IDBError getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, ThreadSafeDataBuffer& outValue) override final;
-    virtual IDBError getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, uint64_t& outCount) override final;
+    virtual IDBError getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&, ThreadSafeDataBuffer& outValue) override final;
+    virtual IDBError getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&, uint64_t& outCount) override final;
     virtual IDBError generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber) override final;
 
     void removeObjectStoreForVersionChangeAbort(MemoryObjectStore&);
index 69aac7a..25fb265 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "ThreadSafeDataBuffer.h"
+
 namespace WebCore {
 namespace IDBServer {
 
@@ -45,6 +47,20 @@ MemoryIndex::~MemoryIndex()
 {
 }
 
+ThreadSafeDataBuffer MemoryIndex::valueForKeyRange(IndexedDB::IndexRecordType, const IDBKeyRangeData&) const
+{
+    // FIXME: Once indexes actually index, we'll return something real.
+    // https://bugs.webkit.org/show_bug.cgi?id=150939
+    return { };
+}
+
+uint64_t MemoryIndex::countForKeyRange(const IDBKeyRangeData&)
+{
+    // FIXME: Once indexes actually index, we'll return something real.
+    // https://bugs.webkit.org/show_bug.cgi?id=150939
+    return 0;
+}
+
 } // namespace IDBServer
 } // namespace WebCore
 
index da4b571..d9fddb1 100644 (file)
 #include "IDBIndexInfo.h"
 
 namespace WebCore {
+
+class ThreadSafeDataBuffer;
+
+struct IDBKeyRangeData;
+
+namespace IndexedDB {
+enum class IndexRecordType;
+}
+
 namespace IDBServer {
 
 class MemoryIndex {
@@ -42,6 +51,9 @@ public:
 
     const IDBIndexInfo& info() const { return m_info; }
 
+    ThreadSafeDataBuffer valueForKeyRange(IndexedDB::IndexRecordType, const IDBKeyRangeData&) const;
+    uint64_t countForKeyRange(const IDBKeyRangeData&);
+    
 private:
     MemoryIndex(const IDBIndexInfo&);
 
index fa23cb5..7419baf 100644 (file)
@@ -72,7 +72,7 @@ IDBError MemoryObjectStore::createIndex(MemoryBackingStoreTransaction& transacti
 {
     LOG(IndexedDB, "MemoryObjectStore::createIndex");
 
-    if (!m_writeTransaction || m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction)
+    if (!m_writeTransaction || !m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction)
         return IDBError(IDBExceptionCode::ConstraintError);
 
     ASSERT(!m_indexesByIdentifier.contains(info.identifier()));
@@ -175,10 +175,16 @@ void MemoryObjectStore::setKeyValue(const IDBKeyData& keyData, const ThreadSafeD
         m_orderedKeys->insert(keyData);
 }
 
-uint64_t MemoryObjectStore::countForKeyRange(const IDBKeyRangeData& inRange) const
+uint64_t MemoryObjectStore::countForKeyRange(uint64_t indexIdentifier, const IDBKeyRangeData& inRange) const
 {
     LOG(IndexedDB, "MemoryObjectStore::countForKeyRange");
 
+    if (indexIdentifier) {
+        auto* index = m_indexesByIdentifier.get(indexIdentifier);
+        ASSERT(index);
+        return index->countForKeyRange(inRange);
+    }
+
     if (!m_keyValueStore)
         return 0;
 
@@ -209,6 +215,15 @@ ThreadSafeDataBuffer MemoryObjectStore::valueForKeyRange(const IDBKeyRangeData&
     return m_keyValueStore->get(key);
 }
 
+ThreadSafeDataBuffer MemoryObjectStore::indexValueForKeyRange(uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range) const
+{
+    LOG(IndexedDB, "MemoryObjectStore::indexValueForKeyRange");
+
+    auto* index = m_indexesByIdentifier.get(indexIdentifier);
+    ASSERT(index);
+    return index->valueForKeyRange(recordType, range);
+}
+
 IDBKeyData MemoryObjectStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& keyRangeData) const
 {
     if (!m_keyValueStore)
index e641973..f9049c0 100644 (file)
@@ -42,6 +42,10 @@ class IDBKeyData;
 
 struct IDBKeyRangeData;
 
+namespace IndexedDB {
+enum class IndexRecordType;
+}
+
 namespace IDBServer {
 
 class MemoryBackingStoreTransaction;
@@ -74,7 +78,8 @@ public:
     void replaceKeyValueStore(std::unique_ptr<KeyValueMap>&&);
 
     ThreadSafeDataBuffer valueForKeyRange(const IDBKeyRangeData&) const;
-    uint64_t countForKeyRange(const IDBKeyRangeData&) const;
+    ThreadSafeDataBuffer indexValueForKeyRange(uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&) const;
+    uint64_t countForKeyRange(uint64_t indexIdentifier, const IDBKeyRangeData&) const;
 
     const IDBObjectStoreInfo& info() const { return m_info; }
 
index cd35772..becba28 100644 (file)
@@ -447,13 +447,17 @@ void UniqueIDBDatabase::didPerformPutOrAdd(uint64_t callbackIdentifier, const ID
     performKeyDataCallback(callbackIdentifier, error, resultKey);
 }
 
-void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ValueDataCallback callback)
+void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBKeyRangeData& range, ValueDataCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::getRecord");
 
     uint64_t callbackID = storeCallback(callback);
-    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyRangeData));
+
+    if (uint64_t indexIdentifier = requestData.indexIdentifier())
+        m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetIndexRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), indexIdentifier, requestData.indexRecordType(), range));
+    else
+        m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), range));
 }
 
 void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData)
@@ -462,7 +466,6 @@ void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBR
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetRecord");
 
     ASSERT(m_backingStore);
-    ASSERT(objectStoreIdentifier);
 
     ThreadSafeDataBuffer valueData;
     IDBError error = m_backingStore->getRecord(transactionIdentifier, objectStoreIdentifier, keyRangeData, valueData);
@@ -470,6 +473,19 @@ void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBR
     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, valueData));
 }
 
+void UniqueIDBDatabase::performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range)
+{
+    ASSERT(!isMainThread());
+    LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetIndexRecord");
+
+    ASSERT(m_backingStore);
+
+    ThreadSafeDataBuffer valueData;
+    IDBError error = m_backingStore->getIndexRecord(transactionIdentifier, objectStoreIdentifier, indexIdentifier, recordType, range, valueData);
+
+    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetRecord, callbackIdentifier, error, valueData));
+}
+
 void UniqueIDBDatabase::didPerformGetRecord(uint64_t callbackIdentifier, const IDBError& error, const ThreadSafeDataBuffer& resultData)
 {
     ASSERT(isMainThread());
@@ -484,10 +500,10 @@ void UniqueIDBDatabase::getCount(const IDBRequestData& requestData, const IDBKey
     LOG(IndexedDB, "(main) UniqueIDBDatabase::getCount");
 
     uint64_t callbackID = storeCallback(callback);
-    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetCount, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), range));
+    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetCount, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), requestData.indexIdentifier(), range));
 }
 
-void UniqueIDBDatabase::performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData)
+void UniqueIDBDatabase::performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& keyRangeData)
 {
     ASSERT(!isMainThread());
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetCount");
@@ -496,7 +512,7 @@ void UniqueIDBDatabase::performGetCount(uint64_t callbackIdentifier, const IDBRe
     ASSERT(objectStoreIdentifier);
 
     uint64_t count;
-    IDBError error = m_backingStore->getCount(transactionIdentifier, objectStoreIdentifier, keyRangeData, count);
+    IDBError error = m_backingStore->getCount(transactionIdentifier, objectStoreIdentifier, indexIdentifier, keyRangeData, count);
 
     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetCount, callbackIdentifier, error, count));
 }
index 4f556d1..4f7298d 100644 (file)
@@ -48,6 +48,10 @@ class IDBError;
 class IDBRequestData;
 class IDBTransactionInfo;
 
+namespace IndexedDB {
+enum class IndexRecordType;
+}
+
 namespace IDBServer {
 
 class IDBConnectionToClient;
@@ -109,7 +113,8 @@ private:
     void performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo&);
     void performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const ThreadSafeDataBuffer& valueData, IndexedDB::ObjectStoreOverwriteMode);
     void performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&);
-    void performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&);
+    void performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&);
+    void performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&);
     void performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&);
     void performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo&);
 
index 5a3d9e5..df164a2 100644 (file)
@@ -46,12 +46,17 @@ IDBRequestData::IDBRequestData(IDBClient::TransactionOperation& operation)
     , m_requestIdentifier(std::make_unique<IDBResourceIdentifier>(operation.identifier()))
     , m_transactionIdentifier(std::make_unique<IDBResourceIdentifier>(operation.transactionIdentifier()))
     , m_objectStoreIdentifier(operation.objectStoreIdentifier())
+    , m_indexIdentifier(operation.indexIdentifier())
 {
+    if (m_indexIdentifier)
+        m_indexRecordType = operation.indexRecordType();
 }
 
 IDBRequestData::IDBRequestData(const IDBRequestData& other)
     : m_serverConnectionIdentifier(other.m_serverConnectionIdentifier)
     , m_objectStoreIdentifier(other.m_objectStoreIdentifier)
+    , m_indexIdentifier(other.m_indexIdentifier)
+    , m_indexRecordType(other.m_indexRecordType)
     , m_databaseIdentifier(other.m_databaseIdentifier)
     , m_requestedVersion(other.m_requestedVersion)
 {
@@ -81,10 +86,22 @@ IDBResourceIdentifier IDBRequestData::transactionIdentifier() const
 
 uint64_t IDBRequestData::objectStoreIdentifier() const
 {
-    RELEASE_ASSERT(m_objectStoreIdentifier);
+    ASSERT(m_objectStoreIdentifier);
     return m_objectStoreIdentifier;
 }
 
+uint64_t IDBRequestData::indexIdentifier() const
+{
+    ASSERT(m_objectStoreIdentifier || m_indexIdentifier);
+    return m_indexIdentifier;
+}
+
+IndexedDB::IndexRecordType IDBRequestData::indexRecordType() const
+{
+    ASSERT(m_indexIdentifier);
+    return m_indexRecordType;
+}
+
 uint64_t IDBRequestData::requestedVersion() const
 {
     return m_requestedVersion;
index b8b4a28..21a2607 100644 (file)
 
 namespace WebCore {
 
+namespace IndexedDB {
+enum class IndexRecordType;
+}
+
 namespace IDBClient {
 class IDBConnectionToServer;
 class IDBOpenDBRequest;
@@ -50,6 +54,8 @@ public:
     IDBResourceIdentifier requestIdentifier() const;
     IDBResourceIdentifier transactionIdentifier() const;
     uint64_t objectStoreIdentifier() const;
+    uint64_t indexIdentifier() const;
+    IndexedDB::IndexRecordType indexRecordType() const;
 
     const IDBDatabaseIdentifier& databaseIdentifier() const { return m_databaseIdentifier; }
     uint64_t requestedVersion() const;
@@ -61,6 +67,8 @@ private:
     std::unique_ptr<IDBResourceIdentifier> m_requestIdentifier;
     std::unique_ptr<IDBResourceIdentifier> m_transactionIdentifier;
     uint64_t m_objectStoreIdentifier { 0 };
+    uint64_t m_indexIdentifier { 0 };
+    IndexedDB::IndexRecordType m_indexRecordType;
 
     IDBDatabaseIdentifier m_databaseIdentifier;
     uint64_t m_requestedVersion { 0 };