Modern IDB: storage/indexeddb/index-duplicate-keypaths.html fails.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 12 Dec 2015 22:03:09 +0000 (22:03 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 12 Dec 2015 22:03:09 +0000 (22:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=152201

Reviewed by Alex Christensen.

Source/WebCore:

No new tests (At least one failing test now passes).

The spec states that if an object store uses a key generator, and then a record is stored whose
key was an explicitly set number, then the key generator value should be bumped to the next
integer higher than the explicit number.

We didn't do that.

Now we do.

* Modules/indexeddb/IndexedDB.h: Add an "OverwriteForCursor" option for overwrite mode.

* Modules/indexeddb/client/IDBObjectStoreImpl.cpp:
(WebCore::IDBClient::IDBObjectStore::putForCursorUpdate): Use the "OverwriteForCursor" mode.

* Modules/indexeddb/server/IDBBackingStore.h: Add maybeUpdateKeyGeneratorNumber

* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber): If the number value
  from the provided key should bump the key generator value, do so now.
* Modules/indexeddb/server/MemoryIDBBackingStore.h:

* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd): After successfully adding the new record,
  possibly bump the key generator value.

LayoutTests:

* platform/mac-wk1/TestExpectations:

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

LayoutTests/ChangeLog
LayoutTests/platform/mac-wk1/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IndexedDB.h
Source/WebCore/Modules/indexeddb/client/IDBObjectStoreImpl.cpp
Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp

index 5ad68ec..32a1bc3 100644 (file)
@@ -1,3 +1,12 @@
+2015-12-12  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: storage/indexeddb/index-duplicate-keypaths.html fails.
+        https://bugs.webkit.org/show_bug.cgi?id=152201
+
+        Reviewed by Alex Christensen.
+
+        * platform/mac-wk1/TestExpectations:
+
 2015-12-11  Simon Fraser  <simon.fraser@apple.com>
 
         Mousewheel events don't work in iframes in RTL documents
index dd34e33..86bcb1a 100644 (file)
@@ -94,7 +94,6 @@ storage/indexeddb/unblocked-version-changes.html [ Skip ]
 # IDB tests with text failures                                                             
 storage/indexeddb/database-deletepending-flag.html [ Failure ]
 storage/indexeddb/delete-closed-database-object.html [ Failure ]
-storage/indexeddb/index-duplicate-keypaths.html [ Failure ]
 storage/indexeddb/intversion-gated-on-delete.html [ Failure ]
 storage/indexeddb/intversion-open-in-upgradeneeded.html [ Failure ]
 storage/indexeddb/intversion-pending-version-changes-descending.html [ Failure ]
index f803cbf..db5c5a4 100644 (file)
@@ -1,3 +1,36 @@
+2015-12-12  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: storage/indexeddb/index-duplicate-keypaths.html fails.
+        https://bugs.webkit.org/show_bug.cgi?id=152201
+
+        Reviewed by Alex Christensen.
+
+        No new tests (At least one failing test now passes).
+        
+        The spec states that if an object store uses a key generator, and then a record is stored whose
+        key was an explicitly set number, then the key generator value should be bumped to the next
+        integer higher than the explicit number.
+        
+        We didn't do that.
+        
+        Now we do.
+
+        * Modules/indexeddb/IndexedDB.h: Add an "OverwriteForCursor" option for overwrite mode.
+        
+        * Modules/indexeddb/client/IDBObjectStoreImpl.cpp:
+        (WebCore::IDBClient::IDBObjectStore::putForCursorUpdate): Use the "OverwriteForCursor" mode.
+                
+        * Modules/indexeddb/server/IDBBackingStore.h: Add maybeUpdateKeyGeneratorNumber
+
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber): If the number value
+          from the provided key should bump the key generator value, do so now.
+        * Modules/indexeddb/server/MemoryIDBBackingStore.h:
+
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd): After successfully adding the new record,
+          possibly bump the key generator value.
+
 2015-12-12  Katlyn Graff  <kgraff@apple.com>
 
         Safari background tabs should be fully suspended where possible.
