Replace IDBKeyPath with a WTF::Variant
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Oct 2016 03:13:21 +0000 (03:13 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Oct 2016 03:13:21 +0000 (03:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163909

Reviewed by Darin Adler.

Source/WebCore:

Replace IDBKeyPath class with the IDBKeyPathVariant type entirely
and rename IDBKeyPathVariant to IDBKeyPath.

Unfortunately, IDBKeyPath still needs some special handling when
returned to the JavaScript because we do not have a toJS() accepting
a WTF::Variant as input yet.

There should be no significant behavior change except that
IDBIndex.keyPath / IDBObjectStore.keyPath now returns an array of
Strings instead of a DOMStringList object when the IDBKeyPath
contains a vector. This is a progression and matches the
specification:
- https://www.w3.org/TR/IndexedDB/#widl-IDBIndex-keyPath
- https://www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-keyPath

No new tests, rebaselined existing tests.

* Modules/indexeddb/IDBCursor.cpp:
(WebCore::IDBCursor::update):
* Modules/indexeddb/IDBDatabase.h:
* Modules/indexeddb/IDBGetResult.cpp:
(WebCore::IDBGetResult::isolatedCopy):
* Modules/indexeddb/IDBKeyPath.cpp:
(WebCore::isIDBKeyPathValid):
(WebCore::IDBKeyPathIsolatedCopy):
* Modules/indexeddb/IDBKeyPath.h:
(WebCore::IDBKeyPathIsolatedCopy):
* Modules/indexeddb/IDBObjectStore.cpp:
(WebCore::IDBObjectStore::keyPath):
(WebCore::IDBObjectStore::putOrAdd):
(WebCore::IDBObjectStore::createIndex):
* Modules/indexeddb/IDBObjectStore.h:
* Modules/indexeddb/server/IDBSerialization.cpp:
(WebCore::serializeIDBKeyPath):
(WebCore::deserializeIDBKeyPath):
* Modules/indexeddb/server/IDBSerialization.h:
* Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
(WebCore::IDBServer::SQLiteIDBBackingStore::extractExistingDatabaseInfo):
* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd):
* Modules/indexeddb/shared/IDBDatabaseInfo.cpp:
(WebCore::IDBDatabaseInfo::createNewObjectStore):
* Modules/indexeddb/shared/IDBDatabaseInfo.h:
* Modules/indexeddb/shared/IDBIndexInfo.cpp:
(WebCore::IDBIndexInfo::IDBIndexInfo):
(WebCore::IDBIndexInfo::isolatedCopy):
* Modules/indexeddb/shared/IDBIndexInfo.h:
* Modules/indexeddb/shared/IDBObjectStoreInfo.cpp:
(WebCore::IDBObjectStoreInfo::IDBObjectStoreInfo):
(WebCore::IDBObjectStoreInfo::createNewIndex):
(WebCore::IDBObjectStoreInfo::isolatedCopy):
* Modules/indexeddb/shared/IDBObjectStoreInfo.h:
(WebCore::IDBObjectStoreInfo::keyPath):
* bindings/js/IDBBindingUtilities.cpp:
(WebCore::injectIDBKeyIntoScriptValue):
(WebCore::maybeCreateIDBKeyFromScriptValueAndKeyPath):
(WebCore::canInjectIDBKeyIntoScriptValue):
(WebCore::createKeyPathArray):
(WebCore::toJS):
* bindings/js/IDBBindingUtilities.h:
* inspector/InspectorIndexedDBAgent.cpp:

Source/WebKit2:

Add coders to encode / decode IDBKeyPath type for IPC.

* Shared/Databases/IndexedDB/WebIDBResult.cpp:
* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<IDBKeyPath>::encode):
(IPC::ArgumentCoder<IDBKeyPath>::decode):
* Shared/WebCoreArgumentCoders.h:
* WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp:

LayoutTests:

Rebaseline a few tests now that IDBIndex.keyPath / IDBObjectStore.keyPath
no longer incorrectly return DOMStringList objects and return regular
arrays instead.

* storage/indexeddb/modern/idbindex-properties-basic-expected.txt:
* storage/indexeddb/modern/idbindex-properties-basic-private-expected.txt:

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

29 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/modern/idbindex-properties-basic-expected.txt
LayoutTests/storage/indexeddb/modern/idbindex-properties-basic-private-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBCursor.cpp
Source/WebCore/Modules/indexeddb/IDBDatabase.h
Source/WebCore/Modules/indexeddb/IDBGetResult.cpp
Source/WebCore/Modules/indexeddb/IDBKeyPath.cpp
Source/WebCore/Modules/indexeddb/IDBKeyPath.h
Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStore.h
Source/WebCore/Modules/indexeddb/server/IDBSerialization.cpp
Source/WebCore/Modules/indexeddb/server/IDBSerialization.h
Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
Source/WebCore/Modules/indexeddb/shared/IDBDatabaseInfo.cpp
Source/WebCore/Modules/indexeddb/shared/IDBDatabaseInfo.h
Source/WebCore/Modules/indexeddb/shared/IDBIndexInfo.cpp
Source/WebCore/Modules/indexeddb/shared/IDBIndexInfo.h
Source/WebCore/Modules/indexeddb/shared/IDBObjectStoreInfo.cpp
Source/WebCore/Modules/indexeddb/shared/IDBObjectStoreInfo.h
Source/WebCore/bindings/js/IDBBindingUtilities.cpp
Source/WebCore/bindings/js/IDBBindingUtilities.h
Source/WebCore/inspector/InspectorIndexedDBAgent.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/Databases/IndexedDB/WebIDBResult.cpp
Source/WebKit2/Shared/WebCoreArgumentCoders.cpp
Source/WebKit2/Shared/WebCoreArgumentCoders.h
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp

index 7b5bf8d..03ec024 100644 (file)
@@ -1,3 +1,17 @@
+2016-10-26  Chris Dumez  <cdumez@apple.com>
+
+        Replace IDBKeyPath with a WTF::Variant
+        https://bugs.webkit.org/show_bug.cgi?id=163909
+
+        Reviewed by Darin Adler.
+
+        Rebaseline a few tests now that IDBIndex.keyPath / IDBObjectStore.keyPath
+        no longer incorrectly return DOMStringList objects and return regular
+        arrays instead.
+
+        * storage/indexeddb/modern/idbindex-properties-basic-expected.txt:
+        * storage/indexeddb/modern/idbindex-properties-basic-private-expected.txt:
+
 2016-10-26  Zalan Bujtas  <zalan@apple.com>
 
         Ignore out-of-flow siblings when searching for a spanner candidate.
