Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpropertycachecreator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <private/qqmlengine_p.h>
7#include <private/qqmlpropertyresolver_p.h>
8
10
11Q_LOGGING_CATEGORY(invalidOverride, "qt.qml.invalidOverride");
12
13QAtomicInt QQmlPropertyCacheCreatorBase::classIndexCounter(0);
14
15template<typename BaseNameHandler, typename FailHandler>
17 const QUrl &url, BaseNameHandler &&baseNameHandler, FailHandler &&failHandler)
18{
19 const QString path = url.path();
20
21 // Not a reusable type if we don't have an absolute Url
22 const qsizetype lastSlash = path.lastIndexOf(QLatin1Char('/'));
23 if (lastSlash <= -1)
24 return failHandler();
25
26 // ### this might not be correct for .ui.qml files
27 const QStringView baseName = QStringView{path}.mid(lastSlash + 1, path.size() - lastSlash - 5);
28
29 // Not a reusable type if it doesn't start with a upper case letter.
30 return (!baseName.isEmpty() && baseName.at(0).isUpper())
31 ? baseNameHandler(baseName)
32 : failHandler();
33}
34
35bool QQmlPropertyCacheCreatorBase::canCreateClassNameTypeByUrl(const QUrl &url)
36{
37 return processUrlForClassName(url, [](QStringView) {
38 return true;
39 }, []() {
40 return false;
41 });
42}
43
44QByteArray QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(const QUrl &url)
45{
46 return processUrlForClassName(url, [](QStringView nameBase) {
47 return nameBase.toUtf8() + QByteArray("_QMLTYPE_");
48 }, []() {
49 return QByteArray("ANON_QML_TYPE_");
50 }) + QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
51}
52
53QByteArray QQmlPropertyCacheCreatorBase::createClassNameForInlineComponent(const QUrl &url)
54{
55 QByteArray baseName = processUrlForClassName(url, [](QStringView nameBase) {
56 return QByteArray(nameBase.toUtf8() + "_QMLTYPE_");
57 }, []() {
58 return QByteArray("ANON_QML_IC_");
59 });
60 return baseName + url.fragment().toUtf8() + '_'
61 + QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
62}
63
65 int referencingObjectIndex,
66 const QV4::CompiledData::Binding *instantiatingBinding,
67 const QString &instantiatingPropertyName,
68 const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache)
69 : referencingObjectIndex(referencingObjectIndex)
73{
74}
75
77{
78 if (!instantiatingBinding
79 || instantiatingBinding->type() != QV4::CompiledData::Binding::Type_GroupProperty) {
80 return true;
81 }
82
83 if (!referencingObjectPropertyCache)
84 return false;
85
86 Q_ASSERT(referencingObjectIndex >= 0);
87 Q_ASSERT(instantiatingBinding->propertyNameIndex != 0);
88
89 bool notInRevision = false;
90 instantiatingProperty = QQmlPropertyResolver(referencingObjectPropertyCache)
91 .property(instantiatingPropertyName, &notInRevision,
92 QQmlPropertyResolver::IgnoreRevision);
93 return instantiatingProperty != nullptr;
94}
95
97{
98 if (instantiatingProperty) {
99 if (instantiatingProperty->isQObject()) {
100 // rawPropertyCacheForType assumes a given unspecified version means "any version".
101 // There is another overload that takes no version, which we shall not use here.
102 auto result = QQmlMetaType::rawPropertyCacheForType(instantiatingProperty->propType(),
103 instantiatingProperty->typeVersion());
104 if (result)
105 return result;
106 /* We might end up here if there's a grouped property, and the type hasn't been registered.
107 Still try to get a property cache, as long as the type of the property is well-behaved
108 (i.e., not dynamic)*/
109 if (auto metaObject = instantiatingProperty->propType().metaObject(); metaObject) {
110 // we'll warn about dynamic meta-object later in the property validator
111 if (!(QMetaObjectPrivate::get(metaObject)->flags & DynamicMetaObject))
112 return QQmlMetaType::propertyCache(metaObject);
113 }
114 // fall through intentional
115 } else if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForValueType(instantiatingProperty->propType())) {
116 return QQmlMetaType::propertyCache(vtmo, instantiatingProperty->typeVersion());
117 }
118 }
119 return QQmlPropertyCache::ConstPtr();
120}
121
123 QQmlPropertyCacheVector *propertyCaches) const
124{
125 for (QQmlBindingInstantiationContext pendingBinding: *this) {
126 const int groupPropertyObjectIndex = pendingBinding.instantiatingBinding->value.objectIndex;
127
128 if (propertyCaches->at(groupPropertyObjectIndex))
129 continue;
130
131 Q_ASSERT(!pendingBinding.instantiatingPropertyName.isEmpty());
132
133 if (!pendingBinding.referencingObjectPropertyCache) {
134 pendingBinding.referencingObjectPropertyCache
135 = propertyCaches->at(pendingBinding.referencingObjectIndex);
136 }
137
138 if (!pendingBinding.resolveInstantiatingProperty())
139 continue;
140 if (auto cache = pendingBinding.instantiatingPropertyCache())
141 propertyCaches->set(groupPropertyObjectIndex, cache);
142 }
143}
144
145QT_END_NAMESPACE
auto processUrlForClassName(const QUrl &url, BaseNameHandler &&baseNameHandler, FailHandler &&failHandler)
QQmlBindingInstantiationContext(int referencingObjectIndex, const QV4::CompiledData::Binding *instantiatingBinding, const QString &instantiatingPropertyName, const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache)
QQmlPropertyCache::ConstPtr instantiatingPropertyCache() const
void resolveMissingPropertyCaches(QQmlPropertyCacheVector *propertyCaches) const