public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/qt6-qtdeclarative] rawhide: Upstream backport:
@ 2026-09-11 10:34 Jan Grulich
  0 siblings, 0 replies; 2+ messages in thread
From: Jan Grulich @ 2026-09-11 10:34 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/qt6-qtdeclarative
            Branch : rawhide
            Commit : 05d82bbddd43586d414b848733f91e2577344b97
            Author : Jan Grulich <jgrulich@redhat.com>
            Date   : 2026-09-11T12:33:52+02:00
            Stats  : +336/-1 in 2 file(s)
            URL    : https://src.fedoraproject.org/rpms/qt6-qtdeclarative/c/05d82bbddd43586d414b848733f91e2577344b97?branch=rawhide

            Log:
            Upstream backport:
QML Engine: correctly compare composites when multiple engines are used

---
diff --git a/qt6-qtdeclarative.spec b/qt6-qtdeclarative.spec
index e2c9768..aadbe9a 100644
--- a/qt6-qtdeclarative.spec
+++ b/qt6-qtdeclarative.spec
@@ -16,7 +16,7 @@
 Summary: Qt6 - QtDeclarative component
 Name:    qt6-%{qt_module}
 Version: 6.11.2
-Release: 1%{?dist}
+Release: 2%{?dist}
 
 License: LGPL-3.0-only OR GPL-3.0-only WITH Qt-GPL-exception-1.0
 Url:     http://www.qt.io
@@ -34,6 +34,7 @@ Source0: https://download.qt.io/official_releases/qt/%{majmin}/%{version}/submod
 Source5: qv4global_p-multilib.h
 
 ## upstream patches
+Patch0:  qtdeclarative-qml-engine-correctly-compare-composites-with-multi-engines.patch
 
 ## upstreamable patches
 
@@ -759,6 +760,10 @@ make check -k -C tests ||:
 %endif
 
 %changelog
+* Fri Sep 11 2026 Jan Grulich <jgrulich@redhat.com> - 6.11.2-2
+- Upstream backport:
+  - QML Engine: correctly compare composites when multiple engines are used
+
 * Fri Aug 21 2026 Jan Grulich <jgrulich@redhat.com> - 6.11.2-1
 - 6.11.2
 

