diff --git a/0111-Fix-qml-cache-invalidation-when-changing-dependent-C.patch b/0111-Fix-qml-cache-invalidation-when-changing-dependent-C.patch new file mode 100644 index 0000000..3244c60 --- /dev/null +++ b/0111-Fix-qml-cache-invalidation-when-changing-dependent-C.patch @@ -0,0 +1,168 @@ +From 98358715930739ca8de172d88c5ce6941c275ff3 Mon Sep 17 00:00:00 2001 +From: Simon Hausmann +Date: Tue, 12 Sep 2017 15:13:33 +0200 +Subject: [PATCH 111/153] Fix qml cache invalidation when changing dependent + C++ registered QML singletons + +When a qml file uses a qml singleton, we need to reliably detect when +the singleton changes and re-generate the cache of the qml file using +it. This is a scenario covered and fixed by commit +5b94de09cc738837d1539e28b3c0dccd17c18d29, with the exception that +currently QML singletons registered via qmlRegisterSingleton were not +added to the list of dependent singletons for a qml file. We can fix +this by extending findCompositeSingletons() to also cover the singletons +that do not originate from a qmldir file. + +[ChangeLog][Qt][Qml] Fixed bug where sometimes changes to a qml +singleton would not propagate to the users or cause crashes. + +Task-number: QTBUG-62243 +Change-Id: I16c3d9ba65fd82e898a29b946c341907751135a9 +Reviewed-by: Lars Knoll +--- + src/qml/qml/qqmlimport.cpp | 11 +++++ + src/qml/qml/qqmlmetatype.cpp | 12 +++++ + src/qml/qml/qqmlmetatype_p.h | 2 + + tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp | 61 ++++++++++++++++++++++++ + 4 files changed, 86 insertions(+) + +diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp +index 0bd731747..ccd287e1b 100644 +--- a/src/qml/qml/qqmlimport.cpp ++++ b/src/qml/qml/qqmlimport.cpp +@@ -471,6 +471,17 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QListuri, import->majversion)) { ++ module->walkCompositeSingletons([&resultList, &set](const QQmlType &singleton) { ++ QQmlImports::CompositeSingletonReference ref; ++ ref.typeName = singleton.elementName(); ++ ref.prefix = set.prefix; ++ ref.majorVersion = singleton.majorVersion(); ++ ref.minorVersion = singleton.minorVersion(); ++ resultList.append(ref); ++ }); ++ } + } + } + +diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp +index 5bbc250d5..8f5d11a96 100644 +--- a/src/qml/qml/qqmlmetatype.cpp ++++ b/src/qml/qml/qqmlmetatype.cpp +@@ -1258,6 +1258,18 @@ QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const + return QQmlType(); + } + ++void QQmlTypeModule::walkCompositeSingletons(const std::function &callback) const ++{ ++ QMutexLocker lock(metaTypeDataLock()); ++ for (auto typeCandidates = d->typeHash.begin(), end = d->typeHash.end(); ++ typeCandidates != end; ++typeCandidates) { ++ for (auto type: typeCandidates.value()) { ++ if (type->regType == QQmlType::CompositeSingletonType) ++ callback(QQmlType(type)); ++ } ++ } ++} ++ + QQmlTypeModuleVersion::QQmlTypeModuleVersion() + : m_module(0), m_minor(0) + { +diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h +index ac2133ba3..9a7736ffc 100644 +--- a/src/qml/qml/qqmlmetatype_p.h ++++ b/src/qml/qml/qqmlmetatype_p.h +@@ -298,6 +298,8 @@ public: + QQmlType type(const QHashedStringRef &, int) const; + QQmlType type(const QV4::String *, int) const; + ++ void walkCompositeSingletons(const std::function &callback) const; ++ + QQmlTypeModulePrivate *priv() { return d; } + private: + //Used by register functions and creates the QQmlTypeModule for them +diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +index 6ab84774f..e75e51ed2 100644 +--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp ++++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +@@ -59,6 +59,7 @@ private slots: + void cacheResources(); + void stableOrderOfDependentCompositeTypes(); + void singletonDependency(); ++ void cppRegisteredSingletonDependency(); + }; + + // A wrapper around QQmlComponent to ensure the temporary reference counts +@@ -790,6 +791,66 @@ void tst_qmldiskcache::singletonDependency() + } + } + ++void tst_qmldiskcache::cppRegisteredSingletonDependency() ++{ ++ qmlClearTypeRegistrations(); ++ QScopedPointer engine(new QQmlEngine); ++ ++ QTemporaryDir tempDir; ++ QVERIFY(tempDir.isValid()); ++ ++ const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) { ++ QFile f(tempDir.path() + '/' + fileName); ++ const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); ++ Q_ASSERT(ok); ++ f.write(contents); ++ return f.fileName(); ++ }; ++ ++ writeTempFile("MySingleton.qml", "import QtQml 2.0\npragma Singleton\nQtObject { property int value: 42 }"); ++ ++ qmlRegisterSingletonType(QUrl::fromLocalFile(tempDir.path() + QLatin1String("/MySingleton.qml")), "CppRegisteredSingletonDependency", 1, 0, "Singly"); ++ ++ const QString testFilePath = writeTempFile("main.qml", "import QtQml 2.0\nimport CppRegisteredSingletonDependency 1.0\nQtObject {\n" ++ " function getValue() { return Singly.value; }\n" ++ "}"); ++ ++ { ++ CleanlyLoadingComponent component(engine.data(), QUrl::fromLocalFile(testFilePath)); ++ QScopedPointer obj(component.create()); ++ QVERIFY(!obj.isNull()); ++ QVariant value; ++ QVERIFY(QMetaObject::invokeMethod(obj.data(), "getValue", Q_RETURN_ARG(QVariant, value))); ++ QCOMPARE(value.toInt(), 42); ++ } ++ ++ const QString testFileCachePath = testFilePath + QLatin1Char('c'); ++ QVERIFY(QFile::exists(testFileCachePath)); ++ QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); ++ ++ engine.reset(new QQmlEngine); ++ waitForFileSystem(); ++ ++ writeTempFile("MySingleton.qml", "import QtQml 2.0\npragma Singleton\nQtObject { property int value: 100 }"); ++ waitForFileSystem(); ++ ++ { ++ CleanlyLoadingComponent component(engine.data(), QUrl::fromLocalFile(testFilePath)); ++ QScopedPointer obj(component.create()); ++ QVERIFY(!obj.isNull()); ++ ++ { ++ QVERIFY(QFile::exists(testFileCachePath)); ++ QDateTime newCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); ++ QVERIFY2(newCacheTimeStamp > initialCacheTimeStamp, qPrintable(newCacheTimeStamp.toString())); ++ } ++ ++ QVariant value; ++ QVERIFY(QMetaObject::invokeMethod(obj.data(), "getValue", Q_RETURN_ARG(QVariant, value))); ++ QCOMPARE(value.toInt(), 100); ++ } ++} ++ + QTEST_MAIN(tst_qmldiskcache) + + #include "tst_qmldiskcache.moc" +-- +2.14.3 + diff --git a/qt5-qtdeclarative.spec b/qt5-qtdeclarative.spec index 1582b7d..f5f2165 100644 --- a/qt5-qtdeclarative.spec +++ b/qt5-qtdeclarative.spec @@ -14,7 +14,7 @@ Summary: Qt5 - QtDeclarative component Name: qt5-%{qt_module} Version: 5.9.2 -Release: 1%{?dist} +Release: 2%{?dist} # See LICENSE.GPL LICENSE.LGPL LGPL_EXCEPTION.txt, for details License: LGPLv2 with exceptions or GPLv3 with exceptions @@ -35,6 +35,9 @@ Patch1: qtdeclarative-opensource-src-5.9.0-no_sse2.patch Patch2: qtdeclarative-QQuickShaderEffectSource_deadlock.patch ## upstream patches +# regression https://bugreports.qt.io/browse/QTBUG-64017 +# so revert this offending commit (for now) +Patch111: 0111-Fix-qml-cache-invalidation-when-changing-dependent-C.patch ## upstreamable patches # use system double-conversation @@ -95,6 +98,9 @@ Requires: %{name}%{?_isa} = %{version}-%{release} %patch1 -p1 -b .no_sse2 %endif %patch2 -p1 -b .QQuickShaderEffectSource_deadlock + +%patch111 -p1 -R -b .0111 + %patch201 -p0 -b .kdebug346118 %patch202 -p1 -b .no_sse2_non_fatal @@ -224,6 +230,9 @@ make check -k -C tests ||: %changelog +* Thu Oct 26 2017 Rex Dieter - 5.9.2-2 +- revert commit causing regresions (QTBUG-64017) + * Mon Oct 09 2017 Jan Grulich - 5.9.2-1 - 5.9.2