index a5e538c..35aadb1 100644 (file)
@@ -79,6 +79,7 @@ enum class KeyPathType {
 
 enum class ObjectStoreOverwriteMode {
     Overwrite,
+    OverwriteForCursor,
     NoOverwrite,
 };
 
index 2f0c105..9a12ee9 100644 (file)
@@ -235,7 +235,7 @@ RefPtr<WebCore::IDBRequest> IDBObjectStore::put(JSC::ExecState& state, JSC::JSVa
 
 RefPtr<IDBRequest> IDBObjectStore::putForCursorUpdate(JSC::ExecState& state, JSC::JSValue value, JSC::JSValue key, ExceptionCodeWithMessage& ec)
 {
-    return putOrAdd(state, value, scriptValueToIDBKey(state, key), IndexedDB::ObjectStoreOverwriteMode::Overwrite, InlineKeyCheck::DoNotPerform, ec);
+    return putOrAdd(state, value, scriptValueToIDBKey(state, key), IndexedDB::ObjectStoreOverwriteMode::OverwriteForCursor, InlineKeyCheck::DoNotPerform, ec);
 }
 
 RefPtr<IDBRequest> IDBObjectStore::putOrAdd(JSC::ExecState& state, JSC::JSValue value, RefPtr<IDBKey> key, IndexedDB::ObjectStoreOverwriteMode overwriteMode, InlineKeyCheck inlineKeyCheck, ExceptionCodeWithMessage& ec)
index 2e8d7be..68506a0 100644 (file)
@@ -72,6 +72,7 @@ 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 maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber) = 0;
     virtual IDBError openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&, IDBGetResult& outResult) = 0;
     virtual IDBError iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBKeyData&, uint32_t count, IDBGetResult& outResult) = 0;
 };
index a5d280d..4ce9eb8 100644 (file)
@@ -346,6 +346,30 @@ IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& t
     return IDBError();
 }
 
+IDBError MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber)
+{
+    LOG(IndexedDB, "MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber");
+    ASSERT(objectStoreIdentifier);
+    ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
+    ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
+
+    MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
+    RELEASE_ASSERT(objectStore);
+
+    if (newKeyNumber < objectStore->currentKeyGeneratorValue())
+        return { };
+
+    uint64_t newKeyInteger(newKeyNumber);
+    if (newKeyInteger <= newKeyNumber)
+        ++newKeyInteger;
+
+    ASSERT(newKeyInteger > newKeyNumber);
+
+    objectStore->setKeyGeneratorValue(newKeyInteger);
+
+    return { };
+}
+
 IDBError MemoryIDBBackingStore::openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info, IDBGetResult& outData)
 {
     LOG(IndexedDB, "MemoryIDBBackingStore::openCursor");
index 0ec5743..300dd41 100644 (file)
@@ -64,6 +64,7 @@ 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 maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber) override final;
     virtual IDBError openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&, IDBGetResult& outResult) override final;
     virtual IDBError iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBKeyData&, uint32_t count, IDBGetResult& outResult) override final;
 
index e756e75..4ac8dd3 100644 (file)
@@ -599,6 +599,13 @@ void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBRe
     }
 
     error = m_backingStore->addRecord(transactionIdentifier, objectStoreIdentifier, usedKey, injectedRecordValue.data() ? injectedRecordValue : originalRecordValue);
+    if (!error.isNull()) {
+        m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
+        return;
+    }
+
+    if (overwriteMode != IndexedDB::ObjectStoreOverwriteMode::OverwriteForCursor && objectStoreInfo->autoIncrement() && keyData.type() == IndexedDB::KeyType::Number)
+        error = m_backingStore->maybeUpdateKeyGeneratorNumber(transactionIdentifier, objectStoreIdentifier, keyData.number());
 
     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
 }