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