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 mo = m_compilationUnit->rootPropertyCache()->firstCppMetaObject();
33 m_isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
34}
35
36/*!
37Returns the property cache, if one alread exists. The cache is not referenced.
38*/
39QQmlPropertyCache::ConstPtr ResolvedTypeReference::propertyCache() const
40{
41 if (m_type.isValid())
42 return m_typePropertyCache;
43 else
44 return m_compilationUnit->rootPropertyCache();
45}
46
47/*!
48Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
49*/
50QQmlPropertyCache::ConstPtr ResolvedTypeReference::createPropertyCache()
51{
52 if (m_typePropertyCache) {
53 return m_typePropertyCache;
54 } else if (m_type.isValid()) {
55 const QMetaObject *metaObject = m_type.metaObject();
56 if (!metaObject) // value type of non-Q_GADGET base with extension
57 metaObject = m_type.extensionMetaObject();
58 if (metaObject)
59 m_typePropertyCache = QQmlMetaType::propertyCache(metaObject, version: m_version);
60 return m_typePropertyCache;
61 } else {
62 Q_ASSERT(m_compilationUnit);
63 return m_compilationUnit->rootPropertyCache();
64 }
65}
66
67bool ResolvedTypeReference::addToHash(
68 QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums)
69{
70 if (m_type.isInlineComponentType()) {
71
72 // A reference to an inline component in the same file will have
73 // - no compilation unit since we cannot resolve the compilation unit before it's built.
74 // - a property cache since we've assigned one in buildMetaObjectsIncrementally().
75 // - a QQmlType that says it's an inline component.
76 // We don't have to add such a thing to the hash since if it changes, the QML document
77 // itself changes, leading to a new timestamp, which is checked before the checksum.
78 if (!m_compilationUnit)
79 return !m_typePropertyCache.isNull();
80
81 } else if (m_type.isValid()) {
82 bool ok = false;
83 if (QQmlPropertyCache::ConstPtr propertyCache = createPropertyCache())
84 hash->addData(data: propertyCache->checksum(checksums, ok: &ok));
85 else
86 Q_ASSERT(m_type.module() == QLatin1String("QML")); // a builtin without metaobject
87 return ok;
88 }
89 if (!m_compilationUnit)
90 return false;
91 hash->addData(data: {m_compilationUnit->data->md5Checksum,
92 sizeof(m_compilationUnit->data->md5Checksum)});
93 return true;
94}
95
96} // namespace QV4
97
98QT_END_NAMESPACE
99

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