⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 243807 in webkit


Ignore:
Timestamp:
Apr 3, 2019, 10:03:59 AM (7 years ago)
Author:
sihui_liu@apple.com
Message:

Blob type cannot be stored correctly in IDB when IDBObjectStore has autoIncrement and keyPath options
https://bugs.webkit.org/show_bug.cgi?id=196128

Reviewed by Geoffrey Garen.

LayoutTests/imported/w3c:

Updated test expectations to PASS.

  • web-platform-tests/IndexedDB/nested-cloning-large-expected.txt:
  • web-platform-tests/IndexedDB/nested-cloning-large-multiple-expected.txt:
  • web-platform-tests/IndexedDB/nested-cloning-small-expected.txt:

Source/WebCore:

If a key is auto-generated, it should become a property of the value object. Network process would perform the
key injection by deserializing IDBValue into script value, setting the property, serializing the result and
storing it in a database record. But network process does not have a JSDOMGlobalObject, so it would fail to
deserialize types including Blob and File.

To solve this issue, we move the key injection to web process and let network process store the original value
it gets. In this case, when web process asks for some value, network process should return key, value and key
path so that web process can decide whether it should perform a key injection before returning the result. Note
that the auto-generated key would always be stored as the key in a ObjectStore record.

Test: storage/indexeddb/modern/objectstore-autoincrement-types.html

  • Modules/indexeddb/IDBCursor.cpp:

(WebCore::IDBCursor::setGetResult):

  • Modules/indexeddb/IDBCursor.h:

(WebCore::IDBCursor::primaryKeyPath):

  • Modules/indexeddb/IDBGetAllResult.cpp:

(WebCore::IDBGetAllResult::isolatedCopy):
(WebCore::IDBGetAllResult::addKey):
(WebCore::IDBGetAllResult::addValue):
(WebCore::IDBGetAllResult::keys const):
(WebCore::IDBGetAllResult::values const):
(WebCore::IDBGetAllResult::allBlobFilePaths const):
(WebCore::isolatedCopyOfVariant): Deleted.

  • Modules/indexeddb/IDBGetAllResult.h: Introduce an IDBKeyPath parameter. Also replace Variant with two Vectors,

because we only needed to store either key or value before, and now the stored value could be incomplete.
(WebCore::IDBGetAllResult::IDBGetAllResult):
(WebCore::IDBGetAllResult::keyPath const):
(WebCore::IDBGetAllResult::encode const):
(WebCore::IDBGetAllResult::decode):

  • Modules/indexeddb/IDBGetResult.cpp:

(WebCore::IDBGetResult::setValue):

  • Modules/indexeddb/IDBGetResult.h:

(WebCore::IDBGetResult::IDBGetResult):
(WebCore::IDBGetResult::keyPath const):

  • Modules/indexeddb/IDBObjectStore.cpp:
  • Modules/indexeddb/IDBRequest.cpp:

(WebCore::IDBRequest::setResult):
(WebCore::IDBRequest::setResultToStructuredClone):

  • Modules/indexeddb/IDBRequest.h:
  • Modules/indexeddb/IDBTransaction.cpp:

(WebCore::IDBTransaction::didGetAllRecordsOnServer):
(WebCore::IDBTransaction::didGetRecordOnServer):

  • Modules/indexeddb/server/MemoryIDBBackingStore.cpp:

(WebCore::IDBServer::MemoryIDBBackingStore::getRecord):

  • Modules/indexeddb/server/MemoryIndex.cpp:

(WebCore::IDBServer::MemoryIndex::getResultForKeyRange const):
(WebCore::IDBServer::MemoryIndex::getAllRecords const):

  • Modules/indexeddb/server/MemoryIndexCursor.cpp:

(WebCore::IDBServer::MemoryIndexCursor::currentData):

  • Modules/indexeddb/server/MemoryObjectStore.cpp:

(WebCore::IDBServer::MemoryObjectStore::updateIndexesForPutRecord):
(WebCore::IDBServer::MemoryObjectStore::populateIndexWithExistingRecords):
(WebCore::IDBServer::MemoryObjectStore::getAllRecords const):

  • Modules/indexeddb/server/MemoryObjectStoreCursor.cpp:

(WebCore::IDBServer::MemoryObjectStoreCursor::currentData):

  • Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:

(WebCore::IDBServer::SQLiteIDBBackingStore::updateOneIndexForAddRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::updateAllIndexesForAddRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::getRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords):
(WebCore::IDBServer::SQLiteIDBBackingStore::getAllObjectStoreRecords):
(WebCore::IDBServer::SQLiteIDBBackingStore::getAllIndexRecords):
(WebCore::IDBServer::SQLiteIDBBackingStore::getIndexRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedGetIndexRecordForOneKey):
(WebCore::IDBServer::SQLiteIDBBackingStore::openCursor):
(WebCore::IDBServer::SQLiteIDBBackingStore::iterateCursor):

  • Modules/indexeddb/server/SQLiteIDBCursor.cpp:

(WebCore::IDBServer::SQLiteIDBCursor::currentData):

  • Modules/indexeddb/server/SQLiteIDBCursor.h:
  • Modules/indexeddb/server/UniqueIDBDatabase.cpp:

(WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd): Remove the key injection from network process.
UniqueIDBDatabase stores any value it gets from IDBClient.

  • Modules/indexeddb/shared/IDBResultData.cpp:

(WebCore::IDBResultData::getResultRef):

  • Modules/indexeddb/shared/IDBResultData.h:
  • bindings/js/IDBBindingUtilities.cpp:

(WebCore::injectIDBKeyIntoScriptValue): If property is read-only, set would fail and injectKeyIntoResult would
return null, but we expect it to return result as long as the property value is the same as target. Therefore,
we can add an early return here.
(WebCore::createKeyPathArray):

(WebCore::generateIndexKeyForValue): We used to generate IndexKey from value stored in database but now the
value gets stored does not include auto-generated key, as we remove the key injection from network process. In
this case if the IDBIndex has the same key path as the auto-generated key, IndexKey would be failed to create
for it cannot extract auto-generated key from value. Since the auto-generated key would always be the key in
database record, we could use value of that key when we find a match in key path.

(WebCore::deserializeIDBValueWithKeyInjection): If the key path in the result is single entry, the key is
probably auto-generated, so we could inject the result key into the result value unconditionally.

  • bindings/js/IDBBindingUtilities.h:
  • bindings/js/JSIDBCursorWithValueCustom.cpp:

(WebCore::JSIDBCursorWithValue::value const):

  • bindings/js/JSIDBRequestCustom.cpp:

(WebCore::JSIDBRequest::result const):

LayoutTests:

  • TestExpectations:
  • storage/indexeddb/modern/objectstore-autoincrement-types-expected.txt: Added.
  • storage/indexeddb/modern/objectstore-autoincrement-types.html: Added.
  • storage/indexeddb/modern/resources/objectstore-autoincrement-types.js: Added.

(next):
(prepareDatabase.event.target.onsuccess):
(prepareDatabase):
(testSteps):

