Modern IDB: Pipe through cursor functions from client to server.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Nov 2015 00:24:11 +0000 (00:24 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Nov 2015 00:24:11 +0000 (00:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=151197

Reviewed by Alex Christensen.

Source/WebCore:

Tests: storage/indexeddb/modern/cursor-1.html
       storage/indexeddb/modern/opencursor-failures.html

This patch implements most IDBCursor considerations at the IDL level, as well as pipes the
appropriate messages through from client to server.

All operations currently end in errors. Bug 151196 will fix that by making cursors functional.

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

* Modules/indexeddb/IDBCursor.h:
(WebCore::IDBCursor::isKeyCursor): Deleted.
* Modules/indexeddb/IDBCursorWithValue.h:

* Modules/indexeddb/IDBGetResult.h:

* Modules/indexeddb/IDBKeyData.h:
(WebCore::IDBKeyData::string):
(WebCore::IDBKeyData::date):
(WebCore::IDBKeyData::number):
(WebCore::IDBKeyData::array):

* Modules/indexeddb/IndexedDB.h:

* Modules/indexeddb/client/IDBAnyImpl.cpp:
(WebCore::IDBClient::IDBAny::IDBAny):
(WebCore::IDBClient::IDBAny::idbCursor):
(WebCore::IDBClient::IDBAny::idbCursorWithValue):
(WebCore::IDBClient::IDBAny::idbIndex):
(WebCore::IDBClient::IDBAny::idbObjectStore):
(WebCore::IDBClient::IDBAny::modernIDBCursor):
* Modules/indexeddb/client/IDBAnyImpl.h:
(WebCore::IDBClient::IDBAny::create):

* Modules/indexeddb/client/IDBConnectionToServer.cpp:
(WebCore::IDBClient::IDBConnectionToServer::openCursor):
(WebCore::IDBClient::IDBConnectionToServer::didOpenCursor):
(WebCore::IDBClient::IDBConnectionToServer::iterateCursor):
(WebCore::IDBClient::IDBConnectionToServer::didIterateCursor):
* Modules/indexeddb/client/IDBConnectionToServer.h:
* Modules/indexeddb/client/IDBConnectionToServerDelegate.h:

* Modules/indexeddb/client/IDBCursorImpl.cpp:
(WebCore::IDBClient::IDBCursor::create):
(WebCore::IDBClient::IDBCursor::IDBCursor):
(WebCore::IDBClient::IDBCursor::sourcesDeleted):
(WebCore::IDBClient::IDBCursor::effectiveObjectStore):
(WebCore::IDBClient::IDBCursor::transaction):
(WebCore::IDBClient::IDBCursor::direction):
(WebCore::IDBClient::IDBCursor::key):
(WebCore::IDBClient::IDBCursor::primaryKey):
(WebCore::IDBClient::IDBCursor::value):
(WebCore::IDBClient::IDBCursor::source):
(WebCore::IDBClient::IDBCursor::update):
(WebCore::IDBClient::IDBCursor::advance):
(WebCore::IDBClient::IDBCursor::continueFunction):
(WebCore::IDBClient::IDBCursor::uncheckedIteratorCursor):
(WebCore::IDBClient::IDBCursor::deleteFunction):
(WebCore::IDBClient::IDBCursor::setGetResult):
* Modules/indexeddb/client/IDBCursorImpl.h:
(WebCore::IDBClient::IDBCursor::info):
(WebCore::IDBClient::IDBCursor::setRequest):
(WebCore::IDBClient::IDBCursor::clearRequest):
(WebCore::IDBClient::IDBCursor::request):

* Modules/indexeddb/client/IDBCursorWithValueImpl.cpp:
(WebCore::IDBClient::IDBCursorWithValue::create):
(WebCore::IDBClient::IDBCursorWithValue::IDBCursorWithValue):
(WebCore::IDBClient::IDBCursorWithValue::~IDBCursorWithValue):
* Modules/indexeddb/client/IDBCursorWithValueImpl.h:

* Modules/indexeddb/client/IDBIndexImpl.cpp:
(WebCore::IDBClient::IDBIndex::openCursor):
(WebCore::IDBClient::IDBIndex::openKeyCursor):
* Modules/indexeddb/client/IDBIndexImpl.h:
(WebCore::IDBClient::IDBIndex::modernObjectStore):
(WebCore::IDBClient::IDBIndex::isDeleted):

* Modules/indexeddb/client/IDBObjectStoreImpl.cpp:
(WebCore::IDBClient::IDBObjectStore::openCursor):
(WebCore::IDBClient::IDBObjectStore::deleteFunction):
* Modules/indexeddb/client/IDBObjectStoreImpl.h:

* Modules/indexeddb/client/IDBRequestImpl.cpp:
(WebCore::IDBClient::IDBRequest::create):
(WebCore::IDBClient::IDBRequest::IDBRequest):
(WebCore::IDBClient::IDBRequest::~IDBRequest):
(WebCore::IDBClient::IDBRequest::source):
(WebCore::IDBClient::IDBRequest::resultCursor):
(WebCore::IDBClient::IDBRequest::willIterateCursor):
(WebCore::IDBClient::IDBRequest::didOpenOrIterateCursor):
(WebCore::IDBClient::IDBRequest::requestCompleted):
* Modules/indexeddb/client/IDBRequestImpl.h:
(WebCore::IDBClient::IDBRequest::modernResult):

* Modules/indexeddb/client/IDBTransactionImpl.cpp:
(WebCore::IDBClient::IDBTransaction::requestOpenCursor):
(WebCore::IDBClient::IDBTransaction::doRequestOpenCursor):
(WebCore::IDBClient::IDBTransaction::openCursorOnServer):
(WebCore::IDBClient::IDBTransaction::didOpenCursorOnServer):
(WebCore::IDBClient::IDBTransaction::iterateCursor):
(WebCore::IDBClient::IDBTransaction::iterateCursorOnServer):
(WebCore::IDBClient::IDBTransaction::didIterateCursorOnServer):
* Modules/indexeddb/client/IDBTransactionImpl.h:

* Modules/indexeddb/client/TransactionOperation.h:
(WebCore::IDBClient::createTransactionOperation):

* Modules/indexeddb/legacy/LegacyCursor.cpp:
(WebCore::LegacyCursor::source):
* Modules/indexeddb/legacy/LegacyCursor.h:
(WebCore::LegacyCursor::continueFunction): Deleted.
(WebCore::LegacyCursor::isKeyCursor): Deleted.
* Modules/indexeddb/legacy/LegacyCursorWithValue.h:

* Modules/indexeddb/server/IDBBackingStore.h:

* Modules/indexeddb/server/IDBConnectionToClient.cpp:
(WebCore::IDBServer::IDBConnectionToClient::didOpenCursor):
(WebCore::IDBServer::IDBConnectionToClient::didIterateCursor):
* Modules/indexeddb/server/IDBConnectionToClient.h:
* Modules/indexeddb/server/IDBConnectionToClientDelegate.h:

* Modules/indexeddb/server/IDBServer.cpp:
(WebCore::IDBServer::IDBServer::openCursor):
(WebCore::IDBServer::IDBServer::iterateCursor):
* Modules/indexeddb/server/IDBServer.h:

* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::openCursor):
(WebCore::IDBServer::MemoryIDBBackingStore::iterateCursor):
* Modules/indexeddb/server/MemoryIDBBackingStore.h:

* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::openCursor):
(WebCore::IDBServer::UniqueIDBDatabase::performOpenCursor):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformOpenCursor):
(WebCore::IDBServer::UniqueIDBDatabase::iterateCursor):
(WebCore::IDBServer::UniqueIDBDatabase::performIterateCursor):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformIterateCursor):
* Modules/indexeddb/server/UniqueIDBDatabase.h:

* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::deleteRecord):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::openCursor):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::iterateCursor):
* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h:

* Modules/indexeddb/shared/IDBCursorInfo.cpp: Added.
(WebCore::IDBCursorInfo::objectStoreCursor):
(WebCore::IDBCursorInfo::indexCursor):
(WebCore::IDBCursorInfo::IDBCursorInfo):
(WebCore::IDBCursorInfo::isDirectionForward):
(WebCore::IDBCursorInfo::isolatedCopy):
* Modules/indexeddb/shared/IDBCursorInfo.h: Added.
(WebCore::IDBCursorInfo::identifier):
(WebCore::IDBCursorInfo::sourceIdentifier):
(WebCore::IDBCursorInfo::cursorSource):
(WebCore::IDBCursorInfo::cursorDirection):
(WebCore::IDBCursorInfo::cursorType):

* Modules/indexeddb/shared/IDBResultData.cpp:
(WebCore::IDBResultData::openCursorSuccess):
(WebCore::IDBResultData::iterateCursorSuccess):
* Modules/indexeddb/shared/IDBResultData.h:

* Modules/indexeddb/shared/InProcessIDBServer.cpp:
(WebCore::InProcessIDBServer::didOpenCursor):
(WebCore::InProcessIDBServer::didIterateCursor):
(WebCore::InProcessIDBServer::openCursor):
(WebCore::InProcessIDBServer::iterateCursor):
* Modules/indexeddb/shared/InProcessIDBServer.h:

* bindings/js/IDBBindingUtilities.cpp:
(WebCore::idbKeyDataToJSValue):
* bindings/js/IDBBindingUtilities.h:

* platform/CrossThreadCopier.cpp:
(WebCore::IDBCursorInfo>::copy):
* platform/CrossThreadCopier.h:

LayoutTests:

* storage/indexeddb/modern/cursor-1-expected.txt: Added.
* storage/indexeddb/modern/cursor-1.html: Added.
* storage/indexeddb/modern/opencursor-failures-expected.txt: Added.
* storage/indexeddb/modern/opencursor-failures.html: Added.

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

56 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/modern/cursor-1-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/cursor-1.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/opencursor-failures-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/opencursor-failures.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBCursor.h
Source/WebCore/Modules/indexeddb/IDBCursorWithValue.h
Source/WebCore/Modules/indexeddb/IDBGetResult.h
Source/WebCore/Modules/indexeddb/IDBKeyData.h
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/IDBConnectionToServer.cpp
Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.h
Source/WebCore/Modules/indexeddb/client/IDBConnectionToServerDelegate.h
Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.h
Source/WebCore/Modules/indexeddb/client/IDBCursorWithValueImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBCursorWithValueImpl.h
Source/WebCore/Modules/indexeddb/client/IDBIndexImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBIndexImpl.h
Source/WebCore/Modules/indexeddb/client/IDBObjectStoreImpl.cpp
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.h
Source/WebCore/Modules/indexeddb/legacy/LegacyCursor.cpp
Source/WebCore/Modules/indexeddb/legacy/LegacyCursor.h
Source/WebCore/Modules/indexeddb/legacy/LegacyCursorWithValue.h
Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClientDelegate.h
Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
Source/WebCore/Modules/indexeddb/server/IDBServer.h
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h
Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.cpp [new file with mode: 0644]
Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.h [new file with mode: 0644]
Source/WebCore/Modules/indexeddb/shared/IDBResultData.cpp
Source/WebCore/Modules/indexeddb/shared/IDBResultData.h
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/IDBBindingUtilities.cpp
Source/WebCore/bindings/js/IDBBindingUtilities.h
Source/WebCore/platform/CrossThreadCopier.cpp
Source/WebCore/platform/CrossThreadCopier.h

index 62ad757..3e3fc0d 100644 (file)
@@ -1,3 +1,15 @@
+2015-11-12  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: Pipe through cursor functions from client to server.
+        https://bugs.webkit.org/show_bug.cgi?id=151197
+
+        Reviewed by Alex Christensen.
+
+        * storage/indexeddb/modern/cursor-1-expected.txt: Added.
+        * storage/indexeddb/modern/cursor-1.html: Added.
+        * storage/indexeddb/modern/opencursor-failures-expected.txt: Added.
+        * storage/indexeddb/modern/opencursor-failures.html: Added.
+
 2015-11-12  Mark Lam  <mark.lam@apple.com>
 
         Layout Test js/regress/ftl-object-sub.html is flaky.