index c37b558..520a221 100644 (file)
@@ -41,13 +41,13 @@ true
 TestIndex6
 [object IDBObjectStore]
 TestObjectStore
-[object DOMStringList]
+foo
 false
 false
 TestIndex7
 [object IDBObjectStore]
 TestObjectStore
-[object DOMStringList]
+foo,bar
 false
 false
 Initial upgrade versionchange transaction complete
@@ -84,13 +84,13 @@ true
 TestIndex6
 [object IDBObjectStore]
 TestObjectStore
-[object DOMStringList]
+foo
 false
 false
 TestIndex7
 [object IDBObjectStore]
 TestObjectStore
-[object DOMStringList]
+foo,bar
 false
 false
 readonly transaction complete
index c37b558..520a221 100644 (file)
@@ -41,13 +41,13 @@ true
 TestIndex6
 [object IDBObjectStore]
 TestObjectStore
-[object DOMStringList]
+foo
 false
 false
 TestIndex7
 [object IDBObjectStore]
 TestObjectStore
-[object DOMStringList]
+foo,bar
 false
 false
 Initial upgrade versionchange transaction complete
@@ -84,13 +84,13 @@ true
 TestIndex6
 [object IDBObjectStore]
 TestObjectStore
-[object DOMStringList]
+foo
 false
 false
 TestIndex7
 [object IDBObjectStore]
 TestObjectStore
-[object DOMStringList]
+foo,bar
 false
 false
 readonly transaction complete
index 5620fab..fde56b9 100644 (file)
@@ -1,3 +1,72 @@
+2016-10-26  Chris Dumez  <cdumez@apple.com>
+
+        Replace IDBKeyPath with a WTF::Variant
+        https://bugs.webkit.org/show_bug.cgi?id=163909
+
+        Reviewed by Darin Adler.
+
+        Replace IDBKeyPath class with the IDBKeyPathVariant type entirely
+        and rename IDBKeyPathVariant to IDBKeyPath.
+
+        Unfortunately, IDBKeyPath still needs some special handling when
+        returned to the JavaScript because we do not have a toJS() accepting
+        a WTF::Variant as input yet.
+
+        There should be no significant behavior change except that
+        IDBIndex.keyPath / IDBObjectStore.keyPath now returns an array of
+        Strings instead of a DOMStringList object when the IDBKeyPath
+        contains a vector. This is a progression and matches the
+        specification:
+        - https://www.w3.org/TR/IndexedDB/#widl-IDBIndex-keyPath
+        - https://www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-keyPath
+
+        No new tests, rebaselined existing tests.
+
+        * Modules/indexeddb/IDBCursor.cpp:
+        (WebCore::IDBCursor::update):
+        * Modules/indexeddb/IDBDatabase.h:
+        * Modules/indexeddb/IDBGetResult.cpp:
+        (WebCore::IDBGetResult::isolatedCopy):
+        * Modules/indexeddb/IDBKeyPath.cpp:
+        (WebCore::isIDBKeyPathValid):
+        (WebCore::IDBKeyPathIsolatedCopy):
+        * Modules/indexeddb/IDBKeyPath.h:
+        (WebCore::IDBKeyPathIsolatedCopy):
+        * Modules/indexeddb/IDBObjectStore.cpp:
+        (WebCore::IDBObjectStore::keyPath):
+        (WebCore::IDBObjectStore::putOrAdd):
+        (WebCore::IDBObjectStore::createIndex):
+        * Modules/indexeddb/IDBObjectStore.h:
+        * Modules/indexeddb/server/IDBSerialization.cpp:
+        (WebCore::serializeIDBKeyPath):
+        (WebCore::deserializeIDBKeyPath):
+        * Modules/indexeddb/server/IDBSerialization.h:
+        * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
+        (WebCore::IDBServer::SQLiteIDBBackingStore::extractExistingDatabaseInfo):
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd):
+        * Modules/indexeddb/shared/IDBDatabaseInfo.cpp:
+        (WebCore::IDBDatabaseInfo::createNewObjectStore):
+        * Modules/indexeddb/shared/IDBDatabaseInfo.h:
+        * Modules/indexeddb/shared/IDBIndexInfo.cpp:
+        (WebCore::IDBIndexInfo::IDBIndexInfo):
+        (WebCore::IDBIndexInfo::isolatedCopy):
+        * Modules/indexeddb/shared/IDBIndexInfo.h:
+        * Modules/indexeddb/shared/IDBObjectStoreInfo.cpp:
+        (WebCore::IDBObjectStoreInfo::IDBObjectStoreInfo):
+        (WebCore::IDBObjectStoreInfo::createNewIndex):
+        (WebCore::IDBObjectStoreInfo::isolatedCopy):
+        * Modules/indexeddb/shared/IDBObjectStoreInfo.h:
+        (WebCore::IDBObjectStoreInfo::keyPath):
+        * bindings/js/IDBBindingUtilities.cpp:
+        (WebCore::injectIDBKeyIntoScriptValue):
+        (WebCore::maybeCreateIDBKeyFromScriptValueAndKeyPath):
+        (WebCore::canInjectIDBKeyIntoScriptValue):
+        (WebCore::createKeyPathArray):
+        (WebCore::toJS):
+        * bindings/js/IDBBindingUtilities.h:
+        * inspector/InspectorIndexedDBAgent.cpp:
+
 2016-10-26  Zalan Bujtas  <zalan@apple.com>
 
         Ignore out-of-flow siblings when searching for a spanner candidate.
index 5416909..195a182 100644 (file)
@@ -194,10 +194,10 @@ ExceptionOr<Ref<IDBRequest>> IDBCursor::update(ExecState& state, JSValue value)
         return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral("Failed to execute 'update' on 'IDBCursor': The cursor is a key cursor.") };
 
     auto& objectStore = effectiveObjectStore();
-    auto& keyPath = objectStore.info().keyPath();
-    const bool usesInLineKeys = !keyPath.isNull();
+    auto& optionalKeyPath = objectStore.info().keyPath();
+    const bool usesInLineKeys = !!optionalKeyPath;
     if (usesInLineKeys) {
-        RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, keyPath);
+        RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, optionalKeyPath.value());
         IDBKeyData keyPathKeyData(keyPathKey.get());
         if (!keyPathKey || keyPathKeyData != m_currentPrimaryKeyData)
             return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to execute 'update' on 'IDBCursor': The effective object store of this cursor uses in-line keys and evaluating the key path of the value parameter results in a different value than the cursor's effective key.") };
index 2b86857..892ec65 100644 (file)
@@ -57,7 +57,7 @@ public:
     RefPtr<DOMStringList> objectStoreNames() const;
 
     struct ObjectStoreParameters {
-        Optional<IDBKeyPathVariant> keyPath;
+        Optional<IDBKeyPath> keyPath;
         bool autoIncrement;
     };
 