Location:
trunk
Files:
3 added
31 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r243806 r243807  
     12019-04-03  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Blob type cannot be stored correctly in IDB when IDBObjectStore has autoIncrement and keyPath options
     4        https://bugs.webkit.org/show_bug.cgi?id=196128
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * TestExpectations:
     9        * storage/indexeddb/modern/objectstore-autoincrement-types-expected.txt: Added.
     10        * storage/indexeddb/modern/objectstore-autoincrement-types.html: Added.
     11        * storage/indexeddb/modern/resources/objectstore-autoincrement-types.js: Added.
     12        (next):
     13        (prepareDatabase.event.target.onsuccess):
     14        (prepareDatabase):
     15        (testSteps):
     16
    1172019-04-03  Youenn Fablet  <youenn@apple.com>
    218
  • trunk/LayoutTests/TestExpectations

    r243765 r243807  
    359359webkit.org/b/179611 imported/w3c/web-platform-tests/xhr/send-entity-body-document.htm [ Pass Failure ]
    360360imported/w3c/web-platform-tests/IndexedDB/nested-cloning-large-multiple.html [ Skip ]
    361 imported/w3c/web-platform-tests/IndexedDB/nested-cloning-large.html [ Skip ]
    362 imported/w3c/web-platform-tests/IndexedDB/nested-cloning-small.html [ Skip ]
    363361imported/w3c/web-platform-tests/css/cssom/interfaces.html [ Pass Timeout ]
    364362[ Debug ] imported/w3c/web-platform-tests/css/cssom-view/interfaces.html [ Skip ]
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r243782 r243807  
     12019-04-03  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Blob type cannot be stored correctly in IDB when IDBObjectStore has autoIncrement and keyPath options
     4        https://bugs.webkit.org/show_bug.cgi?id=196128
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Updated test expectations to PASS.
     9
     10        * web-platform-tests/IndexedDB/nested-cloning-large-expected.txt:
     11        * web-platform-tests/IndexedDB/nested-cloning-large-multiple-expected.txt:
     12        * web-platform-tests/IndexedDB/nested-cloning-small-expected.txt:
     13
    1142019-04-02  Chris Dumez  <cdumez@apple.com>
    215
  • trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/nested-cloning-large-expected.txt

    r222307 r243807  
    22PASS large typed array
    33PASS blob with large typed array
    4 FAIL blob with large typed array with key generator assert_equals: IndexedDB result class should match put() argument expected "[object Blob]" but got "[object Null]"
     4PASS blob with large typed array with key generator
    55PASS array of blobs and large typed arrays
    6 FAIL array of blobs and large typed arrays with key generator assert_equals: IndexedDB result class should match put() argument expected "[object Blob]" but got "[object Null]"
     6PASS array of blobs and large typed arrays with key generator
    77PASS object with blobs and large typed arrays
    8 FAIL object with blobs and large typed arrays with key generator assert_equals: IndexedDB result class should match put() argument expected "[object Blob]" but got "[object Null]"
     8PASS object with blobs and large typed arrays with key generator
    99
  • trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/nested-cloning-large-multiple-expected.txt

    r222362 r243807  
    11
    22PASS multiple requests of objects with blobs and large typed arrays
    3 FAIL multiple requests of objects with blobs and large typed arrays with key generator assert_equals: IndexedDB result class should match put() argument expected "[object Blob]" but got "[object Null]"
     3PASS multiple requests of objects with blobs and large typed arrays with key generator
    44
  • trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/nested-cloning-small-expected.txt

    r222307 r243807  
    33PASS blob
    44PASS blob with small typed array
    5 FAIL blob with small typed array with key generator assert_equals: IndexedDB result class should match put() argument expected "[object Blob]" but got "[object Null]"
     5PASS blob with small typed array with key generator
    66PASS blob array
    7 FAIL blob array with key generator assert_equals: IndexedDB result class should match put() argument expected "[object Blob]" but got "[object Null]"
     7PASS blob array with key generator
    88PASS array of blobs and small typed arrays
    9 FAIL array of blobs and small typed arrays with key generator assert_equals: IndexedDB result class should match put() argument expected "[object Blob]" but got "[object Null]"
     9PASS array of blobs and small typed arrays with key generator
    1010
  • trunk/Source/WebCore/ChangeLog

    r243804 r243807  
     12019-04-03  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Blob type cannot be stored correctly in IDB when IDBObjectStore has autoIncrement and keyPath options
     4        https://bugs.webkit.org/show_bug.cgi?id=196128
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        If a key is auto-generated, it should become a property of the value object. Network process would perform the
     9        key injection by deserializing IDBValue into script value, setting the property, serializing the result and
     10        storing it in a database record. But network process does not have a JSDOMGlobalObject, so it would fail to
     11        deserialize types including Blob and File.
     12
     13        To solve this issue, we move the key injection to web process and let network process store the original value
     14        it gets. In this case, when web process asks for some value, network process should return key, value and key
     15        path so that web process can decide whether it should perform a key injection before returning the result. Note
     16        that the auto-generated key would always be stored as the key in a ObjectStore record.
     17
     18        Test: storage/indexeddb/modern/objectstore-autoincrement-types.html
     19
     20        * Modules/indexeddb/IDBCursor.cpp:
     21        (WebCore::IDBCursor::setGetResult):
     22        * Modules/indexeddb/IDBCursor.h:
     23        (WebCore::IDBCursor::primaryKeyPath):
     24        * Modules/indexeddb/IDBGetAllResult.cpp:
     25        (WebCore::IDBGetAllResult::isolatedCopy):
     26        (WebCore::IDBGetAllResult::addKey):
     27        (WebCore::IDBGetAllResult::addValue):
     28        (WebCore::IDBGetAllResult::keys const):
     29        (WebCore::IDBGetAllResult::values const):
     30        (WebCore::IDBGetAllResult::allBlobFilePaths const):
     31        (WebCore::isolatedCopyOfVariant): Deleted.
     32
     33        * Modules/indexeddb/IDBGetAllResult.h: Introduce an IDBKeyPath parameter. Also replace Variant with two Vectors,
     34        because we only needed to store either key or value before, and now the stored value could be incomplete.
     35        (WebCore::IDBGetAllResult::IDBGetAllResult):
     36        (WebCore::IDBGetAllResult::keyPath const):
     37        (WebCore::IDBGetAllResult::encode const):
     38        (WebCore::IDBGetAllResult::decode):
     39
     40        * Modules/indexeddb/IDBGetResult.cpp:
     41        (WebCore::IDBGetResult::setValue):
     42        * Modules/indexeddb/IDBGetResult.h:
     43        (WebCore::IDBGetResult::IDBGetResult):
     44        (WebCore::IDBGetResult::keyPath const):
     45        * Modules/indexeddb/IDBObjectStore.cpp:
     46        * Modules/indexeddb/IDBRequest.cpp:
     47        (WebCore::IDBRequest::setResult):
     48        (WebCore::IDBRequest::setResultToStructuredClone):
     49        * Modules/indexeddb/IDBRequest.h:
     50        * Modules/indexeddb/IDBTransaction.cpp:
     51        (WebCore::IDBTransaction::didGetAllRecordsOnServer):
     52        (WebCore::IDBTransaction::didGetRecordOnServer):
     53        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
     54        (WebCore::IDBServer::MemoryIDBBackingStore::getRecord):
     55        * Modules/indexeddb/server/MemoryIndex.cpp:
     56        (WebCore::IDBServer::MemoryIndex::getResultForKeyRange const):
     57        (WebCore::IDBServer::MemoryIndex::getAllRecords const):
     58        * Modules/indexeddb/server/MemoryIndexCursor.cpp:
     59        (WebCore::IDBServer::MemoryIndexCursor::currentData):
     60        * Modules/indexeddb/server/MemoryObjectStore.cpp:
     61        (WebCore::IDBServer::MemoryObjectStore::updateIndexesForPutRecord):
     62        (WebCore::IDBServer::MemoryObjectStore::populateIndexWithExistingRecords):
     63        (WebCore::IDBServer::MemoryObjectStore::getAllRecords const):
     64        * Modules/indexeddb/server/MemoryObjectStoreCursor.cpp:
     65        (WebCore::IDBServer::MemoryObjectStoreCursor::currentData):
     66        * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
     67        (WebCore::IDBServer::SQLiteIDBBackingStore::updateOneIndexForAddRecord):
     68        (WebCore::IDBServer::SQLiteIDBBackingStore::updateAllIndexesForAddRecord):
     69        (WebCore::IDBServer::SQLiteIDBBackingStore::getRecord):
     70        (WebCore::IDBServer::SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords):
     71        (WebCore::IDBServer::SQLiteIDBBackingStore::getAllObjectStoreRecords):
     72        (WebCore::IDBServer::SQLiteIDBBackingStore::getAllIndexRecords):
     73        (WebCore::IDBServer::SQLiteIDBBackingStore::getIndexRecord):
     74        (WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedGetIndexRecordForOneKey):
     75        (WebCore::IDBServer::SQLiteIDBBackingStore::openCursor):
     76        (WebCore::IDBServer::SQLiteIDBBackingStore::iterateCursor):
     77        * Modules/indexeddb/server/SQLiteIDBCursor.cpp:
     78        (WebCore::IDBServer::SQLiteIDBCursor::currentData):
     79        * Modules/indexeddb/server/SQLiteIDBCursor.h:
     80
     81        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
     82        (WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd): Remove the key injection from network process.
     83        UniqueIDBDatabase stores any value it gets from IDBClient.
     84
     85        * Modules/indexeddb/shared/IDBResultData.cpp:
     86        (WebCore::IDBResultData::getResultRef):
     87        * Modules/indexeddb/shared/IDBResultData.h:
     88
     89        * bindings/js/IDBBindingUtilities.cpp:
     90        (WebCore::injectIDBKeyIntoScriptValue): If property is read-only, set would fail and injectKeyIntoResult would
     91        return null, but we expect it to return result as long as the property value is the same as target. Therefore,
     92        we can add an early return here.
     93        (WebCore::createKeyPathArray):
     94
     95        (WebCore::generateIndexKeyForValue): We used to generate IndexKey from value stored in database but now the
     96        value gets stored does not include auto-generated key, as we remove the key injection from network process. In
     97        this case if the IDBIndex has the same key path as the auto-generated key, IndexKey would be failed to create
     98        for it cannot extract auto-generated key from value. Since the auto-generated key would always be the key in
     99        database record, we could use value of that key when we find a match in key path.
     100
     101        (WebCore::deserializeIDBValueWithKeyInjection): If the key path in the result is single entry, the key is
     102        probably auto-generated, so we could inject the result key into the result value unconditionally.
     103
     104        * bindings/js/IDBBindingUtilities.h:
     105        * bindings/js/JSIDBCursorWithValueCustom.cpp:
     106        (WebCore::JSIDBCursorWithValue::value const):
     107        * bindings/js/JSIDBRequestCustom.cpp:
     108        (WebCore::JSIDBRequest::result const):
     109
    11102019-04-03  Michael Catanzaro  <mcatanzaro@igalia.com>
    2111
  • trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp

    r243163 r243807  
    342342    m_primaryKey = m_primaryKeyData.maybeCreateIDBKey();
    343343
    344     if (isKeyCursorWithValue())
     344    if (isKeyCursorWithValue()) {
    345345        m_value = getResult.value();
     346        m_keyPath = getResult.keyPath();
     347    }
    346348
    347349    m_gotValue = true;
  • trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h

    r242986 r243807  
    3131#include "IDBCursorDirection.h"
    3232#include "IDBCursorInfo.h"
     33#include "IDBKeyPath.h"
    3334#include "IDBValue.h"
    3435#include "JSValueInWrappedObject.h"
     
    5960    IDBKey* primaryKey() { return m_primaryKey.get(); };
    6061    IDBValue value() { return m_value; };
     62    const Optional<IDBKeyPath>& primaryKeyPath() { return m_keyPath; };
    6163    JSValueInWrappedObject& keyWrapper() { return m_keyWrapper; }
    6264    JSValueInWrappedObject& primaryKeyWrapper() { return m_primaryKeyWrapper; }
     
    105107    IDBKeyData m_primaryKeyData;
    106108    IDBValue m_value;
     109    Optional<IDBKeyPath> m_keyPath;
    107110
    108111    JSValueInWrappedObject m_keyWrapper;
  • trunk/Source/WebCore/Modules/indexeddb/IDBGetAllResult.cpp

    r223238 r243807  
    2929#if ENABLE(INDEXED_DATABASE)
    3030
     31#include <wtf/CrossThreadCopier.h>
    3132#include <wtf/HashSet.h>
    3233
    3334namespace WebCore {
    34 
    35 template<typename T> void isolatedCopyOfVariant(const WTF::Variant<Vector<IDBKeyData>, Vector<IDBValue>, std::nullptr_t>& source, WTF::Variant<Vector<IDBKeyData>, Vector<IDBValue>, std::nullptr_t>& target)
    36 {
    37     target = Vector<T>();
    38     auto& sourceVector = WTF::get<Vector<T>>(source);
    39     auto& targetVector = WTF::get<Vector<T>>(target);
    40     targetVector.reserveInitialCapacity(sourceVector.size());
    41     for (auto& element : sourceVector)
    42         targetVector.uncheckedAppend(element.isolatedCopy());
    43 }
    4435
    4536IDBGetAllResult::IDBGetAllResult(const IDBGetAllResult& that, IsolatedCopyTag)
     
    5647{
    5748    destination.m_type = source.m_type;
    58 
    59     if (WTF::holds_alternative<std::nullptr_t>(source.m_results))
    60         return;
    61 
    62     switch (source.m_type) {
    63     case IndexedDB::GetAllType::Keys:
    64         isolatedCopyOfVariant<IDBKeyData>(source.m_results, destination.m_results);
    65         break;
    66     case IndexedDB::GetAllType::Values:
    67         isolatedCopyOfVariant<IDBValue>(source.m_results, destination.m_results);
    68         break;
    69     }
     49    destination.m_keys = crossThreadCopy(source.m_keys);
     50    destination.m_values = crossThreadCopy(source.m_values);
     51    destination.m_keyPath = WebCore::isolatedCopy(source.m_keyPath);
    7052}
    7153
    7254void IDBGetAllResult::addKey(IDBKeyData&& key)
    7355{
    74     ASSERT(m_type == IndexedDB::GetAllType::Keys);
    75     ASSERT(WTF::holds_alternative<Vector<IDBKeyData>>(m_results));
    76     WTF::get<Vector<IDBKeyData>>(m_results).append(WTFMove(key));
     56    m_keys.append(WTFMove(key));
    7757}
    7858
    7959void IDBGetAllResult::addValue(IDBValue&& value)
    8060{
    81     ASSERT(m_type == IndexedDB::GetAllType::Values);
    82     ASSERT(WTF::holds_alternative<Vector<IDBValue>>(m_results));
    83     WTF::get<Vector<IDBValue>>(m_results).append(WTFMove(value));
     61    m_values.append(WTFMove(value));
    8462}
    8563
    8664const Vector<IDBKeyData>& IDBGetAllResult::keys() const
    8765{
    88     ASSERT(m_type == IndexedDB::GetAllType::Keys);
    89     ASSERT(WTF::holds_alternative<Vector<IDBKeyData>>(m_results));
    90     return WTF::get<Vector<IDBKeyData>>(m_results);
     66    return m_keys;
    9167}
    9268
    9369const Vector<IDBValue>& IDBGetAllResult::values() const
    9470{
    95     ASSERT(m_type == IndexedDB::GetAllType::Values);
    96     ASSERT(WTF::holds_alternative<Vector<IDBValue>>(m_results));
    97     return WTF::get<Vector<IDBValue>>(m_results);
     71    return m_values;
    9872}
    9973
     
    10377
    10478    HashSet<String> pathSet;
    105     for (auto& value : WTF::get<Vector<IDBValue>>(m_results)) {
     79    for (auto& value : m_values) {
    10680        for (auto& path : value.blobFilePaths())
    10781            pathSet.add(path);
  • trunk/Source/WebCore/Modules/indexeddb/IDBGetAllResult.h

    r241183 r243807  
    2929
    3030#include "IDBKeyData.h"
     31#include "IDBKeyPath.h"
    3132#include "IDBValue.h"
    3233#include "IndexedDB.h"
     
    4344    }
    4445
    45     IDBGetAllResult(IndexedDB::GetAllType type)
     46    IDBGetAllResult(IndexedDB::GetAllType type, const Optional<IDBKeyPath>& keyPath)
    4647        : m_type(type)
     48        , m_keyPath(keyPath)
    4749    {
    48         switch (m_type) {
    49         case IndexedDB::GetAllType::Keys:
    50             m_results = Vector<IDBKeyData>();
    51             break;
    52         case IndexedDB::GetAllType::Values:
    53             m_results = Vector<IDBValue>();
    54             break;
    55         }
    5650    }
    5751
     
    6155
    6256    IndexedDB::GetAllType type() const { return m_type; }
     57    const Optional<IDBKeyPath>& keyPath() const { return m_keyPath; }
    6358    const Vector<IDBKeyData>& keys() const;
    6459    const Vector<IDBValue>& values() const;
     
    7671
    7772    IndexedDB::GetAllType m_type { IndexedDB::GetAllType::Keys };
    78     WTF::Variant<Vector<IDBKeyData>, Vector<IDBValue>, std::nullptr_t> m_results { nullptr };
     73    Vector<IDBKeyData> m_keys;
     74    Vector<IDBValue> m_values;
     75    Optional<IDBKeyPath> m_keyPath;
    7976};
    8077
     
    8279void IDBGetAllResult::encode(Encoder& encoder) const
    8380{
    84     encoder << m_type << static_cast<uint64_t>(m_results.index());
    85 
    86     switch (m_results.index()) {
    87     case 0:
    88         encoder << WTF::get<Vector<IDBKeyData>>(m_results);
    89         break;
    90     case 1:
    91         encoder << WTF::get<Vector<IDBValue>>(m_results);
    92         break;
    93     case 2:
    94         break;
    95     default:
    96         RELEASE_ASSERT_NOT_REACHED();
    97     }
     81    encoder << m_type << m_keys << m_values << m_keyPath;
    9882}
    9983
     
    10488        return false;
    10589
    106     uint64_t index;
    107     if (!decoder.decode(index))
     90    if (!decoder.decode(result.m_keys))
    10891        return false;
    10992
    110     switch (index) {
    111     case 0: {
    112         result.m_results = Vector<IDBKeyData>();
    113         if (!decoder.decode(WTF::get<Vector<IDBKeyData>>(result.m_results)))
    114             return false;
    115         break;
    116     }
    117     case 1: {
    118         result.m_results = Vector<IDBValue>();
    119         Optional<Vector<IDBValue>> optional;
    120         decoder >> optional;
    121         if (!optional)
    122             return false;
    123         WTF::get<Vector<IDBValue>>(result.m_results) = WTFMove(*optional);
    124         break;
    125     }
    126     case 2:
    127         result.m_results = nullptr;
    128         break;
    129     default:
    130         RELEASE_ASSERT_NOT_REACHED();
    131     }
     93    if (!decoder.decode(result.m_values))
     94        return false;
     95   
     96    if (!decoder.decode(result.m_keyPath))
     97        return false;
    13298
    13399    return true;
  • trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.cpp

    r215262 r243807  
    5858}
    5959
     60void IDBGetResult::setValue(IDBValue&& value)
     61{
     62    m_value = WTFMove(value);
     63}
     64
    6065} // namespace WebCore
    6166
  • trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.h

    r241183 r243807  
    4444    }
    4545
    46     IDBGetResult(const IDBValue& value, const IDBKeyData& currentPrimaryKey)
    47         : m_value(value)
    48         , m_primaryKeyData(currentPrimaryKey)
    49     {
    50     }
    51 
    52     IDBGetResult(const ThreadSafeDataBuffer& buffer)
    53         : m_value(buffer)
    54     {
    55     }
    56 
    57     IDBGetResult(IDBValue&& buffer)
    58         : m_value(WTFMove(buffer))
    59     {
    60     }
    61 
    62     IDBGetResult(IDBKey& key)
    63         : m_keyData(&key)
    64     {
    65     }
    66 
    6746    IDBGetResult(const IDBKeyData& keyData)
    6847        : m_keyData(keyData)
    6948    {
    70     }
    71 
    72     IDBGetResult(SharedBuffer* buffer, IDBKey& key, const IDBKeyPath& path)
    73         : m_keyData(&key)
    74         , m_keyPath(path)
    75     {
    76         if (buffer)
    77             dataFromBuffer(*buffer);
    7849    }
    7950
     
    8455    }
    8556
    86     IDBGetResult(const IDBKeyData& keyData, const IDBKeyData& primaryKeyData, IDBValue&& value)
     57    IDBGetResult(const IDBKeyData& keyData, const ThreadSafeDataBuffer& buffer, const Optional<IDBKeyPath>& keyPath)
     58        : m_value(buffer)
     59        , m_keyData(keyData)
     60        , m_keyPath(keyPath)
     61    {
     62    }
     63
     64    IDBGetResult(const IDBKeyData& keyData, IDBValue&& value, const Optional<IDBKeyPath>& keyPath)
     65        : m_value(WTFMove(value))
     66        , m_keyData(keyData)
     67        , m_keyPath(keyPath)
     68    {
     69    }
     70
     71    IDBGetResult(const IDBKeyData& keyData, const IDBKeyData& primaryKeyData, IDBValue&& value, const Optional<IDBKeyPath>& keyPath)
    8772        : m_value(WTFMove(value))
    8873        , m_keyData(keyData)
    8974        , m_primaryKeyData(primaryKeyData)
    90     {
    91     }
    92 
    93     IDBGetResult(const IDBKeyData& keyData, const IDBKeyData& primaryKeyData, const IDBValue& value)
    94         : m_value(value)
    95         , m_keyData(keyData)
    96         , m_primaryKeyData(primaryKeyData)
     75        , m_keyPath(keyPath)
    9776    {
    9877    }
     
    10382    IDBGetResult isolatedCopy() const;
    10483
     84    void setValue(IDBValue&&);
     85
    10586    const IDBValue& value() const { return m_value; }
    10687    const IDBKeyData& keyData() const { return m_keyData; }
    10788    const IDBKeyData& primaryKeyData() const { return m_primaryKeyData; }
    108     const IDBKeyPath& keyPath() const { return m_keyPath; }
     89    const Optional<IDBKeyPath>& keyPath() const { return m_keyPath; }
    10990    bool isDefined() const { return m_isDefined; }
    11091
     
    120101    IDBKeyData m_keyData;
    121102    IDBKeyData m_primaryKeyData;
    122     IDBKeyPath m_keyPath;
     103    Optional<IDBKeyPath> m_keyPath;
    123104    bool m_isDefined { true };
    124105};
  • trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp

    r243622 r243807  
    392392}
    393393
    394 void IDBRequest::setResult(const Vector<IDBValue>& values)
    395 {
    396     ASSERT(&originThread() == &Thread::current());
    397 
    398     auto* context = scriptExecutionContext();
    399     if (!context)
    400         return;
    401 
    402     VM& vm = context->vm();
    403     JSLockHolder lock(vm);
    404     m_result = values;
     394void IDBRequest::setResult(const IDBGetAllResult& result)
     395{
     396    ASSERT(&originThread() == &Thread::current());
     397
     398    auto* context = scriptExecutionContext();
     399    if (!context)
     400        return;
     401
     402    VM& vm = context->vm();
     403    JSLockHolder lock(vm);
     404    m_result = result;
    405405    m_resultWrapper = { };
    406406}
     
    420420}
    421421
    422 void IDBRequest::setResultToStructuredClone(const IDBValue& value)
     422void IDBRequest::setResultToStructuredClone(const IDBGetResult& result)
    423423{
    424424    ASSERT(&originThread() == &Thread::current());
     
    432432    VM& vm = context->vm();
    433433    JSLockHolder lock(vm);
    434     m_result = value;
     434    m_result = result;
    435435    m_resultWrapper = { };
    436436}
  • trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h

    r242986 r243807  
    3232#include "IDBActiveDOMObject.h"
    3333#include "IDBError.h"
     34#include "IDBGetAllResult.h"
     35#include "IDBGetResult.h"
    3436#include "IDBKeyData.h"
    3537#include "IDBResourceIdentifier.h"
     
    7678    virtual ~IDBRequest();
    7779
    78     using Result = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, IDBKeyData, Vector<IDBKeyData>, IDBValue, Vector<IDBValue>, uint64_t, NullResultType>;
     80    using Result = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, IDBKeyData, Vector<IDBKeyData>, IDBGetResult, IDBGetAllResult, uint64_t, NullResultType>;
    7981    ExceptionOr<Result> result() const;
    8082    JSValueInWrappedObject& resultWrapper() { return m_resultWrapper; }
     
    107109    void setResult(const IDBKeyData&);
    108110    void setResult(const Vector<IDBKeyData>&);
    109     void setResult(const Vector<IDBValue>&);
     111    void setResultToStructuredClone(const IDBGetResult&);
     112    void setResult(const IDBGetAllResult&);
    110113    void setResult(uint64_t);
    111     void setResultToStructuredClone(const IDBValue&);
    112114    void setResultToUndefined();
    113115
  • trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp

    r242110 r243807  
    987987        break;
    988988    case IndexedDB::GetAllType::Values:
    989         request.setResult(getAllResult.values());
     989        request.setResult(getAllResult);
    990990        break;
    991991    }
     
    10911091    } else {
    10921092        if (resultData.getResult().value().data().data())
    1093             request.setResultToStructuredClone(resultData.getResult().value());
     1093            request.setResultToStructuredClone(resultData.getResult());
    10941094        else
    10951095            request.setResultToUndefined();
  • trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp

    r242911 r243807  
    364364
    365365    switch (type) {
    366     case IDBGetRecordDataType::KeyAndValue:
    367         outValue = objectStore->valueForKeyRange(range);
     366    case IDBGetRecordDataType::KeyAndValue: {
     367        auto key = objectStore->lowestKeyWithRecordInRange(range);
     368        outValue = { key, key.isNull() ? ThreadSafeDataBuffer() : objectStore->valueForKey(key), objectStore->info().keyPath() };
    368369        break;
     370    }
    369371    case IDBGetRecordDataType::KeyOnly:
    370372        outValue = objectStore->lowestKeyWithRecordInRange(range);
  • trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp

    r239427 r243807  
    127127        return { };
    128128
    129     return type == IndexedDB::IndexRecordType::Key ? IDBGetResult(*keyValue) : IDBGetResult(m_objectStore.valueForKeyRange(*keyValue));
     129    return type == IndexedDB::IndexRecordType::Key ? IDBGetResult(*keyValue) : IDBGetResult(*keyValue, m_objectStore.valueForKeyRange(*keyValue), m_objectStore.info().keyPath());
    130130}
    131131
     
    157157    LOG(IndexedDB, "MemoryIndex::getAllRecords");
    158158
    159     result = { type };
     159    result = { type, m_objectStore.info().keyPath() };
    160160
    161161    if (!m_records)
     
    180180        auto allValues = m_records->allValuesForKey(key, targetCount - currentCount);
    181181        for (auto& keyValue : allValues) {
    182             if (type == IndexedDB::GetAllType::Keys) {
    183                 IDBKeyData keyCopy { keyValue };
    184                 result.addKey(WTFMove(keyCopy));
    185             } else
     182            result.addKey(IDBKeyData(keyValue));
     183            if (type == IndexedDB::GetAllType::Values)
    186184                result.addValue(m_objectStore.valueForKeyRange(keyValue));
    187185        }
  • trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.cpp

    r238632 r243807  
    7676    else {
    7777        IDBValue value = { m_index.objectStore().valueForKey(m_currentPrimaryKey), { }, { }, { } };
    78         getResult = { m_currentKey, m_currentPrimaryKey, WTFMove(value) };
     78        getResult = { m_currentKey, m_currentPrimaryKey, WTFMove(value), m_index.objectStore().info().keyPath() };
    7979    }
    8080}
  • trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp

    r239427 r243807  
    311311    for (auto& index : m_indexesByName.values()) {
    312312        IndexKey indexKey;
    313         generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index->info(), jsValue, indexKey);
     313        generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index->info(), jsValue, indexKey, m_info.keyPath(), key);
    314314
    315315        if (indexKey.isNull())
     
    345345
    346346        IndexKey indexKey;
    347         generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index.info(), jsValue, indexKey);
     347        generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index.info(), jsValue, indexKey, m_info.keyPath(), iterator.key);
    348348
    349349        if (indexKey.isNull())
     
    408408void MemoryObjectStore::getAllRecords(const IDBKeyRangeData& keyRangeData, Optional<uint32_t> count, IndexedDB::GetAllType type, IDBGetAllResult& result) const
    409409{
    410     result = { type };
     410    result = { type, m_info.keyPath() };
    411411
    412412    uint32_t targetCount;
     
    425425        range.lowerKey = key;
    426426        range.lowerOpen = true;
    427 
    428         if (type == IndexedDB::GetAllType::Keys)
    429             result.addKey(WTFMove(key));
    430         else
     427        if (type == IndexedDB::GetAllType::Values)
    431428            result.addValue(valueForKey(key));
     429        result.addKey(WTFMove(key));
    432430
    433431        ++currentCount;
  • trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.cpp

    r239427 r243807  
    195195    else {
    196196        IDBValue value = { m_objectStore.valueForKeyRange(m_currentPositionKey), { }, { }, { } };
    197         data = { m_currentPositionKey, m_currentPositionKey, WTFMove(value) };
     197        data = { m_currentPositionKey, m_currentPositionKey, WTFMove(value), m_objectStore.info().keyPath() };
    198198    }
    199199}
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp

    r243615 r243807  
    3030
    3131#include "IDBBindingUtilities.h"
     32#include "IDBCursorInfo.h"
    3233#include "IDBGetAllRecordsData.h"
    3334#include "IDBGetAllResult.h"
     
    17531754
    17541755    IndexKey indexKey;
    1755     generateIndexKeyForValue(*m_globalObject->globalExec(), info, jsValue, indexKey);
     1756    auto* objectStoreInfo = infoForObjectStore(info.objectStoreIdentifier());
     1757    ASSERT(objectStoreInfo);
     1758    generateIndexKeyForValue(*m_globalObject->globalExec(), info, jsValue, indexKey, objectStoreInfo->keyPath(), key);
    17561759
    17571760    if (indexKey.isNull())
     
    17731776    for (auto& index : info.indexMap().values()) {
    17741777        IndexKey indexKey;
    1775         generateIndexKeyForValue(*m_globalObject->globalExec(), index, jsValue, indexKey);
     1778        generateIndexKeyForValue(*m_globalObject->globalExec(), index, jsValue, indexKey, info.keyPath(), key);
    17761779
    17771780        if (indexKey.isNull())
     
    20052008
    20062009    int64_t recordID = 0;
    2007     ThreadSafeDataBuffer resultBuffer;
    2008     {
    2009         static const char* const lowerOpenUpperOpen = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
    2010         static const char* const lowerOpenUpperClosed = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
    2011         static const char* const lowerClosedUpperOpen = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
    2012         static const char* const lowerClosedUpperClosed = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
     2010    ThreadSafeDataBuffer keyResultBuffer, valueResultBuffer;
     2011    {
     2012        static const char* const lowerOpenUpperOpen = "SELECT key, value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
     2013        static const char* const lowerOpenUpperClosed = "SELECT key, value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
     2014        static const char* const lowerClosedUpperOpen = "SELECT key, value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
     2015        static const char* const lowerClosedUpperClosed = "SELECT key, value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
    20132016
    20142017        static const char* const lowerOpenUpperOpenKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
     
    20672070        }
    20682071
    2069         Vector<uint8_t> buffer;
    2070         sql->getColumnBlobAsVector(0, buffer);
    2071         resultBuffer = ThreadSafeDataBuffer::create(WTFMove(buffer));
    2072 
    2073         if (type == IDBGetRecordDataType::KeyAndValue)
    2074             recordID = sql->getColumnInt64(1);
     2072        Vector<uint8_t> keyBuffer;
     2073        sql->getColumnBlobAsVector(0, keyBuffer);
     2074        keyResultBuffer = ThreadSafeDataBuffer::create(WTFMove(keyBuffer));
     2075
     2076        if (type == IDBGetRecordDataType::KeyAndValue) {
     2077            Vector<uint8_t> valueBuffer;
     2078            sql->getColumnBlobAsVector(1, valueBuffer);
     2079            valueResultBuffer = ThreadSafeDataBuffer::create(WTFMove(valueBuffer));
     2080            recordID = sql->getColumnInt64(2);
     2081        }
     2082    }
     2083
     2084    auto* keyVector = keyResultBuffer.data();
     2085    if (!keyVector) {
     2086        LOG_ERROR("Unable to deserialize key data from database for IDBObjectStore");
     2087        return IDBError { UnknownError, "Error extracting key data from database executing IDBObjectStore get"_s };
     2088    }
     2089   
     2090    IDBKeyData keyData;
     2091    if (!deserializeIDBKeyData(keyVector->data(), keyVector->size(), keyData)) {
     2092        LOG_ERROR("Unable to deserialize key data from database for IDBObjectStore");
     2093        return IDBError { UnknownError, "Error extracting key data from database executing IDBObjectStore get"_s };
    20752094    }
    20762095
    20772096    if (type == IDBGetRecordDataType::KeyOnly) {
    2078         auto* vector = resultBuffer.data();
    2079         if (!vector) {
    2080             LOG_ERROR("Unable to deserialize key data from database for IDBObjectStore.getKey()");
    2081             return IDBError { UnknownError, "Error extracting key data from database executing IDBObjectStore.getKey()"_s };
    2082         }
    2083 
    2084         IDBKeyData keyData;
    2085         if (!deserializeIDBKeyData(vector->data(), vector->size(), keyData)) {
    2086             LOG_ERROR("Unable to deserialize key data from database for IDBObjectStore.getKey()");
    2087             return IDBError { UnknownError, "Error extracting key data from database executing IDBObjectStore.getKey()"_s };
    2088         }
    2089 
    20902097        resultValue = { keyData };
    20912098        return IDBError { };
     
    21012108        return error;
    21022109
    2103     resultValue = { { resultBuffer, WTFMove(blobURLs), sessionID, WTFMove(blobFilePaths) } };
     2110    auto* objectStoreInfo = infoForObjectStore(objectStoreID);
     2111    ASSERT(objectStoreInfo);
     2112    resultValue = { keyData, { valueResultBuffer, WTFMove(blobURLs), sessionID, WTFMove(blobFilePaths) }, objectStoreInfo->keyPath()};
    21042113    return IDBError { };
    21052114}
     
    21162125    static const char* const lowerClosedUpperOpenKey = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
    21172126    static const char* const lowerClosedUpperClosedKey = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
    2118     static const char* const lowerOpenUpperOpenValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
    2119     static const char* const lowerOpenUpperClosedValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
    2120     static const char* const lowerClosedUpperOpenValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
    2121     static const char* const lowerClosedUpperClosedValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
     2127    static const char* const lowerOpenUpperOpenValue = "SELECT key, value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
     2128    static const char* const lowerOpenUpperClosedValue = "SELECT key, value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
     2129    static const char* const lowerClosedUpperOpenValue = "SELECT key, value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
     2130    static const char* const lowerClosedUpperClosedValue = "SELECT key, value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
    21222131
    21232132    if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Keys) {
     
    21842193    }
    21852194
    2186     result = { getAllRecordsData.getAllType };
     2195    auto* objectStoreInfo = infoForObjectStore(getAllRecordsData.objectStoreIdentifier);
     2196    ASSERT(objectStoreInfo);
     2197    result = { getAllRecordsData.getAllType, objectStoreInfo->keyPath() };
    21872198
    21882199    uint32_t targetResults;
     
    21962207
    21972208    while (sqlResult == SQLITE_ROW && returnedResults < targetResults) {
     2209        Vector<uint8_t> keyBuffer;
     2210        IDBKeyData keyData;
     2211        sql->getColumnBlobAsVector(0, keyBuffer);
     2212        if (!deserializeIDBKeyData(keyBuffer.data(), keyBuffer.size(), keyData)) {
     2213            LOG_ERROR("Unable to deserialize key data from database while getting all records");
     2214            return IDBError { UnknownError, "Unable to deserialize key data while getting all records"_s };
     2215        }
     2216        result.addKey(WTFMove(keyData));
     2217
    21982218        if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Values) {
    2199             Vector<uint8_t> buffer;
    2200             sql->getColumnBlobAsVector(0, buffer);
    2201             ThreadSafeDataBuffer resultBuffer = ThreadSafeDataBuffer::create(WTFMove(buffer));
    2202 
    2203             auto recordID = sql->getColumnInt64(1);
     2219            Vector<uint8_t> valueBuffer;
     2220            sql->getColumnBlobAsVector(1, valueBuffer);
     2221            ThreadSafeDataBuffer valueResultBuffer = ThreadSafeDataBuffer::create(WTFMove(valueBuffer));
     2222
     2223            auto recordID = sql->getColumnInt64(2);
    22042224
    22052225            ASSERT(recordID);
     
    22122232                return error;
    22132233
    2214             result.addValue({ resultBuffer, WTFMove(blobURLs), sessionID, WTFMove(blobFilePaths) });
    2215         } else {
    2216             Vector<uint8_t> keyData;
    2217             IDBKeyData key;
    2218             sql->getColumnBlobAsVector(0, keyData);
    2219 
    2220             if (!deserializeIDBKeyData(keyData.data(), keyData.size(), key)) {
    2221                 LOG_ERROR("Unable to deserialize key data from database while getting all key records");
    2222                 return IDBError { UnknownError, "Unable to deserialize key data while getting all key records"_s };
    2223             }
    2224 
    2225             result.addKey(WTFMove(key));
     2234            result.addValue({ valueResultBuffer, WTFMove(blobURLs), sessionID, WTFMove(blobFilePaths) });
    22262235        }
    22272236
     
    22642273    }
    22652274
    2266     result = { getAllRecordsData.getAllType };
     2275    auto* objectStoreInfo = infoForObjectStore(getAllRecordsData.objectStoreIdentifier);
     2276    ASSERT(objectStoreInfo);
     2277    result = { getAllRecordsData.getAllType, objectStoreInfo->keyPath() };
     2278
    22672279    uint32_t currentCount = 0;
    22682280    uint32_t targetCount = getAllRecordsData.count ? getAllRecordsData.count.value() : 0;
     
    22702282        targetCount = std::numeric_limits<uint32_t>::max();
    22712283    while (!cursor->didComplete() && !cursor->didError() && currentCount < targetCount) {
    2272         if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Keys) {
    2273             IDBKeyData keyCopy = cursor->currentPrimaryKey();
    2274             result.addKey(WTFMove(keyCopy));
    2275         } else
     2284        IDBKeyData keyCopy = cursor->currentPrimaryKey();
     2285        result.addKey(WTFMove(keyCopy));
     2286        if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Values)
    22762287            result.addValue(cursor->currentValue() ? *cursor->currentValue() : IDBValue());
    22772288
     
    23202331        if (type == IndexedDB::IndexRecordType::Key)
    23212332            getResult = { cursor->currentPrimaryKey() };
    2322         else
    2323             getResult = { cursor->currentValue() ? *cursor->currentValue() : IDBValue(), cursor->currentPrimaryKey() };
     2333        else {
     2334            auto* objectStoreInfo = infoForObjectStore(objectStoreID);
     2335            ASSERT(objectStoreInfo);
     2336            getResult = { cursor->currentPrimaryKey(), cursor->currentPrimaryKey(), cursor->currentValue() ? *cursor->currentValue() : IDBValue(), objectStoreInfo->keyPath() };
     2337        }
    23242338    }
    23252339
     
    23722386    }
    23732387
    2374     sql->getColumnBlobAsVector(1, keyVector);
     2388    Vector<uint8_t> valueVector;
     2389    sql->getColumnBlobAsVector(1, valueVector);
    23752390
    23762391    int64_t recordID = sql->getColumnInt64(2);
     
    23832398        return error;
    23842399
    2385     getResult = { { ThreadSafeDataBuffer::create(WTFMove(keyVector)), WTFMove(blobURLs), sessionID, WTFMove(blobFilePaths) }, objectStoreKey };
     2400    auto* objectStoreInfo = infoForObjectStore(objectStoreID);
     2401    ASSERT(objectStoreInfo);
     2402    getResult = { objectStoreKey, objectStoreKey, { ThreadSafeDataBuffer::create(WTFMove(valueVector)), WTFMove(blobURLs), sessionID, WTFMove(blobFilePaths) }, objectStoreInfo->keyPath() };
    23862403    return IDBError { };
    23872404}
     
    25482565    m_cursors.set(cursor->identifier(), cursor);
    25492566
    2550     cursor->currentData(result);
     2567    auto* objectStoreInfo = infoForObjectStore(info.objectStoreIdentifier());
     2568    ASSERT(objectStoreInfo);
     2569    cursor->currentData(result, objectStoreInfo->keyPath());
    25512570    return IDBError { };
    25522571}
     
    25912610    }
    25922611
    2593     cursor->currentData(result);
     2612    auto* objectStoreInfo = infoForObjectStore(cursor->objectStoreID());
     2613    ASSERT(objectStoreInfo);
     2614    cursor->currentData(result, objectStoreInfo->keyPath());
    25942615    return IDBError { };
    25952616}
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp

    r238632 r243807  
    102102}
    103103
    104 void SQLiteIDBCursor::currentData(IDBGetResult& result)
     104void SQLiteIDBCursor::currentData(IDBGetResult& result, const Optional<IDBKeyPath>& keyPath)
    105105{
    106106    ASSERT(!m_fetchedRecords.isEmpty());
     
    113113    }
    114114
    115     result = { currentRecord.record.key, currentRecord.record.primaryKey, currentRecord.record.value ? *currentRecord.record.value : IDBValue() };
     115    result = { currentRecord.record.key, currentRecord.record.primaryKey, currentRecord.record.value ? *currentRecord.record.value : IDBValue(), keyPath};
    116116}
    117117
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h

    r241183 r243807  
    8080    void objectStoreRecordsChanged();
    8181
    82     void currentData(IDBGetResult&);
     82    void currentData(IDBGetResult&, const Optional<IDBKeyPath>&);
    8383
    8484private:
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp

    r243615 r243807  
    12521252    }
    12531253
    1254     // 3.4.1.2 Object Store Storage Operation
    1255     // If ObjectStore has a key path and the key is autogenerated, then inject the key into the value
    1256     // using steps to assign a key to a value using a key path.
    1257     ThreadSafeDataBuffer injectedRecordValue;
    1258     if (usedKeyIsGenerated && objectStoreInfo->keyPath()) {
    1259         VM& vm = databaseThreadVM();
    1260         JSLockHolder locker(vm);
    1261         auto scope = DECLARE_THROW_SCOPE(vm);
    1262 
    1263         auto value = deserializeIDBValueToJSValue(databaseThreadExecState(), originalRecordValue.data());
    1264         if (value.isUndefined()) {
    1265             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(ConstraintError, "Unable to deserialize record value for record key injection"_s), usedKey));
    1266             return;
    1267         }
    1268 
    1269         if (!injectIDBKeyIntoScriptValue(databaseThreadExecState(), usedKey, value, objectStoreInfo->keyPath().value())) {
    1270             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(ConstraintError, "Unable to inject record key into record value"_s), usedKey));
    1271             return;
    1272         }
    1273 
    1274         auto serializedValue = SerializedScriptValue::create(databaseThreadExecState(), value);
    1275         if (UNLIKELY(scope.exception())) {
    1276             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(ConstraintError, "Unable to serialize record value after injecting record key"_s), usedKey));
    1277             return;
    1278         }
    1279 
    1280         injectedRecordValue = ThreadSafeDataBuffer::copyVector(serializedValue->data());
    1281     }
    1282 
    12831254    // 3.4.1 Object Store Storage Operation
    12841255    // ...If a record already exists in store ...
     
    12911262    }
    12921263
    1293     if (injectedRecordValue.data())
    1294         error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, { injectedRecordValue, originalRecordValue.blobURLs(), originalRecordValue.sessionID(), originalRecordValue.blobFilePaths() });
    1295     else
    1296         error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, originalRecordValue);
     1264    error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, originalRecordValue);
    12971265
    12981266    if (!error.isNull()) {
  • trunk/Source/WebCore/Modules/indexeddb/shared/IDBResultData.cpp

    r234791 r243807  
    234234}
    235235
     236IDBGetResult& IDBResultData::getResultRef()
     237{
     238    RELEASE_ASSERT(m_getResult);
     239    return *m_getResult;
     240}
     241
    236242const IDBGetAllResult& IDBResultData::getAllResult() const
    237243{
  • trunk/Source/WebCore/Modules/indexeddb/shared/IDBResultData.h

    r243163 r243807  
    108108
    109109    WEBCORE_EXPORT const IDBGetResult& getResult() const;
     110    WEBCORE_EXPORT IDBGetResult& getResultRef();
    110111    WEBCORE_EXPORT const IDBGetAllResult& getAllResult() const;
    111112
  • trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp

    r243348 r243807  
    3232#include "IDBBindingUtilities.h"
    3333
     34#include "ExceptionCode.h"
    3435#include "IDBIndexInfo.h"
    3536#include "IDBKey.h"
     
    4243#include "JSDOMConvertDate.h"
    4344#include "JSDOMConvertNullable.h"
     45#include "JSDOMExceptionHandling.h"
    4446#include "JSFile.h"
    4547#include "Logging.h"
     
    325327        return false;
    326328
     329    // Do not set if object already has the correct property value.
     330    auto jsKey = toJS(exec, *exec.lexicalGlobalObject(), key.get());
     331    JSValue existingKey;
     332    if (get(exec, parent, keyPathElements.last(), existingKey) && existingKey == jsKey)
     333        return true;
     334
    327335    if (!set(exec, parent, keyPathElements.last(), toJS(exec, *exec.lexicalGlobalObject(), key.get())))
    328336        return false;
     
    412420}
    413421
    414 static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info)
     422static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info, Optional<IDBKeyPath> objectStoreKeyPath, const IDBKeyData& objectStoreKey)
    415423{
    416424    auto visitor = WTF::makeVisitor([&](const String& string) -> Vector<IDBKeyData> {
     425        // Value doesn't contain auto-generated key, so we need to manually add key if it is possibly auto-generated.
     426        if (objectStoreKeyPath && WTF::holds_alternative<String>(objectStoreKeyPath.value()) && IDBKeyPath(string) == objectStoreKeyPath.value())
     427            return { objectStoreKey };
     428
    417429        auto idbKey = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, string);
    418430        if (!idbKey)
     
    429441        Vector<IDBKeyData> keys;
    430442        for (auto& entry : vector) {
    431             auto key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, entry);
    432             if (!key || !key->isValid())
    433                 return { };
    434             keys.append(key.get());
     443            if (objectStoreKeyPath && WTF::holds_alternative<String>(objectStoreKeyPath.value()) && IDBKeyPath(entry) == objectStoreKeyPath.value())
     444                keys.append(objectStoreKey);
     445            else {
     446                auto key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, entry);
     447                if (!key || !key->isValid())
     448                    return { };
     449                keys.append(key.get());
     450            }
    435451        }
    436452        return keys;
     
    440456}
    441457
    442 void generateIndexKeyForValue(ExecState& exec, const IDBIndexInfo& info, JSValue value, IndexKey& outKey)
    443 {
    444     auto keyDatas = createKeyPathArray(exec, value, info);
    445 
     458void generateIndexKeyForValue(ExecState& exec, const IDBIndexInfo& info, JSValue value, IndexKey& outKey, const Optional<IDBKeyPath>& objectStoreKeyPath, const IDBKeyData& objectStoreKey)
     459{
     460    auto keyDatas = createKeyPathArray(exec, value, info, objectStoreKeyPath, objectStoreKey);
    446461    if (keyDatas.isEmpty())
    447462        return;
     
    450465}
    451466
     467Optional<JSC::JSValue> deserializeIDBValueWithKeyInjection(ExecState& state, const IDBValue& value, const IDBKeyData& key, const Optional<IDBKeyPath>& keyPath)
     468{
     469    auto jsValue = deserializeIDBValueToJSValue(state, value);
     470    if (jsValue.isUndefined() || !keyPath || !WTF::holds_alternative<String>(keyPath.value()) || !isIDBKeyPathValid(keyPath.value()))
     471        return jsValue;
     472
     473    JSLockHolder locker(state.vm());
     474    if (!injectIDBKeyIntoScriptValue(state, key, jsValue, keyPath.value())) {
     475        auto throwScope = DECLARE_THROW_SCOPE(state.vm());
     476        propagateException(state, throwScope, Exception(UnknownError, "Cannot inject key into script value"_s));
     477        return WTF::nullopt;
     478    }
     479
     480    return jsValue;
     481}
     482
    452483} // namespace WebCore
    453484
  • trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h

    r212207 r243807  
    5151bool injectIDBKeyIntoScriptValue(JSC::ExecState&, const IDBKeyData&, JSC::JSValue, const IDBKeyPath&);
    5252
    53 void generateIndexKeyForValue(JSC::ExecState&, const IDBIndexInfo&, JSC::JSValue, IndexKey& outKey);
     53void generateIndexKeyForValue(JSC::ExecState&, const IDBIndexInfo&, JSC::JSValue, IndexKey& outKey, const Optional<IDBKeyPath>&, const IDBKeyData&);
    5454
    5555Ref<IDBKey> scriptValueToIDBKey(JSC::ExecState&, const JSC::JSValue&);
    5656
     57JSC::JSValue deserializeIDBValueToJSValue(JSC::ExecState&, const IDBValue&, Vector<std::pair<String, String>>&);
    5758JSC::JSValue deserializeIDBValueToJSValue(JSC::ExecState&, const IDBValue&);
    5859JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const IDBValue&);
     
    6061JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const IDBKeyData&);
    6162
     63Optional<JSC::JSValue> deserializeIDBValueWithKeyInjection(JSC::ExecState&, const IDBValue&, const IDBKeyData&, const Optional<IDBKeyPath>&);
    6264}
    6365
  • trunk/Source/WebCore/bindings/js/JSIDBCursorWithValueCustom.cpp

    r241196 r243807  
    3939{
    4040    return cachedPropertyValue(state, *this, wrapped().valueWrapper(), [&] {
    41         return deserializeIDBValueToJSValue(state, wrapped().value());
     41        auto result = deserializeIDBValueWithKeyInjection(state, wrapped().value(), wrapped().primaryKey(), wrapped().primaryKeyPath());
     42        return result ? result.value() : jsNull();
    4243    });
    4344}
  • trunk/Source/WebCore/bindings/js/JSIDBRequestCustom.cpp

    r242986 r243807  
    5858        }, [&state] (Vector<IDBKeyData> keyDatas) {
    5959            return toJS<IDLSequence<IDLIDBKeyData>>(state, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), keyDatas);
    60         }, [&state] (IDBValue value) {
    61             return toJS<IDLIDBValue>(state, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), value);
    62         }, [&state] (Vector<IDBValue> values) {
    63             return toJS<IDLSequence<IDLIDBValue>>(state, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), values);
     60        }, [&state] (IDBGetResult getResult) {
     61            auto result = deserializeIDBValueWithKeyInjection(state, getResult.value(), getResult.keyData(), getResult.keyPath());
     62            return result ? result.value() : jsNull();
     63        }, [&state] (IDBGetAllResult getAllResult) {
     64            auto& keys = getAllResult.keys();
     65            auto& values = getAllResult.values();
     66            auto& keyPath = getAllResult.keyPath();
     67            Vector<JSC::JSValue> results;
     68            for (unsigned i = 0; i < values.size(); i ++) {
     69                auto result = deserializeIDBValueWithKeyInjection(state, values[i], keys[i], keyPath);
     70                if (!result)
     71                    return jsNull();
     72                results.append(result.value());
     73            }
     74            return JSValue(JSC::constructArray(&state, nullptr, state.lexicalGlobalObject(), results.data(), results.size()));
    6475        }, [] (uint64_t number) {
    6576            return toJS<IDLUnsignedLongLong>(number);
Note: See TracChangeset for help on using the changeset viewer.