diff --git a/LayoutTests/storage/indexeddb/modern/cursor-1-expected.txt b/LayoutTests/storage/indexeddb/modern/cursor-1-expected.txt
new file mode 100644 (file)
index 0000000..ed2eafb
--- /dev/null
@@ -0,0 +1,77 @@
+This tests basic IDBCursor functionality
+Initial upgrade needed: Old version - 0 New version - 1
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBIndex] (TestIndex1)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursor]
+Cursor direction is: next
+Cursor source is: [object IDBIndex] (TestIndex1)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: nextunique
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: nextunique
+Cursor source is: [object IDBIndex] (TestIndex1)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursor]
+Cursor direction is: nextunique
+Cursor source is: [object IDBIndex] (TestIndex1)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBIndex] (TestIndex1)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursor]
+Cursor direction is: prev
+Cursor source is: [object IDBIndex] (TestIndex1)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prevunique
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prevunique
+Cursor source is: [object IDBIndex] (TestIndex1)
+Cursor key is: null
+Cursor primary key is: null
+Error opening cursor (expected for now)
+Cursor is: [object IDBCursor]
+Cursor direction is: prevunique
+Cursor source is: [object IDBIndex] (TestIndex1)
+Cursor key is: null
+Cursor primary key is: null
+Initial upgrade versionchange transaction complete
+Done
+
diff --git a/LayoutTests/storage/indexeddb/modern/cursor-1.html b/LayoutTests/storage/indexeddb/modern/cursor-1.html
new file mode 100644 (file)
index 0000000..58d463b
--- /dev/null
@@ -0,0 +1,95 @@
+This tests basic IDBCursor functionality<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("Cursor1Database", 1);
+
+function logCursor(cursor)
+{
+    log("Cursor is: " + cursor);
+    log("Cursor direction is: " + cursor.direction);
+    log("Cursor source is: " + cursor.source + " (" + cursor.source.name + ")");    
+    log("Cursor key is: " + cursor.key);    
+    log("Cursor primary key is: " + cursor.primaryKey);    
+}
+
+function setupRequest(request)
+{
+    // FIXME: Right now (until https://bugs.webkit.org/show_bug.cgi?id=151196 is resolved) what should be successful cursor operations will actually always fail.
+    request.onsuccess = function() {
+        log("Success opening cursor");
+        logCursor(request.result);  
+    }
+    request.onerror = function(e) {
+        log("Error opening cursor (expected for now)");
+        logCursor(request.result);
+        e.stopPropagation();
+    } 
+}
+
+var objectStore;
+var index;
+
+function testCursorDirection(direction)
+{
+    var range = IDBKeyRange.lowerBound(-Infinity);
+    var request = objectStore.openCursor(range, direction);
+    setupRequest(request);
+    request = index.openCursor(range, direction);
+    setupRequest(request);
+    request = index.openKeyCursor(range, direction);
+    setupRequest(request);
+}
+
+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");
+    index = objectStore.createIndex("TestIndex1", "bar");
+
+    for (var i = 0; i < 10; ++i) {
+        objectStore.put("Record " + i, i);
+    }
+    objectStore.put({ bar: "Hello" }, "foo");
+
+    testCursorDirection("next");
+    testCursorDirection("nextunique");
+    testCursorDirection("prev");
+    testCursorDirection("prevunique");
+      
+    versionTransaction.onabort = function(event) {
+        log("Initial upgrade versionchange transaction unexpected aborted");
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log("Initial upgrade versionchange transaction complete");
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log("Initial upgrade versionchange transaction unexpected error" + event);
+        done();
+    }
+}
+
+</script>
diff --git a/LayoutTests/storage/indexeddb/modern/opencursor-failures-expected.txt b/LayoutTests/storage/indexeddb/modern/opencursor-failures-expected.txt
new file mode 100644 (file)
index 0000000..1f2fe6a
--- /dev/null
@@ -0,0 +1,21 @@
+This tests some obvious failures that can happen while opening cursors.
+Initial upgrade needed: Old version - 0 New version - 1
+Failed to open object store cursor with invalid keypath
+Failed to open object store cursor with invalid direction
+Failed to open index cursor with invalid keypath
+Failed to open index cursor with invalid direction
+Failed to open index key cursor with invalid keypath
+Failed to open index key cursor with invalid direction
+Failed to open object store cursor on deleted object store
+Failed to open index cursor on deleted object store
+Failed to open index key cursor on deleted object store
+Initial upgrade versionchange transaction complete
+Failed to open object store cursor from completed transaction
+Failed to open index cursor from completed transaction
+Failed to open index key cursor from completed transaction
+Failed to open object store cursor from inactive transaction
+Failed to open index cursor from inactive transaction
+Failed to open index key cursor from inactive transaction
+readonly transaction complete
+Done
+
diff --git a/LayoutTests/storage/indexeddb/modern/opencursor-failures.html b/LayoutTests/storage/indexeddb/modern/opencursor-failures.html
new file mode 100644 (file)
index 0000000..46cbd39
--- /dev/null
@@ -0,0 +1,188 @@
+This tests some obvious failures that can happen while opening cursors.<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("OpenCursorFailuresDatabase", 1);
+var database;
+var objectStore;
+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;
+    objectStore = database.createObjectStore("TestObjectStore");
+    index = objectStore.createIndex("TestIndex", "bar");
+    var request = objectStore.put({ bar: "bar" }, "foo");
+
+    request.onsuccess = function() {
+        try {
+            objectStore.openCursor(NaN);
+        } catch(e) {
+            log("Failed to open object store cursor with invalid keypath");
+        }
+        
+        try {
+            objectStore.openCursor("foo", "invalid direction");
+        } catch(e) {
+            log("Failed to open object store cursor with invalid direction");
+        }
+        
+        try {
+            index.openCursor(NaN);
+        } catch(e) {
+            log("Failed to open index cursor with invalid keypath");
+        }
+
+        try {
+            index.openCursor("foo", "invalid direction");
+        } catch(e) {
+            log("Failed to open index cursor with invalid direction");
+        }
+
+        try {
+            index.openKeyCursor(NaN);
+        } catch(e) {
+            log("Failed to open index key cursor with invalid keypath");
+        }
+
+        try {
+            index.openKeyCursor("foo", "invalid direction");
+        } catch(e) {
+            log("Failed to open index key cursor with invalid direction");
+        }
+        
+        database.deleteObjectStore("TestObjectStore");
+        
+        try {
+            objectStore.openCursor();
+        } catch(e) {
+            log("Failed to open object store cursor on deleted object store");
+        }
+        
+        try {
+            index.openCursor();
+        } catch(e) {
+            log("Failed to open index cursor on deleted object store");
+        }
+
+        try {
+            index.openKeyCursor();
+        } catch(e) {
+            log("Failed to open index key cursor on deleted object store");
+        }
+        
+        // Recreate the objectstore because we'll need it in phase 2.
+        objectStore = database.createObjectStore("TestObjectStore");
+        index = objectStore.createIndex("TestIndex", "bar");
+        objectStore.put({ bar: "bar" }, "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()
+{
+    try {
+        objectStore.openCursor();
+    } catch(e) {
+        log("Failed to open object store cursor from completed transaction");
+    }
+    
+    try {
+        index.openCursor();
+    } catch(e) {
+        log("Failed to open index cursor from completed transaction");
+    }
+
+    try {
+        index.openKeyCursor();
+    } catch(e) {
+        log("Failed to open index key cursor from completed transaction");
+    }
+        
+    var transaction = database.transaction("TestObjectStore", "readonly");
+    objectStore = transaction.objectStore("TestObjectStore");
+    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 getWhileInactive = function() {
+        try {
+            objectStore.openCursor();
+        } catch(e) {
+            log("Failed to open object store cursor from inactive transaction");
+        }
+    
+        try {
+            index.openCursor();
+        } catch(e) {
+            log("Failed to open index cursor from inactive transaction");
+        }
+
+        try {
+            index.openKeyCursor();
+        } catch(e) {
+            log("Failed to open index key cursor from inactive transaction");
+        }
+        canFinish = true;
+    }
+    
+    setTimeout(getWhileInactive, 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 d17ae7f..c9feda7 100644 (file)
@@ -912,6 +912,7 @@ set(WebCore_SOURCES
     Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp
     Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
 
+    Modules/indexeddb/shared/IDBCursorInfo.cpp
     Modules/indexeddb/shared/IDBDatabaseInfo.cpp
     Modules/indexeddb/shared/IDBError.cpp
     Modules/indexeddb/shared/IDBIndexInfo.cpp
index 78da40c..d5e93a7 100644 (file)
@@ -1,3 +1,192 @@
+2015-11-12  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: Pipe through cursor functions from client to server.
+        https://bugs.webkit.org/show_bug.cgi?id=151197
+
+        Reviewed by Alex Christensen.
+
+        Tests: storage/indexeddb/modern/cursor-1.html
+               storage/indexeddb/modern/opencursor-failures.html
+
+        This patch implements most IDBCursor considerations at the IDL level, as well as pipes the
+        appropriate messages through from client to server.
+        
+        All operations currently end in errors. Bug 151196 will fix that by making cursors functional.
+        
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * Modules/indexeddb/IDBCursor.h:
+        (WebCore::IDBCursor::isKeyCursor): Deleted.
+        * Modules/indexeddb/IDBCursorWithValue.h:
+
+        * Modules/indexeddb/IDBGetResult.h:
+
+        * Modules/indexeddb/IDBKeyData.h:
+        (WebCore::IDBKeyData::string):
+        (WebCore::IDBKeyData::date):
+        (WebCore::IDBKeyData::number):
+        (WebCore::IDBKeyData::array):
+
+        * Modules/indexeddb/IndexedDB.h:
+
+        * Modules/indexeddb/client/IDBAnyImpl.cpp:
+        (WebCore::IDBClient::IDBAny::IDBAny):
+        (WebCore::IDBClient::IDBAny::idbCursor):
+        (WebCore::IDBClient::IDBAny::idbCursorWithValue):
+        (WebCore::IDBClient::IDBAny::idbIndex):
+        (WebCore::IDBClient::IDBAny::idbObjectStore):
+        (WebCore::IDBClient::IDBAny::modernIDBCursor):
+        * Modules/indexeddb/client/IDBAnyImpl.h:
+        (WebCore::IDBClient::IDBAny::create):
+
+        * Modules/indexeddb/client/IDBConnectionToServer.cpp:
+        (WebCore::IDBClient::IDBConnectionToServer::openCursor):
+        (WebCore::IDBClient::IDBConnectionToServer::didOpenCursor):
+        (WebCore::IDBClient::IDBConnectionToServer::iterateCursor):
+        (WebCore::IDBClient::IDBConnectionToServer::didIterateCursor):
+        * Modules/indexeddb/client/IDBConnectionToServer.h:
+        * Modules/indexeddb/client/IDBConnectionToServerDelegate.h:
+
+        * Modules/indexeddb/client/IDBCursorImpl.cpp:
+        (WebCore::IDBClient::IDBCursor::create):
+        (WebCore::IDBClient::IDBCursor::IDBCursor):
+        (WebCore::IDBClient::IDBCursor::sourcesDeleted):
+        (WebCore::IDBClient::IDBCursor::effectiveObjectStore):
+        (WebCore::IDBClient::IDBCursor::transaction):
+        (WebCore::IDBClient::IDBCursor::direction):
+        (WebCore::IDBClient::IDBCursor::key):
+        (WebCore::IDBClient::IDBCursor::primaryKey):
+        (WebCore::IDBClient::IDBCursor::value):
+        (WebCore::IDBClient::IDBCursor::source):
+        (WebCore::IDBClient::IDBCursor::update):
+        (WebCore::IDBClient::IDBCursor::advance):
+        (WebCore::IDBClient::IDBCursor::continueFunction):
+        (WebCore::IDBClient::IDBCursor::uncheckedIteratorCursor):
+        (WebCore::IDBClient::IDBCursor::deleteFunction):
+        (WebCore::IDBClient::IDBCursor::setGetResult):
+        * Modules/indexeddb/client/IDBCursorImpl.h:
+        (WebCore::IDBClient::IDBCursor::info):
+        (WebCore::IDBClient::IDBCursor::setRequest):
+        (WebCore::IDBClient::IDBCursor::clearRequest):
+        (WebCore::IDBClient::IDBCursor::request):
+
+        * Modules/indexeddb/client/IDBCursorWithValueImpl.cpp:
+        (WebCore::IDBClient::IDBCursorWithValue::create):
+        (WebCore::IDBClient::IDBCursorWithValue::IDBCursorWithValue):
+        (WebCore::IDBClient::IDBCursorWithValue::~IDBCursorWithValue):
+        * Modules/indexeddb/client/IDBCursorWithValueImpl.h:
+
+        * Modules/indexeddb/client/IDBIndexImpl.cpp:
+        (WebCore::IDBClient::IDBIndex::openCursor):
+        (WebCore::IDBClient::IDBIndex::openKeyCursor):
+        * Modules/indexeddb/client/IDBIndexImpl.h:
+        (WebCore::IDBClient::IDBIndex::modernObjectStore):
+        (WebCore::IDBClient::IDBIndex::isDeleted):
+
+        * Modules/indexeddb/client/IDBObjectStoreImpl.cpp:
+        (WebCore::IDBClient::IDBObjectStore::openCursor):
+        (WebCore::IDBClient::IDBObjectStore::deleteFunction):
+        * Modules/indexeddb/client/IDBObjectStoreImpl.h:
+
+        * Modules/indexeddb/client/IDBRequestImpl.cpp:
+        (WebCore::IDBClient::IDBRequest::create):
+        (WebCore::IDBClient::IDBRequest::IDBRequest):
+        (WebCore::IDBClient::IDBRequest::~IDBRequest):
+        (WebCore::IDBClient::IDBRequest::source):
+        (WebCore::IDBClient::IDBRequest::resultCursor):
+        (WebCore::IDBClient::IDBRequest::willIterateCursor):
+        (WebCore::IDBClient::IDBRequest::didOpenOrIterateCursor):
+        (WebCore::IDBClient::IDBRequest::requestCompleted):
+        * Modules/indexeddb/client/IDBRequestImpl.h:
+        (WebCore::IDBClient::IDBRequest::modernResult):
+
+        * Modules/indexeddb/client/IDBTransactionImpl.cpp:
+        (WebCore::IDBClient::IDBTransaction::requestOpenCursor):
+        (WebCore::IDBClient::IDBTransaction::doRequestOpenCursor):
+        (WebCore::IDBClient::IDBTransaction::openCursorOnServer):
+        (WebCore::IDBClient::IDBTransaction::didOpenCursorOnServer):
+        (WebCore::IDBClient::IDBTransaction::iterateCursor):
+        (WebCore::IDBClient::IDBTransaction::iterateCursorOnServer):
+        (WebCore::IDBClient::IDBTransaction::didIterateCursorOnServer):
+        * Modules/indexeddb/client/IDBTransactionImpl.h:
+
+        * Modules/indexeddb/client/TransactionOperation.h:
+        (WebCore::IDBClient::createTransactionOperation):
+
+        * Modules/indexeddb/legacy/LegacyCursor.cpp:
+        (WebCore::LegacyCursor::source):
+        * Modules/indexeddb/legacy/LegacyCursor.h:
+        (WebCore::LegacyCursor::continueFunction): Deleted.
+        (WebCore::LegacyCursor::isKeyCursor): Deleted.
+        * Modules/indexeddb/legacy/LegacyCursorWithValue.h:
+
+        * Modules/indexeddb/server/IDBBackingStore.h:
+
+        * Modules/indexeddb/server/IDBConnectionToClient.cpp:
+        (WebCore::IDBServer::IDBConnectionToClient::didOpenCursor):
+        (WebCore::IDBServer::IDBConnectionToClient::didIterateCursor):
+        * Modules/indexeddb/server/IDBConnectionToClient.h:
+        * Modules/indexeddb/server/IDBConnectionToClientDelegate.h:
+
+        * Modules/indexeddb/server/IDBServer.cpp:
+        (WebCore::IDBServer::IDBServer::openCursor):
+        (WebCore::IDBServer::IDBServer::iterateCursor):
+        * Modules/indexeddb/server/IDBServer.h:
+
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::openCursor):
+        (WebCore::IDBServer::MemoryIDBBackingStore::iterateCursor):
+        * Modules/indexeddb/server/MemoryIDBBackingStore.h:
+
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::openCursor):
+        (WebCore::IDBServer::UniqueIDBDatabase::performOpenCursor):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformOpenCursor):
+        (WebCore::IDBServer::UniqueIDBDatabase::iterateCursor):
+        (WebCore::IDBServer::UniqueIDBDatabase::performIterateCursor):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformIterateCursor):
+        * Modules/indexeddb/server/UniqueIDBDatabase.h:
+
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::deleteRecord):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::openCursor):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::iterateCursor):
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h:
+
+        * Modules/indexeddb/shared/IDBCursorInfo.cpp: Added.
+        (WebCore::IDBCursorInfo::objectStoreCursor):
+        (WebCore::IDBCursorInfo::indexCursor):
+        (WebCore::IDBCursorInfo::IDBCursorInfo):
+        (WebCore::IDBCursorInfo::isDirectionForward):
+        (WebCore::IDBCursorInfo::isolatedCopy):
+        * Modules/indexeddb/shared/IDBCursorInfo.h: Added.
+        (WebCore::IDBCursorInfo::identifier):
+        (WebCore::IDBCursorInfo::sourceIdentifier):
+        (WebCore::IDBCursorInfo::cursorSource):
+        (WebCore::IDBCursorInfo::cursorDirection):
+        (WebCore::IDBCursorInfo::cursorType):
+
+        * Modules/indexeddb/shared/IDBResultData.cpp:
+        (WebCore::IDBResultData::openCursorSuccess):
+        (WebCore::IDBResultData::iterateCursorSuccess):
+        * Modules/indexeddb/shared/IDBResultData.h:
+
+        * Modules/indexeddb/shared/InProcessIDBServer.cpp:
+        (WebCore::InProcessIDBServer::didOpenCursor):
+        (WebCore::InProcessIDBServer::didIterateCursor):
+        (WebCore::InProcessIDBServer::openCursor):
+        (WebCore::InProcessIDBServer::iterateCursor):
+        * Modules/indexeddb/shared/InProcessIDBServer.h:
+
+        * bindings/js/IDBBindingUtilities.cpp:
+        (WebCore::idbKeyDataToJSValue):
+        * bindings/js/IDBBindingUtilities.h:
+
+        * platform/CrossThreadCopier.cpp:
+        (WebCore::IDBCursorInfo>::copy):
+        * platform/CrossThreadCopier.h:
+
 2015-11-12  Anders Carlsson  <andersca@apple.com>
 
         Delete PlatformMenuDescription.h
