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_p.h
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
5#ifndef QQMLPROPERTYCACHECREATOR_P_H
6#define QQMLPROPERTYCACHECREATOR_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmlvaluetype_p.h>
20#include <private/qqmlengine_p.h>
21#include <private/qqmlmetaobject_p.h>
22#include <private/qqmltypedata_p.h>
23#include <private/inlinecomponentutils_p.h>
24#include <private/qqmlsourcecoordinate_p.h>
25#include <private/qqmlsignalnames_p.h>
26#include <private/qexpected_p.h>
27
28#include <QtCore/qloggingcategory.h>
29#include <QtCore/qscopedvaluerollback.h>
30#include <QtCore/qtyperevision.h>
31
32#if QT_CONFIG(regularexpression)
33#include <QtCore/qregularexpression.h>
34#endif
35
36#include <vector>
37
39
41
42inline QQmlError qQmlCompileError(const QV4::CompiledData::Location &location,
43 const QString &description)
44{
45 QQmlError error;
46 error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line()));
47 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column()));
48 error.setDescription(description);
49 return error;
50}
51
55 int referencingObjectIndex, const QV4::CompiledData::Binding *instantiatingBinding,
56 const QString &instantiatingPropertyName,
57 const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache);
58
61
67};
68
70{
72 QQmlPropertyCacheVector *propertyCaches) const;
73};
74
76{
78public:
80
81 static std::optional<QMetaType> metaTypeForPropertyType(QV4::CompiledData::CommonType type)
82 {
83 switch (type) {
84 case QV4::CompiledData::CommonType::Void: return QMetaType();
85 case QV4::CompiledData::CommonType::Var: return QMetaType::fromType<QVariant>();
86 case QV4::CompiledData::CommonType::Int: return QMetaType::fromType<int>();
87 case QV4::CompiledData::CommonType::Bool: return QMetaType::fromType<bool>();
88 case QV4::CompiledData::CommonType::Real: return QMetaType::fromType<qreal>();
89 case QV4::CompiledData::CommonType::String: return QMetaType::fromType<QString>();
90 case QV4::CompiledData::CommonType::Url: return QMetaType::fromType<QUrl>();
91 case QV4::CompiledData::CommonType::Time: return QMetaType::fromType<QTime>();
92 case QV4::CompiledData::CommonType::Date: return QMetaType::fromType<QDate>();
93 case QV4::CompiledData::CommonType::DateTime: return QMetaType::fromType<QDateTime>();
94#if QT_CONFIG(regularexpression)
95 case QV4::CompiledData::CommonType::RegExp: return QMetaType::fromType<QRegularExpression>();
96#else
97 case QV4::CompiledData::CommonType::RegExp: return {};
98#endif
99 case QV4::CompiledData::CommonType::Rect: return QMetaType::fromType<QRectF>();
100 case QV4::CompiledData::CommonType::Point: return QMetaType::fromType<QPointF>();
101 case QV4::CompiledData::CommonType::Size: return QMetaType::fromType<QSizeF>();
102 case QV4::CompiledData::CommonType::Invalid: break;
103 };
104 return {};
105 }
106
107 static std::optional<QMetaType> listTypeForPropertyType(QV4::CompiledData::CommonType type)
108 {
109 switch (type) {
110 case QV4::CompiledData::CommonType::Void: return QMetaType();
111 case QV4::CompiledData::CommonType::Var: return QMetaType::fromType<QList<QVariant>>();
112 case QV4::CompiledData::CommonType::Int: return QMetaType::fromType<QList<int>>();
113 case QV4::CompiledData::CommonType::Bool: return QMetaType::fromType<QList<bool>>();
114 case QV4::CompiledData::CommonType::Real: return QMetaType::fromType<QList<qreal>>();
115 case QV4::CompiledData::CommonType::String: return QMetaType::fromType<QList<QString>>();
116 case QV4::CompiledData::CommonType::Url: return QMetaType::fromType<QList<QUrl>>();
117 case QV4::CompiledData::CommonType::Time: return QMetaType::fromType<QList<QTime>>();
118 case QV4::CompiledData::CommonType::Date: return QMetaType::fromType<QList<QDate>>();
119 case QV4::CompiledData::CommonType::DateTime: return QMetaType::fromType<QList<QDateTime>>();
120#if QT_CONFIG(regularexpression)
121 case QV4::CompiledData::CommonType::RegExp: return QMetaType::fromType<QList<QRegularExpression>>();
122#else
123 case QV4::CompiledData::CommonType::RegExp: return {};
124#endif
125 case QV4::CompiledData::CommonType::Rect: return QMetaType::fromType<QList<QRectF>>();
126 case QV4::CompiledData::CommonType::Point: return QMetaType::fromType<QList<QPointF>>();
127 case QV4::CompiledData::CommonType::Size: return QMetaType::fromType<QList<QSizeF>>();
128 case QV4::CompiledData::CommonType::Invalid: break;
129 };
130 return {};
131 }
132
133 static QV4::CompiledData::CommonType propertyTypeForMetaType(QMetaType metaType) {
134 if (!metaType.isValid())
135 return QV4::CompiledData::CommonType::Void;
136
137 switch (metaType.id()) {
138 case QMetaType::QVariant:
139 return QV4::CompiledData::CommonType::Var;
140 case QMetaType::Int:
141 return QV4::CompiledData::CommonType::Int;
142 case QMetaType::Bool:
143 return QV4::CompiledData::CommonType::Bool;
144 case QMetaType::QReal:
145 return QV4::CompiledData::CommonType::Real;
146 case QMetaType::QString:
147 return QV4::CompiledData::CommonType::String;
148 case QMetaType::QUrl:
149 return QV4::CompiledData::CommonType::Url;
150 case QMetaType::QTime:
151 return QV4::CompiledData::CommonType::Time;
152 case QMetaType::QDate:
153 return QV4::CompiledData::CommonType::Date;
154 case QMetaType::QDateTime:
155 return QV4::CompiledData::CommonType::DateTime;
156#if QT_CONFIG(regularexpression)
157 case QMetaType::QRegularExpression:
158 return QV4::CompiledData::CommonType::RegExp;
159#endif
160 case QMetaType::QRectF:
161 return QV4::CompiledData::CommonType::Rect;
162 case QMetaType::QPointF:
163 return QV4::CompiledData::CommonType::Point;
164 case QMetaType::QSizeF:
165 return QV4::CompiledData::CommonType::Size;
166 default:
167 break;
168 }
169 return QV4::CompiledData::CommonType::Invalid;
170 }
171
172 static bool canCreateClassNameTypeByUrl(const QUrl &url);
173 static QByteArray createClassNameTypeByUrl(const QUrl &url);
174 static QByteArray createClassNameForInlineComponent(const QUrl &url);
175
177 // valid if and only if an error occurred
179 // true if there was no error and there are still components left to process
180 bool canResume = false;
181 // the object index of the last processed (inline) component root.
183 };
184
185 // TODO just reuse message from the QQmlPropertyCacheCreator::maybeLog
186 static QString explain(OverrideSemantics::Status reason)
187 {
188 switch (reason) {
189 case OverrideSemantics::Status::MissingBase:
190 return tr("Nothing to override. Remove \"override\" keyword");
191 case OverrideSemantics::Status::OverridingFinal:
192 return tr("Cannot override FINAL property");
193 case OverrideSemantics::Status::OverridingNonVirtualError:
194 return tr("Cannot override non virtual property. Add \"virtual\" to the property of "
195 "the base object");
196 default:
197 return tr("unknown");
198 }
199 }
200};
201
202template <typename ObjectContainer>
204{
205public:
206 using CompiledObject = typename ObjectContainer::CompiledObject;
207 using InlineComponent = typename std::remove_reference<decltype (*(std::declval<CompiledObject>().inlineComponentsBegin()))>::type;
208
209 QQmlPropertyCacheCreator(QQmlPropertyCacheVector *propertyCaches,
210 QQmlPendingGroupPropertyBindings *pendingGroupPropertyBindings,
211 QQmlTypeLoader *typeLoader,
212 const ObjectContainer *objectContainer, const QQmlImports *imports,
213 const QByteArray &typeClassName);
214 ~QQmlPropertyCacheCreator() { propertyCaches->seal(); }
215
216
217 /*!
218 \internal
219 Creates the property cache for the CompiledObjects of objectContainer,
220 one (inline) root component at a time.
221
222 \note Later compiler passes might modify those property caches. Therefore,
223 the actual metaobjects are not created yet.
224 */
226
227 /*!
228 \internal
229 Returns a valid error if the inline components of the objectContainer
230 form a cycle. Otherwise an invalid error is returned
231 */
233
234 /*!
235 \internal
236 Tries to creates a property cache for the CompiledObject based on the cache of a base type.
237 Returns QQmlError in case of invalid overrides
238
239 \note: Aliases are added separately in appendAliasToPropertyCache
240 */
241 [[nodiscard]] q23::expected<QQmlPropertyCache::Ptr, QQmlError>
242 tryDeriveCacheFrom(const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache,
243 QByteArray dynamicClassName = QByteArray()) const;
244
245 /*!
246 \internal
247 Tries to create a QQmlPropertyData based on IR of a property.
248 This involves property type resolution and property flags creation
249
250 \a notifyIndex MUST be in the signal index range (see QObjectPrivate::signalIndex()).
251 This is different from QMetaMethod::methodIndex()
252
253 return error in case of failed type resolution
254 */
255 [[nodiscard]] q23::expected<QQmlPropertyData, QQmlError>
256 tryCreateQQmlPropertyData(const QV4::CompiledData::Property &propertyIR, int coreIndex,
257 int notifyIndex) const;
258
259protected:
261
263 const QQmlBindingInstantiationContext &context,
264 VMEMetaObjectIsRequired isVMERequired);
265 QQmlPropertyCache::ConstPtr propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const;
266 QQmlError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache);
267
268 std::optional<QMetaType> metaTypeForParameter(const QV4::CompiledData::ParameterType &param,
269 QString *customTypeName = nullptr) const;
270
271 QString stringAt(int index) const { return objectContainer->stringAt(index); }
272
273private:
274 struct PropertyType
275 {
276 QMetaType metaType;
277 QTypeRevision revision = QTypeRevision::zero();
278 QV4::CompiledData::CommonType commonType = QV4::CompiledData::CommonType::Invalid;
279 };
280
281 [[nodiscard]] q23::expected<PropertyType, QQmlError>
282 tryResolvePropertyType(const QV4::CompiledData::Property &propertyIR) const;
283
284 // can be made a free function
285 [[nodiscard]] static QQmlPropertyData::Flags
286 propertyDataFlags(const QV4::CompiledData::Property &propertyIR,
287 const PropertyType &resolvedPropertyType);
288
289protected:
291 const ObjectContainer * const objectContainer;
292 const QQmlImports * const imports;
295 QByteArray typeClassName; // not const as we temporarily chang it for inline components
296 unsigned int currentRoot; // set to objectID of inline component root when handling inline components
297
302 bool hasCycle = false;
303};
304
305template <typename ObjectContainer>
307 QQmlPropertyCacheVector *propertyCaches,
308 QQmlPendingGroupPropertyBindings *pendingGroupPropertyBindings,
309 QQmlTypeLoader *typeLoader,
310 const ObjectContainer *objectContainer, const QQmlImports *imports,
311 const QByteArray &typeClassName)
313 , objectContainer(objectContainer)
316 , pendingGroupPropertyBindings(pendingGroupPropertyBindings)
318 , currentRoot(-1)
319{
320 propertyCaches->resetAndResize(objectContainer->objectCount());
321
322 using namespace icutils;
323
324 // get a list of all inline components
325
326 for (int i=0; i != objectContainer->objectCount(); ++i) {
327 const CompiledObject *obj = objectContainer->objectAt(i);
328 for (auto it = obj->inlineComponentsBegin(); it != obj->inlineComponentsEnd(); ++it) {
329 allICs.push_back(*it);
330 }
331 }
332
333 // create a graph on inline components referencing inline components
334 std::vector<icutils::Node> nodes;
335 nodes.resize(allICs.size());
336 std::iota(nodes.begin(), nodes.end(), 0);
337 AdjacencyList adjacencyList;
338 adjacencyList.resize(nodes.size());
339 fillAdjacencyListForInlineComponents(objectContainer, adjacencyList, nodes, allICs);
340
341 nodesSorted = topoSort(nodes, adjacencyList, hasCycle);
342 nodeIt = nodesSorted.rbegin();
343}
344
345template <typename ObjectContainer>
347{
348 if (hasCycle) {
349 QQmlError diag;
350 diag.setDescription(QLatin1String("Inline components form a cycle!"));
351 return diag;
352 }
353 return {};
354}
355
356template <typename ObjectContainer>
359{
360 // needs to be checked with verifyNoICCycle before this function is called
361 Q_ASSERT(!hasCycle);
362
363 // create meta objects for inline components before compiling actual root component
364 if (nodeIt != nodesSorted.rend()) {
365 const auto &ic = allICs[nodeIt->index()];
366 QV4::ResolvedTypeReference *typeRef = objectContainer->resolvedType(ic.nameIndex);
367 Q_ASSERT(propertyCaches->at(ic.objectIndex).isNull());
368 Q_ASSERT(typeRef->typePropertyCache().isNull()); // not set yet
369
370 QByteArray icTypeName { objectContainer->stringAt(ic.nameIndex).toUtf8() };
371 QScopedValueRollback<QByteArray> nameChange {typeClassName, icTypeName};
372 QScopedValueRollback<unsigned int> rootChange {currentRoot, ic.objectIndex};
373 ++nodeIt;
374 QQmlError diag = buildMetaObjectRecursively(ic.objectIndex, m_context, VMEMetaObjectIsRequired::Always);
375 if (diag.isValid()) {
376 return {diag, false, 0};
377 }
378 typeRef->setTypePropertyCache(propertyCaches->at(ic.objectIndex));
379 Q_ASSERT(!typeRef->typePropertyCache().isNull());
380 return { QQmlError(), true, int(ic.objectIndex) };
381 }
382
383 auto diag = buildMetaObjectRecursively(/*root object*/0, m_context, VMEMetaObjectIsRequired::Maybe);
384 return {diag, false, 0};
385}
386
387template <typename ObjectContainer>
390 const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache,
391 QByteArray dynamicClassName) const
392{
393 QQmlPropertyCache::Ptr cache = baseTypeCache->copyAndReserve(
394 obj->propertyCount() + obj->aliasCount(),
395 obj->functionCount() + obj->propertyCount() + obj->aliasCount() + obj->signalCount(),
396 obj->signalCount() + obj->propertyCount() + obj->aliasCount(), obj->enumCount());
397 cache->_dynamicClassName = std::move(dynamicClassName);
398
399 int effectiveMethodIndex = cache->methodIndexCacheStart;
400
401 // For property change signal override detection.
402 // We prepopulate a set of signal names which already exist in the object,
403 // and throw an error if there is a signal/method defined as an override.
404 // TODO: Remove AllowOverride once we can. No override should be allowed.
405 enum class AllowOverride { No, Yes };
406 QHash<QString, AllowOverride> seenSignals{
407 { QStringLiteral("destroyed"), AllowOverride::No },
408 { QStringLiteral("parentChanged"), AllowOverride::No },
409 { QStringLiteral("objectNameChanged"), AllowOverride::No }
410 };
411 const QQmlPropertyCache *parentCache = cache.data();
412 while ((parentCache = parentCache->parent().data())) {
413 if (int pSigCount = parentCache->signalCount()) {
414 int pSigOffset = parentCache->signalOffset();
415 for (int i = pSigOffset; i < pSigCount; ++i) {
416 const QQmlPropertyData *currPSig = parentCache->signal(i);
417 // XXX TODO: find a better way to get signal name from the property data :-/
418 for (QQmlPropertyCache::StringCache::ConstIterator iter =
419 parentCache->stringCache.begin();
420 iter != parentCache->stringCache.end(); ++iter) {
421 if (currPSig == (*iter).second) {
422 if (currPSig->isOverridableSignal()) {
423 const qsizetype oldSize = seenSignals.size();
424 AllowOverride &entry = seenSignals[iter.key()];
425 if (seenSignals.size() != oldSize)
426 entry = AllowOverride::Yes;
427 } else {
428 seenSignals[iter.key()] = AllowOverride::No;
429 }
430
431 break;
432 }
433 }
434 }
435 }
436 }
437
438 // Set up notify signals for properties - first normal, then alias
439 auto p = obj->propertiesBegin();
440 auto pend = obj->propertiesEnd();
441 for (; p != pend; ++p) {
442 auto flags = QQmlPropertyData::defaultSignalFlags();
443
444 const QString changedSigName =
445 QQmlSignalNames::propertyNameToChangedSignalName(stringAt(p->nameIndex()));
446 seenSignals[changedSigName] = AllowOverride::No;
447
448 cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
449 }
450
451 auto a = obj->aliasesBegin();
452 auto aend = obj->aliasesEnd();
453 for (; a != aend; ++a) {
454 auto flags = QQmlPropertyData::defaultSignalFlags();
455
456 const QString changedSigName =
457 QQmlSignalNames::propertyNameToChangedSignalName(stringAt(a->nameIndex()));
458 seenSignals[changedSigName] = AllowOverride::No;
459
460 cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
461 }
462
463 auto e = obj->enumsBegin();
464 auto eend = obj->enumsEnd();
465 for (; e != eend; ++e) {
466 const int enumValueCount = e->enumValueCount();
467 QList<QQmlEnumValue> values;
468 values.reserve(enumValueCount);
469
470 auto enumValue = e->enumValuesBegin();
471 auto end = e->enumValuesEnd();
472 for (; enumValue != end; ++enumValue)
473 values.append(QQmlEnumValue(stringAt(enumValue->nameIndex), enumValue->value));
474
475 cache->appendEnum(stringAt(e->nameIndex), values);
476 }
477
478 // Dynamic signals
479 auto s = obj->signalsBegin();
480 auto send = obj->signalsEnd();
481 for (; s != send; ++s) {
482 const int paramCount = s->parameterCount();
483
484 QList<QByteArray> names;
485 names.reserve(paramCount);
486 QVarLengthArray<QMetaType, 10> paramTypes(paramCount);
487
488 if (paramCount) {
489
490 int i = 0;
491 auto param = s->parametersBegin();
492 auto end = s->parametersEnd();
493 for (; param != end; ++param, ++i) {
494 names.append(stringAt(param->nameIndex).toUtf8());
495
496 QString customTypeName;
497 std::optional<QMetaType> type = metaTypeForParameter(param->type, &customTypeName);
498 if (!type.has_value())
499 return q23::make_unexpected(qQmlCompileError(
500 s->location,
501 QQmlPropertyCacheCreatorBase::tr("Invalid signal parameter type: %1")
502 .arg(customTypeName)));
503
504 paramTypes[i] = *type;
505 }
506 }
507
508 auto flags = QQmlPropertyData::defaultSignalFlags();
509 if (paramCount)
510 flags.setHasArguments(true);
511
512 QString signalName = stringAt(s->nameIndex);
513 const auto it = seenSignals.find(signalName);
514 if (it == seenSignals.end()) {
515 seenSignals[signalName] = AllowOverride::No;
516 } else {
517 // TODO: Remove the AllowOverride::Yes branch once we can.
518 QQmlError message = qQmlCompileError(
519 s->location,
520 QQmlPropertyCacheCreatorBase::tr(
521 "Duplicate signal name: "
522 "invalid override of property change signal or superclass signal"));
523 switch (*it) {
524 case AllowOverride::No:
525 return q23::make_unexpected(std::move(message));
526 case AllowOverride::Yes:
527 message.setUrl(objectContainer->url());
528 qCWarning(invalidOverride).noquote() << message.toString();
529 *it = AllowOverride::No; // No further overriding allowed.
530 break;
531 }
532 }
533 cache->appendSignal(signalName, flags, effectiveMethodIndex++,
534 paramCount ? paramTypes.constData() : nullptr, names);
535 }
536
537 // Dynamic slots
538 auto function = objectContainer->objectFunctionsBegin(obj);
539 auto fend = objectContainer->objectFunctionsEnd(obj);
540 for (; function != fend; ++function) {
541 auto flags = QQmlPropertyData::defaultSlotFlags();
542
543 const QString slotName = stringAt(function->nameIndex);
544 const auto it = seenSignals.constFind(slotName);
545 if (it != seenSignals.constEnd()) {
546 // TODO: Remove the AllowOverride::Yes branch once we can.
547 QQmlError message = qQmlCompileError(
548 function->location,
549 QQmlPropertyCacheCreatorBase::tr(
550 "Duplicate method name: "
551 "invalid override of property change signal or superclass signal"));
552 switch (*it) {
553 case AllowOverride::No:
554 return q23::make_unexpected(std::move(message));
555 case AllowOverride::Yes:
556 message.setUrl(objectContainer->url());
557 qCWarning(invalidOverride).noquote() << message.toString();
558 break;
559 }
560 }
561 // Note: we don't append slotName to the seenSignals list, since we don't
562 // protect against overriding change signals or methods with properties.
563
564 QList<QByteArray> parameterNames;
565 QList<QMetaType> parameterTypes;
566 auto formal = function->formalsBegin();
567 auto end = function->formalsEnd();
568 for (; formal != end; ++formal) {
569 flags.setHasArguments(true);
570 parameterNames << stringAt(formal->nameIndex).toUtf8();
571 std::optional<QMetaType> type = metaTypeForParameter(formal->type);
572 if (!type.has_value())
573 type = QMetaType::fromType<QVariant>();
574 parameterTypes << *type;
575 }
576
577 std::optional<QMetaType> returnType = metaTypeForParameter(function->returnType);
578 if (!returnType.has_value())
579 returnType = QMetaType::fromType<QVariant>();
580
581 cache->appendMethod(slotName, flags, effectiveMethodIndex++, *returnType, parameterNames,
582 parameterTypes);
583 }
584
585 // Dynamic properties
586 int propertyIndex = cache->propertyIndexCacheStart;
587 int notifyIndex = cache->signalHandlerIndexCacheStart;
588 int objPropertyIdx = 0;
589 p = obj->propertiesBegin();
590 pend = obj->propertiesEnd();
591 for (; p != pend; ++p, ++objPropertyIdx, propertyIndex++, notifyIndex++) {
592 auto propertyDataOrError = tryCreateQQmlPropertyData(*p, propertyIndex, notifyIndex);
593 if (!propertyDataOrError.has_value()) {
594 return q23::make_unexpected(propertyDataOrError.error());
595 }
596
597 QString propertyName = stringAt(p->nameIndex());
598 if (!obj->hasAliasAsDefaultProperty()
599 && objPropertyIdx == obj->indexOfDefaultPropertyOrAlias)
600 cache->_defaultPropertyName = propertyName;
601
602 const auto &appendResult =
603 cache->appendPropertyAttr(propertyName, std::move(propertyDataOrError).value());
604 if (!appendResult) {
605 return q23::make_unexpected(
606 qQmlCompileError(p->location, explain(appendResult.error())));
607 }
608 }
609 return cache;
610};
611
612template <typename ObjectContainer>
615 const QV4::CompiledData::Property &propertyIR, int coreIndex, int notifyIndex) const
616{
617 const auto propertyTypeOrError = tryResolvePropertyType(propertyIR);
618 if (!propertyTypeOrError.has_value()) {
619 return q23::make_unexpected(propertyTypeOrError.error());
620 }
621 const auto propertyType = propertyTypeOrError.value();
622
623 QQmlPropertyData propertyData;
624 propertyData.setPropType(propertyType.metaType);
625 propertyData.setCoreIndex(coreIndex);
626 propertyData.setNotifyIndex(notifyIndex);
627 propertyData.setFlags(QQmlPropertyCacheCreator::propertyDataFlags(propertyIR, propertyType));
628 propertyData.setTypeVersion(propertyType.revision);
629 return propertyData;
630}
631
632template <typename ObjectContainer>
634{
635 auto isAddressable = [](const QUrl &url) {
636 const QString fileName = url.fileName();
637 return !fileName.isEmpty() && fileName.front().isUpper();
638 };
639
640 const CompiledObject *obj = objectContainer->objectAt(objectIndex);
641 bool needVMEMetaObject = isVMERequired == VMEMetaObjectIsRequired::Always
642 || obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0
643 || obj->functionCount() != 0 || obj->enumCount() != 0
644 || obj->inlineComponentCount() != 0
645 || ((obj->hasFlag(QV4::CompiledData::Object::IsComponent)
646 || (objectIndex == 0 && isAddressable(objectContainer->url())))
647 && !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType());
648
649 if (!needVMEMetaObject) {
650 auto binding = obj->bindingsBegin();
651 auto end = obj->bindingsEnd();
652 for ( ; binding != end; ++binding) {
653 if (binding->type() == QV4::CompiledData::Binding::Type_Object
654 && (binding->flags() & QV4::CompiledData::Binding::IsOnAssignment)) {
655 // If the on assignment is inside a group property, we need to distinguish between QObject based
656 // group properties and value type group properties. For the former the base type is derived from
657 // the property that references us, for the latter we only need a meta-object on the referencing object
658 // because interceptors can't go to the shared value type instances.
659 if (context.instantiatingProperty && QQmlMetaType::isValueType(context.instantiatingProperty->propType())) {
660 if (!propertyCaches->needsVMEMetaObject(context.referencingObjectIndex)) {
661 const CompiledObject *obj = objectContainer->objectAt(context.referencingObjectIndex);
662 auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
663 Q_ASSERT(typeRef);
664 QQmlPropertyCache::ConstPtr baseTypeCache = typeRef->createPropertyCache();
665 QQmlError error = baseTypeCache
666 ? createMetaObject(context.referencingObjectIndex, obj, baseTypeCache)
667 : qQmlCompileError(binding->location, QQmlPropertyCacheCreatorBase::tr(
668 "Type cannot be used for 'on' assignment"));
669 if (error.isValid())
670 return error;
671 }
672 } else {
673 // On assignments are implemented using value interceptors, which require a VME meta object.
674 needVMEMetaObject = true;
675 }
676 break;
677 }
678 }
679 }
680
681 QQmlPropertyCache::ConstPtr baseTypeCache;
682 {
683 QQmlError error;
684 baseTypeCache = propertyCacheForObject(obj, context, &error);
685 if (error.isValid())
686 return error;
687 }
688
689 if (baseTypeCache) {
690 if (needVMEMetaObject) {
691 QQmlError error = createMetaObject(objectIndex, obj, baseTypeCache);
692 if (error.isValid())
693 return error;
694 } else {
695 propertyCaches->set(objectIndex, baseTypeCache);
696 }
697 }
698
699 QQmlPropertyCache::ConstPtr thisCache = propertyCaches->at(objectIndex);
700 auto binding = obj->bindingsBegin();
701 auto end = obj->bindingsEnd();
702 for (; binding != end; ++binding) {
703 switch (binding->type()) {
704 case QV4::CompiledData::Binding::Type_Object:
705 case QV4::CompiledData::Binding::Type_GroupProperty:
706 case QV4::CompiledData::Binding::Type_AttachedProperty:
707 // We can always resolve object, group, and attached properties.
708 break;
709 default:
710 // Everything else is of no interest here.
711 continue;
712 }
713
715 objectIndex, &(*binding), stringAt(binding->propertyNameIndex), thisCache);
716
717 // Binding to group property where we failed to look up the type of the
718 // property? Possibly a group property that is an alias that's not resolved yet.
719 // Let's attempt to resolve it after we're done with the aliases and fill in the
720 // propertyCaches entry then.
721 if (!thisCache || !context.resolveInstantiatingProperty())
722 pendingGroupPropertyBindings->append(context);
723
724 QQmlError error = buildMetaObjectRecursively(
725 binding->value.objectIndex, context, VMEMetaObjectIsRequired::Maybe);
726 if (error.isValid())
727 return error;
728 }
729
730 QQmlError noError;
731 return noError;
732}
733
734template <typename ObjectContainer>
735inline QQmlPropertyCache::ConstPtr QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const
736{
737 if (context.instantiatingProperty) {
738 return context.instantiatingPropertyCache();
739 } else if (obj->inheritedTypeNameIndex != 0) {
740 auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
741 Q_ASSERT(typeRef);
742
743 if (typeRef->isFullyDynamicType()) {
744 if (obj->propertyCount() > 0 || obj->aliasCount() > 0) {
745 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new properties."));
746 return nullptr;
747 }
748 if (obj->signalCount() > 0) {
749 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new signals."));
750 return nullptr;
751 }
752 if (obj->functionCount() > 0) {
753 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully Dynamic types cannot declare new functions."));
754 return nullptr;
755 }
756 }
757
758 if (QQmlPropertyCache::ConstPtr propertyCache = typeRef->createPropertyCache())
759 return propertyCache;
760 *error = qQmlCompileError(
761 obj->location,
762 QQmlPropertyCacheCreatorBase::tr("Type '%1' cannot declare new members.")
763 .arg(stringAt(obj->inheritedTypeNameIndex)));
764 return nullptr;
765 } else if (const QV4::CompiledData::Binding *binding = context.instantiatingBinding) {
766 if (binding->isAttachedProperty()) {
767 auto *typeRef = objectContainer->resolvedType(
768 binding->propertyNameIndex);
769 Q_ASSERT(typeRef);
770 QQmlType qmltype = typeRef->type();
771 if (!qmltype.isValid()) {
772 imports->resolveType(
773 typeLoader, stringAt(binding->propertyNameIndex),
774 &qmltype, nullptr, nullptr);
775 }
776
777 const QMetaObject *attachedMo = qmltype.attachedPropertiesType(typeLoader);
778 if (!attachedMo) {
779 *error = qQmlCompileError(binding->location, QQmlPropertyCacheCreatorBase::tr("Non-existent attached object"));
780 return nullptr;
781 }
782 return QQmlMetaType::propertyCache(attachedMo);
783 }
784 }
785 return nullptr;
786}
787
788template <typename ObjectContainer>
790 int objectIndex, const CompiledObject *obj,
791 const QQmlPropertyCache::ConstPtr &baseTypeCache)
792{
793 const auto dynamicClassName = [this](int objectIndex, const auto &baseTypeCache) -> QByteArray {
794 const auto isComponentRoot = objectIndex == 0 /*root object*/
795 || objectIndex == int(currentRoot) /*root object of IC*/;
796 if (isComponentRoot && !typeClassName.isEmpty()) {
797 return typeClassName;
798 }
799 return QByteArray(QQmlMetaObject(baseTypeCache).className())
800 .append("_QML_")
801 .append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
802 };
803
804 const auto cacheOrError =
805 tryDeriveCacheFrom(obj, baseTypeCache, dynamicClassName(objectIndex, baseTypeCache));
806 if (!cacheOrError.has_value()) {
807 return cacheOrError.error();
808 }
809 auto &cache = cacheOrError.value();
810
811 using ListPropertyAssignBehavior = typename ObjectContainer::ListPropertyAssignBehavior;
812 switch (objectContainer->listPropertyAssignBehavior()) {
813 case ListPropertyAssignBehavior::ReplaceIfNotDefault:
814 cache->_listPropertyAssignBehavior = "ReplaceIfNotDefault";
815 break;
816 case ListPropertyAssignBehavior::Replace:
817 cache->_listPropertyAssignBehavior = "Replace";
818 break;
819 case ListPropertyAssignBehavior::Append:
820 break;
821 }
822
823 propertyCaches->setOwn(objectIndex, cache);
824 propertyCaches->setNeedsVMEMetaObject(objectIndex);
825 return QQmlError();
826}
827
828template <typename ObjectContainer>
830 const QV4::CompiledData::ParameterType &param, QString *customTypeName) const
831{
832 const quint32 typeId = param.typeNameIndexOrCommonType();
833 if (param.indexIsCommonType()) {
834 // built-in type
835 if (param.isList())
836 return listTypeForPropertyType(QV4::CompiledData::CommonType(typeId));
837 return metaTypeForPropertyType(QV4::CompiledData::CommonType(typeId));
838 }
839
840 // lazily resolved type
841 const QString typeName = stringAt(param.typeNameIndexOrCommonType());
842 if (customTypeName)
843 *customTypeName = typeName;
844 QQmlType qmltype;
845 bool selfReference = false;
846 if (!imports->resolveType(
847 typeLoader, typeName, &qmltype, nullptr, nullptr, nullptr,
848 QQmlType::AnyRegistrationType, &selfReference))
849 return {};
850
851 if (!qmltype.isComposite()) {
852 const QMetaType typeId = param.isList() ? qmltype.qListTypeId() : qmltype.typeId();
853 if (!typeId.isValid() && qmltype.isInlineComponentType()) {
854 const QQmlType qmlType = objectContainer->qmlTypeForComponent(qmltype.elementName());
855 return param.isList() ? qmlType.qListTypeId() : qmlType.typeId();
856 } else {
857 return typeId;
858 }
859 }
860
861 if (selfReference) {
862 const QQmlType qmlType = objectContainer->qmlTypeForComponent();
863 return param.isList() ? qmlType.qListTypeId() : qmlType.typeId();
864 }
865
866 return param.isList() ? qmltype.qListTypeId() : qmltype.typeId();
867}
868
869template <typename ObjectContainer>
870inline auto QQmlPropertyCacheCreator<ObjectContainer>::tryResolvePropertyType(
871 const QV4::CompiledData::Property &propertyIR) const
872 -> q23::expected<PropertyType, QQmlError>
873{
874 using namespace Qt::StringLiterals;
875 PropertyType propertyType;
876 propertyType.commonType = propertyIR.commonType();
877
878 if (propertyType.commonType != QV4::CompiledData::CommonType::Invalid) {
879 std::optional<QMetaType> metaType = propertyIR.isList()
880 ? listTypeForPropertyType(propertyType.commonType)
881 : metaTypeForPropertyType(propertyType.commonType);
882 if (!metaType.has_value())
883 metaType = QMetaType::fromType<QVariant>();
884
885 // common type
886 propertyType.metaType = *metaType;
887 return propertyType;
888 }
889
890 // needs to be resolved
891 // can be extracted and passed to tryResolvePropertyType as a function object to simplify
892 // dependency injection (imports / typeLoader)
893 Q_ASSERT(!propertyIR.isCommonType());
894 QQmlType qmltype;
895 bool selfReference = false;
896 QList<QQmlError> errors;
897 const QString typeName = stringAt(propertyIR.commonTypeOrTypeNameIndex());
898 if (!imports->resolveType(typeLoader, typeName, &qmltype, nullptr, nullptr, &errors,
899 QQmlType::AnyRegistrationType, &selfReference)) {
900 Q_ASSERT(!errors.isEmpty());
901
902 if (typeName == "list"_L1 && errors[0].description() == "is not a type"_L1) {
903 errors[0].setDescription(errors[0].description().append(
904 ". It requires an element type argument (eg. list<int>)"_L1));
905 }
906
907 return q23::make_unexpected(
908 qQmlCompileError(propertyIR.location, typeName + u' ' + errors[0].description()));
909 }
910
911 Q_ASSERT(qmltype.isValid());
912
913 propertyType.metaType = propertyIR.isList() ? qmltype.qListTypeId() : qmltype.typeId();
914
915 if (!qmltype.isComposite() && !qmltype.isInlineComponentType())
916 propertyType.revision = qmltype.version();
917
918 return propertyType;
919}
920
921template <typename ObjectContainer>
922inline QQmlPropertyData::Flags QQmlPropertyCacheCreator<ObjectContainer>::propertyDataFlags(
923 const QV4::CompiledData::Property &propertyIR, const PropertyType &resolvedPropertyType)
924{
925 QQmlPropertyData::Flags flags;
926
927 // set type flag
928 if (propertyIR.isList()) {
929 flags.setType(QQmlPropertyData::Flags::QListType);
930 } else if (resolvedPropertyType.commonType == QV4::CompiledData::CommonType::Var) {
931 flags.setType(QQmlPropertyData::Flags::VarPropertyType);
932 } else if (resolvedPropertyType.metaType.flags().testFlag(QMetaType::PointerToQObject)) {
933 flags.setType(QQmlPropertyData::Flags::QObjectDerivedType);
934 }
935
936 // set attributes
937 if (!propertyIR.isReadOnly()
938 && !resolvedPropertyType.metaType.flags().testFlag(QMetaType::IsQmlList))
939 flags.setIsWritable(true);
940 if (propertyIR.isFinal())
941 flags.setIsFinal(true);
942 if (propertyIR.isVirtual())
943 flags.setIsVirtual(true);
944 if (propertyIR.isOverride())
945 flags.setDoesOverride(true);
946
947 return flags;
948}
949
950template <typename ObjectContainer, typename CompiledObject>
951int objectForId(const ObjectContainer *objectContainer, const CompiledObject &component, int id)
952{
953 for (quint32 i = 0, count = component.namedObjectsInComponentCount(); i < count; ++i) {
954 const int candidateIndex = component.namedObjectsInComponentTable()[i];
955 const CompiledObject &candidate = *objectContainer->objectAt(candidateIndex);
956 if (candidate.objectId() == id)
957 return candidateIndex;
958 }
959 return -1;
960}
961
962template <typename ObjectContainer>
964{
965public:
966 typedef typename ObjectContainer::CompiledObject CompiledObject;
967
969 QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer);
971 const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex,
972 int aliasIndex, int encodedMetaPropertyIndex, int resolvedTargetObjectId);
973
974private:
975 QQmlError propertyDataForAlias(
976 const CompiledObject &component, const QV4::CompiledData::Alias &alias, QMetaType *type,
977 QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags,
978 int targetPropertyIndex, int resolvedTargetObjectId);
979
980 QQmlPropertyCacheVector *propertyCaches;
981 const ObjectContainer *objectContainer;
982};
983
984template <typename ObjectContainer>
986 QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer)
988 , objectContainer(objectContainer)
989{
990}
991
992template <typename ObjectContainer>
993inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(
994 const CompiledObject &component, const QV4::CompiledData::Alias &alias, QMetaType *type,
995 QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags,
996 int targetPropertyIndex, int resolvedTargetObjectId)
997{
998 *type = QMetaType();
999 bool writable = false;
1000 bool resettable = false;
1001 bool notifiesViaBindable = false;
1002
1003 propertyFlags->setIsAlias(true);
1004
1005 const int targetObjectIndex = objectForId(objectContainer, component, resolvedTargetObjectId);
1006 Q_ASSERT(targetObjectIndex >= 0);
1007 const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
1008
1009 if (targetPropertyIndex == -1) {
1010 Q_ASSERT(objectContainer->stringAt(alias.propertyNameIndex()).isEmpty());
1011 auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
1012 if (!typeRef) {
1013 // Can be caused by the alias target not being a valid id or property. E.g.:
1014 // property alias dataValue: dataVal
1015 // invalidAliasComponent { id: dataVal }
1016 return qQmlCompileError(targetObject.location,
1017 QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
1018 }
1019
1020 const auto referencedType = typeRef->type();
1021 Q_ASSERT(referencedType.isValid());
1022 *type = referencedType.typeId();
1023 if (!type->isValid() && referencedType.isInlineComponentType()) {
1024 *type = objectContainer->qmlTypeForComponent(referencedType.elementName()).typeId();
1025 Q_ASSERT(type->isValid());
1026 }
1027
1028 *version = typeRef->version();
1029
1030 propertyFlags->setType(QQmlPropertyData::Flags::QObjectDerivedType);
1031 } else {
1032 int coreIndex = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).coreIndex();
1033 int valueTypeIndex
1034 = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).valueTypeIndex();
1035
1036 QQmlPropertyCache::ConstPtr targetCache = propertyCaches->at(targetObjectIndex);
1037 Q_ASSERT(targetCache);
1038
1039 const QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
1040 Q_ASSERT(targetProperty);
1041
1042 const QMetaType targetPropType = targetProperty->propType();
1043
1044 const auto populateWithPropertyData = [&](const QQmlPropertyData *property) {
1045 *type = property->propType();
1046 writable = property->isWritable();
1047 resettable = property->isResettable();
1048 notifiesViaBindable = property->notifiesViaBindable();
1049
1050 if (property->isVarProperty())
1051 propertyFlags->setType(QQmlPropertyData::Flags::QVariantType);
1052 else
1053 propertyFlags->copyPropertyTypeFlags(property->flags());
1054 };
1055
1056 // for deep aliases, valueTypeIndex is always set
1057 if (!QQmlMetaType::isValueType(targetPropType) && valueTypeIndex != -1) {
1058 // deep alias property
1059
1060 QQmlPropertyCache::ConstPtr typeCache
1061 = QQmlMetaType::propertyCacheForType(targetPropType);
1062
1063 if (!typeCache) {
1064 // See if it's a half-resolved composite type
1065 if (const QV4::ResolvedTypeReference *typeRef
1066 = objectContainer->resolvedType(targetPropType)) {
1067 typeCache = typeRef->typePropertyCache();
1068 }
1069 }
1070
1071 const QQmlPropertyData *typeProperty = typeCache
1072 ? typeCache->property(valueTypeIndex)
1073 : nullptr;
1074 if (typeProperty == nullptr) {
1075 return qQmlCompileError(
1076 alias.referenceLocation(),
1077 QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
1078 }
1079 populateWithPropertyData(typeProperty);
1080 } else {
1081 // value type or primitive type or enum
1082 populateWithPropertyData(targetProperty);
1083
1084 if (valueTypeIndex != -1) {
1085 const QMetaObject *valueTypeMetaObject
1086 = QQmlMetaType::metaObjectForValueType(*type);
1087 const QMetaProperty valueTypeMetaProperty
1088 = valueTypeMetaObject->property(valueTypeIndex);
1089 *type = valueTypeMetaProperty.metaType();
1090
1091 // We can only write or reset the value type property if we can write
1092 // the value type itself.
1093 resettable = writable && valueTypeMetaProperty.isResettable();
1094 writable = writable && valueTypeMetaProperty.isWritable();
1095
1096 // Do not update notifiesViaBindable. The core property counts for notifications.
1097 propertyFlags->setIsDeepAlias(true);
1098 }
1099 }
1100 }
1101
1102 propertyFlags->setIsWritable(writable && !alias.isReadOnly());
1103 propertyFlags->setIsResettable(resettable);
1104 propertyFlags->setIsBindable(notifiesViaBindable);
1105 return QQmlError();
1106}
1107
1108template <typename ObjectContainer>
1110 const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex,
1111 int aliasIndex, int encodedMetaPropertyIndex, int resolvedTargetObjectId)
1112{
1113 const CompiledObject &object = *objectContainer->objectAt(objectIndex);
1114
1115 Q_ASSERT(object.aliasCount() > aliasIndex);
1116 QMetaType type;
1117 QTypeRevision version = QTypeRevision::zero();
1118 QQmlPropertyData::Flags propertyFlags;
1119 QQmlError error = propertyDataForAlias(
1120 component, alias, &type, &version, &propertyFlags, encodedMetaPropertyIndex,
1121 resolvedTargetObjectId);
1122 if (error.isValid())
1123 return error;
1124
1125 const QString propertyName = objectContainer->stringAt(alias.nameIndex());
1126
1127 const QQmlPropertyCache::Ptr propertyCache = propertyCaches->ownAt(objectIndex);
1128 Q_ASSERT(propertyCache);
1129
1130 const int effectiveSignalIndex
1131 = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.size();
1132 const int effectivePropertyIndex
1133 = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.size();
1134
1135 if (object.hasAliasAsDefaultProperty() && aliasIndex == object.indexOfDefaultPropertyOrAlias)
1136 propertyCache->_defaultPropertyName = propertyName;
1137
1138 const auto &appendResult =
1139 propertyCache->appendAlias(propertyName, propertyFlags, effectivePropertyIndex, type,
1140 version, effectiveSignalIndex, encodedMetaPropertyIndex,
1141 resolvedTargetObjectId);
1142 if (!appendResult) {
1143 return qQmlCompileError(
1144 alias.location(), QQmlPropertyCacheCreatorBase::explain(appendResult.error()));
1145 }
1146 return QQmlError();
1147}
1148
1149QT_END_NAMESPACE
1150
1151#endif // QQMLPROPERTYCACHECREATOR_P_H
QQmlPropertyCacheAliasCreator(QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer)
QQmlError appendAliasToPropertyCache(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex, int aliasIndex, int encodedMetaPropertyIndex, int resolvedTargetObjectId)
ObjectContainer::CompiledObject CompiledObject
IncrementalResult buildMetaObjectsIncrementally()
typename ObjectContainer::CompiledObject CompiledObject
QString stringAt(int index) const
QQmlPropertyCacheCreator(QQmlPropertyCacheVector *propertyCaches, QQmlPendingGroupPropertyBindings *pendingGroupPropertyBindings, QQmlTypeLoader *typeLoader, const ObjectContainer *objectContainer, const QQmlImports *imports, const QByteArray &typeClassName)
QQmlBindingInstantiationContext m_context
QQmlPendingGroupPropertyBindings * pendingGroupPropertyBindings
q23::expected< QQmlPropertyCache::Ptr, QQmlError > tryDeriveCacheFrom(const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache, QByteArray dynamicClassName=QByteArray()) const
QQmlError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache)
std::optional< QMetaType > metaTypeForParameter(const QV4::CompiledData::ParameterType &param, QString *customTypeName=nullptr) const
typename std::remove_reference< decltype(*(std::declval< CompiledObject >().inlineComponentsBegin()))>::type InlineComponent
const ObjectContainer *const objectContainer
std::vector< icutils::Node >::reverse_iterator nodeIt
QQmlError buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context, VMEMetaObjectIsRequired isVMERequired)
q23::expected< QQmlPropertyData, QQmlError > tryCreateQQmlPropertyData(const QV4::CompiledData::Property &propertyIR, int coreIndex, int notifyIndex) const
std::vector< InlineComponent > allICs
QQmlPropertyCacheVector * propertyCaches
std::vector< icutils::Node > nodesSorted
QQmlPropertyCache::ConstPtr propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQIORing)
auto processUrlForClassName(const QUrl &url, BaseNameHandler &&baseNameHandler, FailHandler &&failHandler)
QQmlError qQmlCompileError(const QV4::CompiledData::Location &location, const QString &description)
int objectForId(const ObjectContainer *objectContainer, const CompiledObject &component, int id)
QQmlBindingInstantiationContext(int referencingObjectIndex, const QV4::CompiledData::Binding *instantiatingBinding, const QString &instantiatingPropertyName, const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache)
QQmlPropertyCache::ConstPtr referencingObjectPropertyCache
const QV4::CompiledData::Binding * instantiatingBinding
const QQmlPropertyData * instantiatingProperty
QQmlPropertyCache::ConstPtr instantiatingPropertyCache() const
void resolveMissingPropertyCaches(QQmlPropertyCacheVector *propertyCaches) const
static QString explain(OverrideSemantics::Status reason)
static bool canCreateClassNameTypeByUrl(const QUrl &url)
static std::optional< QMetaType > metaTypeForPropertyType(QV4::CompiledData::CommonType type)
static QV4::CompiledData::CommonType propertyTypeForMetaType(QMetaType metaType)
static QByteArray createClassNameForInlineComponent(const QUrl &url)
static std::optional< QMetaType > listTypeForPropertyType(QV4::CompiledData::CommonType type)
static QByteArray createClassNameTypeByUrl(const QUrl &url)