diff options
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 174 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatypedata.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatypedata_p.h | 19 | ||||
-rw-r--r-- | src/qml/qml/qqmltype.cpp | 125 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p.h | 17 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p_p.h | 2 |
7 files changed, 183 insertions, 163 deletions
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index f7b5ee8bf0..35340aed47 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -81,6 +81,129 @@ private: LockedData *data = nullptr; }; +static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, + const QQmlPrivate::RegisterInterface &type) +{ + auto *d = new QQmlTypePrivate(QQmlType::InterfaceType); + d->iid = type.iid; + d->typeId = type.typeId; + d->listId = type.listId; + d->isSetup = true; + d->version_maj = 0; + d->version_min = 0; + data->registerType(d); + return d; +} + +static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName, + const QQmlPrivate::RegisterSingletonType &type) +{ + auto *d = new QQmlTypePrivate(QQmlType::SingletonType); + data->registerType(d); + + d->elementName = elementName; + d->module = QString::fromUtf8(type.uri); + + d->version_maj = type.versionMajor; + d->version_min = type.versionMinor; + + if (type.qobjectApi) { + if (type.version >= 1) // static metaobject added in version 1 + d->baseMetaObject = type.instanceMetaObject; + if (type.version >= 2) // typeId added in version 2 + d->typeId = type.typeId; + if (type.version >= 2) // revisions added in version 2 + d->revision = type.revision; + } + + d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; + d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi; + d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi; + d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); + d->extraData.sd->singletonInstanceInfo->instanceMetaObject + = (type.qobjectApi && type.version >= 1) ? type.instanceMetaObject : nullptr; + + return d; +} + +static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName, + const QQmlPrivate::RegisterType &type) +{ + QQmlTypePrivate *d = new QQmlTypePrivate(QQmlType::CppType); + data->registerType(d); + d->elementName = elementName; + d->module = QString::fromUtf8(type.uri); + + d->version_maj = type.versionMajor; + d->version_min = type.versionMinor; + if (type.version >= 1) // revisions added in version 1 + d->revision = type.revision; + d->typeId = type.typeId; + d->listId = type.listId; + d->extraData.cd->allocationSize = type.objectSize; + d->extraData.cd->newFunc = type.create; + d->extraData.cd->noCreationReason = type.noCreationReason; + d->baseMetaObject = type.metaObject; + d->extraData.cd->attachedPropertiesFunc = type.attachedPropertiesFunction; + d->extraData.cd->attachedPropertiesType = type.attachedPropertiesMetaObject; + if (d->extraData.cd->attachedPropertiesType) { + d->extraData.cd->attachedPropertiesId = data->attachedPropertyId(d->baseMetaObject, + d->index); + } else { + d->extraData.cd->attachedPropertiesId = -1; + } + d->extraData.cd->parserStatusCast = type.parserStatusCast; + d->extraData.cd->propertyValueSourceCast = type.valueSourceCast; + d->extraData.cd->propertyValueInterceptorCast = type.valueInterceptorCast; + d->extraData.cd->extFunc = type.extensionObjectCreate; + d->extraData.cd->customParser = type.customParser; + d->extraData.cd->registerEnumClassesUnscoped = true; + + if (type.extensionMetaObject) + d->extraData.cd->extMetaObject = type.extensionMetaObject; + + // Check if the user wants only scoped enum classes + if (d->baseMetaObject) { + auto indexOfClassInfo = d->baseMetaObject->indexOfClassInfo("RegisterEnumClassesUnscoped"); + if (indexOfClassInfo != -1 && QString::fromUtf8(d->baseMetaObject->classInfo(indexOfClassInfo).value()) == QLatin1String("false")) + d->extraData.cd->registerEnumClassesUnscoped = false; + } + + return d; +} + +static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName, + const QQmlPrivate::RegisterCompositeType &type) +{ + auto *d = new QQmlTypePrivate(QQmlType::CompositeType); + data->registerType(d); + d->elementName = elementName; + + d->module = QString::fromUtf8(type.uri); + d->version_maj = type.versionMajor; + d->version_min = type.versionMinor; + + d->extraData.fd->url = QQmlTypeLoader::normalize(type.url); + return d; +} + +static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName, + const QQmlPrivate::RegisterCompositeSingletonType &type) +{ + auto *d = new QQmlTypePrivate(QQmlType::CompositeSingletonType); + data->registerType(d); + d->elementName = elementName; + d->module = QString::fromUtf8(type.uri); + + d->version_maj = type.versionMajor; + d->version_min = type.versionMinor; + + d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; + d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url); + d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); + return d; +} + void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) { @@ -182,9 +305,7 @@ QQmlType QQmlMetaType::registerInterface(const QQmlPrivate::RegisterInterface &t qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); QQmlMetaTypeDataPtr data; - - QQmlType dtype(data, type); - QQmlTypePrivate *priv = dtype.priv(); + QQmlTypePrivate *priv = createQQmlType(data, type); Q_ASSERT(priv); data->idToType.insert(priv->typeId, priv); @@ -200,7 +321,7 @@ QQmlType QQmlMetaType::registerInterface(const QQmlPrivate::RegisterInterface &t data->interfaces.setBit(type.typeId, true); data->lists.setBit(type.listId, true); - return dtype; + return QQmlType(priv); } QString registrationTypeString(QQmlType::RegistrationType typeType) @@ -321,13 +442,13 @@ QQmlType QQmlMetaType::registerType(const QQmlPrivate::RegisterType &type) if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor)) return QQmlType(); - QQmlType dtype(data, elementName, type); + QQmlTypePrivate *priv = createQQmlType(data, elementName, type); - addTypeToData(dtype.priv(), data); + addTypeToData(priv, data); if (!type.typeId) - data->idToType.insert(dtype.typeId(), dtype.priv()); + data->idToType.insert(priv->typeId, priv); - return dtype; + return QQmlType(priv); } QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingletonType &type) @@ -338,11 +459,11 @@ QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingleto if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor)) return QQmlType(); - QQmlType dtype(data, typeName, type); + QQmlTypePrivate *priv = createQQmlType(data, typeName, type); - addTypeToData(dtype.priv(), data); + addTypeToData(priv, data); - return dtype; + return QQmlType(priv); } QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type) @@ -357,14 +478,13 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri, typeName)) return QQmlType(); - QQmlType dtype(data, typeName, type); - - addTypeToData(dtype.priv(), data); + QQmlTypePrivate *priv = createQQmlType(data, typeName, type); + addTypeToData(priv, data); QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType); - files->insertMulti(QQmlTypeLoader::normalize(type.url), dtype.priv()); + files->insertMulti(QQmlTypeLoader::normalize(type.url), priv); - return dtype; + return QQmlType(priv); } QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterCompositeType &type) @@ -379,13 +499,13 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit if (!checkRegistration(QQmlType::CompositeType, data, fileImport?nullptr:type.uri, typeName, type.versionMajor)) return QQmlType(); - QQmlType dtype(data, typeName, type); - addTypeToData(dtype.priv(), data); + QQmlTypePrivate *priv = createQQmlType(data, typeName, type); + addTypeToData(priv, data); QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType); - files->insertMulti(QQmlTypeLoader::normalize(type.url), dtype.priv()); + files->insertMulti(QQmlTypeLoader::normalize(type.url), priv); - return dtype; + return QQmlType(priv); } void QQmlMetaType::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) @@ -484,6 +604,19 @@ void QQmlMetaType::registerUndeletableType(const QQmlType &dtype) data->undeletableTypes.insert(dtype); } +int QQmlMetaType::registerAttachedPropertyId(const QMetaObject *metaObject, int index) +{ + QQmlMetaTypeDataPtr data; + return data->attachedPropertyId(metaObject, index); +} + +bool QQmlMetaType::unregisterAttachedPropertyId(const QMetaObject *metaObject, int index) +{ + QQmlMetaTypeDataPtr data; + // This is run from the QQmlType dtor. QQmlTypes in user code can outlive QQmlMetaTypeData. + return data ? data->removeAttachedPropertyId(metaObject, index) : false; +} + static bool namespaceContainsRegistrations(const QQmlMetaTypeData *data, const QString &uri, int majorVersion) { @@ -664,7 +797,6 @@ QQmlType QQmlMetaType::typeForUrl(const QString &urlString, } data->registerType(priv); - priv->refCount.deref(); addTypeToData(priv, data); data->urlToType.insertMulti(url, priv); return QQmlType(priv); diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 2d22eb519f..dbfa10d044 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -88,6 +88,9 @@ public: static void registerUndeletableType(const QQmlType &dtype); + static int registerAttachedPropertyId(const QMetaObject *metaObject, int index); + static bool unregisterAttachedPropertyId(const QMetaObject *metaObject, int index); + static QList<QString> qmlTypeNames(); static QList<QQmlType> qmlTypes(); static QList<QQmlType> qmlSingletonTypes(); diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp index 989f1adf7c..f4f127ab9a 100644 --- a/src/qml/qml/qqmlmetatypedata.cpp +++ b/src/qml/qml/qqmlmetatypedata.cpp @@ -56,8 +56,13 @@ QQmlMetaTypeData::~QQmlMetaTypeData() for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = propertyCaches.begin(), end = propertyCaches.end(); it != end; ++it) (*it)->release(); + + // Do this before the attached properties disappear. + types.clear(); + undeletableTypes.clear(); } +// This expects a "fresh" QQmlTypePrivate and adopts its reference. void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv) { for (int i = 0; i < types.count(); ++i) { @@ -69,6 +74,7 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv) } types.append(QQmlType(priv)); priv->index = types.count() - 1; + priv->refCount.deref(); } QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject) diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h index cde6294c37..f61adada2c 100644 --- a/src/qml/qml/qqmlmetatypedata_p.h +++ b/src/qml/qml/qqmlmetatypedata_p.h @@ -128,8 +128,27 @@ struct QQmlMetaTypeData qWarning("%s", message.toUtf8().constData()); } + int attachedPropertyId(const QMetaObject *metaObject, int ownIndex) + { + auto iter = attachedPropertyIds.find(metaObject); + return (iter == attachedPropertyIds.end()) + ? *attachedPropertyIds.insert(metaObject, ownIndex) + : *iter; + } + + bool removeAttachedPropertyId(const QMetaObject *metaObject, int ownIndex) + { + auto iter = attachedPropertyIds.find(metaObject); + if (iter != attachedPropertyIds.end() && *iter == ownIndex) { + attachedPropertyIds.erase(iter); + return true; + } + return false; + } + private: QStringList *m_typeRegistrationFailures = nullptr; + QHash<const QMetaObject *, int> attachedPropertyIds; }; inline uint qHash(const QQmlMetaTypeData::VersionedUri &v) diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index 1c69cedcd6..2a1b4715d0 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -115,8 +115,6 @@ QJSValue QQmlType::SingletonInstanceInfo::scriptApi(QQmlEngine *e) const return scriptApis.value(e); } -QHash<const QMetaObject *, int> QQmlTypePrivate::attachedPropertyIds; - QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) : refCount(1), regType(type), iid(nullptr), typeId(0), listId(0), revision(0), containsRevisionedAttributes(false), baseMetaObject(nullptr), @@ -173,122 +171,6 @@ QQmlTypePrivate::~QQmlTypePrivate() } } -QQmlType::QQmlType(QQmlMetaTypeData *data, const QQmlPrivate::RegisterInterface &interface) - : d(new QQmlTypePrivate(InterfaceType)) -{ - d->iid = interface.iid; - d->typeId = interface.typeId; - d->listId = interface.listId; - d->isSetup = true; - d->version_maj = 0; - d->version_min = 0; - data->registerType(d); -} - -QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterSingletonType &type) - : d(new QQmlTypePrivate(SingletonType)) -{ - data->registerType(d); - - d->elementName = elementName; - d->module = QString::fromUtf8(type.uri); - - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; - - if (type.qobjectApi) { - if (type.version >= 1) // static metaobject added in version 1 - d->baseMetaObject = type.instanceMetaObject; - if (type.version >= 2) // typeId added in version 2 - d->typeId = type.typeId; - if (type.version >= 2) // revisions added in version 2 - d->revision = type.revision; - } - - d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo; - d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi; - d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi; - d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); - d->extraData.sd->singletonInstanceInfo->instanceMetaObject - = (type.qobjectApi && type.version >= 1) ? type.instanceMetaObject : nullptr; -} - -QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterCompositeSingletonType &type) - : d(new QQmlTypePrivate(CompositeSingletonType)) -{ - data->registerType(d); - - d->elementName = elementName; - d->module = QString::fromUtf8(type.uri); - - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; - - d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo; - d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url); - d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); -} - -QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterType &type) - : d(new QQmlTypePrivate(CppType)) -{ - data->registerType(d); - - d->elementName = elementName; - d->module = QString::fromUtf8(type.uri); - - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; - if (type.version >= 1) // revisions added in version 1 - d->revision = type.revision; - d->typeId = type.typeId; - d->listId = type.listId; - d->extraData.cd->allocationSize = type.objectSize; - d->extraData.cd->newFunc = type.create; - d->extraData.cd->noCreationReason = type.noCreationReason; - d->baseMetaObject = type.metaObject; - d->extraData.cd->attachedPropertiesFunc = type.attachedPropertiesFunction; - d->extraData.cd->attachedPropertiesType = type.attachedPropertiesMetaObject; - if (d->extraData.cd->attachedPropertiesType) { - auto iter = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject); - if (iter == QQmlTypePrivate::attachedPropertyIds.end()) - iter = QQmlTypePrivate::attachedPropertyIds.insert(d->baseMetaObject, d->index); - d->extraData.cd->attachedPropertiesId = *iter; - } else { - d->extraData.cd->attachedPropertiesId = -1; - } - d->extraData.cd->parserStatusCast = type.parserStatusCast; - d->extraData.cd->propertyValueSourceCast = type.valueSourceCast; - d->extraData.cd->propertyValueInterceptorCast = type.valueInterceptorCast; - d->extraData.cd->extFunc = type.extensionObjectCreate; - d->extraData.cd->customParser = type.customParser; - d->extraData.cd->registerEnumClassesUnscoped = true; - - if (type.extensionMetaObject) - d->extraData.cd->extMetaObject = type.extensionMetaObject; - - // Check if the user wants only scoped enum classes - if (d->baseMetaObject) { - auto indexOfClassInfo = d->baseMetaObject->indexOfClassInfo("RegisterEnumClassesUnscoped"); - if (indexOfClassInfo != -1 && QString::fromUtf8(d->baseMetaObject->classInfo(indexOfClassInfo).value()) == QLatin1String("false")) - d->extraData.cd->registerEnumClassesUnscoped = false; - } -} - -QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterCompositeType &type) - : d(new QQmlTypePrivate(CompositeType)) -{ - data->registerType(d); - - d->elementName = elementName; - - d->module = QString::fromUtf8(type.uri); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; - - d->extraData.fd->url = QQmlTypeLoader::normalize(type.url); -} - QQmlType::QQmlType() : d(nullptr) { @@ -325,11 +207,8 @@ QQmlType::~QQmlType() if (d && !d->refCount.deref()) { // If attached properties were successfully registered, deregister them. // (They may not have been registered if some other type used the same baseMetaObject) - if (d->regType == CppType && d->extraData.cd->attachedPropertiesType) { - auto it = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject); - if (it != QQmlTypePrivate::attachedPropertyIds.end() && *it == d->index) - QQmlTypePrivate::attachedPropertyIds.erase(it); - } + if (d->regType == CppType && d->extraData.cd->attachedPropertiesType) + QQmlMetaType::unregisterAttachedPropertyId(d->baseMetaObject, d->index); delete d; } } diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h index edc1b01a07..969c096aeb 100644 --- a/src/qml/qml/qqmltype_p.h +++ b/src/qml/qml/qqmltype_p.h @@ -60,7 +60,6 @@ QT_BEGIN_NAMESPACE -struct QQmlMetaTypeData; class QHashedCStringRef; class QQmlTypePrivate; class QHashedString; @@ -194,23 +193,7 @@ private: QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const; int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const; - friend class QQmlTypePrivate; - - friend QString registrationTypeString(RegistrationType); - friend bool checkRegistration(RegistrationType, QQmlMetaTypeData *, const char *, const QString &, int); - friend QQmlType registerType(const QQmlPrivate::RegisterType &); - friend QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &); - friend QQmlType registerInterface(const QQmlPrivate::RegisterInterface &); - friend int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &); friend uint qHash(const QQmlType &t, uint seed); - friend Q_QML_EXPORT void qmlClearTypeRegistrations(); - friend class QQmlMetaType; - - QQmlType(QQmlMetaTypeData *data, const QQmlPrivate::RegisterInterface &); - QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterSingletonType &); - QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterType &); - QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterCompositeType &); - QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterCompositeSingletonType &); QQmlTypePrivate *d; }; diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h index fd9b28c322..faff0808ec 100644 --- a/src/qml/qml/qqmltype_p_p.h +++ b/src/qml/qml/qqmltype_p_p.h @@ -129,8 +129,6 @@ public: mutable QStringHash<int> scopedEnumIndex; // maps from enum name to index in scopedEnums mutable QList<QStringHash<int>*> scopedEnums; - static QHash<const QMetaObject *, int> attachedPropertyIds; - struct PropertyCacheByMinorVersion { PropertyCacheByMinorVersion() : cache(nullptr), minorVersion(-1) {} |