index 6c5c8d6..40b28ee 100644 (file)
@@ -63,7 +63,7 @@ public:
     virtual const Deprecated::ScriptValue& key() const = 0;
     virtual const Deprecated::ScriptValue& primaryKey() const = 0;
     virtual const Deprecated::ScriptValue& value() const = 0;
-    virtual IDBAny* source() const = 0;
+    virtual IDBAny* source() = 0;
 
     virtual RefPtr<IDBRequest> update(JSC::ExecState&, Deprecated::ScriptValue&, ExceptionCode&) = 0;
     virtual void advance(unsigned long, ExceptionCode&) = 0;
@@ -72,10 +72,10 @@ public:
     virtual void continueFunction(ScriptExecutionContext*, const Deprecated::ScriptValue& key, ExceptionCode&) = 0;
     virtual RefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, ExceptionCode&) = 0;
 
+    virtual bool isKeyCursor() const = 0;
+
 protected:
     IDBCursor();
-
-    virtual bool isKeyCursor() const { return true; }
 };
 
 } // namespace WebCore
index c5319a0..5f99090 100644 (file)
@@ -38,8 +38,6 @@ public:
 
 protected:
     IDBCursorWithValue();
-
-    virtual bool isKeyCursor() const override { return false; }
 };
 
 } // namespace WebCore
index f3bef37..e9e909e 100644 (file)
@@ -89,6 +89,7 @@ struct IDBGetResult {
 
     ThreadSafeDataBuffer valueBuffer;
     IDBKeyData keyData;
+    IDBKeyData primaryKeyData;
     IDBKeyPath keyPath;
 };
 
index 1469afd..5134a17 100644 (file)
@@ -128,6 +128,30 @@ public:
     static IDBKeyData deletedValue();
     bool isDeletedValue() const { return m_isDeletedValue; }
 
+    String string() const
+    {
+        ASSERT(m_type == KeyType::String);
+        return m_stringValue;
+    }
+
+    double date() const
+    {
+        ASSERT(m_type == KeyType::Date);
+        return m_numberValue;
+    }
+
+    double number() const
+    {
+        ASSERT(m_type == KeyType::Number);
+        return m_numberValue;
+    }
+
+    const Vector<IDBKeyData>& array() const
+    {
+        ASSERT(m_type == KeyType::Array);
+        return m_arrayValue;
+    }
+
 private:
     KeyType m_type;
     Vector<IDBKeyData> m_arrayValue;
index 5b8b00e..a5e538c 100644 (file)
@@ -61,6 +61,11 @@ enum class CursorType {
 };
 const unsigned CursorTypeMaximum = 1;
 
+enum class CursorSource {
+    Index,
+    ObjectStore,
+};
+
 enum class VersionNullness {
     Null,
     NonNull,
index 0c84453..7a94039 100644 (file)
@@ -29,7 +29,7 @@
 #if ENABLE(INDEXED_DATABASE)
 
 #include "IDBAny.h"
-#include "IDBCursorWithValue.h"
+#include "IDBCursorImpl.h"
 #include "IDBFactory.h"
 #include "IDBIndex.h"
 
@@ -59,6 +59,17 @@ IDBAny::IDBAny(Ref<IDBIndex>&& index)
 {
 }
 
+IDBAny::IDBAny(Ref<IDBCursor>&& cursor)
+{
+    if (cursor->isKeyCursor()) {
+        m_type = IDBAny::Type::IDBCursor;
+        m_cursor = WTF::move(cursor);
+    } else {
+        m_type = IDBAny::Type::IDBCursorWithValue;
+        m_cursorWithValue = WTF::move(cursor);
+    }
+}
+
 IDBAny::IDBAny(const IDBKeyPath& keyPath)
     : m_type(IDBAny::Type::KeyPath)
     , m_idbKeyPath(keyPath)
@@ -88,12 +99,14 @@ RefPtr<WebCore::DOMStringList> IDBAny::domStringList()
 
 RefPtr<WebCore::IDBCursor> IDBAny::idbCursor()
 {
-    return nullptr;
+    ASSERT(m_type == IDBAny::Type::IDBCursor || m_type == IDBAny::Type::IDBCursorWithValue);
+    return m_cursor.get();
 }
 
 RefPtr<WebCore::IDBCursorWithValue> IDBAny::idbCursorWithValue()
 {
-    return nullptr;
+    ASSERT(m_type == IDBAny::Type::IDBCursorWithValue);
+    return m_cursorWithValue.get();
 }
 
 RefPtr<WebCore::IDBFactory> IDBAny::idbFactory()
@@ -103,12 +116,14 @@ RefPtr<WebCore::IDBFactory> IDBAny::idbFactory()
 
 RefPtr<WebCore::IDBIndex> IDBAny::idbIndex()
 {
-    return nullptr;
+    ASSERT(m_type == IDBAny::Type::IDBIndex);
+    return m_index.get();
 }
 
 RefPtr<WebCore::IDBObjectStore> IDBAny::idbObjectStore()
 {
-    return nullptr;
+    ASSERT(m_type == IDBAny::Type::IDBObjectStore);
+    return m_objectStore.get();
 }
 
 IDBObjectStore* IDBAny::modernIDBObjectStore()
@@ -123,6 +138,12 @@ IDBIndex* IDBAny::modernIDBIndex()
     return m_index.get();
 }
 
+IDBCursor* IDBAny::modernIDBCursor()
+{
+    ASSERT(m_type == IDBAny::Type::IDBCursor || m_type == IDBAny::Type::IDBCursorWithValue);
+    return m_cursor.get();
+}
+
 RefPtr<WebCore::IDBTransaction> IDBAny::idbTransaction()
 {
     return nullptr;
index 63a1f7a..a8cff10 100644 (file)
@@ -43,14 +43,19 @@ public:
         return adoptRef(new IDBAny(WTF::move(database)));
     }
 
-    static RefPtr<IDBAny> create(Ref<IDBObjectStore>&& objectStore)
+    static Ref<IDBAny> create(Ref<IDBObjectStore>&& objectStore)
     {
-        return adoptRef(new IDBAny(WTF::move(objectStore)));
+        return adoptRef(*new IDBAny(WTF::move(objectStore)));
     }
 
-    static RefPtr<IDBAny> create(Ref<IDBIndex>&& index)
+    static Ref<IDBAny> create(Ref<IDBIndex>&& index)
     {
-        return adoptRef(new IDBAny(WTF::move(index)));
+        return adoptRef(*new IDBAny(WTF::move(index)));
+    }
+
+    static RefPtr<IDBAny> create(Ref<IDBCursor>&& cursor)
+    {
+        return adoptRef(new IDBAny(WTF::move(cursor)));
     }
 
     static RefPtr<IDBAny> create(const IDBKeyPath& keyPath)
@@ -86,12 +91,14 @@ public:
 
     IDBObjectStore* modernIDBObjectStore();
     IDBIndex* modernIDBIndex();
+    IDBCursor* modernIDBCursor();
 
 private:
     explicit IDBAny(IDBAny::Type);
     explicit IDBAny(Ref<IDBDatabase>&&);
     explicit IDBAny(Ref<IDBObjectStore>&&);
     explicit IDBAny(Ref<IDBIndex>&&);
+    explicit IDBAny(Ref<IDBCursor>&&);
     explicit IDBAny(const IDBKeyPath&);
     explicit IDBAny(const Deprecated::ScriptValue&);
 
@@ -99,6 +106,8 @@ private:
     RefPtr<IDBDatabase> m_database;
     RefPtr<IDBObjectStore> m_objectStore;
     RefPtr<IDBIndex> m_index;
+    RefPtr<IDBCursor> m_cursor;
+    RefPtr<IDBCursor> m_cursorWithValue;
 
     const IDBKeyPath m_idbKeyPath;
     const Deprecated::ScriptValue m_scriptValue;
index e9208b2..274fba7 100644 (file)
@@ -217,6 +217,34 @@ void IDBConnectionToServer::didDeleteRecord(const IDBResultData& resultData)
     completeOperation(resultData);
 }
 
