aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltype.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmltype.cpp')
-rw-r--r--src/qml/qml/qqmltype.cpp838
1 files changed, 838 insertions, 0 deletions
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
new file mode 100644
index 0000000000..533c3909ba
--- /dev/null
+++ b/src/qml/qml/qqmltype.cpp
@@ -0,0 +1,838 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qqmltype_p_p.h"
+
+#include <QtQml/qjsvalue.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlcomponent.h>
+
+#include <private/qqmlcustomparser_p.h>
+#include <private/qqmldata_p.h>
+#include <private/qqmlmetatypedata_p.h>
+#include <private/qqmlpropertycache_p.h>
+#include <private/qqmltypedata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
+ : regType(type)
+{
+ switch (type) {
+ case QQmlType::CppType:
+ extraData.cppTypeData = new QQmlCppTypeData;
+ extraData.cppTypeData->allocationSize = 0;
+ extraData.cppTypeData->newFunc = nullptr;
+ extraData.cppTypeData->createValueTypeFunc = nullptr;
+ extraData.cppTypeData->parserStatusCast = -1;
+ extraData.cppTypeData->extFunc = nullptr;
+ extraData.cppTypeData->extMetaObject = nullptr;
+ extraData.cppTypeData->customParser = nullptr;
+ extraData.cppTypeData->attachedPropertiesFunc = nullptr;
+ extraData.cppTypeData->attachedPropertiesType = nullptr;
+ extraData.cppTypeData->propertyValueSourceCast = -1;
+ extraData.cppTypeData->propertyValueInterceptorCast = -1;
+ extraData.cppTypeData->finalizerCast = -1;
+ extraData.cppTypeData->registerEnumClassesUnscoped = true;
+ extraData.cppTypeData->registerEnumsFromRelatedTypes = true;
+ break;
+ case QQmlType::SingletonType:
+ case QQmlType::CompositeSingletonType:
+ extraData.singletonTypeData = new QQmlSingletonTypeData;
+ extraData.singletonTypeData->singletonInstanceInfo = nullptr;
+ extraData.singletonTypeData->extFunc = nullptr;
+ extraData.singletonTypeData->extMetaObject = nullptr;
+ break;
+ case QQmlType::InterfaceType:
+ extraData.interfaceTypeData = nullptr;
+ break;
+ case QQmlType::CompositeType:
+ new (&extraData.compositeTypeData) QUrl();
+ break;
+ case QQmlType::InlineComponentType:
+ new (&extraData.inlineComponentTypeData) QUrl();
+ break;
+ case QQmlType::SequentialContainerType:
+ new (&extraData.sequentialContainerTypeData) QMetaSequence();
+ break;
+ default: qFatal("QQmlTypePrivate Internal Error.");
+ }
+}
+
+QQmlTypePrivate::~QQmlTypePrivate()
+{
+ delete enums.fetchAndStoreAcquire(nullptr);
+ delete proxyMetaObjects.fetchAndStoreAcquire(nullptr);
+
+ if (const QtPrivate::QMetaTypeInterface *iface = typeId.iface()) {
+ if (iface->metaObjectFn == &dynamicQmlMetaObject)
+ QQmlMetaType::unregisterInternalCompositeType(typeId, listId);
+ }
+
+ switch (regType) {
+ case QQmlType::CppType:
+ delete extraData.cppTypeData->customParser;
+ delete extraData.cppTypeData;
+ break;
+ case QQmlType::SingletonType:
+ case QQmlType::CompositeSingletonType:
+ extraData.singletonTypeData->singletonInstanceInfo.reset();
+ delete extraData.singletonTypeData;
+ break;
+ case QQmlType::CompositeType:
+ extraData.compositeTypeData.~QUrl();
+ break;
+ case QQmlType::InlineComponentType:
+ extraData.inlineComponentTypeData.~QUrl();
+ break;
+ case QQmlType::SequentialContainerType:
+ extraData.sequentialContainerTypeData.~QMetaSequence();
+ break;
+ default: //Also InterfaceType, because it has no extra data
+ break;
+ }
+}
+
+QQmlType::QQmlType() = default;
+QQmlType::QQmlType(const QQmlType &) = default;
+QQmlType::QQmlType(QQmlType &&) = default;
+QQmlType &QQmlType::operator =(const QQmlType &other) = default;
+QQmlType &QQmlType::operator =(QQmlType &&other) = default;
+QQmlType::QQmlType(const QQmlTypePrivate *priv) : d(priv) {}
+QQmlType::~QQmlType() = default;
+
+QHashedString QQmlType::module() const
+{
+ if (!d)
+ return QHashedString();
+ return d->module;
+}
+
+QTypeRevision QQmlType::version() const
+{
+ if (!d)
+ return QTypeRevision();
+ return d->version;
+}
+
+bool QQmlType::availableInVersion(QTypeRevision version) const
+{
+ if (!d)
+ return false;
+
+ if (!version.hasMajorVersion())
+ return true;
+
+ if (version.majorVersion() != d->version.majorVersion())
+ return false;
+
+ return !version.hasMinorVersion() || version.minorVersion() >= d->version.minorVersion();
+}
+
+bool QQmlType::availableInVersion(const QHashedStringRef &module, QTypeRevision version) const
+{
+ if (!d || module != d->module)
+ return false;
+
+ return availableInVersion(version);
+}
+
+QQmlType QQmlTypePrivate::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
+{
+ Q_ASSERT(isComposite());
+ if (!engine)
+ return QQmlType();
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
+ if (td.isNull() || !td->isComplete())
+ return QQmlType();
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ return QQmlMetaType::qmlType(mo);
+}
+
+QQmlPropertyCache::ConstPtr QQmlTypePrivate::compositePropertyCache(
+ QQmlEnginePrivate *engine) const
+{
+ // similar logic to resolveCompositeBaseType
+ Q_ASSERT(isComposite());
+ if (!engine)
+ return nullptr;
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
+ if (td.isNull() || !td->isComplete())
+ return nullptr;
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ return compilationUnit->rootPropertyCache();
+}
+
+static bool isPropertyRevisioned(const QMetaObject *mo, int index)
+{
+ return mo->property(index).revision();
+}
+
+const QQmlTypePrivate::ProxyMetaObjects *QQmlTypePrivate::init() const
+{
+ if (const ProxyMetaObjects *result = proxyMetaObjects.loadRelaxed())
+ return result;
+
+ ProxyMetaObjects *proxies = new ProxyMetaObjects;
+ auto finalize = [this, proxies]() -> const ProxyMetaObjects *{
+ const ProxyMetaObjects *concurrentModification;
+ if (proxyMetaObjects.testAndSetOrdered(nullptr, proxies, concurrentModification))
+ return proxies;
+
+ delete proxies;
+ return concurrentModification;
+ };
+
+ const QMetaObject *mo = baseMetaObject;
+ if (!mo) {
+ // version 0 singleton type without metaobject information
+ return finalize();
+ }
+
+ QList<QQmlProxyMetaObject::ProxyData> metaObjects;
+
+ auto setupExtendedMetaObject = [&](const QMetaObject *extMetaObject,
+ QObject *(*extFunc)(QObject *)) {
+ if (!extMetaObject)
+ return;
+
+ // XXX - very inefficient
+ QMetaObjectBuilder builder;
+ QQmlMetaType::clone(builder, extMetaObject, extMetaObject, extMetaObject,
+ extFunc ? QQmlMetaType::CloneAll : QQmlMetaType::CloneEnumsOnly);
+ QMetaObject *mmo = builder.toMetaObject();
+ mmo->d.superdata = mo;
+ QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 };
+ metaObjects << data;
+ QQmlMetaType::registerMetaObjectForType(mmo, const_cast<QQmlTypePrivate *>(this));
+ };
+
+ if (regType == QQmlType::SingletonType)
+ setupExtendedMetaObject(extraData.singletonTypeData->extMetaObject, extraData.singletonTypeData->extFunc);
+ else if (regType == QQmlType::CppType)
+ setupExtendedMetaObject(extraData.cppTypeData->extMetaObject, extraData.cppTypeData->extFunc);
+
+ metaObjects.append(QQmlMetaType::proxyData(
+ mo, baseMetaObject, metaObjects.isEmpty() ? nullptr
+ : metaObjects.constLast().metaObject));
+
+ for (int ii = 0; ii < metaObjects.size(); ++ii) {
+ metaObjects[ii].propertyOffset =
+ metaObjects.at(ii).metaObject->propertyOffset();
+ metaObjects[ii].methodOffset =
+ metaObjects.at(ii).metaObject->methodOffset();
+ }
+
+ bool containsRevisionedAttributes = false;
+
+ // Check for revisioned details
+ {
+ const QMetaObject *mo = nullptr;
+ if (metaObjects.isEmpty())
+ mo = baseMetaObject;
+ else
+ mo = metaObjects.constFirst().metaObject;
+
+ for (int ii = 0; !containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
+ if (isPropertyRevisioned(mo, ii))
+ containsRevisionedAttributes = true;
+ }
+
+ for (int ii = 0; !containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
+ if (mo->method(ii).revision() != 0)
+ containsRevisionedAttributes = true;
+ }
+ }
+
+ proxies->data = std::move(metaObjects);
+ proxies->containsRevisionedAttributes = containsRevisionedAttributes;
+
+ return finalize();
+}
+
+const QQmlTypePrivate::Enums *QQmlTypePrivate::initEnums(QQmlEnginePrivate *engine) const
+{
+ if (const Enums *result = enums.loadRelaxed())
+ return result;
+
+ QQmlPropertyCache::ConstPtr cache;
+ if (isComposite()) {
+ cache = compositePropertyCache(engine);
+ if (!cache)
+ return nullptr; // Composite type not ready, yet.
+ }
+
+ Enums *newEnums = new Enums;
+
+ // beware: It could be a singleton type without metaobject
+
+ if (cache)
+ insertEnumsFromPropertyCache(newEnums, cache);
+
+ if (baseMetaObject) {
+ // init() can add to the metaObjects list. Therefore, check proxies->data only below
+ const ProxyMetaObjects *proxies = init();
+ insertEnums(
+ newEnums,
+ proxies->data.isEmpty() ? baseMetaObject : proxies->data.constFirst().metaObject);
+ }
+
+ const Enums *concurrentModification;
+ if (enums.testAndSetOrdered(nullptr, newEnums, concurrentModification))
+ return newEnums;
+
+ delete newEnums;
+ return concurrentModification;
+}
+
+void QQmlTypePrivate::insertEnums(Enums *enums, const QMetaObject *metaObject) const
+{
+ // Add any enum values defined by 'related' classes
+ if (regType != QQmlType::CppType || extraData.cppTypeData->registerEnumsFromRelatedTypes) {
+ if (const auto *related = metaObject->d.relatedMetaObjects) {
+ while (const QMetaObject *relatedMetaObject = *related) {
+ insertEnums(enums, relatedMetaObject);
+ ++related;
+ }
+ }
+ }
+
+ QSet<QString> localEnums;
+ const QMetaObject *localMetaObject = nullptr;
+
+ // ### TODO (QTBUG-123294): track this at instance creation time
+ auto shouldSingletonAlsoRegisterUnscoped = [&](){
+ Q_ASSERT(regType == QQmlType::SingletonType);
+ if (!baseMetaObject)
+ return true;
+ int idx = baseMetaObject->indexOfClassInfo("RegisterEnumClassesUnscoped");
+ if (idx == -1)
+ return true;
+ if (qstrcmp(baseMetaObject->classInfo(idx).value(), "false") == 0)
+ return false;
+ return true;
+ };
+
+ // Add any enum values defined by this class, overwriting any inherited values
+ for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
+ QMetaEnum e = metaObject->enumerator(ii);
+ const bool isScoped = e.isScoped();
+ QStringHash<int> *scoped = isScoped ? new QStringHash<int>() : nullptr;
+
+ // We allow enums in sub-classes to overwrite enums from base-classes, such as
+ // ListView.Center (from enum PositionMode) overwriting Item.Center (from enum TransformOrigin).
+ // This is acceptable because the _use_ of the enum from the QML side requires qualification
+ // anyway, i.e. ListView.Center vs. Item.Center.
+ // However if a class defines two enums with the same value, then that must produce a warning
+ // because it represents a valid conflict.
+ if (e.enclosingMetaObject() != localMetaObject) {
+ localEnums.clear();
+ localMetaObject = e.enclosingMetaObject();
+ }
+ const bool shouldRegisterUnscoped = !isScoped
+ || (regType == QQmlType::CppType && extraData.cppTypeData->registerEnumClassesUnscoped)
+ || (regType == QQmlType::SingletonType && shouldSingletonAlsoRegisterUnscoped())
+ ;
+
+ for (int jj = 0; jj < e.keyCount(); ++jj) {
+ const QString key = QString::fromUtf8(e.key(jj));
+ const int value = e.value(jj);
+ if (shouldRegisterUnscoped) {
+ if (localEnums.contains(key)) {
+ auto existingEntry = enums->enums.find(key);
+ if (existingEntry != enums->enums.end() && existingEntry.value() != value) {
+ qWarning("Previously registered enum will be overwritten due to name clash: %s.%s", metaObject->className(), key.toUtf8().constData());
+ createEnumConflictReport(metaObject, key);
+ }
+ } else {
+ localEnums.insert(key);
+ }
+ enums->enums.insert(key, value);
+ }
+ if (isScoped)
+ scoped->insert(key, value);
+ }
+
+ if (isScoped) {
+ enums->scopedEnums << scoped;
+ enums->scopedEnumIndex.insert(QString::fromUtf8(e.name()), enums->scopedEnums.size()-1);
+ }
+ }
+}
+
+void QQmlTypePrivate::createListOfPossibleConflictingItems(const QMetaObject *metaObject, QList<EnumInfo> &enumInfoList, QStringList path) const
+{
+ path.append(QString::fromUtf8(metaObject->className()));
+
+ if (metaObject->d.relatedMetaObjects) {
+ const auto *related = metaObject->d.relatedMetaObjects;
+ if (related) {
+ while (*related)
+ createListOfPossibleConflictingItems(*related++, enumInfoList, path);
+ }
+ }
+
+ for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
+ const auto e = metaObject->enumerator(ii);
+
+ for (int jj = 0; jj < e.keyCount(); ++jj) {
+ const QString key = QString::fromUtf8(e.key(jj));
+
+ EnumInfo enumInfo;
+ enumInfo.metaObjectName = QString::fromUtf8(metaObject->className());
+ enumInfo.enumName = QString::fromUtf8(e.name());
+ enumInfo.enumKey = key;
+ enumInfo.scoped = e.isScoped();
+ enumInfo.path = path;
+ enumInfo.metaEnumScope = QString::fromUtf8(e.scope());
+ enumInfoList.append(enumInfo);
+ }
+ }
+}
+
+void QQmlTypePrivate::createEnumConflictReport(const QMetaObject *metaObject, const QString &conflictingKey) const
+{
+ QList<EnumInfo> enumInfoList;
+
+ if (baseMetaObject) // prefer baseMetaObject if available
+ metaObject = baseMetaObject;
+
+ if (!metaObject) { // If there is no metaObject at all return early
+ qWarning() << "No meta object information available. Skipping conflict analysis.";
+ return;
+ }
+
+ createListOfPossibleConflictingItems(metaObject, enumInfoList, QStringList());
+
+ qWarning().noquote() << QLatin1String("Possible conflicting items:");
+ // find items with conflicting key
+ for (const auto &i : std::as_const(enumInfoList)) {
+ if (i.enumKey == conflictingKey)
+ qWarning().noquote().nospace() << " " << i.metaObjectName << "." << i.enumName << "." << i.enumKey << " from scope "
+ << i.metaEnumScope << " injected by " << i.path.join(QLatin1String("->"));
+ }
+}
+
+void QQmlTypePrivate::insertEnumsFromPropertyCache(
+ Enums *enums, const QQmlPropertyCache::ConstPtr &cache) const
+{
+ const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
+
+ for (const QQmlPropertyCache *currentCache = cache.data();
+ currentCache && currentCache->metaObject() != cppMetaObject;
+ currentCache = currentCache->parent().data()) {
+
+ int count = currentCache->qmlEnumCount();
+ for (int ii = 0; ii < count; ++ii) {
+ QStringHash<int> *scoped = new QStringHash<int>();
+ QQmlEnumData *enumData = currentCache->qmlEnum(ii);
+
+ for (int jj = 0; jj < enumData->values.size(); ++jj) {
+ const QQmlEnumValue &value = enumData->values.at(jj);
+ enums->enums.insert(value.namedValue, value.value);
+ scoped->insert(value.namedValue, value.value);
+ }
+ enums->scopedEnums << scoped;
+ enums->scopedEnumIndex.insert(enumData->name, enums->scopedEnums.size()-1);
+ }
+ }
+ insertEnums(enums, cppMetaObject);
+}
+
+void QQmlTypePrivate::setName(const QString &uri, const QString &element)
+{
+ module = uri;
+ elementName = element;
+ name = uri.isEmpty() ? element : (uri + QLatin1Char('/') + element);
+}
+
+QByteArray QQmlType::typeName() const
+{
+ if (d) {
+ if (d->regType == SingletonType || d->regType == CompositeSingletonType)
+ return d->extraData.singletonTypeData->singletonInstanceInfo->typeName;
+ else if (d->baseMetaObject)
+ return d->baseMetaObject->className();
+ }
+ return QByteArray();
+}
+
+QString QQmlType::elementName() const
+{
+ if (!d)
+ return QString();
+ return d->elementName;
+}
+
+QString QQmlType::qmlTypeName() const
+{
+ if (!d)
+ return QString();
+ return d->name;
+}
+
+/*!
+ \internal
+ Allocates and initializes an object if the type is creatable.
+ Returns a pointer to the object, or nullptr if the type was
+ not creatable.
+ */
+QObject *QQmlType::create() const
+{
+ void *unused;
+ return create(&unused, 0);
+}
+
+/*!
+ \internal
+ \brief Like create without arguments, but allocates some extra space after the object.
+ \param memory An out-only argument. *memory will point to the start of the additionally
+ allocated memory.
+ \param additionalMemory The amount of extra memory in bytes that shoudld be allocated.
+
+ \note This function is used to allocate the QQmlData next to the object in the
+ QQmlObjectCreator.
+
+ \overload
+ */
+QObject *QQmlType::create(void **memory, size_t additionalMemory) const
+{
+ if (!d || !isCreatable())
+ return nullptr;
+
+ QObject *rv = (QObject *)operator new(d->extraData.cppTypeData->allocationSize + additionalMemory);
+ d->extraData.cppTypeData->newFunc(rv, d->extraData.cppTypeData->userdata);
+
+ createProxy(rv);
+ *memory = ((char *)rv) + d->extraData.cppTypeData->allocationSize;
+ return rv;
+}
+
+/*!
+ \internal
+ Like create, but also allocates memory behind the object, constructs a QQmlData there
+ and lets the objects declarativeData point to the newly created QQmlData.
+ */
+QObject *QQmlType::createWithQQmlData() const
+{
+ void *ddataMemory = nullptr;
+ auto instance = create(&ddataMemory, sizeof(QQmlData));
+ if (!instance)
+ return nullptr;
+ QObjectPrivate* p = QObjectPrivate::get(instance);
+ Q_ASSERT(!p->isDeletingChildren);
+ if (!p->declarativeData)
+ p->declarativeData = new (ddataMemory) QQmlData(QQmlData::DoesNotOwnMemory);
+ return instance;
+}
+
+QQmlType::SingletonInstanceInfo::ConstPtr QQmlType::singletonInstanceInfo() const
+{
+ if (!d)
+ return {};
+ if (d->regType != SingletonType && d->regType != CompositeSingletonType)
+ return {};
+ return d->extraData.singletonTypeData->singletonInstanceInfo;
+}
+
+QQmlCustomParser *QQmlType::customParser() const
+{
+ if (!d)
+ return nullptr;
+ if (d->regType != CppType)
+ return nullptr;
+ return d->extraData.cppTypeData->customParser;
+}
+
+QQmlType::CreateValueTypeFunc QQmlType::createValueTypeFunction() const
+{
+ if (!d || d->regType != CppType)
+ return nullptr;
+ return d->extraData.cppTypeData->createValueTypeFunc;
+}
+
+bool QQmlType::canConstructValueType() const
+{
+ if (!d || d->regType != CppType)
+ return false;
+ return d->extraData.cppTypeData->constructValueType;
+}
+
+bool QQmlType::canPopulateValueType() const
+{
+ if (!d || d->regType != CppType)
+ return false;
+ return d->extraData.cppTypeData->populateValueType;
+}
+
+QQmlType::CreateFunc QQmlType::createFunction() const
+{
+ if (!d || d->regType != CppType)
+ return nullptr;
+ return d->extraData.cppTypeData->newFunc;
+}
+
+QString QQmlType::noCreationReason() const
+{
+ if (!d || d->regType != CppType)
+ return QString();
+ return d->extraData.cppTypeData->noCreationReason;
+}
+
+bool QQmlType::isCreatable() const
+{
+ return d && d->regType == CppType && d->extraData.cppTypeData->newFunc;
+}
+
+QQmlType::ExtensionFunc QQmlType::extensionFunction() const
+{
+ if (!d)
+ return nullptr;
+
+ switch (d->regType) {
+ case CppType:
+ return d->extraData.cppTypeData->extFunc;
+ case SingletonType:
+ return d->extraData.singletonTypeData->extFunc;
+ default:
+ return nullptr;
+ }
+}
+
+const QMetaObject *QQmlType::extensionMetaObject() const
+{
+ if (!d)
+ return nullptr;
+
+ switch (d->regType) {
+ case CppType:
+ return d->extraData.cppTypeData->extMetaObject;
+ case SingletonType:
+ return d->extraData.singletonTypeData->extMetaObject;
+ default:
+ return nullptr;
+ }
+}
+
+bool QQmlType::isExtendedType() const
+{
+ return d && !d->init()->data.isEmpty();
+}
+
+bool QQmlType::isSingleton() const
+{
+ return d && (d->regType == SingletonType || d->regType == CompositeSingletonType);
+}
+
+bool QQmlType::isInterface() const
+{
+ return d && d->regType == InterfaceType;
+}
+
+bool QQmlType::isComposite() const
+{
+ return d && d->isComposite();
+}
+
+bool QQmlType::isCompositeSingleton() const
+{
+ // if the outer type is a composite singleton, d->regType will indicate that even for
+ // the inline component type
+ // however, inline components can -at least for now- never be singletons
+ // so we just do one additional check
+ return d && d->regType == CompositeSingletonType && !isInlineComponentType();
+}
+
+bool QQmlType::isQObjectSingleton() const
+{
+ return d && d->regType == SingletonType && d->extraData.singletonTypeData->singletonInstanceInfo->qobjectCallback;
+}
+
+bool QQmlType::isQJSValueSingleton() const
+{
+ return d && d->regType == SingletonType && d->extraData.singletonTypeData->singletonInstanceInfo->scriptCallback;
+}
+
+bool QQmlType::isSequentialContainer() const
+{
+ return d && d->regType == SequentialContainerType;
+}
+
+bool QQmlType::isValueType() const
+{
+ return d && d->isValueType();
+}
+
+QMetaType QQmlType::typeId() const
+{
+ return d ? d->typeId : QMetaType{};
+}
+
+QMetaType QQmlType::qListTypeId() const
+{
+ return d ? d->listId : QMetaType{};
+}
+
+QMetaSequence QQmlType::listMetaSequence() const
+{
+ return isSequentialContainer() ? d->extraData.sequentialContainerTypeData : QMetaSequence();
+}
+
+const QMetaObject *QQmlType::metaObject() const
+{
+ return d ? d->metaObject() : nullptr;
+}
+
+const QMetaObject *QQmlType::metaObjectForValueType() const
+{
+ Q_ASSERT(d);
+ return d->metaObjectForValueType();
+}
+
+const QMetaObject *QQmlType::baseMetaObject() const
+{
+ return d ? d->baseMetaObject : nullptr;
+}
+
+bool QQmlType::containsRevisionedAttributes() const
+{
+ return d && d->init()->containsRevisionedAttributes;
+}
+
+QTypeRevision QQmlType::metaObjectRevision() const
+{
+ return d ? d->revision : QTypeRevision();
+}
+
+QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const
+{
+ if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(engine) : nullptr)
+ return base->extraData.cppTypeData->attachedPropertiesFunc;
+ return nullptr;
+}
+
+const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const
+{
+ if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(engine) : nullptr)
+ return base->extraData.cppTypeData->attachedPropertiesType;
+ return nullptr;
+}
+
+int QQmlType::parserStatusCast() const
+{
+ if (!d || d->regType != CppType)
+ return -1;
+ return d->extraData.cppTypeData->parserStatusCast;
+}
+
+int QQmlType::propertyValueSourceCast() const
+{
+ if (!d || d->regType != CppType)
+ return -1;
+ return d->extraData.cppTypeData->propertyValueSourceCast;
+}
+
+int QQmlType::propertyValueInterceptorCast() const
+{
+ if (!d || d->regType != CppType)
+ return -1;
+ return d->extraData.cppTypeData->propertyValueInterceptorCast;
+}
+
+int QQmlType::finalizerCast() const
+{
+ if (!d || d->regType != CppType)
+ return -1;
+ return d->extraData.cppTypeData->finalizerCast;
+}
+
+const char *QQmlType::interfaceIId() const
+{
+ if (!d || d->regType != InterfaceType)
+ return nullptr;
+ return d->extraData.interfaceTypeData;
+}
+
+int QQmlType::index() const
+{
+ return d ? d->index : -1;
+}
+
+bool QQmlType::isInlineComponentType() const {
+ return d ? d->regType == QQmlType::InlineComponentType : false;
+}
+
+QUrl QQmlType::sourceUrl() const
+{
+ return d ? d->sourceUrl() : QUrl();
+}
+
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
+{
+ return QQmlTypePrivate::enumValue(d, engine, name, ok);
+}
+
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
+{
+ return QQmlTypePrivate::enumValue(d, engine, name, ok);
+}
+
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
+{
+ return QQmlTypePrivate::enumValue(d, engine, name, ok);
+}
+
+int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
+{
+ return QQmlTypePrivate::scopedEnumIndex(d, engine, name, ok);
+}
+
+int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+{
+ return QQmlTypePrivate::scopedEnumIndex(d, engine, name, ok);
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const
+{
+ return QQmlTypePrivate::scopedEnumValue(d, engine, index, name, ok);
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const
+{
+ return QQmlTypePrivate::scopedEnumValue(d, engine, index, name, ok);
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QHashedStringRef &scopedEnumName, const QHashedStringRef &name, bool *ok) const
+{
+ return QQmlTypePrivate::scopedEnumValue(d, engine, scopedEnumName, name, ok);
+}
+
+void QQmlType::refHandle(const QQmlTypePrivate *priv)
+{
+ if (priv)
+ priv->addref();
+}
+
+void QQmlType::derefHandle(const QQmlTypePrivate *priv)
+{
+ if (priv)
+ priv->release();
+}
+
+int QQmlType::refCount(const QQmlTypePrivate *priv)
+{
+ if (priv)
+ return priv->count();
+ return -1;
+}
+
+void QQmlType::createProxy(QObject *instance) const
+{
+ const QQmlTypePrivate::ProxyMetaObjects *proxies = d->init();
+ if (!proxies->data.isEmpty())
+ (void)new QQmlProxyMetaObject(instance, &proxies->data);
+}
+
+QT_END_NAMESPACE