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 | |
4 | #include "qqmlpropertycachecreator_p.h" |
5 | |
6 | #include <private/qqmlengine_p.h> |
7 | |
8 | #if QT_CONFIG(regularexpression) |
9 | #include <QtCore/qregularexpression.h> |
10 | #endif |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | QAtomicInt QQmlPropertyCacheCreatorBase::classIndexCounter(0); |
15 | |
16 | |
17 | QMetaType QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(QV4::CompiledData::CommonType type) |
18 | { |
19 | switch (type) { |
20 | case QV4::CompiledData::CommonType::Void: return QMetaType(); |
21 | case QV4::CompiledData::CommonType::Var: return QMetaType::fromType<QVariant>(); |
22 | case QV4::CompiledData::CommonType::Int: return QMetaType::fromType<int>(); |
23 | case QV4::CompiledData::CommonType::Bool: return QMetaType::fromType<bool>(); |
24 | case QV4::CompiledData::CommonType::Real: return QMetaType::fromType<qreal>(); |
25 | case QV4::CompiledData::CommonType::String: return QMetaType::fromType<QString>(); |
26 | case QV4::CompiledData::CommonType::Url: return QMetaType::fromType<QUrl>(); |
27 | case QV4::CompiledData::CommonType::Time: return QMetaType::fromType<QTime>(); |
28 | case QV4::CompiledData::CommonType::Date: return QMetaType::fromType<QDate>(); |
29 | case QV4::CompiledData::CommonType::DateTime: return QMetaType::fromType<QDateTime>(); |
30 | #if QT_CONFIG(regularexpression) |
31 | case QV4::CompiledData::CommonType::RegExp: return QMetaType::fromType<QRegularExpression>(); |
32 | #else |
33 | case QV4::CompiledData::CommonType::RegExp: return QMetaType(); |
34 | #endif |
35 | case QV4::CompiledData::CommonType::Rect: return QMetaType::fromType<QRectF>(); |
36 | case QV4::CompiledData::CommonType::Point: return QMetaType::fromType<QPointF>(); |
37 | case QV4::CompiledData::CommonType::Size: return QMetaType::fromType<QSizeF>(); |
38 | case QV4::CompiledData::CommonType::Invalid: break; |
39 | }; |
40 | return QMetaType {}; |
41 | } |
42 | |
43 | QMetaType QQmlPropertyCacheCreatorBase::listTypeForPropertyType(QV4::CompiledData::CommonType type) |
44 | { |
45 | switch (type) { |
46 | case QV4::CompiledData::CommonType::Void: return QMetaType(); |
47 | case QV4::CompiledData::CommonType::Var: return QMetaType::fromType<QList<QVariant>>(); |
48 | case QV4::CompiledData::CommonType::Int: return QMetaType::fromType<QList<int>>(); |
49 | case QV4::CompiledData::CommonType::Bool: return QMetaType::fromType<QList<bool>>(); |
50 | case QV4::CompiledData::CommonType::Real: return QMetaType::fromType<QList<qreal>>(); |
51 | case QV4::CompiledData::CommonType::String: return QMetaType::fromType<QList<QString>>(); |
52 | case QV4::CompiledData::CommonType::Url: return QMetaType::fromType<QList<QUrl>>(); |
53 | case QV4::CompiledData::CommonType::Time: return QMetaType::fromType<QList<QTime>>(); |
54 | case QV4::CompiledData::CommonType::Date: return QMetaType::fromType<QList<QDate>>(); |
55 | case QV4::CompiledData::CommonType::DateTime: return QMetaType::fromType<QList<QDateTime>>(); |
56 | #if QT_CONFIG(regularexpression) |
57 | case QV4::CompiledData::CommonType::RegExp: return QMetaType::fromType<QList<QRegularExpression>>(); |
58 | #else |
59 | case QV4::CompiledData::CommonType::RegExp: return QMetaType(); |
60 | #endif |
61 | case QV4::CompiledData::CommonType::Rect: return QMetaType::fromType<QList<QRectF>>(); |
62 | case QV4::CompiledData::CommonType::Point: return QMetaType::fromType<QList<QPointF>>(); |
63 | case QV4::CompiledData::CommonType::Size: return QMetaType::fromType<QList<QSizeF>>(); |
64 | case QV4::CompiledData::CommonType::Invalid: break; |
65 | }; |
66 | return QMetaType {}; |
67 | } |
68 | |
69 | QByteArray QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(const QUrl &url) |
70 | { |
71 | const QString path = url.path(); |
72 | int lastSlash = path.lastIndexOf(c: QLatin1Char('/')); |
73 | // Not a reusable type if we don't have an absolute Url |
74 | if (lastSlash <= -1) |
75 | return QByteArray(); |
76 | // ### this might not be correct for .ui.qml files |
77 | const QStringView nameBase = QStringView{path}.mid(pos: lastSlash + 1, n: path.size() - lastSlash - 5); |
78 | // Not a reusable type if it doesn't start with a upper case letter. |
79 | if (nameBase.isEmpty() || !nameBase.at(n: 0).isUpper()) |
80 | return QByteArray(); |
81 | return nameBase.toUtf8() + "_QMLTYPE_" + |
82 | QByteArray::number(classIndexCounter.fetchAndAddRelaxed(valueToAdd: 1)); |
83 | } |
84 | |
85 | QByteArray QQmlPropertyCacheCreatorBase::createClassNameForInlineComponent(const QUrl &baseUrl, int icId) |
86 | { |
87 | QByteArray baseName = createClassNameTypeByUrl(url: baseUrl); |
88 | if (baseName.isEmpty()) |
89 | baseName = QByteArray("ANON_QML_IC_" ) + QByteArray::number(classIndexCounter.fetchAndAddRelaxed(valueToAdd: 1)); |
90 | baseName += "_" + QByteArray::number(icId); |
91 | return baseName; |
92 | } |
93 | |
94 | QQmlBindingInstantiationContext::QQmlBindingInstantiationContext( |
95 | int referencingObjectIndex, |
96 | const QV4::CompiledData::Binding *instantiatingBinding, |
97 | const QString &instantiatingPropertyName, |
98 | const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache) |
99 | : referencingObjectIndex(referencingObjectIndex) |
100 | , instantiatingBinding(instantiatingBinding) |
101 | , instantiatingPropertyName(instantiatingPropertyName) |
102 | , referencingObjectPropertyCache(referencingObjectPropertyCache) |
103 | { |
104 | } |
105 | |
106 | bool QQmlBindingInstantiationContext::resolveInstantiatingProperty() |
107 | { |
108 | if (!instantiatingBinding |
109 | || instantiatingBinding->type() != QV4::CompiledData::Binding::Type_GroupProperty) { |
110 | return true; |
111 | } |
112 | |
113 | if (!referencingObjectPropertyCache) |
114 | return false; |
115 | |
116 | Q_ASSERT(referencingObjectIndex >= 0); |
117 | Q_ASSERT(instantiatingBinding->propertyNameIndex != 0); |
118 | |
119 | bool notInRevision = false; |
120 | instantiatingProperty = QQmlPropertyResolver(referencingObjectPropertyCache) |
121 | .property(name: instantiatingPropertyName, notInRevision: ¬InRevision, |
122 | check: QQmlPropertyResolver::IgnoreRevision); |
123 | return instantiatingProperty != nullptr; |
124 | } |
125 | |
126 | QQmlPropertyCache::ConstPtr QQmlBindingInstantiationContext::instantiatingPropertyCache() const |
127 | { |
128 | if (instantiatingProperty) { |
129 | if (instantiatingProperty->isQObject()) { |
130 | // rawPropertyCacheForType assumes a given unspecified version means "any version". |
131 | // There is another overload that takes no version, which we shall not use here. |
132 | return QQmlMetaType::rawPropertyCacheForType(metaType: instantiatingProperty->propType(), |
133 | version: instantiatingProperty->typeVersion()); |
134 | } else if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForValueType(type: instantiatingProperty->propType())) { |
135 | return QQmlMetaType::propertyCache(metaObject: vtmo, version: instantiatingProperty->typeVersion()); |
136 | } |
137 | } |
138 | return QQmlPropertyCache::ConstPtr(); |
139 | } |
140 | |
141 | void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches( |
142 | QQmlPropertyCacheVector *propertyCaches) const |
143 | { |
144 | for (QQmlBindingInstantiationContext pendingBinding: *this) { |
145 | const int groupPropertyObjectIndex = pendingBinding.instantiatingBinding->value.objectIndex; |
146 | |
147 | if (propertyCaches->at(index: groupPropertyObjectIndex)) |
148 | continue; |
149 | |
150 | if (pendingBinding.instantiatingPropertyName.isEmpty()) { |
151 | // Generalized group property. |
152 | auto cache = propertyCaches->at(index: pendingBinding.referencingObjectIndex); |
153 | propertyCaches->set(index: groupPropertyObjectIndex, replacement: cache); |
154 | continue; |
155 | } |
156 | |
157 | if (!pendingBinding.referencingObjectPropertyCache) { |
158 | pendingBinding.referencingObjectPropertyCache |
159 | = propertyCaches->at(index: pendingBinding.referencingObjectIndex); |
160 | } |
161 | |
162 | if (!pendingBinding.resolveInstantiatingProperty()) |
163 | continue; |
164 | auto cache = pendingBinding.instantiatingPropertyCache(); |
165 | propertyCaches->set(index: groupPropertyObjectIndex, replacement: cache); |
166 | } |
167 | } |
168 | |
169 | QT_END_NAMESPACE |
170 | |