+void IDBConnectionToServer::openCursor(TransactionOperation& operation, const IDBCursorInfo& info)
+{
+    LOG(IndexedDB, "IDBConnectionToServer::openCursor");
+
+    saveOperation(operation);
+    m_delegate->openCursor(IDBRequestData(operation), info);
+}
+
+void IDBConnectionToServer::didOpenCursor(const IDBResultData& resultData)
+{
+    LOG(IndexedDB, "IDBConnectionToServer::didOpenCursor");
+    completeOperation(resultData);
+}
+
+void IDBConnectionToServer::iterateCursor(TransactionOperation& operation, const IDBKeyData& key, unsigned long count)
+{
+    LOG(IndexedDB, "IDBConnectionToServer::iterateCursor");
+
+    saveOperation(operation);
+    m_delegate->iterateCursor(IDBRequestData(operation), key, count);
+}
+
+void IDBConnectionToServer::didIterateCursor(const IDBResultData& resultData)
+{
+    LOG(IndexedDB, "IDBConnectionToServer::didIterateCursor");
+    completeOperation(resultData);
+}
+
 void IDBConnectionToServer::establishTransaction(IDBTransaction& transaction)
 {
     LOG(IndexedDB, "IDBConnectionToServer::establishTransaction");
index 76d69dc..1cdce73 100644 (file)
@@ -38,6 +38,7 @@
 
 namespace WebCore {
 
+class IDBCursorInfo;
 class IDBError;
 class IDBObjectStoreInfo;
 class IDBResultData;
@@ -85,6 +86,12 @@ public:
     void deleteRecord(TransactionOperation&, const IDBKeyRangeData&);
     void didDeleteRecord(const IDBResultData&);
 
+    void openCursor(TransactionOperation&, const IDBCursorInfo&);
+    void didOpenCursor(const IDBResultData&);
+
+    void iterateCursor(TransactionOperation&, const IDBKeyData&, unsigned long count);
+    void didIterateCursor(const IDBResultData&);
+
     void commitTransaction(IDBTransaction&);
     void didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError&);
 
index 230564d..f9b8c9c 100644 (file)
 
 namespace WebCore {
 
+class IDBCursorInfo;
 class IDBIndexInfo;
 class IDBKey;
+class IDBKeyData;
 class IDBObjectStoreInfo;
 class IDBRequestData;
 class IDBResourceIdentifier;
@@ -65,6 +67,9 @@ public:
     virtual void getRecord(const IDBRequestData&, const IDBKeyRangeData&) = 0;
     virtual void getCount(const IDBRequestData&, const IDBKeyRangeData&) = 0;
     virtual void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&) = 0;
+    virtual void openCursor(const IDBRequestData&, const IDBCursorInfo&) = 0;
+    virtual void iterateCursor(const IDBRequestData&, const IDBKeyData&, unsigned long count) = 0;
+
     virtual void establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo&) = 0;
 
     virtual void databaseConnectionClosed(uint64_t databaseConnectionIdentifier) = 0;
index 4aae81e..615d157 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "DOMRequestState.h"
+#include "ExceptionCode.h"
+#include "IDBBindingUtilities.h"
+#include "IDBDatabaseException.h"
+#include "IDBGetResult.h"
+#include "Logging.h"
+#include "ScriptExecutionContext.h"
+
 namespace WebCore {
 namespace IDBClient {
 
+Ref<IDBCursor> IDBCursor::create(IDBTransaction& transaction, IDBIndex& index, const IDBCursorInfo& info)
+{
+    return adoptRef(*new IDBCursor(transaction, index, info));
+}
+
+IDBCursor::IDBCursor(IDBTransaction&, IDBObjectStore& objectStore, const IDBCursorInfo& info)
+    : m_info(info)
+    , m_source(IDBAny::create(objectStore).leakRef())
+    , m_objectStore(&objectStore)
+{
+}
+
+IDBCursor::IDBCursor(IDBTransaction&, IDBIndex& index, const IDBCursorInfo& info)
+    : m_info(info)
+    , m_source(IDBAny::create(index).leakRef())
+    , m_index(&index)
+{
+}
+
 IDBCursor::~IDBCursor()
 {
 }
 
+bool IDBCursor::sourcesDeleted() const
+{
+    if (m_objectStore)
+        return m_objectStore->isDeleted();
+
+    ASSERT(m_index);
+    return m_index->isDeleted() || m_index->modernObjectStore().isDeleted();
+}
+
+IDBObjectStore& IDBCursor::effectiveObjectStore() const
+{
+    if (m_objectStore)
+        return *m_objectStore;
+
+    ASSERT(m_index);
+    return m_index->modernObjectStore();
+}
+
+IDBTransaction& IDBCursor::transaction() const
+{
+    return effectiveObjectStore().modernTransaction();
+}
+
 const String& IDBCursor::direction() const
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    return IDBCursor::directionToString(m_info.cursorDirection());
 }
 
 const Deprecated::ScriptValue& IDBCursor::key() const
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    return m_deprecatedCurrentKey;
 }
 
 const Deprecated::ScriptValue& IDBCursor::primaryKey() const
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    return m_deprecatedCurrentPrimaryKey;
 }
 
 const Deprecated::ScriptValue& IDBCursor::value() const
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    return m_deprecatedCurrentValue;
+}
+
+IDBAny* IDBCursor::source()
+{
+    return &m_source.get();
+}
+
+RefPtr<WebCore::IDBRequest> IDBCursor::update(JSC::ExecState& exec, Deprecated::ScriptValue& value, ExceptionCode& ec)
+{
+    LOG(IndexedDB, "IDBCursor::advance");
+
+    if (sourcesDeleted()) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    if (!transaction().isActive()) {
+        ec = IDBDatabaseException::TransactionInactiveError;
+        return nullptr;
+    }
+
+    if (transaction().isReadOnly()) {
+        ec = IDBDatabaseException::ReadOnlyError;
+        return nullptr;
+    }
+
+    if (!m_gotValue) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    if (isKeyCursor()) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    return effectiveObjectStore().put(exec, value.jsValue(), m_deprecatedCurrentPrimaryKey.jsValue(), ec);
+}
+
+void IDBCursor::advance(unsigned long count, ExceptionCode& ec)
+{
+    LOG(IndexedDB, "IDBCursor::advance");
+
+    if (!m_request) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return;
+    }
+    
+    if (!count) {
+        ec = TypeError;
+        return;
+    }
+
+    if (sourcesDeleted()) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return;
+    }
+
+    if (!transaction().isActive()) {
+        ec = IDBDatabaseException::TransactionInactiveError;
+        return;
+    }
+
+    if (!m_gotValue) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return;
+    }
+
+    uncheckedIteratorCursor(IDBKeyData(), count);
 }
 
-IDBAny* IDBCursor::source() const
+void IDBCursor::continueFunction(ScriptExecutionContext* context, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    if (!context) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return;
+    }
+
+    continueFunction(IDBKeyData(), ec);
 }
 
-RefPtr<IDBRequest> IDBCursor::update(JSC::ExecState&, Deprecated::ScriptValue&, ExceptionCode&)
+void IDBCursor::continueFunction(ScriptExecutionContext* context, const Deprecated::ScriptValue& keyValue, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    if (!context) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return;
+    }
+
+    DOMRequestState requestState(context);
+    RefPtr<IDBKey> key = scriptValueToIDBKey(&requestState, keyValue);
+    continueFunction(key.get(), ec);
 }
 
-void IDBCursor::advance(unsigned long, ExceptionCode&)
+void IDBCursor::continueFunction(const IDBKeyData& key, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBCursor::continueFunction");
+
+    if (!m_request) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return;
+    }
+
+    if (sourcesDeleted()) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return;
+    }
+
+    if (!transaction().isActive()) {
+        ec = IDBDatabaseException::TransactionInactiveError;
+        return;
+    }
+
+    if (!m_gotValue) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return;
+    }
+
+    if (!key.isValid()) {
+        ec = IDBDatabaseException::DataError;
+        return;
+    }
+
+    if (m_info.isDirectionForward()) {
+        if (key.compare(m_currentPrimaryKeyData) <= 0) {
+            ec = IDBDatabaseException::DataError;
+            return;
+        }
+    } else if (key.compare(m_currentPrimaryKeyData) >= 0) {
+        ec = IDBDatabaseException::DataError;
+        return;
+    }
+
+    uncheckedIteratorCursor(key, 0);
 }
 
-void IDBCursor::continueFunction(ScriptExecutionContext*, ExceptionCode&)
+void IDBCursor::uncheckedIteratorCursor(const IDBKeyData& key, unsigned long count)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    m_request->willIterateCursor(*this);
+    transaction().iterateCursor(*this, key, count);
 }
 
-void IDBCursor::continueFunction(ScriptExecutionContext*, const Deprecated::ScriptValue&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBCursor::deleteFunction(ScriptExecutionContext* context, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBCursor::deleteFunction");
+
+    if (!context) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    if (sourcesDeleted()) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    if (!transaction().isActive()) {
+        ec = IDBDatabaseException::TransactionInactiveError;
+        return nullptr;
+    }
+
+    if (transaction().isReadOnly()) {
+        ec = IDBDatabaseException::ReadOnlyError;
+        return nullptr;
+    }
+
+    if (!m_gotValue) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    return effectiveObjectStore().deleteFunction(context, m_deprecatedCurrentPrimaryKey.jsValue(), ec);
 }
 
-RefPtr<IDBRequest> IDBCursor::deleteFunction(ScriptExecutionContext*, ExceptionCode&)
+void IDBCursor::setGetResult(const IDBGetResult&)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBCursor::setGetResult");
+
+    // FIXME: Implement.
+
+    m_gotValue = true;
 }
 
 } // namespace IDBClient
index e89b91b..50dd0f0 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "IDBAnyImpl.h"
+#include "IDBCursorInfo.h"
 #include "IDBCursorWithValue.h"
 
 namespace WebCore {
+
+struct IDBGetResult;
+
 namespace IDBClient {
 
+class IDBIndex;
+class IDBObjectStore;
+class IDBTransaction;
+
 class IDBCursor : public WebCore::IDBCursorWithValue {
 public:
+    static Ref<IDBCursor> create(IDBTransaction&, IDBIndex&, const IDBCursorInfo&);
+
     virtual ~IDBCursor();
 
     // Implement the IDL
@@ -42,16 +53,52 @@ public:
     virtual const Deprecated::ScriptValue& key() const override final;
     virtual const Deprecated::ScriptValue& primaryKey() const override final;
     virtual const Deprecated::ScriptValue& value() const override final;
-    virtual IDBAny* source() const override final;
+    virtual IDBAny* source() override final;
 
-    virtual RefPtr<IDBRequest> update(JSC::ExecState&, Deprecated::ScriptValue&, ExceptionCode&) override final;
+    virtual RefPtr<WebCore::IDBRequest> update(JSC::ExecState&, Deprecated::ScriptValue&, ExceptionCode&) override final;
     virtual void advance(unsigned long, ExceptionCode&) override final;
     virtual void continueFunction(ScriptExecutionContext*, ExceptionCode&) override final;
     virtual void continueFunction(ScriptExecutionContext*, const Deprecated::ScriptValue& key, ExceptionCode&) override final;
-    virtual RefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, ExceptionCode&) override final;
+    virtual RefPtr<WebCore::IDBRequest> deleteFunction(ScriptExecutionContext*, ExceptionCode&) override final;
+
+    void continueFunction(const IDBKeyData&, ExceptionCode&);
+
+    const IDBCursorInfo& info() const { return m_info; }
+
+    void setRequest(IDBRequest& request) { m_request = &request; }
+    void clearRequest() { m_request = nullptr; }
+    IDBRequest* request() { return m_request; }
+
+    void setGetResult(const IDBGetResult&);
+
+    virtual bool isKeyCursor() const override { return true; }
 
 protected:
-    IDBCursor();
+    IDBCursor(IDBTransaction&, IDBObjectStore&, const IDBCursorInfo&);
+    IDBCursor(IDBTransaction&, IDBIndex&, const IDBCursorInfo&);
+
+private:
+    IDBCursorInfo m_info;
+    Ref<IDBAny> m_source;
+    IDBObjectStore* m_objectStore { nullptr };
+    IDBIndex* m_index { nullptr };
+    IDBRequest* m_request;
+
+    bool sourcesDeleted() const;
+    IDBObjectStore& effectiveObjectStore() const;
+    IDBTransaction& transaction() const;
+
+    void uncheckedIteratorCursor(const IDBKeyData&, unsigned long count);
+
+    bool m_gotValue { false };
+
+    IDBKeyData m_currentPrimaryKeyData;
+
+    // FIXME: When ditching Legacy IDB and combining this implementation with the abstract IDBCursor,
+    // these Deprecated::ScriptValue members should be JSValues instead.
+    Deprecated::ScriptValue m_deprecatedCurrentKey;
+    Deprecated::ScriptValue m_deprecatedCurrentPrimaryKey;
+    Deprecated::ScriptValue m_deprecatedCurrentValue;
 };
 
 } // namespace IDBClient
