aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4resolvedtypereference.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4resolvedtypereference.cpp')
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference.cpp98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4resolvedtypereference.cpp b/src/qml/jsruntime/qv4resolvedtypereference.cpp
new file mode 100644
index 0000000000..7dcf2cd0b8
--- /dev/null
+++ b/src/qml/jsruntime/qv4resolvedtypereference.cpp
@@ -0,0 +1,98 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qv4resolvedtypereference_p.h"
+
+#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/qqmlpropertymap.h>
+#include <QtCore/qcryptographichash.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+template <typename T>
+bool qtTypeInherits(const QMetaObject *mo) {
+ while (mo) {
+ if (mo == &T::staticMetaObject)
+ return true;
+ mo = mo->superClass();
+ }
+ return false;
+}
+
+void ResolvedTypeReference::doDynamicTypeCheck()
+{
+ const QMetaObject *mo = nullptr;
+ if (m_typePropertyCache)
+ mo = m_typePropertyCache->firstCppMetaObject();
+ else if (m_type.isValid())
+ mo = m_type.metaObject();
+ else if (m_compilationUnit)
+ mo = m_compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ m_isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
+}
+
+/*!
+Returns the property cache, if one alread exists. The cache is not referenced.
+*/
+QQmlPropertyCache::ConstPtr ResolvedTypeReference::propertyCache() const
+{
+ if (m_type.isValid())
+ return m_typePropertyCache;
+ else
+ return m_compilationUnit->rootPropertyCache();
+}
+
+/*!
+Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
+*/
+QQmlPropertyCache::ConstPtr ResolvedTypeReference::createPropertyCache()
+{
+ if (m_typePropertyCache) {
+ return m_typePropertyCache;
+ } else if (m_type.isValid()) {
+ const QMetaObject *metaObject = m_type.metaObject();
+ if (!metaObject) // value type of non-Q_GADGET base with extension
+ metaObject = m_type.extensionMetaObject();
+ if (metaObject)
+ m_typePropertyCache = QQmlMetaType::propertyCache(metaObject, m_version);
+ return m_typePropertyCache;
+ } else {
+ Q_ASSERT(m_compilationUnit);
+ return m_compilationUnit->rootPropertyCache();
+ }
+}
+
+bool ResolvedTypeReference::addToHash(
+ QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums)
+{
+ if (m_type.isInlineComponentType()) {
+
+ // A reference to an inline component in the same file will have
+ // - no compilation unit since we cannot resolve the compilation unit before it's built.
+ // - a property cache since we've assigned one in buildMetaObjectsIncrementally().
+ // - a QQmlType that says it's an inline component.
+ // We don't have to add such a thing to the hash since if it changes, the QML document
+ // itself changes, leading to a new timestamp, which is checked before the checksum.
+ if (!m_compilationUnit)
+ return !m_typePropertyCache.isNull();
+
+ } else if (m_type.isValid()) {
+ bool ok = false;
+ if (QQmlPropertyCache::ConstPtr propertyCache = createPropertyCache())
+ hash->addData(propertyCache->checksum(checksums, &ok));
+ else
+ Q_ASSERT(m_type.module() == QLatin1String("QML")); // a builtin without metaobject
+ return ok;
+ }
+ if (!m_compilationUnit)
+ return false;
+ hash->addData({m_compilationUnit->unitData()->md5Checksum,
+ sizeof(m_compilationUnit->unitData()->md5Checksum)});
+ return true;
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE