+226
@@ -0,0 +1,226 @@
|
|||||||
|
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
|
||||||
|
index 083c3ec2df8..ef36bf67c50 100644
|
||||||
|
--- a/src/qml/jsruntime/qv4lookup_p.h
|
||||||
|
+++ b/src/qml/jsruntime/qv4lookup_p.h
|
||||||
|
@@ -159,6 +159,10 @@ struct Q_QML_EXPORT Lookup {
|
||||||
|
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;
|
||||||
|
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
|
||||||
|
index 4e3b4fcf1ee..3f0d9e332b1 100644
|
||||||
|
--- a/src/qml/qml/qqml.cpp
|
||||||
|
+++ b/src/qml/qml/qqml.cpp
|
||||||
|
@@ -1386,16 +1386,16 @@ struct FallbackPropertyQmlData
|
||||||
|
|
||||||
|
static FallbackPropertyQmlData findFallbackPropertyQmlData(QV4::Lookup *lookup, QObject *object)
|
||||||
|
{
|
||||||
|
+ // We've just initialized the lookup. So everything must be fine here.
|
||||||
|
+
|
||||||
|
QQmlData *qmlData = QQmlData::get(object);
|
||||||
|
- if (qmlData && qmlData->isQueuedForDeletion)
|
||||||
|
- return {qmlData, nullptr, PropertyResult::Deleted};
|
||||||
|
|
||||||
|
+ 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 @@ bool AOTCompiledContext::loadScopeObjectPropertyLookup(uint index, void *target)
|
||||||
|
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 @@ bool AOTCompiledContext::writeBackScopeObjectPropertyLookup(uint index, void *so
|
||||||
|
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 @@ bool AOTCompiledContext::getObjectLookup(uint index, QObject *object, void *targ
|
||||||
|
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 @@ bool AOTCompiledContext::writeBackObjectLookup(uint index, QObject *object, void
|
||||||
|
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 @@ bool AOTCompiledContext::setObjectLookup(uint index, QObject *object, void *valu
|
||||||
|
result = lookup->asVariant
|
||||||
|
? storeFallbackAsVariant(engine->handle(), lookup, object, value)
|
||||||
|
: storeFallbackProperty(lookup, object, value);
|
||||||
|
+ lookup->call = QV4::Lookup::Call::SetterGeneric;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
|
||||||
|
index 79e908c9674..67cdefa30d9 100644
|
||||||
|
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
|
||||||
|
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
|
||||||
|
@@ -26,6 +26,7 @@ set(cpp_sources
|
||||||
|
multiforeign.h
|
||||||
|
objectwithmethod.h
|
||||||
|
person.cpp person.h
|
||||||
|
+ propertymap.h
|
||||||
|
qmlusing.h
|
||||||
|
recursiveObject.h
|
||||||
|
refuseWrite.h
|
||||||
|
@@ -282,6 +283,7 @@ set(qml_files
|
||||||
|
popContextAfterRet.qml
|
||||||
|
prefixedMetaType.qml
|
||||||
|
pressAndHoldButton.qml
|
||||||
|
+ propertyMap.qml
|
||||||
|
qmlUsing.qml
|
||||||
|
qtbug113150.qml
|
||||||
|
qtfont.qml
|
||||||
|
diff --git a/tests/auto/qml/qmlcppcodegen/data/propertyMap.qml b/tests/auto/qml/qmlcppcodegen/data/propertyMap.qml
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000..c00f3972e8a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/auto/qml/qmlcppcodegen/data/propertyMap.qml
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+pragma Strict
|
||||||
|
+import TestTypes
|
||||||
|
+
|
||||||
|
+WithPropertyMap {
|
||||||
|
+ objectName: map.foo
|
||||||
|
+}
|
||||||
|
diff --git a/tests/auto/qml/qmlcppcodegen/data/propertymap.h b/tests/auto/qml/qmlcppcodegen/data/propertymap.h
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000..64d84c5c097
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/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
|
||||||
|
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
|
||||||
|
index 70c50b457a9..a90e2a60505 100644
|
||||||
|
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
|
||||||
|
+++ b/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 @@ private slots:
|
||||||
|
void parentProperty();
|
||||||
|
void popContextAfterRet();
|
||||||
|
void prefixedType();
|
||||||
|
+ void propertyMap();
|
||||||
|
void propertyOfParent();
|
||||||
|
void qmlUsing();
|
||||||
|
void qtfont();
|
||||||
|
@@ -4908,6 +4910,47 @@ void tst_QmlCppCodegen::prefixedType()
|
||||||
|
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;
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<Dependency versionFrom="6.10.1">qt6-languageserver-devel</Dependency>
|
<Dependency versionFrom="6.10.1">qt6-languageserver-devel</Dependency>
|
||||||
</BuildDependencies>
|
</BuildDependencies>
|
||||||
<Patches>
|
<Patches>
|
||||||
<!-- <Patch level="1">CVE-2025-12385-qtdeclarative-6.9-0001.diff</Patch> -->
|
<Patch level="1">9c6b2b78e9076f1c2676aa0c41573db9ca480654.diff</Patch>
|
||||||
<!-- <Patch level="1">CVE-2025-12385-qtdeclarative-6.9-0002.diff</Patch> -->
|
<!-- <Patch level="1">CVE-2025-12385-qtdeclarative-6.9-0002.diff</Patch> -->
|
||||||
</Patches>
|
</Patches>
|
||||||
</Source>
|
</Source>
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
</Files>
|
</Files>
|
||||||
</Package-->
|
</Package-->
|
||||||
<History>
|
<History>
|
||||||
<Update release="20">
|
<Update release="21">
|
||||||
<Date>2025-11-30</Date>
|
<Date>2025-11-30</Date>
|
||||||
<Version>6.10.1</Version>
|
<Version>6.10.1</Version>
|
||||||
<Comment>Version bump.</Comment>
|
<Comment>Version bump.</Comment>
|
||||||
|
|||||||
Reference in New Issue
Block a user