aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-02-17 01:01:00 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-02-17 10:21:59 +0100
commit3e758800b4daf8fbc870a2ff5d54fce9d4402ce8 (patch)
treeba237b9da1c7dfd08bf13e71c5dbd6b3c2e77633 /src/qml/qml
parent925a0e499a5dbdb180fd9969a79abf96006ce4fd (diff)
parent55546991e24ca6799709cbe0171b9ab87216c35f (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts: src/imports/qtqml/plugin.cpp src/qml/qml/qqml.h src/qml/qml/qqmlmetatype.cpp src/qml/qml/qqmlmetatype_p.h src/qml/qml/qqmltypeloader.cpp src/qml/types/qqmlbind.cpp src/quick/items/qquickitemsmodule.cpp tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp Change-Id: I52548938a582cb6510271ed4bc3a9aa0c3c11df6
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqml.cpp37
-rw-r--r--src/qml/qml/qqml.h71
-rw-r--r--src/qml/qml/qqmlbinding.cpp9
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp31
-rw-r--r--src/qml/qml/qqmlengine.cpp6
-rw-r--r--src/qml/qml/qqmlengine_p.h16
-rw-r--r--src/qml/qml/qqmlmetatype.cpp22
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp6
-rw-r--r--src/qml/qml/qqmlprivate.h21
-rw-r--r--src/qml/qml/qqmlproperty.cpp47
-rw-r--r--src/qml/qml/qqmlpropertyvalidator.cpp2
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp6
-rw-r--r--src/qml/qml/qqmltypedata.cpp5
-rw-r--r--src/qml/qml/qqmltypeloader.cpp82
-rw-r--r--src/qml/qml/qqmltypenotavailable.cpp2
-rw-r--r--src/qml/qml/qqmltypenotavailable_p.h4
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp92
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h49
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp29
20 files changed, 398 insertions, 141 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index c71e6b68b8..ea6f15e9c2 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -46,6 +46,7 @@
#include <private/qqmlmetatypedata_p.h>
#include <private/qqmltype_p_p.h>
#include <private/qqmltypemodule_p_p.h>
+#include <private/qqmltypenotavailable_p.h>
#include <QtCore/qmutex.h>
@@ -358,4 +359,40 @@ void QQmlPrivate::qmlunregister(RegistrationType type, quintptr data)
}
}
+namespace QQmlPrivate {
+ template<>
+ void qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>(
+ const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject)
+ {
+ using T = QQmlTypeNotAvailable;
+
+ QML_GETTYPENAMES
+
+ RegisterTypeAndRevisions type = {
+ 0,
+ qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+ qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ 0,
+ nullptr,
+
+ uri,
+ QTypeRevision::fromMajorVersion(versionMajor),
+
+ &QQmlTypeNotAvailable::staticMetaObject,
+ classInfoMetaObject,
+
+ attachedPropertiesFunc<T>(),
+ attachedPropertiesMetaObject<T>(),
+
+ StaticCastSelector<T, QQmlParserStatus>::cast(),
+ StaticCastSelector<T, QQmlPropertyValueSource>::cast(),
+ StaticCastSelector<T, QQmlPropertyValueInterceptor>::cast(),
+
+ nullptr, nullptr, qmlCreateCustomParser<T>
+ };
+
+ qmlregister(TypeAndRevisionsRegistration, &type);
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 096bef7e4b..b9445e48a8 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -120,6 +120,16 @@
template<typename T, typename... Args> \
friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+#define QML_INTERFACE \
+ Q_CLASSINFO("QML.Element", "anonymous") \
+ enum class QmlIsInterface {yes = true}; \
+ template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlInterface; \
+ template<typename T, typename... Args> \
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+
+#define QML_UNAVAILABLE \
+ QML_FOREIGN(QQmlTypeNotAvailable)
+
enum { /* TYPEINFO flags */
QML_HAS_ATTACHED_PROPERTIES = 0x01
};
@@ -183,7 +193,8 @@ QT_DEPRECATED_VERSION_X_5_14("Use qmlRegisterAnonymousType instead") int qmlRegi
}
#endif
-int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message);
+int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor,
+ const char *qmlName, const QString& message);
template<typename T>
int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
@@ -422,9 +433,8 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
-
template<typename T, typename E>
-int qmlRegisterExtendedType()
+int qmlRegisterExtendedType(const char *uri, int versionMajor)
{
QML_GETTYPENAMES
@@ -437,7 +447,7 @@ int qmlRegisterExtendedType()
nullptr,
QString(),
- nullptr, QTypeRevision::zero(), nullptr, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, 0), nullptr, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -455,6 +465,15 @@ int qmlRegisterExtendedType()
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
+#if QT_DEPRECATED_SINCE(5, 15)
+template<typename T, typename E>
+QT_DEPRECATED_VERSION_X_5_15("Use qmlRegisterExtendedType(uri, versionMajor) instead")
+int qmlRegisterExtendedType()
+{
+ return qmlRegisterExtendedType<T, E>("", 0);
+}
+#endif
+
template<typename T, typename E>
int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
const char *qmlName)
@@ -494,7 +513,9 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
+#if QT_DEPRECATED_SINCE(5, 15)
template<typename T>
+QT_DEPRECATED_VERSION_X_5_15("Use qmlRegisterInterface(uri, versionMajor) instead")
int qmlRegisterInterface(const char *typeName)
{
QByteArray name(typeName);
@@ -503,12 +524,33 @@ int qmlRegisterInterface(const char *typeName)
QByteArray listName("QQmlListProperty<" + name + '>');
QQmlPrivate::RegisterInterface qmlInterface = {
- 0,
+ 1,
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
- qobject_interface_iid<T *>()
+ qobject_interface_iid<T *>(),
+ "",
+ QTypeRevision::zero()
+ };
+
+ return QQmlPrivate::qmlregister(QQmlPrivate::InterfaceRegistration, &qmlInterface);
+}
+#endif
+
+template<typename T>
+int qmlRegisterInterface(const char *uri, int versionMajor)
+{
+ QML_GETTYPENAMES
+
+ QQmlPrivate::RegisterInterface qmlInterface = {
+ 1,
+ qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+ qRegisterNormalizedMetaType<QQmlListProperty<T>>(listName.constData()),
+ qobject_interface_iid<T *>(),
+
+ uri,
+ QTypeRevision::fromVersion(versionMajor, 0)
};
return QQmlPrivate::qmlregister(QQmlPrivate::InterfaceRegistration, &qmlInterface);
@@ -766,11 +808,11 @@ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, i
return QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &type);
}
-template<class T, class Resolved, class Extended, bool Singleton>
+template<class T, class Resolved, class Extended, bool Singleton, bool Interface>
struct QmlTypeAndRevisionsRegistration;
template<class T, class Resolved, class Extended>
-struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false> {
+struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false, false> {
static void registerTypeAndRevisions(const char *uri, int versionMajor)
{
QQmlPrivate::qmlRegisterTypeAndRevisions<Resolved, Extended>(
@@ -779,7 +821,7 @@ struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false> {
};
template<class T, class Resolved>
-struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true> {
+struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true, false> {
static void registerTypeAndRevisions(const char *uri, int versionMajor)
{
QQmlPrivate::qmlRegisterSingletonAndRevisions<Resolved>(
@@ -787,6 +829,14 @@ struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true> {
}
};
+template<class T, class Resolved>
+struct QmlTypeAndRevisionsRegistration<T, Resolved, void, false, true> {
+ static void registerTypeAndRevisions(const char *uri, int versionMajor)
+ {
+ qmlRegisterInterface<Resolved>(uri, versionMajor);
+ }
+};
+
template<typename T = void, typename... Args>
void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor);
@@ -796,7 +846,8 @@ void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor)
QmlTypeAndRevisionsRegistration<
T, typename QQmlPrivate::QmlResolved<T>::Type,
typename QQmlPrivate::QmlExtended<T>::Type,
- QQmlPrivate::QmlSingleton<T>::Value>
+ QQmlPrivate::QmlSingleton<T>::Value,
+ QQmlPrivate::QmlInterface<T>::Value>
::registerTypeAndRevisions(uri, versionMajor);
qmlRegisterTypesAndRevisions<Args...>(uri, versionMajor);
}
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index e14b00af22..b9566d5862 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -43,6 +43,10 @@
#include "qqmlcontext.h"
#include "qqmlinfo.h"
#include "qqmldata_p.h"
+
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qqmldebugconnector_p.h>
+
#include <private/qqmlprofiler_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlscriptstring_p.h>
@@ -392,6 +396,11 @@ QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer<QV4::Exe
b->QQmlJavaScriptExpression::setContext(ctxt);
b->setScopeObject(obj);
+ if (QQmlDebugTranslationService *service
+ = QQmlDebugConnector::service<QQmlDebugTranslationService>()) {
+ service->foundTranslationBinding(b, obj, ctxt);
+ }
+
return b;
}
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 87f7fffe41..02c2b87a6e 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -125,8 +125,13 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
// * <TypeName>.<EnumValue>
// * <TypeName>.<ScopedEnumName>.<EnumValue>
- int dot = script.indexOf('.');
- if (dot == -1 || dot == script.length()-1)
+ auto nextDot = [&](int dot) {
+ const int nextDot = script.indexOf('.', dot + 1);
+ return (nextDot == script.length() - 1) ? -1 : nextDot;
+ };
+
+ int dot = nextDot(-1);
+ if (dot == -1)
return -1;
QString scope = QString::fromUtf8(script.left(dot));
@@ -137,18 +142,32 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
QQmlType type;
if (imports.isT1()) {
- imports.asT1()->resolveType(scope, &type, nullptr, nullptr, nullptr);
+ QQmlImportNamespace *ns = nullptr;
+ if (!imports.asT1()->resolveType(scope, &type, nullptr, &ns))
+ return -1;
+ if (!type.isValid() && ns != nullptr) {
+ dot = nextDot(dot);
+ if (dot == -1 || !imports.asT1()->resolveType(QString::fromUtf8(script.left(dot)),
+ &type, nullptr, nullptr)) {
+ return -1;
+ }
+ }
} else {
QQmlTypeNameCache::Result result = imports.asT2()->query(scope);
- if (result.isValid())
+ if (result.isValid()) {
type = result.type;
+ } else if (result.importNamespace) {
+ dot = nextDot(dot);
+ if (dot != -1)
+ type = imports.asT2()->query(QString::fromUtf8(script.left(dot))).type;
+ }
}
if (!type.isValid())
return -1;
- int dot2 = script.indexOf('.', dot+1);
- const bool dot2Valid = dot2 != -1 && dot2 != script.length()-1;
+ const int dot2 = nextDot(dot);
+ const bool dot2Valid = (dot2 != -1);
QByteArray enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1);
QByteArray scopedEnumName = (dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QByteArray());
if (!scopedEnumName.isEmpty())
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 7f30c4d713..c8b41d3684 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -654,11 +654,7 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
for (auto iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) {
iter.value()->isRegisteredWithEngine = false;
-
- // since unregisterInternalCompositeType() will not be called in this
- // case, we have to clean up the type registration manually
- QMetaType::unregisterType(iter.value()->metaTypeId);
- QMetaType::unregisterType(iter.value()->listMetaTypeId);
+ QQmlMetaType::unregisterInternalCompositeType({iter.value()->metaTypeId, iter.value()->listMetaTypeId});
}
#if QT_CONFIG(qml_debug)
delete profiler;
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 2c702367a4..8e292c4bbc 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -269,8 +269,24 @@ public:
mutable QMutex networkAccessManagerMutex;
+ QQmlGadgetPtrWrapper *valueTypeInstance(int typeIndex)
+ {
+ auto it = cachedValueTypeInstances.find(typeIndex);
+ if (it != cachedValueTypeInstances.end())
+ return *it;
+
+ if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(typeIndex)) {
+ QQmlGadgetPtrWrapper *instance = new QQmlGadgetPtrWrapper(valueType, q_func());
+ cachedValueTypeInstances.insert(typeIndex, instance);
+ return instance;
+ }
+
+ return nullptr;
+ }
+
private:
QHash<QQmlType, QJSValue> singletonInstances;
+ QHash<int, QQmlGadgetPtrWrapper *> cachedValueTypeInstances;
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
// the threaded loader. Only access them through their respective accessor methods.
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index c5c767df43..0baf142913 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -92,7 +92,12 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data,
d->typeId = type.typeId;
d->listId = type.listId;
d->isSetup = true;
- d->version = QTypeRevision::zero();
+ if (type.structVersion > 0) {
+ d->module = QString::fromUtf8(type.uri);
+ d->version = type.version;
+ } else {
+ d->version = QTypeRevision::zero();
+ }
data->registerType(d);
return d;
}
@@ -293,6 +298,17 @@ bool QQmlMetaType::qmlRegisterModuleTypes(const QString &uri)
return data->registerModuleTypes(uri);
}
+/*!
+ \internal
+ Method is only used to in tst_qqmlenginecleanup.cpp to test whether all
+ types have been removed from qmlLists after shutdown of QQmlEngine
+ */
+int QQmlMetaType::qmlRegisteredListTypeCount()
+{
+ QQmlMetaTypeDataPtr data;
+ return data->qmlLists.count();
+}
+
void QQmlMetaType::clearTypeRegistrations()
{
//Only cleans global static, assumed no running engine
@@ -329,7 +345,7 @@ void QQmlMetaType::unregisterAutoParentFunction(const QQmlPrivate::AutoParentFun
QQmlType QQmlMetaType::registerInterface(const QQmlPrivate::RegisterInterface &type)
{
- if (type.structVersion > 0)
+ if (type.structVersion > 1)
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
QQmlMetaTypeDataPtr data;
@@ -338,8 +354,6 @@ QQmlType QQmlMetaType::registerInterface(const QQmlPrivate::RegisterInterface &t
data->idToType.insert(priv->typeId, priv);
data->idToType.insert(priv->listId, priv);
- if (!priv->elementName.isEmpty())
- data->nameToType.insert(priv->elementName, priv);
if (data->interfaces.size() <= type.typeId)
data->interfaces.resize(type.typeId + 16);
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index c68bf0c551..0fc179fd34 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -202,6 +202,8 @@ public:
static void qmlRemoveModuleRegistration(const QString &uri);
static bool qmlRegisterModuleTypes(const QString &uri);
+
+ static int qmlRegisteredListTypeCount();
};
Q_DECLARE_TYPEINFO(QQmlMetaType, Q_MOVABLE_TYPE);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 6cc2bf49c8..28dd3d4ab4 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -173,7 +173,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
context = new QQmlContextData;
context->isInternal = true;
context->imports = compilationUnit->typeNameCache;
- context->initFromTypeCompilationUnit(compilationUnit, flags & CreationFlags::NormalObject ? subComponentIndex : -1);
+ context->initFromTypeCompilationUnit(compilationUnit, subComponentIndex);
context->setParent(parentContext);
if (!sharedState->rootContext) {
@@ -856,12 +856,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
QObject *groupObject = nullptr;
- QQmlValueType *valueType = nullptr;
+ QQmlGadgetPtrWrapper *valueType = nullptr;
const QQmlPropertyData *valueTypeProperty = nullptr;
QObject *bindingTarget = _bindingTarget;
if (QQmlValueTypeFactory::isValueType(bindingProperty->propType())) {
- valueType = QQmlValueTypeFactory::valueType(bindingProperty->propType());
+ valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType());
if (!valueType) {
recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
return false;
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index 527c5ee603..2e4bc60f79 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -125,6 +125,7 @@ class QJSValue;
class QJSEngine;
class QQmlEngine;
class QQmlCustomParser;
+class QQmlTypeNotAvailable;
template<class T>
QQmlCustomParser *qmlCreateCustomParser()
@@ -406,6 +407,9 @@ namespace QQmlPrivate
int listId;
const char *iid;
+
+ const char *uri;
+ QTypeRevision version;
};
struct RegisterAutoParent {
@@ -578,6 +582,18 @@ namespace QQmlPrivate
static constexpr bool Value = bool(T::QmlIsSingleton::yes);
};
+ template<class T, class = QmlVoidT<>>
+ struct QmlInterface
+ {
+ static constexpr bool Value = false;
+ };
+
+ template<class T>
+ struct QmlInterface<T, QmlVoidT<typename T::QmlIsInterface>>
+ {
+ static constexpr bool Value = bool(T::QmlIsInterface::yes);
+ };
+
template<typename T>
void qmlRegisterSingletonAndRevisions(const char *uri, int versionMajor,
const QMetaObject *classInfoMetaObject)
@@ -636,6 +652,11 @@ namespace QQmlPrivate
qmlregister(TypeAndRevisionsRegistration, &type);
}
+
+ template<>
+ void Q_QML_EXPORT qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>(
+ const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject);
+
} // namespace QQmlPrivate
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 93020661e2..8521de6ab3 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -353,10 +353,15 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (terminal.count() >= 3 &&
terminal.at(0) == QLatin1Char('o') &&
terminal.at(1) == QLatin1Char('n') &&
- terminal.at(2).isUpper()) {
+ (terminal.at(2).isUpper() || terminal.at(2) == '_')) {
QString signalName = terminal.mid(2).toString();
- signalName[0] = signalName.at(0).toLower();
+ int firstNon_;
+ int length = signalName.length();
+ for (firstNon_ = 0; firstNon_ < length; ++firstNon_)
+ if (signalName.at(firstNon_) != '_')
+ break;
+ signalName[firstNon_] = signalName.at(firstNon_).toLower();
// XXX - this code treats methods as signals
@@ -1044,13 +1049,19 @@ QVariant QQmlProperty::read(const QObject *object, const QString &name, QQmlEngi
QVariant QQmlPropertyPrivate::readValueProperty()
{
- if (isValueType()) {
-
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType());
- Q_ASSERT(valueType);
- valueType->read(object, core.coreIndex());
- return valueType->metaObject()->property(valueTypeData.coreIndex()).read(valueType);
+ auto doRead = [&](QQmlGadgetPtrWrapper *wrapper) {
+ wrapper->read(object, core.coreIndex());
+ return wrapper->property(valueTypeData.coreIndex()).read(wrapper);
+ };
+ if (isValueType()) {
+ if (QQmlGadgetPtrWrapper *wrapper = QQmlGadgetPtrWrapper::instance(engine, core.propType()))
+ return doRead(wrapper);
+ if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType())) {
+ QQmlGadgetPtrWrapper wrapper(valueType, nullptr);
+ return doRead(&wrapper);
+ }
+ return QVariant();
} else if (core.isQList()) {
QQmlListProperty<QObject> prop;
@@ -1183,10 +1194,22 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
bool rv = false;
if (valueTypeData.isValid()) {
- QQmlValueType *writeBack = QQmlValueTypeFactory::valueType(core.propType());
- writeBack->read(object, core.coreIndex());
- rv = write(writeBack, valueTypeData, value, context, flags);
- writeBack->write(object, core.coreIndex(), flags);
+ auto doWrite = [&](QQmlGadgetPtrWrapper *wrapper) {
+ wrapper->read(object, core.coreIndex());
+ rv = write(wrapper, valueTypeData, value, context, flags);
+ wrapper->write(object, core.coreIndex(), flags);
+ };
+
+ QQmlGadgetPtrWrapper *wrapper = context
+ ? QQmlGadgetPtrWrapper::instance(context->engine, core.propType())
+ : nullptr;
+ if (wrapper) {
+ doWrite(wrapper);
+ } else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType())) {
+ QQmlGadgetPtrWrapper wrapper(valueType, nullptr);
+ doWrite(&wrapper);
+ }
+
} else {
rv = write(object, core, value, context, flags);
}
diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp
index 001b19a8e5..3fb2eb399f 100644
--- a/src/qml/qml/qqmlpropertyvalidator.cpp
+++ b/src/qml/qml/qqmlpropertyvalidator.cpp
@@ -104,7 +104,7 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject(
validateObject(it->objectIndex, /* instantiatingBinding*/ nullptr);
}
- if (obj->flags & QV4::CompiledData::Object::IsComponent) {
+ if (obj->flags & QV4::CompiledData::Object::IsComponent && !(obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot)) {
Q_ASSERT(obj->nBindings == 1);
const QV4::CompiledData::Binding *componentBinding = obj->bindingTable();
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index d7a549e380..3518b21a70 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -881,6 +881,10 @@ bool QQmlComponentAndAliasResolver::resolve()
const int objCountWithoutSynthesizedComponents = qmlObjects->count();
for (int i = 0; i < objCountWithoutSynthesizedComponents; ++i) {
QmlIR::Object *obj = qmlObjects->at(i);
+ if (obj->isInlineComponent) {
+ componentRoots.append(i);
+ continue;
+ }
QQmlPropertyCache *cache = propertyCaches.at(i);
if (obj->inheritedTypeNameIndex == 0 && !cache)
continue;
@@ -936,7 +940,7 @@ bool QQmlComponentAndAliasResolver::resolve()
_objectsWithAliases.clear();
- if (!collectIdsAndAliases(rootBinding->value.objectIndex))
+ if (!collectIdsAndAliases(component->isInlineComponent ? componentRoots.at(i) : rootBinding->value.objectIndex))
return false;
component->namedObjectsInComponent.allocate(pool, _idToObjectIndex);
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index ec9061d04e..30d50b911e 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -829,8 +829,9 @@ void QQmlTypeData::resolveTypes()
if (ref.type.isCompositeSingleton()) {
ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
- if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies || m_waitingOnMe.contains(ref.typeData.data())) {
- // TODO: give an error message? If so, we should record and show the path of the cycle.
+ if (ref.typeData->isWaiting() || m_waitingOnMe.contains(ref.typeData.data())) {
+ qWarning() << "Cyclic dependency detected between" << ref.typeData->urlString()
+ << "and" << urlString();
continue;
}
addDependency(ref.typeData.data());
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index afad15331c..d8cfd80b9b 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -602,51 +602,59 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo
scriptImported(blob, import->location, script.nameSpace, import->qualifier);
}
}
+ } else if (
+ // Major version of module already registered:
+ // We believe that the registration is complete.
+ QQmlMetaType::typeModule(import->uri, import->version)
+
+ // Otherwise, try to register further module types.
+ || (qmldirResult != QQmlImports::QmldirInterceptedToRemote
+ && QQmlMetaType::qmlRegisterModuleTypes(import->uri))
+
+ // Otherwise, there is no way to register any further types.
+ // Try with any module of that name.
+ || QQmlMetaType::isAnyModule(import->uri)) {
+
+ if (!m_importCache.addLibraryImport(
+ importDatabase, import->uri, import->qualifier, import->version,
+ QString(), QString(), false, errors)) {
+ return false;
+ }
} else {
- // Is this a module?
- if (QQmlMetaType::isAnyModule(import->uri)
- || (qmldirResult != QQmlImports::QmldirInterceptedToRemote
- && QQmlMetaType::qmlRegisterModuleTypes(import->uri))) {
+ // We haven't yet resolved this import
+ m_unresolvedImports << import;
+
+ QQmlAbstractUrlInterceptor *interceptor = typeLoader()->engine()->urlInterceptor();
+
+ // Query any network import paths for this library.
+ // Interceptor might redirect local paths.
+ QStringList remotePathList = importDatabase->importPathList(
+ interceptor ? QQmlImportDatabase::LocalOrRemote
+ : QQmlImportDatabase::Remote);
+ if (!remotePathList.isEmpty()) {
+ // Add this library and request the possible locations for it
if (!m_importCache.addLibraryImport(
importDatabase, import->uri, import->qualifier, import->version,
- QString(), QString(), false, errors))
+ QString(), QString(), true, errors))
return false;
- } else {
- // We haven't yet resolved this import
- m_unresolvedImports << import;
-
- QQmlAbstractUrlInterceptor *interceptor = typeLoader()->engine()->urlInterceptor();
-
- // Query any network import paths for this library.
- // Interceptor might redirect local paths.
- QStringList remotePathList = importDatabase->importPathList(
- interceptor ? QQmlImportDatabase::LocalOrRemote
- : QQmlImportDatabase::Remote);
- if (!remotePathList.isEmpty()) {
- // Add this library and request the possible locations for it
- if (!m_importCache.addLibraryImport(
- importDatabase, import->uri, import->qualifier, import->version,
- QString(), QString(), true, errors))
- return false;
- // Probe for all possible locations
- int priority = 0;
- const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(
- import->uri, remotePathList, import->version);
- for (const QString &qmldirPath : qmlDirPaths) {
- if (interceptor) {
- QUrl url = interceptor->intercept(
- QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
- QQmlAbstractUrlInterceptor::QmldirFile);
- if (!QQmlFile::isLocalFile(url)
- && !fetchQmldir(url, import, ++priority, errors)) {
- return false;
- }
- } else if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors)) {
+ // Probe for all possible locations
+ int priority = 0;
+ const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(
+ import->uri, remotePathList, import->version);
+ for (const QString &qmldirPath : qmlDirPaths) {
+ if (interceptor) {
+ QUrl url = interceptor->intercept(
+ QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
+ QQmlAbstractUrlInterceptor::QmldirFile);
+ if (!QQmlFile::isLocalFile(url)
+ && !fetchQmldir(url, import, ++priority, errors)) {
return false;
}
-
+ } else if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors)) {
+ return false;
}
+
}
}
}
diff --git a/src/qml/qml/qqmltypenotavailable.cpp b/src/qml/qml/qqmltypenotavailable.cpp
index ffa4472e4b..0e95d6062c 100644
--- a/src/qml/qml/qqmltypenotavailable.cpp
+++ b/src/qml/qml/qqmltypenotavailable.cpp
@@ -46,8 +46,6 @@ int qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMi
return qmlRegisterUncreatableType<QQmlTypeNotAvailable>(uri,versionMajor,versionMinor,qmlName,message);
}
-QQmlTypeNotAvailable::QQmlTypeNotAvailable() { }
-
QT_END_NAMESPACE
#include "moc_qqmltypenotavailable_p.cpp"
diff --git a/src/qml/qml/qqmltypenotavailable_p.h b/src/qml/qml/qqmltypenotavailable_p.h
index 8db5876b10..9bb19ed86c 100644
--- a/src/qml/qml/qqmltypenotavailable_p.h
+++ b/src/qml/qml/qqmltypenotavailable_p.h
@@ -55,14 +55,10 @@
QT_BEGIN_NAMESPACE
-
class QQmlTypeNotAvailable : public QObject {
Q_OBJECT
QML_NAMED_ELEMENT(TypeNotAvailable)
QML_UNCREATABLE("Type not available.")
-
-public:
- QQmlTypeNotAvailable();
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 4beb6a4d07..254f1015e2 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -42,11 +42,11 @@
#include <QtCore/qmutex.h>
#include <private/qqmlglobal_p.h>
#include <QtCore/qdebug.h>
+#include <private/qqmlengine_p.h>
#include <private/qmetaobjectbuilder_p.h>
#if QT_CONFIG(qml_itemmodel)
#include <private/qqmlmodelindexvaluetype_p.h>
#endif
-#include <private/qmetatype_p.h>
Q_DECLARE_METATYPE(QQmlProperty)
@@ -221,61 +221,82 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor,
#endif
}
-QQmlValueType::QQmlValueType() :
- _metaObject(nullptr),
- gadgetPtr(nullptr),
- metaType(QMetaType::UnknownType)
+QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
+ : metaType(typeId)
{
+ QMetaObjectBuilder builder(gadgetMetaObject);
+ dynamicMetaObject = builder.toMetaObject();
+ *static_cast<QMetaObject*>(this) = *dynamicMetaObject;
}
-QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
- : gadgetPtr(QMetaType::create(typeId))
- , metaType(typeId)
+QQmlValueType::~QQmlValueType()
{
- QObjectPrivate *op = QObjectPrivate::get(this);
- Q_ASSERT(!op->metaObject);
- op->metaObject = this;
+ ::free(dynamicMetaObject);
+}
- QMetaObjectBuilder builder(gadgetMetaObject);
- _metaObject = builder.toMetaObject();
+QQmlGadgetPtrWrapper *QQmlGadgetPtrWrapper::instance(QQmlEngine *engine, int index)
+{
+ return engine ? QQmlEnginePrivate::get(engine)->valueTypeInstance(index) : nullptr;
+}
- *static_cast<QMetaObject*>(this) = *_metaObject;
+QQmlGadgetPtrWrapper::QQmlGadgetPtrWrapper(QQmlValueType *valueType, QObject *parent)
+ : QObject(parent), m_gadgetPtr(valueType->create())
+{
+ QObjectPrivate *d = QObjectPrivate::get(this);
+ Q_ASSERT(!d->metaObject);
+ d->metaObject = valueType;
}
-QQmlValueType::~QQmlValueType()
+QQmlGadgetPtrWrapper::~QQmlGadgetPtrWrapper()
{
- QObjectPrivate *op = QObjectPrivate::get(this);
- Q_ASSERT(op->metaObject == nullptr || op->metaObject == this);
- op->metaObject = nullptr;
- ::free(const_cast<QMetaObject *>(_metaObject));
- metaType.destroy(gadgetPtr);
+ QObjectPrivate *d = QObjectPrivate::get(this);
+ static_cast<const QQmlValueType *>(d->metaObject)->destroy(m_gadgetPtr);
+ d->metaObject = nullptr;
}
-void QQmlValueType::read(QObject *obj, int idx)
+void QQmlGadgetPtrWrapper::read(QObject *obj, int idx)
{
- void *a[] = { gadgetPtr, nullptr };
+ Q_ASSERT(m_gadgetPtr);
+ void *a[] = { m_gadgetPtr, nullptr };
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags)
+void QQmlGadgetPtrWrapper::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags)
{
- Q_ASSERT(gadgetPtr);
+ Q_ASSERT(m_gadgetPtr);
int status = -1;
- void *a[] = { gadgetPtr, nullptr, &status, &flags };
+ void *a[] = { m_gadgetPtr, nullptr, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
-QVariant QQmlValueType::value()
+QVariant QQmlGadgetPtrWrapper::value()
+{
+ Q_ASSERT(m_gadgetPtr);
+ return QVariant(metaTypeId(), m_gadgetPtr);
+}
+
+void QQmlGadgetPtrWrapper::setValue(const QVariant &value)
+{
+ Q_ASSERT(m_gadgetPtr);
+ Q_ASSERT(metaTypeId() == value.userType());
+ const QQmlValueType *type = valueType();
+ type->destruct(m_gadgetPtr);
+ type->construct(m_gadgetPtr, value.constData());
+}
+
+int QQmlGadgetPtrWrapper::metaCall(QMetaObject::Call type, int id, void **argv)
{
- Q_ASSERT(gadgetPtr);
- return QVariant(metaType.id(), gadgetPtr);
+ Q_ASSERT(m_gadgetPtr);
+ const QMetaObject *metaObject = valueType();
+ QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &id);
+ metaObject->d.static_metacall(static_cast<QObject *>(m_gadgetPtr), type, id, argv);
+ return id;
}
-void QQmlValueType::setValue(const QVariant &value)
+const QQmlValueType *QQmlGadgetPtrWrapper::valueType() const
{
- Q_ASSERT(metaType.id() == value.userType());
- metaType.destruct(gadgetPtr);
- metaType.construct(gadgetPtr, value.constData());
+ const QObjectPrivate *d = QObjectPrivate::get(this);
+ return static_cast<const QQmlValueType *>(d->metaObject);
}
QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *)
@@ -287,12 +308,9 @@ void QQmlValueType::objectDestroyed(QObject *)
{
}
-int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **argv)
+int QQmlValueType::metaCall(QObject *object, QMetaObject::Call type, int _id, void **argv)
{
- const QMetaObject *mo = _metaObject;
- QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &mo, &_id);
- mo->d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), type, _id, argv);
- return _id;
+ return static_cast<QQmlGadgetPtrWrapper *>(object)->metaCall(type, _id, argv);
}
QString QQmlPointFValueType::toString() const
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 901b7a6fd7..6768991581 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -54,7 +54,9 @@
#include "qqml.h"
#include "qqmlproperty.h"
#include "qqmlproperty_p.h"
+
#include <private/qqmlnullablevalue_p.h>
+#include <private/qmetatype_p.h>
#include <QtCore/qobject.h>
#include <QtCore/qrect.h>
@@ -65,16 +67,20 @@
QT_BEGIN_NAMESPACE
-class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject, public QAbstractDynamicMetaObject
+class Q_QML_PRIVATE_EXPORT QQmlValueType : public QAbstractDynamicMetaObject
{
public:
- QQmlValueType();
+ QQmlValueType() : metaType(QMetaType::UnknownType) {}
QQmlValueType(int userType, const QMetaObject *metaObject);
- ~QQmlValueType() override;
- void read(QObject *, int);
- void write(QObject *, int, QQmlPropertyData::WriteFlags flags);
- QVariant value();
- void setValue(const QVariant &);
+ ~QQmlValueType();
+
+ void *create() const { return metaType.create(); }
+ void destroy(void *gadgetPtr) const { metaType.destroy(gadgetPtr); }
+
+ void construct(void *gadgetPtr, const void *copy) const { metaType.construct(gadgetPtr, copy); }
+ void destruct(void *gadgetPtr) const { metaType.destruct(gadgetPtr); }
+
+ int metaTypeId() const { return metaType.id(); }
// ---- dynamic meta object data interface
QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override;
@@ -82,12 +88,33 @@ public:
int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv) override;
// ----
-private:
- const QMetaObject *_metaObject;
- void *gadgetPtr;
-
public:
QMetaType metaType;
+ QMetaObject *dynamicMetaObject = nullptr;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlGadgetPtrWrapper : public QObject
+{
+ Q_OBJECT
+public:
+ static QQmlGadgetPtrWrapper *instance(QQmlEngine *engine, int index);
+
+ QQmlGadgetPtrWrapper(QQmlValueType *valueType, QObject *parent);
+ ~QQmlGadgetPtrWrapper();
+
+ void read(QObject *obj, int idx);
+ void write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags);
+ QVariant value();
+ void setValue(const QVariant &value);
+
+ int metaTypeId() const { return valueType()->metaTypeId(); }
+ int metaCall(QMetaObject::Call type, int id, void **argv);
+ QMetaProperty property(int index) { return valueType()->property(index); }
+
+private:
+ const QQmlValueType *valueType() const;
+
+ void *m_gadgetPtr = nullptr;
};
class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index ecb86e2f10..de23e929e2 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -136,6 +136,20 @@ static void list_clear(QQmlListProperty<QObject> *prop)
resolved.activateSignal();
}
+static void list_replace(QQmlListProperty<QObject> *prop, int index, QObject *o)
+{
+ const ResolvedList resolved(prop);
+ resolved.list()->replace(index, o);
+ resolved.activateSignal();
+}
+
+static void list_removeLast(QQmlListProperty<QObject> *prop)
+{
+ const ResolvedList resolved(prop);
+ resolved.list()->removeLast();
+ resolved.activateSignal();
+}
+
QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr()
: QQmlGuard<QObject>(nullptr), m_target(nullptr), m_index(-1)
{
@@ -289,11 +303,13 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
continue;
const int valueIndex = vi->m_propertyIndex.valueTypeIndex();
- int type = QQmlData::get(object)->propertyCache->property(id)->propType();
+ const QQmlData *data = QQmlData::get(object);
+ const int type = data->propertyCache->property(id)->propType();
if (type != QMetaType::UnknownType) {
if (valueIndex != -1) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
+ QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance(
+ data->context->engine, type);
Q_ASSERT(valueType);
//
@@ -327,7 +343,7 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
// (7) Issue the interceptor call with the new component value.
//
- QMetaProperty valueProp = valueType->metaObject()->property(valueIndex);
+ QMetaProperty valueProp = valueType->property(valueIndex);
QVariant newValue(type, a[0]);
valueType->read(object, id);
@@ -735,7 +751,8 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
*static_cast<QQmlListProperty<QObject> *>(a[0])
= QQmlListProperty<QObject>(
object, reinterpret_cast<void *>(quintptr(id)),
- list_append, list_count, list_at, list_clear);
+ list_append, list_count, list_at,
+ list_clear, list_replace, list_removeLast);
} else {
*reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id);
}
@@ -879,9 +896,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
return -1;
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
// Value type property or deep alias
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType());
+ QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance(
+ ctxt->engine, pd->propType());
if (valueType) {
-
valueType->read(target, coreIndex);
int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a);