diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-07-10 10:33:49 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-08-28 13:49:11 +0200 |
commit | 2afed94c70913e018198422ef222c9168326d09c (patch) | |
tree | 526952d291b70065886377e540f9e149be2f1537 | |
parent | 6e423233b2e419fc3d7fc30bebcad976dca31934 (diff) |
Fix QtQml after QMetaType/QVariant changes in Qt Core
Change-Id: I2a983cf8188e88d80d3b7726208d821427eb8f3c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsapi/qjsvalue.cpp | 65 | ||||
-rw-r--r-- | src/qml/jsapi/qjsvalue.h | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 118 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast.cpp | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 13 | ||||
-rw-r--r-- | tests/auto/qml/qjsengine/tst_qjsengine.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp | 1 |
9 files changed, 107 insertions, 109 deletions
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp index 47bb64140f..4da6b71b40 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp @@ -39,6 +39,7 @@ #include "qqmlpreviewposition.h" +#include <QtCore/qiodevice.h> #include <QtGui/qwindow.h> #include <QtGui/qscreen.h> #include <QtGui/qguiapplication.h> diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index 663f6ced82..4a1833be51 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -1277,4 +1277,69 @@ bool QJSValue::isQMetaObject() const return QJSValuePrivate::asManagedType<QV4::QMetaObjectWrapper>(this); } +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QJSValue &jsv) +{ + quint32 isNullOrUndefined = 0; + if (jsv.isNull()) + isNullOrUndefined |= 0x1; + if (jsv.isUndefined()) + isNullOrUndefined |= 0x2; + stream << isNullOrUndefined; + if (!isNullOrUndefined) { + const QVariant v = jsv.toVariant(); + switch (v.userType()) { + case QMetaType::Bool: + case QMetaType::Double: + case QMetaType::Int: + case QMetaType::QString: + v.save(stream); + break; + default: + qWarning() << "QDataStream::operator<< was to save a non-trivial QJSValue." + << "This is not supported anymore, please stream a QVariant instead."; + QVariant().save(stream); + break; + } + + } + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QJSValue &jsv) +{ + quint32 isNullOrUndefined; + stream >> isNullOrUndefined; + + if (isNullOrUndefined & 0x1) { + jsv = QJSValue(QJSValue::NullValue); + } else if (isNullOrUndefined & 0x2) { + jsv = QJSValue(); + } else { + QVariant v; + v.load(stream); + + switch (v.userType()) { + case QMetaType::Bool: + jsv = QJSValue(v.toBool()); + break; + case QMetaType::Double: + jsv = QJSValue(v.toDouble()); + break; + case QMetaType::Int: + jsv = QJSValue(v.toInt()); + break; + case QMetaType::QString: + jsv = QJSValue(v.toString()); + break; + default: + qWarning() << "QDataStream::operator>> to restore a non-trivial QJSValue." + << "This is not supported anymore, please stream a QVariant instead."; + break; + } + } + return stream; +} +#endif + QT_END_NAMESPACE diff --git a/src/qml/jsapi/qjsvalue.h b/src/qml/jsapi/qjsvalue.h index 3da76d16cb..c814ce14f8 100644 --- a/src/qml/jsapi/qjsvalue.h +++ b/src/qml/jsapi/qjsvalue.h @@ -158,6 +158,11 @@ private: quint64 d; }; +#ifndef QT_NO_DATASTREAM +Q_QML_EXPORT QDataStream &operator<<(QDataStream &, const QJSValue &); +Q_QML_EXPORT QDataStream &operator>>(QDataStream &, QJSValue &); +#endif + QT_END_NAMESPACE Q_DECLARE_METATYPE(QJSValue) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index f40fc3b780..9cd558590f 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -157,70 +157,6 @@ ReturnType convertJSValueToVariantType(const QJSValue &value) return value.toVariant().value<ReturnType>(); } -static void saveJSValue(QDataStream &stream, const void *data) -{ - const QJSValue *jsv = reinterpret_cast<const QJSValue *>(data); - quint32 isNullOrUndefined = 0; - if (jsv->isNull()) - isNullOrUndefined |= 0x1; - if (jsv->isUndefined()) - isNullOrUndefined |= 0x2; - stream << isNullOrUndefined; - if (!isNullOrUndefined) { - const QVariant v = reinterpret_cast<const QJSValue*>(data)->toVariant(); - switch (v.userType()) { - case QMetaType::Bool: - case QMetaType::Double: - case QMetaType::Int: - case QMetaType::QString: - v.save(stream); - break; - default: - qWarning() << "QDataStream::operator<< was to save a non-trivial QJSValue." - << "This is not supported anymore, please stream a QVariant instead."; - QVariant().save(stream); - break; - } - - } -} - -static void restoreJSValue(QDataStream &stream, void *data) -{ - QJSValue *jsv = reinterpret_cast<QJSValue*>(data); - - quint32 isNullOrUndefined; - stream >> isNullOrUndefined; - - if (isNullOrUndefined & 0x1) { - *jsv = QJSValue(QJSValue::NullValue); - } else if (isNullOrUndefined & 0x2) { - *jsv = QJSValue(); - } else { - QVariant v; - v.load(stream); - - switch (v.userType()) { - case QMetaType::Bool: - *jsv = QJSValue(v.toBool()); - break; - case QMetaType::Double: - *jsv = QJSValue(v.toDouble()); - break; - case QMetaType::Int: - *jsv = QJSValue(v.toInt()); - break; - case QMetaType::QString: - *jsv = QJSValue(v.toString()); - break; - default: - qWarning() << "QDataStream::operator>> to restore a non-trivial QJSValue." - << "This is not supported anymore, please stream a QVariant instead."; - break; - } - } -} - struct JSArrayIterator { QJSValue const* data; quint32 index; @@ -241,9 +177,10 @@ static QtMetaTypePrivate::QSequentialIterableImpl jsvalueToSequence (const QJSVa // set up some functions so that non-array QSequentialIterables do not crash // but instead appear as an empty sequence iterator._size = [](const void *) {return 0;}; - iterator._moveToBegin = [](const void *, void **) {}; - iterator._moveToEnd = [](const void *, void **) {}; + iterator._at = [](const void *, int, void *) {}; + iterator._moveTo = [](const void *, void **, QSequentialIterableImpl::Position) {}; iterator._advance = [](void **, int) {}; + iterator._get = [](void * const *, void *) {}; iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/}; iterator._destroyIter = [](void **){}; return iterator; @@ -251,8 +188,7 @@ static QtMetaTypePrivate::QSequentialIterableImpl jsvalueToSequence (const QJSVa iterator._iterable = &value; iterator._iterator = nullptr; - iterator._metaType_id = qMetaTypeId<QVariant>(); - iterator._metaType_flags = QVariantConstructionFlags::ShouldDeleteVariantData; + iterator._metaType = QMetaType::fromType<QVariant>(); iterator._iteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability; iterator._size = [](const void *p) -> int { return static_cast<QJSValue const *>(p)->property(QString::fromLatin1("length")).toInt(); @@ -263,32 +199,28 @@ static QtMetaTypePrivate::QSequentialIterableImpl jsvalueToSequence (const QJSVa * and QSequentialIterable::operator*() will free that memory */ - iterator._at = [](const void *iterable, int index) -> void const * { - auto const value = static_cast<QJSValue const *>(iterable)->property(quint32(index)).toVariant(); - return QMetaType::create(qMetaTypeId<QVariant>(), &value); + iterator._at = [](const void *iterable, int index, void *dataPtr) -> void { + auto *data = static_cast<QVariant *>(dataPtr); + *data = static_cast<QJSValue const *>(iterable)->property(quint32(index)).toVariant(); }; - iterator._moveToBegin = [](const void *iterable, void **iterator) { + iterator._moveTo = [](const void *iterable, void **iterator, QSequentialIterableImpl::Position pos) { createNewIteratorIfNonExisting(iterator); auto jsArrayIterator = static_cast<JSArrayIterator *>(*iterator); jsArrayIterator->index = 0; jsArrayIterator->data = reinterpret_cast<QJSValue const*>(iterable); - }; - iterator._moveToEnd = [](const void *iterable, void **iterator) { - createNewIteratorIfNonExisting(iterator); - auto jsArrayIterator = static_cast<JSArrayIterator *>(*iterator); - auto length = static_cast<QJSValue const *>(iterable)->property(QString::fromLatin1("length")).toInt(); - jsArrayIterator->data = reinterpret_cast<QJSValue const*>(iterable); - jsArrayIterator->index = quint32(length); + if (pos == QSequentialIterableImpl::ToEnd) { + auto length = static_cast<QJSValue const *>(iterable)->property(QString::fromLatin1("length")).toInt(); + jsArrayIterator->index = quint32(length); + } }; iterator._advance = [](void **iterator, int advanceBy) { static_cast<JSArrayIterator *>(*iterator)->index += quint32(advanceBy); }; - iterator._get = []( void * const *iterator, int metaTypeId, uint flags) -> VariantData { + iterator._get = []( void * const *iterator, void *dataPtr) -> void { auto const * const arrayIterator = static_cast<const JSArrayIterator *>(*iterator); QJSValue const * const jsArray = arrayIterator->data; - auto const value = jsArray->property(arrayIterator->index).toVariant(); - Q_ASSERT(flags & QVariantConstructionFlags::ShouldDeleteVariantData); - return {metaTypeId, QMetaType::create(qMetaTypeId<QVariant>(), &value), flags}; + auto *data = static_cast<QVariant *>(dataPtr); + *data = jsArray->property(arrayIterator->index).toVariant(); }; iterator._destroyIter = [](void **iterator) { delete static_cast<JSArrayIterator *>(*iterator); @@ -848,7 +780,6 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>); if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QtMetaTypePrivate::QSequentialIterableImpl>()) QMetaType::registerConverter<QJSValue, QtMetaTypePrivate::QSequentialIterableImpl>(jsvalueToSequence); - QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue); QV4::QObjectWrapper::initializeBindings(this); @@ -1565,11 +1496,8 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return retn; #endif if (typeHint != -1) { - // the QVariant constructor will create a copy, so we have manually - // destroy the value returned by QMetaType::create - auto temp = QMetaType::create(typeHint); - retn = QVariant(QMetaType(typeHint), temp); - QMetaType::destroy(typeHint, temp); + auto metaType = QMetaType(typeHint); + retn = QVariant(metaType, nullptr); auto retnAsIterable = retn.value<QtMetaTypePrivate::QSequentialIterableImpl>(); if (retnAsIterable.containerCapabilities() & QtMetaTypePrivate::ContainerIsAppendable) { auto const length = a->getLength(); @@ -1577,26 +1505,26 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int for (qint64 i = 0; i < length; ++i) { arrayValue = a->get(i); QVariant asVariant; - if (QMetaType::hasRegisteredConverterFunction(qMetaTypeId<QJSValue>(), retnAsIterable._metaType_id)) { + if (QMetaType::hasRegisteredConverterFunction(qMetaTypeId<QJSValue>(), retnAsIterable._metaType.id())) { // before attempting a conversion from the concrete types, // check if there exists a conversion from QJSValue -> out type // prefer that one for compatibility reasons asVariant = QVariant::fromValue(QJSValuePrivate::fromReturnedValue(arrayValue->asReturnedValue())); - if (asVariant.convert(retnAsIterable._metaType_id)) { + if (asVariant.convert(retnAsIterable._metaType.id())) { retnAsIterable.append(asVariant.constData()); continue; } } - asVariant = toVariant(e, arrayValue, retnAsIterable._metaType_id, false, visitedObjects); + asVariant = toVariant(e, arrayValue, retnAsIterable._metaType.id(), false, visitedObjects); auto originalType = asVariant.userType(); - bool couldConvert = asVariant.convert(retnAsIterable._metaType_id); + bool couldConvert = asVariant.convert(retnAsIterable._metaType.id()); if (!couldConvert) { qWarning() << QLatin1String("Could not convert array value at position %1 from %2 to %3") .arg(QString::number(i), QString::fromUtf8(QMetaType::typeName(originalType)), - QString::fromUtf8(QMetaType::typeName(retnAsIterable._metaType_id))); + QString::fromUtf8(QMetaType::typeName(retnAsIterable._metaType.id()))); // create default constructed value - asVariant = QVariant(QMetaType(retnAsIterable._metaType_id), nullptr); + asVariant = QVariant(retnAsIterable._metaType, nullptr); } retnAsIterable.append(asVariant.constData()); } diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index 9885875499..7309cf8162 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -41,6 +41,7 @@ #include "qqmljsast_p.h" #include "qqmljsastvisitor_p.h" +#include <qlocale.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 7191da694d..4326002575 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -767,23 +767,23 @@ void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int in parameterTypes.count() + 1)); void **args = ev->args(); - int *types = ev->types(); + QMetaType *types = ev->types(); for (int ii = 0; ii < parameterTypes.count(); ++ii) { const QByteArray &typeName = parameterTypes.at(ii); if (typeName.endsWith('*')) - types[ii + 1] = QMetaType::VoidStar; + types[ii + 1] = QMetaType(QMetaType::VoidStar); else - types[ii + 1] = QMetaType::type(typeName); + types[ii + 1] = QMetaType::fromName(typeName); - if (!types[ii + 1]) { + if (!types[ii + 1].isValid()) { qWarning("QObject::connect: Cannot queue arguments of type '%s'\n" "(Make sure '%s' is registered using qRegisterMetaType().)", typeName.constData(), typeName.constData()); return; } - args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]); + args[ii + 1] = types[ii + 1].create(a[ii + 1]); } QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject; diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 9b0df3c5c4..cb2522a675 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -549,16 +549,12 @@ struct QQmlMetaTypeInterface : QtPrivate::QMetaTypeInterface QQmlMetaTypeInterface(const QByteArray &name) : QMetaTypeInterface { /*.revision=*/ 0, - /*.size=*/ sizeof(T), /*.alignment=*/ alignof(T), + /*.size=*/ sizeof(T), /*.flags=*/ QtPrivate::QMetaTypeTypeFlags<T>::Flags, - /*.metaObject=*/ nullptr, - /*.name=*/ name.constData(), /*.typeId=*/ 0, - /*.ref=*/ { Q_BASIC_ATOMIC_INITIALIZER(0) }, - /*.deleteSelf=*/ [](QMetaTypeInterface *self) { - delete static_cast<QQmlMetaTypeInterface *>(self); - }, + /*.metaObject=*/ nullptr,//QtPrivate::MetaObjectForType<T>::value(), + /*.name=*/ name.constData(), /*.defaultCtr=*/ [](const QMetaTypeInterface *, void *addr) { new (addr) T(); }, /*.copyCtr=*/ [](const QMetaTypeInterface *, void *addr, const void *other) { new (addr) T(*reinterpret_cast<const T *>(other)); @@ -571,6 +567,9 @@ struct QQmlMetaTypeInterface : QtPrivate::QMetaTypeInterface }, /*.equals*/ nullptr, /*.lessThan*/ nullptr, + /*.debugStream=*/ nullptr, + /*.dataStreamOut=*/ nullptr, + /*.dataStreamIn=*/ nullptr, /*.legacyRegisterOp=*/ nullptr } , name(name) { } diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index cd03903da2..81e150bf1f 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -563,7 +563,7 @@ void tst_QJSEngine::toScriptValue() if (input.metaType().id() == QMetaType::QChar) { if (!input.convert(QMetaType::QString)) QFAIL("cannot convert to the original value"); - } else if (!output.convert(input.metaType().id())) + } else if (!output.convert(input.metaType().id()) && input.isValid()) QFAIL("cannot convert to the original value"); QCOMPARE(input, output); } diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp index 48613d04f1..c0f74b3ec0 100644 --- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp +++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp @@ -98,7 +98,6 @@ void tst_qqmlconsole::logging() QStringList stringList; stringList << QStringLiteral("Hello") << QStringLiteral("World"); CustomObject customObject; - QVERIFY(QMetaType::registerDebugStreamOperator<CustomObject>()); QQmlComponent component(&engine, testUrl); QScopedPointer<QObject> object(component.createWithInitialProperties({ |