1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qv4resolvedtypereference_p.h"
5
6#include <QtQml/private/qqmlengine_p.h>
7#include <QtQml/qqmlpropertymap.h>
8#include <QtCore/qcryptographichash.h>
9
10QT_BEGIN_NAMESPACE
11
12namespace QV4 {
13
14template <typename T>
15bool qtTypeInherits(const QMetaObject *mo) {
16 while (mo) {
17 if (mo == &T::staticMetaObject)
18 return true;
19 mo = mo->superClass();
20 }
21 return false;
22}
23
24void ResolvedTypeReference::doDynamicTypeCheck()
25{
26 const QMetaObject *mo = nullptr;
27 if (m_typePropertyCache) {
28 mo = m_typePropertyCache->firstCppMetaObject();
29 } else if (m_type.isValid()) {
30 mo = m_type.metaObject();
31 } else if (m_compilationUnit) {
32 if (const auto cache = m_compilationUnit->rootPropertyCache())
33 mo = cache->firstCppMetaObject();
34 }
35 m_isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
36}
37
38/*!
39Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
40*/
41QQmlPropertyCache::ConstPtr ResolvedTypeReference::createPropertyCache()
42{
43 if (m_typePropertyCache) {
44 return m_typePropertyCache;
45 } else if (m_type.isValid()) {
46 const QMetaObject *metaObject = m_type.metaObject();
47 if (!metaObject) // value type of non-Q_GADGET base with extension
48 metaObject = m_type.extensionMetaObject();
49 if (metaObject)
50 m_typePropertyCache = QQmlMetaType::propertyCache(metaObject, version: m_version);
51 return m_typePropertyCache;
52 } else {
53 Q_ASSERT(m_compilationUnit);
54 return m_compilationUnit->rootPropertyCache();
55 }
56}
57
58bool ResolvedTypeReference::addToHash(
59 QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums)
60{
61 if (m_type.isInlineComponentType()) {
62
63 // A reference to an inline component in the same file will have
64 // - no compilation unit since we cannot resolve the compilation unit before it's built.
65 // - a property cache since we've assigned one in buildMetaObjectsIncrementally().
66 // - a QQmlType that says it's an inline component.
67 // We don't have to add such a thing to the hash since if it changes, the QML document
68 // itself changes, leading to a new timestamp, which is checked before the checksum.
69 if (!m_compilationUnit)
70 return !m_typePropertyCache.isNull();
71
72 } else if (m_type.isValid()) {
73 bool ok = false;
74 if (QQmlPropertyCache::ConstPtr propertyCache = createPropertyCache())
75 hash->addData(data: propertyCache->checksum(checksums, ok: &ok));
76 else
77 Q_ASSERT(m_type.module() == QLatin1String("QML")); // a builtin without metaobject
78 return ok;
79 }
80 if (!m_compilationUnit)
81 return false;
82 hash->addData(data: {m_compilationUnit->unitData()->md5Checksum,
83 sizeof(m_compilationUnit->unitData()->md5Checksum)});
84 return true;
85}
86
87} // namespace QV4
88
89QT_END_NAMESPACE
90

source code of qtdeclarative/src/qml/jsruntime/qv4resolvedtypereference.cpp