index c6578f8..aa36451 100644 (file)
@@ -53,7 +53,7 @@ void IDBGetResult::isolatedCopy(const IDBGetResult& source, IDBGetResult& destin
     destination.m_value = source.m_value.isolatedCopy();
     destination.m_keyData = source.m_keyData.isolatedCopy();
     destination.m_primaryKeyData = source.m_primaryKeyData.isolatedCopy();
-    destination.m_keyPath = source.m_keyPath.isolatedCopy();
+    destination.m_keyPath = WebCore::isolatedCopy(source.m_keyPath);
     destination.m_isDefined = source.m_isDefined;
 }
 
index c4a4ee2..f415ac8 100644 (file)
  */
 
 #include "config.h"
-#include "IDBKeyPath.h"
 
 #if ENABLE(INDEXED_DATABASE)
+#include "IDBKeyPath.h"
 
-#include "KeyedCoding.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
 
@@ -191,38 +190,7 @@ void IDBParseKeyPath(const String& keyPath, Vector<String>& elements, IDBKeyPath
     }
 }
 
-IDBKeyPath::IDBKeyPath(const String& string)
-    : m_type(Type::String)
-    , m_string(string)
-{
-    ASSERT(!m_string.isNull());
-}
-
-IDBKeyPath::IDBKeyPath(const Vector<String>& array)
-    : m_type(Type::Array)
-    , m_array(array)
-{
-#if !LOG_DISABLED
-    for (auto& key : array)
-        ASSERT(!key.isNull());
-#endif
-}
-
-IDBKeyPath::IDBKeyPath(Optional<IDBKeyPathVariant>&& variant)
-{
-    if (!variant)
-        return;
-
-    if (WTF::holds_alternative<String>(*variant)) {
-        m_type = Type::String;
-        m_string = WTFMove(WTF::get<String>(*variant));
-    } else {
-        m_type = Type::Array;
-        m_array = WTFMove(WTF::get<Vector<String>>(*variant));
-    }
-}
-
-bool isIDBKeyPathValid(const IDBKeyPathVariant& keyPath)
+bool isIDBKeyPathValid(const IDBKeyPath& keyPath)
 {
     auto visitor = WTF::makeVisitor([](const String& string) {
         return IDBIsValidKeyPath(string);
@@ -238,73 +206,19 @@ bool isIDBKeyPathValid(const IDBKeyPathVariant& keyPath)
     return WTF::visit(visitor, keyPath);
 }
 
-bool IDBKeyPath::operator==(const IDBKeyPath& other) const
+IDBKeyPath isolatedCopy(const IDBKeyPath& keyPath)
 {
-    if (m_type != other.m_type)
-        return false;
-
-    switch (m_type) {
-    case Type::Null:
-        return true;
-    case Type::String:
-        return m_string == other.m_string;
-    case Type::Array:
-        return m_array == other.m_array;
-    }
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
-IDBKeyPath IDBKeyPath::isolatedCopy() const
-{
-    IDBKeyPath result;
-    result.m_type = m_type;
-    result.m_string = m_string.isolatedCopy();
-    result.m_array.reserveInitialCapacity(m_array.size());
-    for (auto& key : m_array)
-        result.m_array.uncheckedAppend(key.isolatedCopy());
-    return result;
-}
-
-void IDBKeyPath::encode(KeyedEncoder& encoder) const
-{
-    encoder.encodeEnum("type", m_type);
-    switch (m_type) {
-    case Type::Null:
-        return;
-    case Type::String:
-        encoder.encodeString("string", m_string);
-        return;
-    case Type::Array:
-        encoder.encodeObjects("array", m_array.begin(), m_array.end(), [](WebCore::KeyedEncoder& encoder, const String& string) {
-            encoder.encodeString("string", string);
-        });
-        return;
-    };
-    ASSERT_NOT_REACHED();
-}
-
-bool IDBKeyPath::decode(KeyedDecoder& decoder, IDBKeyPath& result)
-{
-    bool succeeded = decoder.decodeEnum("type", result.m_type, [](Type value) {
-        return value == Type::Null || value == Type::String || value == Type::Array;
+    auto visitor = WTF::makeVisitor([](const String& string) -> IDBKeyPath {
+        return string.isolatedCopy();
+    }, [](const Vector<String>& vector) -> IDBKeyPath {
+        Vector<String> vectorCopy;
+        vectorCopy.reserveInitialCapacity(vector.size());
+        for (auto& string : vector)
+            vectorCopy.uncheckedAppend(string.isolatedCopy());
+        return vectorCopy;
     });
-    if (!succeeded)
-        return false;
 
-    switch (result.m_type) {
-    case Type::Null:
-        return true;
-    case Type::String:
-        return decoder.decodeString("string", result.m_string);
-    case Type::Array:
-        result.m_array.clear();
-        return decoder.decodeObjects("array", result.m_array, [](KeyedDecoder& decoder, String& result) {
-            return decoder.decodeString("string", result);
-        });
-    }
-    ASSERT_NOT_REACHED();
-    return false;
+    return WTF::visit(visitor, keyPath);
 }
 
 } // namespace WebCore
index 0f9c5cc..e6faa19 100644 (file)
 
 namespace WebCore {
 
-using IDBKeyPathVariant = WTF::Variant<String, Vector<String>>;
-bool isIDBKeyPathValid(const IDBKeyPathVariant&);
-
-class KeyedDecoder;
-class KeyedEncoder;
+using IDBKeyPath = WTF::Variant<String, Vector<String>>;
+bool isIDBKeyPathValid(const IDBKeyPath&);
 
 enum class IDBKeyPathParseError {
     None,
@@ -47,95 +44,12 @@ enum class IDBKeyPathParseError {
 };
 
 void IDBParseKeyPath(const String&, Vector<String>&, IDBKeyPathParseError&);
-
-// FIXME: We should be able to replace IDBKeyPath with IDBKeyPathVariant.
-class IDBKeyPath {
-public:
-    IDBKeyPath() { }
-    WEBCORE_EXPORT IDBKeyPath(const String&);
-    WEBCORE_EXPORT IDBKeyPath(const Vector<String>& array);
-    WEBCORE_EXPORT IDBKeyPath(Optional<IDBKeyPathVariant>&&);
-
-    enum class Type { Null, String, Array };
-    Type type() const { return m_type; }
-
-    const Vector<String>& array() const
-    {
-        ASSERT(m_type == Type::Array);
-        return m_array;
-    }
-
-    const String& string() const
-    {
-        ASSERT(m_type == Type::String);
-        return m_string;
-    }
-
-    bool isNull() const { return m_type == Type::Null; }
-    bool operator==(const IDBKeyPath& other) const;
-
-    IDBKeyPath isolatedCopy() const;
-
-    template<class Encoder> void encode(Encoder&) const;
-    template<class Decoder> static bool decode(Decoder&, IDBKeyPath&);
-    
-    WEBCORE_EXPORT void encode(KeyedEncoder&) const;
-    WEBCORE_EXPORT static bool decode(KeyedDecoder&, IDBKeyPath&);
-
-private:
-    Type m_type { Type::Null };
-    String m_string;
-    Vector<String> m_array;
-};
-
-template<class Encoder> void IDBKeyPath::encode(Encoder& encoder) const
-{
-    encoder.encodeEnum(m_type);
-
-    switch (m_type) {
-    case Type::Null:
-        break;
-    case Type::String:
-        encoder << m_string;
-        break;
-    case Type::Array:
-        encoder << m_array;
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-}
-
-template<class Decoder> bool IDBKeyPath::decode(Decoder& decoder, IDBKeyPath& keyPath)
+IDBKeyPath isolatedCopy(const IDBKeyPath&);
+inline Optional<IDBKeyPath> isolatedCopy(const Optional<IDBKeyPath>& variant)
 {
-    Type type;
-    if (!decoder.decodeEnum(type))
-        return false;
-
-    switch (type) {
-    case Type::Null:
-        keyPath = IDBKeyPath();
-        return true;
-
-    case Type::String: {
-        String string;
-        if (!decoder.decode(string))
-            return false;
-
-        keyPath = IDBKeyPath(string);
-        return true;
-    }
-    case Type::Array: {
-        Vector<String> array;
-        if (!decoder.decode(array))
-            return false;
-
-        keyPath = IDBKeyPath(array);
-        return true;
-    }
-    default:
-        return true;
-    }
+    if (!variant)
+        return { };
+    return isolatedCopy(variant.value());
 }
 
 } // namespace WebCore
index 79ee3d7..effa0e6 100644 (file)
@@ -120,7 +120,7 @@ ExceptionOr<void> IDBObjectStore::setName(const String& name)
     return { };
 }
 
-const IDBKeyPath& IDBObjectStore::keyPath() const
+const Optional<IDBKeyPath>& IDBObjectStore::keyPath() const
 {
     ASSERT(currentThread() == m_transaction->database().originThreadID());
     return m_info.keyPath();
@@ -311,20 +311,20 @@ ExceptionOr<Ref<IDBRequest>> IDBObjectStore::putOrAdd(ExecState& state, JSValue
     if (key && !key->isValid())
         return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to store record in an IDBObjectStore: The parameter is not a valid key.") };
 
-    bool usesInlineKeys = !m_info.keyPath().isNull();
+    bool usesInlineKeys = !!m_info.keyPath();
     bool usesKeyGenerator = autoIncrement();
     if (usesInlineKeys && inlineKeyCheck == InlineKeyCheck::Perform) {
         if (key)
             return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to store record in an IDBObjectStore: The object store uses in-line keys and the key parameter was provided.") };
 
-        RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, m_info.keyPath());
+        RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, m_info.keyPath().value());
         if (keyPathKey && !keyPathKey->isValid())
             return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to store record in an IDBObjectStore: Evaluating the object store's key path yielded a value that is not a valid key.") };
 
         if (!keyPathKey) {
             if (!usesKeyGenerator)
                 return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to store record in an IDBObjectStore: Evaluating the object store's key path did not yield a value.") };
-            if (!canInjectIDBKeyIntoScriptValue(state, value, m_info.keyPath()))
+            if (!canInjectIDBKeyIntoScriptValue(state, value, m_info.keyPath().value()))
                 return Exception { IDBDatabaseException::DataError };
         }
 
@@ -399,7 +399,7 @@ ExceptionOr<Ref<IDBRequest>> IDBObjectStore::clear(ExecState& execState)
     return m_transaction->requestClearObjectStore(execState, *this);
 }
 
-ExceptionOr<Ref<IDBIndex>> IDBObjectStore::createIndex(ExecState&, const String& name, IDBKeyPathVariant&& keyPath, const IndexParameters& parameters)
+ExceptionOr<Ref<IDBIndex>> IDBObjectStore::createIndex(ExecState&, const String& name, IDBKeyPath&& keyPath, const IndexParameters& parameters)
 {
     LOG(IndexedDB, "IDBObjectStore::createIndex %s", name.utf8().data());
     ASSERT(currentThread() == m_transaction->database().originThreadID());
@@ -426,7 +426,7 @@ ExceptionOr<Ref<IDBIndex>> IDBObjectStore::createIndex(ExecState&, const String&
         return Exception { IDBDatabaseException::InvalidAccessError, ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': The keyPath argument was an array and the multiEntry option is true.") };
 
     // Install the new Index into the ObjectStore's info.
-    IDBIndexInfo info = m_info.createNewIndex(name, Optional<IDBKeyPathVariant>(WTFMove(keyPath)), parameters.unique, parameters.multiEntry);
+    IDBIndexInfo info = m_info.createNewIndex(name, WTFMove(keyPath), parameters.unique, parameters.multiEntry);
     m_transaction->database().didCreateIndexInfo(info);
 
     // Create the actual IDBObjectStore from the transaction, which also schedules the operation server side.
index 7b21ccc..f787fab 100644 (file)
@@ -62,7 +62,7 @@ public:
 
     const String& name() const;
     ExceptionOr<void> setName(const String&);
-    const IDBKeyPath& keyPath() const;
+    const Optional<IDBKeyPath>& keyPath() const;
     RefPtr<DOMStringList> indexNames() const;
     IDBTransaction& transaction();
     bool autoIncrement() const;
@@ -83,7 +83,7 @@ public:
     ExceptionOr<Ref<IDBRequest>> deleteFunction(JSC::ExecState&, IDBKeyRange*);
     ExceptionOr<Ref<IDBRequest>> deleteFunction(JSC::ExecState&, JSC::JSValue key);
     ExceptionOr<Ref<IDBRequest>> clear(JSC::ExecState&);
-    ExceptionOr<Ref<IDBIndex>> createIndex(JSC::ExecState&, const String& name, IDBKeyPathVariant&&, const IndexParameters&);
+    ExceptionOr<Ref<IDBIndex>> createIndex(JSC::ExecState&, const String& name, IDBKeyPath&&, const IndexParameters&);
     ExceptionOr<Ref<IDBIndex>> index(const String& name);
     ExceptionOr<void> deleteIndex(const String& name);
     ExceptionOr<Ref<IDBRequest>> count(JSC::ExecState&, IDBKeyRange*);
index ce159aa..580e351 100644 (file)
 
 namespace WebCore {
 
-RefPtr<SharedBuffer> serializeIDBKeyPath(const IDBKeyPath& keyPath)
+enum class KeyPathType { Null, String, Array };
+
+RefPtr<SharedBuffer> serializeIDBKeyPath(const Optional<IDBKeyPath>& keyPath)
 {
     auto encoder = KeyedEncoder::encoder();
-    keyPath.encode(*encoder);
+
+    if (keyPath) {
+        auto visitor = WTF::makeVisitor([&](const String& string) {
+            encoder->encodeEnum("type", KeyPathType::String);
+            encoder->encodeString("string", string);
+        }, [&](const Vector<String>& vector) {
+            encoder->encodeEnum("type", KeyPathType::Array);
+            encoder->encodeObjects("array", vector.begin(), vector.end(), [](WebCore::KeyedEncoder& encoder, const String& string) {
+                encoder.encodeString("string", string);
+            });
+        });
+        WTF::visit(visitor, keyPath.value());
+    } else
+        encoder->encodeEnum("type", KeyPathType::Null);
+
     return encoder->finishEncoding();
 }
 
-bool deserializeIDBKeyPath(const uint8_t* data, size_t size, IDBKeyPath& result)
+bool deserializeIDBKeyPath(const uint8_t* data, size_t size, Optional<IDBKeyPath>& result)
 {
     if (!data || !size)
         return false;
 
     auto decoder = KeyedDecoder::decoder(data, size);
-    return IDBKeyPath::decode(*decoder, result);
+
+    KeyPathType type;
+    bool succeeded = decoder->decodeEnum("type", type, [](KeyPathType value) {
+        return value == KeyPathType::Null || value == KeyPathType::String || value == KeyPathType::Array;
+    });
+    if (!succeeded)
+        return false;
+
+    switch (type) {
+    case KeyPathType::Null:
+        break;
+    case KeyPathType::String: {
+        String string;
+        if (!decoder->decodeString("string", string))
+            return false;
+        result = IDBKeyPath(WTFMove(string));
+        break;
+    }
+    case KeyPathType::Array: {
+        Vector<String> vector;
+        succeeded = decoder->decodeObjects("array", vector, [](KeyedDecoder& decoder, String& result) {
+            return decoder.decodeString("string", result);
+        });
+        if (!succeeded)
+            return false;
+        result = IDBKeyPath(WTFMove(vector));
+        break;
+    }
+    }
+    return true;
 }
 
 RefPtr<SharedBuffer> serializeIDBKeyData(const IDBKeyData& key)
index 80d2c2b..cc4862b 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "IDBKeyPath.h"
 #include "SharedBuffer.h"
 
 namespace WebCore {
 
 class IDBKeyData;
-class IDBKeyPath;
 
-RefPtr<SharedBuffer> serializeIDBKeyPath(const IDBKeyPath&);
-bool deserializeIDBKeyPath(const uint8_t* buffer, size_t bufferSize, IDBKeyPath&);
+RefPtr<SharedBuffer> serializeIDBKeyPath(const Optional<IDBKeyPath>&);
+bool deserializeIDBKeyPath(const uint8_t* buffer, size_t bufferSize, Optional<IDBKeyPath>&);
 
 RefPtr<SharedBuffer> serializeIDBKeyData(const IDBKeyData&);
 bool deserializeIDBKeyData(const uint8_t* buffer, size_t bufferSize, IDBKeyData&);
index bd76ef4..73e1e02 100644 (file)
@@ -599,7 +599,7 @@ std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::extractExistingDatabaseI
             Vector<char> keyPathBuffer;
             sql.getColumnBlobAsVector(2, keyPathBuffer);
 
-            IDBKeyPath objectStoreKeyPath;
+            Optional<IDBKeyPath> objectStoreKeyPath;
             if (!deserializeIDBKeyPath(reinterpret_cast<const uint8_t*>(keyPathBuffer.data()), keyPathBuffer.size(), objectStoreKeyPath)) {
                 LOG_ERROR("Unable to extract key path from database");
                 return nullptr;
@@ -607,7 +607,7 @@ std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::extractExistingDatabaseI
 
             bool autoIncrement = sql.getColumnInt(3);
 
-            databaseInfo->addExistingObjectStore({ objectStoreID, objectStoreName, objectStoreKeyPath, autoIncrement });
+            databaseInfo->addExistingObjectStore({ objectStoreID, objectStoreName, WTFMove(objectStoreKeyPath), autoIncrement });
 
             result = sql.step();
         }
@@ -632,11 +632,15 @@ std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::extractExistingDatabaseI
             Vector<char> keyPathBuffer;
             sql.getColumnBlobAsVector(3, keyPathBuffer);
 
-            IDBKeyPath indexKeyPath;
+            Optional<IDBKeyPath> indexKeyPath;
             if (!deserializeIDBKeyPath(reinterpret_cast<const uint8_t*>(keyPathBuffer.data()), keyPathBuffer.size(), indexKeyPath)) {
                 LOG_ERROR("Unable to extract key path from database");
                 return nullptr;
             }
+            if (!indexKeyPath) {
+                LOG_ERROR("Unable to extract key path from database");
+                return nullptr;
+            }
 
             bool unique = sql.getColumnInt(4);
             bool multiEntry = sql.getColumnInt(5);
@@ -647,7 +651,7 @@ std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::extractExistingDatabaseI
                 return nullptr;
             }
 
-            objectStore->addExistingIndex({ indexID, objectStoreID, indexName, indexKeyPath, unique, multiEntry });
+            objectStore->addExistingIndex({ indexID, objectStoreID, indexName, WTFMove(indexKeyPath.value()), unique, multiEntry });
 
             result = sql.step();
         }
index 302f837..8fedcf6 100644 (file)
@@ -953,7 +953,7 @@ void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBRe
     // If ObjectStore has a key path and the key is autogenerated, then inject the key into the value
     // using steps to assign a key to a value using a key path.
     ThreadSafeDataBuffer injectedRecordValue;
-    if (usedKeyIsGenerated && !objectStoreInfo->keyPath().isNull()) {
+    if (usedKeyIsGenerated && objectStoreInfo->keyPath()) {
         VM& vm = databaseThreadVM();
         JSLockHolder locker(vm);
         auto scope = DECLARE_THROW_SCOPE(vm);
@@ -964,7 +964,7 @@ void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBRe
             return;
         }
 
-        if (!injectIDBKeyIntoScriptValue(databaseThreadExecState(), usedKey, value, objectStoreInfo->keyPath())) {
+        if (!injectIDBKeyIntoScriptValue(databaseThreadExecState(), usedKey, value, objectStoreInfo->keyPath().value())) {
             postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBDatabaseException::ConstraintError, ASCIILiteral("Unable to inject record key into record value")), usedKey));
             return;
         }
index 44c2b46..f985717 100644 (file)
@@ -66,9 +66,9 @@ bool IDBDatabaseInfo::hasObjectStore(const String& name) const
     return false;
 }
 
-IDBObjectStoreInfo IDBDatabaseInfo::createNewObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
+IDBObjectStoreInfo IDBDatabaseInfo::createNewObjectStore(const String& name, Optional<IDBKeyPath>&& keyPath, bool autoIncrement)
 {
-    IDBObjectStoreInfo info(++m_maxObjectStoreID, name, keyPath, autoIncrement);
+    IDBObjectStoreInfo info(++m_maxObjectStoreID, name, WTFMove(keyPath), autoIncrement);
     m_objectStoreMap.set(info.identifier(), info);
     return info;
 }
index 8e3d481..e0b5144 100644 (file)
@@ -33,8 +33,6 @@
 
 namespace WebCore {
 
-class IDBKeyPath;
-
 class IDBDatabaseInfo {
 public:
     IDBDatabaseInfo(const String& name, uint64_t version);
@@ -50,7 +48,7 @@ public:
     uint64_t version() const { return m_version; }
 
     bool hasObjectStore(const String& name) const;
-    IDBObjectStoreInfo createNewObjectStore(const String& name, const IDBKeyPath&, bool autoIncrement);
+    IDBObjectStoreInfo createNewObjectStore(const String& name, Optional<IDBKeyPath>&&, bool autoIncrement);
     void addExistingObjectStore(const IDBObjectStoreInfo&);
     IDBObjectStoreInfo* infoForExistingObjectStore(uint64_t objectStoreIdentifier);
     IDBObjectStoreInfo* infoForExistingObjectStore(const String& objectStoreName);
index cbf85f6..468c9b8 100644 (file)
@@ -34,11 +34,11 @@ IDBIndexInfo::IDBIndexInfo()
 {
 }
 
-IDBIndexInfo::IDBIndexInfo(uint64_t identifier, uint64_t objectStoreIdentifier, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
+IDBIndexInfo::IDBIndexInfo(uint64_t identifier, uint64_t objectStoreIdentifier, const String& name, IDBKeyPath&& keyPath, bool unique, bool multiEntry)
     : m_identifier(identifier)
     , m_objectStoreIdentifier(objectStoreIdentifier)
     , m_name(name)
-    , m_keyPath(keyPath)
+    , m_keyPath(WTFMove(keyPath))
     , m_unique(unique)
     , m_multiEntry(multiEntry)
 {
@@ -46,7 +46,7 @@ IDBIndexInfo::IDBIndexInfo(uint64_t identifier, uint64_t objectStoreIdentifier,
 
 IDBIndexInfo IDBIndexInfo::isolatedCopy() const
 {
-    return { m_identifier, m_objectStoreIdentifier, m_name.isolatedCopy(), m_keyPath.isolatedCopy(), m_unique, m_multiEntry };
+    return { m_identifier, m_objectStoreIdentifier, m_name.isolatedCopy(), WebCore::isolatedCopy(m_keyPath), m_unique, m_multiEntry };
 }
 
 #if !LOG_DISABLED
index 7f09d92..8157758 100644 (file)
@@ -36,7 +36,7 @@ namespace WebCore {
 class IDBIndexInfo {
 public:
     WEBCORE_EXPORT IDBIndexInfo();
-    IDBIndexInfo(uint64_t identifier, uint64_t objectStoreIdentifier, const String& name, const IDBKeyPath&, bool unique, bool multiEntry);
+    IDBIndexInfo(uint64_t identifier, uint64_t objectStoreIdentifier, const String& name, IDBKeyPath&&, bool unique, bool multiEntry);
 
     IDBIndexInfo isolatedCopy() const;
 
index 3f1c85e..6820a9f 100644 (file)
@@ -35,17 +35,17 @@ IDBObjectStoreInfo::IDBObjectStoreInfo()
 {
 }
 
-IDBObjectStoreInfo::IDBObjectStoreInfo(uint64_t identifier, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
+IDBObjectStoreInfo::IDBObjectStoreInfo(uint64_t identifier, const String& name, Optional<IDBKeyPath>&& keyPath, bool autoIncrement)
     : m_identifier(identifier)
     , m_name(name)
-    , m_keyPath(keyPath)
+    , m_keyPath(WTFMove(keyPath))
     , m_autoIncrement(autoIncrement)
 {
 }
 
-IDBIndexInfo IDBObjectStoreInfo::createNewIndex(const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry)
+IDBIndexInfo IDBObjectStoreInfo::createNewIndex(const String& name, IDBKeyPath&& keyPath, bool unique, bool multiEntry)
 {
-    IDBIndexInfo info(++m_maxIndexID, m_identifier, name, keyPath, unique, multiEntry);
+    IDBIndexInfo info(++m_maxIndexID, m_identifier, name, WTFMove(keyPath), unique, multiEntry);
     m_indexMap.set(info.identifier(), info);
     return info;
 }
@@ -96,7 +96,7 @@ IDBIndexInfo* IDBObjectStoreInfo::infoForExistingIndex(uint64_t identifier)
 
 IDBObjectStoreInfo IDBObjectStoreInfo::isolatedCopy() const
 {
-    IDBObjectStoreInfo result = { m_identifier, m_name.isolatedCopy(), m_keyPath.isolatedCopy(), m_autoIncrement };
+    IDBObjectStoreInfo result = { m_identifier, m_name.isolatedCopy(), WebCore::isolatedCopy(m_keyPath), m_autoIncrement };
 
     for (auto& iterator : m_indexMap) {
         result.m_indexMap.set(iterator.key, iterator.value.isolatedCopy());
index ddea1ea..5075a41 100644 (file)
 
 namespace WebCore {
 
-class IDBKeyPath;
-
 class IDBObjectStoreInfo {
 public:
     WEBCORE_EXPORT IDBObjectStoreInfo();
-    IDBObjectStoreInfo(uint64_t identifier, const String& name, const IDBKeyPath&, bool autoIncrement);
+    IDBObjectStoreInfo(uint64_t identifier, const String& name, Optional<IDBKeyPath>&&, bool autoIncrement);
 
     uint64_t identifier() const { return m_identifier; }
     const String& name() const { return m_name; }
-    const IDBKeyPath& keyPath() const { return m_keyPath; }
+    const Optional<IDBKeyPath>& keyPath() const { return m_keyPath; }
     bool autoIncrement() const { return m_autoIncrement; }
     uint64_t maxIndexID() const { return m_maxIndexID; }
 
@@ -52,7 +50,7 @@ public:
 
     IDBObjectStoreInfo isolatedCopy() const;
 
-    IDBIndexInfo createNewIndex(const String& name, const IDBKeyPath&, bool unique, bool multiEntry);
+    IDBIndexInfo createNewIndex(const String& name, IDBKeyPath&&, bool unique, bool multiEntry);
     void addExistingIndex(const IDBIndexInfo&);
     bool hasIndex(const String& name) const;
     bool hasIndex(uint64_t indexIdentifier) const;
@@ -75,7 +73,7 @@ public:
 private:
     uint64_t m_identifier { 0 };
     String m_name;
-    IDBKeyPath m_keyPath;
+    Optional<IDBKeyPath> m_keyPath;
     bool m_autoIncrement { false };
     uint64_t m_maxIndexID { 0 };
 
index 571dbc1..d67c470 100644 (file)
@@ -242,11 +242,11 @@ bool injectIDBKeyIntoScriptValue(ExecState& exec, const IDBKeyData& keyData, JSV
 {
     LOG(IndexedDB, "injectIDBKeyIntoScriptValue");
 
-    ASSERT(keyPath.type() == IDBKeyPath::Type::String);
+    ASSERT(WTF::holds_alternative<String>(keyPath));
 
     Vector<String> keyPathElements;
     IDBKeyPathParseError error;
-    IDBParseKeyPath(keyPath.string(), keyPathElements, error);
+    IDBParseKeyPath(WTF::get<String>(keyPath), keyPathElements, error);
     ASSERT(error == IDBKeyPathParseError::None);
 
     if (keyPathElements.isEmpty())
@@ -269,10 +269,8 @@ bool injectIDBKeyIntoScriptValue(ExecState& exec, const IDBKeyData& keyData, JSV
 
 RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const JSValue& value, const IDBKeyPath& keyPath)
 {
-    ASSERT(!keyPath.isNull());
-
-    if (keyPath.type() == IDBKeyPath::Type::Array) {
-        const Vector<String>& array = keyPath.array();
+    if (WTF::holds_alternative<Vector<String>>(keyPath)) {
+        auto& array = WTF::get<Vector<String>>(keyPath);
         Vector<RefPtr<IDBKey>> result;
         result.reserveInitialCapacity(array.size());
         for (auto& string : array) {
@@ -284,18 +282,17 @@ RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const
         return IDBKey::createArray(WTFMove(result));
     }
 
-    ASSERT(keyPath.type() == IDBKeyPath::Type::String);
-    return internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, keyPath.string());
+    return internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, WTF::get<String>(keyPath));
 }
 
 bool canInjectIDBKeyIntoScriptValue(ExecState& exec, const JSValue& scriptValue, const IDBKeyPath& keyPath)
 {
     LOG(StorageAPI, "canInjectIDBKeyIntoScriptValue");
 
-    ASSERT(keyPath.type() == IDBKeyPath::Type::String);
+    ASSERT(WTF::holds_alternative<String>(keyPath));
     Vector<String> keyPathElements;
     IDBKeyPathParseError error;
-    IDBParseKeyPath(keyPath.string(), keyPathElements, error);
+    IDBParseKeyPath(WTF::get<String>(keyPath), keyPathElements, error);
     ASSERT(error == IDBKeyPathParseError::None);
 
     if (!keyPathElements.size())
@@ -339,35 +336,30 @@ JSC::JSValue idbKeyDataToScriptValue(JSC::ExecState& exec, const IDBKeyData& key
 
 static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info)
 {
-    Vector<IDBKeyData> keys;
-
-    switch (info.keyPath().type()) {
-    case IDBKeyPath::Type::Array:
-        for (auto& entry : info.keyPath().array()) {
-            auto key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, entry);
-            if (!key)
-                return { };
-            keys.append(key.get());
-        }
-        break;
-    case IDBKeyPath::Type::String: {
-        auto idbKey = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, info.keyPath().string());
+    auto visitor = WTF::makeVisitor([&](const String& string) -> Vector<IDBKeyData> {
+        auto idbKey = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, string);
         if (!idbKey)
             return { };
 
+        Vector<IDBKeyData> keys;
         if (info.multiEntry() && idbKey->type() == IndexedDB::Array) {
             for (auto& key : idbKey->array())
                 keys.append(key.get());
         } else
             keys.append(idbKey.get());
+        return keys;
+    }, [&](const Vector<String>& vector) -> Vector<IDBKeyData> {
+        Vector<IDBKeyData> keys;
+        for (auto& entry : vector) {
+            auto key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, entry);
+            if (!key)
+                return { };
+            keys.append(key.get());
+        }
+        return keys;
+    });
 
-        break;
-    }
-    case IDBKeyPath::Type::Null:
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-
-    return keys;
+    return WTF::visit(visitor, info.keyPath());
 }
 
 void generateIndexKeyForValue(ExecState& exec, const IDBIndexInfo& info, JSValue value, IndexKey& outKey)
@@ -380,22 +372,17 @@ void generateIndexKeyForValue(ExecState& exec, const IDBIndexInfo& info, JSValue
     outKey = IndexKey(WTFMove(keyDatas));
 }
 
-JSValue toJS(ExecState& state, JSDOMGlobalObject& globalObject, const IDBKeyPath& value)
+JSValue toJS(ExecState& state, JSDOMGlobalObject& globalObject, const Optional<IDBKeyPath>& keyPath)
 {
-    switch (value.type()) {
-    case IDBKeyPath::Type::Null:
+    if (!keyPath)
         return jsNull();
-    case IDBKeyPath::Type::String:
-        return jsStringWithCache(&state, value.string());
-    case IDBKeyPath::Type::Array:
-        auto keyPaths = DOMStringList::create();
-        for (auto& path : value.array())
-            keyPaths->append(path);
-        return toJS(&state, &globalObject, keyPaths);
-    }
 
-    ASSERT_NOT_REACHED();
-    return jsNull();
+    auto visitor = WTF::makeVisitor([&](const String& string) -> JSValue {
+        return toJS<IDLDOMString>(state, globalObject, string);
+    }, [&](const Vector<String>& vector) -> JSValue {
+        return toJS<IDLSequence<IDLDOMString>>(state, globalObject, vector);
+    });
+    return WTF::visit(visitor, keyPath.value());
 }
 
 } // namespace WebCore
index aa4f5c3..757a29a 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "IDBKeyPath.h"
 #include <wtf/Forward.h>
 
 namespace JSC {
@@ -41,13 +42,13 @@ namespace WebCore {
 class IDBIndexInfo;
 class IDBKey;
 class IDBKeyData;
-class IDBKeyPath;
 class IDBValue;
 class IndexKey;
 class JSDOMGlobalObject;
 class ThreadSafeDataBuffer;
 
-JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, const IDBKeyPath&);
+// FIXME: Remove this once we support returning union types.
+JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, const Optional<IDBKeyPath>&);
 
 RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(JSC::ExecState&, const JSC::JSValue&, const IDBKeyPath&);
 bool canInjectIDBKeyIntoScriptValue(JSC::ExecState&, const JSC::JSValue&, const IDBKeyPath&);
index c5c8013..cf430ba 100644 (file)
@@ -162,39 +162,24 @@ void ExecutableWithDatabase::start(IDBFactory* idbFactory, SecurityOrigin*, cons
 }
 
 
-static RefPtr<KeyPath> keyPathFromIDBKeyPath(const IDBKeyPath& idbKeyPath)
+static RefPtr<KeyPath> keyPathFromIDBKeyPath(const Optional<IDBKeyPath>& idbKeyPath)
 {
-    RefPtr<KeyPath> keyPath;
-    switch (idbKeyPath.type()) {
-    case IDBKeyPath::Type::Null:
-        keyPath = KeyPath::create()
-            .setType(KeyPath::Type::Null)
-            .release();
-        break;
-
-    case IDBKeyPath::Type::String:
-        keyPath = KeyPath::create()
-            .setType(KeyPath::Type::String)
-            .release();
-        keyPath->setString(idbKeyPath.string());
-        break;
-
-    case IDBKeyPath::Type::Array: {
+    if (!idbKeyPath)
+        return KeyPath::create().setType(KeyPath::Type::Null).release();
+
+    auto visitor = WTF::makeVisitor([](const String& string) {
+        RefPtr<KeyPath> keyPath = KeyPath::create().setType(KeyPath::Type::String).release();
+        keyPath->setString(string);
+        return keyPath;
+    }, [](const Vector<String>& vector) {
         auto array = Inspector::Protocol::Array<String>::create();
-        for (auto& string : idbKeyPath.array())
+        for (auto& string : vector)
             array->addItem(string);
-        keyPath = KeyPath::create()
-            .setType(KeyPath::Type::Array)
-            .release();
+        RefPtr<KeyPath> keyPath = KeyPath::create().setType(KeyPath::Type::Array).release();
         keyPath->setArray(WTFMove(array));
-        break;
-    }
-
-    default:
-        ASSERT_NOT_REACHED();
-    }
-
-    return keyPath;
+        return keyPath;
+    });
+    return WTF::visit(visitor, idbKeyPath.value());
 }
 
 static RefPtr<IDBTransaction> transactionForDatabase(IDBDatabase* idbDatabase, const String& objectStoreName, const String& mode = IDBTransaction::modeReadOnly())
index 8f82447..09b7993 100644 (file)
@@ -1,3 +1,19 @@
+2016-10-26  Chris Dumez  <cdumez@apple.com>
+
+        Replace IDBKeyPath with a WTF::Variant
+        https://bugs.webkit.org/show_bug.cgi?id=163909
+
+        Reviewed by Darin Adler.
+
+        Add coders to encode / decode IDBKeyPath type for IPC.
+
+        * Shared/Databases/IndexedDB/WebIDBResult.cpp:
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<IDBKeyPath>::encode):
+        (IPC::ArgumentCoder<IDBKeyPath>::decode):
+        * Shared/WebCoreArgumentCoders.h:
+        * WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp:
+
 2016-10-26  Brian Burg  <bburg@apple.com>
 
         Web Inspector: remove unused bool return value from FrontendChannel::sendMessageToFrontend
index a0ec81a..706c62e 100644 (file)
@@ -28,7 +28,7 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
-#include "ArgumentCoders.h"
+#include "WebCoreArgumentCoders.h"
 
 namespace WebKit {
 
index 3793fbb..66fc612 100644 (file)
@@ -2303,5 +2303,35 @@ bool ArgumentCoder<CaptureDevice>::decode(Decoder& decoder, WebCore::CaptureDevi
 }
 #endif
 
+#if ENABLE(INDEXED_DATABASE)
+void ArgumentCoder<IDBKeyPath>::encode(Encoder& encoder, const IDBKeyPath& keyPath)
+{
+    bool isString = WTF::holds_alternative<String>(keyPath);
+    encoder << isString;
+    if (isString)
+        encoder << WTF::get<String>(keyPath);
+    else
+        encoder << WTF::get<Vector<String>>(keyPath);
+}
+
+bool ArgumentCoder<IDBKeyPath>::decode(Decoder& decoder, IDBKeyPath& keyPath)
+{
+    bool isString;
+    if (!decoder.decode(isString))
+        return false;
+    if (isString) {
+        String string;
+        if (!decoder.decode(string))
+            return false;
+        keyPath = string;
+    } else {
+        Vector<String> vector;
+        if (!decoder.decode(vector))
+            return false;
+        keyPath = vector;
+    }
+    return true;
+}
+#endif
 
 } // namespace IPC
index b4b111b..604dc97 100644 (file)
@@ -134,6 +134,12 @@ struct MediaConstraintsData;
 }
 #endif
 
+#if ENABLE(INDEXED_DATABASE)
+namespace WebCore {
+using IDBKeyPath = Variant<String, Vector<String>>;
+}
+#endif
+
 namespace IPC {
 
 template<> struct ArgumentCoder<WebCore::AffineTransform> {
@@ -547,6 +553,15 @@ template<> struct ArgumentCoder<WebCore::CaptureDevice> {
 };
 #endif
 
+#if ENABLE(INDEXED_DATABASE)
+
+template<> struct ArgumentCoder<WebCore::IDBKeyPath> {
+    static void encode(Encoder&, const WebCore::IDBKeyPath&);
+    static bool decode(Decoder&, WebCore::IDBKeyPath&);
+};
+
+#endif
+
 } // namespace IPC
 
 namespace WTF {
index 7b3b3f8..f6defce 100644 (file)
@@ -32,6 +32,7 @@
 #include "DatabaseToWebProcessConnectionMessages.h"
 #include "NetworkConnectionToWebProcessMessages.h"
 #include "NetworkProcessConnection.h"
+#include "WebCoreArgumentCoders.h"
 #include "WebIDBConnectionToClientMessages.h"
 #include "WebIDBResult.h"
 #include "WebProcess.h"