diff options
Diffstat (limited to 'src/qml')
81 files changed, 1087 insertions, 1145 deletions
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index a5a1cf8969..7d6ef14854 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -57,6 +57,7 @@ #include <QtCore/qvector.h> #include <QtCore/qstringlist.h> #include <QtCore/qhash.h> +#include <QtCore/qversionnumber.h> #if QT_CONFIG(temporaryfile) #include <QtCore/qsavefile.h> @@ -65,6 +66,7 @@ #include <private/qendian_p.h> #include <private/qv4staticvalue_p.h> #include <functional> +#include <limits.h> QT_BEGIN_NAMESPACE @@ -75,7 +77,7 @@ QT_BEGIN_NAMESPACE // Also change the comment behind the number to describe the latest change. This has the added // benefit that if another patch changes the version too, it will result in a merge conflict, and // not get removed silently. -#define QV4_DATA_STRUCTURE_VERSION 0x29// support additional required property features +#define QV4_DATA_STRUCTURE_VERSION 0x30// support additional required property features class QIODevice; class QQmlTypeNameCache; @@ -195,39 +197,14 @@ struct JSClass }; static_assert(sizeof(JSClass) == 4, "JSClass structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); -// This data structure is intended to be binary compatible with QStringData/QStaticStringData on -// 64-bit and 32-bit little-endian architectures, in all directions. So the same structure mapped -// from a file must be castable to a QStringData regardless of the pointer size. With the first -// few fields that's easy, they're always 32-bit. However the offset field of QArrayData is a -// ptrdiff_t and thus variable in size. -// On 64-bit systems compilers enforce an 8-byte alignment and thus place it at offset 16, while -// on 32-bit systems offset 12 is sufficient. Therefore the two values don't overlap and contain -// the same value. struct String { - qint32_le refcount; // -1 qint32_le size; - quint32_le allocAndCapacityReservedFlag; // 0 - quint32_le offsetOn32Bit; - quint64_le offsetOn64Bit; - // uint16 strdata[] static int calculateSize(const QString &str) { return (sizeof(String) + (str.length() + 1) * sizeof(quint16) + 7) & ~0x7; } }; -static_assert(sizeof(String) == 24, "String structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); - -// Ensure compatibility with QString -static_assert(offsetof(QArrayData, ref) == offsetof(String, refcount), "refcount must be at the same location"); -static_assert(offsetof(QArrayData, size) == offsetof(String, size), "size must be at the same location"); -static_assert(offsetof(String, offsetOn64Bit) == 16, "offset must be at 8-byte aligned location"); -static_assert(offsetof(String, offsetOn32Bit) == 12, "offset must be at 4-byte aligned location"); -#if QT_POINTER_SIZE == 8 -static_assert(offsetof(QArrayData, offset) == offsetof(String, offsetOn64Bit), "offset must be at the same location"); -#else -static_assert(offsetof(QArrayData, offset) == offsetof(String, offsetOn32Bit), "offset must be at the same location"); -#endif struct CodeOffsetToLine { quint32_le codeOffset; @@ -905,14 +882,16 @@ struct Import quint32_le uriIndex; quint32_le qualifierIndex; - qint32_le majorVersion; - qint32_le minorVersion; - Location location; + QTypeRevision version; + quint16_le reserved; - Import() { type = 0; uriIndex = 0; qualifierIndex = 0; majorVersion = 0; minorVersion = 0; } + Import() + { + type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0; + } }; -static_assert(sizeof(Import) == 24, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Import) == 20, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct QmlUnit { @@ -1016,14 +995,13 @@ struct Unit const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable); const quint32_le offset = offsetTable[idx]; const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset); + Q_ASSERT(str->size >= 0); if (str->size == 0) return QString(); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - if (flags & StaticData) { - const QStringDataPtr holder = { const_cast<QStringData *>(reinterpret_cast<const QStringData*>(str)) }; - return QString(holder); - } const QChar *characters = reinterpret_cast<const QChar *>(str + 1); + if (flags & StaticData) + return QString::fromRawData(characters, str->size); return QString(characters, str->size); #else const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1); diff --git a/src/qml/common/qv4stringtoarrayindex_p.h b/src/qml/common/qv4stringtoarrayindex_p.h index 61bd988d1e..d4b064f865 100644 --- a/src/qml/common/qv4stringtoarrayindex_p.h +++ b/src/qml/common/qv4stringtoarrayindex_p.h @@ -65,6 +65,8 @@ inline uint charToUInt(const char *ch) { return static_cast<unsigned char>(*ch); template <typename T> uint stringToArrayIndex(const T *ch, const T *end) { + if (ch == end) + return std::numeric_limits<uint>::max(); uint i = charToUInt(ch) - '0'; if (i > 9) return std::numeric_limits<uint>::max(); diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index a3ee431e90..4de7734ecf 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -407,11 +407,7 @@ void ScriptDirectivesCollector::importModule(const QString &uri, const QString & QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>(); import->type = QV4::CompiledData::Import::ImportLibrary; import->uriIndex = jsGenerator->registerString(uri); - int vmaj; - int vmin; - IRBuilder::extractVersion(QStringRef(&version), &vmaj, &vmin); - import->majorVersion = vmaj; - import->minorVersion = vmin; + import->version = IRBuilder::extractVersion(QStringRef(&version)); import->qualifierIndex = jsGenerator->registerString(module); import->location.line = lineNumber; import->location.column = column; @@ -752,16 +748,14 @@ bool IRBuilder::visit(QQmlJS::AST::UiImport *node) } if (node->version) { - import->majorVersion = node->version->majorVersion; - import->minorVersion = node->version->minorVersion; + import->version = node->version->version; } else if (import->type == QV4::CompiledData::Import::ImportLibrary) { recordError(node->importIdToken, QCoreApplication::translate("QQmlParser","Library import requires a version")); return false; } else { // For backward compatibility in how the imports are loaded we - // must otherwise initialize the major and minor version to -1. - import->majorVersion = -1; - import->minorVersion = -1; + // must otherwise initialize the major and minor version to invalid. + import->version = QTypeRevision(); } import->location.line = node->importToken.startLine; @@ -1055,22 +1049,15 @@ QStringRef IRBuilder::asStringRef(QQmlJS::AST::Node *node) return textRefAt(node->firstSourceLocation(), node->lastSourceLocation()); } -void IRBuilder::extractVersion(const QStringRef &string, int *maj, int *min) +QTypeRevision IRBuilder::extractVersion(const QStringRef &string) { - *maj = -1; *min = -1; + if (string.isEmpty()) + return QTypeRevision(); - if (!string.isEmpty()) { - - int dot = string.indexOf(QLatin1Char('.')); - - if (dot < 0) { - *maj = string.toInt(); - *min = 0; - } else { - *maj = string.left(dot).toInt(); - *min = string.mid(dot + 1).toInt(); - } - } + const int dot = string.indexOf(QLatin1Char('.')); + return (dot < 0) + ? QTypeRevision::fromVersion(string.toInt(), 0) + : QTypeRevision::fromVersion(string.left(dot).toInt(), string.mid(dot + 1).toInt()); } QStringRef IRBuilder::textRefAt(const QQmlJS::AST::SourceLocation &first, const QQmlJS::AST::SourceLocation &last) const diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 32921638af..ae74254a42 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -498,7 +498,7 @@ public: static QString asString(QQmlJS::AST::UiQualifiedId *node); QStringRef asStringRef(QQmlJS::AST::Node *node); - static void extractVersion(const QStringRef &string, int *maj, int *min); + static QTypeRevision extractVersion(const QStringRef &string); QStringRef textRefAt(const QQmlJS::AST::SourceLocation &loc) const { return QStringRef(&sourceCode, loc.offset, loc.length); } QStringRef textRefAt(const QQmlJS::AST::SourceLocation &first, diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index acc4b02e96..0c0a005689 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. @@ -47,6 +48,7 @@ #include <private/qml_compile_hash_p.h> #include <private/qqmlirbuilder_p.h> #include <QCryptographicHash> +#include <QtEndian> // Efficient implementation that takes advantage of powers of two. static inline size_t roundUpToMultipleOf(size_t divisor, size_t x) @@ -108,19 +110,11 @@ void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit) QV4::CompiledData::String *s = reinterpret_cast<QV4::CompiledData::String *>(stringData); Q_ASSERT(reinterpret_cast<uintptr_t>(s) % alignof(QV4::CompiledData::String) == 0); - s->refcount = -1; + Q_ASSERT(qstr.length() >= 0); s->size = qstr.length(); - s->allocAndCapacityReservedFlag = 0; - s->offsetOn32Bit = sizeof(QV4::CompiledData::String); - s->offsetOn64Bit = sizeof(QV4::CompiledData::String); ushort *uc = reinterpret_cast<ushort *>(reinterpret_cast<char *>(s) + sizeof(*s)); -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - memcpy(uc, qstr.constData(), s->size * sizeof(ushort)); -#else - for (int i = 0; i < s->size; ++i) - uc[i] = qToLittleEndian<ushort>(qstr.at(i).unicode()); -#endif + qToLittleEndian<ushort>(qstr.constData(), s->size, uc); uc[s->size] = 0; stringData += QV4::CompiledData::String::calculateSize(qstr); diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index c0dd696b8a..254e1c46e9 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -348,7 +348,7 @@ QT_BEGIN_NAMESPACE #endif #endif -#define MOTH_INSTR_ALIGN_MASK (Q_ALIGNOF(QV4::Moth::Instr) - 1) +#define MOTH_INSTR_ALIGN_MASK (alignof(QV4::Moth::Instr) - 1) #define MOTH_INSTR_ENUM(I) I, I##_Wide, #define MOTH_INSTR_SIZE(I) (sizeof(QV4::Moth::Instr::instr_##I)) diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index 7c2693508c..4095cd22ea 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -284,7 +284,7 @@ In particular, QML currently supports: \li \c {std::vector<bool>} \endlist -and all registered QList, QVector, QQueue, QStack, QSet, QLinkedList, std::list, +and all registered QList, QVector, QQueue, QStack, QSet, std::list, std::vector that contain a type marked with \l Q_DECLARE_METATYPE. These sequence types are implemented directly in terms of the underlying C++ diff --git a/src/qml/doc/src/external-resources.qdoc b/src/qml/doc/src/external-resources.qdoc index 68c5ab4664..17ac7693bc 100644 --- a/src/qml/doc/src/external-resources.qdoc +++ b/src/qml/doc/src/external-resources.qdoc @@ -45,7 +45,7 @@ \title Mozilla Developer Network Date Reference */ /*! - \externalpage hhttps://www.froglogic.com/squish/gui-testing + \externalpage https://www.froglogic.com/squish/gui-testing \title Squish */ /*! diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h index 7866a5bdda..37376a1485 100644 --- a/src/qml/jsapi/qjsengine_p.h +++ b/src/qml/jsapi/qjsengine_p.h @@ -110,8 +110,8 @@ public: QString uiLanguage; // These methods may be called from the QML loader thread - inline QQmlPropertyCache *cache(QObject *obj, int minorVersion = -1); - inline QQmlPropertyCache *cache(const QMetaObject *, int minorVersion = -1); + inline QQmlPropertyCache *cache(QObject *obj, QTypeRevision version = QTypeRevision()); + inline QQmlPropertyCache *cache(const QMetaObject *obj, QTypeRevision version = QTypeRevision()); }; QJSEnginePrivate::Locker::Locker(const QJSEngine *e) @@ -161,14 +161,14 @@ and deleted before the loader thread has a chance to use or reference it. This can't currently happen as the cache holds a reference to the QQmlPropertyCache until the QQmlEngine is destroyed. */ -QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, int minorVersion) +QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, QTypeRevision version) { if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted) return nullptr; Locker locker(this); const QMetaObject *mo = obj->metaObject(); - return QQmlMetaType::propertyCache(mo, minorVersion); + return QQmlMetaType::propertyCache(mo, version); } /*! @@ -180,12 +180,12 @@ exist for the lifetime of the QQmlEngine. The returned cache is not referenced, so if it is to be stored, call addref(). */ -QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, int minorVersion) +QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, QTypeRevision version) { Q_ASSERT(metaObject); Locker locker(this); - return QQmlMetaType::propertyCache(metaObject, minorVersion); + return QQmlMetaType::propertyCache(metaObject, version); } diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index a99ec16943..a2fac21b29 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -127,13 +127,17 @@ ReturnedValue ArrayBufferCtor::method_isView(const FunctionObject *, const Value void Heap::SharedArrayBuffer::init(size_t length) { Object::init(); + QPair<QTypedArrayData<char> *, char *> pair; if (length < UINT_MAX) - data = QTypedArrayData<char>::allocate(length + 1); - if (!data) { + pair = QTypedArrayData<char>::allocate(length + 1); + if (!pair.first) { + new (&d) QArrayDataPointer<char>(); internalClass->engine->throwRangeError(QStringLiteral("ArrayBuffer: out of memory")); return; } - data->size = int(length); + auto data = new (&d) QArrayDataPointer<char>{ pair.first, pair.second, uint(length) }; + + // can't use appendInitialize() because we want to set the terminating '\0' memset(data->data(), 0, length + 1); isShared = true; } @@ -141,41 +145,24 @@ void Heap::SharedArrayBuffer::init(size_t length) void Heap::SharedArrayBuffer::init(const QByteArray& array) { Object::init(); - data = const_cast<QByteArray&>(array).data_ptr(); - data->ref.ref(); + new (&d) QArrayDataPointer<char>(*const_cast<QByteArray &>(array).data_ptr()); isShared = true; } void Heap::SharedArrayBuffer::destroy() { - if (data && !data->ref.deref()) - QTypedArrayData<char>::deallocate(data); + data().~QArrayDataPointer(); Object::destroy(); } QByteArray ArrayBuffer::asByteArray() const { - QByteArrayDataPtr ba = { d()->data }; - ba.ptr->ref.ref(); - return QByteArray(ba); + return QByteArray(d()->data()); } -void ArrayBuffer::detach() { - if (!d()->data->ref.isShared()) - return; - - QTypedArrayData<char> *oldData = d()->data; - - d()->data = QTypedArrayData<char>::allocate(oldData->size + 1); - if (!d()->data) { - engine()->throwRangeError(QStringLiteral("ArrayBuffer: out of memory")); - return; - } - - memcpy(d()->data->data(), oldData->data(), oldData->size + 1); - - if (!oldData->ref.deref()) - QTypedArrayData<char>::deallocate(oldData); +void ArrayBuffer::detach() +{ + d()->data().detach(); } @@ -200,7 +187,7 @@ ReturnedValue SharedArrayBufferPrototype::method_get_byteLength(const FunctionOb if (!a || a->isDetachedBuffer() || !a->isSharedArrayBuffer()) return b->engine()->throwTypeError(); - return Encode(a->d()->data->size); + return Encode(a->d()->data()->size); } ReturnedValue SharedArrayBufferPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) @@ -217,12 +204,12 @@ ReturnedValue SharedArrayBufferPrototype::slice(const FunctionObject *b, const V double start = argc > 0 ? argv[0].toInteger() : 0; double end = (argc < 2 || argv[1].isUndefined()) ? - a->d()->data->size : argv[1].toInteger(); + a->d()->data()->size : argv[1].toInteger(); if (scope.hasException()) return QV4::Encode::undefined(); - double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size); - double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size); + double first = (start < 0) ? qMax(a->d()->data()->size + start, 0.) : qMin(start, (double)a->d()->data()->size); + double final = (end < 0) ? qMax(a->d()->data()->size + end, 0.) : qMin(end, (double)a->d()->data()->size); const FunctionObject *constructor = a->speciesConstructor(scope, shared ? scope.engine->sharedArrayBufferCtor() : scope.engine->arrayBufferCtor()); if (!constructor) @@ -231,13 +218,13 @@ ReturnedValue SharedArrayBufferPrototype::slice(const FunctionObject *b, const V double newLen = qMax(final - first, 0.); ScopedValue argument(scope, QV4::Encode(newLen)); QV4::Scoped<SharedArrayBuffer> newBuffer(scope, constructor->callAsConstructor(argument, 1)); - if (!newBuffer || newBuffer->d()->data->size < (int)newLen || + if (!newBuffer || newBuffer->d()->data()->size < newLen || newBuffer->isDetachedBuffer() || (newBuffer->isSharedArrayBuffer() != shared) || newBuffer->sameValue(*a) || a->isDetachedBuffer()) return scope.engine->throwTypeError(); - memcpy(newBuffer->d()->data->data(), a->d()->data->data() + (uint)first, newLen); + memcpy(newBuffer->d()->data()->data(), a->d()->data()->data() + (uint)first, newLen); return newBuffer->asReturnedValue(); } @@ -265,7 +252,7 @@ ReturnedValue ArrayBufferPrototype::method_get_byteLength(const FunctionObject * if (!a || a->isDetachedBuffer() || a->isSharedArrayBuffer()) return f->engine()->throwTypeError(); - return Encode(a->d()->data->size); + return Encode(a->d()->data()->size); } ReturnedValue ArrayBufferPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index 8344fa2554..1873c41261 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -52,6 +52,7 @@ #include "qv4object_p.h" #include "qv4functionobject_p.h" +#include <QtCore/qarraydatapointer.h> QT_BEGIN_NAMESPACE @@ -71,12 +72,14 @@ struct Q_QML_PRIVATE_EXPORT SharedArrayBuffer : Object { void init(size_t length); void init(const QByteArray& array); void destroy(); - QTypedArrayData<char> *data; + std::aligned_storage_t<sizeof(QArrayDataPointer<char>), alignof(QArrayDataPointer<char>)> d; + const QArrayDataPointer<char> &data() const { return *reinterpret_cast<const QArrayDataPointer<char> *>(&d); } + QArrayDataPointer<char> &data() { return *reinterpret_cast<QArrayDataPointer<char> *>(&d); } bool isShared; - uint byteLength() const { return data ? data->size : 0; } + uint byteLength() const { return data().size; } - bool isDetachedBuffer() const { return !data; } + bool isDetachedBuffer() const { return data().isNull(); } bool isSharedArrayBuffer() const { return isShared; } }; @@ -90,9 +93,7 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : SharedArrayBuffer { isShared = false; } void detachArrayBuffer() { - if (data && !data->ref.deref()) - QTypedArrayData<char>::deallocate(data); - data = nullptr; + data().clear(); } }; @@ -124,11 +125,11 @@ struct Q_QML_PRIVATE_EXPORT SharedArrayBuffer : Object QByteArray asByteArray() const; uint byteLength() const { return d()->byteLength(); } - char *data() { Q_ASSERT(d()->data); return d()->data->data(); } - const char *constData() { Q_ASSERT(d()->data); return d()->data->data(); } + char *data() { return d()->data()->data(); } + const char *constData() { return d()->data()->data(); } - bool isShared() { return d()->data->ref.isShared(); } - bool isDetachedBuffer() const { return !d()->data; } + bool isShared() { return d()->data()->isShared(); } + bool isDetachedBuffer() const { return d()->data().isNull(); } bool isSharedArrayBuffer() const { return d()->isShared; } }; @@ -140,11 +141,11 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : SharedArrayBuffer QByteArray asByteArray() const; uint byteLength() const { return d()->byteLength(); } - char *data() { detach(); return d()->data ? d()->data->data() : nullptr; } + char *data() { if (d()->data().needsDetach()) detach(); return d()->data().data(); } // ### is that detach needed? - const char *constData() { detach(); return d()->data ? d()->data->data() : nullptr; } + const char *constData() const { return d()->data().data(); } - bool isShared() { return d()->data && d()->data->ref.isShared(); } + bool isShared() { return d()->data()->isShared(); } void detach(); void detachArrayBuffer() { d()->detachArrayBuffer(); } }; diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index 5ab8cf2dcb..bb1acb963e 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -85,7 +85,7 @@ ReturnedValue DataViewCtor::virtualCallAsConstructor(const FunctionObject *f, co if (buffer->isDetachedBuffer()) return scope.engine->throwTypeError(); - uint bufferLength = buffer->d()->data->size; + uint bufferLength = buffer->d()->data()->size; if (offset > bufferLength) return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range")); @@ -197,7 +197,7 @@ ReturnedValue DataViewPrototype::method_getChar(const FunctionObject *b, const V return e->throwRangeError(QStringLiteral("index out of range")); idx += v->d()->byteOffset; - T t = T(v->d()->buffer->data->data()[idx]); + T t = T(v->d()->buffer->data()->data()[idx]); return Encode((int)t); } @@ -221,8 +221,8 @@ ReturnedValue DataViewPrototype::method_get(const FunctionObject *b, const Value bool littleEndian = argc < 2 ? false : argv[1].toBoolean(); T t = littleEndian - ? qFromLittleEndian<T>((uchar *)v->d()->buffer->data->data() + idx) - : qFromBigEndian<T>((uchar *)v->d()->buffer->data->data() + idx); + ? qFromLittleEndian<T>((uchar *)v->d()->buffer->data()->data() + idx) + : qFromBigEndian<T>((uchar *)v->d()->buffer->data()->data() + idx); return Encode(t); } @@ -252,8 +252,8 @@ ReturnedValue DataViewPrototype::method_getFloat(const FunctionObject *b, const float f; } u; u.i = littleEndian - ? qFromLittleEndian<uint>((uchar *)v->d()->buffer->data->data() + idx) - : qFromBigEndian<uint>((uchar *)v->d()->buffer->data->data() + idx); + ? qFromLittleEndian<uint>((uchar *)v->d()->buffer->data()->data() + idx) + : qFromBigEndian<uint>((uchar *)v->d()->buffer->data()->data() + idx); return Encode(u.f); } else { Q_ASSERT(sizeof(T) == 8); @@ -262,8 +262,8 @@ ReturnedValue DataViewPrototype::method_getFloat(const FunctionObject *b, const double d; } u; u.i = littleEndian - ? qFromLittleEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx) - : qFromBigEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx); + ? qFromLittleEndian<quint64>((uchar *)v->d()->buffer->data()->data() + idx) + : qFromBigEndian<quint64>((uchar *)v->d()->buffer->data()->data() + idx); return Encode(u.d); } } @@ -288,7 +288,7 @@ ReturnedValue DataViewPrototype::method_setChar(const FunctionObject *b, const V return e->throwRangeError(QStringLiteral("index out of range")); idx += v->d()->byteOffset; - v->d()->buffer->data->data()[idx] = (char)val; + v->d()->buffer->data()->data()[idx] = (char)val; RETURN_UNDEFINED(); } @@ -316,9 +316,9 @@ ReturnedValue DataViewPrototype::method_set(const FunctionObject *b, const Value if (littleEndian) - qToLittleEndian<T>(val, (uchar *)v->d()->buffer->data->data() + idx); + qToLittleEndian<T>(val, (uchar *)v->d()->buffer->data()->data() + idx); else - qToBigEndian<T>(val, (uchar *)v->d()->buffer->data->data() + idx); + qToBigEndian<T>(val, (uchar *)v->d()->buffer->data()->data() + idx); RETURN_UNDEFINED(); } @@ -352,9 +352,9 @@ ReturnedValue DataViewPrototype::method_setFloat(const FunctionObject *b, const } u; u.f = val; if (littleEndian) - qToLittleEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx); + qToLittleEndian(u.i, (uchar *)v->d()->buffer->data()->data() + idx); else - qToBigEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx); + qToBigEndian(u.i, (uchar *)v->d()->buffer->data()->data() + idx); } else { Q_ASSERT(sizeof(T) == 8); union { @@ -363,9 +363,9 @@ ReturnedValue DataViewPrototype::method_setFloat(const FunctionObject *b, const } u; u.d = val; if (littleEndian) - qToLittleEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx); + qToLittleEndian(u.i, (uchar *)v->d()->buffer->data()->data() + idx); else - qToBigEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx); + qToBigEndian(u.i, (uchar *)v->d()->buffer->data()->data() + idx); } RETURN_UNDEFINED(); } diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index fa4a1f1ce4..962b23fad6 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -817,7 +817,7 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQm if (typePropertyCache) { return typePropertyCache; } else if (type.isValid()) { - typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion); + typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), version); return typePropertyCache; } else { Q_ASSERT(compilationUnit); diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index 8cad18a3dc..c080978a87 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -326,17 +326,15 @@ private: struct ResolvedTypeReference { ResolvedTypeReference() - : majorVersion(0) - , minorVersion(0) - , isFullyDynamicType(false) + : version(QTypeRevision::zero()) + , isFullyDynamicType(false) {} QQmlType type; QQmlRefPointer<QQmlPropertyCache> typePropertyCache; QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit; - int majorVersion; - int minorVersion; + 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; diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 5a1b27fda6..ee42342bf2 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -80,7 +80,6 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description #if QT_CONFIG(qml_itemmodel) #define FOREACH_QML_SEQUENCE_TYPE_FOR_ITEMMODEL(F) \ F(QModelIndex, QModelIndex, QModelIndexList, QModelIndex()) \ - F(QModelIndex, QModelIndexVector, QVector<QModelIndex>, QModelIndex()) \ F(QModelIndex, QModelIndexStdVector, std::vector<QModelIndex>, QModelIndex()) \ F(QItemSelectionRange, QItemSelectionRange, QItemSelection, QItemSelectionRange()) #else @@ -88,9 +87,6 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description #endif #define FOREACH_QML_SEQUENCE_TYPE(F) \ - F(int, IntVector, QVector<int>, 0) \ - F(qreal, RealVector, QVector<qreal>, 0.0) \ - F(bool, BoolVector, QVector<bool>, false) \ F(int, IntStdVector, std::vector<int>, 0) \ F(qreal, RealStdVector, std::vector<qreal>, 0.0) \ F(bool, BoolStdVector, std::vector<bool>, false) \ @@ -99,10 +95,8 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description F(bool, Bool, QList<bool>, false) \ F(QString, String, QList<QString>, QString()) \ F(QString, QString, QStringList, QString()) \ - F(QString, StringVector, QVector<QString>, QString()) \ F(QString, StringStdVector, std::vector<QString>, QString()) \ F(QUrl, Url, QList<QUrl>, QUrl()) \ - F(QUrl, UrlVector, QVector<QUrl>, QUrl()) \ F(QUrl, UrlStdVector, std::vector<QUrl>, QUrl()) \ FOREACH_QML_SEQUENCE_TYPE_FOR_ITEMMODEL(F) @@ -377,24 +371,8 @@ public: ++arrayIndex; if (attrs) *attrs = QV4::Attr_Data; - - // TODO: Replace the container->at() below with operator[] in Qt6! - // TODO: But _not_ in Qt5! - // - // gcc 5.3.1 as shipped on RHEL 7.6 includes a copy of basic_string<char> - // into QtQml, when it sees a std::vector::at(). The basic_string symbols - // are publicly visible and preferred over the ones from libstdc++ when - // building user code. Therefore, removing this at() breaks binary - // compatibility. We _do_ want to remove it in Qt6, though. - // - // The exact mechanism is that at() checks its argument and can throw an - // out_of_range exception. The construction of this exception then triggers - // some string manipulation that uses the std::basic_string symbols. Clearly, - // this is a compiler bug. And clearly, we don't want the check as we can't - // catch the exception anyway. - if (pd) - pd->value = convertElementToValue(s->engine(), s->d()->container->at(index)); + pd->value = convertElementToValue(s->engine(), (*s->d()->container)[index]); return PropertyKey::fromArrayIndex(index); } @@ -672,12 +650,6 @@ void Heap::QQmlSequence<Container>::init(QObject *object, int propertyIndex, boo namespace QV4 { -typedef QQmlSequence<QVector<int> > QQmlIntVectorList; -DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntVectorList); -typedef QQmlSequence<QVector<qreal> > QQmlRealVectorList; -DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlRealVectorList); -typedef QQmlSequence<QVector<bool> > QQmlBoolVectorList; -DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlBoolVectorList); typedef QQmlSequence<std::vector<int> > QQmlIntStdVectorList; DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntStdVectorList); typedef QQmlSequence<std::vector<qreal> > QQmlRealStdVectorList; @@ -688,23 +660,17 @@ typedef QQmlSequence<QStringList> QQmlQStringList; DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQStringList); typedef QQmlSequence<QList<QString> > QQmlStringList; DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringList); -typedef QQmlSequence<QVector<QString> > QQmlStringVectorList; -DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringVectorList); typedef QQmlSequence<std::vector<QString> > QQmlStringStdVectorList; -DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringStdVectorList); typedef QQmlSequence<QList<int> > QQmlIntList; DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringStdVectorList); typedef QQmlSequence<QList<QUrl> > QQmlUrlList; DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlList); -typedef QQmlSequence<QVector<QUrl> > QQmlUrlVectorList; -DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlVectorList); typedef QQmlSequence<std::vector<QUrl> > QQmlUrlStdVectorList; DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlStdVectorList); #if QT_CONFIG(qml_itemmodel) typedef QQmlSequence<QModelIndexList> QQmlQModelIndexList; DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexList); -typedef QQmlSequence<QVector<QModelIndex> > QQmlQModelIndexVectorList; -DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexVectorList); typedef QQmlSequence<std::vector<QModelIndex> > QQmlQModelIndexStdVectorList; DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexStdVectorList); typedef QQmlSequence<QItemSelection> QQmlQItemSelectionRangeList; diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp index 8930c9a94d..7457e724e2 100644 --- a/src/qml/jsruntime/qv4sparsearray.cpp +++ b/src/qml/jsruntime/qv4sparsearray.cpp @@ -359,7 +359,7 @@ static inline void qMapDeallocate(SparseArrayNode *node, int alignment) SparseArrayNode *SparseArray::createNode(uint sl, SparseArrayNode *parent, bool left) { - SparseArrayNode *node = static_cast<SparseArrayNode *>(qMapAllocate(sizeof(SparseArrayNode), Q_ALIGNOF(SparseArrayNode))); + SparseArrayNode *node = static_cast<SparseArrayNode *>(qMapAllocate(sizeof(SparseArrayNode), alignof(SparseArrayNode))); Q_CHECK_PTR(node); node->p = (quintptr)parent; diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h index c1e50c8dcf..248fcdb02f 100644 --- a/src/qml/jsruntime/qv4sparsearray_p.h +++ b/src/qml/jsruntime/qv4sparsearray_p.h @@ -147,7 +147,7 @@ struct Q_QML_EXPORT SparseArray SparseArray(); ~SparseArray() { if (root()) - freeTree(header.left, Q_ALIGNOF(SparseArrayNode)); + freeTree(header.left, alignof(SparseArrayNode)); } SparseArray(const SparseArray &other); diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 223f4a4769..fc004a2ce0 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -91,18 +91,14 @@ bool String::virtualIsEqualTo(Managed *t, Managed *o) void Heap::String::init(const QString &t) { - Base::init(); - + QString mutableText(t); + StringOrSymbol::init(mutableText.data_ptr()); subtype = String::StringType_Unknown; - - text = const_cast<QString &>(t).data_ptr(); - text->ref.ref(); } void Heap::ComplexString::init(String *l, String *r) { - Base::init(); - + StringOrSymbol::init(); subtype = String::StringType_AddedString; left = l; @@ -125,7 +121,7 @@ void Heap::ComplexString::init(String *l, String *r) void Heap::ComplexString::init(Heap::String *ref, int from, int len) { Q_ASSERT(ref->length() >= from + len); - Base::init(); + StringOrSymbol::init(); subtype = String::StringType_SubString; @@ -136,11 +132,11 @@ void Heap::ComplexString::init(Heap::String *ref, int from, int len) void Heap::StringOrSymbol::destroy() { - if (text) { - internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar)); - if (!text->ref.deref()) - QStringData::deallocate(text); + if (subtype < Heap::String::StringType_AddedString) { + internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage( + qptrdiff(-text()->size) * qptrdiff(sizeof(QChar))); } + text().~QStringPrivate(); Base::destroy(); } @@ -164,27 +160,27 @@ uint String::toUInt(bool *ok) const void String::createPropertyKeyImpl() const { - if (!d()->text) + if (d()->subtype >= Heap::String::StringType_AddedString) d()->simplifyString(); - Q_ASSERT(d()->text); + Q_ASSERT(d()->subtype < Heap::String::StringType_AddedString); engine()->identifierTable->asPropertyKey(this); } void Heap::String::simplifyString() const { - Q_ASSERT(!text); + Q_ASSERT(subtype >= StringType_AddedString); int l = length(); QString result(l, Qt::Uninitialized); QChar *ch = const_cast<QChar *>(result.constData()); append(this, ch); - text = result.data_ptr(); - text->ref.ref(); + text() = result.data_ptr(); const ComplexString *cs = static_cast<const ComplexString *>(this); identifier = PropertyKey::invalid(); cs->left = cs->right = nullptr; - internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar)); + internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage( + qptrdiff(text().size) * qptrdiff(sizeof(QChar))); subtype = StringType_Unknown; } @@ -206,7 +202,7 @@ bool Heap::String::startsWithUpper() const offset = cs->from; } Q_ASSERT(str->subtype < Heap::String::StringType_Complex); - return str->text->size > offset && QChar::isUpper(str->text->data()[offset]); + return str->text().size > offset && QChar::isUpper(str->text().data()[offset]); } void Heap::String::append(const String *data, QChar *ch) @@ -228,21 +224,21 @@ void Heap::String::append(const String *data, QChar *ch) memcpy(ch, cs->left->toQString().constData() + cs->from, cs->len*sizeof(QChar)); ch += cs->len; } else { - memcpy(static_cast<void *>(ch), static_cast<const void *>(item->text->data()), item->text->size * sizeof(QChar)); - ch += item->text->size; + memcpy(static_cast<void *>(ch), item->text().data(), item->text().size * sizeof(QChar)); + ch += item->text().size; } } } void Heap::StringOrSymbol::createHashValue() const { - if (!text) { + if (subtype >= StringType_AddedString) { Q_ASSERT(internalClass->vtable->isString); static_cast<const Heap::String *>(this)->simplifyString(); } - Q_ASSERT(text); - const QChar *ch = reinterpret_cast<const QChar *>(text->data()); - const QChar *end = ch + text->size; + Q_ASSERT(subtype < StringType_AddedString); + const QChar *ch = reinterpret_cast<const QChar *>(text().data()); + const QChar *end = ch + text().size; stringHash = QV4::String::calculateHashValue(ch, end, &subtype); } diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 52fe09cd72..d5d11ef660 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -77,7 +77,18 @@ struct Q_QML_PRIVATE_EXPORT StringOrSymbol : Base StringType_Complex = StringType_AddedString }; - mutable QStringData *text; + void init() { + Base::init(); + new (&textStorage) QStringPrivate; + } + + void init(QStringPrivate text) + { + Base::init(); + new (&textStorage) QStringPrivate(std::move(text)); + } + + mutable std::aligned_storage<sizeof(QStringPrivate), alignof(QStringPrivate)>::type textStorage; mutable PropertyKey identifier; mutable uint subtype; mutable uint stringHash; @@ -85,12 +96,11 @@ struct Q_QML_PRIVATE_EXPORT StringOrSymbol : Base static void markObjects(Heap::Base *that, MarkStack *markStack); void destroy(); + QStringPrivate &text() const { return *reinterpret_cast<QStringPrivate *>(&textStorage); } + inline QString toQString() const { - if (!text) - return QString(); - QStringDataPtr ptr = { text }; - text->ref.ref(); - return QString(ptr); + QStringPrivate dd = text(); + return QString(std::move(dd)); } void createHashValue() const; inline unsigned hashValue() const { @@ -113,14 +123,12 @@ struct Q_QML_PRIVATE_EXPORT String : StringOrSymbol { void simplifyString() const; int length() const; std::size_t retainedTextSize() const { - return subtype >= StringType_Complex ? 0 : (std::size_t(text->size) * sizeof(QChar)); + return subtype >= StringType_Complex ? 0 : (std::size_t(text().size) * sizeof(QChar)); } inline QString toQString() const { if (subtype >= StringType_Complex) simplifyString(); - QStringDataPtr ptr = { text }; - text->ref.ref(); - return QString(ptr); + return StringOrSymbol::toQString(); } inline bool isEqualTo(const String *other) const { if (this == other) @@ -158,7 +166,7 @@ Q_STATIC_ASSERT(std::is_trivial< ComplexString >::value); inline int String::length() const { - return text ? text->size : static_cast<const ComplexString *>(this)->len; + return subtype < StringType_AddedString ? text().size : static_cast<const ComplexString *>(this)->len; } } @@ -252,7 +260,7 @@ public: } if (subtype) - *subtype = (charToUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular; + *subtype = (ch != end && charToUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular; return h; } }; diff --git a/src/qml/jsruntime/qv4symbol.cpp b/src/qml/jsruntime/qv4symbol.cpp index 004a9938e2..be6d821c14 100644 --- a/src/qml/jsruntime/qv4symbol.cpp +++ b/src/qml/jsruntime/qv4symbol.cpp @@ -50,10 +50,9 @@ DEFINE_OBJECT_VTABLE(SymbolObject); void Heap::Symbol::init(const QString &s) { Q_ASSERT(s.at(0) == QLatin1Char('@')); - identifier = PropertyKey::fromStringOrSymbol(this); QString desc(s); - text = desc.data_ptr(); - text->ref.ref(); + StringOrSymbol::init(desc.data_ptr()); + identifier = PropertyKey::fromStringOrSymbol(this); } void Heap::SymbolCtor::init(QV4::ExecutionContext *scope) diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index d03b67aa27..f425c6c87f 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -338,8 +338,8 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f, array->d()->byteLength = destByteLength; array->d()->byteOffset = 0; - const char *src = buffer->d()->data->data() + typedArray->d()->byteOffset; - char *dest = newBuffer->d()->data->data(); + const char *src = buffer->d()->data()->data() + typedArray->d()->byteOffset; + char *dest = newBuffer->d()->data()->data(); // check if src and new type have the same size. In that case we can simply memcpy the data if (srcElementSize == destElementSize) { @@ -420,7 +420,7 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f, array->d()->byteOffset = 0; uint idx = 0; - char *b = newBuffer->d()->data->data(); + char *b = newBuffer->d()->data()->data(); ScopedValue val(scope); while (idx < l) { val = o->get(idx); @@ -480,7 +480,7 @@ ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Val if (hasProperty) *hasProperty = true; - return a->d()->type->read(a->d()->buffer->data->data() + byteOffset); + return a->d()->type->read(a->d()->buffer->data()->data() + byteOffset); } bool TypedArray::virtualHasProperty(const Managed *m, PropertyKey id) @@ -538,7 +538,7 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu Value v = Value::fromReturnedValue(value.convertedToNumber()); if (scope.hasException() || a->d()->buffer->isDetachedBuffer()) return scope.engine->throwTypeError(); - a->d()->type->write(a->d()->buffer->data->data() + byteOffset, v); + a->d()->type->write(a->d()->buffer->data()->data() + byteOffset, v); return true; } @@ -569,7 +569,7 @@ bool TypedArray::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Prop uint bytesPerElement = a->d()->type->bytesPerElement; uint byteOffset = a->d()->byteOffset + index * bytesPerElement; Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength()); - a->d()->type->write(a->d()->buffer->data->data() + byteOffset, v); + a->d()->type->write(a->d()->buffer->data()->data() + byteOffset, v); } return true; } @@ -713,7 +713,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_copyWithin(const FunctionObje if (from != to) { int elementSize = O->d()->type->bytesPerElement; - char *data = O->d()->buffer->data->data() + O->d()->byteOffset; + char *data = O->d()->buffer->data()->data() + O->d()->byteOffset; memmove(data + to*elementSize, data + from*elementSize, count*elementSize); } @@ -749,7 +749,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_every(const FunctionObject *b ScopedValue r(scope); Value *arguments = scope.alloc(3); - const char *data = v->d()->buffer->data->data(); + const char *data = v->d()->buffer->data()->data(); uint bytesPerElement = v->d()->type->bytesPerElement; uint byteOffset = v->d()->byteOffset; @@ -803,7 +803,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_fill(const FunctionObject *b, if (scope.hasException() || v->d()->buffer->isDetachedBuffer()) return scope.engine->throwTypeError(); - char *data = v->d()->buffer->data->data(); + char *data = v->d()->buffer->data()->data(); uint bytesPerElement = v->d()->type->bytesPerElement; uint byteOffset = v->d()->byteOffset; @@ -1422,7 +1422,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b, uint idx = 0; if (buffer->isDetachedBuffer()) return scope.engine->throwTypeError(); - char *b = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize; + char *b = buffer->d()->data()->data() + a->d()->byteOffset + offset*elementSize; ScopedValue val(scope); while (idx < l) { val = o->get(idx); @@ -1451,8 +1451,8 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b, if (offset > aLength || l > aLength - offset) RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"))); - char *dest = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize; - const char *src = srcBuffer->d()->data->data() + srcTypedArray->d()->byteOffset; + char *dest = buffer->d()->data()->data() + a->d()->byteOffset + offset*elementSize; + const char *src = srcBuffer->d()->data()->data() + srcTypedArray->d()->byteOffset; if (srcTypedArray->d()->type == a->d()->type) { // same type of typed arrays, use memmove (as srcbuffer and buffer could be the same) memmove(dest, src, srcTypedArray->d()->byteLength); diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h index 65656e3389..e590083bc3 100644 --- a/src/qml/jsruntime/qv4typedarray_p.h +++ b/src/qml/jsruntime/qv4typedarray_p.h @@ -156,8 +156,8 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object return d()->byteLength/d()->type->bytesPerElement; } - QTypedArrayData<char> *arrayData() { - return d()->buffer->data; + QArrayDataPointer<char> *arrayData() { + return &d()->buffer->data(); } Heap::TypedArray::Type arrayType() const { diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index f6d8bcf9c3..a246dfba7a 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -836,7 +836,15 @@ UiImport: UiImportHead Semicolon; UiVersionSpecifier: T_VERSION_NUMBER T_DOT T_VERSION_NUMBER; /. case $rule_number: { - auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval, sym(3).dval); + const int major = sym(1).dval; + const int minor = sym(3).dval; + if (!QTypeRevision::isValidSegment(major) || !QTypeRevision::isValidSegment(minor)) { + diagnostic_messages.append( + compileError(loc(1), + QLatin1String("Invalid version. Version numbers must be >= 0 and < 255."))); + return false; + } + auto version = new (pool) AST::UiVersionSpecifier(major, minor); version->majorToken = loc(1); version->minorToken = loc(3); sym(1).UiVersionSpecifier = version; @@ -847,6 +855,13 @@ UiVersionSpecifier: T_VERSION_NUMBER T_DOT T_VERSION_NUMBER; UiVersionSpecifier: T_VERSION_NUMBER; /. case $rule_number: { + const int major = sym(1).dval; + if (!QTypeRevision::isValidSegment(major)) { + diagnostic_messages.append( + compileError(loc(1), + QLatin1String("Invalid major version. Version numbers must be >= 0 and < 255."))); + return false; + } auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval, 0); version->majorToken = loc(1); sym(1).UiVersionSpecifier = version; diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index 053e9fd2d3..b92a635228 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -57,6 +57,7 @@ #include <private/qqmljsmemorypool_p.h> #include <QtCore/qstring.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -646,7 +647,10 @@ class QML_PARSER_EXPORT UiVersionSpecifier : public Node public: QQMLJS_DECLARE_AST_NODE(UiVersionSpecifier) - UiVersionSpecifier(int majorum, int minorum) : majorVersion(majorum), minorVersion(minorum) { kind = K; } + UiVersionSpecifier(int majorum, int minorum) : version(QTypeRevision::fromVersion(majorum, minorum)) + { + kind = K; + } void accept0(BaseVisitor *visitor) override; @@ -658,8 +662,7 @@ public: } // attributes: - int majorVersion; - int minorVersion; + QTypeRevision version; SourceLocation majorToken; SourceLocation minorToken; }; diff --git a/src/qml/qml.pro b/src/qml/qml.pro index e39a8319b6..7bb3547ee9 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -71,7 +71,7 @@ MODULE_PLUGIN_TYPES = \ QMLTYPES_FILENAME = plugins.qmltypes QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/QtQml QML_IMPORT_NAME = QtQml -IMPORT_VERSION = 2.$$QT_MINOR_VERSION +QML_IMPORT_VERSION = $$QT_VERSION CONFIG += qmltypes install_qmltypes install_metatypes load(qt_module) diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp index 6c58ab87f4..4553fa9359 100644 --- a/src/qml/qml/ftw/qhashedstring.cpp +++ b/src/qml/qml/ftw/qhashedstring.cpp @@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE // Copy of QString's qMemCompare bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length) { - Q_ASSERT(lhs && rhs); + Q_ASSERT((lhs && rhs) || !length); const quint16 *a = (const quint16 *)lhs; const quint16 *b = (const quint16 *)rhs; diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp index 7d2ad354d6..0f7726ef65 100644 --- a/src/qml/qml/ftw/qqmlthread.cpp +++ b/src/qml/qml/ftw/qqmlthread.cpp @@ -188,13 +188,7 @@ void QQmlThreadPrivate::threadEvent() lock(); for (;;) { - if (m_shutdown) { - quit(); - wakeOne(); - unlock(); - - return; - } else if (!threadList.isEmpty()) { + if (!threadList.isEmpty()) { m_threadProcessing = true; QQmlThread::Message *message = threadList.first(); @@ -206,6 +200,12 @@ void QQmlThreadPrivate::threadEvent() lock(); delete threadList.takeFirst(); + } else if (m_shutdown) { + quit(); + wakeOne(); + unlock(); + + return; } else { wakeOne(); @@ -242,6 +242,7 @@ void QQmlThread::shutdown() d->lock(); Q_ASSERT(!d->m_shutdown); + d->m_shutdown = true; for (;;) { if (d->mainSync || !d->mainList.isEmpty()) { d->unlock(); @@ -254,13 +255,10 @@ void QQmlThread::shutdown() } } - d->m_shutdown = true; - if (QCoreApplication::closingDown()) { + if (QCoreApplication::closingDown()) d->quit(); - } else { + else d->triggerThreadEvent(); - d->wait(); - } d->unlock(); d->QThread::wait(); diff --git a/src/qml/qml/ftw/qstringhash_p.h b/src/qml/qml/ftw/qstringhash_p.h index f9435b4919..fc73fdfa50 100644 --- a/src/qml/qml/ftw/qstringhash_p.h +++ b/src/qml/qml/ftw/qstringhash_p.h @@ -54,25 +54,31 @@ #include <private/qhashedstring_p.h> #include <private/qprimefornumbits_p.h> -#include <QtCore/qglobal.h> +#include <QtCore/qbytearray.h> +#include <QtCore/qstring.h> QT_BEGIN_NAMESPACE +static inline QString::DataPointer &mutableStringData(const QHashedString &key) +{ + return const_cast<QHashedString &>(key).data_ptr(); +} + class QStringHashData; class QStringHashNode { public: QStringHashNode() - : ckey(nullptr) { } QStringHashNode(const QHashedString &key) : length(key.length()), hash(key.hash()), symbolId(0) + , arrayData(mutableStringData(key).d_ptr()) + , strData(mutableStringData(key).data()) { - strData = const_cast<QHashedString &>(key).data_ptr(); + arrayData->ref(); setQString(true); - strData->ref.ref(); } QStringHashNode(const QHashedCStringRef &key) @@ -81,15 +87,21 @@ public: } QStringHashNode(const QStringHashNode &o) - : length(o.length), hash(o.hash), symbolId(o.symbolId), ckey(o.ckey) + : length(o.length), hash(o.hash), symbolId(o.symbolId), arrayData(o.arrayData) { setQString(o.isQString()); - if (isQString()) { strData->ref.ref(); } + if (isQString()) { + strData = o.strData; + arrayData->ref(); + } else { + ckey = o.ckey; + } } ~QStringHashNode() { - if (isQString()) { if (!strData->ref.deref()) free(strData); } + if (isQString() && !arrayData->deref()) + QTypedArrayData<ushort>::deallocate(arrayData); } QFlagPointer<QStringHashNode> next; @@ -98,15 +110,18 @@ public: quint32 hash = 0; quint32 symbolId = 0; + QTypedArrayData<ushort> *arrayData = nullptr; union { - const char *ckey; - QStringData *strData; + const char *ckey = nullptr; + ushort *strData; }; inline QHashedString key() const { - if (isQString()) - return QHashedString(QString((QChar *)strData->data(), length), hash); + if (isQString()) { + arrayData->ref(); + return QHashedString(QString(QStringPrivate(arrayData, strData, length)), hash); + } return QHashedString(QString::fromLatin1(ckey, length), hash); } @@ -114,16 +129,14 @@ public: bool isQString() const { return next.flag(); } void setQString(bool v) { if (v) next.setFlag(); else next.clearFlag(); } - inline char *cStrData() const { return (char *)ckey; } - inline quint16 *utf16Data() const { return (quint16 *)strData->data(); } + inline qsizetype size() const { return length; } + inline const char *cStrData() const { return ckey; } + inline const quint16 *utf16Data() const { return strData; } inline bool equals(const QV4::Value &string) const { QString s = string.toQStringNoThrow(); if (isQString()) { - QStringDataPtr dd; - dd.ptr = strData; - strData->ref.ref(); - return QString(dd) == s; + return QStringView(utf16Data(), length) == s; } else { return QLatin1String(cStrData(), length) == s; } @@ -133,10 +146,7 @@ public: if (length != string->d()->length() || hash != string->hashValue()) return false; if (isQString()) { - QStringDataPtr dd; - dd.ptr = strData; - strData->ref.ref(); - return QString(dd) == string->toQString(); + return QStringView(utf16Data(), length) == string->toQString(); } else { return QLatin1String(cStrData(), length) == string->toQString(); } @@ -510,8 +520,9 @@ void QStringHash<T>::initializeNode(Node *node, const QHashedString &key) { node->length = key.length(); node->hash = key.hash(); - node->strData = const_cast<QHashedString &>(key).data_ptr(); - node->strData->ref.ref(); + node->arrayData = mutableStringData(key).d_ptr(); + node->strData = mutableStringData(key).data(); + node->arrayData->ref(); node->setQString(true); } @@ -547,10 +558,11 @@ typename QStringHash<T>::Node *QStringHash<T>::takeNode(const Node &o) Node *rv = nodePool->nodes + nodePool->used++; rv->length = o.length; rv->hash = o.hash; + rv->arrayData = o.arrayData; if (o.isQString()) { rv->strData = o.strData; - rv->strData->ref.ref(); rv->setQString(true); + rv->arrayData->ref(); } else { rv->ckey = o.ckey; } diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index fe4e2f4e55..ea6f15e9c2 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -62,19 +62,20 @@ void qmlClearTypeRegistrations() // Declared in qqml.h //From qqml.h bool qmlProtectModule(const char *uri, int majVersion) { - return QQmlMetaType::protectModule(QString::fromUtf8(uri), majVersion); + return QQmlMetaType::protectModule(QString::fromUtf8(uri), + QTypeRevision::fromMajorVersion(majVersion)); } //From qqml.h void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor) { - QQmlMetaType::registerModule(uri, versionMajor, versionMinor); + QQmlMetaType::registerModule(uri, QTypeRevision::fromVersion(versionMajor, versionMinor)); } //From qqml.h int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - return QQmlMetaType::typeId(uri, versionMajor, versionMinor, qmlName); + return QQmlMetaType::typeId(uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName); } // From qqmlprivate.h @@ -104,9 +105,9 @@ QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJS return m_object; }; -static QVector<int> availableRevisions(const QMetaObject *metaObject) +static QVector<QTypeRevision> availableRevisions(const QMetaObject *metaObject) { - QVector<int> revisions; + QVector<QTypeRevision> revisions; if (!metaObject) return revisions; const int propertyOffset = metaObject->propertyOffset(); @@ -115,7 +116,7 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject) propertyIndex < propertyEnd; ++propertyIndex) { const QMetaProperty property = metaObject->property(propertyIndex); if (int revision = property.revision()) - revisions.append(revision); + revisions.append(QTypeRevision::fromEncodedVersion(revision)); } const int methodOffset = metaObject->methodOffset(); const int methodCount = metaObject->methodCount(); @@ -123,7 +124,7 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject) methodIndex < methodEnd; ++methodIndex) { const QMetaMethod method = metaObject->method(methodIndex); if (int revision = method.revision()) - revisions.append(revision); + revisions.append(QTypeRevision::fromEncodedVersion(revision)); } // Need to also check parent meta objects, as their revisions are inherited. @@ -133,6 +134,54 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject) return revisions; } +template<typename Registration> +void assignVersions(Registration *registration, QTypeRevision revision, + QTypeRevision defaultVersion) +{ + const quint8 majorVersion = revision.hasMajorVersion() ? revision.majorVersion() + : defaultVersion.majorVersion(); + registration->version = revision.hasMinorVersion() + ? QTypeRevision::fromVersion(majorVersion, revision.minorVersion()) + : QTypeRevision::fromMajorVersion(majorVersion); + registration->revision = revision; +} + +static QVector<QTypeRevision> prepareRevisions(const QMetaObject *metaObject, QTypeRevision added) +{ + auto revisions = availableRevisions(metaObject); + revisions.append(added); + return revisions; +} + +static void uniqueRevisions(QVector<QTypeRevision> *revisions, QTypeRevision defaultVersion, + QTypeRevision added) +{ + bool revisionsHaveMajorVersions = false; + for (QTypeRevision revision : QVector<QTypeRevision>(*revisions)) { // yes, copy + // allow any minor version for each explicitly specified past major one + if (revision.hasMajorVersion()) { + revisionsHaveMajorVersions = true; + if (revision.majorVersion() < defaultVersion.majorVersion()) + revisions->append(QTypeRevision::fromVersion(revision.majorVersion(), 254)); + } + } + + if (revisionsHaveMajorVersions) { + if (!added.hasMajorVersion()) { + // If added in unspecified major version, assume default one. + revisions->append(QTypeRevision::fromVersion(defaultVersion.majorVersion(), + added.minorVersion())); + } else if (added.majorVersion() < defaultVersion.majorVersion()) { + // If added in past major version, add .0 of default version. + revisions->append(QTypeRevision::fromVersion(defaultVersion.majorVersion(), 0)); + } + } + + std::sort(revisions->begin(), revisions->end()); + const auto it = std::unique(revisions->begin(), revisions->end()); + revisions->erase(it, revisions->end()); +} + /* This method is "over generalized" to allow us to (potentially) register more types of things in the future without adding exported symbols. @@ -164,8 +213,7 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) nullptr, noCreateReason, type.uri, - type.versionMajor, - -1, + type.version, nullptr, type.metaObject, type.attachedPropertiesFunction, @@ -176,28 +224,26 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) type.extensionObjectCreate, type.extensionMetaObject, nullptr, - -1 + QTypeRevision() }; - const int added = intClassInfo(type.classInfoMetaObject, "QML.AddedInMinorVersion", 0); - const int removed = intClassInfo(type.classInfoMetaObject, "QML.RemovedInMinorVersion", -1); + const QTypeRevision added = revisionClassInfo( + type.classInfoMetaObject, "QML.AddedInVersion", + QTypeRevision::fromMinorVersion(0)); + const QTypeRevision removed = revisionClassInfo( + type.classInfoMetaObject, "QML.RemovedInVersion"); - auto revisions = availableRevisions(type.metaObject); - revisions.append(qMax(added, 0)); + auto revisions = prepareRevisions(type.metaObject, added); if (type.attachedPropertiesMetaObject) revisions += availableRevisions(type.attachedPropertiesMetaObject); + uniqueRevisions(&revisions, type.version, added); - std::sort(revisions.begin(), revisions.end()); - const auto it = std::unique(revisions.begin(), revisions.end()); - revisions.erase(it, revisions.end()); - - const bool typeWasRemoved = removed >= added; - for (int revision : revisions) { + for (QTypeRevision revision : revisions) { if (revision < added) continue; // When removed, we still add revisions, but anonymous ones - if (typeWasRemoved && revision >= removed) { + if (removed.isValid() && !(revision < removed)) { revisionRegistration.elementName = nullptr; revisionRegistration.create = nullptr; } else { @@ -205,11 +251,8 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) revisionRegistration.create = creatable ? type.create : nullptr; } - // Equivalent of qmlRegisterRevision<T, revision>(...) - revisionRegistration.versionMinor = revision; - revisionRegistration.revision = revision; + assignVersions(&revisionRegistration, revision, type.version); revisionRegistration.customParser = type.customParserFactory(); - qmlregister(TypeRegistration, &revisionRegistration); } break; @@ -221,36 +264,33 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) RegisterSingletonType revisionRegistration = { QmlCurrentSingletonTypeRegistrationVersion, type.uri, - type.versionMajor, - -1, + type.version, elementName, type.scriptApi, nullptr, type.instanceMetaObject, type.typeId, - -1, + QTypeRevision(), type.generalizedQobjectApi }; - const int added = intClassInfo(type.classInfoMetaObject, "QML.AddedInMinorVersion", 0); - const int removed = intClassInfo(type.classInfoMetaObject, "QML.RemovedInMinorVersion", -1); + const QTypeRevision added = revisionClassInfo( + type.classInfoMetaObject, "QML.AddedInVersion", + QTypeRevision::fromMinorVersion(0)); + const QTypeRevision removed = revisionClassInfo( + type.classInfoMetaObject, "QML.RemovedInVersion"); - auto revisions = availableRevisions(type.instanceMetaObject); - revisions.append(qMax(added, 0)); + auto revisions = prepareRevisions(type.instanceMetaObject, added); + uniqueRevisions(&revisions, type.version, added); - std::sort(revisions.begin(), revisions.end()); - const auto it = std::unique(revisions.begin(), revisions.end()); - revisions.erase(it, revisions.end()); - - const bool typeWasRemoved = removed >= added; - for (int revision : qAsConst(revisions)) { + for (QTypeRevision revision : qAsConst(revisions)) { if (revision < added) continue; // When removed, we still add revisions, but anonymous ones - if (typeWasRemoved && revision >= removed) { + if (removed.isValid() && !(revision < removed)) { revisionRegistration.typeName = nullptr; revisionRegistration.scriptApi = nullptr; revisionRegistration.generalizedQobjectApi = nullptr; @@ -260,10 +300,7 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) revisionRegistration.generalizedQobjectApi = type.generalizedQobjectApi; } - // Equivalent of qmlRegisterRevision<T, revision>(...) - revisionRegistration.versionMinor = revision; - revisionRegistration.revision = revision; - + assignVersions(&revisionRegistration, revision, type.version); qmlregister(SingletonRegistration, &revisionRegistration); } break; @@ -339,7 +376,7 @@ namespace QQmlPrivate { nullptr, uri, - versionMajor, + QTypeRevision::fromMajorVersion(versionMajor), &QQmlTypeNotAvailable::staticMetaObject, classInfoMetaObject, diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index ef7fdd1945..b9445e48a8 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -44,6 +44,7 @@ #include <QtCore/qbytearray.h> #include <QtCore/qmetaobject.h> +#include <QtCore/qversionnumber.h> #define QML_VERSION 0x020000 #define QML_VERSION_STR "2.0" @@ -88,10 +89,16 @@ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor); #define QML_ADDED_IN_MINOR_VERSION(VERSION) \ - Q_CLASSINFO("QML.AddedInMinorVersion", #VERSION) + Q_CLASSINFO("QML.AddedInVersion", Q_REVISION(VERSION)) + +#define QML_ADDED_IN_VERSION(MAJOR, MINOR) \ + Q_CLASSINFO("QML.AddedInVersion", Q_REVISION(MAJOR, MINOR)) #define QML_REMOVED_IN_MINOR_VERSION(VERSION) \ - Q_CLASSINFO("QML.RemovedInMinorVersion", #VERSION) + Q_CLASSINFO("QML.RemovedInVersion", Q_REVISION(VERSION)) + +#define QML_REMOVED_IN_VERSION(MAJOR, MINOR) \ + Q_CLASSINFO("QML.RemovedInVersion", Q_REVISION(MAJOR, MINOR)) #define QML_ATTACHED(ATTACHED_TYPE) \ Q_CLASSINFO("QML.Attached", #ATTACHED_TYPE) \ @@ -160,7 +167,7 @@ int qmlRegisterAnonymousType(const char *uri, int versionMajor) nullptr, QString(), - uri, versionMajor, 0, nullptr, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, 0), nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -172,7 +179,7 @@ int qmlRegisterAnonymousType(const char *uri, int versionMajor) nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -203,7 +210,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -215,7 +222,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -235,7 +242,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -247,7 +254,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin nullptr, nullptr, nullptr, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -274,7 +281,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, attached, attachedMetaObject, @@ -286,7 +293,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::createParent<E>, &E::staticMetaObject, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -313,7 +320,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, attached, attachedMetaObject, @@ -325,7 +332,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::createParent<E>, &E::staticMetaObject, nullptr, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -346,7 +353,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -358,7 +365,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -377,7 +384,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -389,7 +396,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c nullptr, nullptr, nullptr, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -408,7 +415,7 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, nullptr, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -420,7 +427,7 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) nullptr, nullptr, nullptr, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -440,7 +447,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor) nullptr, QString(), - uri, versionMajor, 0, nullptr, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, 0), nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -452,7 +459,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor) QQmlPrivate::createParent<E>, &E::staticMetaObject, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -488,7 +495,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, attached, attachedMetaObject, @@ -500,7 +507,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, QQmlPrivate::createParent<E>, &E::staticMetaObject, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -524,7 +531,7 @@ int qmlRegisterInterface(const char *typeName) qobject_interface_iid<T *>(), "", - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::InterfaceRegistration, &qmlInterface); @@ -543,7 +550,7 @@ int qmlRegisterInterface(const char *uri, int versionMajor) qobject_interface_iid<T *>(), uri, - versionMajor + QTypeRevision::fromVersion(versionMajor, 0) }; return QQmlPrivate::qmlregister(QQmlPrivate::InterfaceRegistration, &qmlInterface); @@ -563,7 +570,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -575,7 +582,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, nullptr, nullptr, parser, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -595,7 +602,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc<T>(), QQmlPrivate::attachedPropertiesMetaObject<T>(), @@ -607,7 +614,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, nullptr, nullptr, parser, - metaObjectRevision + QTypeRevision::fromMinorVersion(metaObjectRevision) }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -634,7 +641,7 @@ int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int version sizeof(T), QQmlPrivate::createInto<T>, QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, attached, attachedMetaObject, @@ -646,7 +653,7 @@ int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int version QQmlPrivate::createParent<E>, &E::staticMetaObject, parser, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -709,9 +716,9 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi QQmlPrivate::RegisterSingletonType api = { 0, - uri, versionMajor, versionMinor, typeName, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), typeName, - callback, nullptr, nullptr, 0, 0, {} + callback, nullptr, nullptr, 0, QTypeRevision::zero(), {} }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -727,9 +734,10 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi QQmlPrivate::RegisterSingletonType api = { QmlCurrentSingletonTypeRegistrationVersion, - uri, versionMajor, versionMinor, typeName, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), typeName, - nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, callback + nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), + QTypeRevision::zero(), callback }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -746,9 +754,10 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi QQmlPrivate::RegisterSingletonType api = { QmlCurrentSingletonTypeRegistrationVersion, - uri, versionMajor, versionMinor, typeName, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), typeName, - nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, callback + nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), + QTypeRevision::zero(), callback }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -774,8 +783,7 @@ inline int qmlRegisterSingletonType(const QUrl &url, const char *uri, int versio QQmlPrivate::RegisterCompositeSingletonType type = { url, uri, - versionMajor, - versionMinor, + QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName }; @@ -793,8 +801,7 @@ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, i QQmlPrivate::RegisterCompositeType type = { url, uri, - versionMajor, - versionMinor, + QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName }; diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index cb5d5a787c..9a4ea711f3 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -71,6 +71,7 @@ class Q_QML_EXPORT QQmlComponent : public QObject Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QUrl url READ url CONSTANT) QML_NAMED_ELEMENT(Component) + QML_ADDED_IN_VERSION(2, 0) QML_ATTACHED(QQmlComponentAttached) Q_CLASSINFO("QML.Builtin", "QML") diff --git a/src/qml/qml/qqmlcomponentattached_p.h b/src/qml/qml/qqmlcomponentattached_p.h index 8ecd9da17d..eb6d35652b 100644 --- a/src/qml/qml/qqmlcomponentattached_p.h +++ b/src/qml/qml/qqmlcomponentattached_p.h @@ -66,6 +66,7 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentAttached : public QObject // when registering QQmlComponent, but we cannot #include it from qqmlcomponent.h. Therefore we // force an anonymous type registration here. QML_ANONYMOUS + QML_ADDED_IN_VERSION(2, 0) public: QQmlComponentAttached(QObject *parent = nullptr); ~QQmlComponentAttached(); diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index ecd5020482..02c2b87a6e 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -108,12 +108,6 @@ void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const exceptions << error; } -struct StaticQtMetaObject : public QObject -{ - static const QMetaObject *get() - { return &staticQtMetaObject; } -}; - /*! If \a script is a simple enumeration expression (eg. Text.AlignLeft), returns the integer equivalent (eg. 1), and sets \a ok to true. @@ -149,12 +143,12 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const if (imports.isT1()) { QQmlImportNamespace *ns = nullptr; - if (!imports.asT1()->resolveType(scope, &type, nullptr, nullptr, &ns)) + 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, nullptr)) { + &type, nullptr, nullptr)) { return -1; } } @@ -183,7 +177,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const } QByteArray enumValue = script.mid(dot + 1); - const QMetaObject *mo = StaticQtMetaObject::get(); + const QMetaObject *mo = &Qt::staticMetaObject; int i = mo->enumeratorCount(); while (i--) { int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok); diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index f97612ab75..c8b41d3684 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -118,7 +118,7 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, nullptr, reason, - uri, versionMajor, versionMinor, qmlName, &staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &staticMetaObject, QQmlAttachedPropertiesFunc(), nullptr, @@ -130,7 +130,7 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); @@ -195,35 +195,6 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, bool QQmlEnginePrivate::qml_debugging_enabled = false; bool QQmlEnginePrivate::s_designerMode = false; -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -void QQmlEnginePrivate::registerQuickTypes() -{ - // Don't add anything here. These are only for backwards compatibility. - // Also, don't use qmlRegisterTypesAndRevisions as that will auto-add future revisions. - - const char uri[] = "QtQuick"; - - qmlRegisterType<QQmlComponent>(uri, 2, 0, "Component"); - qmlRegisterType<QObject>(uri, 2, 0, "QtObject"); - qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding"); - qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding"); - qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser); - - // Connections revision 3 was added in QtQml 2.3, but only in QtQuick 2.7. - qmlRegisterCustomType<QQmlConnections, 3>(uri, 2, 7, "Connections", new QQmlConnectionsParser); - -#if QT_CONFIG(qml_animation) - qmlRegisterType<QQmlTimer>(uri, 2, 0,"Timer"); -#endif - qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory"); - qmlRegisterType<QQmlLoggingCategory, 12>(uri, 2, 12, "LoggingCategory"); -#if QT_CONFIG(qml_locale) - // Locale was added in QtQuick 2.0 and in QtQml 2.2 - qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()")); -#endif -} -#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - bool QQmlEnginePrivate::designerMode() { return s_designerMode; @@ -2269,7 +2240,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths) bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors) { Q_D(QQmlEngine); - return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), -1, errors); + return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), QTypeRevision(), errors); } #endif @@ -2326,17 +2297,6 @@ QString QQmlEngine::offlineStorageDatabaseFilePath(const QString &databaseName) return d->offlineStorageDatabaseDirectory() + QLatin1String(md5.result().toHex()); } -// #### Qt 6: Remove this function, it exists only for binary compatibility. -/*! - * \internal - */ -bool QQmlEngine::addNamedBundle(const QString &name, const QString &fileName) -{ - Q_UNUSED(name) - Q_UNUSED(fileName) - return false; -} - QString QQmlEnginePrivate::offlineStorageDatabaseDirectory() const { Q_Q(const QQmlEngine); @@ -2390,58 +2350,91 @@ static QQmlPropertyCache *propertyCacheForPotentialInlineComponentType(int t, co return (*iter)->rootPropertyCache().data(); } +/*! + * \internal + * + * Look up by type's baseMetaObject. + */ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const { - Locker locker(this); - auto iter = m_compositeTypes.constFind(t); - if (iter != m_compositeTypes.cend()) { - return propertyCacheForPotentialInlineComponentType(t, iter); - } else { - QQmlType type = QQmlMetaType::qmlType(t); - return QQmlMetaObject(type.baseMetaObject()); - } + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return QQmlMetaObject(composite); + + QQmlType type = QQmlMetaType::qmlType(t); + return QQmlMetaObject(type.baseMetaObject()); } +/*! + * \internal + * + * Look up by type's metaObject. + */ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const { - Locker locker(this); - auto iter = m_compositeTypes.constFind(t); - if (iter != m_compositeTypes.cend()) { - return propertyCacheForPotentialInlineComponentType(t, iter); - } else { - QQmlType type = QQmlMetaType::qmlType(t); - return QQmlMetaObject(type.metaObject()); - } + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return QQmlMetaObject(composite); + + QQmlType type = QQmlMetaType::qmlType(t); + return QQmlMetaObject(type.metaObject()); } +/*! + * \internal + * + * Look up by type's metaObject and version. + */ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t) { - Locker locker(this); - auto iter = m_compositeTypes.constFind(t); - if (iter != m_compositeTypes.cend()) { - return propertyCacheForPotentialInlineComponentType(t, iter); - } else { - QQmlType type = QQmlMetaType::qmlType(t); - locker.unlock(); - return type.isValid() ? cache(type.metaObject()) : nullptr; - } + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return composite; + + QQmlType type = QQmlMetaType::qmlType(t); + return type.isValid() ? cache(type.metaObject(), type.version()) : nullptr; +} + +/*! + * \internal + * + * Look up by type's baseMetaObject and unspecified/any version. + * TODO: Is this correct? Passing a plain QTypeRevision() rather than QTypeRevision::zero() or + * the actual type's version seems strange. The behavior has been in place for a while. + */ +QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t) +{ + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return composite; + + QQmlType type = QQmlMetaType::qmlType(t); + return type.isValid() ? cache(type.baseMetaObject(), QTypeRevision()) : nullptr; } -QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, int minorVersion) +/*! + * \internal + * + * Look up by QQmlType and version. We only fall back to lookup by metaobject if the type + * has no revisiononed attributes here. Unspecified versions are interpreted as "any". + */ +QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, QTypeRevision version) +{ + if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t)) + return composite; + + QQmlType type = QQmlMetaType::qmlType(t); + if (!type.isValid()) + return nullptr; + + return type.containsRevisionedAttributes() + ? QQmlMetaType::propertyCache(type, version) + : cache(type.metaObject(), version); +} + +QQmlPropertyCache *QQmlEnginePrivate::findPropertyCacheInCompositeTypes(int t) const { Locker locker(this); auto iter = m_compositeTypes.constFind(t); - if (iter != m_compositeTypes.cend()) { - return propertyCacheForPotentialInlineComponentType(t, iter); - } else { - QQmlType type = QQmlMetaType::qmlType(t); - locker.unlock(); - - if (minorVersion >= 0) - return type.isValid() ? cache(type, minorVersion) : nullptr; - else - return type.isValid() ? cache(type.baseMetaObject()) : nullptr; - } + return (iter == m_compositeTypes.constEnd()) + ? nullptr + : propertyCacheForPotentialInlineComponentType(t, iter); } void QQmlEnginePrivate::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index 31fe3a1849..a686d8a1d9 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -112,7 +112,9 @@ public: void setPluginPathList(const QStringList &paths); void addPluginPath(const QString& dir); - bool addNamedBundle(const QString &name, const QString &fileName); +#if QT_DEPRECATED_SINCE(6, 0) + QT_DEPRECATED bool addNamedBundle(const QString &, const QString &) { return false; } +#endif #if QT_CONFIG(library) bool importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors); diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 263c69e2d8..424335b61a 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -105,6 +105,7 @@ struct QObjectForeign { Q_GADGET QML_FOREIGN(QObject) QML_NAMED_ELEMENT(QtObject) + QML_ADDED_IN_VERSION(2, 0) Q_CLASSINFO("QML.Root", "QML") }; @@ -216,7 +217,7 @@ public: QString offlineStorageDatabaseDirectory() const; // These methods may be called from the loader thread - inline QQmlPropertyCache *cache(const QQmlType &, int); + inline QQmlPropertyCache *cache(const QQmlType &, QTypeRevision version); using QJSEnginePrivate::cache; // These methods may be called from the loader thread @@ -228,7 +229,8 @@ public: QQmlMetaObject rawMetaObjectForType(int) const; QQmlMetaObject metaObjectForType(int) const; QQmlPropertyCache *propertyCacheForType(int); - QQmlPropertyCache *rawPropertyCacheForType(int, int minorVersion = -1); + QQmlPropertyCache *rawPropertyCacheForType(int); + QQmlPropertyCache *rawPropertyCacheForType(int, QTypeRevision version); void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); QV4::ExecutableCompilationUnit *obtainExecutableCompilationUnit(int typeId); @@ -260,9 +262,6 @@ public: static QList<QQmlError> qmlErrorFromDiagnostics(const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages); static void defineModule(); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - static void registerQuickTypes(); -#endif static bool designerMode(); static void activateDesignerMode(); @@ -301,6 +300,7 @@ private: void doDeleteInEngineThread(); void cleanupScarceResources(); + QQmlPropertyCache *findPropertyCacheInCompositeTypes(int t) const; }; /* @@ -399,15 +399,15 @@ Returns a QQmlPropertyCache for \a type with \a minorVersion. The returned cache is not referenced, so if it is to be stored, call addref(). */ -QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersion) +QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, QTypeRevision version) { Q_ASSERT(type.isValid()); - if (minorVersion == -1 || !type.containsRevisionedAttributes()) - return cache(type.metaObject(), minorVersion); + if (!version.hasMinorVersion() || !type.containsRevisionedAttributes()) + return cache(type.metaObject(), version); Locker locker(this); - return QQmlMetaType::propertyCache(type, minorVersion); + return QQmlMetaType::propertyCache(type, version); } QV4::ExecutionEngine *QQmlEnginePrivate::getV4Engine(QQmlEngine *e) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index e442f07527..ee512a5137 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -213,12 +213,12 @@ public: QQmlImportNamespace *importNamespace(const QString &prefix) const; bool addLibraryImport(const QString& uri, const QString &prefix, - int vmaj, int vmin, const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, + QTypeRevision version, const QString &qmldirIdentifier, + const QString &qmldirUrl, bool incomplete, QQmlImportDatabase *database, QList<QQmlError> *errors); - bool addFileImport(const QString &uri, const QString &prefix, - int vmaj, int vmin, + bool addFileImport(const QString &uri, const QString &prefix, QTypeRevision version, bool isImplicitImport, bool incomplete, QQmlImportDatabase *database, QList<QQmlError> *errors); @@ -227,7 +227,7 @@ public: QQmlImportDatabase *database, QList<QQmlError> *errors); - bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor, + bool resolveType(const QHashedStringRef &type, QTypeRevision *version_return, QQmlType *type_return, QList<QQmlError> *errors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected = nullptr); @@ -247,14 +247,13 @@ public: QQmlTypeLoader *typeLoader; static QQmlImports::LocalQmldirResult locateLocalQmldir( - const QString &uri, int vmaj, int vmin, QQmlImportDatabase *database, + const QString &uri, QTypeRevision version, QQmlImportDatabase *database, QString *outQmldirFilePath, QString *outUrl); - static bool validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, int vmaj, int vmin, - QList<QQmlError> *errors); + static bool validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, + QTypeRevision version, QList<QQmlError> *errors); - bool importExtension(const QString &absoluteFilePath, const QString &uri, - int vmaj, int vmin, + bool importExtension(const QString &absoluteFilePath, const QString &uri, QTypeRevision version, QQmlImportDatabase *database, const QQmlTypeLoaderQmldirContent &qmldir, QList<QQmlError> *errors); @@ -264,10 +263,10 @@ public: QString resolvedUri(const QString &dir_arg, QQmlImportDatabase *database); - QQmlImportInstance *addImportToNamespace(QQmlImportNamespace *nameSpace, - const QString &uri, const QString &url, - int vmaj, int vmin, QV4::CompiledData::Import::ImportType type, - QList<QQmlError> *errors, bool lowPrecedence = false); + QQmlImportInstance *addImportToNamespace(QQmlImportNamespace *nameSpace, const QString &uri, + const QString &url, QTypeRevision version, + QV4::CompiledData::Import::ImportType type, + QList<QQmlError> *errors, bool lowPrecedence = false); bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris, const QString &qmldirPath, QList<QQmlError> *errors); @@ -344,9 +343,9 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const for (int ii = set.imports.count() - 1; ii >= 0; --ii) { const QQmlImportInstance *import = set.imports.at(ii); - QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion); + QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version); if (module) { - cache->m_anonymousImports.append(QQmlTypeModuleVersion(module, import->minversion)); + cache->m_anonymousImports.append(QQmlTypeModuleVersion(module, import->version)); } } @@ -360,10 +359,10 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const for (int ii = set.imports.count() - 1; ii >= 0; --ii) { const QQmlImportInstance *import = set.imports.at(ii); - QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion); + QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version); if (module) { QQmlImportRef &typeimport = cache->m_namedImports[set.prefix]; - typeimport.modules.append(QQmlTypeModuleVersion(module, import->minversion)); + typeimport.modules.append(QQmlTypeModuleVersion(module, import->version)); } } } @@ -395,36 +394,35 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports:: const QQmlDirComponents &components = import->qmlDirComponents; - const int importMajorVersion = import->majversion; - const int importMinorVersion = import->minversion; - auto shouldSkipSingleton = [importMajorVersion, importMinorVersion](int singletonMajorVersion, int singletonMinorVersion) -> bool { - return importMajorVersion != -1 && - (singletonMajorVersion > importMajorVersion || (singletonMajorVersion == importMajorVersion && singletonMinorVersion > importMinorVersion)); + const QTypeRevision importVersion = import->version; + auto shouldSkipSingleton = [importVersion](QTypeRevision singletonVersion) -> bool { + return importVersion.hasMajorVersion() && + (singletonVersion.majorVersion() > importVersion.majorVersion() + || (singletonVersion.majorVersion() == importVersion.majorVersion() + && singletonVersion.minorVersion() > importVersion.minorVersion())); }; ConstIterator cend = components.constEnd(); for (ConstIterator cit = components.constBegin(); cit != cend; ++cit) { if (cit->singleton && excludeBaseUrl(import->url, cit->fileName, baseUrl.toString())) { - if (shouldSkipSingleton(cit->majorVersion, cit->minorVersion)) + if (shouldSkipSingleton(cit->version)) continue; QQmlImports::CompositeSingletonReference ref; ref.typeName = cit->typeName; ref.prefix = set.prefix; - ref.majorVersion = cit->majorVersion; - ref.minorVersion = cit->minorVersion; + ref.version = cit->version; resultList.append(ref); } } - if (QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion)) { + if (QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version)) { module->walkCompositeSingletons([&resultList, &set, &shouldSkipSingleton](const QQmlType &singleton) { - if (shouldSkipSingleton(singleton.majorVersion(), singleton.minorVersion())) + if (shouldSkipSingleton(singleton.version())) return; QQmlImports::CompositeSingletonReference ref; ref.typeName = singleton.elementName(); ref.prefix = set.prefix; - ref.majorVersion = singleton.majorVersion(); - ref.minorVersion = singleton.minorVersion(); + ref.version = singleton.version(); resultList.append(ref); }); } @@ -461,9 +459,9 @@ QList<QQmlImports::CompositeSingletonReference> QQmlImports::resolvedCompositeSi if (lhs.typeName != rhs.typeName) return lhs.typeName < rhs.typeName; - return lhs.majorVersion != rhs.majorVersion - ? lhs.majorVersion < rhs.majorVersion - : lhs.minorVersion < rhs.minorVersion; + return lhs.version.majorVersion() != rhs.version.majorVersion() + ? lhs.version.majorVersion() < rhs.version.majorVersion() + : lhs.version.minorVersion() < rhs.version.minorVersion(); }); return compositeSingletons; @@ -532,7 +530,8 @@ static QString joinStringRefs(const QVector<QStringRef> &refs, const QChar &sep) - base/QtQml.2/Models/qmldir - base/QtQml/Models/qmldir */ -QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin) +QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, + QTypeRevision version) { const QVector<QStringRef> parts = uri.splitRef(Dot, QString::SkipEmptyParts); @@ -540,8 +539,8 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi // fully & partially versioned parts + 1 unversioned for each base path qmlDirPathsPaths.reserve(basePaths.count() * (2 * parts.count() + 1)); - for (int version = FullyVersioned; version <= Unversioned; ++version) { - const QString ver = versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version)); + for (int versionMode = FullyVersioned; versionMode <= Unversioned; ++versionMode) { + const QString ver = versionString(version, QQmlImports::ImportVersion(versionMode)); for (const QString &path : basePaths) { QString dir = path; @@ -551,7 +550,7 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi // append to the end qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + Slash_qmldir; - if (version != Unversioned) { + if (versionMode != Unversioned) { // insert in the middle for (int index = parts.count() - 2; index >= 0; --index) { qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash) @@ -565,14 +564,14 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi return qmlDirPathsPaths; } -QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) +QString QQmlImports::versionString(QTypeRevision version, ImportVersion versionMode) { - if (version == QQmlImports::FullyVersioned) { + if (versionMode == QQmlImports::FullyVersioned) { // extension with fully encoded version number (eg. MyModule.3.2) - return QString::asprintf(".%d.%d", vmaj, vmin); - } else if (version == QQmlImports::PartiallyVersioned) { + return QString::asprintf(".%d.%d", version.majorVersion(), version.minorVersion()); + } else if (versionMode == QQmlImports::PartiallyVersioned) { // extension with encoded version major (eg. MyModule.3) - return QString::asprintf(".%d", vmaj); + return QString::asprintf(".%d", version.majorVersion()); } // else extension without version number (eg. MyModule) return QString(); } @@ -591,7 +590,7 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) \sa addFileImport(), addLibraryImport */ bool QQmlImports::resolveType(const QHashedStringRef &type, - QQmlType *type_return, int *vmaj, int *vmin, + QQmlType *type_return, QTypeRevision *version_return, QQmlImportNamespace** ns_return, QList<QQmlError> *errors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected) const @@ -603,7 +602,7 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, return true; } if (type_return) { - if (d->resolveType(type, vmaj, vmin, type_return, errors, registrationType, + if (d->resolveType(type, version_return, type_return, errors, registrationType, typeRecursionDetected)) { if (qmlImportTrace()) { #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \ @@ -627,7 +626,9 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, return false; } -bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors) +bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, + const QQmlTypeLoaderQmldirContent &qmldir, + QQmlImportNamespace *nameSpace, QList<QQmlError> *errors) { Q_ASSERT(resolvedUrl.endsWith(Slash)); url = resolvedUrl; @@ -648,24 +649,27 @@ bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQml } } - qmlDirScripts = getVersionedScripts(scripts, majversion, minversion); + qmlDirScripts = getVersionedScripts(scripts, version); } return true; } -QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin) +QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qmldirscripts, + QTypeRevision version) { QMap<QString, QQmlDirParser::Script> versioned; for (QList<QQmlDirParser::Script>::const_iterator sit = qmldirscripts.constBegin(); sit != qmldirscripts.constEnd(); ++sit) { // Only include scripts that match our requested version - if (((vmaj == -1) || (sit->majorVersion == vmaj)) && - ((vmin == -1) || (sit->minorVersion <= vmin))) { + if ((!version.hasMajorVersion() || (sit->version.majorVersion() == version.majorVersion())) + && (!version.hasMinorVersion() + || (sit->version.minorVersion() <= version.minorVersion()))) { // Load the highest version that matches QMap<QString, QQmlDirParser::Script>::iterator vit = versioned.find(sit->nameSpace); - if (vit == versioned.end() || (vit->minorVersion < sit->minorVersion)) { + if (vit == versioned.end() + || (vit->version.minorVersion() < sit->version.minorVersion())) { versioned.insert(sit->nameSpace, *sit); } } @@ -685,26 +689,25 @@ QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qml If the return pointer is 0, the corresponding search is not done. */ bool QQmlImports::resolveType(QQmlImportNamespace *ns, const QHashedStringRef &type, - QQmlType *type_return, int *vmaj, int *vmin, + QQmlType *type_return, QTypeRevision *version_return, QQmlType::RegistrationType registrationType) const { - return ns->resolveType(d->typeLoader, type, vmaj, vmin, type_return, nullptr, nullptr, registrationType); + return ns->resolveType(d->typeLoader, type, version_return, type_return, nullptr, nullptr, + registrationType); } bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, - int *vmajor, int *vminor, QQmlType *type_return, QString *base, - bool *typeRecursionDetected, + QTypeRevision *version_return, QQmlType *type_return, + QString *base, bool *typeRecursionDetected, QQmlType::RegistrationType registrationType, QQmlImport::RecursionRestriction recursionRestriction, QList<QQmlError> *errors) const { - if (majversion >= 0 && minversion >= 0) { - QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion); + if (version.hasMajorVersion() && version.hasMinorVersion()) { + QQmlType t = QQmlMetaType::qmlType(type, uri, version); if (t.isValid()) { - if (vmajor) - *vmajor = majversion; - if (vminor) - *vminor = minversion; + if (version_return) + *version_return = version; if (type_return) *type_return = t; return true; @@ -764,14 +767,16 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt break; } - // importing version -1 means import ALL versions - if ((majversion == -1) || - (implicitlyImported && c.internal) || // allow the implicit import of internal types - (c.majorVersion == majversion && c.minorVersion <= minversion)) { + // importing invalid version means import ALL versions + if (!version.hasMajorVersion() || (implicitlyImported && c.internal) + // allow the implicit import of internal types + || (c.version.majorVersion() == version.majorVersion() + && c.version.minorVersion() <= version.minorVersion())) { // Is this better than the previous candidate? - if ((candidate == end) || - (c.majorVersion > candidate->majorVersion) || - ((c.majorVersion == candidate->majorVersion) && (c.minorVersion > candidate->minorVersion))) { + if ((candidate == end) + || (c.version.majorVersion() > candidate->version.majorVersion()) + || ((c.version.majorVersion() == candidate->version.majorVersion()) + && (c.version.minorVersion() > candidate->version.minorVersion()))) { if (base) { componentUrl = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName); if (c.internal) { @@ -799,12 +804,9 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt if (!base) // ensure we have a componentUrl componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName); QQmlType returnType = QQmlMetaType::typeForUrl(componentUrl, type, isCompositeSingleton, - nullptr, candidate->majorVersion, - candidate->minorVersion); - if (vmajor) - *vmajor = candidate->majorVersion; - if (vminor) - *vminor = candidate->minorVersion; + nullptr, candidate->version); + if (version_return) + *version_return = candidate->version; if (type_return) *type_return = returnType; return returnType.isValid(); @@ -856,14 +858,14 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt return false; } -bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor, +bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, QTypeRevision *version_return, QQmlType *type_return, QList<QQmlError> *errors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected) { const QVector<QHashedStringRef> splitName = type.split(Dot); auto resolveTypeInNamespace = [&](QHashedStringRef unqualifiedtype, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors) -> bool { - if (nameSpace->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors, + if (nameSpace->resolveType(typeLoader, unqualifiedtype, version_return, type_return, &base, errors, registrationType, typeRecursionDetected)) return true; if (nameSpace->imports.count() == 1 && !nameSpace->imports.at(0)->isLibrary && type_return && nameSpace != &unqualifiedset) { @@ -976,7 +978,7 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const } bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, - int *vmajor, int *vminor, QQmlType *type_return, + QTypeRevision *version_return, QQmlType *type_return, QString *base, QList<QQmlError> *errors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected) @@ -990,13 +992,13 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS for (int i=0; i<imports.count(); ++i) { const QQmlImportInstance *import = imports.at(i); - if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, base, + if (import->resolveType(typeLoader, type, version_return, type_return, base, typeRecursionDetected, registrationType, recursionRestriction, errors)) { if (qmlCheckTypes()) { // check for type clashes for (int j = i+1; j<imports.count(); ++j) { const QQmlImportInstance *import2 = imports.at(j); - if (import2->resolveType(typeLoader, type, vmajor, vminor, nullptr, base, + if (import2->resolveType(typeLoader, type, version_return, nullptr, base, nullptr, registrationType)) { if (errors) { QString u1 = import->url; @@ -1023,9 +1025,11 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS error.setDescription(QQmlImportDatabase::tr("is ambiguous. Found in %1 and in %2").arg(u1).arg(u2)); } else { error.setDescription(QQmlImportDatabase::tr("is ambiguous. Found in %1 in version %2.%3 and %4.%5") - .arg(u1) - .arg(import->majversion).arg(import->minversion) - .arg(import2->majversion).arg(import2->minversion)); + .arg(u1) + .arg(import->version.majorVersion()) + .arg(import->version.minorVersion()) + .arg(import2->version.majorVersion()) + .arg(import2->version.minorVersion())); } errors->prepend(error); } @@ -1071,18 +1075,19 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr QtQml.Models, \a vmaj is 2, and \a vmin is 0, this method returns the following: [QtQml.Models.2.0, QtQml.2.0.Models, QtQml.Models.2, QtQml.2.Models, QtQml.Models] */ -static QStringList versionUriList(const QString &uri, int vmaj, int vmin) +static QStringList versionUriList(const QString &uri, QTypeRevision version) { QStringList result; - for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) { + for (int mode = QQmlImports::FullyVersioned; mode <= QQmlImports::Unversioned; ++mode) { int index = uri.length(); do { QString versionUri = uri; - versionUri.insert(index, QQmlImports::versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version))); + versionUri.insert(index, QQmlImports::versionString( + version, QQmlImports::ImportVersion(mode))); result += versionUri; index = uri.lastIndexOf(Dot, index - 1); - } while (index > 0 && version != QQmlImports::Unversioned); + } while (index > 0 && mode != QQmlImports::Unversioned); } return result; } @@ -1147,8 +1152,7 @@ Import an extension defined by a qmldir file. \a qmldirFilePath is a raw file path. */ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, - const QString &uri, - int vmaj, int vmin, + const QString &uri, QTypeRevision version, QQmlImportDatabase *database, const QQmlTypeLoaderQmldirContent &qmldir, QList<QQmlError> *errors) @@ -1173,13 +1177,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, if (qmldirPluginCount == 0) return true; - if (database->qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) { - if ((vmaj >= 0 && vmin >= 0) - ? !QQmlMetaType::isModule(uri, vmaj, vmin) - : !QQmlMetaType::isAnyModule(uri)) { - QQmlMetaType::qmlRegisterModuleTypes(uri, vmaj); - } - } else { + if (!database->qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) { // First search for listed qmldir plugins dynamically. If we cannot resolve them all, we continue // searching static plugins that has correct metadata uri. Note that since we only know the uri // for a static plugin, and not the filename, we cannot know which static plugin belongs to which @@ -1201,7 +1199,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name); if (!resolvedFilePath.isEmpty()) { dynamicPluginsFound++; - if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, vmaj, errors)) { + if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, version, errors)) { if (errors) { // XXX TODO: should we leave the import plugin error alone? // Here, we pop it off the top and coalesce it into this error's message. @@ -1226,7 +1224,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, // versioned to unversioned, we need to compare with differnt version strings. If a module // has several plugins, they must all have the same version. Start by populating pluginPairs // with relevant plugins to cut the list short early on: - const QStringList versionUris = versionUriList(uri, vmaj, vmin); + const QStringList versionUris = versionUriList(uri, version); QVector<StaticPluginPair> pluginPairs; if (!populatePluginPairVector(pluginPairs, uri, versionUris, qmldirFilePath, errors)) return false; @@ -1238,7 +1236,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, if (versionUri == metaTagUri.toString()) { staticPluginsFound++; QObject *instance = pair.first.instance(); - if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, vmaj, errors)) { + if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, version, errors)) { if (errors) { QQmlError poppedError = errors->takeFirst(); QQmlError error; @@ -1341,10 +1339,11 @@ and fills in outQmldirFilePath and outQmldirUrl appropriately. Otherwise return false. */ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( - const QString &uri, int vmaj, int vmin, QQmlImportDatabase *database, + const QString &uri, QTypeRevision version, QQmlImportDatabase *database, QString *outQmldirFilePath, QString *outQmldirPathUrl) { - Q_ASSERT(vmaj >= 0 && vmin >= 0); // Versions are always specified for libraries + // Versions are always specified for libraries + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); // Check cache first @@ -1355,7 +1354,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( cacheHead = *cachePtr; QQmlImportDatabase::QmldirCache *cache = cacheHead; while (cache) { - if (cache->versionMajor == vmaj && cache->versionMinor == vmin) { + if (cache->version == version) { *outQmldirFilePath = cache->qmldirFilePath; *outQmldirPathUrl = cache->qmldirPathUrl; return cache->qmldirFilePath.isEmpty() ? QQmlImports::QmldirNotFound @@ -1375,7 +1374,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( // Search local import paths for a matching version const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths( - uri, localImportPaths, vmaj, vmin); + uri, localImportPaths, version); bool pathTurnedRemote = false; for (QString qmldirPath : qmlDirPaths) { if (interceptor) { @@ -1397,8 +1396,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( url = QUrl::fromLocalFile(absolutePath.toString()).toString(); QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; - cache->versionMajor = vmaj; - cache->versionMinor = vmin; + cache->version = version; cache->qmldirFilePath = absoluteFilePath; cache->qmldirPathUrl = url; cache->next = cacheHead; @@ -1412,19 +1410,19 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir( } QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; - cache->versionMajor = vmaj; - cache->versionMinor = vmin; + cache->version = version; cache->next = cacheHead; database->qmldirCache.insert(uri, cache); return pathTurnedRemote ? QQmlImports::QmldirInterceptedToRemote : QQmlImports::QmldirNotFound; } -bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, int vmaj, int vmin, +bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, + const QString &uri, QTypeRevision version, QList<QQmlError> *errors) { - int lowest_min = INT_MAX; - int highest_min = INT_MIN; + quint8 lowest_min = std::numeric_limits<quint8>::max(); + quint8 highest_min = 0; typedef QQmlDirComponents::const_iterator ConstIterator; const QQmlDirComponents &components = qmldir.components(); @@ -1432,21 +1430,20 @@ bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent ConstIterator cend = components.constEnd(); for (ConstIterator cit = components.constBegin(); cit != cend; ++cit) { for (ConstIterator cit2 = components.constBegin(); cit2 != cit; ++cit2) { - if ((cit2->typeName == cit->typeName) && - (cit2->majorVersion == cit->majorVersion) && - (cit2->minorVersion == cit->minorVersion)) { + if (cit2->typeName == cit->typeName && cit2->version == cit->version) { // This entry clashes with a predecessor QQmlError error; error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"") - .arg(cit->typeName).arg(cit->majorVersion).arg(cit->minorVersion).arg(uri)); + .arg(cit->typeName).arg(cit->version.majorVersion()) + .arg(cit->version.minorVersion()).arg(uri)); errors->prepend(error); return false; } } - if (cit->majorVersion == vmaj) { - lowest_min = qMin(lowest_min, cit->minorVersion); - highest_min = qMax(highest_min, cit->minorVersion); + if (cit->version.majorVersion() == version.majorVersion()) { + lowest_min = qMin(lowest_min, cit->version.minorVersion()); + highest_min = qMax(highest_min, cit->version.minorVersion()); } } @@ -1456,27 +1453,27 @@ bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent SConstIterator send = scripts.constEnd(); for (SConstIterator sit = scripts.constBegin(); sit != send; ++sit) { for (SConstIterator sit2 = scripts.constBegin(); sit2 != sit; ++sit2) { - if ((sit2->nameSpace == sit->nameSpace) && - (sit2->majorVersion == sit->majorVersion) && - (sit2->minorVersion == sit->minorVersion)) { + if (sit2->nameSpace == sit->nameSpace && sit2->version == sit->version) { // This entry clashes with a predecessor QQmlError error; error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"") - .arg(sit->nameSpace).arg(sit->majorVersion).arg(sit->minorVersion).arg(uri)); + .arg(sit->nameSpace).arg(sit->version.majorVersion()) + .arg(sit->version.minorVersion()).arg(uri)); errors->prepend(error); return false; } } - if (sit->majorVersion == vmaj) { - lowest_min = qMin(lowest_min, sit->minorVersion); - highest_min = qMax(highest_min, sit->minorVersion); + if (sit->version.majorVersion() == version.majorVersion()) { + lowest_min = qMin(lowest_min, sit->version.minorVersion()); + highest_min = qMax(highest_min, sit->version.minorVersion()); } } - if (lowest_min > vmin || highest_min < vmin) { + if (lowest_min > version.minorVersion() || highest_min < version.minorVersion()) { QQmlError error; - error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin)); + error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed") + .arg(uri).arg(version.majorVersion()).arg(version.minorVersion())); errors->prepend(error); return false; } @@ -1503,10 +1500,9 @@ QQmlImportNamespace *QQmlImportsPrivate::importNamespace(const QString &prefix) return nameSpace; } -QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace *nameSpace, - const QString &uri, const QString &url, int vmaj, int vmin, - QV4::CompiledData::Import::ImportType type, - QList<QQmlError> *errors, bool lowPrecedence) +QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace( + QQmlImportNamespace *nameSpace, const QString &uri, const QString &url, QTypeRevision version, + QV4::CompiledData::Import::ImportType type, QList<QQmlError> *errors, bool lowPrecedence) { Q_ASSERT(nameSpace); Q_ASSERT(errors); @@ -1517,8 +1513,7 @@ QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace import->uri = uri; import->url = url; import->localDirectoryPath = QQmlFile::urlToLocalFileOrQrc(url); - import->majversion = vmaj; - import->minversion = vmin; + import->version = version; import->isLibrary = (type == QV4::CompiledData::Import::ImportLibrary); if (lowPrecedence) @@ -1529,10 +1524,10 @@ QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace return import; } -bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &prefix, - int vmaj, int vmin, const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, - QQmlImportDatabase *database, - QList<QQmlError> *errors) +bool QQmlImportsPrivate::addLibraryImport( + const QString& uri, const QString &prefix, QTypeRevision version, + const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, + QQmlImportDatabase *database, QList<QQmlError> *errors) { Q_ASSERT(database); Q_ASSERT(errors); @@ -1540,7 +1535,9 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre QQmlImportNamespace *nameSpace = importNamespace(prefix); Q_ASSERT(nameSpace); - QQmlImportInstance *inserted = addImportToNamespace(nameSpace, uri, qmldirUrl, vmaj, vmin, QV4::CompiledData::Import::ImportLibrary, errors); + QQmlImportInstance *inserted = addImportToNamespace( + nameSpace, uri, qmldirUrl, version, + QV4::CompiledData::Import::ImportLibrary, errors); Q_ASSERT(inserted); if (!incomplete) { @@ -1551,7 +1548,7 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre return false; if (qmldir.hasContent()) { - if (!importExtension(qmldir.pluginLocation(), uri, vmaj, vmin, database, qmldir, errors)) + if (!importExtension(qmldir.pluginLocation(), uri, version, database, qmldir, errors)) return false; if (!inserted->setQmldirContent(qmldirUrl, qmldir, nameSpace, errors)) @@ -1560,18 +1557,22 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre } // Ensure that we are actually providing something - if ((vmaj < 0) || (vmin < 0) || !QQmlMetaType::isModule(uri, vmaj, vmin)) { + if (!version.hasMajorVersion() || !version.hasMinorVersion() + || !QQmlMetaType::isModule(uri, version)) { if (inserted->qmlDirComponents.isEmpty() && inserted->qmlDirScripts.isEmpty()) { QQmlError error; - if (QQmlMetaType::isAnyModule(uri)) - error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin)); - else + if (QQmlMetaType::isAnyModule(uri)) { + error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed") + .arg(uri).arg(version.majorVersion()).arg(version.minorVersion())); + } else { error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed").arg(uri)); + } errors->prepend(error); return false; - } else if ((vmaj >= 0) && (vmin >= 0) && qmldir.hasContent()) { + } else if (version.hasMajorVersion() && version.hasMinorVersion() + && qmldir.hasContent()) { // Verify that the qmldir content is valid for this version - if (!validateQmldirVersion(qmldir, uri, vmaj, vmin, errors)) + if (!validateQmldirVersion(qmldir, uri, version, errors)) return false; } } @@ -1580,10 +1581,9 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre return true; } -bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix, - int vmaj, int vmin, - bool isImplicitImport, bool incomplete, QQmlImportDatabase *database, - QList<QQmlError> *errors) +bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix, QTypeRevision version, + bool isImplicitImport, bool incomplete, + QQmlImportDatabase *database, QList<QQmlError> *errors) { Q_ASSERT(errors); @@ -1659,7 +1659,9 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix } } - QQmlImportInstance *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QV4::CompiledData::Import::ImportFile, errors, isImplicitImport); + QQmlImportInstance *inserted = addImportToNamespace( + nameSpace, importUri, url, version, QV4::CompiledData::Import::ImportFile, + errors, isImplicitImport); Q_ASSERT(inserted); if (!incomplete && !qmldirIdentifier.isEmpty()) { @@ -1668,7 +1670,7 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix return false; if (qmldir.hasContent()) { - if (!importExtension(qmldir.pluginLocation(), importUri, vmaj, vmin, database, qmldir, errors)) + if (!importExtension(qmldir.pluginLocation(), importUri, version, database, qmldir, errors)) return false; if (!inserted->setQmldirContent(url, qmldir, nameSpace, errors)) @@ -1692,26 +1694,27 @@ bool QQmlImportsPrivate::updateQmldirContent(const QString &uri, const QString & return false; if (qmldir.hasContent()) { - int vmaj = import->majversion; - int vmin = import->minversion; - if (!importExtension(qmldir.pluginLocation(), uri, vmaj, vmin, database, qmldir, errors)) + QTypeRevision version = import->version; + if (!importExtension(qmldir.pluginLocation(), uri, version, database, qmldir, errors)) return false; if (import->setQmldirContent(qmldirUrl, qmldir, nameSpace, errors)) { if (import->qmlDirComponents.isEmpty() && import->qmlDirScripts.isEmpty()) { // The implicit import qmldir can be empty, and plugins have no extra versions - if (uri != QLatin1String(".") && !QQmlMetaType::isModule(uri, vmaj, vmin)) { + if (uri != QLatin1String(".") && !QQmlMetaType::isModule(uri, version)) { QQmlError error; - if (QQmlMetaType::isAnyModule(uri)) - error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin)); - else + if (QQmlMetaType::isAnyModule(uri)) { + error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed") + .arg(uri).arg(version.majorVersion()).arg(version.minorVersion())); + } else { error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed").arg(uri)); + } errors->prepend(error); return false; } - } else if ((vmaj >= 0) && (vmin >= 0)) { + } else if (version.hasMajorVersion() && version.hasMinorVersion()) { // Verify that the qmldir content is valid for this version - if (!validateQmldirVersion(qmldir, uri, vmaj, vmin, errors)) + if (!validateQmldirVersion(qmldir, uri, version, errors)) return false; } return true; @@ -1745,7 +1748,8 @@ bool QQmlImports::addImplicitImport(QQmlImportDatabase *importDb, QList<QQmlErro << ")::addImplicitImport"; bool incomplete = !isLocal(baseUrl()); - return d->addFileImport(QLatin1String("."), QString(), -1, -1, true, incomplete, importDb, errors); + return d->addFileImport(QLatin1String("."), QString(), QTypeRevision(), true, incomplete, + importDb, errors); } /*! @@ -1756,8 +1760,7 @@ bool QQmlImports::addInlineComponentImport(QQmlImportInstance *const importInsta importInstance->url = importUrl.toString(); importInstance->uri = name; importInstance->isInlineComponent = true; - importInstance->majversion = 0; - importInstance->minversion = 0; + importInstance->version = QTypeRevision::zero(); importInstance->containingType = containingType; d->unqualifiedset.imports.push_back(importInstance); return true; @@ -1785,7 +1788,7 @@ bool QQmlImports::addInlineComponentImport(QQmlImportInstance *const importInsta filled appropriately. */ bool QQmlImports::addFileImport(QQmlImportDatabase *importDb, - const QString& uri, const QString& prefix, int vmaj, int vmin, + const QString& uri, const QString& prefix, QTypeRevision version, bool incomplete, QList<QQmlError> *errors) { Q_ASSERT(importDb); @@ -1793,13 +1796,13 @@ bool QQmlImports::addFileImport(QQmlImportDatabase *importDb, if (qmlImportTrace()) qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) << ')' << "::addFileImport: " - << uri << ' ' << vmaj << '.' << vmin << " as " << prefix; + << uri << ' ' << version << " as " << prefix; - return d->addFileImport(uri, prefix, vmaj, vmin, false, incomplete, importDb, errors); + return d->addFileImport(uri, prefix, version, false, incomplete, importDb, errors); } bool QQmlImports::addLibraryImport(QQmlImportDatabase *importDb, - const QString &uri, const QString &prefix, int vmaj, int vmin, + const QString &uri, const QString &prefix, QTypeRevision version, const QString &qmldirIdentifier, const QString& qmldirUrl, bool incomplete, QList<QQmlError> *errors) { Q_ASSERT(importDb); @@ -1807,9 +1810,9 @@ bool QQmlImports::addLibraryImport(QQmlImportDatabase *importDb, if (qmlImportTrace()) qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) << ')' << "::addLibraryImport: " - << uri << ' ' << vmaj << '.' << vmin << " as " << prefix; + << uri << ' ' << version << " as " << prefix; - return d->addLibraryImport(uri, prefix, vmaj, vmin, qmldirIdentifier, qmldirUrl, incomplete, importDb, errors); + return d->addLibraryImport(uri, prefix, version, qmldirIdentifier, qmldirUrl, incomplete, importDb, errors); } bool QQmlImports::updateQmldirContent(QQmlImportDatabase *importDb, @@ -1827,10 +1830,10 @@ bool QQmlImports::updateQmldirContent(QQmlImportDatabase *importDb, } QQmlImports::LocalQmldirResult QQmlImports::locateLocalQmldir( - QQmlImportDatabase *importDb, const QString &uri, int vmaj, int vmin, + QQmlImportDatabase *importDb, const QString &uri, QTypeRevision version, QString *qmldirFilePath, QString *url) { - return d->locateLocalQmldir(uri, vmaj, vmin, importDb, qmldirFilePath, url); + return d->locateLocalQmldir(uri, version, importDb, qmldirFilePath, url); } bool QQmlImports::isLocal(const QString &url) @@ -2139,19 +2142,21 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths) \internal */ static bool registerPluginTypes(QObject *instance, const QString &basePath, const QString &uri, - const QString &typeNamespace, int vmaj, QList<QQmlError> *errors) + const QString &typeNamespace, QTypeRevision version, + QList<QQmlError> *errors) { if (qmlImportTrace()) qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath; - if (!QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors)) + if (!QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, version, errors)) return false; - if (vmaj >= 0 && !typeNamespace.isEmpty() && !QQmlMetaType::protectModule(uri, vmaj)) { + if (version.hasMajorVersion() && !typeNamespace.isEmpty() + && !QQmlMetaType::protectModule(uri, version)) { QQmlError error; error.setDescription( QString::fromLatin1("Cannot protect module %1 %2 as it was never registered") - .arg(uri).arg(vmaj)); + .arg(uri).arg(version.majorVersion())); errors->append(error); return false; } @@ -2162,8 +2167,9 @@ static bool registerPluginTypes(QObject *instance, const QString &basePath, cons /*! \internal */ -bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors) +bool QQmlImportDatabase::importStaticPlugin( + QObject *instance, const QString &basePath, const QString &uri, + const QString &typeNamespace, QTypeRevision version, QList<QQmlError> *errors) { // Dynamic plugins are differentiated by their filepath. For static plugins we // don't have that information so we use their address as key instead. @@ -2186,7 +2192,7 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba plugin.loader = nullptr; plugins->insert(uniquePluginID, plugin); - if (!registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors)) + if (!registerPluginTypes(instance, basePath, uri, typeNamespace, version, errors)) return false; } @@ -2206,8 +2212,9 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba /*! \internal */ -bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QString &uri, - const QString &typeNamespace, int vmaj, QList<QQmlError> *errors) +bool QQmlImportDatabase::importDynamicPlugin( + const QString &filePath, const QString &uri, const QString &typeNamespace, + QTypeRevision version, QList<QQmlError> *errors) { QFileInfo fileInfo(filePath); const QString absoluteFilePath = fileInfo.absoluteFilePath(); @@ -2261,7 +2268,7 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr plugins->insert(absoluteFilePath, plugin); // Continue with shared code path for dynamic and static plugins: - if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, vmaj, errors)) + if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, version, errors)) return false; } } diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 2e994fd27f..7416bb7a4c 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -81,8 +81,7 @@ struct QQmlImportInstance QString url; // the base path of the import QString localDirectoryPath; // the base path of the import if it's a local file QQmlType containingType; // points to the containing type for inline components - int majversion; // the major version imported - int minversion; // the minor version imported + QTypeRevision version; // the version imported bool isLibrary; // true means that this is not a file import bool implicitlyImported = false; bool isInlineComponent = false; @@ -92,10 +91,11 @@ struct QQmlImportInstance bool setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors); - static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin); + static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, + QTypeRevision version); bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, - int *vmajor, int *vminor, QQmlType* type_return, + QTypeRevision *version_return, QQmlType* type_return, QString *base = nullptr, bool *typeRecursionDetected = nullptr, QQmlType::RegistrationType = QQmlType::AnyRegistrationType, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion, @@ -113,7 +113,7 @@ public: QQmlImportInstance *findImport(const QString &uri) const; bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, - int *vmajor, int *vminor, QQmlType* type_return, + QTypeRevision *version_return, QQmlType* type_return, QString *base = nullptr, QList<QQmlError> *errors = nullptr, QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType, bool *typeRecursionDeteced = nullptr); @@ -140,14 +140,14 @@ public: bool resolveType(const QHashedStringRef &type, QQmlType *type_return, - int *version_major, int *version_minor, + QTypeRevision *version_return, QQmlImportNamespace **ns_return, QList<QQmlError> *errors = nullptr, QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType, bool *typeRecursionDetected = nullptr) const; bool resolveType(QQmlImportNamespace *, const QHashedStringRef& type, - QQmlType *type_return, int *version_major, int *version_minor, + QQmlType *type_return, QTypeRevision *version_return, QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType) const; @@ -156,11 +156,11 @@ public: bool addInlineComponentImport(QQmlImportInstance *const importInstance, const QString &name, const QUrl importUrl, QQmlType containingType); bool addFileImport(QQmlImportDatabase *, - const QString& uri, const QString& prefix, int vmaj, int vmin, bool incomplete, - QList<QQmlError> *errors); + const QString& uri, const QString& prefix, QTypeRevision version, + bool incomplete, QList<QQmlError> *errors); bool addLibraryImport(QQmlImportDatabase *importDb, - const QString &uri, const QString &prefix, int vmaj, int vmin, + const QString &uri, const QString &prefix, QTypeRevision version, const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, QList<QQmlError> *errors); bool updateQmldirContent(QQmlImportDatabase *importDb, @@ -174,7 +174,7 @@ public: }; LocalQmldirResult locateLocalQmldir( - QQmlImportDatabase *, const QString &uri, int vmaj, int vmin, + QQmlImportDatabase *, const QString &uri, QTypeRevision version, QString *qmldirFilePath, QString *url); void populateCache(QQmlTypeNameCache *cache) const; @@ -192,14 +192,14 @@ public: { QString typeName; QString prefix; - int majorVersion; - int minorVersion; + QTypeRevision version; }; QList<CompositeSingletonReference> resolvedCompositeSingletons() const; - static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin); - static QString versionString(int vmaj, int vmin, ImportVersion version); + static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, + QTypeRevision version); + static QString versionString(QTypeRevision version, ImportVersion importVersion); static bool isLocal(const QString &url); static bool isLocal(const QUrl &url); @@ -222,7 +222,9 @@ public: ~QQmlImportDatabase(); #if QT_CONFIG(library) - bool importDynamicPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, int vmaj, QList<QQmlError> *errors); + bool importDynamicPlugin(const QString &filePath, const QString &uri, + const QString &importNamespace, QTypeRevision version, + QList<QQmlError> *errors); bool removeDynamicPlugin(const QString &filePath); QStringList dynamicPlugins() const; #endif @@ -245,13 +247,13 @@ private: const QString &qmldirPath, const QString &qmldirPluginPath, const QString &baseName); bool importStaticPlugin(QObject *instance, const QString &basePath, const QString &uri, - const QString &typeNamespace, int vmaj, QList<QQmlError> *errors); + const QString &typeNamespace, QTypeRevision version, + QList<QQmlError> *errors); void clearDirCache(); void finalizePlugin(QObject *instance, const QString &path, const QString &uri); struct QmldirCache { - int versionMajor; - int versionMinor; + QTypeRevision version; QString qmldirFilePath; QString qmldirPathUrl; QmldirCache *next; diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 7af6af276a..bc227ad713 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -835,7 +835,7 @@ QV4::ReturnedValue QQmlLocale::locale(ExecutionEngine *engine, const QString &lo { QLocale qlocale; if (!localeName.isEmpty()) - qlocale = localeName; + qlocale = QLocale(localeName); return wrap(engine, qlocale); } diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index 1d6fdb12a7..d7bff5a1b7 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -96,7 +96,7 @@ class Q_QML_PRIVATE_EXPORT QQmlLocale Q_GADGET QML_NAMED_ELEMENT(Locale) QML_UNCREATABLE("Locale cannot be instantiated. Use Qt.locale().") - QML_ADDED_IN_MINOR_VERSION(2) + QML_ADDED_IN_VERSION(2, 2) public: ~QQmlLocale(); diff --git a/src/qml/qml/qqmlloggingcategory_p.h b/src/qml/qml/qqmlloggingcategory_p.h index c7377528b4..9cee029a9b 100644 --- a/src/qml/qml/qqmlloggingcategory_p.h +++ b/src/qml/qml/qqmlloggingcategory_p.h @@ -66,9 +66,9 @@ class QQmlLoggingCategory : public QObject, public QQmlParserStatus Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString name READ name WRITE setName) - Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION 12) + Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION(2, 12)) QML_NAMED_ELEMENT(LoggingCategory) - QML_ADDED_IN_MINOR_VERSION(8) + QML_ADDED_IN_VERSION(2, 8) public: enum DefaultLogLevel { diff --git a/src/qml/qml/qqmlmetaobject.cpp b/src/qml/qml/qqmlmetaobject.cpp index a967f46b12..a87865fd81 100644 --- a/src/qml/qml/qqmlmetaobject.cpp +++ b/src/qml/qml/qqmlmetaobject.cpp @@ -44,12 +44,6 @@ QT_BEGIN_NAMESPACE -struct StaticQtMetaObject : public QObject -{ - static const QMetaObject *get() - { return &staticQtMetaObject; } -}; - static bool isNamedEnumeratorInScope(const QMetaObject *resolvedMetaObject, const QByteArray &scope, const QByteArray &name) { @@ -74,7 +68,7 @@ static bool isNamedEnumerator(const QMetaObject *metaObj, const QByteArray &scop } if (scope == "Qt") - return isNamedEnumeratorInScope(StaticQtMetaObject::get(), scope, name); + return isNamedEnumeratorInScope(&Qt::staticMetaObject, scope, name); if (isNamedEnumeratorInScope(metaObj, scope, name)) return true; diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index b2a769cab4..0baf142913 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -92,12 +92,11 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, d->typeId = type.typeId; d->listId = type.listId; d->isSetup = true; - d->version_min = 0; - if (type.version > 0) { + if (type.structVersion > 0) { d->module = QString::fromUtf8(type.uri); - d->version_maj = type.versionMajor; + d->version = type.version; } else { - d->version_maj = 0; + d->version = QTypeRevision::zero(); } data->registerType(d); return d; @@ -110,28 +109,30 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el data->registerType(d); d->setName(QString::fromUtf8(type.uri), elementName); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; + d->version = type.version; - if (type.qobjectApi || (type.version >= 3 && type.generalizedQobjectApi)) { - if (type.version >= 1) // static metaobject added in version 1 + if (type.qobjectApi || (type.structVersion >= 3 && type.generalizedQobjectApi)) { + if (type.structVersion >= 1) // static metaobject added in version 1 d->baseMetaObject = type.instanceMetaObject; - if (type.version >= 2) // typeId added in version 2 + if (type.structVersion >= 2) // typeId added in version 2 d->typeId = type.typeId; - if (type.version >= 2) // revisions added in version 2 + if (type.structVersion >= 2) // revisions added in version 2 d->revision = type.revision; } d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi; - if (type.version >= 3) { + if (type.structVersion >= 3) { d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.generalizedQobjectApi; } else { d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi; } d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); d->extraData.sd->singletonInstanceInfo->instanceMetaObject - = ((type.qobjectApi || (type.version >= 3 && type.generalizedQobjectApi) ) && type.version >= 1) ? type.instanceMetaObject : nullptr; + = ((type.qobjectApi || (type.structVersion >= 3 && type.generalizedQobjectApi) ) + && type.structVersion >= 1) + ? type.instanceMetaObject + : nullptr; return d; } @@ -143,9 +144,8 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el data->registerType(d); d->setName(QString::fromUtf8(type.uri), elementName); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; - if (type.version >= 1) // revisions added in version 1 + d->version = type.version; + if (type.structVersion >= 1) // revisions added in version 1 d->revision = type.revision; d->typeId = type.typeId; d->listId = type.listId; @@ -181,8 +181,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el auto *d = new QQmlTypePrivate(QQmlType::CompositeType); data->registerType(d); d->setName(QString::fromUtf8(type.uri), elementName); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; + d->version = type.version; d->extraData.fd->url = QQmlTypeLoader::normalize(type.url); return d; @@ -195,8 +194,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el data->registerType(d); d->setName(QString::fromUtf8(type.uri), elementName); - d->version_maj = type.versionMajor; - d->version_min = type.versionMinor; + d->version = type.version; d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url); @@ -272,35 +270,32 @@ void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo, } } -void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, int majorVersion, - void (*registerFunction)()) +void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)()) { - const QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion); QQmlMetaTypeDataPtr data; - if (data->moduleTypeRegistrationFunctions.contains(versionedUri)) - qFatal("Cannot add multiple registrations for %s %d", qPrintable(uri), majorVersion); + if (data->moduleTypeRegistrationFunctions.contains(uri)) + qFatal("Cannot add multiple registrations for %s", qPrintable(uri)); else - data->moduleTypeRegistrationFunctions.insert(versionedUri, registerFunction); + data->moduleTypeRegistrationFunctions.insert(uri, registerFunction); } -void QQmlMetaType::qmlRemoveModuleRegistration(const QString &uri, int majorVersion) +void QQmlMetaType::qmlRemoveModuleRegistration(const QString &uri) { - const QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion); QQmlMetaTypeDataPtr data; if (!data.isValid()) return; // shutdown/deletion race. Not a problem. - if (!data->moduleTypeRegistrationFunctions.contains(versionedUri)) - qFatal("Cannot remove multiple registrations for %s %d", qPrintable(uri), majorVersion); + if (!data->moduleTypeRegistrationFunctions.contains(uri)) + qFatal("Cannot remove multiple registrations for %s", qPrintable(uri)); else - data->moduleTypeRegistrationFunctions.remove(versionedUri); + data->moduleTypeRegistrationFunctions.remove(uri); } -bool QQmlMetaType::qmlRegisterModuleTypes(const QString &uri, int majorVersion) +bool QQmlMetaType::qmlRegisterModuleTypes(const QString &uri) { QQmlMetaTypeDataPtr data; - return data->registerModuleTypes(QQmlMetaTypeData::VersionedUri(uri, majorVersion)); + return data->registerModuleTypes(uri); } /*! @@ -350,7 +345,7 @@ void QQmlMetaType::unregisterAutoParentFunction(const QQmlPrivate::AutoParentFun QQmlType QQmlMetaType::registerInterface(const QQmlPrivate::RegisterInterface &type) { - if (type.version > 1) + if (type.structVersion > 1) qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); QQmlMetaTypeDataPtr data; @@ -386,7 +381,7 @@ QString registrationTypeString(QQmlType::RegistrationType typeType) // NOTE: caller must hold a QMutexLocker on "data" bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, - const char *uri, const QString &typeName, int majorVersion) + const char *uri, const QString &typeName, QTypeRevision version) { if (!typeName.isEmpty()) { if (typeName.at(0).isLower()) { @@ -407,14 +402,14 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da if (uri && !typeName.isEmpty()) { QString nameSpace = QString::fromUtf8(uri); - QQmlMetaTypeData::VersionedUri versionedUri; - versionedUri.uri = nameSpace; - versionedUri.majorVersion = majorVersion; + QQmlMetaTypeData::VersionedUri versionedUri(nameSpace, version); if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){ if (qqtm->isLocked()){ QString failure(QCoreApplication::translate("qmlRegisterType", "Cannot install %1 '%2' into protected module '%3' version '%4'")); - data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion)); + data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)) + .arg(typeName).arg(nameSpace) + .arg(version.majorVersion())); return false; } } @@ -424,9 +419,9 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da } // NOTE: caller must hold a QMutexLocker on "data" -QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMetaTypeData *data) +QQmlTypeModule *getTypeModule(const QHashedString &uri, QTypeRevision version, QQmlMetaTypeData *data) { - QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion); + QQmlMetaTypeData::VersionedUri versionedUri(uri, version); QQmlTypeModule *module = data->uriToModule.value(versionedUri); if (!module) { module = new QQmlTypeModule(versionedUri.uri, versionedUri.majorVersion); @@ -463,7 +458,7 @@ void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data) if (!type->module.isEmpty()) { const QHashedString &mod = type->module; - QQmlTypeModule *module = getTypeModule(mod, type->version_maj, data); + QQmlTypeModule *module = getTypeModule(mod, type->version, data); Q_ASSERT(module); module->add(type); } @@ -474,7 +469,7 @@ QQmlType QQmlMetaType::registerType(const QQmlPrivate::RegisterType &type) QQmlMetaTypeDataPtr data; QString elementName = QString::fromUtf8(type.elementName); - if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor)) + if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.version)) return QQmlType(); QQmlTypePrivate *priv = createQQmlType(data, elementName, type); @@ -491,7 +486,7 @@ QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingleto QQmlMetaTypeDataPtr data; QString typeName = QString::fromUtf8(type.typeName); - if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor)) + if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.version)) return QQmlType(); QQmlTypePrivate *priv = createQQmlType(data, typeName, type); @@ -511,7 +506,7 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe if (*(type.uri) == '\0') fileImport = true; if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri, - typeName, type.versionMajor)) { + typeName, type.version)) { return QQmlType(); } @@ -533,7 +528,7 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit bool fileImport = false; if (*(type.uri) == '\0') fileImport = true; - if (!checkRegistration(QQmlType::CompositeType, data, fileImport?nullptr:type.uri, typeName, type.versionMajor)) + if (!checkRegistration(QQmlType::CompositeType, data, fileImport?nullptr:type.uri, typeName, type.version)) return QQmlType(); QQmlTypePrivate *priv = createQQmlType(data, typeName, type); @@ -581,7 +576,7 @@ void QQmlMetaType::unregisterInternalCompositeType(const CompositeMetaTypeIds &t int QQmlMetaType::registerUnitCacheHook( const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration) { - if (hookRegistration.version > 0) + if (hookRegistration.structVersion > 0) qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); QQmlMetaTypeDataPtr data; @@ -589,40 +584,37 @@ int QQmlMetaType::registerUnitCacheHook( return 0; } -bool QQmlMetaType::protectModule(const QString &uri, int majVersion) +bool QQmlMetaType::protectModule(const QString &uri, QTypeRevision version) { QQmlMetaTypeDataPtr data; - QQmlMetaTypeData::VersionedUri versionedUri; - versionedUri.uri = uri; - versionedUri.majorVersion = majVersion; - - if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) { + if (QQmlTypeModule* qqtm = data->uriToModule.value( + QQmlMetaTypeData::VersionedUri(uri, version), nullptr)) { qqtm->lock(); return true; } return false; } -void QQmlMetaType::registerModule(const char *uri, int versionMajor, int versionMinor) +void QQmlMetaType::registerModule(const char *uri, QTypeRevision version) { QQmlMetaTypeDataPtr data; - QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data); + QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), version, data); Q_ASSERT(module); - module->addMinorVersion(versionMinor); + module->addMinorVersion(version.minorVersion()); } -int QQmlMetaType::typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName) +int QQmlMetaType::typeId(const char *uri, QTypeRevision version, const char *qmlName) { QQmlMetaTypeDataPtr data; - QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data); + QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), version, data); if (!module) return -1; - QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), versionMinor); + QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), version); if (!type.isValid()) return -1; @@ -636,12 +628,12 @@ void QQmlMetaType::registerUndeletableType(const QQmlType &dtype) } static bool namespaceContainsRegistrations(const QQmlMetaTypeData *data, const QString &uri, - int majorVersion) + QTypeRevision version) { // Has any type previously been installed to this namespace? QHashedString nameSpace(uri); for (const QQmlType &type : data->types) { - if (type.module() == nameSpace && type.majorVersion() == majorVersion) + if (type.module() == nameSpace && type.version().majorVersion() == version.majorVersion()) return true; } @@ -668,8 +660,8 @@ public: bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, int vmaj, - QList<QQmlError> *errors) + const QString &uri, const QString &typeNamespace, + QTypeRevision version, QList<QQmlError> *errors) { if (!typeNamespace.isEmpty() && typeNamespace != uri) { // This is an 'identified' module @@ -690,7 +682,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat QQmlMetaTypeRegistrationFailureRecorder failureRecorder(data, &failures); if (!typeNamespace.isEmpty()) { // This is an 'identified' module - if (namespaceContainsRegistrations(data, typeNamespace, vmaj)) { + if (namespaceContainsRegistrations(data, typeNamespace, version)) { // Other modules have already installed to this namespace if (errors) { QQmlError error; @@ -732,7 +724,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat iface->registerTypes(moduleId); } - data->registerModuleTypes(QQmlMetaTypeData::VersionedUri(uri, vmaj)); + data->registerModuleTypes(uri); if (!failures.isEmpty()) { if (errors) { @@ -763,7 +755,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat QQmlType QQmlMetaType::typeForUrl(const QString &urlString, const QHashedStringRef &qualifiedType, bool isCompositeSingleton, QList<QQmlError> *errors, - int majorVersion, int minorVersion) + QTypeRevision version) { // ### unfortunate (costly) conversion const QUrl url = QQmlTypeLoader::normalize(QUrl(urlString)); @@ -808,11 +800,10 @@ QQmlType QQmlMetaType::typeForUrl(const QString &urlString, const QQmlType::RegistrationType registrationType = isCompositeSingleton ? QQmlType::CompositeSingletonType : QQmlType::CompositeType; - if (checkRegistration(registrationType, data, nullptr, typeName, majorVersion)) { + if (checkRegistration(registrationType, data, nullptr, typeName, version)) { auto *priv = new QQmlTypePrivate(registrationType); priv->setName(QString(), typeName); - priv->version_maj = majorVersion; - priv->version_min = minorVersion; + priv->version = version; if (isCompositeSingleton) { priv->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo; @@ -865,14 +856,12 @@ bool QQmlMetaType::isAnyModule(const QString &uri) /* Returns true if a module \a uri of this version is installed and locked; */ -bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion) +bool QQmlMetaType::isLockedModule(const QString &uri, QTypeRevision version) { QQmlMetaTypeDataPtr data; - QQmlMetaTypeData::VersionedUri versionedUri; - versionedUri.uri = uri; - versionedUri.majorVersion = majVersion; - if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) + if (QQmlTypeModule* qqtm = data->uriToModule.value( + QQmlMetaTypeData::VersionedUri(uri, version), nullptr)) return qqtm->isLocked(); return false; } @@ -884,24 +873,24 @@ bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion) So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10. */ -bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor) +bool QQmlMetaType::isModule(const QString &module, QTypeRevision version) { - Q_ASSERT(versionMajor >= 0 && versionMinor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); QQmlMetaTypeDataPtr data; // first, check Types QQmlTypeModule *tm = - data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor)); - if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor) + data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, version)); + if (tm && tm->minimumMinorVersion() <= version.minorVersion() && tm->maximumMinorVersion() >= version.minorVersion()) return true; return false; } -QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion) +QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, QTypeRevision version) { QQmlMetaTypeDataPtr data; - return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion)); + return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, version)); } QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions() @@ -1120,7 +1109,7 @@ QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type) Returns the type (if any) of URI-qualified named \a qualifiedName and version specified by \a version_major and \a version_minor. */ -QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, QTypeRevision version) { int slash = qualifiedName.indexOf(QLatin1Char('/')); if (slash <= 0) @@ -1129,23 +1118,23 @@ QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, QHashedStringRef module(qualifiedName.constData(), slash); QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.length() - slash - 1); - return qmlType(name, module, version_major, version_minor); + return qmlType(name, module, version); } /*! Returns the type (if any) of \a name in \a module and version specified by \a version_major and \a version_minor. */ -QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, + QTypeRevision version) { - Q_ASSERT(version_major >= 0 && version_minor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); const QQmlMetaTypeDataPtr data; QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name); while (it != data->nameToType.cend() && it.key() == name) { QQmlType t(*it); - // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty - if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor)) + if (module.isEmpty() || t.availableInVersion(module, version)) return t; ++it; } @@ -1168,15 +1157,16 @@ QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject) by \a version_major and \a version_minor in module specified by \a uri. Returns null if no type is registered. */ -QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, + QTypeRevision version) { - Q_ASSERT(version_major >= 0 && version_minor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); const QQmlMetaTypeDataPtr data; QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject); while (it != data->metaObjectToType.cend() && it.key() == metaObject) { QQmlType t(*it); - if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor)) + if (module.isEmpty() || t.availableInVersion(module, version)) return t; ++it; } @@ -1226,16 +1216,16 @@ QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileI return QQmlType(); } -QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, int minorVersion) +QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, QTypeRevision version) { QQmlMetaTypeDataPtr data; // not const: the cache is created on demand - return data->propertyCache(metaObject, minorVersion); + return data->propertyCache(metaObject, version); } -QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, int minorVersion) +QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, QTypeRevision version) { QQmlMetaTypeDataPtr data; // not const: the cache is created on demand - return data->propertyCache(type, minorVersion); + return data->propertyCache(type, version); } void QQmlMetaType::unregisterType(int typeIndex) @@ -1250,7 +1240,7 @@ void QQmlMetaType::unregisterType(int typeIndex) removeQQmlTypePrivate(data->metaObjectToType, d); for (auto & module : data->uriToModule) module->remove(d); - data->clearPropertyCachesForMinorVersion(typeIndex); + data->clearPropertyCachesForVersion(typeIndex); data->types[typeIndex] = QQmlType(); data->undeletableTypes.remove(type); } @@ -1282,7 +1272,7 @@ void QQmlMetaType::freeUnusedTypesAndCaches() for (auto &module : data->uriToModule) module->remove(d); - data->clearPropertyCachesForMinorVersion(d->index); + data->clearPropertyCachesForVersion(d->index); *it = QQmlType(); } else { ++it; diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 0c5bc043c4..0fc179fd34 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -81,20 +81,20 @@ public: static QQmlType registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type); static QQmlType registerCompositeType(const QQmlPrivate::RegisterCompositeType &type); static bool registerPluginTypes(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, int vmaj, - QList<QQmlError> *errors); + const QString &uri, const QString &typeNamespace, + QTypeRevision version, QList<QQmlError> *errors); static QQmlType typeForUrl(const QString &urlString, const QHashedStringRef& typeName, bool isCompositeSingleton, QList<QQmlError> *errors, - int majorVersion = -1, int minorVersion = -1); + QTypeRevision version = QTypeRevision()); static void unregisterType(int type); static CompositeMetaTypeIds registerInternalCompositeType(const QByteArray &className); static void unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds); - static void registerModule(const char *uri, int versionMajor, int versionMinor); - static bool protectModule(const QString &uri, int majVersion); + static void registerModule(const char *uri, QTypeRevision version); + static bool protectModule(const QString &uri, QTypeRevision version); - static int typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName); + static int typeId(const char *uri, QTypeRevision version, const char *qmlName); static void registerUndeletableType(const QQmlType &dtype); @@ -108,15 +108,16 @@ public: QmlType }; - static QQmlType qmlType(const QString &qualifiedName, int, int); - static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int); + static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version); + static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, QTypeRevision version); static QQmlType qmlType(const QMetaObject *); - static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor); + static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, QTypeRevision version); static QQmlType qmlType(int typeId, TypeIdCategory category = TypeIdCategory::MetaType); static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false); - static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion = -1); - static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); + static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, + QTypeRevision version = QTypeRevision()); + static QQmlPropertyCache *propertyCache(const QQmlType &type, QTypeRevision version); static void freeUnusedTypesAndCaches(); @@ -150,9 +151,9 @@ public: static StringConverter customStringConverter(int); static bool isAnyModule(const QString &uri); - static bool isLockedModule(const QString &uri, int majorVersion); - static bool isModule(const QString &module, int versionMajor, int versionMinor); - static QQmlTypeModule *typeModule(const QString &uri, int majorVersion); + static bool isLockedModule(const QString &uri, QTypeRevision version); + static bool isModule(const QString &module, QTypeRevision version); + static QQmlTypeModule *typeModule(const QString &uri, QTypeRevision version); static QList<QQmlPrivate::AutoParentFunction> parentFunctions(); @@ -197,11 +198,10 @@ public: static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd); - static void qmlInsertModuleRegistration(const QString &uri, int majorVersion, - void (*registerFunction)()); - static void qmlRemoveModuleRegistration(const QString &uri, int majorVersion); + static void qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)()); + static void qmlRemoveModuleRegistration(const QString &uri); - static bool qmlRegisterModuleTypes(const QString &uri, int majorVersion); + static bool qmlRegisterModuleTypes(const QString &uri); static int qmlRegisteredListTypeCount(); }; diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp index ed885eaa97..a34a0c1ae4 100644 --- a/src/qml/qml/qqmlmetatypedata.cpp +++ b/src/qml/qml/qqmlmetatypedata.cpp @@ -78,9 +78,9 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv) priv->release(); } -bool QQmlMetaTypeData::registerModuleTypes(const QQmlMetaTypeData::VersionedUri &versionedUri) +bool QQmlMetaTypeData::registerModuleTypes(const QString &uri) { - auto function = moduleTypeRegistrationFunctions.constFind(versionedUri); + auto function = moduleTypeRegistrationFunctions.constFind(uri); if (function != moduleTypeRegistrationFunctions.constEnd()) { (*function)(); return true; @@ -88,28 +88,28 @@ bool QQmlMetaTypeData::registerModuleTypes(const QQmlMetaTypeData::VersionedUri return false; } -QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForMinorVersion(int index, int minorVersion) const +QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForVersion(int index, QTypeRevision version) const { return (index < typePropertyCaches.length()) - ? typePropertyCaches.at(index).value(minorVersion).data() + ? typePropertyCaches.at(index).value(version).data() : nullptr; } -void QQmlMetaTypeData::setPropertyCacheForMinorVersion(int index, int minorVersion, - QQmlPropertyCache *cache) +void QQmlMetaTypeData::setPropertyCacheForVersion(int index, QTypeRevision version, + QQmlPropertyCache *cache) { if (index >= typePropertyCaches.length()) typePropertyCaches.resize(index + 1); - typePropertyCaches[index][minorVersion] = cache; + typePropertyCaches[index][version] = cache; } -void QQmlMetaTypeData::clearPropertyCachesForMinorVersion(int index) +void QQmlMetaTypeData::clearPropertyCachesForVersion(int index) { if (index < typePropertyCaches.length()) typePropertyCaches[index].clear(); } -QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion) +QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, QTypeRevision version) { if (QQmlPropertyCache *rv = propertyCaches.value(metaObject)) return rv; @@ -119,29 +119,36 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject propertyCaches.insert(metaObject, rv); return rv; } - QQmlPropertyCache *super = propertyCache(metaObject->superClass(), minorVersion); - QQmlPropertyCache *rv = super->copyAndAppend(metaObject, minorVersion); + QQmlPropertyCache *super = propertyCache(metaObject->superClass(), version); + QQmlPropertyCache *rv = super->copyAndAppend(metaObject, version); propertyCaches.insert(metaObject, rv); return rv; } -QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion) +QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRevision version) { Q_ASSERT(type.isValid()); - if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), minorVersion)) + if (QQmlPropertyCache *pc = propertyCacheForVersion(type.index(), version)) return pc; QVector<QQmlType> types; - int maxMinorVersion = 0; + quint8 maxMinorVersion = 0; const QMetaObject *metaObject = type.metaObject(); + const QTypeRevision combinedVersion = version.hasMajorVersion() + ? version + : (version.hasMinorVersion() + ? QTypeRevision::fromVersion(type.version().majorVersion(), + version.minorVersion()) + : type.version()); + while (metaObject) { - QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), type.majorVersion(), minorVersion); + QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), combinedVersion); if (t.isValid()) { - maxMinorVersion = qMax(maxMinorVersion, t.minorVersion()); + maxMinorVersion = qMax(maxMinorVersion, t.version().minorVersion()); types << t; } else { types << QQmlType(); @@ -150,12 +157,14 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min metaObject = metaObject->superClass(); } - if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), maxMinorVersion)) { - setPropertyCacheForMinorVersion(type.index(), minorVersion, pc); + const QTypeRevision maxVersion = QTypeRevision::fromVersion(combinedVersion.majorVersion(), + maxMinorVersion); + if (QQmlPropertyCache *pc = propertyCacheForVersion(type.index(), maxVersion)) { + setPropertyCacheForVersion(type.index(), maxVersion, pc); return pc; } - QQmlPropertyCache *raw = propertyCache(type.metaObject(), minorVersion); + QQmlPropertyCache *raw = propertyCache(type.metaObject(), combinedVersion); bool hasCopied = false; @@ -164,7 +173,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min if (!currentType.isValid()) continue; - int rev = currentType.metaObjectRevision(); + QTypeRevision rev = currentType.metaObjectRevision(); int moIndex = types.count() - 1 - ii; if (raw->allowedRevision(moIndex) != rev) { @@ -222,13 +231,13 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min } #endif - setPropertyCacheForMinorVersion(type.index(), minorVersion, raw); + setPropertyCacheForVersion(type.index(), version, raw); if (hasCopied) raw->release(); - if (minorVersion != maxMinorVersion) - setPropertyCacheForMinorVersion(type.index(), maxMinorVersion, raw); + if (version != maxVersion) + setPropertyCacheForVersion(type.index(), maxVersion, raw); return raw; } diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h index e51d4ca1a4..26fc566653 100644 --- a/src/qml/qml/qqmlmetatypedata_p.h +++ b/src/qml/qml/qqmlmetatypedata_p.h @@ -83,25 +83,24 @@ struct QQmlMetaTypeData MetaObjects metaObjectToType; typedef QHash<int, QQmlMetaType::StringConverter> StringConverters; StringConverters stringConverters; - QVector<QHash<int, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches; + QVector<QHash<QTypeRevision, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches; struct VersionedUri { - VersionedUri() - : majorVersion(0) {} - VersionedUri(const QHashedString &uri, int majorVersion) - : uri(uri), majorVersion(majorVersion) {} + VersionedUri() : majorVersion(0) {} + VersionedUri(const QHashedString &uri, QTypeRevision version) + : uri(uri), majorVersion(version.majorVersion()) {} bool operator==(const VersionedUri &other) const { return other.majorVersion == majorVersion && other.uri == uri; } QHashedString uri; - int majorVersion; + quint8 majorVersion; }; typedef QHash<VersionedUri, QQmlTypeModule *> TypeModules; TypeModules uriToModule; - QHash<VersionedUri, void (*)()> moduleTypeRegistrationFunctions; - bool registerModuleTypes(const VersionedUri &versionedUri); + QHash<QString, void (*)()> moduleTypeRegistrationFunctions; + bool registerModuleTypes(const QString &uri); QBitArray objects; QBitArray interfaces; @@ -114,12 +113,12 @@ struct QQmlMetaTypeData QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches; - QQmlPropertyCache *propertyCacheForMinorVersion(int index, int minorVersion) const; - void setPropertyCacheForMinorVersion(int index, int minorVersion, QQmlPropertyCache *cache); - void clearPropertyCachesForMinorVersion(int index); + QQmlPropertyCache *propertyCacheForVersion(int index, QTypeRevision version) const; + void setPropertyCacheForVersion(int index, QTypeRevision version, QQmlPropertyCache *cache); + void clearPropertyCachesForVersion(int index); - QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion); - QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); + QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, QTypeRevision version); + QQmlPropertyCache *propertyCache(const QQmlType &type, QTypeRevision version); void setTypeRegistrationFailures(QStringList *failures) { diff --git a/src/qml/qml/qqmlmoduleregistration.cpp b/src/qml/qml/qqmlmoduleregistration.cpp index b7bc3555a6..422a5c0551 100644 --- a/src/qml/qml/qqmlmoduleregistration.cpp +++ b/src/qml/qml/qqmlmoduleregistration.cpp @@ -39,27 +39,33 @@ #include <QtQml/private/qqmlmetatype_p.h> #include <QtQml/qqmlmoduleregistration.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE struct QQmlModuleRegistrationPrivate { const QString uri; - const int majorVersion; }; +QQmlModuleRegistration::QQmlModuleRegistration(const char *uri, void (*registerFunction)()) : + d(new QQmlModuleRegistrationPrivate { QString::fromUtf8(uri) }) +{ + QQmlMetaType::qmlInsertModuleRegistration(d->uri, registerFunction); +} + +#if QT_DEPRECATED_SINCE(6, 0) QQmlModuleRegistration::QQmlModuleRegistration( - const char *uri, int majorVersion, - void (*registerFunction)()) : - d(new QQmlModuleRegistrationPrivate { QString::fromUtf8(uri), majorVersion }) + const char *uri, int majorVersion, void (*registerFunction)()) : + QQmlModuleRegistration(uri, registerFunction) { - QQmlMetaType::qmlInsertModuleRegistration(d->uri, d->majorVersion, - registerFunction); + Q_UNUSED(majorVersion); } +#endif QQmlModuleRegistration::~QQmlModuleRegistration() { - QQmlMetaType::qmlRemoveModuleRegistration(d->uri, d->majorVersion); + QQmlMetaType::qmlRemoveModuleRegistration(d->uri); delete d; } diff --git a/src/qml/qml/qqmlmoduleregistration.h b/src/qml/qml/qqmlmoduleregistration.h index 6f553a2823..3db535faa0 100644 --- a/src/qml/qml/qqmlmoduleregistration.h +++ b/src/qml/qml/qqmlmoduleregistration.h @@ -49,9 +49,14 @@ class Q_QML_EXPORT QQmlModuleRegistration { Q_DISABLE_COPY_MOVE(QQmlModuleRegistration) public: - QQmlModuleRegistration(const char *uri, int majorVersion, void (*registerFunction)()); + QQmlModuleRegistration(const char *uri, void (*registerFunction)()); ~QQmlModuleRegistration(); +#if QT_DEPRECATED_SINCE(6, 0) + QT_DEPRECATED_X("Use registration without major version") + QQmlModuleRegistration(const char *uri, int majorVersion, void (*registerFunction)()); +#endif + private: QQmlModuleRegistrationPrivate *d = nullptr; }; diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index d6a9e73763..2e4bc60f79 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -63,6 +63,7 @@ #include <QtCore/qvariant.h> #include <QtCore/qurl.h> #include <QtCore/qpointer.h> +#include <QtCore/qversionnumber.h> #include <QtCore/qmetaobject.h> #include <QtCore/qdebug.h> @@ -343,7 +344,7 @@ namespace QQmlPrivate typedef AutoParentResult (*AutoParentFunction)(QObject *object, QObject *parent); struct RegisterType { - int version; + int structVersion; int typeId; int listId; @@ -352,8 +353,7 @@ namespace QQmlPrivate QString noCreationReason; const char *uri; - int versionMajor; - int versionMinor; + QTypeRevision version; const char *elementName; const QMetaObject *metaObject; @@ -369,12 +369,12 @@ namespace QQmlPrivate QQmlCustomParser *customParser; - int revision; + QTypeRevision revision; // If this is extended ensure "version" is bumped!!! }; struct RegisterTypeAndRevisions { - int version; + int structVersion; int typeId; int listId; @@ -382,7 +382,7 @@ namespace QQmlPrivate void (*create)(void *); const char *uri; - int versionMajor; + QTypeRevision version; const QMetaObject *metaObject; const QMetaObject *classInfoMetaObject; @@ -401,7 +401,7 @@ namespace QQmlPrivate }; struct RegisterInterface { - int version; + int structVersion; int typeId; int listId; @@ -409,7 +409,7 @@ namespace QQmlPrivate const char *iid; const char *uri; - int versionMajor; + QTypeRevision version; }; struct RegisterAutoParent { @@ -419,26 +419,25 @@ namespace QQmlPrivate }; struct RegisterSingletonType { - int version; + int structVersion; const char *uri; - int versionMajor; - int versionMinor; + QTypeRevision version; const char *typeName; QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); QObject *(*qobjectApi)(QQmlEngine *, QJSEngine *); const QMetaObject *instanceMetaObject; // new in version 1 int typeId; // new in version 2 - int revision; // new in version 2 + QTypeRevision revision; // new in version 2 std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3 // If this is extended ensure "version" is bumped!!! }; struct RegisterSingletonTypeAndRevisions { - int version; + int structVersion; const char *uri; - int versionMajor; + QTypeRevision version; QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); const QMetaObject *instanceMetaObject; @@ -451,16 +450,14 @@ namespace QQmlPrivate struct RegisterCompositeType { QUrl url; const char *uri; - int versionMajor; - int versionMinor; + QTypeRevision version; const char *typeName; }; struct RegisterCompositeSingletonType { QUrl url; const char *uri; - int versionMajor; - int versionMinor; + QTypeRevision version; const char *typeName; }; @@ -472,7 +469,7 @@ namespace QQmlPrivate typedef const CachedQmlUnit *(*QmlUnitCacheLookupFunction)(const QUrl &url); struct RegisterQmlUnitCacheHook { - int version; + int structVersion; QmlUnitCacheLookupFunction lookupCachedQmlUnit; }; @@ -516,11 +513,13 @@ namespace QQmlPrivate return metaObject->classInfo(indexOfOwnClassInfo(metaObject, key)).value(); } - inline int intClassInfo(const QMetaObject *metaObject, const char *key, int defaultValue = 0) + inline QTypeRevision revisionClassInfo(const QMetaObject *metaObject, const char *key, + QTypeRevision defaultValue = QTypeRevision()) { const int index = indexOfOwnClassInfo(metaObject, key); return (index == -1) ? defaultValue - : QByteArray(metaObject->classInfo(index).value()).toInt(); + : QTypeRevision::fromEncodedVersion( + QByteArray(metaObject->classInfo(index).value()).toInt()); } inline bool boolClassInfo(const QMetaObject *metaObject, const char *key, @@ -605,7 +604,7 @@ namespace QQmlPrivate 0, uri, - versionMajor, + QTypeRevision::fromMajorVersion(versionMajor), nullptr, @@ -633,7 +632,7 @@ namespace QQmlPrivate Constructors<T>::createInto, uri, - versionMajor, + QTypeRevision::fromMajorVersion(versionMajor), &T::staticMetaObject, classInfoMetaObject, diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 0e5534fc04..7ba3d7b813 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -127,11 +127,11 @@ QQmlPropertyData::flagsForProperty(const QMetaProperty &p) static void populate(QQmlPropertyData *data, const QMetaProperty &p) { - Q_ASSERT(p.revision() <= Q_INT16_MAX); + Q_ASSERT(p.revision() <= std::numeric_limits<quint16>::max()); data->setCoreIndex(p.propertyIndex()); data->setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal())); data->setFlags(fastFlagsForProperty(p)); - data->setRevision(p.revision()); + data->setRevision(QTypeRevision::fromEncodedVersion(p.revision())); } void QQmlPropertyData::lazyLoad(const QMetaProperty &p) @@ -183,8 +183,8 @@ void QQmlPropertyData::load(const QMetaMethod &m) if (m.attributes() & QMetaMethod::Cloned) m_flags.setIsCloned(true); - Q_ASSERT(m.revision() <= Q_INT16_MAX); - setRevision(m.revision()); + Q_ASSERT(m.revision() <= std::numeric_limits<quint16>::max()); + setRevision(QTypeRevision::fromEncodedVersion(m.revision())); } void QQmlPropertyData::lazyLoad(const QMetaMethod &m) @@ -212,14 +212,14 @@ QQmlPropertyCache::QQmlPropertyCache() /*! Creates a new QQmlPropertyCache of \a metaObject. */ -QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, int metaObjectRevision) +QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, QTypeRevision metaObjectRevision) : QQmlPropertyCache() { Q_ASSERT(metaObject); update(metaObject); - if (metaObjectRevision > 0) { + if (metaObjectRevision.isValid() && metaObjectRevision != QTypeRevision::zero()) { // Set the revision of the meta object that this cache describes to be // 'metaObjectRevision'. This is useful when constructing a property cache // from a type that was created directly in C++, and not through QML. For such @@ -291,14 +291,15 @@ QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int meth This is different from QMetaMethod::methodIndex(). */ void QQmlPropertyCache::appendProperty(const QString &name, QQmlPropertyData::Flags flags, - int coreIndex, int propType, int minorVersion, int notifyIndex) + int coreIndex, int propType, QTypeRevision version, + int notifyIndex) { QQmlPropertyData data; data.setPropType(propType); data.setCoreIndex(coreIndex); data.setNotifyIndex(notifyIndex); data.setFlags(flags); - data.setTypeMinorVersion(minorVersion); + data.setTypeVersion(version); QQmlPropertyData *old = findNamedProperty(name); if (old) @@ -433,12 +434,12 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) { - return copyAndAppend(metaObject, -1, propertyFlags, methodFlags, signalFlags); + return copyAndAppend(metaObject, QTypeRevision(), propertyFlags, methodFlags, signalFlags); } QQmlPropertyCache * QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, - int typeMinorVersion, + QTypeRevision typeVersion, QQmlPropertyData::Flags propertyFlags, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) @@ -452,13 +453,13 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, QMetaObjectPrivate::get(metaObject)->signalCount + QMetaObjectPrivate::get(metaObject)->propertyCount); - rv->append(metaObject, typeMinorVersion, propertyFlags, methodFlags, signalFlags); + rv->append(metaObject, typeVersion, propertyFlags, methodFlags, signalFlags); return rv; } void QQmlPropertyCache::append(const QMetaObject *metaObject, - int typeMinorVersion, + QTypeRevision typeVersion, QQmlPropertyData::Flags propertyFlags, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) @@ -467,7 +468,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, bool dynamicMetaObject = isDynamicMetaObject(metaObject); - allowedRevisionCache.append(0); + allowedRevisionCache.append(QTypeRevision::zero()); int methodCount = metaObject->methodCount(); Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4); @@ -612,7 +613,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, data->setFlags(propertyFlags); data->lazyLoad(p); - data->setTypeMinorVersion(typeMinorVersion); + data->setTypeVersion(typeVersion); data->m_flags.setIsDirect(!dynamicMetaObject); @@ -697,7 +698,7 @@ void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject) updateRecur(metaObject->superClass()); - append(metaObject, -1); + append(metaObject, QTypeRevision()); } void QQmlPropertyCache::update(const QMetaObject *metaObject) @@ -745,7 +746,7 @@ void QQmlPropertyCache::invalidate(const QMetaObject *metaObject) methodIndexCacheStart = parent()->methodIndexCache.count() + parent()->methodIndexCacheStart; signalHandlerIndexCacheStart = parent()->signalHandlerIndexCache.count() + parent()->signalHandlerIndexCacheStart; stringCache.linkAndReserve(parent()->stringCache, reserve); - append(metaObject, -1); + append(metaObject, QTypeRevision()); } else { propertyIndexCacheStart = 0; methodIndexCacheStart = 0; @@ -1066,13 +1067,10 @@ static inline const QMetaObjectPrivate *priv(const uint* data) static inline const QByteArray stringData(const QMetaObject *mo, int index) { - Q_ASSERT(priv(mo->d.data)->revision >= 7); - const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo->d.stringdata[index]) }; - Q_ASSERT(data.ptr->ref.isStatic()); - Q_ASSERT(data.ptr->alloc == 0); - Q_ASSERT(data.ptr->capacityReserved == 0); - Q_ASSERT(data.ptr->size >= 0); - return data; + uint offset = mo->d.stringdata[2*index]; + uint length = mo->d.stringdata[2*index + 1]; + const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset; + return QByteArray::fromRawData(string, length); } bool QQmlPropertyCache::isDynamicMetaObject(const QMetaObject *mo) diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index a5340cec37..9e6eaf9778 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -60,6 +60,7 @@ #include <private/qlinkedstringhash_p.h> #include <QtCore/qvarlengtharray.h> #include <QtCore/qvector.h> +#include <QtCore/qversionnumber.h> #include <private/qv4value_p.h> #include <private/qqmlpropertydata_p.h> @@ -80,7 +81,7 @@ class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount { public: QQmlPropertyCache(); - QQmlPropertyCache(const QMetaObject *, int metaObjectRevision = 0); + QQmlPropertyCache(const QMetaObject *, QTypeRevision metaObjectRevision = QTypeRevision::zero()); ~QQmlPropertyCache() override; void update(const QMetaObject *); @@ -92,7 +93,8 @@ public: QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags()); - QQmlPropertyCache *copyAndAppend(const QMetaObject *, int typeMinorVersion, + QQmlPropertyCache *copyAndAppend( + const QMetaObject *, QTypeRevision typeVersion, QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags()); @@ -100,7 +102,7 @@ public: QQmlPropertyCache *copyAndReserve(int propertyCount, int methodCount, int signalCount, int enumCount); void appendProperty(const QString &, QQmlPropertyData::Flags flags, int coreIndex, - int propType, int revision, int notifyIndex); + int propType, QTypeRevision revision, int notifyIndex); void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex, const int *types = nullptr, const QList<QByteArray> &names = QList<QByteArray>()); void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex, int returnType, @@ -174,8 +176,8 @@ public: QByteArray checksum(bool *ok); - int allowedRevision(int index) const { return allowedRevisionCache[index]; } - void setAllowedRevision(int index, int allowed) { allowedRevisionCache[index] = allowed; } + QTypeRevision allowedRevision(int index) const { return allowedRevisionCache[index]; } + void setAllowedRevision(int index, QTypeRevision allowed) { allowedRevisionCache[index] = allowed; } private: friend class QQmlEnginePrivate; @@ -187,7 +189,7 @@ private: inline QQmlPropertyCache *copy(int reserve); - void append(const QMetaObject *, int typeMinorVersion, + void append(const QMetaObject *, QTypeRevision typeVersion, QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags()); @@ -196,7 +198,7 @@ private: typedef QVector<QQmlPropertyData> IndexCache; typedef QLinkedStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache; - typedef QVector<int> AllowedRevisionCache; + typedef QVector<QTypeRevision> AllowedRevisionCache; QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *, QQmlContextData *) const; QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *, QQmlContextData *) const; @@ -352,8 +354,9 @@ QQmlPropertyCache::overrideData(QQmlPropertyData *data) const bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const { - return (data->metaObjectOffset() == -1 && data->revision() == 0) || - (allowedRevisionCache[data->metaObjectOffset()] >= data->revision()); + return (data->metaObjectOffset() == -1 && data->revision() == QTypeRevision::zero()) + || (allowedRevisionCache[data->metaObjectOffset()].toEncodedVersion<quint16>() + >= data->revision().toEncodedVersion<quint16>()); } int QQmlPropertyCache::propertyCount() const diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp index 36581bda4e..f132fb2d78 100644 --- a/src/qml/qml/qqmlpropertycachecreator.cpp +++ b/src/qml/qml/qqmlpropertycachecreator.cpp @@ -119,9 +119,12 @@ QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiating { if (instantiatingProperty) { if (instantiatingProperty->isQObject()) { - return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(), instantiatingProperty->typeMinorVersion()); + // rawPropertyCacheForType assumes a given unspecified version means "any version". + // There is another overload that takes no version, which we shall not use here. + return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(), + instantiatingProperty->typeVersion()); } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType())) { - return enginePrivate->cache(vtmo, instantiatingProperty->typeMinorVersion()); + return enginePrivate->cache(vtmo, instantiatingProperty->typeVersion()); } } return QQmlRefPointer<QQmlPropertyCache>(); diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index d99f5b6e98..5e26eb1ea7 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -538,7 +538,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea pend = obj->propertiesEnd(); for ( ; p != pend; ++p, ++propertyIdx) { int propertyType = 0; - int propertTypeMinorVersion = 0; + QTypeRevision propertyTypeVersion = QTypeRevision::zero(); QQmlPropertyData::Flags propertyFlags; const QV4::CompiledData::BuiltinType type = p->builtinType(); @@ -557,7 +557,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea QQmlType qmltype; bool selfReference = false; - if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex), &qmltype, nullptr, nullptr, nullptr, + if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex), &qmltype, nullptr, nullptr, nullptr, QQmlType::AnyRegistrationType, &selfReference)) { return qQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Invalid property type")); } @@ -599,7 +599,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea propertyType = qmltype.qListTypeId(); } else { propertyType = qmltype.typeId(); - propertTypeMinorVersion = qmltype.minorVersion(); + propertyTypeVersion = qmltype.version(); } } @@ -617,7 +617,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias) cache->_defaultPropertyName = propertyName; cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, - propertyType, propertTypeMinorVersion, effectiveSignalIndex); + propertyType, propertyTypeVersion, effectiveSignalIndex); effectiveSignalIndex++; } @@ -641,8 +641,8 @@ inline int QQmlPropertyCacheCreator<ObjectContainer>::metaTypeForParameter(const *customTypeName = typeName; QQmlType qmltype; bool selfReference = false; - if (!imports->resolveType(typeName, &qmltype, nullptr, nullptr, nullptr, nullptr, QQmlType::AnyRegistrationType, - &selfReference)) + if (!imports->resolveType(typeName, &qmltype, nullptr, nullptr, nullptr, + QQmlType::AnyRegistrationType, &selfReference)) return QMetaType::UnknownType; if (!qmltype.isComposite()) @@ -674,7 +674,7 @@ public: private: void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex, QQmlEnginePrivate *enginePriv); - QQmlJS::DiagnosticMessage propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv); + QQmlJS::DiagnosticMessage propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv); void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const; @@ -785,7 +785,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl } template <typename ObjectContainer> -inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion, +inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv) { *type = 0; @@ -818,7 +818,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: lastAlias = targetAlias; } while (lastAlias->aliasToLocalAlias); - return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags, enginePriv); + return propertyDataForAlias(component, *lastAlias, type, version, propertyFlags, enginePriv); } const int targetObjectIndex = objectForId(component, alias.targetObjectId); @@ -841,7 +841,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: else *type = typeRef->compilationUnit->metaTypeId; - *minorVersion = typeRef->minorVersion; + *version = typeRef->version; propertyFlags->type = QQmlPropertyData::Flags::QObjectDerivedType; } else { @@ -920,9 +920,10 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved); int type = 0; - int minorVersion = 0; + QTypeRevision version = QTypeRevision::zero(); QQmlPropertyData::Flags propertyFlags; - QQmlJS::DiagnosticMessage error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags, enginePriv); + QQmlJS::DiagnosticMessage error = propertyDataForAlias(component, *alias, &type, &version, + &propertyFlags, enginePriv); if (error.isValid()) return error; @@ -932,7 +933,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>: propertyCache->_defaultPropertyName = propertyName; propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, - type, minorVersion, effectiveSignalIndex++); + type, version, effectiveSignalIndex++); } return QQmlJS::DiagnosticMessage(); diff --git a/src/qml/qml/qqmlpropertydata_p.h b/src/qml/qml/qqmlpropertydata_p.h index 7f70c34854..f21b502b50 100644 --- a/src/qml/qml/qqmlpropertydata_p.h +++ b/src/qml/qml/qqmlpropertydata_p.h @@ -53,6 +53,7 @@ #include <private/qobject_p.h> #include <QtCore/qglobal.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -251,7 +252,7 @@ public: bool isConstructor() const { return m_flags.isConstructor; } bool hasOverride() const { return overrideIndex() >= 0; } - bool hasRevision() const { return revision() != 0; } + bool hasRevision() const { return revision() != QTypeRevision::zero(); } bool isFullyResolved() const { return !m_flags.notFullyResolved; } @@ -290,12 +291,8 @@ public: m_coreIndex = qint16(idx); } - quint8 revision() const { return m_revision; } - void setRevision(quint8 rev) - { - Q_ASSERT(rev <= std::numeric_limits<quint8>::max()); - m_revision = quint8(rev); - } + QTypeRevision revision() const { return m_revision; } + void setRevision(QTypeRevision revision) { m_revision = revision; } /* If a property is a C++ type, then we store the minor * version of this type. @@ -315,12 +312,8 @@ public: * */ - quint8 typeMinorVersion() const { return m_typeMinorVersion; } - void setTypeMinorVersion(quint8 rev) - { - Q_ASSERT(rev <= std::numeric_limits<quint8>::max()); - m_typeMinorVersion = quint8(rev); - } + QTypeRevision typeVersion() const { return m_typeVersion; } + void setTypeVersion(QTypeRevision typeVersion) { m_typeVersion = typeVersion; } QQmlPropertyCacheMethodArguments *arguments() const { return m_arguments; } void setArguments(QQmlPropertyCacheMethodArguments *args) { m_arguments = args; } @@ -412,18 +405,20 @@ private: qint16 m_notifyIndex = -1; qint16 m_overrideIndex = -1; - quint8 m_revision = 0; - quint8 m_typeMinorVersion = 0; qint16 m_metaObjectOffset = -1; + quint16 m_reserved = 0; + + QTypeRevision m_revision = QTypeRevision::zero(); + QTypeRevision m_typeVersion = QTypeRevision::zero(); QQmlPropertyCacheMethodArguments *m_arguments = nullptr; StaticMetaCallFunction m_staticMetaCallFunction = nullptr; }; #if QT_POINTER_SIZE == 4 - Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 24); + Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 28); #else // QT_POINTER_SIZE == 8 - Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 32); + Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 40); #endif bool QQmlPropertyData::operator==(const QQmlPropertyData &other) const diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp index c897ac8751..3fb2eb399f 100644 --- a/src/qml/qml/qqmlpropertyvalidator.cpp +++ b/src/qml/qml/qqmlpropertyvalidator.cpp @@ -192,7 +192,10 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( 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->majorVersion).arg(objectType->minorVersion)); + 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())); } else { return recordError(binding->location, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name)); } @@ -212,7 +215,7 @@ QVector<QQmlJS::DiagnosticMessage> QQmlPropertyValidator::validateObject( if (name.constData()->isUpper() && !binding->isAttachedProperty()) { QQmlType type; QQmlImportNamespace *typeNamespace = nullptr; - imports.resolveType(stringAt(binding->propertyNameIndex), &type, nullptr, nullptr, &typeNamespace); + imports.resolveType(stringAt(binding->propertyNameIndex), &type, nullptr, &typeNamespace); if (typeNamespace) return recordError(binding->location, tr("Invalid use of namespace")); return recordError(binding->location, tr("Invalid attached object assignment")); @@ -744,8 +747,8 @@ QQmlJS::DiagnosticMessage QQmlPropertyValidator::validateObjectBinding(QQmlPrope // We want to use the raw metaObject here as the raw metaobject is the // actual property type before we applied any extensions that might // effect the properties on the type, but don't effect assignability - // Using -1 for the minor version ensures that we get the raw metaObject. - QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(propType, -1); + // Not passing a version ensures that we get the raw metaObject. + QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(propType); if (propertyMetaObject) { // Will be true if the assigned type inherits propertyMetaObject diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index 96a35b0fe9..047da376c6 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) - : regType(type), iid(nullptr), typeId(0), listId(0), revision(0), + : regType(type), iid(nullptr), typeId(0), listId(0), revision(QTypeRevision::zero()), containsRevisionedAttributes(false), baseMetaObject(nullptr), index(-1), isSetup(false), isEnumFromCacheSetup(false), isEnumFromBaseSetup(false), haveSuperType(false) @@ -132,34 +132,29 @@ QHashedString QQmlType::module() const return d->module; } -int QQmlType::majorVersion() const +QTypeRevision QQmlType::version() const { if (!d) - return -1; - return d->version_maj; -} - -int QQmlType::minorVersion() const -{ - if (!d) - return -1; - return d->version_min; + return QTypeRevision(); + return d->version; } -bool QQmlType::availableInVersion(int vmajor, int vminor) const +bool QQmlType::availableInVersion(QTypeRevision version) const { - Q_ASSERT(vmajor >= 0 && vminor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); if (!d) return false; - return vmajor == d->version_maj && vminor >= d->version_min; + return version.majorVersion() == d->version.majorVersion() + && version.minorVersion() >= d->version.minorVersion(); } -bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const +bool QQmlType::availableInVersion(const QHashedStringRef &module, QTypeRevision version) const { - Q_ASSERT(vmajor >= 0 && vminor >= 0); + Q_ASSERT(version.hasMajorVersion() && version.hasMinorVersion()); if (!d) return false; - return module == d->module && vmajor == d->version_maj && vminor >= d->version_min; + return module == d->module && version.majorVersion() == d->version.majorVersion() + && version.minorVersion() >= d->version.minorVersion(); } QQmlType QQmlTypePrivate::resolveCompositeBaseType(QQmlEnginePrivate *engine) const @@ -629,9 +624,9 @@ bool QQmlType::containsRevisionedAttributes() const return d->containsRevisionedAttributes; } -int QQmlType::metaObjectRevision() const +QTypeRevision QQmlType::metaObjectRevision() const { - return d ? d->revision : -1; + return d ? d->revision : QTypeRevision(); } QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h index 387baa74bb..c33cad7c88 100644 --- a/src/qml/qml/qqmltype_p.h +++ b/src/qml/qml/qqmltype_p.h @@ -60,6 +60,7 @@ #include <QtQml/qjsvalue.h> #include <QtCore/qobject.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -98,11 +99,10 @@ public: QString elementName() const; QHashedString module() const; - int majorVersion() const; - int minorVersion() const; + QTypeRevision version() const; - bool availableInVersion(int vmajor, int vminor) const; - bool availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const; + bool availableInVersion(QTypeRevision version) const; + bool availableInVersion(const QHashedStringRef &module, QTypeRevision version) const; QObject *create() const; void create(QObject **, void **, size_t) const; @@ -129,7 +129,7 @@ public: const QMetaObject *metaObject() const; const QMetaObject *baseMetaObject() const; - int metaObjectRevision() const; + QTypeRevision metaObjectRevision() const; bool containsRevisionedAttributes() const; QQmlAttachedPropertiesFunc attachedPropertiesFunction(QQmlEnginePrivate *engine) const; diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h index 43344827db..0d493c4871 100644 --- a/src/qml/qml/qqmltype_p_p.h +++ b/src/qml/qml/qqmltype_p_p.h @@ -157,11 +157,10 @@ public: QHashedString module; QString name; QString elementName; - int version_maj; - int version_min; int typeId; int listId; - int revision; + QTypeRevision version; + QTypeRevision revision; mutable bool containsRevisionedAttributes; mutable QQmlType superType; const QMetaObject *baseMetaObject; diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp index d527fe0335..3518b21a70 100644 --- a/src/qml/qml/qqmltypecompiler.cpp +++ b/src/qml/qml/qqmltypecompiler.cpp @@ -257,7 +257,7 @@ QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scrip return object->bindingAsString(document, scriptIndex); } -void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion) +void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier, QTypeRevision version) { const quint32 moduleIdx = registerString(module); const quint32 qualifierIdx = registerString(qualifier); @@ -272,8 +272,7 @@ void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier auto pool = memoryPool(); QV4::CompiledData::Import *import = pool->New<QV4::CompiledData::Import>(); import->type = QV4::CompiledData::Import::ImportLibrary; - import->majorVersion = majorVersion; - import->minorVersion = minorVersion; + import->version = version; import->uriIndex = moduleIdx; import->qualifierIndex = qualifierIdx; document->imports.append(import); @@ -394,7 +393,10 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio auto *typeRef = resolvedType(obj->inheritedTypeNameIndex); 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()).arg(type.majorVersion()).arg(type.minorVersion())); + COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.") + .arg(typeName).arg(originalPropertyName).arg(type.module()) + .arg(type.version().majorVersion()) + .arg(type.version().minorVersion())); } else { COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(originalPropertyName)); } @@ -530,12 +532,6 @@ bool QQmlEnumTypeResolver::resolveEnumBindings() return true; } -struct StaticQtMetaObject : public QObject -{ - static const QMetaObject *get() - { return &staticQtMetaObject; } -}; - bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject) { if (enumName.length() > 0 && enumName[0].isLower() && !isQtObject) { @@ -626,7 +622,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, value = type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok); } else { QByteArray enumName = enumValue.toUtf8(); - const QMetaObject *metaObject = StaticQtMetaObject::get(); + const QMetaObject *metaObject = &Qt::staticMetaObject; for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) { QMetaEnum e = metaObject->enumerator(ii); value = e.keyToValue(enumName.constData(), &ok); @@ -655,7 +651,7 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QStringRef &e return type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue.constData(), enumValue.length()), ok); } - const QMetaObject *mo = StaticQtMetaObject::get(); + const QMetaObject *mo = &Qt::staticMetaObject; int i = mo->enumeratorCount(); const QByteArray ba = enumValue.toUtf8(); while (i--) { @@ -822,7 +818,12 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI if (!pd || !pd->isQObject()) continue; - QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeMinorVersion()); + // If the version is given, use it and look up by QQmlType. + // Otherwise, make sure we look up by metaobject. + // TODO: Is this correct? + QQmlPropertyCache *pc = pd->typeVersion().hasMinorVersion() + ? enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeVersion()) + : enginePrivate->rawPropertyCacheForType(pd->propType()); const QMetaObject *mo = pc ? pc->firstCppMetaObject() : nullptr; while (mo) { if (mo == &QQmlComponent::staticMetaObject) @@ -838,7 +839,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI Q_ASSERT(componentType.isValid()); const QString qualifier = QStringLiteral("QmlInternals"); - compiler->addImport(componentType.module(), qualifier, componentType.majorVersion(), componentType.minorVersion()); + compiler->addImport(componentType.module(), qualifier, componentType.version()); QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>(); syntheticComponent->init(pool, compiler->registerString(qualifier + QLatin1Char('.') + componentType.elementName()), compiler->registerString(QString())); @@ -848,8 +849,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) { auto typeRef = new QV4::ResolvedTypeReference; typeRef->type = componentType; - typeRef->majorVersion = componentType.majorVersion(); - typeRef->minorVersion = componentType.minorVersion(); + typeRef->version = componentType.version(); insertResolvedType(syntheticComponent->inheritedTypeNameIndex, typeRef); } diff --git a/src/qml/qml/qqmltypecompiler_p.h b/src/qml/qml/qqmltypecompiler_p.h index 319df8673b..050c75b30d 100644 --- a/src/qml/qml/qqmltypecompiler_p.h +++ b/src/qml/qml/qqmltypecompiler_p.h @@ -124,7 +124,7 @@ public: QString bindingAsString(const QmlIR::Object *object, int scriptIndex) const; - void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion); + void addImport(const QString &module, const QString &qualifier, QTypeRevision version); QV4::ResolvedTypeReference *resolvedType(int id) const { diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index ebe4e32b48..30d50b911e 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -182,8 +182,8 @@ bool QQmlTypeData::tryLoadFromDiskCache() const QV4::CompiledData::Import *import = m_compiledData->importAt(i); if (m_compiledData->stringAt(import->uriIndex) == QLatin1String(".") && import->qualifierIndex == 0 - && import->majorVersion == -1 - && import->minorVersion == -1) { + && !import->version.hasMajorVersion() + && !import->version.hasMinorVersion()) { QList<QQmlError> errors; auto pendingImport = std::make_shared<PendingImport>(this, import); if (!fetchQmldir(qmldirUrl, pendingImport, 1, &errors)) { @@ -213,9 +213,9 @@ bool QQmlTypeData::tryLoadFromDiskCache() QQmlType containingType; auto containingTypeName = finalUrl().fileName().split(QLatin1Char('.')).first(); - int major = -1, minor = -1; + QTypeRevision version; QQmlImportNamespace *ns = nullptr; - m_importCache.resolveType(containingTypeName, &containingType, &major, &minor, &ns); + m_importCache.resolveType(containingTypeName, &containingType, &version, &ns); for (auto&& ic: ics) { QString const nameString = m_compiledData->stringAt(ic.nameIndex); QByteArray const name = nameString.toUtf8(); @@ -651,9 +651,9 @@ void QQmlTypeData::continueLoadFromIR() { QQmlType containingType; auto containingTypeName = finalUrl().fileName().split(QLatin1Char('.')).first(); - int major = -1, minor = -1; + QTypeRevision version; QQmlImportNamespace *ns = nullptr; - m_importCache.resolveType(containingTypeName, &containingType, &major, &minor, &ns); + m_importCache.resolveType(containingTypeName, &containingType, &version, &ns); for (auto const& object: m_document->objects) { for (auto it = object->inlineComponentsBegin(); it != object->inlineComponentsEnd(); ++it) { QString const nameString = m_document->stringAt(it->nameIndex); @@ -679,8 +679,7 @@ void QQmlTypeData::continueLoadFromIR() // This qmldir is for the implicit import auto implicitImport = std::make_shared<PendingImport>(); implicitImport->uri = QLatin1String("."); - implicitImport->majorVersion = -1; - implicitImport->minorVersion = -1; + implicitImport->version = QTypeRevision(); QList<QQmlError> errors; if (!fetchQmldir(qmldirUrl, implicitImport, 1, &errors)) { @@ -824,11 +823,8 @@ void QQmlTypeData::resolveTypes() typeName = csRef.typeName; } - int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1; - int minorVersion = csRef.minorVersion > -1 ? csRef.minorVersion : -1; - - if (!resolveType(typeName, majorVersion, minorVersion, ref, -1, -1, true, - QQmlType::CompositeSingletonType)) + QTypeRevision version = csRef.version; + if (!resolveType(typeName, version, ref, -1, -1, true, QQmlType::CompositeSingletonType)) return; if (ref.type.isCompositeSingleton()) { @@ -852,14 +848,13 @@ void QQmlTypeData::resolveTypes() const bool reportErrors = unresolvedRef->errorWhenNotFound; - int majorVersion = -1; - int minorVersion = -1; + QTypeRevision version; const QString name = stringAt(unresolvedRef.key()); bool *selfReferenceDetection = unresolvedRef->needsCreation ? nullptr : &ref.selfReference; - if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line, + if (!resolveType(name, version, ref, unresolvedRef->location.line, unresolvedRef->location.column, reportErrors, QQmlType::AnyRegistrationType, selfReferenceDetection) && reportErrors) return; @@ -879,8 +874,7 @@ void QQmlTypeData::resolveTypes() } } } - ref.majorVersion = majorVersion; - ref.minorVersion = minorVersion; + ref.version = version; ref.location.line = unresolvedRef->location.line; ref.location.column = unresolvedRef->location.column; @@ -963,13 +957,10 @@ QQmlJS::DiagnosticMessage QQmlTypeData::buildTypeResolutionCaches( return qQmlCompileError(resolvedType->location, reason); } - if (ref->type.containsRevisionedAttributes()) { - ref->typePropertyCache = engine->cache(ref->type, - resolvedType->minorVersion); - } + if (ref->type.containsRevisionedAttributes()) + ref->typePropertyCache = engine->cache(ref->type, resolvedType->version); } - ref->majorVersion = resolvedType->majorVersion; - ref->minorVersion = resolvedType->minorVersion; + ref->version = resolvedType->version; ref->doDynamicTypeCheck(); resolvedTypeCache->insert(resolvedType.key(), ref.take()); } @@ -977,7 +968,7 @@ QQmlJS::DiagnosticMessage QQmlTypeData::buildTypeResolutionCaches( return noError; } -bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, +bool QQmlTypeData::resolveType(const QString &typeName, QTypeRevision &version, TypeReference &ref, int lineNumber, int columnNumber, bool reportErrors, QQmlType::RegistrationType registrationType, bool *typeRecursionDetected) @@ -985,7 +976,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int & QQmlImportNamespace *typeNamespace = nullptr; QList<QQmlError> errors; - bool typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion, + bool typeFound = m_importCache.resolveType(typeName, &ref.type, &version, &typeNamespace, &errors, registrationType, typeRecursionDetected); if (!typeNamespace && !typeFound && !m_implicitImportLoaded) { @@ -993,7 +984,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int & if (loadImplicitImport()) { // Try again to find the type errors.clear(); - typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion, + typeFound = m_importCache.resolveType(typeName, &ref.type, &version, &typeNamespace, &errors, registrationType, typeRecursionDetected); } else { diff --git a/src/qml/qml/qqmltypedata_p.h b/src/qml/qml/qqmltypedata_p.h index d894090b36..1506ee2010 100644 --- a/src/qml/qml/qqmltypedata_p.h +++ b/src/qml/qml/qqmltypedata_p.h @@ -62,12 +62,11 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob public: struct TypeReference { - TypeReference() : majorVersion(0), minorVersion(0), needsCreation(true) {} + TypeReference() : version(QTypeRevision::zero()), needsCreation(true) {} QV4::CompiledData::Location location; QQmlType type; - int majorVersion; - int minorVersion; + QTypeRevision version; QQmlRefPointer<QQmlTypeData> typeData; bool selfReference = false; QString prefix; // used by CompositeSingleton types @@ -134,7 +133,7 @@ private: const QV4::CompiledData::DependentTypesHasher &dependencyHasher); void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache, const QV4::ResolvedTypeReferenceMap &resolvedTypeCache); - bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, + bool resolveType(const QString &typeName, QTypeRevision &version, TypeReference &ref, int lineNumber = -1, int columnNumber = -1, bool reportErrors = true, QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType, diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index f910fe1140..c5218bee33 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -487,8 +487,7 @@ QQmlTypeLoader::Blob::PendingImport::PendingImport(QQmlTypeLoader::Blob *blob, c type = static_cast<QV4::CompiledData::Import::ImportType>(quint32(import->type)); uri = blob->stringAt(import->uriIndex); qualifier = blob->stringAt(import->qualifierIndex); - majorVersion = import->majorVersion; - minorVersion = import->minorVersion; + version = import->version; location = import->location; } @@ -578,12 +577,13 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo QString qmldirUrl; const QQmlImports::LocalQmldirResult qmldirResult = m_importCache.locateLocalQmldir( - importDatabase, import->uri, import->majorVersion, import->minorVersion, + importDatabase, import->uri, import->version, &qmldirFilePath, &qmldirUrl); if (qmldirResult == QQmlImports::QmldirFound) { // This is a local library import - if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, - import->minorVersion, qmldirFilePath, qmldirUrl, false, errors)) + if (!m_importCache.addLibraryImport( + importDatabase, import->uri, import->qualifier, + import->version, qmldirFilePath, qmldirUrl, false, errors)) return false; if (!loadImportDependencies(import, qmldirFilePath, errors)) @@ -605,19 +605,19 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo } else if ( // Major version of module already registered: // We believe that the registration is complete. - QQmlMetaType::typeModule(import->uri, import->majorVersion) + QQmlMetaType::typeModule(import->uri, import->version) // Otherwise, try to register further module types. || (qmldirResult != QQmlImports::QmldirInterceptedToRemote - && QQmlMetaType::qmlRegisterModuleTypes(import->uri, import->majorVersion)) + && 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->majorVersion, - import->minorVersion, QString(), QString(), false, errors)) { + importDatabase, import->uri, import->qualifier, import->version, + QString(), QString(), false, errors)) { return false; } } else { @@ -633,13 +633,15 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo : 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->majorVersion, - import->minorVersion, QString(), QString(), true, errors)) + 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->majorVersion, import->minorVersion); + const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths( + import->uri, remotePathList, import->version); for (const QString &qmldirPath : qmlDirPaths) { if (interceptor) { QUrl url = interceptor->intercept( @@ -671,8 +673,8 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo incomplete = true; } - if (!m_importCache.addFileImport(importDatabase, import->uri, import->qualifier, import->majorVersion, - import->minorVersion, incomplete, errors)) + if (!m_importCache.addFileImport(importDatabase, import->uri, import->qualifier, + import->version, incomplete, errors)) return false; if (incomplete) { @@ -711,8 +713,7 @@ bool QQmlTypeLoader::Blob::loadImportDependencies(PendingImportPtr currentImport auto dependencyImport = std::make_shared<PendingImport>(); dependencyImport->uri = implicitImports; dependencyImport->qualifier = currentImport->qualifier; - dependencyImport->majorVersion = currentImport->majorVersion; - dependencyImport->minorVersion = currentImport->minorVersion; + dependencyImport->version = currentImport->version; if (!addImport(dependencyImport, errors)) return false; } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index adecf61896..a1ba2967e3 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -97,8 +97,7 @@ public: QString uri; QString qualifier; - int majorVersion = -1; - int minorVersion = -1; + QTypeRevision version; QV4::CompiledData::Location location; diff --git a/src/qml/qml/qqmltypemodule.cpp b/src/qml/qml/qqmltypemodule.cpp index 9d6f269030..e6bf796d74 100644 --- a/src/qml/qml/qqmltypemodule.cpp +++ b/src/qml/qml/qqmltypemodule.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE -QQmlTypeModule::QQmlTypeModule(const QString &module, int majorVersion) +QQmlTypeModule::QQmlTypeModule(const QString &module, quint8 majorVersion) : d(new QQmlTypeModulePrivate(module, majorVersion)) { } @@ -61,23 +61,23 @@ QString QQmlTypeModule::module() const return d->module; } -int QQmlTypeModule::majorVersion() const +quint8 QQmlTypeModule::majorVersion() const { // No need to lock. d->majorVersion is const return d->majorVersion; } -int QQmlTypeModule::minimumMinorVersion() const +quint8 QQmlTypeModule::minimumMinorVersion() const { return d->minMinorVersion.loadRelaxed(); } -int QQmlTypeModule::maximumMinorVersion() const +quint8 QQmlTypeModule::maximumMinorVersion() const { return d->maxMinorVersion.loadRelaxed(); } -void QQmlTypeModule::addMinorVersion(int version) +void QQmlTypeModule::addMinorVersion(quint8 version) { for (int oldVersion = d->minMinorVersion.loadRelaxed(); oldVersion > version && !d->minMinorVersion.testAndSetOrdered(oldVersion, version); @@ -93,16 +93,16 @@ void QQmlTypeModule::addMinorVersion(int version) void QQmlTypeModule::add(QQmlTypePrivate *type) { QMutexLocker lock(&d->mutex); - addMinorVersion(type->version_min); + addMinorVersion(type->version.minorVersion()); QList<QQmlTypePrivate *> &list = d->typeHash[type->elementName]; for (int ii = 0; ii < list.count(); ++ii) { QQmlTypePrivate *in_list = list.at(ii); Q_ASSERT(in_list); - if (in_list->version_min < type->version_min) { + if (in_list->version.minorVersion() < type->version.minorVersion()) { list.insert(ii, type); return; - } else if (in_list->version_min == type->version_min) { + } else if (in_list->version.minorVersion() == type->version.minorVersion()) { list[ii] = type; return; } @@ -137,26 +137,26 @@ void QQmlTypeModule::lock() d->locked.storeRelaxed(1); } -QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const +QQmlType QQmlTypeModule::type(const QHashedStringRef &name, QTypeRevision version) const { QMutexLocker lock(&d->mutex); QList<QQmlTypePrivate *> *types = d->typeHash.value(name); if (types) { for (int ii = 0; ii < types->count(); ++ii) - if (types->at(ii)->version_min <= minor) + if (types->at(ii)->version.minorVersion() <= version.minorVersion()) return QQmlType(types->at(ii)); } return QQmlType(); } -QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const +QQmlType QQmlTypeModule::type(const QV4::String *name, QTypeRevision version) const { QMutexLocker lock(&d->mutex); QList<QQmlTypePrivate *> *types = d->typeHash.value(name); if (types) { for (int ii = 0; ii < types->count(); ++ii) - if (types->at(ii)->version_min <= minor) + if (types->at(ii)->version.minorVersion() <= version.minorVersion()) return QQmlType(types->at(ii)); } diff --git a/src/qml/qml/qqmltypemodule_p.h b/src/qml/qml/qqmltypemodule_p.h index b84a91b5db..d3149567a3 100644 --- a/src/qml/qml/qqmltypemodule_p.h +++ b/src/qml/qml/qqmltypemodule_p.h @@ -53,6 +53,7 @@ #include <QtQml/qtqmlglobal.h> #include <QtCore/qstring.h> +#include <QtCore/qversionnumber.h> #include <functional> @@ -72,7 +73,7 @@ class QQmlTypeModulePrivate; class QQmlTypeModule { public: - QQmlTypeModule(const QString &uri = QString(), int majorVersion = 0); + QQmlTypeModule(const QString &uri = QString(), quint8 majorVersion = 0); ~QQmlTypeModule(); void add(QQmlTypePrivate *); @@ -82,14 +83,14 @@ public: void lock(); QString module() const; - int majorVersion() const; + quint8 majorVersion() const; - void addMinorVersion(int minorVersion); - int minimumMinorVersion() const; - int maximumMinorVersion() const; + void addMinorVersion(quint8 minorVersion); + quint8 minimumMinorVersion() const; + quint8 maximumMinorVersion() const; - QQmlType type(const QHashedStringRef &, int) const; - QQmlType type(const QV4::String *, int) const; + QQmlType type(const QHashedStringRef &, QTypeRevision version) const; + QQmlType type(const QV4::String *, QTypeRevision version) const; void walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const; diff --git a/src/qml/qml/qqmltypemodule_p_p.h b/src/qml/qml/qqmltypemodule_p_p.h index b1dab1c4a0..5d4d2e458a 100644 --- a/src/qml/qml/qqmltypemodule_p_p.h +++ b/src/qml/qml/qqmltypemodule_p_p.h @@ -62,15 +62,15 @@ QT_BEGIN_NAMESPACE class QQmlTypeModulePrivate { public: - QQmlTypeModulePrivate(QString module, int majorVersion) : + QQmlTypeModulePrivate(QString module, quint8 majorVersion) : module(std::move(module)), majorVersion(majorVersion) {} const QString module; - const int majorVersion = 0; + const quint8 majorVersion = 0; // Can only ever decrease - QAtomicInt minMinorVersion = std::numeric_limits<int>::max(); + QAtomicInt minMinorVersion = std::numeric_limits<quint8>::max(); // Can only ever increase QAtomicInt maxMinorVersion = 0; diff --git a/src/qml/qml/qqmltypemoduleversion.cpp b/src/qml/qml/qqmltypemoduleversion.cpp index bbbfa1a7b6..207b77770a 100644 --- a/src/qml/qml/qqmltypemoduleversion.cpp +++ b/src/qml/qml/qqmltypemoduleversion.cpp @@ -49,11 +49,11 @@ QQmlTypeModuleVersion::QQmlTypeModuleVersion() { } -QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor) - : m_module(module), m_minor(minor) +QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, QTypeRevision version) + : m_module(module), m_minor(version.minorVersion()) { Q_ASSERT(m_module); - Q_ASSERT(m_minor >= 0); + Q_ASSERT(QTypeRevision::isValidSegment(m_minor)); } QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o) @@ -68,28 +68,18 @@ QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVers return *this; } -QQmlTypeModule *QQmlTypeModuleVersion::module() const -{ - return m_module; -} - -int QQmlTypeModuleVersion::minorVersion() const -{ - return m_minor; -} - QQmlType QQmlTypeModuleVersion::type(const QHashedStringRef &name) const { if (!m_module) return QQmlType(); - return m_module->type(name, m_minor); + return m_module->type(name, QTypeRevision::fromMinorVersion(m_minor)); } QQmlType QQmlTypeModuleVersion::type(const QV4::String *name) const { if (!m_module) return QQmlType(); - return m_module->type(name, m_minor); + return m_module->type(name, QTypeRevision::fromMinorVersion(m_minor)); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypemoduleversion_p.h b/src/qml/qml/qqmltypemoduleversion_p.h index 20f4709ecb..b7e94ef27b 100644 --- a/src/qml/qml/qqmltypemoduleversion_p.h +++ b/src/qml/qml/qqmltypemoduleversion_p.h @@ -52,6 +52,7 @@ // #include <QtQml/qtqmlglobal.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -67,19 +68,16 @@ class QQmlTypeModuleVersion { public: QQmlTypeModuleVersion(); - QQmlTypeModuleVersion(QQmlTypeModule *, int); + QQmlTypeModuleVersion(QQmlTypeModule *, QTypeRevision); QQmlTypeModuleVersion(const QQmlTypeModuleVersion &); QQmlTypeModuleVersion &operator=(const QQmlTypeModuleVersion &); - QQmlTypeModule *module() const; - int minorVersion() const; - QQmlType type(const QHashedStringRef &) const; QQmlType type(const QV4::String *) const; private: QQmlTypeModule *m_module; - int m_minor; + quint8 m_minor; }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp index 1015403226..45333668e3 100644 --- a/src/qml/qml/qqmltypenamecache.cpp +++ b/src/qml/qml/qqmltypenamecache.cpp @@ -101,7 +101,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name) QQmlImportNamespace *typeNamespace = nullptr; QList<QQmlError> errors; QQmlType t; - bool typeFound = m_imports.resolveType(name, &t, nullptr, nullptr, &typeNamespace, &errors); + bool typeFound = m_imports.resolveType(name, &t, nullptr, &typeNamespace, &errors); if (typeFound) { return Result(t); } @@ -129,7 +129,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name, QQmlImportNamespace *typeNamespace = nullptr; QList<QQmlError> errors; QQmlType t; - bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, nullptr, &typeNamespace, &errors); + bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, &typeNamespace, &errors); if (typeFound) { return Result(t); } @@ -155,7 +155,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQml QList<QQmlError> errors; QQmlType t; bool typeRecursionDetected = false; - bool typeFound = m_imports.resolveType(typeName, &t, nullptr, nullptr, &typeNamespace, &errors, + bool typeFound = m_imports.resolveType(typeName, &t, nullptr, &typeNamespace, &errors, QQmlType::AnyRegistrationType, recursionRestriction == QQmlImport::AllowRecursion ? &typeRecursionDetected : nullptr); if (typeFound) { @@ -191,7 +191,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, cons QQmlImportNamespace *typeNamespace = nullptr; QList<QQmlError> errors; QQmlType t; - bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, nullptr, &typeNamespace, &errors); + bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, &typeNamespace, &errors); if (typeFound) { return Result(t); } diff --git a/src/qml/qml/qqmltypenotavailable_p.h b/src/qml/qml/qqmltypenotavailable_p.h index 9bb19ed86c..97956fa982 100644 --- a/src/qml/qml/qqmltypenotavailable_p.h +++ b/src/qml/qml/qqmltypenotavailable_p.h @@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE class QQmlTypeNotAvailable : public QObject { Q_OBJECT QML_NAMED_ELEMENT(TypeNotAvailable) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Type not available.") }; diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index a86564a49a..254f1015e2 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -132,8 +132,10 @@ const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t) return &QQmlRectValueType::staticMetaObject; case QMetaType::QRectF: return &QQmlRectFValueType::staticMetaObject; +#if QT_CONFIG(easingcurve) case QMetaType::QEasingCurve: return &QQmlEasingValueType::staticMetaObject; +#endif #if QT_CONFIG(qml_itemmodel) case QMetaType::QModelIndex: return &QQmlModelIndexValueType::staticMetaObject; @@ -214,7 +216,9 @@ const QMetaObject *QQmlValueTypeFactory::metaObjectForMetaType(int type) void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, int versionMinor) { +#if QT_CONFIG(easingcurve) qmlRegisterValueTypeEnums<QQmlEasingValueType>(uri, versionMajor, versionMinor, "Easing"); +#endif } QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) @@ -527,6 +531,7 @@ int QQmlRectValueType::bottom() const return v.bottom(); } +#if QT_CONFIG(easingcurve) QQmlEasingValueType::Type QQmlEasingValueType::type() const { return (QQmlEasingValueType::Type)v.type(); @@ -620,6 +625,8 @@ QVariantList QQmlEasingValueType::bezierCurve() const rv << QVariant(point.x()) << QVariant(point.y()); return rv; } +#endif // easingcurve + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index 29fa999725..e716f79ae3 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -60,7 +60,9 @@ #include <QtCore/qobject.h> #include <QtCore/qrect.h> +#if QT_CONFIG(easingcurve) #include <QtCore/qeasingcurve.h> +#endif #include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE @@ -238,11 +240,13 @@ public: int bottom() const; }; +#if QT_CONFIG(easingcurve) struct QQmlEasingValueType { QEasingCurve v; Q_GADGET QML_NAMED_ELEMENT(Easing) + QML_ADDED_IN_VERSION(2, 0) QML_UNCREATABLE("Use the Type enum.") Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL) @@ -290,6 +294,7 @@ public: void setBezierCurve(const QVariantList &); QVariantList bezierCurve() const; }; +#endif struct QQmlPropertyValueType { @@ -316,7 +321,7 @@ int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMino QString(), - uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject, nullptr, nullptr, @@ -325,7 +330,7 @@ int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMino nullptr, nullptr, nullptr, - 0 + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index c820499703..c23542dd44 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1203,25 +1203,15 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url) if (m_method == QLatin1String("PUT")) { if (!xhrFileWrite()) { - if (qEnvironmentVariableIsSet("QML_XHR_ALLOW_FILE_WRITE")) { - qWarning("XMLHttpRequest: Tried to use PUT on a local file despite being disabled."); - return; - } else { - qWarning("XMLHttpRequest: Using PUT on a local file is dangerous " - "and will be disabled by default in a future Qt version." - "Set QML_XHR_ALLOW_FILE_WRITE to 1 if you wish to continue using this feature."); - } + qWarning("XMLHttpRequest: Using PUT on a local file is disabled by default.\n" + "Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature."); + return; } } else if (m_method == QLatin1String("GET")) { if (!xhrFileRead()) { - if (qEnvironmentVariableIsSet("QML_XHR_ALLOW_FILE_READ")) { - qWarning("XMLHttpRequest: Tried to use GET on a local file despite being disabled."); - return; - } else { - qWarning("XMLHttpRequest: Using GET on a local file is dangerous " - "and will be disabled by default in a future Qt version." - "Set QML_XHR_ALLOW_FILE_READ to 1 if you wish to continue using this feature."); - } + qWarning("XMLHttpRequest: Using GET on a local file is disabled by default.\n" + "Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature."); + return; } } else { qWarning("XMLHttpRequest: Unsupported method used on a local file"); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 02628a9810..f4e529f2de 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -93,12 +93,6 @@ DEFINE_OBJECT_VTABLE(QtObject); return scope.engine->throwTypeError(QString::fromUtf8(msg)); \ } while (false) -struct StaticQtMetaObject : public QObject -{ - static const QMetaObject *get() - { return &staticQtMetaObject; } -}; - void Heap::QtObject::init(QQmlEngine *qmlEngine) { Heap::Object::init(); @@ -177,7 +171,7 @@ ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) con ScopedString key(scope); ScopedValue value(scope); - const QMetaObject *qtMetaObject = StaticQtMetaObject::get(); + const QMetaObject *qtMetaObject = &Qt::staticMetaObject; for (int enumCount = qtMetaObject->enumeratorCount(); d()->enumeratorIterator < enumCount; ++d()->enumeratorIterator) { QMetaEnum enumerator = qtMetaObject->enumerator(d()->enumeratorIterator); diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp index 36b47a3302..8d20490d5e 100644 --- a/src/qml/qmldirparser/qqmldirparser.cpp +++ b/src/qml/qmldirparser/qqmldirparser.cpp @@ -60,17 +60,17 @@ static int parseInt(const QStringRef &str, bool *ok) return number; } -static bool parseVersion(const QString &str, int *major, int *minor) +static QTypeRevision parseVersion(const QString &str) { const int dotIndex = str.indexOf(QLatin1Char('.')); if (dotIndex != -1 && str.indexOf(QLatin1Char('.'), dotIndex + 1) == -1) { bool ok = false; - *major = parseInt(QStringRef(&str, 0, dotIndex), &ok); - if (ok) - *minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok); - return ok; + const int major = parseInt(QStringRef(&str, 0, dotIndex), &ok); + if (!ok) return QTypeRevision(); + const int minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok); + return ok ? QTypeRevision::fromVersion(major, minor) : QTypeRevision(); } - return false; + return QTypeRevision(); } void QQmlDirParser::clear() @@ -203,7 +203,7 @@ bool QQmlDirParser::parse(const QString &source) QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1)); continue; } - Component entry(sections[1], sections[2], -1, -1); + Component entry(sections[1], sections[2], QTypeRevision()); entry.internal = true; _components.insert(entry.typeName, entry); } else if (sections[0] == QLatin1String("singleton")) { @@ -214,16 +214,16 @@ bool QQmlDirParser::parse(const QString &source) } else if (sectionCount == 3) { // handle qmldir directory listing case where singleton is defined in the following pattern: // singleton TestSingletonType TestSingletonType.qml - Component entry(sections[1], sections[2], -1, -1); + Component entry(sections[1], sections[2], QTypeRevision()); entry.singleton = true; _components.insert(entry.typeName, entry); } else { // handle qmldir module listing case where singleton is defined in the following pattern: // singleton TestSingletonType 2.0 TestSingletonType20.qml - int major, minor; - if (parseVersion(sections[2], &major, &minor)) { + const QTypeRevision version = parseVersion(sections[2]); + if (version.isValid()) { const QString &fileName = sections[3]; - Component entry(sections[1], fileName, major, minor); + Component entry(sections[1], fileName, version); entry.singleton = true; _components.insert(entry.typeName, entry); } else { @@ -253,9 +253,9 @@ bool QQmlDirParser::parse(const QString &source) continue; } - int major, minor; - if (parseVersion(sections[2], &major, &minor)) { - Component entry(sections[1], QString(), major, minor); + const QTypeRevision version = parseVersion(sections[2]); + if (version.isValid()) { + Component entry(sections[1], QString(), version); entry.internal = true; _dependencies.insert(entry.typeName, entry); } else { @@ -270,19 +270,19 @@ bool QQmlDirParser::parse(const QString &source) _imports << sections[1]; } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) - const Component entry(sections[0], sections[1], -1, -1); + const Component entry(sections[0], sections[1], QTypeRevision()); _components.insert(entry.typeName, entry); } else if (sectionCount == 3) { - int major, minor; - if (parseVersion(sections[1], &major, &minor)) { + const QTypeRevision version = parseVersion(sections[1]); + if (version.isValid()) { const QString &fileName = sections[2]; if (fileName.endsWith(QLatin1String(".js")) || fileName.endsWith(QLatin1String(".mjs"))) { // A 'js' extension indicates a namespaced script import - const Script entry(sections[0], fileName, major, minor); + const Script entry(sections[0], fileName, version); _scripts.append(entry); } else { - const Component entry(sections[0], fileName, major, minor); + const Component entry(sections[0], fileName, version); _components.insert(entry.typeName, entry); } } else { @@ -387,15 +387,17 @@ QString QQmlDirParser::className() const QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component) { - const QString output = QStringLiteral("{%1 %2.%3}"). - arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion); + const QString output = QStringLiteral("{%1 %2.%3}") + .arg(component.typeName).arg(component.version.majorVersion()) + .arg(component.version.minorVersion()); return debug << qPrintable(output); } QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script) { - const QString output = QStringLiteral("{%1 %2.%3}"). - arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion); + const QString output = QStringLiteral("{%1 %2.%3}") + .arg(script.nameSpace).arg(script.version.majorVersion()) + .arg(script.version.minorVersion()); return debug << qPrintable(output); } diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h index 3696a1aa12..ccdac8f484 100644 --- a/src/qml/qmldirparser/qqmldirparser_p.h +++ b/src/qml/qmldirparser/qqmldirparser_p.h @@ -54,6 +54,7 @@ #include <QtCore/QUrl> #include <QtCore/QHash> #include <QtCore/QDebug> +#include <QtCore/QTypeRevision> #include <private/qtqmlcompilerglobal_p.h> #include <private/qqmljsengine_p.h> #include <private/qqmljsdiagnosticmessage_p.h> @@ -101,8 +102,8 @@ public: { Component() = default; - Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion) - : typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion), + Component(const QString &typeName, const QString &fileName, QTypeRevision version) + : typeName(typeName), fileName(fileName), version(version), internal(false), singleton(false) { checkNonRelative("Component", typeName, fileName); @@ -110,8 +111,7 @@ public: QString typeName; QString fileName; - int majorVersion = 0; - int minorVersion = 0; + QTypeRevision version = QTypeRevision::zero(); bool internal = false; bool singleton = false; }; @@ -120,16 +120,15 @@ public: { Script() = default; - Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion) - : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) + Script(const QString &nameSpace, const QString &fileName, QTypeRevision version) + : nameSpace(nameSpace), fileName(fileName), version(version) { checkNonRelative("Script", nameSpace, fileName); } QString nameSpace; QString fileName; - int majorVersion = 0; - int minorVersion = 0; + QTypeRevision version = QTypeRevision::zero(); }; QMultiHash<QString,Component> components() const; diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 6d6553259e..6d762401d0 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -73,8 +73,7 @@ public: , delayed(false) , pendingEval(false) , restoreBinding(true) - , restoreValue(false) - , restoreModeExplicit(false) + , restoreValue(true) , writingProperty(false) {} ~QQmlBindPrivate() { } @@ -93,7 +92,6 @@ public: bool pendingEval:1; bool restoreBinding:1; bool restoreValue:1; - bool restoreModeExplicit:1; bool writingProperty: 1; void validate(QObject *binding) const; @@ -196,13 +194,8 @@ QQmlBind::~QQmlBind() } \endcode - When the binding becomes inactive again, any direct bindings that were previously - set on the property will be restored. - - \note By default, a previously set literal value is not restored when the Binding becomes - inactive. Rather, the last value set by the now inactive Binding is retained. You can customize - the restoration behavior for literal values as well as bindings using the \l restoreMode - property. The default will change in Qt 6.0. + By default, any binding or value that was set perviously is restored when the binding becomes + inactive. You can customize the restoration behavior using the \l restoreMode property. \sa restoreMode */ @@ -371,8 +364,7 @@ void QQmlBind::setDelayed(bool delayed) \li Binding.RestoreBindingOrValue The original value is always restored. \endlist - \warning The default value is Binding.RestoreBinding. This will change in - Qt 6.0 to Binding.RestoreBindingOrValue. + The default value is \c Binding.RestoreBindingOrValue. If you rely on any specific behavior regarding the restoration of plain values when bindings get disabled you should migrate to explicitly set the @@ -395,7 +387,6 @@ QQmlBind::RestorationMode QQmlBind::restoreMode() const void QQmlBind::setRestoreMode(RestorationMode newMode) { Q_D(QQmlBind); - d->restoreModeExplicit = true; if (newMode != restoreMode()) { d->restoreValue = (newMode & RestoreValue); d->restoreBinding = (newMode & RestoreBinding); @@ -482,27 +473,11 @@ void QQmlBind::eval() Q_ASSERT(vmemo); vmemo->setVMEProperty(propPriv->core.coreIndex(), *d->v4Value.valueRef()); d->clearPrev(); - } else if (!d->restoreModeExplicit) { - qmlWarning(this) - << "Not restoring previous value because restoreMode has not been set.\n" - << "This behavior is deprecated.\n" - << "You have to import QtQml 2.15 after any QtQuick imports and set\n" - << "the restoreMode of the binding to fix this warning.\n" - << "In Qt < 6.0 the default is Binding.RestoreBinding.\n" - << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue."; } } else if (d->prevIsVariant) { if (d->restoreValue) { d->prop.write(d->prevValue); d->clearPrev(); - } else if (!d->restoreModeExplicit) { - qmlWarning(this) - << "Not restoring previous value because restoreMode has not been set.\n" - << "This behavior is deprecated.\n" - << "You have to import QtQml 2.15 after any QtQuick imports and set\n" - << "the restoreMode of the binding to fix this warning.\n" - << "In Qt < 6.0 the default is Binding.RestoreBinding.\n" - << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue.\n"; } } return; diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h index c709224c23..052af0d167 100644 --- a/src/qml/types/qqmlbind_p.h +++ b/src/qml/types/qqmlbind_p.h @@ -77,11 +77,12 @@ private: Q_PROPERTY(QString property READ property WRITE setProperty) Q_PROPERTY(QJSValue value READ value WRITE setValue) Q_PROPERTY(bool when READ when WRITE setWhen) - Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION 8) + Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION(2, 8)) Q_PROPERTY(RestorationMode restoreMode READ restoreMode WRITE setRestoreMode - NOTIFY restoreModeChanged REVISION 14) + NOTIFY restoreModeChanged REVISION(2, 14)) Q_ENUM(RestorationMode) QML_NAMED_ELEMENT(Binding) + QML_ADDED_IN_VERSION(2, 0) public: QQmlBind(QObject *parent=nullptr); diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h index 7bf688cf75..8ed874d9fc 100644 --- a/src/qml/types/qqmlconnections_p.h +++ b/src/qml/types/qqmlconnections_p.h @@ -69,9 +69,10 @@ class Q_AUTOTEST_EXPORT QQmlConnections : public QObject, public QQmlParserStatu Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged REVISION 3) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged REVISION(2, 3)) Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals) QML_NAMED_ELEMENT(Connections) + QML_ADDED_IN_VERSION(2, 0) public: QQmlConnections(QObject *parent=nullptr); @@ -88,7 +89,7 @@ public: Q_SIGNALS: void targetChanged(); - Q_REVISION(3) void enabledChanged(); + Q_REVISION(2, 3) void enabledChanged(); private: void connectSignals(); diff --git a/src/qml/types/qqmltimer_p.h b/src/qml/types/qqmltimer_p.h index 0cd93e4659..a8236977c4 100644 --- a/src/qml/types/qqmltimer_p.h +++ b/src/qml/types/qqmltimer_p.h @@ -73,6 +73,7 @@ class Q_QML_PRIVATE_EXPORT QQmlTimer : public QObject, public QQmlParserStatus Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged) Q_PROPERTY(QObject *parent READ parent CONSTANT) QML_NAMED_ELEMENT(Timer) + QML_ADDED_IN_VERSION(2, 0) public: QQmlTimer(QObject *parent=nullptr); |