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