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 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 QMetaType();
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 QMetaType {};
105 }
106
107 static 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 QMetaType();
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 QMetaType {};
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 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 QMetaType type = metaTypeForParameter(param->type, &customTypeName);
498 if (!type.isValid())
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 QMetaType type = metaTypeForParameter(formal->type);
572 if (!type.isValid())
573 type = QMetaType::fromType<QVariant>();
574 parameterTypes << type;
575 }
576
577 QMetaType returnType = metaTypeForParameter(function->returnType);
578 if (!returnType.isValid())
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 QMetaType();
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 // common type
880 propertyType.metaType = propertyIR.isList()
881 ? listTypeForPropertyType(propertyType.commonType)
882 : metaTypeForPropertyType(propertyType.commonType);
883 return propertyType;
884 }
885
886 // needs to be resolved
887 // can be extracted and passed to tryResolvePropertyType as a function object to simplify
888 // dependency injection (imports / typeLoader)
889 Q_ASSERT(!propertyIR.isCommonType());
890 QQmlType qmltype;
891 bool selfReference = false;
892 QList<QQmlError> errors;
893 const QString typeName = stringAt(propertyIR.commonTypeOrTypeNameIndex());
894 if (!imports->resolveType(typeLoader, typeName, &qmltype, nullptr, nullptr, &errors,
895 QQmlType::AnyRegistrationType, &selfReference)) {
896 Q_ASSERT(!errors.isEmpty());
897
898 if (typeName == "list"_L1 && errors[0].description() == "is not a type"_L1) {
899 errors[0].setDescription(errors[0].description().append(
900 ". It requires an element type argument (eg. list<int>)"_L1));
901 }
902
903 return q23::make_unexpected(
904 qQmlCompileError(propertyIR.location, typeName + u' ' + errors[0].description()));
905 }
906
907 Q_ASSERT(qmltype.isValid());
908
909 propertyType.metaType = propertyIR.isList() ? qmltype.qListTypeId() : qmltype.typeId();
910
911 if (!qmltype.isComposite() && !qmltype.isInlineComponentType())
912 propertyType.revision = qmltype.version();
913
914 return propertyType;
915}
916
917template <typename ObjectContainer>
918inline QQmlPropertyData::Flags QQmlPropertyCacheCreator<ObjectContainer>::propertyDataFlags(
919 const QV4::CompiledData::Property &propertyIR, const PropertyType &resolvedPropertyType)
920{
921 QQmlPropertyData::Flags flags;
922
923 // set type flag
924 if (propertyIR.isList()) {
925 flags.setType(QQmlPropertyData::Flags::QListType);
926 } else if (resolvedPropertyType.commonType == QV4::CompiledData::CommonType::Var) {
927 flags.setType(QQmlPropertyData::Flags::VarPropertyType);
928 } else if (resolvedPropertyType.metaType.flags().testFlag(QMetaType::PointerToQObject)) {
929 flags.setType(QQmlPropertyData::Flags::QObjectDerivedType);
930 }
931
932 // set attributes
933 if (!propertyIR.isReadOnly()
934 && !resolvedPropertyType.metaType.flags().testFlag(QMetaType::IsQmlList))
935 flags.setIsWritable(true);
936 if (propertyIR.isFinal())
937 flags.setIsFinal(true);
938 if (propertyIR.isVirtual())
939 flags.setIsVirtual(true);
940 if (propertyIR.isOverride())
941 flags.setDoesOverride(true);
942
943 return flags;
944}
945
946template <typename ObjectContainer, typename CompiledObject>
947int objectForId(const ObjectContainer *objectContainer, const CompiledObject &component, int id)
948{
949 for (quint32 i = 0, count = component.namedObjectsInComponentCount(); i < count; ++i) {
950 const int candidateIndex = component.namedObjectsInComponentTable()[i];
951 const CompiledObject &candidate = *objectContainer->objectAt(candidateIndex);
952 if (candidate.objectId() == id)
953 return candidateIndex;
954 }
955 return -1;
956}
957
958template <typename ObjectContainer>
960{
961public:
962 typedef typename ObjectContainer::CompiledObject CompiledObject;
963
965 QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer);
967 const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex,
968 int aliasIndex, int encodedMetaPropertyIndex, int resolvedTargetObjectId);
969
970private:
971 QQmlError propertyDataForAlias(
972 const CompiledObject &component, const QV4::CompiledData::Alias &alias, QMetaType *type,
973 QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags,
974 int targetPropertyIndex, int resolvedTargetObjectId);
975
976 QQmlPropertyCacheVector *propertyCaches;
977 const ObjectContainer *objectContainer;
978};
979
980template <typename ObjectContainer>
982 QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer)
984 , objectContainer(objectContainer)
985{
986}
987
988template <typename ObjectContainer>
989inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(
990 const CompiledObject &component, const QV4::CompiledData::Alias &alias, QMetaType *type,
991 QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags,
992 int targetPropertyIndex, int resolvedTargetObjectId)
993{
994 *type = QMetaType();
995 bool writable = false;
996 bool resettable = false;
997 bool notifiesViaBindable = false;
998
999 propertyFlags->setIsAlias(true);
1000
1001 const int targetObjectIndex = objectForId(objectContainer, component, resolvedTargetObjectId);
1002 Q_ASSERT(targetObjectIndex >= 0);
1003 const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
1004
1005 if (targetPropertyIndex == -1) {
1006 Q_ASSERT(objectContainer->stringAt(alias.propertyNameIndex()).isEmpty());
1007 auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
1008 if (!typeRef) {
1009 // Can be caused by the alias target not being a valid id or property. E.g.:
1010 // property alias dataValue: dataVal
1011 // invalidAliasComponent { id: dataVal }
1012 return qQmlCompileError(targetObject.location,
1013 QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
1014 }
1015
1016 const auto referencedType = typeRef->type();
1017 Q_ASSERT(referencedType.isValid());
1018 *type = referencedType.typeId();
1019 if (!type->isValid() && referencedType.isInlineComponentType()) {
1020 *type = objectContainer->qmlTypeForComponent(referencedType.elementName()).typeId();
1021 Q_ASSERT(type->isValid());
1022 }
1023
1024 *version = typeRef->version();
1025
1026 propertyFlags->setType(QQmlPropertyData::Flags::QObjectDerivedType);
1027 } else {
1028 int coreIndex = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).coreIndex();
1029 int valueTypeIndex
1030 = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).valueTypeIndex();
1031
1032 QQmlPropertyCache::ConstPtr targetCache = propertyCaches->at(targetObjectIndex);
1033 Q_ASSERT(targetCache);
1034
1035 const QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
1036 Q_ASSERT(targetProperty);
1037
1038 const QMetaType targetPropType = targetProperty->propType();
1039
1040 const auto populateWithPropertyData = [&](const QQmlPropertyData *property) {
1041 *type = property->propType();
1042 writable = property->isWritable();
1043 resettable = property->isResettable();
1044 notifiesViaBindable = property->notifiesViaBindable();
1045
1046 if (property->isVarProperty())
1047 propertyFlags->setType(QQmlPropertyData::Flags::QVariantType);
1048 else
1049 propertyFlags->copyPropertyTypeFlags(property->flags());
1050 };
1051
1052 // for deep aliases, valueTypeIndex is always set
1053 if (!QQmlMetaType::isValueType(targetPropType) && valueTypeIndex != -1) {
1054 // deep alias property
1055
1056 QQmlPropertyCache::ConstPtr typeCache
1057 = QQmlMetaType::propertyCacheForType(targetPropType);
1058
1059 if (!typeCache) {
1060 // See if it's a half-resolved composite type
1061 if (const QV4::ResolvedTypeReference *typeRef
1062 = objectContainer->resolvedType(targetPropType)) {
1063 typeCache = typeRef->typePropertyCache();
1064 }
1065 }
1066
1067 const QQmlPropertyData *typeProperty = typeCache
1068 ? typeCache->property(valueTypeIndex)
1069 : nullptr;
1070 if (typeProperty == nullptr) {
1071 return qQmlCompileError(
1072 alias.referenceLocation(),
1073 QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
1074 }
1075 populateWithPropertyData(typeProperty);
1076 } else {
1077 // value type or primitive type or enum
1078 populateWithPropertyData(targetProperty);
1079
1080 if (valueTypeIndex != -1) {
1081 const QMetaObject *valueTypeMetaObject
1082 = QQmlMetaType::metaObjectForValueType(*type);
1083 const QMetaProperty valueTypeMetaProperty
1084 = valueTypeMetaObject->property(valueTypeIndex);
1085 *type = valueTypeMetaProperty.metaType();
1086
1087 // We can only write or reset the value type property if we can write
1088 // the value type itself.
1089 resettable = writable && valueTypeMetaProperty.isResettable();
1090 writable = writable && valueTypeMetaProperty.isWritable();
1091
1092 // Do not update notifiesViaBindable. The core property counts for notifications.
1093 propertyFlags->setIsDeepAlias(true);
1094 }
1095 }
1096 }
1097
1098 propertyFlags->setIsWritable(writable && !alias.isReadOnly());
1099 propertyFlags->setIsResettable(resettable);
1100 propertyFlags->setIsBindable(notifiesViaBindable);
1101 return QQmlError();
1102}
1103
1104template <typename ObjectContainer>
1106 const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex,
1107 int aliasIndex, int encodedMetaPropertyIndex, int resolvedTargetObjectId)
1108{
1109 const CompiledObject &object = *objectContainer->objectAt(objectIndex);
1110
1111 Q_ASSERT(object.aliasCount() > aliasIndex);
1112 QMetaType type;
1113 QTypeRevision version = QTypeRevision::zero();
1114 QQmlPropertyData::Flags propertyFlags;
1115 QQmlError error = propertyDataForAlias(
1116 component, alias, &type, &version, &propertyFlags, encodedMetaPropertyIndex,
1117 resolvedTargetObjectId);
1118 if (error.isValid())
1119 return error;
1120
1121 const QString propertyName = objectContainer->stringAt(alias.nameIndex());
1122
1123 const QQmlPropertyCache::Ptr propertyCache = propertyCaches->ownAt(objectIndex);
1124 Q_ASSERT(propertyCache);
1125
1126 const int effectiveSignalIndex
1127 = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.size();
1128 const int effectivePropertyIndex
1129 = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.size();
1130
1131 if (object.hasAliasAsDefaultProperty() && aliasIndex == object.indexOfDefaultPropertyOrAlias)
1132 propertyCache->_defaultPropertyName = propertyName;
1133
1134 const auto &appendResult =
1135 propertyCache->appendAlias(propertyName, propertyFlags, effectivePropertyIndex, type,
1136 version, effectiveSignalIndex, encodedMetaPropertyIndex,
1137 resolvedTargetObjectId);
1138 if (!appendResult) {
1139 return qQmlCompileError(
1140 alias.location(), QQmlPropertyCacheCreatorBase::explain(appendResult.error()));
1141 }
1142 return QQmlError();
1143}
1144
1145QT_END_NAMESPACE
1146
1147#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)
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 QV4::CompiledData::CommonType propertyTypeForMetaType(QMetaType metaType)
static QByteArray createClassNameForInlineComponent(const QUrl &url)
static QMetaType listTypeForPropertyType(QV4::CompiledData::CommonType type)
static QByteArray createClassNameTypeByUrl(const QUrl &url)
static QMetaType metaTypeForPropertyType(QV4::CompiledData::CommonType type)