index 4d32e75..eeedb2b 100644 (file)
 #if ENABLE(INDEXED_DATABASE)
 
 namespace WebCore {
+namespace IDBClient {
 
+Ref<IDBCursorWithValue> IDBCursorWithValue::create(IDBTransaction& transaction, IDBObjectStore& objectStore, const IDBCursorInfo& info)
+{
+    return adoptRef(*new IDBCursorWithValue(transaction, objectStore, info));
+}
+
+Ref<IDBCursorWithValue> IDBCursorWithValue::create(IDBTransaction& transaction, IDBIndex& index, const IDBCursorInfo& info)
+{
+    return adoptRef(*new IDBCursorWithValue(transaction, index, info));
+}
+
+IDBCursorWithValue::IDBCursorWithValue(IDBTransaction& transaction, IDBObjectStore& objectStore, const IDBCursorInfo& info)
+    : IDBCursor(transaction, objectStore, info)
+{
+}
+
+IDBCursorWithValue::IDBCursorWithValue(IDBTransaction& transaction, IDBIndex& index, const IDBCursorInfo& info)
+    : IDBCursor(transaction, index, info)
+{
+}
+
+IDBCursorWithValue::~IDBCursorWithValue()
+{
+}
+
+} // namespace IDBClient
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index addab6f..df34cde 100644 (file)
@@ -35,10 +35,16 @@ namespace IDBClient {
 
 class IDBCursorWithValue : public IDBCursor {
 public:
+    static Ref<IDBCursorWithValue> create(IDBTransaction&, IDBObjectStore&, const IDBCursorInfo&);
+    static Ref<IDBCursorWithValue> create(IDBTransaction&, IDBIndex&, const IDBCursorInfo&);
+
     virtual ~IDBCursorWithValue();
 
+    virtual bool isKeyCursor() const override final { return false; }
+
 private:
-    IDBCursorWithValue();
+    IDBCursorWithValue(IDBTransaction&, IDBObjectStore&, const IDBCursorInfo&);
+    IDBCursorWithValue(IDBTransaction&, IDBIndex&, const IDBCursorInfo&);
 };
 
 } // namespace IDBClient
index f69b2a7..f092580 100644 (file)
@@ -31,6 +31,8 @@
 #include "DOMRequestState.h"
 #include "IDBAnyImpl.h"
 #include "IDBBindingUtilities.h"
+#include "IDBCursorImpl.h"
+#include "IDBDatabaseException.h"
 #include "IDBKeyRangeData.h"
 #include "IDBObjectStoreImpl.h"
 #include "IDBTransactionImpl.h"
@@ -84,14 +86,37 @@ bool IDBIndex::multiEntry() const
     return m_info.multiEntry();
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::openCursor(ScriptExecutionContext*, IDBKeyRange*, const String&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, IDBKeyRange* range, const String& directionString, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::openCursor");
+
+    if (m_deleted || m_objectStore->isDeleted()) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    if (!m_objectStore->modernTransaction().isActive()) {
+        ec = IDBDatabaseException::TransactionInactiveError;
+        return nullptr;
+    }
+
+    IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, ec);
+    if (ec)
+        return nullptr;
+
+    auto info = IDBCursorInfo::indexCursor(m_objectStore->modernTransaction(), m_info.identifier(), range, direction, IndexedDB::CursorType::KeyAndValue);
+    Ref<IDBRequest> request = m_objectStore->modernTransaction().requestOpenCursor(*context, *this, info);
+    return WTF::move(request);
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::openCursor(ScriptExecutionContext*, const Deprecated::ScriptValue&, const String&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, const String& direction, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::openCursor");
+    RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec);
+    if (ec)
+        return nullptr;
+
+    return openCursor(context, keyRange.get(), direction, ec);
 }
 
 RefPtr<WebCore::IDBRequest> IDBIndex::count(ScriptExecutionContext* context, ExceptionCode& ec)
@@ -159,14 +184,37 @@ RefPtr<WebCore::IDBRequest> IDBIndex::doCount(ScriptExecutionContext& context, c
     return transaction.requestCount(context, *this, range);
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext*, IDBKeyRange*, const String&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, IDBKeyRange* range, const String& directionString, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::openKeyCursor");
+
+    if (m_deleted || m_objectStore->isDeleted()) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    if (!m_objectStore->modernTransaction().isActive()) {
+        ec = IDBDatabaseException::TransactionInactiveError;
+        return nullptr;
+    }
+
+    IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, ec);
+    if (ec)
+        return nullptr;
+
+    auto info = IDBCursorInfo::indexCursor(m_objectStore->modernTransaction(), m_info.identifier(), range, direction, IndexedDB::CursorType::KeyOnly);
+    Ref<IDBRequest> request = m_objectStore->modernTransaction().requestOpenCursor(*context, *this, info);
+    return WTF::move(request);
 }
 
-RefPtr<WebCore::IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext*, const Deprecated::ScriptValue&, const String&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, const String& direction, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBIndex::openKeyCursor");
+    RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec);
+    if (ec)
+        return nullptr;
+
+    return openKeyCursor(context, keyRange.get(), direction, ec);
 }
 
 RefPtr<WebCore::IDBRequest> IDBIndex::get(ScriptExecutionContext* context, IDBKeyRange* range, ExceptionCode& ec)
index 50809c3..1704ddb 100644 (file)
@@ -77,6 +77,9 @@ public:
 
     const IDBIndexInfo& info() const { return m_info; }
 
+    IDBObjectStore& modernObjectStore() { return m_objectStore.get(); }
+    bool isDeleted() const { return m_deleted; }
+
 private:
     IDBIndex(const IDBIndexInfo&, IDBObjectStore&);
 
index 90f0001..b34405e 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "DOMRequestState.h"
 #include "IDBBindingUtilities.h"
+#include "IDBCursorImpl.h"
 #include "IDBDatabaseException.h"
 #include "IDBError.h"
 #include "IDBIndexImpl.h"
@@ -89,29 +90,51 @@ bool IDBObjectStore::autoIncrement() const
     return m_info.autoIncrement();
 }
 
-RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext*, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    return openCursor(context, static_cast<IDBKeyRange*>(nullptr), ec);
 }
 
-RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext*, IDBKeyRange*, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, IDBKeyRange* keyRange, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    return openCursor(context, keyRange, IDBCursor::directionNext(), ec);
 }
 
-RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext*, const Deprecated::ScriptValue&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    return openCursor(context, key, IDBCursor::directionNext(), ec);
 }
 
-RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext*, IDBKeyRange*, const String&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, IDBKeyRange* range, const String& directionString, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    LOG(IndexedDB, "IDBObjectStore::openCursor");
+
+    if (m_deleted) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return nullptr;
+    }
+
+    if (!m_transaction->isActive()) {
+        ec = IDBDatabaseException::TransactionInactiveError;
+        return nullptr;
+    }
+
+    IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, ec);
+    if (ec)
+        return nullptr;
+
+    auto info = IDBCursorInfo::objectStoreCursor(m_transaction.get(), m_info.identifier(), range, direction);
+    Ref<IDBRequest> request = m_transaction->requestOpenCursor(*context, *this, info);
+    return WTF::move(request);
 }
 
-RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext*, const Deprecated::ScriptValue&, const String&, ExceptionCode&)
+RefPtr<WebCore::IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, const String& direction, ExceptionCode& ec)
 {
-    RELEASE_ASSERT_NOT_REACHED();
+    RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(context, key, ec);
+    if (ec)
+        return 0;
+
+    return openCursor(context, keyRange.get(), direction, ec);
 }
 
 RefPtr<WebCore::IDBRequest> IDBObjectStore::get(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
@@ -308,6 +331,11 @@ RefPtr<WebCore::IDBRequest> IDBObjectStore::deleteFunction(ScriptExecutionContex
 
 RefPtr<WebCore::IDBRequest> IDBObjectStore::deleteFunction(ScriptExecutionContext* context, const Deprecated::ScriptValue& key, ExceptionCode& ec)
 {
+    return deleteFunction(context, key.jsValue(), ec);
+}
+
+RefPtr<WebCore::IDBRequest> IDBObjectStore::deleteFunction(ScriptExecutionContext* context, JSC::JSValue key, ExceptionCode& ec)
+{
     DOMRequestState requestState(context);
     RefPtr<IDBKey> idbKey = scriptValueToIDBKey(&requestState, key);
     if (!idbKey || idbKey->type() == KeyType::Invalid) {
index 92e7daf..73d167e 100644 (file)
@@ -78,6 +78,8 @@ public:
     virtual RefPtr<WebCore::IDBRequest> count(ScriptExecutionContext*, IDBKeyRange*, ExceptionCode&) override final;
     virtual RefPtr<WebCore::IDBRequest> count(ScriptExecutionContext*, const Deprecated::ScriptValue& key, ExceptionCode&) override final;
 
+    RefPtr<WebCore::IDBRequest> deleteFunction(ScriptExecutionContext*, JSC::JSValue key, ExceptionCode&);
+
     void markAsDeleted();
     bool isDeleted() const { return m_deleted; }
 
index 98aead5..c56a713 100644 (file)
@@ -31,6 +31,7 @@
 #include "DOMRequestState.h"
 #include "EventQueue.h"
 #include "IDBBindingUtilities.h"
+#include "IDBCursorImpl.h"
 #include "IDBEventDispatcher.h"
 #include "IDBKeyData.h"
 #include "IDBResultData.h"
@@ -47,6 +48,11 @@ Ref<IDBRequest> IDBRequest::create(ScriptExecutionContext& context, IDBObjectSto
     return adoptRef(*new IDBRequest(context, objectStore, transaction));
 }
 
+Ref<IDBRequest> IDBRequest::create(ScriptExecutionContext& context, IDBCursor& cursor, IDBTransaction& transaction)
+{
+    return adoptRef(*new IDBRequest(context, cursor, transaction));
+}
+
 Ref<IDBRequest> IDBRequest::createCount(ScriptExecutionContext& context, IDBIndex& index, IDBTransaction& transaction)
 {
     return adoptRef(*new IDBRequest(context, index, transaction));
@@ -75,6 +81,23 @@ IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBObjectStore& objectSt
     suspendIfNeeded();
 }
 
+IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBCursor& cursor, IDBTransaction& transaction)
+    : IDBOpenDBRequest(&context)
+    , m_transaction(&transaction)
+    , m_connection(transaction.serverConnection())
+    , m_resourceIdentifier(transaction.serverConnection())
+    , m_pendingCursor(&cursor)
+{
+    suspendIfNeeded();
+
+    cursor.setRequest(*this);
+
+    auto* cursorSource = cursor.source();
+    ASSERT(cursorSource);
+    ASSERT(cursorSource->type() == IDBAny::Type::IDBObjectStore || cursorSource->type() == IDBAny::Type::IDBIndex);
+    m_source = cursorSource;
+}
+
 IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBIndex& index, IDBTransaction& transaction)
     : IDBOpenDBRequest(&context)
     , m_transaction(&transaction)
@@ -93,6 +116,11 @@ IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBIndex& index, Indexed
 
 IDBRequest::~IDBRequest()
 {
+    if (m_result) {
+        auto type = m_result->type();
+        if (type == IDBAny::Type::IDBCursor || type == IDBAny::Type::IDBCursorWithValue)
+            m_result->modernIDBCursor()->clearRequest();
+    }
 }
 
 RefPtr<WebCore::IDBAny> IDBRequest::result(ExceptionCode&) const
@@ -112,7 +140,7 @@ RefPtr<DOMError> IDBRequest::error(ExceptionCode&) const
 
 RefPtr<WebCore::IDBAny> IDBRequest::source() const
 {
-    return nullptr;
+    return m_source;
 }
 
 RefPtr<WebCore::IDBTransaction> IDBRequest::transaction() const
@@ -261,8 +289,46 @@ void IDBRequest::setResultToUndefined()
     m_result = IDBAny::createUndefined();
 }
 
+IDBCursor* IDBRequest::resultCursor()
+{
+    if (!m_result)
+        return nullptr;
+    if (m_result->type() == IDBAny::Type::IDBCursor || m_result->type() == IDBAny::Type::IDBCursorWithValue)
+        return m_result->modernIDBCursor();
+    return nullptr;
+}
+
+void IDBRequest::willIterateCursor(IDBCursor& cursor)
+{
+    ASSERT(m_readyState == IDBRequestReadyState::Done);
+    ASSERT(scriptExecutionContext());
+    ASSERT(m_transaction);
+    ASSERT(!m_pendingCursor);
+    ASSERT(&cursor == resultCursor());
+
+    m_pendingCursor = &cursor;
+    m_result = nullptr;
+    m_readyState = IDBRequestReadyState::Pending;
+    m_domError = nullptr;
+    m_idbError = { };
+}
+
+void IDBRequest::didOpenOrIterateCursor(const IDBResultData& resultData)
+{
+    ASSERT(m_pendingCursor);
+    if (resultData.type() == IDBResultType::IterateCursorSuccess)
+        m_pendingCursor->setGetResult(resultData.getResult());
+
+    m_result = IDBAny::create(*m_pendingCursor);
+    m_pendingCursor = nullptr;
+
+    requestCompleted(resultData);
+}
+
 void IDBRequest::requestCompleted(const IDBResultData& resultData)
 {
+    m_readyState = IDBRequestReadyState::Done;
+
     m_idbError = resultData.error();
     if (!m_idbError.isNull())
         onError();
index 290e39c..07063d6 100644 (file)
@@ -52,6 +52,7 @@ class IDBConnectionToServer;
 class IDBRequest : public WebCore::IDBOpenDBRequest, public RefCounted<IDBRequest> {
 public:
     static Ref<IDBRequest> create(ScriptExecutionContext&, IDBObjectStore&, IDBTransaction&);
+    static Ref<IDBRequest> create(ScriptExecutionContext&, IDBCursor&, IDBTransaction&);
     static Ref<IDBRequest> createCount(ScriptExecutionContext&, IDBIndex&, IDBTransaction&);
     static Ref<IDBRequest> createGet(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, IDBTransaction&);
 
@@ -89,9 +90,15 @@ public:
     void setResultToStructuredClone(const ThreadSafeDataBuffer&);
     void setResultToUndefined();
 
+    IDBAny* modernResult() { return m_result.get(); }
+
+    void willIterateCursor(IDBCursor&);
+    void didOpenOrIterateCursor(const IDBResultData&);
+
 protected:
     IDBRequest(IDBConnectionToServer&, ScriptExecutionContext*);
     IDBRequest(ScriptExecutionContext&, IDBObjectStore&, IDBTransaction&);
+    IDBRequest(ScriptExecutionContext&, IDBCursor&, IDBTransaction&);
     IDBRequest(ScriptExecutionContext&, IDBIndex&, IDBTransaction&);
     IDBRequest(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, IDBTransaction&);
 
@@ -114,11 +121,15 @@ private:
     void onError();
     void onSuccess();
 
+    IDBCursor* resultCursor();
+
     IDBConnectionToServer& m_connection;
     IDBResourceIdentifier m_resourceIdentifier;
     RefPtr<IDBAny> m_source;
     bool m_hasPendingActivity { true };
     IndexedDB::IndexRecordType m_requestedIndexRecordType;
+
+    RefPtr<IDBCursor> m_pendingCursor;
 };
 
 } // namespace IDBClient
index 4a47194..c5a98e3 100644 (file)
 
 #include "DOMError.h"
 #include "EventQueue.h"
+#include "IDBCursorWithValueImpl.h"
 #include "IDBDatabaseImpl.h"
 #include "IDBError.h"
 #include "IDBEventDispatcher.h"
+#include "IDBKeyData.h"
 #include "IDBKeyRangeData.h"
 #include "IDBObjectStore.h"
 #include "IDBRequestImpl.h"
@@ -431,6 +433,76 @@ void IDBTransaction::didCreateIndexOnServer(const IDBResultData& resultData)
     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::CreateIndexSuccess);
 }
 