diff --git a/qtdeclarative-qml-engine-correctly-compare-composites-with-multi-engines.patch b/qtdeclarative-qml-engine-correctly-compare-composites-with-multi-engines.patch
new file mode 100644
index 0000000..e5d01bd
--- /dev/null
+++ b/qtdeclarative-qml-engine-correctly-compare-composites-with-multi-engines.patch
@@ -0,0 +1,330 @@
+From 8b8c30429419a3b9f0bd74fd5fb0066c851ae623 Mon Sep 17 00:00:00 2001
+From: Fabian Kosmale <fabian.kosmale@qt.io>
+Date: Mon, 31 Aug 2026 16:54:58 +0200
+Subject: [PATCH] QML engine: Correctly compare composites when multiple engines are used
+
+Since 6.11, we allow multiple types to be active for the same URL.
+While we converted multiple places to handle this, we missed adjusting
+the property validator. There, we just picked the last inserted property
+cache, which can lead to validation failures.
+
+Fix this by adding a fallback path which checks all potential matches
+when the initial lookup would yield an error.
+
+The same kind of check is also needed in qmlobject_can_qml_cast.
+
+Amends 9cc23ca91c404f24fff3c36e8c9425ae674f341d.
+
+Change compared to 6.12:
+Dropped the isComposite check, which doesn't exist there. That causes
+one potential extra unneeded lock acquisition, but only in a case
+where'd we get an error anyway.
+
+Fixes: QTBUG-149607
+Change-Id: Ibd0df2325807e75b23056ebc0bacdfe877b002f3
+Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
+(cherry picked from commit 94a76ed58629932f6d689c48ecf8d3132188923b)
+Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
+(cherry picked from commit 8c23f65ec4889f9ff7f609002a129698796de2b8)
+---
+
+diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
+index 3e11b86..e4d94e4 100644
+--- a/src/qml/qml/qqmlglobal.cpp
++++ b/src/qml/qml/qqmlglobal.cpp
+@@ -1112,9 +1112,9 @@
+ 
+     // A non-composite type will always have a metaobject.
+     const QMetaObject *typeMetaObject = type.metaObject();
+-    const QQmlPropertyCache::ConstPtr typePropertyCache = typeMetaObject
+-            ? QQmlPropertyCache::ConstPtr()
+-            : QQmlMetaType::findPropertyCacheInCompositeTypes(type.typeId());
++    QVarLengthArray<QQmlPropertyCache::ConstPtr, 4> allPropertyCacheCandidates =
++            typeMetaObject ? QVarLengthArray<QQmlPropertyCache::ConstPtr, 4>{}
++                           : QQmlMetaType::rawCompositePropertyCachesForType(type.typeId());
+ 
+     if (const QQmlData *ddata = ddata_for_cast(object)) {
+         for (const QQmlPropertyCache *propertyCache = ddata->propertyCache.data(); propertyCache;
+@@ -1134,17 +1134,17 @@
+                 // property caches to be unrelated but the types still convertible.
+                 // Multiple property caches can hold the same metaobject, for example for
+                 // versions of non-composite types.
+-                if (propertyCache == typePropertyCache.data())
++                if (allPropertyCacheCandidates.contains(propertyCache))
+                     return true;
+             }
+         }
+     }
+ 
+-    // If nothing else works, we have to create the metaobjects.
++    // If nothing else works, we have to create the metaobjects (if we can).
++    if (!typeMetaObject && !allPropertyCacheCandidates.isEmpty())
++        typeMetaObject = allPropertyCacheCandidates.first()->createMetaObject();
+ 
+-    return object->metaObject()->inherits(typeMetaObject
+-            ? typeMetaObject
+-            : (typePropertyCache ? typePropertyCache->createMetaObject() : nullptr));
++    return object->metaObject()->inherits(typeMetaObject);
+ }
+ 
+ QT_END_NAMESPACE
+diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
+index 173c21d..1703c99 100644
+--- a/src/qml/qml/qqmlmetatype.cpp
++++ b/src/qml/qml/qqmlmetatype.cpp
+@@ -1490,6 +1490,20 @@
+ /*!
+  * \internal
+  *
++ * Returns all candidate property caches for a composite
++ * metatype instead of only the last inserted one.
++ * compare rawPropertyCacheForType (which handles however also non-composites)
++ */
++QVarLengthArray<QQmlPropertyCache::ConstPtr, 4>
++QQmlMetaType::rawCompositePropertyCachesForType(QMetaType metaType)
++{
++    const QQmlMetaTypeDataPtr data;
++    return data->findPropertyCachesInCompositeTypes(metaType);
++}
++
++/*!
++ * \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".
+  */
+diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
+index 62b6cba..040a42d 100644
+--- a/src/qml/qml/qqmlmetatype_p.h
++++ b/src/qml/qml/qqmlmetatype_p.h
+@@ -23,6 +23,7 @@
+ #include <private/qtqmlglobal_p.h>
+ 
+ #include <QtCore/qtyperevision.h>
++#include <QtCore/qvarlengtharray.h>
+ 
+ QT_BEGIN_NAMESPACE
+ 
+@@ -171,6 +172,10 @@
+     static QQmlPropertyCache::ConstPtr rawPropertyCacheForType(
+             QMetaType metaType, QTypeRevision version);
+ 
++    // All property caches for a composite metatype, which may map to more than one of them.
++    static QVarLengthArray<QQmlPropertyCache::ConstPtr, 4> rawCompositePropertyCachesForType(
++            QMetaType metaType);
++
+     static bool canConvert(QObject *o, QMetaType metaType);
+     static bool canConvert(const QQmlPropertyCache::ConstPtr &from, QMetaType metaType);
+ 
+diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
+index e72a3a9..41d7d8c 100644
+--- a/src/qml/qml/qqmlmetatypedata.cpp
++++ b/src/qml/qml/qqmlmetatypedata.cpp
+@@ -257,6 +257,18 @@
+             : propertyCacheForPotentialInlineComponentType(t, iter);
+ }
+ 
++QVarLengthArray<QQmlPropertyCache::ConstPtr, 4>
++QQmlMetaTypeData::findPropertyCachesInCompositeTypes(QMetaType t) const
++{
++    QVarLengthArray<QQmlPropertyCache::ConstPtr, 4> result;
++    const auto [begin, end] = compositeTypes.equal_range(t.iface());
++    for (auto iter = begin; iter != end; ++iter) {
++        if (auto cache = propertyCacheForPotentialInlineComponentType(t, iter))
++            result.append(std::move(cache));
++    }
++    return result;
++}
++
+ void QQmlMetaTypeData::clearCompositeTypes()
+ {
+     // Unregister all remaining composite types.
+diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h
+index ce13c40..95c60a1 100644
+--- a/src/qml/qml/qqmlmetatypedata_p.h
++++ b/src/qml/qml/qqmlmetatypedata_p.h
+@@ -23,6 +23,7 @@
+ #include <private/qqmlvaluetype_p.h>
+ 
+ #include <QtCore/qset.h>
++#include <QtCore/qvarlengtharray.h>
+ #include <QtCore/qvector.h>
+ 
+ QT_BEGIN_NAMESPACE
+@@ -119,6 +120,10 @@
+     QQmlPropertyCache::ConstPtr propertyCache(const QQmlType &type, QTypeRevision version);
+     QQmlPropertyCache::ConstPtr findPropertyCacheInCompositeTypes(QMetaType t) const;
+ 
++    // Same, but returns all matches rather than only the last inserted one.
++    QVarLengthArray<QQmlPropertyCache::ConstPtr, 4> findPropertyCachesInCompositeTypes(
++            QMetaType t) const;
++
+     static QQmlPropertyCache::ConstPtr propertyCacheForPotentialInlineComponentType(
+             QMetaType t, const QQmlMetaTypeData::CompositeTypes::const_iterator &iter);
+ 
+diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp
+index c252f47..1acbb22 100644
+--- a/src/qml/qml/qqmlpropertyvalidator.cpp
++++ b/src/qml/qml/qqmlpropertyvalidator.cpp
+@@ -2,6 +2,7 @@
+ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+ // Qt-Security score:significant
+ 
++#include "qqmlmetatype_p.h"
+ #include "qqmlpropertyvalidator_p.h"
+ 
+ #include <private/qqmlcustomparser_p.h>
+@@ -781,10 +782,29 @@
+             // Will be true if the assigned type inherits propertyMetaObject
+             // Determine isAssignable value
+             bool isAssignable = false;
+-            QQmlPropertyCache::ConstPtr c = propertyCaches.at(binding->value.objectIndex);
+-            while (c && !isAssignable) {
+-                isAssignable |= c == propertyMetaObject;
+-                c = c->parent();
++            QQmlPropertyCache::ConstPtr source = propertyCaches.at(binding->value.objectIndex);
++
++            const auto inheritsFrom = [&](const QQmlPropertyCache::ConstPtr &target) {
++                for (QQmlPropertyCache::ConstPtr c = source; c; c = c->parent()) {
++                    if (c == target)
++                        return true;
++                }
++                return false;
++            };
++
++            isAssignable = inheritsFrom(propertyMetaObject);
++
++            if (!isAssignable) {
++                // A single (composite) metatype can map to multiple property caches when
++                // there are multiple engines; rawPropertyCacheForType only returns one of
++                // them. For non-composite types this yields an empty list and is a no-op.
++                const auto candidates = QQmlMetaType::rawCompositePropertyCachesForType(propType);
++                for (const auto &candidate : candidates) {
++                    if (inheritsFrom(candidate)) {
++                        isAssignable = true;
++                        break;
++                    }
++                }
+             }
+ 
+             if (!isAssignable) {
+diff --git a/tests/auto/qml/qqmllanguage/data/canQmlCastMultiEngine/Foo.qml b/tests/auto/qml/qqmllanguage/data/canQmlCastMultiEngine/Foo.qml
+new file mode 100644
+index 0000000..8fc36a4
+--- /dev/null
++++ b/tests/auto/qml/qqmllanguage/data/canQmlCastMultiEngine/Foo.qml
+@@ -0,0 +1,3 @@
++import QtQml
++
++QtObject {}
+diff --git a/tests/auto/qml/qqmllanguage/data/canQmlCastMultiEngine/Main.qml b/tests/auto/qml/qqmllanguage/data/canQmlCastMultiEngine/Main.qml
+new file mode 100644
+index 0000000..1470151
+--- /dev/null
++++ b/tests/auto/qml/qqmllanguage/data/canQmlCastMultiEngine/Main.qml
+@@ -0,0 +1,9 @@
++import QtQml
++
++QtObject {
++    property Foo theFoo: Foo {}
++
++    function check(foo: Foo) : bool {
++        return foo !== null;
++    }
++}
+diff --git a/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Consumer1.qml b/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Consumer1.qml
+new file mode 100644
+index 0000000..80de08e
+--- /dev/null
++++ b/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Consumer1.qml
+@@ -0,0 +1,5 @@
++import QtQml
++
++QtObject {
++    property Foo f: Foo {}
++}
+diff --git a/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Consumer2.qml b/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Consumer2.qml
+new file mode 100644
+index 0000000..80de08e
+--- /dev/null
++++ b/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Consumer2.qml
+@@ -0,0 +1,5 @@
++import QtQml
++
++QtObject {
++    property Foo f: Foo {}
++}
+diff --git a/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Foo.qml b/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Foo.qml
+new file mode 100644
+index 0000000..8fc36a4
+--- /dev/null
++++ b/tests/auto/qml/qqmllanguage/data/propertyValidatorMultiEngine/Foo.qml
+@@ -0,0 +1,3 @@
++import QtQml
++
++QtObject {}
+diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+index c683aa1..0af0f34 100644
+--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
++++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+@@ -298,6 +298,8 @@
+     void instanceof();
+     void instanceofMultiEngine();
+     void instanceofMultiEngineInlineComponent();
++    void propertyValidatorMultiEngine();
++    void canQmlCastMultiEngine();
+ 
+     void concurrentLoadQmlDir();
+ 
+@@ -6013,6 +6015,51 @@
+     QVERIFY(result2.toBool());
+ }
+ 
++// verify that the property validator does not get confused when
++// multiple engines end up registering the same type, leading to
++// multiple entries in compositeTypes
++void tst_qqmllanguage::propertyValidatorMultiEngine()
++{
++    QQmlEngine engine1;
++    QQmlComponent c1(&engine1, testFileUrl("propertyValidatorMultiEngine/Consumer1.qml"));
++    QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
++
++    QQmlEngine engine2;
++    QQmlComponent c2(&engine2, testFileUrl("propertyValidatorMultiEngine/Consumer1.qml"));
++    QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
++
++    QQmlComponent c3(&engine1, testFileUrl("propertyValidatorMultiEngine/Consumer2.qml"));
++    QVERIFY2(c3.isReady(), qPrintable(c3.errorString()));
++}
++
++// Verify that qmlobject_can_qml_cast() still recognizes a composite type when
++// multiple engines have loaded the same QML file
++void tst_qqmllanguage::canQmlCastMultiEngine()
++{
++    const QUrl url = testFileUrl("canQmlCastMultiEngine/Main.qml");
++
++    QQmlEngine engine1;
++    QQmlComponent c1(&engine1, url);
++    QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
++    QScopedPointer<QObject> obj1(c1.create());
++    QVERIFY(obj1);
++
++    // A second engine loads the same file and registers another compilation unit
++    // (and thus another property cache) for Foo.
++    QQmlEngine engine2;
++    QQmlComponent c2(&engine2, url);
++    QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
++    QScopedPointer<QObject> obj2(c2.create());
++    QVERIFY(obj2);
++
++    // Call the typed function on engine1's object with engine1's Foo instance.
++    QQmlExpression expr(engine1.contextForObject(obj1.data()), obj1.data(),
++                        QStringLiteral("check(theFoo)"));
++    const QVariant result = expr.evaluate();
++    QVERIFY2(!expr.hasError(), qPrintable(expr.error().description()));
++    QVERIFY(result.toBool());
++}
++
+ void tst_qqmllanguage::concurrentLoadQmlDir()
+ {
+     ThreadedTestHTTPServer server(dataDirectory());

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [rpms/qt6-qtdeclarative] rawhide: Upstream backport:
@ 2026-07-14  5:41 Jan Grulich
  0 siblings, 0 replies; 2+ messages in thread
From: Jan Grulich @ 2026-07-14  5:41 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/qt6-qtdeclarative
            Branch : rawhide
            Commit : 2bc3f001ec2964ce90237afc3102b075cc548a49
            Author : Jan Grulich <jgrulich@redhat.com>
            Date   : 2026-07-14T07:41:14+02:00
            Stats  : +39/-1 in 2 file(s)
            URL    : https://src.fedoraproject.org/rpms/qt6-qtdeclarative/c/2bc3f001ec2964ce90237afc3102b075cc548a49?branch=rawhide

            Log:
            Upstream backport:
a11y: Guard against nullptr for scrollbar valueInterface

---
diff --git a/qt6-qtdeclarative.spec b/qt6-qtdeclarative.spec
index a7493be..99ab65e 100644
--- a/qt6-qtdeclarative.spec
+++ b/qt6-qtdeclarative.spec
@@ -16,7 +16,7 @@
 Summary: Qt6 - QtDeclarative component
 Name:    qt6-%{qt_module}
 Version: 6.11.1
-Release: 2%{?dist}
+Release: 3%{?dist}
 
 License: LGPL-3.0-only OR GPL-3.0-only WITH Qt-GPL-exception-1.0
 Url:     http://www.qt.io
@@ -36,6 +36,7 @@ Source5: qv4global_p-multilib.h
 ## upstream patches
 Patch0:  qtdeclarative-dialogs-use-generic-qtquickcontrols-import-in-base-fallback-dialogs.patch
 Patch1:  qtdeclarative-qmltableinstancemodel-refactor-qmodelindex-calculation-out-of-qquicktableview.patch
+Patch2:  qtdeclarative-a11y-guard-against-nullptr-for-scrollbar-valueinterface.patch
 
 ## upstreamable patches
 
@@ -754,6 +755,10 @@ make check -k -C tests ||:
 %endif
 
 %changelog
+* Tue Jul 14 2026 Jan Grulich <jgrulich@redhat.com> - 6.11.1-3
+- Upstream backport:
+  - a11y: Guard against nullptr for scrollbar valueInterface
+
 * Mon May 25 2026 Jan Grulich <jgrulich@redhat.com> - 6.11.1-2
 - Upstream backport:
   - QQmlTableInstanceModel: refactor QModelIndex calculation out

diff --git a/qtdeclarative-a11y-guard-against-nullptr-for-scrollbar-valueinterface.patch b/qtdeclarative-a11y-guard-against-nullptr-for-scrollbar-valueinterface.patch
new file mode 100644
index 0000000..aac99c8
--- /dev/null
+++ b/qtdeclarative-a11y-guard-against-nullptr-for-scrollbar-valueinterface.patch
@@ -0,0 +1,33 @@
+From 0093e85bbff86a25f3ab069de8ac19b3d723f706 Mon Sep 17 00:00:00 2001
+From: Magnus Groß <magnus@mggross.com>
+Date: Sat, 30 May 2026 21:26:03 +0200
+Subject: [PATCH] a11y: Guard against nullptr for scrollbar valueInterface
+
+The regression was introduced in 3e233634d83, which mistakenly assumed
+that valueInterface cannot be nullptr.
+
+Fixes: QTBUG-146959
+Pick-to: 6.11
+Change-Id: Ia47a05c9da6bf3889b12475f737aeab20485fe59
+Reviewed-by: MohammadHossein Qanbari <mohammad.qanbari@qt.io>
+---
+
+diff --git a/src/quicktemplates/qquickscrollbar.cpp b/src/quicktemplates/qquickscrollbar.cpp
+index f7d0600..70c3b69 100644
+--- a/src/quicktemplates/qquickscrollbar.cpp
++++ b/src/quicktemplates/qquickscrollbar.cpp
+@@ -474,10 +474,10 @@
+ #if QT_CONFIG(accessibility)
+     if (QAccessible::isActive()) {
+         if (QAccessibleInterface *accessible = QAccessible::queryAccessibleInterface(q)) {
+-            QAccessibleValueInterface *valueInterface = accessible->valueInterface();
+-            Q_ASSERT(valueInterface);
+-            QAccessibleValueChangeEvent event(q, valueInterface->currentValue());
+-            QAccessible::updateAccessibility(&event);
++            if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
++                QAccessibleValueChangeEvent event(q, valueInterface->currentValue());
++                QAccessible::updateAccessibility(&event);
++            }
+         }
+     }
+ #endif

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-11 10:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-11 10:34 [rpms/qt6-qtdeclarative] rawhide: Upstream backport: Jan Grulich
  -- strict thread matches above, loose matches on Subject: below --
2026-07-14  5:41 Jan Grulich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox