diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-09-02 10:49:32 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-09-04 15:51:48 +0200 |
commit | f862b3edeb8a96a49a5d12620506d33d5a5aadca (patch) | |
tree | 14e2a1398a029ab3c2bb7a92599baed5235e8444 /src/qml/qml/qqmlvaluetype.cpp | |
parent | 258143c07a900c895f597dd135fa6eea51b65111 (diff) |
Make QQmlValueTypeFactory::valueType() and isValueType() consistent
If isValueType() returns true, we should really return a non-null value
from valueType(). Otherwise the assumption that
QQmlValueTypeWrapper::valueType is never null breaks. In particular, the
unknown type and various primitive types are _not_ value types. We
special case the, probably common, UnknownType and check the actual
return value of valueType() for anything else. In order to avoid looking
up the metaobject each time we request a type that is not a value type,
we keep an invalid value type as marker for "not checked yet" and
replace that with nullptr once we determine that the type in question is
indeed not a value type.
Fixes: QTBUG-76866
Change-Id: I797f4cdd4db48ffc1b8fa2d919afc8022f67fa94
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlvaluetype.cpp')
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 88f7b69dc2..a4737b3da9 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -65,11 +65,13 @@ struct QQmlValueTypeFactoryImpl QQmlValueType *valueTypes[QVariant::UserType]; QHash<int, QQmlValueType *> userTypes; QMutex mutex; + + QQmlValueType invalidValueType; }; QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl() { - std::fill_n(valueTypes, int(QVariant::UserType), nullptr); + std::fill_n(valueTypes, int(QVariant::UserType), &invalidValueType); #if QT_CONFIG(qml_itemmodel) // See types wrapped in qqmlmodelindexvaluetype_p.h @@ -79,20 +81,18 @@ QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl() QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl() { - qDeleteAll(valueTypes, valueTypes + QVariant::UserType); + for (QQmlValueType *type : valueTypes) { + if (type != &invalidValueType) + delete type; + } qDeleteAll(userTypes); } -bool QQmlValueTypeFactoryImpl::isValueType(int idx) +bool isInternalType(int idx) { - if (idx >= QMetaType::User) - return valueType(idx) != nullptr; - - if (idx < 0) - return false; - // Qt internal types switch (idx) { + case QMetaType::UnknownType: case QMetaType::QStringList: case QMetaType::QObjectStar: case QMetaType::VoidStar: @@ -101,12 +101,20 @@ bool QQmlValueTypeFactoryImpl::isValueType(int idx) case QMetaType::QLocale: case QMetaType::QImage: // scarce type, keep as QVariant case QMetaType::QPixmap: // scarce type, keep as QVariant - return false; - default: return true; + default: + return false; } } +bool QQmlValueTypeFactoryImpl::isValueType(int idx) +{ + if (idx < 0 || isInternalType(idx)) + return false; + + return valueType(idx) != nullptr; +} + const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t) { switch (t) { @@ -166,15 +174,17 @@ QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx) } QQmlValueType *rv = valueTypes[idx]; - if (!rv) { + if (rv == &invalidValueType) { // No need for mutex protection - the most we can lose is a valueType instance // TODO: Investigate the performance/memory characteristics of // removing the preallocated array - if (const QMetaObject *mo = metaObjectForMetaType(idx)) { - rv = new QQmlValueType(idx, mo); - valueTypes[idx] = rv; - } + if (isInternalType(idx)) + rv = valueTypes[idx] = nullptr; + else if (const QMetaObject *mo = metaObjectForMetaType(idx)) + rv = valueTypes[idx] = new QQmlValueType(idx, mo); + else + rv = valueTypes[idx] = nullptr; } return rv; @@ -204,6 +214,13 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, qmlRegisterValueTypeEnums<QQmlEasingValueType>(uri, versionMajor, versionMinor, "Easing"); } +QQmlValueType::QQmlValueType() : + _metaObject(nullptr), + gadgetPtr(nullptr), + metaType(QMetaType::UnknownType) +{ +} + QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) : gadgetPtr(QMetaType::create(typeId)) , metaType(typeId) @@ -221,7 +238,7 @@ QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) QQmlValueType::~QQmlValueType() { QObjectPrivate *op = QObjectPrivate::get(this); - Q_ASSERT(op->metaObject == this); + Q_ASSERT(op->metaObject == nullptr || op->metaObject == this); op->metaObject = nullptr; ::free(const_cast<QMetaObject *>(_metaObject)); metaType.destroy(gadgetPtr); |