+Ref<IDBRequest> IDBTransaction::requestOpenCursor(ScriptExecutionContext& context, IDBObjectStore& objectStore, const IDBCursorInfo& info)
+{
+    LOG(IndexedDB, "IDBTransaction::requestOpenCursor");
+
+    return doRequestOpenCursor(context, IDBCursorWithValue::create(*this, objectStore, info));
+}
+
+Ref<IDBRequest> IDBTransaction::requestOpenCursor(ScriptExecutionContext& context, IDBIndex& index, const IDBCursorInfo& info)
+{
+    LOG(IndexedDB, "IDBTransaction::requestOpenCursor");
+
+    if (info.cursorType() == IndexedDB::CursorType::KeyOnly)
+        return doRequestOpenCursor(context, IDBCursor::create(*this, index, info));
+
+    return doRequestOpenCursor(context, IDBCursorWithValue::create(*this, index, info));
+}
+
+Ref<IDBRequest> IDBTransaction::doRequestOpenCursor(ScriptExecutionContext& context, Ref<IDBCursor>&& cursor)
+{
+    ASSERT(isActive());
+
+    Ref<IDBRequest> request = IDBRequest::create(context, cursor.get(), *this);
+    addRequest(request.get());
+
+    auto operation = createTransactionOperation(*this, request.get(), &IDBTransaction::didOpenCursorOnServer, &IDBTransaction::openCursorOnServer, cursor->info());
+    scheduleOperation(WTF::move(operation));
+
+    return WTF::move(request);
+}
+
+void IDBTransaction::openCursorOnServer(TransactionOperation& operation, const IDBCursorInfo& info)
+{
+    LOG(IndexedDB, "IDBTransaction::openCursorOnServer");
+
+    m_database->serverConnection().openCursor(operation, info);
+}
+
+void IDBTransaction::didOpenCursorOnServer(IDBRequest& request, const IDBResultData& resultData)
+{
+    LOG(IndexedDB, "IDBTransaction::didOpenCursorOnServer");
+
+    request.didOpenOrIterateCursor(resultData);
+}
+
+void IDBTransaction::iterateCursor(IDBCursor& cursor, const IDBKeyData& key, unsigned long count)
+{
+    LOG(IndexedDB, "IDBTransaction::iterateCursor");
+    ASSERT(isActive());
+    ASSERT(cursor.request());
+
+    addRequest(*cursor.request());
+
+    auto operation = createTransactionOperation(*this, *cursor.request(), &IDBTransaction::didIterateCursorOnServer, &IDBTransaction::iterateCursorOnServer, key, count);
+    scheduleOperation(WTF::move(operation));
+}
+
+void IDBTransaction::iterateCursorOnServer(TransactionOperation& operation, const IDBKeyData& key, const unsigned long& count)
+{
+    LOG(IndexedDB, "IDBTransaction::iterateCursorOnServer");
+
+    serverConnection().iterateCursor(operation, key, count);
+}
+
+void IDBTransaction::didIterateCursorOnServer(IDBRequest& request, const IDBResultData& resultData)
+{
+    LOG(IndexedDB, "IDBTransaction::didIterateCursorOnServer");
+
+    request.didOpenOrIterateCursor(resultData);
+}
+
 Ref<IDBRequest> IDBTransaction::requestGetRecord(ScriptExecutionContext& context, IDBObjectStore& objectStore, const IDBKeyRangeData& keyRangeData)
 {
     LOG(IndexedDB, "IDBTransaction::requestGetRecord");
index 0436195..4de0ed3 100644 (file)
@@ -41,7 +41,9 @@
 
 namespace WebCore {
 
+class IDBCursorInfo;
 class IDBIndexInfo;
+class IDBKeyData;
 class IDBObjectStoreInfo;
 class IDBResultData;
 
@@ -49,6 +51,7 @@ struct IDBKeyRangeData;
 
 namespace IDBClient {
 
+class IDBCursor;
 class IDBDatabase;
 class IDBIndex;
 class TransactionOperation;
@@ -101,6 +104,9 @@ public:
     Ref<IDBRequest> requestCount(ScriptExecutionContext&, IDBIndex&, const IDBKeyRangeData&);
     Ref<IDBRequest> requestGetValue(ScriptExecutionContext&, IDBIndex&, const IDBKeyRangeData&);
     Ref<IDBRequest> requestGetKey(ScriptExecutionContext&, IDBIndex&, const IDBKeyRangeData&);
+    Ref<IDBRequest> requestOpenCursor(ScriptExecutionContext&, IDBObjectStore&, const IDBCursorInfo&);
+    Ref<IDBRequest> requestOpenCursor(ScriptExecutionContext&, IDBIndex&, const IDBCursorInfo&);
+    void iterateCursor(IDBCursor&, const IDBKeyData&, unsigned long count);
 
     void deleteObjectStore(const String& objectStoreName);
 
@@ -159,6 +165,13 @@ private:
     void deleteObjectStoreOnServer(TransactionOperation&, const String& objectStoreName);
     void didDeleteObjectStoreOnServer(const IDBResultData&);
 
+    Ref<IDBRequest> doRequestOpenCursor(ScriptExecutionContext&, Ref<IDBCursor>&&);
+    void openCursorOnServer(TransactionOperation&, const IDBCursorInfo&);
+    void didOpenCursorOnServer(IDBRequest&, const IDBResultData&);
+
+    void iterateCursorOnServer(TransactionOperation&, const IDBKeyData&, const unsigned long& count);
+    void didIterateCursorOnServer(IDBRequest&, const IDBResultData&);
+
     void establishOnServer();
 
     void scheduleOperationTimer();
index 10a6754..5ae99ec 100644 (file)
@@ -148,6 +148,19 @@ RefPtr<TransactionOperation> createTransactionOperation(
     return adoptRef(operation);
 }
 
+template<typename MP1, typename P1, typename MP2, typename P2>
+RefPtr<TransactionOperation> createTransactionOperation(
+    IDBTransaction& transaction,
+    IDBRequest& request,
+    void (IDBTransaction::*complete)(IDBRequest&, const IDBResultData&),
+    void (IDBTransaction::*perform)(TransactionOperation&, MP1, MP2),
+    const P1& parameter1,
+    const P2& parameter2)
+{
+    auto operation = new TransactionOperationImpl<MP1, MP2>(transaction, request, complete, perform, parameter1, parameter2);
+    return adoptRef(operation);
+}
+
 template<typename MP1, typename MP2, typename MP3, typename P1, typename P2, typename P3>
 RefPtr<TransactionOperation> createTransactionOperation(
     IDBTransaction& transaction,
index ae4711b..a7a4201 100644 (file)
@@ -91,7 +91,7 @@ const Deprecated::ScriptValue& LegacyCursor::value() const
     return m_currentValue;
 }
 
-IDBAny* LegacyCursor::source() const
+IDBAny* LegacyCursor::source()
 {
     return m_source.get();
 }
index 0cf9bff..76704d2 100644 (file)
@@ -55,18 +55,18 @@ public:
     virtual ~LegacyCursor();
 
     // Implement the IDL
-    const String& direction() const;
-    const Deprecated::ScriptValue& key() const;
-    const Deprecated::ScriptValue& primaryKey() const;
-    const Deprecated::ScriptValue& value() const;
-    IDBAny* source() const;
-
-    RefPtr<IDBRequest> update(JSC::ExecState&, Deprecated::ScriptValue&, ExceptionCode&);
-    void advance(unsigned long, ExceptionCode&);
+    const String& direction() const override;
+    const Deprecated::ScriptValue& key() const override;
+    const Deprecated::ScriptValue& primaryKey() const override;
+    const Deprecated::ScriptValue& value() const override;
+    IDBAny* source() override;
+
+    RefPtr<IDBRequest> update(JSC::ExecState&, Deprecated::ScriptValue&, ExceptionCode&) override;
+    void advance(unsigned long, ExceptionCode&) override;
     // FIXME: Try to modify the code generator so this overload is unneeded.
-    void continueFunction(ScriptExecutionContext*, ExceptionCode& ec) { continueFunction(static_cast<IDBKey*>(nullptr), ec); }
-    void continueFunction(ScriptExecutionContext*, const Deprecated::ScriptValue& key, ExceptionCode&);
-    RefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, ExceptionCode&);
+    void continueFunction(ScriptExecutionContext*, ExceptionCode& ec) override { continueFunction(static_cast<IDBKey*>(nullptr), ec); }
+    void continueFunction(ScriptExecutionContext*, const Deprecated::ScriptValue& key, ExceptionCode&) override;
+    RefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, ExceptionCode&) override;
 
     void continueFunction(PassRefPtr<IDBKey>, ExceptionCode&);
     void postSuccessHandlerCallback();
@@ -74,9 +74,10 @@ public:
     void setValueReady(DOMRequestState*, PassRefPtr<IDBKey>, PassRefPtr<IDBKey> primaryKey, Deprecated::ScriptValue&);
     PassRefPtr<IDBKey> idbPrimaryKey() { return m_currentPrimaryKey; }
 
+    virtual bool isKeyCursor() const override { return true; }
+
 protected:
     LegacyCursor(PassRefPtr<IDBCursorBackend>, IndexedDB::CursorDirection, LegacyRequest*, LegacyAny* source, LegacyTransaction*);
-    virtual bool isKeyCursor() const { return true; }
 
 private:
     PassRefPtr<LegacyObjectStore> effectiveObjectStore();
index 487b1f1..7258f2d 100644 (file)
@@ -41,8 +41,7 @@ public:
     // The value attribute defined in the IDL is simply implemented in LegacyCursor (but not exposed via
     // its IDL). This is to make the implementation more simple while matching what the spec says.
 
-protected:
-    virtual bool isKeyCursor() const override { return false; }
+    virtual bool isKeyCursor() const override final { return false; }
 
 private:
     LegacyCursorWithValue(PassRefPtr<IDBCursorBackend>, IndexedDB::CursorDirection, LegacyRequest*, LegacyAny* source, LegacyTransaction*);
index 40a9d2b..c7825b0 100644 (file)
@@ -33,6 +33,7 @@
 
 namespace WebCore {
 
+class IDBCursorInfo;
 class IDBIndexInfo;
 class IDBKeyData;
 class IDBObjectStoreInfo;
@@ -70,7 +71,8 @@ public:
     virtual IDBError getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&, IDBGetResult& 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;
-
+    virtual IDBError openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&, IDBGetResult& outResult) = 0;
+    virtual IDBError iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBKeyData&, unsigned long count, IDBGetResult& outResult) = 0;
 };
 
 } // namespace IDBServer
index adf8522..02e1d1b 100644 (file)
@@ -103,6 +103,16 @@ void IDBConnectionToClient::didDeleteRecord(const IDBResultData& result)
     m_delegate->didDeleteRecord(result);
 }
 
+void IDBConnectionToClient::didOpenCursor(const IDBResultData& result)
+{
+    m_delegate->didOpenCursor(result);
+}
+
+void IDBConnectionToClient::didIterateCursor(const IDBResultData& result)
+{
+    m_delegate->didIterateCursor(result);
+}
+
 void IDBConnectionToClient::didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error)
 {
     m_delegate->didCommitTransaction(transactionIdentifier, error);
index 50e8c57..ef880c6 100644 (file)
@@ -60,6 +60,8 @@ public:
     void didGetRecord(const IDBResultData&);
     void didGetCount(const IDBResultData&);
     void didDeleteRecord(const IDBResultData&);
+    void didOpenCursor(const IDBResultData&);
+    void didIterateCursor(const IDBResultData&);
 
     void fireVersionChangeEvent(UniqueIDBDatabaseConnection&, uint64_t requestedVersion);
     void didStartTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError&);
index 0b631bf..3a8f16e 100644 (file)
@@ -56,6 +56,8 @@ public:
     virtual void didGetRecord(const IDBResultData&) = 0;
     virtual void didGetCount(const IDBResultData&) = 0;
     virtual void didDeleteRecord(const IDBResultData&) = 0;
+    virtual void didOpenCursor(const IDBResultData&) = 0;
+    virtual void didIterateCursor(const IDBResultData&) = 0;
 
     virtual void fireVersionChangeEvent(UniqueIDBDatabaseConnection&, uint64_t requestedVersion) = 0;
     virtual void didStartTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError&) = 0;
index 5f3f500..c6378ee 100644 (file)
@@ -247,6 +247,28 @@ void IDBServer::deleteRecord(const IDBRequestData& requestData, const IDBKeyRang
     transaction->deleteRecord(requestData, keyRangeData);
 }
 
