Changeset 244436 in webkit


Ignore:
Timestamp:
Apr 18, 2019 2:45:41 PM (5 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
<rdar://problem/49562115>

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/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:

  • 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.

(prepareDatabase.event.target.onsuccess):
(prepareDatabase):
(compare):
(runGetTest):
(runGetAllTest):
(get store):
(testSteps):

Location:
trunk
Files:
3 added
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r244430 r244436  
     12019-04-18  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        <rdar://problem/49562115>
     6
     7        Reviewed by Geoffrey Garen.
     8
     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        (prepareDatabase.event.target.onsuccess):
     13        (prepareDatabase):
     14        (compare):
     15        (runGetTest):
     16        (runGetAllTest):
     17        (get store):
     18        (testSteps):
     19
    1202019-04-18  Timothy Hatcher  <timothy@apple.com>
    221
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r244423 r244436  
     12019-04-18  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        <rdar://problem/49562115>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        Updated test expectations to PASS.
     10
     11        * web-platform-tests/IndexedDB/nested-cloning-large-expected.txt:
     12        * web-platform-tests/IndexedDB/nested-cloning-large-multiple-expected.txt:
     13        * web-platform-tests/IndexedDB/nested-cloning-small-expected.txt:
     14
    1152019-04-18  Antoine Quint  <graouts@apple.com>
    216
  • trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/nested-cloning-large-expected.txt

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r244434 r244436  
     12019-04-18  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        <rdar://problem/49562115>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        If a key is auto-generated, it should become a property of the value object. Network process would perform the
     10        key injection by deserializing IDBValue into script value, setting the property, serializing the result and
     11        storing it in a database record. But network process does not have a JSDOMGlobalObject, so it would fail to
     12        deserialize types including Blob and File.
     13
     14        To solve this issue, we move the key injection to web process and let network process store the original value
     15        it gets. In this case, when web process asks for some value, network process should return key, value and key
     16        path so that web process can decide whether it should perform a key injection before returning the result. Note
     17        that the auto-generated key would always be stored as the key in a ObjectStore record.
     18
     19        Test: storage/indexeddb/modern/objectstore-autoincrement-types.html
     20
     21        * Modules/indexeddb/IDBCursor.cpp:
     22        (WebCore::IDBCursor::setGetResult):
     23        * Modules/indexeddb/IDBCursor.h:
     24        (WebCore::IDBCursor::primaryKeyPath):
     25        * Modules/indexeddb/IDBGetAllResult.cpp:
     26        (WebCore::IDBGetAllResult::isolatedCopy):
     27        (WebCore::IDBGetAllResult::addKey):
     28        (WebCore::IDBGetAllResult::addValue):
     29        (WebCore::IDBGetAllResult::keys const):
     30        (WebCore::IDBGetAllResult::values const):
     31        (WebCore::IDBGetAllResult::allBlobFilePaths const):
     32        (WebCore::isolatedCopyOfVariant): Deleted.
     33
     34        * Modules/indexeddb/IDBGetAllResult.h: Introduce an IDBKeyPath parameter. Also replace Variant with two Vectors,
     35        because we only needed to store either key or value before, and now the stored value could be incomplete.
     36        (WebCore::IDBGetAllResult::IDBGetAllResult):
     37        (WebCore::IDBGetAllResult::keyPath const):
     38        (WebCore::IDBGetAllResult::encode const):
     39        (WebCore::IDBGetAllResult::decode):
     40
     41        * Modules/indexeddb/IDBGetResult.cpp:
     42        (WebCore::IDBGetResult::setValue):
     43        * Modules/indexeddb/IDBGetResult.h:
     44        (WebCore::IDBGetResult::IDBGetResult):
     45        (WebCore::IDBGetResult::keyPath const):
     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        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
     81
     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
     94        (WebCore::createKeyPathArray):
     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-18  Zalan Bujtas  <zalan@apple.com>
    2111
  • trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp

    r243910 r244436  
    345345    m_primaryKey = m_primaryKeyData.maybeCreateIDBKey();
    346346
    347     if (isKeyCursorWithValue())
     347    if (isKeyCursorWithValue()) {
    348348        m_value = getResult.value();
     349        m_keyPath = getResult.keyPath();
     350    }
    349351
    350352    m_gotValue = true;
  • trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h

    r244115 r244436  
    3131#include "IDBCursorDirection.h"
    3232#include "IDBCursorInfo.h"
     33#include "IDBKeyPath.h"
    3334#include "IDBRequest.h"
    3435#include "IDBValue.h"
     
    6162    IDBKey* primaryKey() { return m_primaryKey.get(); };
    6263    IDBValue value() { return m_value; };
     64    const Optional<IDBKeyPath>& primaryKeyPath() { return m_keyPath; };
    6365    JSValueInWrappedObject& keyWrapper() { return m_keyWrapper; }
    6466    JSValueInWrappedObject& primaryKeyWrapper() { return m_primaryKeyWrapper; }
     
    107109    IDBKeyData m_primaryKeyData;
    108110    IDBValue m_value;
     111    Optional<IDBKeyPath> m_keyPath;
    109112
    110113    JSValueInWrappedObject m_keyWrapper;
  • trunk/Source/WebCore/Modules/indexeddb/IDBGetAllResult.cpp

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    395395}
    396396
    397 void IDBRequest::setResult(const Vector<IDBValue>& values)
    398 {
    399     ASSERT(&originThread() == &Thread::current());
    400 
    401     auto* context = scriptExecutionContext();
    402     if (!context)
    403         return;
    404 
    405     VM& vm = context->vm();
    406     JSLockHolder lock(vm);
    407     m_result = values;
     397void IDBRequest::setResult(const IDBGetAllResult& result)
     398{
     399    ASSERT(&originThread() == &Thread::current());
     400
     401    auto* context = scriptExecutionContext();
     402    if (!context)
     403        return;
     404
     405    VM& vm = context->vm();
     406    JSLockHolder lock(vm);
     407    m_result = result;
    408408    m_resultWrapper = { };
    409409}
     
    423423}
    424424
    425 void IDBRequest::setResultToStructuredClone(const IDBValue& value)
     425void IDBRequest::setResultToStructuredClone(const IDBGetResult& result)
    426426{
    427427    ASSERT(&originThread() == &Thread::current());
     
    435435    VM& vm = context->vm();
    436436    JSLockHolder lock(vm);
    437     m_result = value;
     437    m_result = result;
    438438    m_resultWrapper = { };
    439439}
  • trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h

    r243910 r244436  
    3232#include "IDBActiveDOMObject.h"
    3333#include "IDBError.h"
     34#include "IDBGetAllResult.h"
     35#include "IDBGetResult.h"
    3436#include "IDBKeyData.h"
    3537#include "IDBResourceIdentifier.h"
     
    7779    virtual ~IDBRequest();
    7880
    79     using Result = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, IDBKeyData, Vector<IDBKeyData>, IDBValue, Vector<IDBValue>, uint64_t, NullResultType>;
     81    using Result = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, IDBKeyData, Vector<IDBKeyData>, IDBGetResult, IDBGetAllResult, uint64_t, NullResultType>;
    8082    ExceptionOr<Result> result() const;
    8183    JSValueInWrappedObject& resultWrapper() { return m_resultWrapper; }
     
    108110    void setResult(const IDBKeyData&);
    109111    void setResult(const Vector<IDBKeyData>&);
    110     void setResult(const Vector<IDBValue>&);
     112    void setResultToStructuredClone(const IDBGetResult&);
     113    void setResult(const IDBGetAllResult&);
    111114    void setResult(uint64_t);
    112     void setResultToStructuredClone(const IDBValue&);
    113115    void setResultToUndefined();
    114116
  • trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp

    r243910 r244436  
    990990        break;
    991991    case IndexedDB::GetAllType::Values:
    992         request.setResult(getAllResult.values());
     992        request.setResult(getAllResult);
    993993        break;
    994994    }
     
    10941094    } else {
    10951095        if (resultData.getResult().value().data().data())
    1096             request.setResultToStructuredClone(resultData.getResult().value());
     1096            request.setResultToStructuredClone(resultData.getResult());
    10971097        else
    10981098            request.setResultToUndefined();
  • trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r244077 r244436  
    12481248    }
    12491249
    1250     // 3.4.1.2 Object Store Storage Operation
    1251     // If ObjectStore has a key path and the key is autogenerated, then inject the key into the value
    1252     // using steps to assign a key to a value using a key path.
    1253     ThreadSafeDataBuffer injectedRecordValue;
    1254     if (usedKeyIsGenerated && objectStoreInfo->keyPath()) {
    1255         VM& vm = databaseThreadVM();
    1256         JSLockHolder locker(vm);
    1257         auto scope = DECLARE_THROW_SCOPE(vm);
    1258 
    1259         auto value = deserializeIDBValueToJSValue(databaseThreadExecState(), originalRecordValue.data());
    1260         if (value.isUndefined()) {
    1261             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(ConstraintError, "Unable to deserialize record value for record key injection"_s), usedKey));
    1262             return;
    1263         }
    1264 
    1265         if (!injectIDBKeyIntoScriptValue(databaseThreadExecState(), usedKey, value, objectStoreInfo->keyPath().value())) {
    1266             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(ConstraintError, "Unable to inject record key into record value"_s), usedKey));
    1267             return;
    1268         }
    1269 
    1270         auto serializedValue = SerializedScriptValue::create(databaseThreadExecState(), value);
    1271         if (UNLIKELY(scope.exception())) {
    1272             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(ConstraintError, "Unable to serialize record value after injecting record key"_s), usedKey));
    1273             return;
    1274         }
    1275 
    1276         injectedRecordValue = ThreadSafeDataBuffer::copyVector(serializedValue->data());
    1277     }
    1278 
    12791250    // 3.4.1 Object Store Storage Operation
    12801251    // ...If a record already exists in store ...
     
    12871258    }
    12881259
    1289     if (injectedRecordValue.data())
    1290         error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, { injectedRecordValue, originalRecordValue.blobURLs(), originalRecordValue.sessionID(), originalRecordValue.blobFilePaths() });
    1291     else
    1292         error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, originalRecordValue);
     1260    error = m_backingStore->addRecord(transactionIdentifier, *objectStoreInfo, usedKey, originalRecordValue);
    12931261
    12941262    if (!error.isNull()) {
  • trunk/Source/WebCore/Modules/indexeddb/shared/IDBResultData.cpp

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r243910 r244436  
    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

    r244225 r244436  
    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

    r243910 r244436  
    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            auto scope = DECLARE_THROW_SCOPE(state.vm());
     68            JSC::MarkedArgumentBuffer list;
     69            for (unsigned i = 0; i < values.size(); i ++) {
     70                auto result = deserializeIDBValueWithKeyInjection(state, values[i], keys[i], keyPath);
     71                if (!result)
     72                    return jsNull();
     73                list.append(result.value());
     74                if (UNLIKELY(list.hasOverflowed())) {
     75                    propagateException(state, scope, Exception(UnknownError));
     76                    return jsNull();
     77                }
     78            }
     79            return JSValue(JSC::constructArray(&state, nullptr, state.lexicalGlobalObject(), list));
    6480        }, [] (uint64_t number) {
    6581            return toJS<IDLUnsignedLongLong>(number);
Note: See TracChangeset for help on using the changeset viewer.