summaryrefslogtreecommitdiff
path: root/x11-toolkits/qt6-declarative/files/patch-QTBUG-142331
diff options
context:
space:
mode:
Diffstat (limited to 'x11-toolkits/qt6-declarative/files/patch-QTBUG-142331')
-rw-r--r--x11-toolkits/qt6-declarative/files/patch-QTBUG-142331229
1 files changed, 229 insertions, 0 deletions
diff --git a/x11-toolkits/qt6-declarative/files/patch-QTBUG-142331 b/x11-toolkits/qt6-declarative/files/patch-QTBUG-142331
new file mode 100644
index 000000000000..2e031cca4397
--- /dev/null
+++ b/x11-toolkits/qt6-declarative/files/patch-QTBUG-142331
@@ -0,0 +1,229 @@
+From 9c6b2b78e9076f1c2676aa0c41573db9ca480654 Mon Sep 17 00:00:00 2001
+From: Ulf Hermann <ulf.hermann@qt.io>
+Date: Tue, 02 Dec 2025 17:42:30 +0100
+Subject: [PATCH] QtQml: Invalidate fallback lookups after each call from AOT code
+
+Fallback property lookups are created for completely dynamic
+metaobjects. Anything about them may change between any two calls.
+
+Pick-to: 6.8 6.5
+Fixes: QTBUG-142331
+Change-Id: Ib732c37a6f27ab8105bea0eeae000af7eb9c36d7
+Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
+(cherry picked from commit 9af6d2d6d0046b3c8369e15eb4791957cdc7ab7b)
+Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
+---
+
+--- src/qml/jsruntime/qv4lookup_p.h
++++ src/qml/jsruntime/qv4lookup_p.h
+@@ -159,6 +159,10 @@
+ const QQmlPropertyData *propertyData;
+ } qobjectMethodLookup;
+ struct {
++ // NB: None of this is actually cache-able. The metaobject may change at any time.
++ // We invalidate this data every time the lookup is invoked and thereby force a
++ // re-initialization next time.
++
+ quintptr isConstant; // This is a bool, encoded as 0 or 1. Both values are ignored by gc
+ quintptr metaObject; // a (const QMetaObject* & 1) or nullptr
+ int coreIndex;
+--- src/qml/qml/qqml.cpp
++++ src/qml/qml/qqml.cpp
+@@ -1386,16 +1386,16 @@
+
+ static FallbackPropertyQmlData findFallbackPropertyQmlData(QV4::Lookup *lookup, QObject *object)
+ {
+- QQmlData *qmlData = QQmlData::get(object);
+- if (qmlData && qmlData->isQueuedForDeletion)
+- return {qmlData, nullptr, PropertyResult::Deleted};
++ // We've just initialized the lookup. So everything must be fine here.
+
++ QQmlData *qmlData = QQmlData::get(object);
++
++ Q_ASSERT(!qmlData || !qmlData->isQueuedForDeletion);
+ Q_ASSERT(!QQmlData::wasDeleted(object));
+
+ const QMetaObject *metaObject
+ = reinterpret_cast<const QMetaObject *>(lookup->qobjectFallbackLookup.metaObject - 1);
+- if (!metaObject || metaObject != object->metaObject())
+- return {qmlData, nullptr, PropertyResult::NeedsInit};
++ Q_ASSERT(metaObject == object->metaObject());
+
+ return {qmlData, metaObject, PropertyResult::OK};
+ }
+@@ -2585,6 +2585,7 @@
+ break;
+ case QV4::Lookup::Call::ContextGetterScopeObjectPropertyFallback:
+ result = loadFallbackProperty(lookup, qmlScopeObject, target, this);
++ lookup->call = QV4::Lookup::Call::ContextGetterGeneric;
+ break;
+ default:
+ return false;
+@@ -2616,6 +2617,7 @@
+ break;
+ case QV4::Lookup::Call::ContextGetterScopeObjectPropertyFallback:
+ result = writeBackFallbackProperty(lookup, qmlScopeObject, source);
++ lookup->call = QV4::Lookup::Call::ContextGetterGeneric;
+ break;
+ default:
+ return false;
+@@ -2816,6 +2818,7 @@
+ result = lookup->asVariant
+ ? loadFallbackAsVariant(lookup, object, target, this)
+ : loadFallbackProperty(lookup, object, target, this);
++ lookup->call = QV4::Lookup::Call::GetterGeneric;
+ break;
+ default:
+ return false;
+@@ -2850,6 +2853,7 @@
+ result = lookup->asVariant
+ ? writeBackFallbackAsVariant(lookup, object, source)
+ : writeBackFallbackProperty(lookup, object, source);
++ lookup->call = QV4::Lookup::Call::GetterGeneric;
+ break;
+ default:
+ return false;
+@@ -3010,6 +3014,7 @@
+ result = lookup->asVariant
+ ? storeFallbackAsVariant(engine->handle(), lookup, object, value)
+ : storeFallbackProperty(lookup, object, value);
++ lookup->call = QV4::Lookup::Call::SetterGeneric;
+ break;
+ default:
+ return false;
+--- tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
++++ tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+@@ -26,6 +26,7 @@
+ multiforeign.h
+ objectwithmethod.h
+ person.cpp person.h
++ propertymap.h
+ qmlusing.h
+ recursiveObject.h
+ refuseWrite.h
+@@ -282,6 +283,7 @@
+ popContextAfterRet.qml
+ prefixedMetaType.qml
+ pressAndHoldButton.qml
++ propertyMap.qml
+ qmlUsing.qml
+ qtbug113150.qml
+ qtfont.qml
+--- /dev/null
++++ tests/auto/qml/qmlcppcodegen/data/propertyMap.qml
+@@ -0,0 +1,6 @@
++pragma Strict
++import TestTypes
++
++WithPropertyMap {
++ objectName: map.foo
++}
+--- /dev/null
++++ tests/auto/qml/qmlcppcodegen/data/propertymap.h
+@@ -0,0 +1,40 @@
++// Copyright (C) 2025 The Qt Company Ltd.
++// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++#ifndef PROPERTYMAP_H
++#define PROPERTYMAP_H
++
++#include <QtCore/qobject.h>
++#include <QtQml/qqml.h>
++#include <QtQml/qqmlpropertymap.h>
++
++class WithPropertyMap : public QObject
++{
++ Q_OBJECT
++ QML_ELEMENT
++ Q_PROPERTY(QQmlPropertyMap *map READ map NOTIFY mapChanged)
++public:
++ WithPropertyMap(QObject *parent = nullptr)
++ : QObject(parent)
++ , m_map(new QQmlPropertyMap(this))
++ {
++ }
++
++ QQmlPropertyMap *map() const { return m_map; }
++
++ void setProperties(const QVariantHash &properties)
++ {
++ delete m_map;
++ m_map = new QQmlPropertyMap(this);
++ m_map->insert(properties);
++ emit mapChanged();
++ }
++
++signals:
++ void mapChanged();
++
++private:
++ QQmlPropertyMap *m_map = nullptr;
++};
++
++#endif // PROPERTYMAP_H
+--- tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
++++ tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+@@ -10,6 +10,7 @@
+ #include <data/getOptionalLookup.h>
+ #include <data/listprovider.h>
+ #include <data/objectwithmethod.h>
++#include <data/propertymap.h>
+ #include <data/qmlusing.h>
+ #include <data/refuseWrite.h>
+ #include <data/resettable.h>
+@@ -237,6 +238,7 @@
+ void parentProperty();
+ void popContextAfterRet();
+ void prefixedType();
++ void propertyMap();
+ void propertyOfParent();
+ void qmlUsing();
+ void qtfont();
+@@ -4908,6 +4910,47 @@
+ QCOMPARE(o->property("countH").toInt(), 11);
+ }
+
++void tst_QmlCppCodegen::propertyMap()
++{
++ QQmlEngine engine;
++
++ const QUrl document(u"qrc:/qt/qml/TestTypes/propertyMap.qml"_s);
++ QQmlComponent c(&engine, document);
++ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
++
++ QTest::ignoreMessage(
++ QtWarningMsg, qPrintable(
++ document.toString()
++ + u":5:5: QML WithPropertyMap: Unable to assign [undefined] to \"objectName\""));
++
++ QScopedPointer<QObject> o(c.create());
++ QVERIFY(o);
++
++ WithPropertyMap *w = qobject_cast<WithPropertyMap *>(o.data());
++ QVERIFY(w);
++
++ QVERIFY(w->objectName().isEmpty());
++
++ w->setProperties({
++ { u"foo"_s, u"aaa"_s },
++ { u"bar"_s, u"bbb"_s },
++ });
++
++ QCOMPARE(w->objectName(), u"aaa"_s);
++
++ w->setProperties({
++ { u"foo"_s, u"ccc"_s },
++ });
++
++ QCOMPARE(w->objectName(), u"ccc"_s);
++
++ w->setProperties({
++ { u"foo"_s, 24.25 },
++ });
++
++ QCOMPARE(w->objectName(), u"24.25"_s);
++}
++
+ void tst_QmlCppCodegen::propertyOfParent()
+ {
+ QQmlEngine engine;