+void IDBServer::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info)
+{
+    LOG(IndexedDB, "IDBServer::openCursor");
+
+    auto transaction = m_transactions.get(requestData.transactionIdentifier());
+    if (!transaction)
+        return;
+
+    transaction->openCursor(requestData, info);
+}
+
+void IDBServer::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count)
+{
+    LOG(IndexedDB, "IDBServer::iterateCursor");
+
+    auto transaction = m_transactions.get(requestData.transactionIdentifier());
+    if (!transaction)
+        return;
+
+    transaction->iterateCursor(requestData, key, count);
+}
+
 void IDBServer::establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo& info)
 {
     LOG(IndexedDB, "IDBServer::establishTransaction");
index 3684f22..fa586c0 100644 (file)
@@ -43,6 +43,7 @@
 namespace WebCore {
 
 class CrossThreadTask;
+class IDBCursorInfo;
 class IDBRequestData;
 
 namespace IDBServer {
@@ -67,6 +68,9 @@ public:
     void getRecord(const IDBRequestData&, const IDBKeyRangeData&);
     void getCount(const IDBRequestData&, const IDBKeyRangeData&);
     void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&);
+    void openCursor(const IDBRequestData&, const IDBCursorInfo&);
+    void iterateCursor(const IDBRequestData&, const IDBKeyData&, unsigned long count);
+
     void establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo&);
     void databaseConnectionClosed(uint64_t databaseConnectionIdentifier);
 
index 12f8f62..0964f87 100644 (file)
@@ -329,6 +329,24 @@ IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& t
     return IDBError();
 }
 
+IDBError MemoryIDBBackingStore::openCursor(const IDBResourceIdentifier&, const IDBCursorInfo&, IDBGetResult&)
+{
+    LOG(IndexedDB, "MemoryIDBBackingStore::openCursor");
+
+    // FIXME: Implement.
+
+    return { IDBExceptionCode::Unknown };
+}
+
+IDBError MemoryIDBBackingStore::iterateCursor(const IDBResourceIdentifier&, const IDBKeyData&, unsigned long, IDBGetResult&)
+{
+    LOG(IndexedDB, "MemoryIDBBackingStore::iterateCursor");
+
+    // FIXME: Implement.
+
+    return { IDBExceptionCode::Unknown };
+}
+
 void MemoryIDBBackingStore::registerObjectStore(std::unique_ptr<MemoryObjectStore>&& objectStore)
 {
     ASSERT(objectStore);
index f21e4ef..67911cb 100644 (file)
@@ -63,6 +63,8 @@ public:
     virtual IDBError getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&, IDBGetResult& 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;
+    virtual IDBError openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&, IDBGetResult& outResult) override final;
+    virtual IDBError iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBKeyData&, unsigned long count, IDBGetResult& outResult) override final;
 
     void removeObjectStoreForVersionChangeAbort(MemoryObjectStore&);
     void restoreObjectStoreForVersionChangeAbort(std::unique_ptr<MemoryObjectStore>&&);
index db8379e..fbd9978 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "IDBCursorInfo.h"
 #include "IDBKeyRangeData.h"
 #include "IDBResultData.h"
 #include "IDBServer.h"
@@ -552,6 +553,62 @@ void UniqueIDBDatabase::didPerformDeleteRecord(uint64_t callbackIdentifier, cons
     performErrorCallback(callbackIdentifier, error);
 }
 
+void UniqueIDBDatabase::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
+{
+    ASSERT(isMainThread());
+    LOG(IndexedDB, "(main) UniqueIDBDatabase::openCursor");
+
+    uint64_t callbackID = storeCallback(callback);
+    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performOpenCursor, callbackID, requestData.transactionIdentifier(), info));
+}
+
+void UniqueIDBDatabase::performOpenCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info)
+{
+    ASSERT(!isMainThread());
+    LOG(IndexedDB, "(db) UniqueIDBDatabase::performOpenCursor");
+
+    IDBGetResult result;
+    IDBError error = m_backingStore->openCursor(transactionIdentifier, info, result);
+
+    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformOpenCursor, callbackIdentifier, error, result));
+}
+
+void UniqueIDBDatabase::didPerformOpenCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
+{
+    ASSERT(isMainThread());
+    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformOpenCursor");
+
+    performGetResultCallback(callbackIdentifier, error, result);
+}
+
+void UniqueIDBDatabase::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count, GetResultCallback callback)
+{
+    ASSERT(isMainThread());
+    LOG(IndexedDB, "(main) UniqueIDBDatabase::iterateCursor");
+
+    uint64_t callbackID = storeCallback(callback);
+    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performIterateCursor, callbackID, requestData.transactionIdentifier(), key, count));
+}
+
+void UniqueIDBDatabase::performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBKeyData& key, unsigned long count)
+{
+    ASSERT(!isMainThread());
+    LOG(IndexedDB, "(db) UniqueIDBDatabase::performIterateCursor");
+
+    IDBGetResult result;
+    IDBError error = m_backingStore->iterateCursor(transactionIdentifier, key, count, result);
+
+    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformIterateCursor, callbackIdentifier, error, result));
+}
+
+void UniqueIDBDatabase::didPerformIterateCursor(uint64_t callbackIdentifier, const IDBError& error, const IDBGetResult& result)
+{
+    ASSERT(isMainThread());
+    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformIterateCursor");
+
+    performGetResultCallback(callbackIdentifier, error, result);
+}
+
 void UniqueIDBDatabase::commitTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
 {
     ASSERT(isMainThread());
index 727b34e..4108fd9 100644 (file)
@@ -83,6 +83,8 @@ public:
     void getRecord(const IDBRequestData&, const IDBKeyRangeData&, GetResultCallback);
     void getCount(const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
     void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
+    void openCursor(const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
+    void iterateCursor(const IDBRequestData&, const IDBKeyData&, unsigned long count, GetResultCallback);
     void commitTransaction(UniqueIDBDatabaseTransaction&, ErrorCallback);
     void abortTransaction(UniqueIDBDatabaseTransaction&, ErrorCallback);
     void transactionDestroyed(UniqueIDBDatabaseTransaction&);
@@ -117,6 +119,8 @@ private:
     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 performOpenCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&);
+    void performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBKeyData&, unsigned long count);
     void performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo&);
 
     // Main thread callbacks
@@ -129,6 +133,8 @@ private:
     void didPerformGetRecord(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
     void didPerformGetCount(uint64_t callbackIdentifier, const IDBError&, uint64_t);
     void didPerformDeleteRecord(uint64_t callbackIdentifier, const IDBError&);
+    void didPerformOpenCursor(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
+    void didPerformIterateCursor(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
     void didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError&, const IDBResourceIdentifier& transactionIdentifier);
     void didPerformAbortTransaction(uint64_t callbackIdentifier, const IDBError&, const IDBResourceIdentifier& transactionIdentifier);
     void didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError&);
index fd43b1f..effb38c 100644 (file)
@@ -232,6 +232,40 @@ void UniqueIDBDatabaseTransaction::deleteRecord(const IDBRequestData& requestDat
     });
 }
 
+void UniqueIDBDatabaseTransaction::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info)
+{
+    LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor");
+
+    ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
+
+    RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this);
+    m_databaseConnection->database().openCursor(requestData, info, [this, protectedThis, requestData](const IDBError& error, const IDBGetResult& result) {
+        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor (callback)");
+
+        if (error.isNull())
+            m_databaseConnection->connectionToClient().didOpenCursor(IDBResultData::openCursorSuccess(requestData.requestIdentifier(), result));
+        else
+            m_databaseConnection->connectionToClient().didOpenCursor(IDBResultData::error(requestData.requestIdentifier(), error));
+    });
+}
+
+void UniqueIDBDatabaseTransaction::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count)
+{
+    LOG(IndexedDB, "UniqueIDBDatabaseTransaction::iterateCursor");
+
+    ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
+
+    RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this);
+    m_databaseConnection->database().iterateCursor(requestData, key, count, [this, protectedThis, requestData](const IDBError& error, const IDBGetResult& result) {
+        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor (callback)");
+
+        if (error.isNull())
+            m_databaseConnection->connectionToClient().didIterateCursor(IDBResultData::iterateCursorSuccess(requestData.requestIdentifier(), result));
+        else
+            m_databaseConnection->connectionToClient().didIterateCursor(IDBResultData::error(requestData.requestIdentifier(), error));
+    });
+}
+
 const Vector<uint64_t>& UniqueIDBDatabaseTransaction::objectStoreIdentifiers()
 {
     if (!m_objectStoreIdentifiers.isEmpty())
index e8fde4e..e1736d6 100644 (file)
@@ -35,6 +35,7 @@
 
 namespace WebCore {
 
+class IDBCursorInfo;
 class IDBDatabaseInfo;
 class IDBError;
 class IDBIndexInfo;
@@ -73,6 +74,8 @@ public:
     void getRecord(const IDBRequestData&, const IDBKeyRangeData&);
     void getCount(const IDBRequestData&, const IDBKeyRangeData&);
     void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&);
+    void openCursor(const IDBRequestData&, const IDBCursorInfo&);
+    void iterateCursor(const IDBRequestData&, const IDBKeyData&, unsigned long count);
 
     void didActivateInBackingStore(const IDBError&);
 
diff --git a/Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.cpp b/Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.cpp
new file mode 100644 (file)
index 0000000..0384601
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IDBCursorInfo.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBTransactionImpl.h"
+#include "IndexedDB.h"
+
+namespace WebCore {
+
+IDBCursorInfo IDBCursorInfo::objectStoreCursor(IDBClient::IDBTransaction& transaction, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, IndexedDB::CursorDirection direction)
+{
+    return { transaction, IndexedDB::CursorSource::ObjectStore, objectStoreIdentifier, range, direction, IndexedDB::CursorType::KeyAndValue };
+}
+
+IDBCursorInfo IDBCursorInfo::indexCursor(IDBClient::IDBTransaction& transaction, uint64_t indexIdentifier, const IDBKeyRangeData& range, IndexedDB::CursorDirection direction, IndexedDB::CursorType type)
+{
+    return { transaction, IndexedDB::CursorSource::Index, indexIdentifier, range, direction, type };
+}
+
+IDBCursorInfo::IDBCursorInfo(IDBClient::IDBTransaction& transaction, IndexedDB::CursorSource source, uint64_t sourceIdentifier, const IDBKeyRangeData& range, IndexedDB::CursorDirection direction, IndexedDB::CursorType type)
+    : m_cursorIdentifier(transaction.serverConnection())
+    , m_transactionIdentifier(transaction.info().identifier())
+    , m_sourceIdentifier(sourceIdentifier)
+    , m_range(range)
+    , m_source(source)
+    , m_direction(direction)
+    , m_type(type)
+{
+}
+
+IDBCursorInfo::IDBCursorInfo(const IDBResourceIdentifier& cursorIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t sourceIdentifier, const IDBKeyRangeData& range, IndexedDB::CursorSource source, IndexedDB::CursorDirection direction, IndexedDB::CursorType type)
+    : m_cursorIdentifier(cursorIdentifier)
+    , m_transactionIdentifier(transactionIdentifier)
+    , m_sourceIdentifier(sourceIdentifier)
+    , m_range(range)
+    , m_source(source)
+    , m_direction(direction)
+    , m_type(type)
+{
+}
+
+bool IDBCursorInfo::isDirectionForward() const
+{
+    return m_direction == IndexedDB::CursorDirection::Next || m_direction == IndexedDB::CursorDirection::NextNoDuplicate;
+}
+
+IDBCursorInfo IDBCursorInfo::isolatedCopy() const
+{
+    return { m_cursorIdentifier.isolatedCopy(), m_transactionIdentifier.isolatedCopy(), m_sourceIdentifier, m_range.isolatedCopy(), m_source, m_direction, m_type };
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.h b/Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.h
new file mode 100644 (file)
index 0000000..34a3b8f
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IDBCursorInfo_h
+#define IDBCursorInfo_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBKeyRangeData.h"
+#include "IDBResourceIdentifier.h"
+
+namespace WebCore {
+
+namespace IDBClient {
+class IDBTransaction;
+}
+
+namespace IndexedDB {
+enum class CursorDirection;
+enum class CursorSource;
+enum class CursorType;
+}
+
+struct IDBKeyRangeData;
+
+class IDBCursorInfo {
+public:
+    static IDBCursorInfo objectStoreCursor(IDBClient::IDBTransaction&, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, IndexedDB::CursorDirection);
+    static IDBCursorInfo indexCursor(IDBClient::IDBTransaction&, uint64_t indexIdentifier, const IDBKeyRangeData&, IndexedDB::CursorDirection, IndexedDB::CursorType);
+
+    IDBResourceIdentifier identifier() const { return m_cursorIdentifier; }
+    uint64_t sourceIdentifier() const { return m_sourceIdentifier; }
+
+    IndexedDB::CursorSource cursorSource() const { return m_source; }
+    IndexedDB::CursorDirection cursorDirection() const { return m_direction; }
+    IndexedDB::CursorType cursorType() const { return m_type; }
+
+    bool isDirectionForward() const;
+
+    IDBCursorInfo isolatedCopy() const;
+
+private:
+    IDBCursorInfo(IDBClient::IDBTransaction&, IndexedDB::CursorSource, uint64_t sourceIdentifier, const IDBKeyRangeData&, IndexedDB::CursorDirection, IndexedDB::CursorType);
+    IDBCursorInfo(const IDBResourceIdentifier&, const IDBResourceIdentifier&, uint64_t, const IDBKeyRangeData&, IndexedDB::CursorSource, IndexedDB::CursorDirection, IndexedDB::CursorType);
+
+    IDBResourceIdentifier m_cursorIdentifier;
+    IDBResourceIdentifier m_transactionIdentifier;
+    uint64_t m_sourceIdentifier;
+
+    IDBKeyRangeData m_range;
+
+    IndexedDB::CursorSource m_source;
+    IndexedDB::CursorDirection m_direction;
+    IndexedDB::CursorType m_type;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+#endif // IDBCursorInfo_h
index 37da733..c3d0716 100644 (file)
@@ -136,6 +136,20 @@ IDBResultData IDBResultData::deleteRecordSuccess(const IDBResourceIdentifier& re
     return { IDBResultType::DeleteRecordSuccess, requestIdentifier };
 }
 
+IDBResultData IDBResultData::openCursorSuccess(const IDBResourceIdentifier& requestIdentifier, const IDBGetResult& getResult)
+{
+    IDBResultData result(IDBResultType::OpenCursorSuccess, requestIdentifier);
+    result.m_getResult = std::make_unique<IDBGetResult>(getResult);
+    return result;
+}
+
+IDBResultData IDBResultData::iterateCursorSuccess(const IDBResourceIdentifier& requestIdentifier, const IDBGetResult& getResult)
+{
+    IDBResultData result(IDBResultType::IterateCursorSuccess, requestIdentifier);
+    result.m_getResult = std::make_unique<IDBGetResult>(getResult);
+    return result;
+}
+
 const IDBDatabaseInfo& IDBResultData::databaseInfo() const
 {
     RELEASE_ASSERT(m_databaseInfo);
index d8226b6..2ede7bc 100644 (file)
@@ -53,6 +53,8 @@ enum class IDBResultType {
     GetCountSuccess,
     DeleteRecordSuccess,
     CreateIndexSuccess,
+    OpenCursorSuccess,
+    IterateCursorSuccess,
 };
 
 namespace IDBServer {
@@ -73,6 +75,8 @@ public:
     static IDBResultData getRecordSuccess(const IDBResourceIdentifier&, const IDBGetResult&);
     static IDBResultData getCountSuccess(const IDBResourceIdentifier&, uint64_t count);
     static IDBResultData deleteRecordSuccess(const IDBResourceIdentifier&);
+    static IDBResultData openCursorSuccess(const IDBResourceIdentifier&, const IDBGetResult&);
+    static IDBResultData iterateCursorSuccess(const IDBResourceIdentifier&, const IDBGetResult&);
 
     IDBResultData(const IDBResultData&);
 
index d7efa51..dbbc125 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "IDBConnectionToClient.h"
 #include "IDBConnectionToServer.h"
+#include "IDBCursorInfo.h"
 #include "IDBKeyRangeData.h"
 #include "IDBOpenDBRequestImpl.h"
 #include "IDBRequestData.h"
@@ -183,6 +184,22 @@ void InProcessIDBServer::didDeleteRecord(const IDBResultData& resultData)
     });
 }
 
+void InProcessIDBServer::didOpenCursor(const IDBResultData& resultData)
+{
+    RefPtr<InProcessIDBServer> self(this);
+    RunLoop::current().dispatch([this, self, resultData] {
+        m_connectionToServer->didOpenCursor(resultData);
+    });
+}
+
+void InProcessIDBServer::didIterateCursor(const IDBResultData& resultData)
+{
+    RefPtr<InProcessIDBServer> self(this);
+    RunLoop::current().dispatch([this, self, resultData] {
+        m_connectionToServer->didIterateCursor(resultData);
+    });
+}
+
 void InProcessIDBServer::abortTransaction(IDBResourceIdentifier& resourceIdentifier)
 {
     RefPtr<InProcessIDBServer> self(this);
@@ -268,6 +285,24 @@ void InProcessIDBServer::deleteRecord(const IDBRequestData& requestData, const I
     });
 }
 
+void InProcessIDBServer::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info)
+{
+    RefPtr<InProcessIDBServer> self(this);
+
+    RunLoop::current().dispatch([this, self, requestData, info] {
+        m_server->openCursor(requestData, info);
+    });
+}
+
+void InProcessIDBServer::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count)
+{
+    RefPtr<InProcessIDBServer> self(this);
+
+    RunLoop::current().dispatch([this, self, requestData, key, count] {
+        m_server->iterateCursor(requestData, key, count);
+    });
+}
+
 void InProcessIDBServer::establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo& info)
 {
     RefPtr<InProcessIDBServer> self(this);
index 339d79a..7553e17 100644 (file)
@@ -66,6 +66,8 @@ public:
     virtual void getRecord(const IDBRequestData&, const IDBKeyRangeData&) override final;
     virtual void getCount(const IDBRequestData&, const IDBKeyRangeData&) override final;
     virtual void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&) override final;
