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