aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-03-24 18:21:15 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-03-25 10:51:47 +0100
commit3f0c9122c5971090d0256bda4e9fb53da4a76ea0 (patch)
treeca51902e6fb457e61da574d55ebee72d7a28ca7a
parentd9eeab6e2c699761115d9acbca292c16762eb8f3 (diff)
Encapsulate QV4::ResolvedTypeReference
It's used all over the place. We need a proper interface. Change-Id: Iebe254ef3bf35503bf3fdd3639979a5db2b3449e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qml/.prev_CMakeLists.txt1
-rw-r--r--src/qml/CMakeLists.txt1
-rw-r--r--src/qml/inlinecomponentutils_p.h10
-rw-r--r--src/qml/jsruntime/jsruntime.pri6
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp115
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h25
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference.cpp115
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference_p.h113
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp22
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h22
-rw-r--r--src/qml/qml/qqmlpropertyvalidator.cpp21
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp23
-rw-r--r--src/qml/qml/qqmltypedata.cpp34
-rw-r--r--src/qmltest/quicktest.cpp12
14 files changed, 338 insertions, 182 deletions
diff --git a/src/qml/.prev_CMakeLists.txt b/src/qml/.prev_CMakeLists.txt
index 9528b3068a..0f25337573 100644
--- a/src/qml/.prev_CMakeLists.txt
+++ b/src/qml/.prev_CMakeLists.txt
@@ -135,6 +135,7 @@ qt_add_module(Qml
jsruntime/qv4reflect.cpp jsruntime/qv4reflect_p.h
jsruntime/qv4regexp.cpp jsruntime/qv4regexp_p.h
jsruntime/qv4regexpobject.cpp jsruntime/qv4regexpobject_p.h
+ jsruntime/qv4resolvedtypereference.cpp jsruntime/qv4resolvedtypereference_p.h
jsruntime/qv4runtime.cpp jsruntime/qv4runtime_p.h
jsruntime/qv4runtimeapi_p.h
jsruntime/qv4runtimecodegen.cpp jsruntime/qv4runtimecodegen_p.h
diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt
index 3a6f75a58b..f6ab914b9a 100644
--- a/src/qml/CMakeLists.txt
+++ b/src/qml/CMakeLists.txt
@@ -135,6 +135,7 @@ qt_add_module(Qml
jsruntime/qv4reflect.cpp jsruntime/qv4reflect_p.h
jsruntime/qv4regexp.cpp jsruntime/qv4regexp_p.h
jsruntime/qv4regexpobject.cpp jsruntime/qv4regexpobject_p.h
+ jsruntime/qv4resolvedtypereference.cpp jsruntime/qv4resolvedtypereference_p.h
jsruntime/qv4runtime.cpp jsruntime/qv4runtime_p.h
jsruntime/qv4runtimeapi_p.h
jsruntime/qv4runtimecodegen.cpp jsruntime/qv4runtimecodegen_p.h
diff --git a/src/qml/inlinecomponentutils_p.h b/src/qml/inlinecomponentutils_p.h
index 99b28349cd..ae436d53b0 100644
--- a/src/qml/inlinecomponentutils_p.h
+++ b/src/qml/inlinecomponentutils_p.h
@@ -51,7 +51,7 @@
//
#include <private/qv4compileddata_p.h>
-#include <private/qv4executablecompilationunit_p.h>
+#include <private/qv4resolvedtypereference_p.h>
namespace icutils {
struct Node {
@@ -88,10 +88,12 @@ void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer, Adja
const CompiledObject *obj = objectContainer->objectAt(ic.objectIndex);
QV4::ResolvedTypeReference *currentICTypeRef = objectContainer->resolvedType(ic.nameIndex);
auto createEdgeFromTypeRef = [&](QV4::ResolvedTypeReference *targetTypeRef) {
- if (targetTypeRef && targetTypeRef->type.isInlineComponentType()) {
- if (targetTypeRef->type.containingType() == currentICTypeRef->type.containingType()) {
+ if (targetTypeRef) {
+ const auto targetType = targetTypeRef->type();
+ if (targetType.isInlineComponentType()
+ && targetType.containingType() == currentICTypeRef->type().containingType()) {
auto icIt = std::find_if(allICs.cbegin(), allICs.cend(), [&](const QV4::CompiledData::InlineComponent &icSearched){
- return int(icSearched.objectIndex) == targetTypeRef->type.inlineComponentObjectId();
+ return int(icSearched.objectIndex) == targetType.inlineComponentObjectId();
});
Q_ASSERT(icIt != allICs.cend());
Node& target = nodes[i];
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 32acc6affc..0c84886da4 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -62,7 +62,8 @@ SOURCES += \
$$PWD/qv4value.cpp \
$$PWD/qv4compilationunitmapper.cpp \
$$PWD/qv4executablecompilationunit.cpp \
- $$PWD/qv4executableallocator.cpp
+ $$PWD/qv4executableallocator.cpp \
+ $$PWD/qv4resolvedtypereference.cpp
qtConfig(qml-debug): SOURCES += $$PWD/qv4profiling.cpp
@@ -138,7 +139,8 @@ HEADERS += \
$$PWD/qv4compilationunitmapper_p.h \
$$PWD/qv4executablecompilationunit_p.h \
$$PWD/qv4functiontable_p.h \
- $$PWD/qv4runtimeapi_p.h
+ $$PWD/qv4runtimeapi_p.h \
+ $$PWD/qv4resolvedtypereference_p.h
qtConfig(qml-sequence-object) {
HEADERS += \
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index fb19ac4b66..7f4e35e815 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -54,6 +54,7 @@
#include <private/qml_compile_hash_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/inlinecomponentutils_p.h>
+#include <private/qv4resolvedtypereference_p.h>
#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlpropertymap.h>
@@ -406,12 +407,13 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
- if (typeRef->compilationUnit) {
- metaTypeId = typeRef->compilationUnit->metaTypeId;
- listMetaTypeId = typeRef->compilationUnit->listMetaTypeId;
+ if (const auto compilationUnit = typeRef->compilationUnit()) {
+ metaTypeId = compilationUnit->metaTypeId;
+ listMetaTypeId = compilationUnit->listMetaTypeId;
} else {
- metaTypeId = typeRef->type.typeId();
- listMetaTypeId = typeRef->type.qListTypeId();
+ const auto type = typeRef->type();
+ metaTypeId = type.typeId();
+ listMetaTypeId = type.qListTypeId();
}
}
@@ -449,21 +451,21 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
inlineComponentData[lastICRoot].totalBindingCount += obj->nBindings;
if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid() && typeRef->type.parserStatusCast() != -1)
+ const auto type = typeRef->type();
+ if (type.isValid() && type.parserStatusCast() != -1)
++inlineComponentData[lastICRoot].totalParserStatusCount;
++inlineComponentData[lastICRoot].totalObjectCount;
- if (typeRef->compilationUnit) {
+ if (const auto compilationUnit = typeRef->compilationUnit()) {
// if the type is an inline component type, we have to extract the information from it
// This requires that inline components are visited in the correct order
- auto icRoot = typeRef->compilationUnit->icRoot;
- if (typeRef->type.isInlineComponentType()) {
- icRoot = typeRef->type.inlineComponentId();
- }
- QScopedValueRollback<int> rollback {typeRef->compilationUnit->icRoot, icRoot};
- inlineComponentData[lastICRoot].totalBindingCount += typeRef->compilationUnit->totalBindingsCount();
- inlineComponentData[lastICRoot].totalParserStatusCount += typeRef->compilationUnit->totalParserStatusCount();
- inlineComponentData[lastICRoot].totalObjectCount += typeRef->compilationUnit->totalObjectCount();
+ auto icRoot = compilationUnit->icRoot;
+ if (type.isInlineComponentType())
+ icRoot = type.inlineComponentId();
+ QScopedValueRollback<int> rollback {compilationUnit->icRoot, icRoot};
+ inlineComponentData[lastICRoot].totalBindingCount += compilationUnit->totalBindingsCount();
+ inlineComponentData[lastICRoot].totalParserStatusCount += compilationUnit->totalParserStatusCount();
+ inlineComponentData[lastICRoot].totalObjectCount += compilationUnit->totalObjectCount();
}
}
}
@@ -478,18 +480,18 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
}
bindingCount += obj->nBindings;
if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid() && typeRef->type.parserStatusCast() != -1)
+ const auto type = typeRef->type();
+ if (type.isValid() && type.parserStatusCast() != -1)
++parserStatusCount;
++objectCount;
- if (typeRef->compilationUnit) {
- auto icRoot = typeRef->compilationUnit->icRoot;
- if (typeRef->type.isInlineComponentType()) {
- icRoot = typeRef->type.inlineComponentId();
- }
- QScopedValueRollback<int> rollback {typeRef->compilationUnit->icRoot, icRoot};
- bindingCount += typeRef->compilationUnit->totalBindingsCount();
- parserStatusCount += typeRef->compilationUnit->totalParserStatusCount();
- objectCount += typeRef->compilationUnit->totalObjectCount();
+ if (const auto compilationUnit = typeRef->compilationUnit()) {
+ auto icRoot = compilationUnit->icRoot;
+ if (type.isInlineComponentType())
+ icRoot = type.inlineComponentId();
+ QScopedValueRollback<int> rollback {compilationUnit->icRoot, icRoot};
+ bindingCount += compilationUnit->totalBindingsCount();
+ parserStatusCount += compilationUnit->totalParserStatusCount();
+ objectCount += compilationUnit->totalObjectCount();
}
}
}
@@ -798,69 +800,6 @@ bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorSt
});
}
-/*!
-Returns the property cache, if one alread exists. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
-{
- if (type.isValid())
- return typePropertyCache;
- else
- return compilationUnit->rootPropertyCache();
-}
-
-/*!
-Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
-{
- if (typePropertyCache) {
- return typePropertyCache;
- } else if (type.isValid()) {
- typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), version);
- return typePropertyCache;
- } else {
- Q_ASSERT(compilationUnit);
- return compilationUnit->rootPropertyCache();
- }
-}
-
-bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
-{
- if (type.isValid() && !type.isInlineComponentType()) {
- bool ok = false;
- hash->addData(createPropertyCache(engine)->checksum(&ok));
- return ok;
- }
- if (!compilationUnit)
- return false;
- hash->addData(compilationUnit->data->md5Checksum,
- sizeof(compilationUnit->data->md5Checksum));
- return true;
-}
-
-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 (typePropertyCache)
- mo = typePropertyCache->firstCppMetaObject();
- else if (type.isValid())
- mo = type.metaObject();
- else if (compilationUnit)
- mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
- isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
-}
-
bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
{
for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index a748e0a762..4af2d0ea93 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -90,7 +90,7 @@ namespace QV4 {
typedef QVector<QQmlPropertyData*> BindingPropertyData;
class CompilationUnitMapper;
-struct ResolvedTypeReference;
+class ResolvedTypeReference;
// map from name index
// While this could be a hash, a map is chosen here to provide a stable
// order, which is used to calculating a check-sum on dependent meta-objects.
@@ -323,29 +323,6 @@ private:
bool includeDefaultExport = true) const;
};
-struct ResolvedTypeReference
-{
- ResolvedTypeReference()
- : version(QTypeRevision::zero())
- , isFullyDynamicType(false)
- {}
-
- QQmlType type;
- QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
-
- QTypeRevision version;
- // Types such as QQmlPropertyMap can add properties dynamically at run-time and
- // therefore cannot have a property cache installed when instantiated.
- bool isFullyDynamicType;
-
- QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
- QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
-
- void doDynamicTypeCheck();
-};
-
IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
{
auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
diff --git a/src/qml/jsruntime/qv4resolvedtypereference.cpp b/src/qml/jsruntime/qv4resolvedtypereference.cpp
new file mode 100644
index 0000000000..d81f512391
--- /dev/null
+++ b/src/qml/jsruntime/qv4resolvedtypereference.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#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.
+*/
+QQmlRefPointer<QQmlPropertyCache> 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.
+*/
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
+{
+ if (m_typePropertyCache) {
+ return m_typePropertyCache;
+ } else if (m_type.isValid()) {
+ m_typePropertyCache = QQmlEnginePrivate::get(engine)->cache(m_type.metaObject(), m_version);
+ return m_typePropertyCache;
+ } else {
+ Q_ASSERT(m_compilationUnit);
+ return m_compilationUnit->rootPropertyCache();
+ }
+}
+
+bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
+{
+ if (m_type.isValid() && !m_type.isInlineComponentType()) {
+ bool ok = false;
+ hash->addData(createPropertyCache(engine)->checksum(&ok));
+ return ok;
+ }
+ if (!m_compilationUnit)
+ return false;
+ hash->addData(m_compilationUnit->data->md5Checksum,
+ sizeof(m_compilationUnit->data->md5Checksum));
+ return true;
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4resolvedtypereference_p.h b/src/qml/jsruntime/qv4resolvedtypereference_p.h
new file mode 100644
index 0000000000..88b77cf2a8
--- /dev/null
+++ b/src/qml/jsruntime/qv4resolvedtypereference_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4RESOLVEDTYPEREFERNCE_P_H
+#define QV4RESOLVEDTYPEREFERNCE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qtqmlglobal_p.h>
+#include <QtQml/private/qqmlrefcount_p.h>
+#include <QtQml/private/qqmlpropertycache_p.h>
+#include <QtQml/private/qqmltype_p.h>
+#include <QtQml/private/qv4executablecompilationunit_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCryptographicHash;
+namespace QV4 {
+
+class ResolvedTypeReference
+{
+ Q_DISABLE_COPY_MOVE(ResolvedTypeReference)
+public:
+ ResolvedTypeReference() = default;
+
+ QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
+ QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
+
+ void doDynamicTypeCheck();
+
+ QQmlType type() const { return m_type; }
+ void setType(QQmlType type) { m_type = std::move(type); }
+
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() { return m_compilationUnit; }
+ void setCompilationUnit(QQmlRefPointer<QV4::ExecutableCompilationUnit> unit)
+ {
+ m_compilationUnit = std::move(unit);
+ }
+
+ QQmlRefPointer<QQmlPropertyCache> typePropertyCache() const { return m_typePropertyCache; }
+ void setTypePropertyCache(QQmlRefPointer<QQmlPropertyCache> cache)
+ {
+ m_typePropertyCache = std::move(cache);
+ }
+
+ QTypeRevision version() const { return m_version; }
+ void setVersion(QTypeRevision version) { m_version = version; }
+
+ bool isFullyDynamicType() const { return m_isFullyDynamicType; }
+ void setFullyDynamicType(bool fullyDynamic) { m_isFullyDynamicType = fullyDynamic; }
+
+private:
+ QQmlType m_type;
+ QQmlRefPointer<QQmlPropertyCache> m_typePropertyCache;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> m_compilationUnit;
+
+ QTypeRevision m_version = QTypeRevision::zero();
+ // Types such as QQmlPropertyMap can add properties dynamically at run-time and
+ // therefore cannot have a property cache installed when instantiated.
+ bool m_isFullyDynamicType = false;
+};
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif // QV4RESOLVEDTYPEREFERNCE_P_H
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index d43b351a50..213e15e173 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -59,6 +59,7 @@
#include <private/qqmlsourcecoordinate_p.h>
#include <private/qjsvalue_p.h>
#include <private/qv4generatorobject_p.h>
+#include <private/qv4resolvedtypereference_p.h>
#include <QScopedValueRollback>
@@ -815,7 +816,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
Q_ASSERT(tr);
- QQmlType attachedType = tr->type;
+ QQmlType attachedType = tr->type();
if (!attachedType.isValid()) {
QQmlTypeNameCache::Result res = context->imports()->query(
stringAt(binding->propertyNameIndex));
@@ -1192,8 +1193,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
} else {
QV4::ResolvedTypeReference *typeRef = resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
- installPropertyCache = !typeRef->isFullyDynamicType;
- QQmlType type = typeRef->type;
+ installPropertyCache = !typeRef->isFullyDynamicType();
+ const QQmlType type = typeRef->type();
if (type.isValid() && !type.isInlineComponentType()) {
typeName = type.qmlTypeName();
@@ -1226,19 +1227,18 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
sharedState->allCreatedObjects.push(instance);
} else {
- Q_ASSERT(typeRef->compilationUnit);
- typeName = typeRef->compilationUnit->fileName();
+ const auto compilationUnit = typeRef->compilationUnit();
+ Q_ASSERT(compilationUnit);
+ typeName = compilationUnit->fileName();
// compilation unit is shared between root type and its inline component types
// so isSingleton errorneously returns true for inline components
- if (typeRef->compilationUnit->unitData()->isSingleton() && !type.isInlineComponentType())
- {
+ if (compilationUnit->unitData()->isSingleton() && !type.isInlineComponentType()) {
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
return nullptr;
}
-
if (!type.isInlineComponentType()) {
- QQmlObjectCreator subCreator(context, typeRef->compilationUnit, sharedState.data());
+ QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data());
instance = subCreator.create();
if (!instance) {
errors += subCreator.errors;
@@ -1246,8 +1246,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
}
} else {
int subObjectId = type.inlineComponentId();
- QScopedValueRollback<int> rollback {typeRef->compilationUnit->icRoot, subObjectId};
- QQmlObjectCreator subCreator(context, typeRef->compilationUnit, sharedState.data());
+ QScopedValueRollback<int> rollback {compilationUnit->icRoot, subObjectId};
+ QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data());
instance = subCreator.create(subObjectId, nullptr, nullptr, CreationFlags::InlineComponent);
if (!instance) {
errors += subCreator.errors;
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index ad125b47e7..961bbb4d19 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -197,7 +197,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects()
const auto &ic = allICs[nodeIt->index];
QV4::ResolvedTypeReference *typeRef = objectContainer->resolvedType(ic.nameIndex);
Q_ASSERT(propertyCaches->at(ic.objectIndex) == nullptr);
- Q_ASSERT(typeRef->typePropertyCache.isNull()); // not set yet
+ Q_ASSERT(typeRef->typePropertyCache().isNull()); // not set yet
QByteArray icTypeName { objectContainer->stringAt(ic.nameIndex).toUtf8() };
QScopedValueRollback<QByteArray> nameChange {typeClassName, icTypeName};
@@ -206,8 +206,8 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects()
if (diag.isValid()) {
return diag;
}
- typeRef->typePropertyCache = propertyCaches->at(ic.objectIndex);
- Q_ASSERT(!typeRef->typePropertyCache.isNull());
+ typeRef->setTypePropertyCache(propertyCaches->at(ic.objectIndex));
+ Q_ASSERT(!typeRef->typePropertyCache().isNull());
}
return buildMetaObjectRecursively(/*root object*/0, context, VMEMetaObjectIsRequired::Maybe);
@@ -226,7 +226,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur
|| obj->signalCount() != 0 || obj->functionCount() != 0 || obj->enumCount() != 0
|| (((obj->flags & QV4::CompiledData::Object::IsComponent)
|| (objectIndex == 0 && isAddressable(objectContainer->url())))
- && !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType);
+ && !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType());
if (!needVMEMetaObject) {
auto binding = obj->bindingsBegin();
@@ -305,10 +305,9 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
return context.instantiatingPropertyCache(enginePrivate);
} else if (obj->inheritedTypeNameIndex != 0) {
auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
- QQmlType qmltype = typeRef->type;
Q_ASSERT(typeRef);
- if (typeRef->isFullyDynamicType) {
+ if (typeRef->isFullyDynamicType()) {
if (obj->propertyCount() > 0 || obj->aliasCount() > 0) {
*error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new properties."));
return nullptr;
@@ -328,7 +327,7 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
auto *typeRef = objectContainer->resolvedType(
context.instantiatingBinding->propertyNameIndex);
Q_ASSERT(typeRef);
- QQmlType qmltype = typeRef->type;
+ QQmlType qmltype = typeRef->type();
if (!qmltype.isValid()) {
imports->resolveType(stringAt(context.instantiatingBinding->propertyNameIndex),
&qmltype, nullptr, nullptr, nullptr);
@@ -839,12 +838,13 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
}
- if (typeRef->type.isValid())
- *type = typeRef->type.typeId().id();
+ const auto referencedType = typeRef->type();
+ if (referencedType.isValid())
+ *type = referencedType.typeId().id();
else
- *type = typeRef->compilationUnit->metaTypeId.id();
+ *type = typeRef->compilationUnit()->metaTypeId.id();
- *version = typeRef->version;
+ *version = typeRef->version();
propertyFlags->type = QQmlPropertyData::Flags::QObjectDerivedType;
} else {
diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp
index 312153576a..13995d6001 100644
--- a/src/qml/qml/qqmlpropertyvalidator.cpp
+++ b/src/qml/qml/qqmlpropertyvalidator.cpp
@@ -117,8 +117,9 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
QQmlCustomParser *customParser = nullptr;
if (auto typeRef = resolvedType(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid())
- customParser = typeRef->type.customParser();
+ const auto type = typeRef->type();
+ if (type.isValid())
+ customParser = type.customParser();
}
QList<const QV4::CompiledData::Binding*> customBindings;
@@ -190,12 +191,16 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
if (notInRevision) {
QString typeName = stringAt(obj->inheritedTypeNameIndex);
- auto *objectType = resolvedType(obj->inheritedTypeNameIndex);
- if (objectType && objectType->type.isValid()) {
- return recordError(binding->location, tr("\"%1.%2\" is not available in %3 %4.%5.")
- .arg(typeName).arg(name).arg(objectType->type.module())
- .arg(objectType->version.majorVersion())
- .arg(objectType->version.minorVersion()));
+ if (auto *objectType = resolvedType(obj->inheritedTypeNameIndex)) {
+ const auto type = objectType->type();
+ if (type.isValid()) {
+ const auto version = objectType->version();
+ return recordError(binding->location,
+ tr("\"%1.%2\" is not available in %3 %4.%5.")
+ .arg(typeName).arg(name).arg(type.module())
+ .arg(version.majorVersion())
+ .arg(version.minorVersion()));
+ }
} else {
return recordError(binding->location, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name));
}
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index 5c04abf367..957f64e367 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -71,7 +71,7 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile()
for (auto it = resolvedTypes->constBegin(), end = resolvedTypes->constEnd();
it != end; ++it) {
- QQmlCustomParser *customParser = (*it)->type.customParser();
+ QQmlCustomParser *customParser = (*it)->type().customParser();
if (customParser)
customParsers.insert(it.key(), customParser);
}
@@ -337,7 +337,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex);
auto *typeRef = resolvedType(binding->propertyNameIndex);
- QQmlType type = typeRef ? typeRef->type : QQmlType();
+ QQmlType type = typeRef ? typeRef->type() : QQmlType();
if (!type.isValid())
imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr);
@@ -398,7 +398,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
const QString &originalPropertyName = stringAt(binding->propertyNameIndex);
auto *typeRef = resolvedType(obj->inheritedTypeNameIndex);
- const QQmlType type = typeRef ? typeRef->type : QQmlType();
+ const QQmlType type = typeRef ? typeRef->type() : QQmlType();
if (type.isValid()) {
COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.")
.arg(typeName).arg(originalPropertyName).arg(type.module())
@@ -607,7 +607,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
bool ok = false;
auto *tr = resolvedType(obj->inheritedTypeNameIndex);
- if (type.isValid() && tr && tr->type == type) {
+ if (type.isValid() && tr && tr->type() == type) {
// When these two match, we can short cut the search
QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex());
QMetaEnum menum = mprop.enumerator();
@@ -807,10 +807,11 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
Q_ASSERT(tr);
const QMetaObject *firstMetaObject = nullptr;
- if (tr->type.isValid())
- firstMetaObject = tr->type.metaObject();
- else if (tr->compilationUnit)
- firstMetaObject = tr->compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ const auto type = tr->type();
+ if (type.isValid())
+ firstMetaObject = type.metaObject();
+ else if (const auto compilationUnit = tr->compilationUnit())
+ firstMetaObject = compilationUnit->rootPropertyCache()->firstCppMetaObject();
if (isUsableComponent(firstMetaObject))
continue;
// if here, not a QQmlComponent, so needs wrapping
@@ -855,8 +856,8 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) {
auto typeRef = new QV4::ResolvedTypeReference;
- typeRef->type = componentType;
- typeRef->version = componentType.version();
+ typeRef->setType(componentType);
+ typeRef->setVersion(componentType.version());
insertResolvedType(syntheticComponent->inheritedTypeNameIndex, typeRef);
}
@@ -901,7 +902,7 @@ bool QQmlComponentAndAliasResolver::resolve()
if (obj->inheritedTypeNameIndex) {
auto *tref = resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(tref);
- if (tref->type.metaObject() == &QQmlComponent::staticMetaObject)
+ if (tref->type().metaObject() == &QQmlComponent::staticMetaObject)
isExplicitComponent = true;
}
if (!isExplicitComponent) {
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index 943d483847..b264528daa 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -300,7 +300,7 @@ void QQmlTypeData::setCompileUnit(const Container &container)
auto const root = container->objectAt(i);
for (auto it = root->inlineComponentsBegin(); it != root->inlineComponentsEnd(); ++it) {
auto *typeRef = m_compiledData->resolvedType(it->nameIndex);
- typeRef->compilationUnit = m_compiledData; // share compilation unit
+ typeRef->setCompilationUnit(m_compiledData); // share compilation unit
}
}
}
@@ -913,7 +913,7 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
if (resolvedType->needsCreation && qmlType.isCompositeSingleton()) {
return qQmlCompileError(resolvedType->location, tr("Composite Singleton Type %1 is not creatable.").arg(qmlType.qmlTypeName()));
}
- ref->compilationUnit = resolvedType->typeData->compilationUnit();
+ ref->setCompilationUnit(resolvedType->typeData->compilationUnit());
if (resolvedType->type.isInlineComponentType()) {
// Inline component which is part of an already resolved type
int objectId = -1;
@@ -924,44 +924,44 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
objectId = resolvedType->type.inlineComponentId();
}
Q_ASSERT(objectId != -1);
- ref->typePropertyCache = resolvedType->typeData->compilationUnit()->propertyCaches.at(objectId);
- ref->type = qmlType;
- Q_ASSERT(ref->type.isInlineComponentType());
+ ref->setTypePropertyCache(resolvedType->typeData->compilationUnit()->propertyCaches.at(objectId));
+ ref->setType(qmlType);
+ Q_ASSERT(ref->type().isInlineComponentType());
}
} else if (resolvedType->type.isInlineComponentType()) {
// Inline component, defined in the file we are currently compiling
if (!m_inlineComponentToCompiledData.contains(resolvedType.key())) {
- ref->type = qmlType;
+ ref->setType(qmlType);
if (qmlType.isValid()) {
// this is required for inline components in singletons
auto type = qmlType.lookupInlineComponentById(qmlType.inlineComponentId()).typeId();
auto typeID = type.isValid() ? type.id() : -1;
auto exUnit = engine->obtainExecutableCompilationUnit(typeID);
if (exUnit) {
- ref->compilationUnit = exUnit;
- ref->typePropertyCache = engine->propertyCacheForType(typeID);
+ ref->setCompilationUnit(exUnit);
+ ref->setTypePropertyCache(engine->propertyCacheForType(typeID));
}
}
} else {
- ref->compilationUnit = m_inlineComponentToCompiledData[resolvedType.key()];
- ref->typePropertyCache = m_inlineComponentToCompiledData[resolvedType.key()]->rootPropertyCache();
+ ref->setCompilationUnit(m_inlineComponentToCompiledData[resolvedType.key()]);
+ ref->setTypePropertyCache(m_inlineComponentToCompiledData[resolvedType.key()]->rootPropertyCache());
}
} else if (qmlType.isValid() && !resolvedType->selfReference) {
- ref->type = qmlType;
- Q_ASSERT(ref->type.isValid());
+ ref->setType(qmlType);
+ Q_ASSERT(ref->type().isValid());
- if (resolvedType->needsCreation && !ref->type.isCreatable()) {
- QString reason = ref->type.noCreationReason();
+ if (resolvedType->needsCreation && !qmlType.isCreatable()) {
+ QString reason = qmlType.noCreationReason();
if (reason.isEmpty())
reason = tr("Element is not creatable.");
return qQmlCompileError(resolvedType->location, reason);
}
- if (ref->type.containsRevisionedAttributes())
- ref->typePropertyCache = engine->cache(ref->type, resolvedType->version);
+ if (qmlType.containsRevisionedAttributes())
+ ref->setTypePropertyCache(engine->cache(qmlType, resolvedType->version));
}
- ref->version = resolvedType->version;
+ ref->setVersion(resolvedType->version);
ref->doDynamicTypeCheck();
resolvedTypeCache->insert(resolvedType.key(), ref.take());
}
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 96a5c20f22..b2f54d978f 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -70,7 +70,7 @@
#include <QtQml/QQmlFileSelector>
#include <private/qqmlcomponent_p.h>
-#include <private/qv4executablecompilationunit_p.h>
+#include <private/qv4resolvedtypereference_p.h>
#ifdef QT_QMLTEST_WITH_WIDGETS
#include <QtWidgets/QApplication>
@@ -332,8 +332,9 @@ private:
}
};
- TestCaseEnumerationResult enumerateTestCases(QV4::ExecutableCompilationUnit *compilationUnit,
- const Object *object = nullptr)
+ TestCaseEnumerationResult enumerateTestCases(
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const Object *object = nullptr)
{
QQmlType testCaseType;
for (quint32 i = 0, count = compilationUnit->importCount(); i < count; ++i) {
@@ -356,9 +357,8 @@ private:
if (!object) // Start at root of compilation unit if not enumerating a specific child
object = compilationUnit->objectAt(0);
- if (QV4::ExecutableCompilationUnit *superTypeUnit
- = compilationUnit->resolvedTypes.value(object->inheritedTypeNameIndex)
- ->compilationUnit.data()) {
+ if (const auto superTypeUnit = compilationUnit->resolvedTypes.value(
+ object->inheritedTypeNameIndex)->compilationUnit()) {
// We have a non-C++ super type, which could indicate we're a subtype of a TestCase
if (testCaseType.isValid() && superTypeUnit->url() == testCaseType.sourceUrl())
result.isTestCase = true;