+    virtual void openCursor(const IDBRequestData&, const IDBCursorInfo&) override final;
+    virtual void iterateCursor(const IDBRequestData&, const IDBKeyData&, unsigned long count) override final;
     virtual void establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo&) override final;
     virtual void databaseConnectionClosed(uint64_t databaseConnectionIdentifier) override final;
 
@@ -83,6 +85,8 @@ public:
     virtual void didGetRecord(const IDBResultData&) override final;
     virtual void didGetCount(const IDBResultData&) override final;
     virtual void didDeleteRecord(const IDBResultData&) override final;
+    virtual void didOpenCursor(const IDBResultData&) override final;
+    virtual void didIterateCursor(const IDBResultData&) override final;
     virtual void fireVersionChangeEvent(IDBServer::UniqueIDBDatabaseConnection&, uint64_t requestedVersion) override final;
     virtual void didStartTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError&) override final;
 
index 9e31c47..8f225ad 100644 (file)
                517138F01BED1D1A000D5F01 /* IndexKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 517138EE1BED1D17000D5F01 /* IndexKey.h */; };
                517138F71BF128BB000D5F01 /* IndexValueStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517138F51BF12262000D5F01 /* IndexValueStore.cpp */; };
                517138F81BF128BB000D5F01 /* IndexValueStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 517138F61BF12262000D5F01 /* IndexValueStore.h */; };
+               517138FB1BF3ADF4000D5F01 /* IDBCursorInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517138F91BF3ADAC000D5F01 /* IDBCursorInfo.cpp */; };
+               517138FC1BF3ADF4000D5F01 /* IDBCursorInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 517138FA1BF3ADAC000D5F01 /* IDBCursorInfo.h */; };
                51741D0F0B07259A00ED442C /* BackForwardClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0B0B07259A00ED442C /* BackForwardClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51741D110B07259A00ED442C /* HistoryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0D0B07259A00ED442C /* HistoryItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51741D120B07259A00ED442C /* HistoryItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51741D0E0B07259A00ED442C /* HistoryItem.cpp */; };
                517138EE1BED1D17000D5F01 /* IndexKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexKey.h; sourceTree = "<group>"; };
                517138F51BF12262000D5F01 /* IndexValueStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexValueStore.cpp; sourceTree = "<group>"; };
                517138F61BF12262000D5F01 /* IndexValueStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexValueStore.h; sourceTree = "<group>"; };
+               517138F91BF3ADAC000D5F01 /* IDBCursorInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBCursorInfo.cpp; sourceTree = "<group>"; };
+               517138FA1BF3ADAC000D5F01 /* IDBCursorInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBCursorInfo.h; sourceTree = "<group>"; };
                51741D0B0B07259A00ED442C /* BackForwardClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardClient.h; sourceTree = "<group>"; };
                51741D0D0B07259A00ED442C /* HistoryItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HistoryItem.h; sourceTree = "<group>"; };
                51741D0E0B07259A00ED442C /* HistoryItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HistoryItem.cpp; sourceTree = "<group>"; };
                510A58E11BAA409800C19282 /* shared */ = {
                        isa = PBXGroup;
                        children = (
+                               517138F91BF3ADAC000D5F01 /* IDBCursorInfo.cpp */,
+                               517138FA1BF3ADAC000D5F01 /* IDBCursorInfo.h */,
                                51BA4AC11BBB5CBF00DF3D6D /* IDBDatabaseInfo.cpp */,
                                51BA4AC21BBB5CBF00DF3D6D /* IDBDatabaseInfo.h */,
                                5148453C1BB9D076006A72ED /* IDBError.cpp */,
                                854075200AD6C5FB00620C57 /* DOMEventTarget.h in Headers */,
                                85C78A680ABDE1B40044FC16 /* DOMException.h in Headers */,
                                BC1A37B5097C715F0019F3D8 /* DOMExtensions.h in Headers */,
+                               517138FC1BF3ADF4000D5F01 /* IDBCursorInfo.h in Headers */,
                                BC00F0040E0A185500FD04E3 /* DOMFile.h in Headers */,
                                2E3BC108117D479800B9409A /* DOMFileError.h in Headers */,
                                2E3BC10B117D47C800B9409A /* DOMFileErrorInternal.h in Headers */,
                                316FE0730E6CCBEE00BF6088 /* JSCSSKeyframesRule.cpp in Sources */,
                                BC46C2000C0DDC8F0020CFC3 /* JSCSSMediaRule.cpp in Sources */,
                                BC46C2020C0DDC8F0020CFC3 /* JSCSSPageRule.cpp in Sources */,
+                               517138FB1BF3ADF4000D5F01 /* IDBCursorInfo.cpp in Sources */,
                                930705E909E0C9F000B17FE4 /* JSCSSPrimitiveValue.cpp in Sources */,
                                14CF7B3309F6ECD700EB3665 /* JSCSSRule.cpp in Sources */,
                                BC46C1EE0C0DDBDF0020CFC3 /* JSCSSRuleCustom.cpp in Sources */,
index ef23f29..7134286 100644 (file)
@@ -78,6 +78,43 @@ static bool set(ExecState* exec, JSValue& object, const String& keyPathElement,
     return true;
 }
 
+JSValue idbKeyDataToJSValue(JSC::ExecState& exec, const IDBKeyData& keyData)
+{
+    if (keyData.isNull())
+        return jsUndefined();
+
+    Locker<JSLock> locker(exec.vm().apiLock());
+
+    switch (keyData.type()) {
+    case KeyType::Array:
+        {
+            const Vector<IDBKeyData>& inArray = keyData.array();
+            size_t size = inArray.size();
+            JSArray* outArray = constructEmptyArray(&exec, 0, exec.lexicalGlobalObject(), size);
+            for (size_t i = 0; i < size; ++i) {
+                auto& arrayKey = inArray.at(i);
+                outArray->putDirectIndex(&exec, i, idbKeyDataToJSValue(exec, arrayKey));
+            }
+            return JSValue(outArray);
+        }
+    case KeyType::String:
+        return jsStringWithCache(&exec, keyData.string());
+    case KeyType::Date:
+        return jsDateOrNull(&exec, keyData.date());
+    case KeyType::Number:
+        return jsNumber(keyData.number());
+    case KeyType::Min:
+    case KeyType::Max:
+    case KeyType::Invalid:
+        ASSERT_NOT_REACHED();
+        return jsUndefined();
+    }
+
+    ASSERT_NOT_REACHED();
+    return jsUndefined();
+
+}
+
 static JSValue idbKeyToJSValue(ExecState* exec, JSDOMGlobalObject* globalObject, IDBKey* key)
 {
     if (!key || !exec) {
index 61f3b0d..5bc4442 100644 (file)
@@ -70,6 +70,7 @@ Deprecated::ScriptValue idbKeyDataToScriptValue(ScriptExecutionContext*, const I
 
 JSC::JSValue idbValueDataToJSValue(JSC::ExecState&, const ThreadSafeDataBuffer& valueData);
 void generateIndexKeyForValue(JSC::ExecState&, const IDBIndexInfo&, JSC::JSValue, IndexKey& outKey);
+JSC::JSValue idbKeyDataToJSValue(JSC::ExecState&, const IDBKeyData&);
 
 }
 
index 2266f14..3f741cf 100644 (file)
@@ -43,6 +43,7 @@
 #include <wtf/text/WTFString.h>
 
 #if ENABLE(INDEXED_DATABASE)
+#include "IDBCursorInfo.h"
 #include "IDBDatabaseIdentifier.h"
 #include "IDBDatabaseInfo.h"
 #include "IDBDatabaseMetadata.h"
@@ -175,6 +176,11 @@ CrossThreadCopierBase<false, false, IDBIndexInfo>::Type CrossThreadCopierBase<fa
     return info.isolatedCopy();
 }
 
+CrossThreadCopierBase<false, false, IDBCursorInfo>::Type CrossThreadCopierBase<false, false, IDBCursorInfo>::copy(const IDBCursorInfo& info)
+{
+    return info.isolatedCopy();
+}
+
 #endif // ENABLE(INDEXED_DATABASE)
 
 // Test CrossThreadCopier using COMPILE_ASSERT.
index 0ff0a5c..6e1091b 100644 (file)
@@ -239,6 +239,12 @@ namespace WebCore {
         static Type copy(const IDBIndexInfo&);
     };
 
+    class IDBCursorInfo;
+    template<> struct WEBCORE_EXPORT CrossThreadCopierBase<false, false, IDBCursorInfo> {
+        typedef IDBCursorInfo Type;
+        static Type copy(const IDBCursorInfo&);
+    };
+
 #endif
 
     template<typename T>