5#include "ftw/qhashedstring_p.h"
6#include "jsapi/qjsmanagedvalue.h"
7#include "jsapi/qjsprimitivevalue.h"
11#include <private/qqmlextensionplugin_p.h>
12#include <private/qqmlmetatypedata_p.h>
13#include <private/qqmlpropertycachecreator_p.h>
14#include <private/qqmlscriptblob_p.h>
15#include <private/qqmlscriptdata_p.h>
16#include <private/qqmltype_p_p.h>
17#include <private/qqmltypemodule_p.h>
18#include <private/qqmlvaluetype_p.h>
20#include <QtCore/qcoreapplication.h>
21#include <QtCore/qmutex.h>
22#include <QtCore/qloggingcategory.h>
29
30
31
32
34struct LockedData :
private QQmlMetaTypeData
36 friend class QQmlMetaTypeDataPtr;
39Q_GLOBAL_STATIC(LockedData, metaTypeData)
40Q_GLOBAL_STATIC(QRecursiveMutex, metaTypeDataLock)
42struct ModuleUri :
public QString
44 ModuleUri(
const QString &string) : QString(string) {}
45 ModuleUri(
const std::unique_ptr<QQmlTypeModule> &module) : QString(module->module()) {}
67 LockedData *data =
nullptr;
71 const QQmlPrivate::RegisterInterface &type)
73 auto *d =
new QQmlTypePrivate(QQmlType::InterfaceType);
74 d->extraData.interfaceTypeData = type.iid;
75 d->typeId = type.typeId;
76 d->listId = type.listId;
77 d->module = QString::fromUtf8(type.uri);
78 d->version = type.version;
79 data->registerType(d);
84 QQmlMetaTypeData *data,
const QString &elementName,
85 const QQmlPrivate::RegisterSingletonType &type,
86 const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
88 auto *d =
new QQmlTypePrivate(QQmlType::SingletonType);
89 data->registerType(d);
91 d->setName(QString::fromUtf8(type.uri), elementName);
92 d->version = type.version;
94 if (type.qObjectApi) {
95 d->baseMetaObject = type.instanceMetaObject;
96 d->typeId = type.typeId;
97 d->revision = type.revision;
100 d->extraData.singletonTypeData->singletonInstanceInfo = siinfo;
101 d->extraData.singletonTypeData->extFunc = type.extensionObjectCreate;
102 d->extraData.singletonTypeData->extMetaObject = type.extensionMetaObject;
108 const QQmlPrivate::RegisterType &type)
110 QQmlTypePrivate *d =
new QQmlTypePrivate(QQmlType::CppType);
111 data->registerType(d);
112 d->setName(QString::fromUtf8(type.uri), elementName);
114 d->version = type.version;
115 d->revision = type.revision;
116 d->typeId = type.typeId;
117 d->listId = type.listId;
118 d->extraData.cppTypeData->allocationSize = type.objectSize;
119 d->extraData.cppTypeData->userdata = type.userdata;
120 d->extraData.cppTypeData->newFunc = type.create;
121 d->extraData.cppTypeData->noCreationReason = type.noCreationReason;
122 d->extraData.cppTypeData->createValueTypeFunc = type.createValueType;
123 d->baseMetaObject = type.metaObject;
124 d->extraData.cppTypeData->attachedPropertiesFunc = type.attachedPropertiesFunction;
125 d->extraData.cppTypeData->attachedPropertiesType = type.attachedPropertiesMetaObject;
126 d->extraData.cppTypeData->parserStatusCast = type.parserStatusCast;
127 d->extraData.cppTypeData->propertyValueSourceCast = type.valueSourceCast;
128 d->extraData.cppTypeData->propertyValueInterceptorCast = type.valueInterceptorCast;
129 d->extraData.cppTypeData->finalizerCast = type.has(QQmlPrivate::RegisterType::FinalizerCast)
132 d->extraData.cppTypeData->extFunc = type.extensionObjectCreate;
133 d->extraData.cppTypeData->customParser =
reinterpret_cast<QQmlCustomParser *>(type.customParser);
134 d->extraData.cppTypeData->registerEnumClassesUnscoped =
true;
135 d->extraData.cppTypeData->registerEnumsFromRelatedTypes =
true;
136 d->extraData.cppTypeData->constructValueType = type.has(QQmlPrivate::RegisterType::CreationMethod)
137 && type.creationMethod != QQmlPrivate::ValueTypeCreationMethod::None;
138 d->extraData.cppTypeData->populateValueType = type.has(QQmlPrivate::RegisterType::CreationMethod)
139 && type.creationMethod == QQmlPrivate::ValueTypeCreationMethod::Structured;
141 if (type.extensionMetaObject)
142 d->extraData.cppTypeData->extMetaObject = type.extensionMetaObject;
145 if (d->baseMetaObject) {
146 auto indexOfUnscoped = d->baseMetaObject->indexOfClassInfo(
"RegisterEnumClassesUnscoped");
147 if (indexOfUnscoped != -1
148 && qstrcmp(d->baseMetaObject->classInfo(indexOfUnscoped).value(),
"false") == 0) {
149 d->extraData.cppTypeData->registerEnumClassesUnscoped =
false;
152 auto indexOfRelated = d->baseMetaObject->indexOfClassInfo(
"RegisterEnumsFromRelatedTypes");
153 if (indexOfRelated != -1
154 && qstrcmp(d->baseMetaObject->classInfo(indexOfRelated).value(),
"false") == 0) {
155 d->extraData.cppTypeData->registerEnumsFromRelatedTypes =
false;
163 QQmlMetaTypeData *data,
const QUrl &url, QQmlTypePrivate *priv,
const QByteArray &className)
165 Q_ASSERT(!className.isEmpty());
166 QByteArray ptr = className +
'*';
167 QByteArray lst =
"QQmlListProperty<" + className +
'>';
169 QQmlMetaTypeData::CompositeMetaTypes &types = data->compositeMetaTypes[url];
171 Q_ASSERT(types.listType);
173 QMetaType::unregisterMetaType(QMetaType(types.type));
174 QMetaType::unregisterMetaType(QMetaType(types.listType));
176 types.type->name =
std::move(ptr);
177 types.type->QMetaTypeInterface::name = types.type->name.constData();
178 types.listType->name =
std::move(lst);
179 types.listType->QMetaTypeInterface::name = types.listType->name.constData();
185 QMetaType ptr_type(types.type);
186 QMetaType lst_type(types.listType);
192 priv->typeId = ptr_type;
193 priv->listId = lst_type;
197 const QQmlPrivate::RegisterCompositeType &type)
199 auto *d =
new QQmlTypePrivate(QQmlType::CompositeType);
200 data->registerType(d);
201 d->setName(QString::fromUtf8(type.uri), elementName);
202 d->version = type.version;
204 const QUrl normalized = QQmlMetaType::normalizedUrl(type.url);
205 d->extraData.compositeTypeData = normalized;
206 addQQmlMetaTypeInterfaces(
207 data, normalized, d, QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(normalized));
212 QQmlMetaTypeData *data,
const QString &elementName,
213 const QQmlPrivate::RegisterCompositeSingletonType &type,
214 const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
216 auto *d =
new QQmlTypePrivate(QQmlType::CompositeSingletonType);
217 data->registerType(d);
218 d->setName(QString::fromUtf8(type.uri), elementName);
220 d->version = type.version;
222 d->extraData.singletonTypeData->singletonInstanceInfo = siinfo;
223 const QUrl &url = siinfo->url;
224 addQQmlMetaTypeInterfaces(
225 data, url, d, QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(url));
229void QQmlMetaType::clone(QMetaObjectBuilder &builder,
const QMetaObject *mo,
230 const QMetaObject *ignoreStart,
const QMetaObject *ignoreEnd,
231 QQmlMetaType::ClonePolicy policy)
234 builder.setClassName(mo->className());
237 for (
int ii = mo->classInfoOffset(); ii < mo->classInfoCount(); ++ii) {
238 QMetaClassInfo info = mo->classInfo(ii);
240 int otherIndex = ignoreEnd->indexOfClassInfo(info.name());
241 if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) {
244 builder.addClassInfo(info.name(), info.value());
248 if (policy != QQmlMetaType::CloneEnumsOnly) {
250 for (
int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) {
251 QMetaMethod method = mo->method(ii);
254 QByteArray name = method.name();
258 for (
int ii = ignoreStart->methodOffset() + ignoreStart->methodCount();
259 !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount(); ++ii) {
261 QMetaMethod other = ignoreEnd->method(ii);
263 found = name == other.name();
266 QMetaMethodBuilder m = builder.addMethod(method);
268 m.setAccess(QMetaMethod::Private);
272 for (
int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) {
273 QMetaProperty property = mo->property(ii);
275 int otherIndex = ignoreEnd->indexOfProperty(property.name());
276 if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) {
277 builder.addProperty(QByteArray(
"__qml_ignore__") + property.name(),
281 builder.addProperty(property);
287 for (
int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
288 QMetaEnum enumerator = mo->enumerator(ii);
290 int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
291 if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
294 builder.addEnumerator(enumerator);
299void QQmlMetaType::qmlInsertModuleRegistration(
const QString &uri,
void (*registerFunction)())
301 QQmlMetaTypeDataPtr data;
302 if (data->moduleTypeRegistrationFunctions.contains(uri))
303 qFatal(
"Cannot add multiple registrations for %s", qPrintable(uri));
305 data->moduleTypeRegistrationFunctions.insert(uri, registerFunction);
308void QQmlMetaType::qmlRemoveModuleRegistration(
const QString &uri)
310 QQmlMetaTypeDataPtr data;
315 if (!data->moduleTypeRegistrationFunctions.remove(uri))
316 qFatal(
"Cannot remove multiple registrations for %s", qPrintable(uri));
319bool QQmlMetaType::qmlRegisterModuleTypes(
const QString &uri)
321 QQmlMetaTypeDataPtr data;
322 return data->registerModuleTypes(uri);
325void QQmlMetaType::clearTypeRegistrations()
328 QQmlMetaTypeDataPtr data;
330 data->uriToModule.clear();
332 data->idToType.clear();
333 data->nameToType.clear();
334 data->urlToType.clear();
335 data->speculativeInlineComponentTypes.clear();
336 data->metaObjectToType.clear();
337 data->undeletableTypes.clear();
338 data->propertyCaches.clear();
340 qDeleteAll(data->metaTypeToValueType);
341 data->metaTypeToValueType.clear();
343 data->moduleImports.clear();
345 data->clearCompositeTypes();
347 qDeleteAll(data->metaTypeToValueType);
348 data->metaTypeToValueType.clear();
350 data->clearCompositeMetaTypes();
353void QQmlMetaType::registerTypeAlias(
int typeIndex,
const QString &name)
355 QQmlMetaTypeDataPtr data;
356 const QQmlType type = data->types.value(typeIndex).type;
357 const QQmlTypePrivate *priv = type.priv();
358 data->nameToType.insert(name, priv);
361int QQmlMetaType::registerAutoParentFunction(
const QQmlPrivate::RegisterAutoParent &function)
363 if (function.structVersion > 1)
364 qFatal(
"qmlRegisterType(): Cannot mix incompatible QML versions.");
366 QQmlMetaTypeDataPtr data;
368 data->parentFunctions.append(function.function);
370 return data->parentFunctions.size() - 1;
373void QQmlMetaType::unregisterAutoParentFunction(
const QQmlPrivate::AutoParentFunction &function)
375 QQmlMetaTypeDataPtr data;
376 data->parentFunctions.removeOne(function);
379QQmlType QQmlMetaType::registerInterface(
const QQmlPrivate::RegisterInterface &type)
381 if (type.structVersion > 1)
382 qFatal(
"qmlRegisterType(): Cannot mix incompatible QML versions.");
384 QQmlMetaTypeDataPtr data;
385 QQmlTypePrivate *priv = createQQmlType(data, type);
389 data->idToType.insert(priv->typeId.id(), priv);
390 data->idToType.insert(priv->listId.id(), priv);
392 return QQmlType(priv);
398 if (typeType == QQmlType::CppType)
399 typeStr = QStringLiteral(
"element");
400 else if (typeType == QQmlType::SingletonType)
401 typeStr = QStringLiteral(
"singleton type");
402 else if (typeType == QQmlType::CompositeSingletonType)
403 typeStr = QStringLiteral(
"composite singleton type");
404 else if (typeType == QQmlType::SequentialContainerType)
405 typeStr = QStringLiteral(
"sequential container type");
407 typeStr = QStringLiteral(
"type");
413 QQmlType::RegistrationType typeType, QQmlMetaTypeData *data,
const char *uri,
414 const QString &typeName, QTypeRevision version, QMetaType::TypeFlags flags)
416 if (!typeName.isEmpty()) {
417 if (typeName.at(0).isLower() && (flags & QMetaType::PointerToQObject)) {
418 QString failure(QCoreApplication::translate(
"qmlRegisterType",
"Invalid QML %1 name \"%2\"; type names must begin with an uppercase letter"));
419 data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType), typeName));
423 if (typeName.at(0).isUpper()
424 && (flags & (QMetaType::IsGadget | QMetaType::PointerToGadget))) {
425 qCWarning(lcTypeRegistration).noquote()
426 << QCoreApplication::translate(
428 "Invalid QML %1 name \"%2\"; "
429 "value type names should begin with a lowercase letter")
430 .arg(registrationTypeString(typeType), typeName);
436 int typeNameLen = typeName.size();
437 for (
int ii = 0; ii < typeNameLen; ++ii) {
438 if (!(typeName.at(ii).isLetterOrNumber() || typeName.at(ii) == u'_')) {
439 QString failure(QCoreApplication::translate(
"qmlRegisterType",
"Invalid QML %1 name \"%2\""));
440 data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType), typeName));
446 if (uri && !typeName.isEmpty()) {
447 QString nameSpace = QString::fromUtf8(uri);
449 if (qqtm && qqtm->lockLevel() != QQmlTypeModule::LockLevel::Open) {
450 QString failure(QCoreApplication::translate(
452 "Cannot install %1 '%2' into protected module '%3' version '%4'"));
453 data->recordTypeRegFailure(failure
454 .arg(registrationTypeString(typeType), typeName, nameSpace)
455 .arg(version.majorVersion()));
465 const QHashedString &uri, QTypeRevision version, QQmlMetaTypeData *data)
469 return data->addTypeModule(std::make_unique<QQmlTypeModule>(uri, version.majorVersion()));
477 if (!type->elementName.isEmpty())
478 data->nameToType.insert(type->elementName, type);
480 if (type->baseMetaObject)
481 data->metaObjectToType.insert(type->baseMetaObject, type);
483 if (type->regType == QQmlType::SequentialContainerType) {
484 if (type->listId.isValid())
485 data->idToType.insert(type->listId.id(), type);
487 if (type->typeId.isValid())
488 data->idToType.insert(type->typeId.id(), type);
490 if (type->listId.flags().testFlag(QMetaType::IsQmlList))
491 data->idToType.insert(type->listId.id(), type);
494 if (!type->module.isEmpty()) {
495 const QHashedString &mod = type->module;
503QQmlType QQmlMetaType::registerType(
const QQmlPrivate::RegisterType &type)
505 if (type.structVersion >
int(QQmlPrivate::RegisterType::CurrentVersion))
506 qFatal(
"qmlRegisterType(): Cannot mix incompatible QML versions.");
508 QQmlMetaTypeDataPtr data;
510 QString elementName = QString::fromUtf8(type.elementName);
511 if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.version,
512 QMetaType(type.typeId).flags())) {
516 QQmlTypePrivate *priv = createQQmlType(data, elementName, type);
517 addTypeToData(priv, data);
519 return QQmlType(priv);
522QQmlType QQmlMetaType::registerSingletonType(
523 const QQmlPrivate::RegisterSingletonType &type,
524 const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
526 if (type.structVersion > 1)
527 qFatal(
"qmlRegisterType(): Cannot mix incompatible QML versions.");
529 QQmlMetaTypeDataPtr data;
531 QString typeName = QString::fromUtf8(type.typeName);
532 if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.version,
533 QMetaType(type.typeId).flags())) {
537 QQmlTypePrivate *priv = createQQmlType(data, typeName, type, siinfo);
539 addTypeToData(priv, data);
541 return QQmlType(priv);
544QQmlType QQmlMetaType::registerCompositeSingletonType(
545 const QQmlPrivate::RegisterCompositeSingletonType &type,
546 const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
548 if (type.structVersion > 1)
549 qFatal(
"qmlRegisterType(): Cannot mix incompatible QML versions.");
552 QQmlMetaTypeDataPtr data;
554 QString typeName = QString::fromUtf8(type.typeName);
555 if (!checkRegistration(
556 QQmlType::CompositeSingletonType, data, type.uri, typeName, type.version, {})) {
560 QQmlTypePrivate *priv = createQQmlType(data, typeName, type, siinfo);
561 addTypeToData(priv, data);
563 data->urlToType.insert(siinfo->url, priv);
565 return QQmlType(priv);
568QQmlType QQmlMetaType::registerCompositeType(
const QQmlPrivate::RegisterCompositeType &type)
570 if (type.structVersion > 1)
571 qFatal(
"qmlRegisterType(): Cannot mix incompatible QML versions.");
574 QQmlMetaTypeDataPtr data;
576 QString typeName = QString::fromUtf8(type.typeName);
577 if (!checkRegistration(QQmlType::CompositeType, data, type.uri, typeName, type.version, {}))
580 QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
581 addTypeToData(priv, data);
583 data->urlToType.insert(QQmlMetaType::normalizedUrl(type.url), priv);
585 return QQmlType(priv);
608 QQmlMetaTypeData *data,
const QUrl &url,
const QHashedStringRef &qualifiedType,
609 QQmlMetaType::CompositeTypeLookupMode mode, QList<QQmlError> *errors, QTypeRevision version)
611 const int dot = qualifiedType.indexOf(QLatin1Char(
'.'));
612 const QString typeName = dot < 0
613 ? qualifiedType.toString()
614 : QString(qualifiedType.constData() + dot + 1, qualifiedType.length() - dot - 1);
616 QStringList failures;
636 QQmlType::RegistrationType registrationType;
638 case QQmlMetaType::Singleton:
639 registrationType = QQmlType::CompositeSingletonType;
641 case QQmlMetaType::NonSingleton:
642 registrationType = QQmlType::CompositeType;
644 case QQmlMetaType::JavaScript:
645 registrationType = QQmlType::JavaScriptType;
648 Q_UNREACHABLE_RETURN(QQmlType());
651 if (checkRegistration(registrationType, data,
nullptr, typeName, version, {})) {
658 auto *priv =
new QQmlTypePrivate(registrationType);
659 addQQmlMetaTypeInterfaces(
660 data, url, priv, QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(url));
662 priv->setName(QString(), typeName);
663 priv->version = version;
666 case QQmlMetaType::Singleton: {
667 QQmlType::SingletonInstanceInfo::Ptr siinfo = QQmlType::SingletonInstanceInfo::create();
669 siinfo->typeName = typeName.toUtf8();
670 priv->extraData.singletonTypeData->singletonInstanceInfo =
671 QQmlType::SingletonInstanceInfo::ConstPtr(
672 siinfo.take(), QQmlType::SingletonInstanceInfo::ConstPtr::Adopt);
675 case QQmlMetaType::NonSingleton: {
676 priv->extraData.compositeTypeData = url;
679 case QQmlMetaType::JavaScript: {
680 priv->extraData.javaScriptTypeData = url;
685 data->registerType(priv);
686 addTypeToData(priv, data);
687 return QQmlType(priv);
695 error.setDescription(failures.join(u'\n'));
696 errors->prepend(error);
698 qWarning(
"%s", failures.join(u'\n').toLatin1().constData());
703QQmlType QQmlMetaType::findCompositeType(
704 const QUrl &url,
const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit,
705 CompositeTypeLookupMode mode)
707 const QUrl normalized = QQmlMetaType::normalizedUrl(url);
708 QQmlMetaTypeDataPtr data;
710 bool urlExists =
true;
711 auto found = data->urlToType.constFind(normalized);
712 if (found == data->urlToType.cend())
716 if (compilationUnit.isNull())
717 return QQmlType(*found);
718 const auto [begin, end]
719 = std::as_const(data->compositeTypes).equal_range(found.value()->typeId.iface());
721 return QQmlType(*found);
722 for (
auto it = begin; it != end; ++it) {
723 if (it.value() == compilationUnit)
724 return QQmlType(*found);
728 const QQmlType type = createTypeForUrl(
729 data, normalized, QHashedStringRef(), mode,
nullptr, QTypeRevision());
731 if (!urlExists && type.isValid())
732 data->urlToType.insert(normalized, type.priv());
739 QQmlTypePrivate *priv =
new QQmlTypePrivate(QQmlType::InlineComponentType);
740 priv->setName(QString(), url.fragment());
742 priv->extraData.inlineComponentTypeData = url;
743 data->registerType(priv);
745 addQQmlMetaTypeInterfaces(
746 data, url, priv, QQmlPropertyCacheCreatorBase::createClassNameForInlineComponent(url));
747 data->urlToType.insert(url, priv);
749 data->idToType.insert(priv->typeId.id(), priv);
750 data->idToType.insert(priv->listId.id(), priv);
752 return QQmlType(priv);
755QQmlType QQmlMetaType::findOrCreateFactualInlineComponentType(
756 const QUrl &url,
const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
758 QQmlMetaTypeDataPtr data;
762 const auto it = data->urlToType.constFind(url);
763 if (it == data->urlToType.constEnd())
764 return doRegisterInlineComponentType(data, url);
766 const auto [begin, end]
767 = std::as_const(data->compositeTypes).equal_range((*it)->typeId.iface());
769 data->speculativeInlineComponentTypes.remove(url);
770 return QQmlType(*it);
773 for (
auto jt = begin; jt != end; ++jt) {
774 if (*jt != compilationUnit)
777 data->speculativeInlineComponentTypes.remove(url);
778 return QQmlType(*it);
781 return doRegisterInlineComponentType(data, url);
784int QQmlMetaType::registerUnitCacheHook(
785 const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration)
787 if (hookRegistration.structVersion > 1)
788 qFatal(
"qmlRegisterType(): Cannot mix incompatible QML versions.");
790 QQmlMetaTypeDataPtr data;
791 data->lookupCachedQmlUnit << hookRegistration.lookupCachedQmlUnit;
795QQmlType QQmlMetaType::registerSequentialContainer(
796 const QQmlPrivate::RegisterSequentialContainer &container)
798 if (container.structVersion > 1)
799 qFatal(
"qmlRegisterSequenceContainer(): Cannot mix incompatible QML versions.");
801 QQmlMetaTypeDataPtr data;
803 if (!checkRegistration(QQmlType::SequentialContainerType, data, container.uri, QString(),
804 container.version, {})) {
808 QQmlTypePrivate *priv =
new QQmlTypePrivate(QQmlType::SequentialContainerType);
810 data->registerType(priv);
811 priv->setName(QString::fromUtf8(container.uri), QString());
812 priv->version = container.version;
813 priv->revision = container.revision;
814 priv->typeId = container.metaSequence.valueMetaType();
815 priv->listId = container.typeId;
816 priv->extraData.sequentialContainerTypeData = container.metaSequence;
818 addTypeToData(priv, data);
820 return QQmlType(priv);
823void QQmlMetaType::unregisterSequentialContainer(
int id)
828bool QQmlMetaType::protectModule(
const QString &uri, QTypeRevision version,
829 bool weakProtectAllVersions)
831 QQmlMetaTypeDataPtr data;
832 if (version.hasMajorVersion()) {
833 if (QQmlTypeModule *module = data->findTypeModule(uri, version)) {
834 if (!weakProtectAllVersions) {
835 module->setLockLevel(QQmlTypeModule::LockLevel::Strong);
843 const auto range = std::equal_range(
844 data->uriToModule.begin(), data->uriToModule.end(), uri,
845 std::less<ModuleUri>());
847 for (
auto it = range.first; it != range.second; ++it)
848 (*it)->setLockLevel(QQmlTypeModule::LockLevel::Weak);
850 return range.first != range.second;
853void QQmlMetaType::registerModuleImport(
const QString &uri, QTypeRevision moduleVersion,
854 const QQmlDirParser::Import &import)
856 QQmlMetaTypeDataPtr data;
858 data->moduleImports.insert(QQmlMetaTypeData::VersionedUri(uri, moduleVersion), import);
861void QQmlMetaType::unregisterModuleImport(
const QString &uri, QTypeRevision moduleVersion,
862 const QQmlDirParser::Import &import)
864 QQmlMetaTypeDataPtr data;
865 data->moduleImports.remove(QQmlMetaTypeData::VersionedUri(uri, moduleVersion), import);
868QList<QQmlDirParser::Import> QQmlMetaType::moduleImports(
869 const QString &uri, QTypeRevision version)
871 QQmlMetaTypeDataPtr data;
872 QList<QQmlDirParser::Import> result;
874 const auto unrevisioned = data->moduleImports.equal_range(
875 QQmlMetaTypeData::VersionedUri(uri, QTypeRevision()));
876 for (
auto it = unrevisioned.second; it != unrevisioned.first;)
877 result.append(*(--it));
879 if (version.hasMajorVersion()) {
880 const auto revisioned = data->moduleImports.equal_range(
881 QQmlMetaTypeData::VersionedUri(uri, version));
882 for (
auto it = revisioned.second; it != revisioned.first;)
883 result.append(*(--it));
888 const auto begin = data->moduleImports.begin();
889 auto it = unrevisioned.first;
893 const QQmlMetaTypeData::VersionedUri latestVersion = (--it).key();
894 if (latestVersion.uri != uri)
899 }
while (it != begin && (--it).key() == latestVersion);
904void QQmlMetaType::registerModule(
const char *uri, QTypeRevision version)
906 QQmlMetaTypeDataPtr data;
908 QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), version, data);
911 if (version.hasMinorVersion())
912 module->addMinorVersion(version.minorVersion());
915int QQmlMetaType::typeId(
const char *uri, QTypeRevision version,
const char *qmlName)
917 QQmlMetaTypeDataPtr data;
919 QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), version, data);
923 QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), version);
930void QQmlMetaType::registerUndeletableType(
const QQmlType &dtype)
932 QQmlMetaTypeDataPtr data;
933 data->undeletableTypes.insert(dtype);
937 QTypeRevision version)
941 for (
const auto &typeAndCaches : std::as_const(data->types)) {
942 const QQmlType &type = typeAndCaches.type;
943 if (type.module() == nameSpace && type.version().majorVersion() == version.majorVersion())
950QQmlMetaType::RegistrationResult QQmlMetaType::registerPluginTypes(
951 QObject *instance,
const QString &basePath,
const QString &uri,
952 const QString &typeNamespace, QTypeRevision version, QList<QQmlError> *errors)
954 if (!typeNamespace.isEmpty() && typeNamespace != uri) {
959 error.setDescription(
960 QStringLiteral(
"Module namespace '%1' does not match import URI '%2'")
961 .arg(typeNamespace, uri));
962 errors->prepend(error);
964 return RegistrationResult::Failure;
967 QStringList failures;
968 QQmlMetaTypeDataPtr data;
970 QQmlMetaTypeRegistrationFailureRecorder failureRecorder(data, &failures);
971 if (!typeNamespace.isEmpty()) {
973 if (namespaceContainsRegistrations(data, typeNamespace, version)) {
977 error.setDescription(QStringLiteral(
"Namespace '%1' has already been used "
978 "for type registration")
979 .arg(typeNamespace));
980 errors->prepend(error);
982 return RegistrationResult::Failure;
986 qWarning().nospace() << qPrintable(
987 QStringLiteral(
"Module '%1' does not contain a module identifier directive - "
988 "it cannot be protected from external registrations.").arg(uri));
991 if (instance && !qobject_cast<QQmlEngineExtensionInterface *>(instance)) {
992 QQmlTypesExtensionInterface *iface = qobject_cast<QQmlTypesExtensionInterface *>(instance);
997 error.setDescription(QStringLiteral(
"Module loaded for URI '%1' does not implement "
998 "QQmlEngineExtensionInterface").arg(typeNamespace));
999 errors->prepend(error);
1001 return RegistrationResult::Failure;
1004#if QT_DEPRECATED_SINCE(6
, 3
)
1005 if (
auto *plugin = qobject_cast<QQmlExtensionPlugin *>(instance)) {
1007 QQmlExtensionPluginPrivate::get(plugin)->baseUrl
1008 = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
1014 const QByteArray bytes = uri.toUtf8();
1015 const char *moduleId = bytes.constData();
1016 iface->registerTypes(moduleId);
1019 if (failures.isEmpty() && !data->registerModuleTypes(uri))
1020 return RegistrationResult::NoRegistrationFunction;
1022 if (!failures.isEmpty()) {
1024 for (
const QString &failure : std::as_const(failures)) {
1026 error.setDescription(failure);
1027 errors->prepend(error);
1030 return RegistrationResult::Failure;
1034 return RegistrationResult::Success;
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048QQmlType QQmlMetaType::typeForUrl(
1049 const QUrl &url,
const QHashedStringRef &qualifiedType, CompositeTypeLookupMode mode,
1050 QList<QQmlError> *errors, QTypeRevision version)
1053 const QUrl normalized = QQmlMetaType::normalizedUrl(url);
1055 QQmlMetaTypeDataPtr data;
1057 QQmlType ret(data->urlToType.value(normalized));
1058 if (ret.isValid() && ret.sourceUrl() == normalized)
1062 const QQmlType type = createTypeForUrl(
1063 data, normalized, qualifiedType, mode, errors, version);
1064 data->urlToType.insert(normalized, type.priv());
1069
1070
1071QTypeRevision QQmlMetaType::latestModuleVersion(
const QString &uri)
1073 QQmlMetaTypeDataPtr data;
1074 auto upper = std::upper_bound(data->uriToModule.begin(), data->uriToModule.end(), uri,
1075 std::less<ModuleUri>());
1076 if (upper == data->uriToModule.begin())
1077 return QTypeRevision();
1079 const auto module = (--upper)->get();
1080 return (module->module() == uri)
1081 ? QTypeRevision::fromVersion(module->majorVersion(), module->maximumMinorVersion())
1086
1087
1088bool QQmlMetaType::isStronglyLockedModule(
const QString &uri, QTypeRevision version)
1090 QQmlMetaTypeDataPtr data;
1092 if (QQmlTypeModule* qqtm = data->findTypeModule(uri, version))
1093 return qqtm->lockLevel() == QQmlTypeModule::LockLevel::Strong;
1098
1099
1100
1101
1102
1103
1104QTypeRevision QQmlMetaType::matchingModuleVersion(
const QString &module, QTypeRevision version)
1106 if (!version.hasMajorVersion())
1107 return latestModuleVersion(module);
1109 QQmlMetaTypeDataPtr data;
1112 if (QQmlTypeModule *tm = data->findTypeModule(module, version)) {
1113 if (!version.hasMinorVersion())
1114 return QTypeRevision::fromVersion(version.majorVersion(), tm->maximumMinorVersion());
1116 if (tm->minimumMinorVersion() <= version.minorVersion()
1117 && tm->maximumMinorVersion() >= version.minorVersion()) {
1122 return QTypeRevision();
1125QQmlTypeModule *QQmlMetaType::typeModule(
const QString &uri, QTypeRevision version)
1127 QQmlMetaTypeDataPtr data;
1129 if (version.hasMajorVersion())
1130 return data->findTypeModule(uri, version);
1132 auto range = std::equal_range(data->uriToModule.begin(), data->uriToModule.end(),
1133 uri, std::less<ModuleUri>());
1135 return range.first == range.second ?
nullptr : (--range.second)->get();
1138QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
1140 QQmlMetaTypeDataPtr data;
1141 return data->parentFunctions;
1144QObject *QQmlMetaType::toQObject(
const QVariant &v,
bool *ok)
1146 if (!v.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
1147 if (ok) *ok =
false;
1153 return *(QObject *
const *)v.constData();
1157
1158
1159QMetaType QQmlMetaType::listValueType(QMetaType metaType)
1161 if (isList(metaType)) {
1162 const auto iface = metaType.iface();
1163 if (iface && iface->metaObjectFn == &dynamicQmlListMarker)
1164 return QMetaType(
static_cast<
const QQmlListMetaTypeInterface *>(iface)->valueType);
1165 }
else if (metaType.flags() & QMetaType::PointerToQObject) {
1169 QQmlMetaTypeDataPtr data;
1171 QQmlTypePrivate *type = data->idToType.value(metaType.id());
1173 if (type && type->listId == metaType)
1174 return type->typeId;
1176 return QMetaType {};
1179QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFunc(
1180 QQmlTypeLoader *typeLoader,
const QMetaObject *mo)
1182 QQmlMetaTypeDataPtr data;
1184 QQmlType type(data->metaObjectToType.value(mo));
1185 return type.attachedPropertiesFunction(typeLoader);
1188QMetaProperty QQmlMetaType::defaultProperty(
const QMetaObject *metaObject)
1190 int idx = metaObject->indexOfClassInfo(
"DefaultProperty");
1192 return QMetaProperty();
1194 QMetaClassInfo info = metaObject->classInfo(idx);
1196 return QMetaProperty();
1198 idx = metaObject->indexOfProperty(info.value());
1200 return QMetaProperty();
1202 return metaObject->property(idx);
1205QMetaProperty QQmlMetaType::defaultProperty(QObject *obj)
1208 return QMetaProperty();
1210 const QMetaObject *metaObject = obj->metaObject();
1211 return defaultProperty(metaObject);
1214QMetaMethod QQmlMetaType::defaultMethod(
const QMetaObject *metaObject)
1216 int idx = metaObject->indexOfClassInfo(
"DefaultMethod");
1218 return QMetaMethod();
1220 QMetaClassInfo info = metaObject->classInfo(idx);
1222 return QMetaMethod();
1224 idx = metaObject->indexOfMethod(info.value());
1226 return QMetaMethod();
1228 return metaObject->method(idx);
1231QMetaMethod QQmlMetaType::defaultMethod(QObject *obj)
1234 return QMetaMethod();
1236 const QMetaObject *metaObject = obj->metaObject();
1237 return defaultMethod(metaObject);
1241
1242
1243bool QQmlMetaType::isInterface(QMetaType metaType)
1245 const QQmlMetaTypeDataPtr data;
1246 return QQmlType(data->idToType.value(metaType.id())).isInterface();
1249const char *QQmlMetaType::interfaceIId(QMetaType metaType)
1251 const QQmlMetaTypeDataPtr data;
1252 const QQmlType type(data->idToType.value(metaType.id()));
1253 return (type.isInterface() && type.typeId() == metaType) ? type.interfaceIId() :
nullptr;
1256bool QQmlMetaType::isList(QMetaType type)
1258 if (type.flags().testFlag(QMetaType::IsQmlList))
1265
1266
1267
1268QQmlType QQmlMetaType::qmlType(
const QString &qualifiedName, QTypeRevision version)
1270 int slash = qualifiedName.indexOf(QLatin1Char(
'/'));
1274 QHashedStringRef module(qualifiedName.constData(), slash);
1275 QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.size() - slash - 1);
1277 return qmlType(name, module, version);
1281
1282
1283
1284
1285
1286
1287
1288QQmlType QQmlMetaType::qmlType(
const QHashedStringRef &name,
const QHashedStringRef &module,
1289 QTypeRevision version)
1291 const QQmlMetaTypeDataPtr data;
1293 const QHashedString key(QString::fromRawData(name.constData(), name.length()), name.hash());
1294 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(key);
1295 while (it != data->nameToType.cend() && QHashedStringRef(it.key()) == name) {
1297 if (module.isEmpty() || t.availableInVersion(module, version))
1306
1307
1308
1309QQmlType QQmlMetaType::qmlType(
const QMetaObject *metaObject)
1311 const QQmlMetaTypeDataPtr data;
1312 return QQmlType(data->metaObjectToType.value(metaObject));
1316
1317
1318
1319
1320QQmlType QQmlMetaType::qmlType(
const QMetaObject *metaObject,
const QHashedStringRef &module,
1321 QTypeRevision version)
1323 const QQmlMetaTypeDataPtr data;
1325 const auto range = data->metaObjectToType.equal_range(metaObject);
1326 for (
auto it = range.first; it != range.second; ++it) {
1328 if (module.isEmpty() || t.availableInVersion(module, version))
1336
1337
1338
1339QQmlType QQmlMetaType::qmlTypeById(
int qmlTypeId)
1341 const QQmlMetaTypeDataPtr data;
1342 return data->types.value(qmlTypeId).type;
1346
1347
1348
1349
1350
1351
1352
1353
1354QQmlType QQmlMetaType::firstQmlTypeForAttachmentMetaObject(
const QMetaObject *attachmentMetaObject)
1356 const QQmlMetaTypeDataPtr data;
1357 if (
auto qmlTypePriv = data->metaObjectToType.value(attachmentMetaObject)) {
1359 if (qmlTypePriv->regType == QQmlType::CppType &&
1360 qmlTypePriv->extraData.cppTypeData->attachedPropertiesType == attachmentMetaObject)
1361 return QQmlType(qmlTypePriv);
1363 auto getAttachmentMetaObject = [](
const QQmlTypePrivate *priv) ->
const QMetaObject * {
1364 if (priv->regType != QQmlType::CppType)
1366 return priv->extraData.cppTypeData->attachedPropertiesType;
1368 auto it = std::find_if(data->metaObjectToType.constBegin(),
1369 data->metaObjectToType.constEnd(),
1370 [&](
const QQmlTypePrivate *type) {
return attachmentMetaObject == getAttachmentMetaObject(type); }
1372 if (it == data->metaObjectToType.constEnd())
1374 return QQmlType(*it);
1378
1379
1380
1381QQmlType QQmlMetaType::qmlType(QMetaType metaType)
1383 const QQmlMetaTypeDataPtr data;
1384 QQmlTypePrivate *type = data->idToType.value(metaType.id());
1385 return (type && type->typeId == metaType) ? QQmlType(type) : QQmlType();
1388QQmlType QQmlMetaType::qmlListType(QMetaType metaType)
1390 const QQmlMetaTypeDataPtr data;
1391 QQmlTypePrivate *type = data->idToType.value(metaType.id());
1392 return (type && type->listId == metaType) ? QQmlType(type) : QQmlType();
1396
1397
1398
1399
1400
1401QQmlType QQmlMetaType::qmlType(
const QUrl &unNormalizedUrl)
1403 const QUrl url = QQmlMetaType::normalizedUrl(unNormalizedUrl);
1404 const QQmlMetaTypeDataPtr data;
1406 QQmlType type(data->urlToType.value(url));
1408 if (type.sourceUrl() == url)
1414QQmlType QQmlMetaType::findOrCreateSpeculativeInlineComponentType(
const QUrl &url)
1416 QQmlMetaTypeDataPtr data;
1417 const auto it = data->urlToType.constFind(url);
1418 if (it != data->urlToType.constEnd())
1419 return QQmlType(*it);
1424 baseUrl.setFragment(QString());
1428 if (baseUrl.isEmpty())
1429 return doRegisterInlineComponentType(data, url);
1433 const auto baseIt = data->urlToType.constFind(baseUrl);
1434 if (baseIt == data->urlToType.constEnd()) {
1435 data->speculativeInlineComponentTypes.insert(url);
1436 return doRegisterInlineComponentType(data, url);
1441 const auto cu = data->compositeTypes.value((*baseIt)->typeId.iface());
1443 data->speculativeInlineComponentTypes.insert(url);
1444 return doRegisterInlineComponentType(data, url);
1449 Q_ASSERT(std::none_of(
1450 cu->inlineComponentData.constBegin(), cu->inlineComponentData.constEnd(),
1451 [&](
const QV4::CompiledData::InlineComponentData &icData) {
1452 return icData.qmlType.elementName() == url.fragment();
1460
1461
1462
1463
1464
1465QQmlPropertyCache::ConstPtr QQmlMetaType::propertyCache(QObject *obj, QTypeRevision version)
1467 if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
1468 return QQmlPropertyCache::ConstPtr();
1469 return QQmlMetaType::propertyCache(obj->metaObject(), version);
1472QQmlPropertyCache::ConstPtr QQmlMetaType::propertyCache(
1473 const QMetaObject *metaObject, QTypeRevision version)
1475 QQmlMetaTypeDataPtr data;
1476 return data->propertyCache(metaObject, version);
1479QQmlPropertyCache::ConstPtr QQmlMetaType::propertyCache(
1480 const QQmlType &type, QTypeRevision version)
1482 QQmlMetaTypeDataPtr data;
1483 return data->propertyCache(type, version);
1487
1488
1489
1490
1491QQmlMetaObject QQmlMetaType::rawMetaObjectForType(QMetaType metaType)
1493 const QQmlMetaTypeDataPtr data;
1494 if (
auto composite = data->findPropertyCacheInCompositeTypes(metaType))
1495 return QQmlMetaObject(composite);
1497 const QQmlTypePrivate *type = data->idToType.value(metaType.id());
1498 return (type && type->typeId == metaType) ? type->baseMetaObject :
nullptr;
1502
1503
1504
1505
1506QQmlMetaObject QQmlMetaType::metaObjectForType(QMetaType metaType)
1508 const QQmlMetaTypeDataPtr data;
1509 if (
auto composite = data->findPropertyCacheInCompositeTypes(metaType))
1510 return QQmlMetaObject(composite);
1512 const QQmlTypePrivate *type = data->idToType.value(metaType.id());
1513 return (type && type->typeId == metaType)
1514 ? QQmlType(type).metaObject()
1519
1520
1521
1522
1523QQmlPropertyCache::ConstPtr QQmlMetaType::propertyCacheForType(QMetaType metaType)
1525 QQmlMetaTypeDataPtr data;
1526 if (
auto composite = data->findPropertyCacheInCompositeTypes(metaType))
1529 const QQmlTypePrivate *type = data->idToType.value(metaType.id());
1530 if (type && type->typeId == metaType) {
1531 if (
const QMetaObject *mo = QQmlType(type).metaObject())
1532 return data->propertyCache(mo, type->version);
1535 return QQmlPropertyCache::ConstPtr();
1539
1540
1541
1542
1543
1544
1545QQmlPropertyCache::ConstPtr QQmlMetaType::rawPropertyCacheForType(QMetaType metaType)
1547 QQmlMetaTypeDataPtr data;
1548 if (
auto composite = QQmlMetaType::findPropertyCacheInCompositeTypes(metaType))
1551 const QQmlTypePrivate *type = data->idToType.value(metaType.id());
1552 if (!type || type->typeId != metaType)
1553 return QQmlPropertyCache::ConstPtr();
1555 const QMetaObject *metaObject = type->isValueType()
1556 ? type->metaObjectForValueType()
1557 : type->baseMetaObject;
1560 ? data->propertyCache(metaObject, QTypeRevision())
1561 : QQmlPropertyCache::ConstPtr();
1565
1566
1567
1568
1569
1570
1571QVarLengthArray<QQmlPropertyCache::ConstPtr, 4>
1572QQmlMetaType::rawCompositePropertyCachesForType(QMetaType metaType)
1574 const QQmlMetaTypeDataPtr data;
1575 return data->findPropertyCachesInCompositeTypes(metaType);
1579
1580
1581
1582
1583
1584QQmlPropertyCache::ConstPtr QQmlMetaType::rawPropertyCacheForType(
1585 QMetaType metaType, QTypeRevision version)
1587 QQmlMetaTypeDataPtr data;
1588 if (
auto composite = data->findPropertyCacheInCompositeTypes(metaType))
1591 const QQmlTypePrivate *typePriv = data->idToType.value(metaType.id());
1592 if (!typePriv || typePriv->typeId != metaType)
1593 return QQmlPropertyCache::ConstPtr();
1595 const QQmlType type(typePriv);
1596 if (type.containsRevisionedAttributes()) {
1598 Q_ASSERT(type.metaObject());
1599 return data->propertyCache(type, version);
1602 if (
const QMetaObject *metaObject = type.metaObject())
1603 return data->propertyCache(metaObject, version);
1605 return QQmlPropertyCache::ConstPtr();
1608template<
typename From,
typename CanConvertPropCache,
typename CanConvertMetaObject>
1611 CanConvertPropCache &&canConvertPropCache, CanConvertMetaObject &&canConvertMetaObject)
1619 auto [it, end] = data->compositeTypes.equal_range(metaType.iface());
1622 if (canConvertPropCache(
1623 from, QQmlMetaTypeData::propertyCacheForPotentialInlineComponentType(
1627 }
while(++it != end);
1634 const QQmlTypePrivate *type = data->idToType.value(metaType.id());
1635 if (type && type->typeId == metaType && type->baseMetaObject)
1636 return canConvertMetaObject(from, type->baseMetaObject);
1639 if (
const QMetaObject *metaObject = metaType.metaObject())
1640 return canConvertMetaObject(from, metaObject);
1645bool QQmlMetaType::canConvert(QObject *o, QMetaType metaType)
1647 QQmlMetaTypeDataPtr data;
1649 return canConvertToPropCacheOrMetaObject(
1650 data, o, metaType, [](QObject *o,
const QQmlPropertyCache::ConstPtr &propCache) {
1651 return QQmlMetaObject::canConvert(o, propCache);
1652 }, [](QObject *o,
const QMetaObject *metaObject) {
1653 return QQmlMetaObject::canConvert(o, metaObject);
1658 const QQmlPropertyCache::ConstPtr &derived,
const QQmlPropertyCache::ConstPtr &base)
1660 for (QQmlPropertyCache::ConstPtr parent = derived; parent; parent = parent->parent()) {
1668bool QQmlMetaType::canConvert(
const QQmlPropertyCache::ConstPtr &from, QMetaType metaType)
1670 QQmlMetaTypeDataPtr data;
1672 return canConvertToPropCacheOrMetaObject(
1673 data, from, metaType,
1674 [](
const QQmlPropertyCache::ConstPtr &from,
const QQmlPropertyCache::ConstPtr &to) {
1675 return inherits(from, to);
1676 }, [&](
const QQmlPropertyCache::ConstPtr &from,
const QMetaObject *toMeta) {
1677 if (
const QMetaObject *fromMeta = from->metaObject())
1678 return QQmlMetaObject::canConvert(fromMeta, toMeta);
1679 return inherits(from, data->propertyCache(toMeta, QTypeRevision()));
1684bool QQmlMetaType::canLosslesslyHoldUndefined(QMetaType metaType)
1686 switch (metaType.id()) {
1687 case QMetaType::QVariant:
1689 case QMetaType::QJsonValue:
1694 if (metaType == QMetaType::fromType<QJSValue>())
1696 if (metaType == QMetaType::fromType<QJSPrimitiveValue>())
1698 if (metaType == QMetaType::fromType<QJSManagedValue>())
1705void QQmlMetaType::unregisterType(
int typeIndex)
1707 QQmlMetaTypeDataPtr data;
1708 const QQmlType type = data->types.value(typeIndex).type;
1709 if (
const QQmlTypePrivate *d = type.priv()) {
1710 if (d->regType == QQmlType::CompositeType || d->regType == QQmlType::CompositeSingletonType) {
1711 removeFromInlineComponents(data->urlToType, d);
1712 removeFromInlineComponents(data->speculativeInlineComponentTypes, d);
1714 removeQQmlTypePrivate(data->idToType, d);
1715 removeQQmlTypePrivate(data->nameToType, d);
1716 removeQQmlTypePrivate(data->urlToType, d);
1717 removeQQmlTypePrivate(data->metaObjectToType, d);
1718 data->speculativeInlineComponentTypes.remove(d->sourceUrl());
1719 for (
auto & module : data->uriToModule)
1721 data->types[typeIndex] = QQmlMetaTypeData::Type();
1722 data->undeletableTypes.remove(type);
1726void QQmlMetaType::registerMetaObjectForType(
const QMetaObject *metaobject,
const QQmlTypePrivate *type)
1730 QQmlMetaTypeDataPtr data;
1731 data->metaObjectToType.insert(metaobject, type);
1736 for (
auto it = data->urlToType.begin(), end = data->urlToType.end();
1738 if (!QQmlMetaType::equalBaseUrls(it.key(), d->sourceUrl()))
1741 const QQmlTypePrivate *icPriv = *it;
1742 if (icPriv && icPriv->count() > 1)
1749 QQmlMetaTypeData *data,
1750 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
1753 auto doCheck = [&](
const QtPrivate::QMetaTypeInterface *iface) {
1757 const auto [begin, end] = std::as_const(data->compositeTypes).equal_range(iface);
1758 for (
auto it = begin; it != end; ++it) {
1759 if (*it == compilationUnit)
1764 doCheck(compilationUnit->metaType().iface());
1765 for (
const auto &inlineData : std::as_const(compilationUnit->inlineComponentData))
1766 doCheck(inlineData.qmlType.typeId().iface());
1771void QQmlMetaType::freeUnusedTypesAndCaches()
1773 QQmlMetaTypeDataPtr data;
1776 if (!data.isValid())
1779 bool droppedAtLeastOneComposite;
1781 droppedAtLeastOneComposite =
false;
1782 auto it = data->compositeTypes.cbegin();
1783 while (it != data->compositeTypes.cend()) {
1784 const auto &cu = *it;
1785 if (cu->count() <= doCountInternalCompositeTypeSelfReferences(data, cu)) {
1786 QQmlMetaTypeData::clearCompositeType(cu);
1787 it = data->compositeTypes.erase(it);
1788 droppedAtLeastOneComposite =
true;
1793 }
while (droppedAtLeastOneComposite);
1795 bool deletedAtLeastOneType;
1797 deletedAtLeastOneType =
false;
1798 auto it = data->types.begin();
1799 while (it != data->types.end()) {
1800 const QQmlTypePrivate *d = it->type.priv();
1801 if (d && d->count() == 1 && !hasActiveInlineComponents(data, d)) {
1802 deletedAtLeastOneType =
true;
1804 if (d->regType == QQmlType::CompositeType
1805 || d->regType == QQmlType::CompositeSingletonType) {
1806 removeFromInlineComponents(data->urlToType, d);
1807 removeFromInlineComponents(data->speculativeInlineComponentTypes, d);
1809 removeQQmlTypePrivate(data->idToType, d);
1810 removeQQmlTypePrivate(data->nameToType, d);
1811 removeQQmlTypePrivate(data->urlToType, d);
1812 removeQQmlTypePrivate(data->metaObjectToType, d);
1813 data->speculativeInlineComponentTypes.remove(d->sourceUrl());
1815 for (
auto &module : data->uriToModule)
1818 *it = QQmlMetaTypeData::Type();
1823 }
while (deletedAtLeastOneType);
1825 bool deletedAtLeastOneCache;
1827 deletedAtLeastOneCache =
false;
1828 auto it = data->propertyCaches.begin();
1829 while (it != data->propertyCaches.end()) {
1830 if ((*it)->count() == 1) {
1831 it = data->propertyCaches.erase(it);
1832 deletedAtLeastOneCache =
true;
1837 }
while (deletedAtLeastOneCache);
1841
1842
1843QList<QString> QQmlMetaType::qmlTypeNames()
1845 const QQmlMetaTypeDataPtr data;
1847 QList<QString> names;
1848 names.reserve(data->nameToType.size());
1849 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.cbegin();
1850 while (it != data->nameToType.cend()) {
1852 names += t.qmlTypeName();
1860
1861
1862QList<QQmlType> QQmlMetaType::qmlTypes()
1864 const QQmlMetaTypeDataPtr data;
1866 QList<QQmlType> types;
1867 for (
const QQmlTypePrivate *t : data->nameToType)
1868 types.append(QQmlType(t));
1874
1875
1876QList<QQmlType> QQmlMetaType::qmlAllTypes()
1878 const QQmlMetaTypeDataPtr data;
1879 QList<QQmlType> types;
1880 types.reserve(data->types.size());
1882 data->types.constBegin(), data->types.constEnd(),
1883 std::back_inserter(types), [](
const auto &type) {
return type.type; });
1888
1889
1890QList<QQmlType> QQmlMetaType::qmlSingletonTypes()
1892 const QQmlMetaTypeDataPtr data;
1894 QList<QQmlType> retn;
1895 for (
const auto t : std::as_const(data->nameToType)) {
1897 if (type.isSingleton())
1905 quint32 numTypedFunctions = 0;
1906 for (
const QQmlPrivate::AOTCompiledFunction *function = unit->aotCompiledFunctions;
1907 function; ++function) {
1908 if (function->functionPtr)
1909 ++numTypedFunctions;
1913 return numTypedFunctions == unit->qmlData->functionTableSize;
1916const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(
1917 const QUrl &uri, QQmlMetaType::CacheMode mode, CachedUnitLookupError *status)
1919 Q_ASSERT(mode != RejectAll);
1920 const QQmlMetaTypeDataPtr data;
1922 for (
const auto lookup : std::as_const(data->lookupCachedQmlUnit)) {
1923 if (
const QQmlPrivate::CachedQmlUnit *unit = lookup(uri)) {
1925 if (!unit->qmlData->verifyHeader(QDateTime(), &error)) {
1926 qCDebug(DBG_DISK_CACHE) <<
"Error loading pre-compiled file " << uri <<
":" << error;
1928 *status = CachedUnitLookupError::VersionMismatch;
1932 if (mode == RequireFullyTyped && !isFullyTyped(unit)) {
1933 qCDebug(DBG_DISK_CACHE)
1934 <<
"Error loading pre-compiled file " << uri
1935 <<
": compilation unit contains functions not compiled to native code.";
1937 *status = CachedUnitLookupError::NotFullyTyped;
1942 *status = CachedUnitLookupError::NoError;
1947 qCDebug(DBG_DISK_CACHE) <<
"No pre-compiled unit found for" << uri;
1950 *status = CachedUnitLookupError::NoUnitFound;
1955void QQmlMetaType::prependCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler)
1957 QQmlMetaTypeDataPtr data;
1958 data->lookupCachedQmlUnit.prepend(handler);
1961void QQmlMetaType::removeCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler)
1963 QQmlMetaTypeDataPtr data;
1964 data->lookupCachedQmlUnit.removeAll(handler);
1968
1969
1970QString QQmlMetaType::prettyTypeName(
const QObject *object)
1977 QQmlType type = QQmlMetaType::qmlType(object->metaObject());
1978 if (type.isValid()) {
1979 typeName = type.qmlTypeName();
1980 const int lastSlash = typeName.lastIndexOf(QLatin1Char(
'/'));
1981 if (lastSlash != -1)
1982 typeName = typeName.mid(lastSlash + 1);
1985 if (typeName.isEmpty()) {
1986 typeName = QString::fromUtf8(object->metaObject()->className());
1987 int marker = typeName.indexOf(QLatin1String(
"_QMLTYPE_"));
1989 typeName = typeName.left(marker);
1991 marker = typeName.indexOf(QLatin1String(
"_QML_"));
1993 typeName = QStringView{typeName}.left(marker) + QLatin1Char(
'*');
1994 type = QQmlMetaType::qmlType(QMetaType::fromName(typeName.toUtf8()));
1995 if (type.isValid()) {
1996 QString qmlTypeName = type.qmlTypeName();
1997 const int lastSlash = qmlTypeName.lastIndexOf(QLatin1Char(
'/'));
1998 if (lastSlash != -1)
1999 qmlTypeName = qmlTypeName.mid(lastSlash + 1);
2000 if (!qmlTypeName.isEmpty())
2001 typeName = qmlTypeName;
2009QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(
const QMetaObject *mo,
2010 const QMetaObject *baseMetaObject,
2011 QMetaObject *lastMetaObject)
2013 QList<QQmlProxyMetaObject::ProxyData> metaObjects;
2014 mo = mo->d.superdata;
2019 auto createProxyMetaObject = [&](
const QQmlTypePrivate *This,
2020 const QMetaObject *superdataBaseMetaObject,
2021 const QMetaObject *extMetaObject,
2022 QObject *(*extFunc)(QObject *)) {
2026 QMetaObjectBuilder builder;
2027 clone(builder, extMetaObject, superdataBaseMetaObject, baseMetaObject,
2028 extFunc ? QQmlMetaType::CloneAll : QQmlMetaType::CloneEnumsOnly);
2029 QMetaObject *mmo = builder.toMetaObject();
2030 mmo->d.superdata = baseMetaObject;
2031 if (!metaObjects.isEmpty())
2032 metaObjects.constLast().metaObject->d.superdata = mmo;
2033 else if (lastMetaObject)
2034 lastMetaObject->d.superdata = mmo;
2035 QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 };
2036 metaObjects << data;
2037 registerMetaObjectForType(mmo, This);
2040 for (
const QQmlMetaTypeDataPtr data; mo; mo = mo->d.superdata) {
2047 if (
const QQmlTypePrivate *t = data->metaObjectToType.value(mo)) {
2048 if (t->regType == QQmlType::CppType) {
2049 createProxyMetaObject(
2050 t, t->baseMetaObject, t->extraData.cppTypeData->extMetaObject,
2051 t->extraData.cppTypeData->extFunc);
2052 }
else if (t->regType == QQmlType::SingletonType) {
2053 createProxyMetaObject(
2054 t, t->baseMetaObject, t->extraData.singletonTypeData->extMetaObject,
2055 t->extraData.singletonTypeData->extFunc);
2067 case QMetaType::UnknownType:
2068 case QMetaType::QStringList:
2069 case QMetaType::QObjectStar:
2070 case QMetaType::VoidStar:
2071 case QMetaType::Nullptr:
2072 case QMetaType::QVariant:
2073 case QMetaType::QLocale:
2074 case QMetaType::QImage:
2075 case QMetaType::QPixmap:
2082bool QQmlMetaType::isValueType(QMetaType type)
2084 if (type.flags().testFlag(QMetaType::PointerToQObject))
2087 if (!type.isValid() || isInternalType(type.id()))
2090 return valueType(type) !=
nullptr;
2093const QMetaObject *QQmlMetaType::metaObjectForValueType(QMetaType metaType)
2095 switch (metaType.id()) {
2096 case QMetaType::QPoint:
2097 return &QQmlPointValueType::staticMetaObject;
2098 case QMetaType::QPointF:
2099 return &QQmlPointFValueType::staticMetaObject;
2100 case QMetaType::QSize:
2101 return &QQmlSizeValueType::staticMetaObject;
2102 case QMetaType::QSizeF:
2103 return &QQmlSizeFValueType::staticMetaObject;
2104 case QMetaType::QRect:
2105 return &QQmlRectValueType::staticMetaObject;
2106 case QMetaType::QRectF:
2107 return &QQmlRectFValueType::staticMetaObject;
2108#if QT_CONFIG(easingcurve)
2109 case QMetaType::QEasingCurve:
2110 return &QQmlEasingValueType::staticMetaObject;
2119 if (!(metaType.flags() & QMetaType::PointerToQObject)) {
2120 const QQmlMetaTypeDataPtr data;
2121 const QQmlTypePrivate *type = data->idToType.value(metaType.id());
2122 if (type && type->regType == QQmlType::CppType && type->typeId == metaType) {
2123 if (
const QMetaObject *mo = type->metaObjectForValueType())
2129 if (metaType.flags() & QMetaType::IsGadget)
2130 return metaType.metaObject();
2135QQmlValueType *QQmlMetaType::valueType(QMetaType type)
2137 QQmlMetaTypeDataPtr data;
2139 const auto it = data->metaTypeToValueType.constFind(type.id());
2140 if (it != data->metaTypeToValueType.constEnd())
2143 if (
const QMetaObject *mo = metaObjectForValueType(type))
2144 return *data->metaTypeToValueType.insert(type.id(),
new QQmlValueType(type, mo));
2145 return *data->metaTypeToValueType.insert(type.id(),
nullptr);
2148QQmlPropertyCache::ConstPtr QQmlMetaType::findPropertyCacheInCompositeTypes(QMetaType t)
2150 const QQmlMetaTypeDataPtr data;
2151 return data->findPropertyCacheInCompositeTypes(t);
2154void QQmlMetaType::registerInternalCompositeType(
2155 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
2157 QQmlMetaTypeDataPtr data;
2159 auto doInsert = [&data, &compilationUnit](
const QtPrivate::QMetaTypeInterface *iface) {
2161 Q_ASSERT(compilationUnit);
2166 auto it = data->compositeTypes.insert(iface, compilationUnit);
2172 const auto end = data->compositeTypes.end();
2173 while (++it != end && it.key() == iface) {
2174 if (*it == compilationUnit) {
2175 data->compositeTypes.erase(it);
2181 doInsert(compilationUnit->metaType().iface());
2182 for (
const auto &inlineData : std::as_const(compilationUnit->inlineComponentData))
2183 doInsert(inlineData.qmlType.typeId().iface());
2189 const QUrl baseUrl = compilationUnit->finalUrl();
2190 if (baseUrl.isEmpty())
2193 for (
auto it = data->speculativeInlineComponentTypes.begin();
2194 it != data->speculativeInlineComponentTypes.end();) {
2195 const QUrl &url = *it;
2196 if (!equalBaseUrls(url, baseUrl)) {
2201 const QString icName = url.fragment();
2202 if (compilationUnit->inlineComponentData.contains(icName)) {
2204 it = data->speculativeInlineComponentTypes.erase(it);
2209 const auto typeIt = data->urlToType.constFind(url);
2210 Q_ASSERT(typeIt != data->urlToType.constEnd());
2212 const QQmlTypePrivate *d = *typeIt;
2213 data->urlToType.erase(typeIt);
2214 data->idToType.remove(d->typeId.id());
2215 data->idToType.remove(d->listId.id());
2216 data->types[d->index] = {};
2217 it = data->speculativeInlineComponentTypes.erase(it);
2221void QQmlMetaType::unregisterInternalCompositeType(
2222 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
2224 QQmlMetaTypeDataPtr data;
2226 auto doRemove = [&](
const QtPrivate::QMetaTypeInterface *iface) {
2230 const auto [begin, end] = std::as_const(data->compositeTypes).equal_range(iface);
2231 for (
auto it = begin; it != end; ++it) {
2232 if (*it == compilationUnit) {
2233 QQmlMetaTypeData::clearCompositeType(compilationUnit);
2234 data->compositeTypes.erase(it);
2240 doRemove(compilationUnit->metaType().iface());
2241 for (
const auto &inlineData : std::as_const(compilationUnit->inlineComponentData))
2242 doRemove(inlineData.qmlType.typeId().iface());
2244 const QUrl baseUrl = compilationUnit->finalUrl();
2245 if (baseUrl.isEmpty())
2249 for (
auto it = data->speculativeInlineComponentTypes.begin();
2250 it != data->speculativeInlineComponentTypes.end();) {
2251 if (equalBaseUrls(*it, baseUrl))
2252 it = data->speculativeInlineComponentTypes.erase(it);
2258void QQmlMetaType::deepClearCompositeType(
2259 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &oldUnit)
2261 unregisterInternalCompositeType(oldUnit);
2262 unregisterType(oldUnit->qmlType.index());
2263 for (
const auto &icData : std::as_const(oldUnit->inlineComponentData))
2264 unregisterType(icData.qmlType.index());
2267int QQmlMetaType::countInternalCompositeTypeSelfReferences(
2268 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
2270 QQmlMetaTypeDataPtr data;
2271 return doCountInternalCompositeTypeSelfReferences(data, compilationUnit);
2274QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlMetaType::obtainCompilationUnit(
2277 const QQmlMetaTypeDataPtr data;
2280 return data->compositeTypes.value(type.iface());
2283QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlMetaType::obtainCompilationUnit(
2286 const QUrl normalized = QQmlMetaType::normalizedUrl(url);
2287 QQmlMetaTypeDataPtr data;
2289 auto found = data->urlToType.constFind(normalized);
2290 if (found == data->urlToType.constEnd())
2291 return QQmlRefPointer<QV4::CompiledData::CompilationUnit>();
2294 const auto composite = data->compositeTypes.constFind(found.value()->typeId.iface());
2295 return composite == data->compositeTypes.constEnd()
2296 ? QQmlRefPointer<QV4::CompiledData::CompilationUnit>()
2297 : composite.value();
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)