static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info)
{
    Vector<IDBKeyData> keys;

    switch (info.keyPath().type()) {
    case IndexedDB::KeyPathType::Array:
        for (auto& entry : info.keyPath().array()) {
            auto key = internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, entry);
            if (!key)
                return { };
            keys.append(key.get());
        }
        break;
    case IndexedDB::KeyPathType::String: {
        auto idbKey = internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, info.keyPath().string());
        if (!idbKey)
            return { };

        if (info.multiEntry() && idbKey->type() == IndexedDB::Array) {
            for (auto& key : idbKey->array())
                keys.append(key.get());
        } else
            keys.append(idbKey.get());

        break;
    }
    case IndexedDB::KeyPathType::Null:
        RELEASE_ASSERT_NOT_REACHED();
    }

    return keys;
}
RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const Deprecated::ScriptValue& value, const IDBKeyPath& keyPath)
{
    ASSERT(!keyPath.isNull());

    if (keyPath.type() == IndexedDB::KeyPathType::Array) {
        Vector<RefPtr<IDBKey>> result;
        const Vector<String>& array = keyPath.array();
        for (size_t i = 0; i < array.size(); i++) {
            RefPtr<IDBKey> key = internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, array[i]);
            if (!key)
                return nullptr;
            result.append(key);
        }
        return IDBKey::createArray(result);
    }

    ASSERT(keyPath.type() == IndexedDB::KeyPathType::String);
    return internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, keyPath.string());
}
RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const JSC::JSValue& value, const IDBKeyPath& keyPath)
{
    ASSERT(!keyPath.isNull());

    if (keyPath.type() == IndexedDB::KeyPathType::Array) {
        const Vector<String>& array = keyPath.array();
        Vector<RefPtr<IDBKey>> result;
        result.reserveInitialCapacity(array.size());
        for (auto& string : array) {
            RefPtr<IDBKey> key = internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, string);
            if (!key)
                return nullptr;
            result.uncheckedAppend(WTFMove(key));
        }
        return IDBKey::createArray(WTFMove(result));
    }

    ASSERT(keyPath.type() == IndexedDB::KeyPathType::String);
    return internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, keyPath.string());
}
RefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(ExecState* exec, const Deprecated::ScriptValue& value, const IDBKeyPath& keyPath)
{
    LOG(StorageAPI, "createIDBKeyFromScriptValueAndKeyPath");
    ASSERT(!keyPath.isNull());

    if (keyPath.type() == IDBKeyPath::ArrayType) {
        Vector<RefPtr<IDBKey>> result;
        const Vector<String>& array = keyPath.array();
        for (size_t i = 0; i < array.size(); i++) {
            RefPtr<IDBKey> key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, array[i]);
            if (!key)
                return nullptr;
            result.append(key);
        }
        return IDBKey::createArray(result);
    }

    ASSERT(keyPath.type() == IDBKeyPath::StringType);
    return internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, keyPath.string());
}