aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-02-26 12:44:21 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-03-01 09:51:19 +0100
commit939c132db071873ab7bf7159d53541ab17182214 (patch)
tree230b02423671ad69bcb08f94797188d7dc62eb04
parent72571aac9a393f0494831916ee53df8fa20f98c5 (diff)
QQmlPropertyCache: Correctly set flags when loading methods
We commonly load multiple methods in sequence into the same QQmlPropertyData. We need to set all the relevant flags for each one. Otherwise the wrong flags are transferred to subsequent methods. Pick-to: 6.5 Task-number: QTBUG-112366 Change-Id: I7432500b9149fdd8dd2dd98eb923ada70232fb6d Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> (cherry picked from commit 69ca18785c6693b6cf167dc95275a19399c7f4e1) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 93f72abeb2756a9f0306904b8a74b0f340a4ecc6)
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp33
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/childobject.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h7
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp8
4 files changed, 48 insertions, 8 deletions
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index b51fc963f7..ddab42336f 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -84,27 +84,44 @@ void QQmlPropertyData::load(const QMetaMethod &m)
{
setCoreIndex(m.methodIndex());
setArguments(nullptr);
+ m_flags.type = Flags::FunctionType;
- setPropType(m.returnMetaType());
+ // We need to set the constructor, signal, constant, arguments, V4Function, cloned flags.
+ // These are specific to methods and change with each method.
+ // The same QQmlPropertyData may be loaded with multiple methods in sequence.
- m_flags.type = Flags::FunctionType;
- if (m.methodType() == QMetaMethod::Signal) {
+ switch (m.methodType()) {
+ case QMetaMethod::Signal:
m_flags.setIsSignal(true);
- } else if (m.methodType() == QMetaMethod::Constructor) {
+ m_flags.setIsConstructor(false);
+ setPropType(m.returnMetaType());
+ break;
+ case QMetaMethod::Constructor:
+ m_flags.setIsSignal(false);
m_flags.setIsConstructor(true);
setPropType(QMetaType::fromType<QObject *>());
+ break;
+ default:
+ m_flags.setIsSignal(false);
+ m_flags.setIsConstructor(false);
+ setPropType(m.returnMetaType());
+ break;
}
+
m_flags.setIsConstant(m.isConst());
const int paramCount = m.parameterCount();
if (paramCount) {
m_flags.setHasArguments(true);
- if ((paramCount == 1) && (m.parameterMetaType(0) == QMetaType::fromType<QQmlV4Function *>()))
- m_flags.setIsV4Function(true);
+ m_flags.setIsV4Function(
+ paramCount == 1 &&
+ m.parameterMetaType(0) == QMetaType::fromType<QQmlV4Function *>());
+ } else {
+ m_flags.setHasArguments(false);
+ m_flags.setIsV4Function(false);
}
- if (m.attributes() & QMetaMethod::Cloned)
- m_flags.setIsCloned(true);
+ m_flags.setIsCloned(m.attributes() & QMetaMethod::Cloned);
Q_ASSERT(m.revision() <= std::numeric_limits<quint16>::max());
setRevision(QTypeRevision::fromEncodedVersion(m.revision()));
diff --git a/tests/auto/qml/qmlcppcodegen/data/childobject.qml b/tests/auto/qml/qmlcppcodegen/data/childobject.qml
index db6b910ec2..76ad8fbbb2 100644
--- a/tests/auto/qml/qmlcppcodegen/data/childobject.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/childobject.qml
@@ -8,6 +8,14 @@ QtObject {
function doString() { overloaded("string"); }
function doNumber() { overloaded(5.2); }
function doArray() { overloaded({a: 2, b: 3, c: 3}); }
+
+ function doString2() { overloaded2("string"); }
+ function doNumber2() { overloaded2(5.2); }
+
+ // Artificially pass an extra argument to avoid choosing the "string" overload.
+ // Unfortunately this is still order-dependent on the metaobject level.
+ function doArray2() { overloaded2({a: 2, b: 3, c: 3}, 1); }
+
function doFoo() { foo(this); }
}
objectName: child.objectName
diff --git a/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h b/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
index ee01d2a0d2..9d706ff9ac 100644
--- a/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
+++ b/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
@@ -29,12 +29,19 @@ public:
QProperty<int> theThing;
QBindable<int> theThingBindable() { return QBindable<int>(&theThing); }
+ // The meta methods are populated back to front.
+ // The V4Function flag should not bleed into the others in either case.
+
Q_INVOKABLE void overloaded(QQmlV4Function *) { setObjectName(QStringLiteral("javaScript")); }
Q_INVOKABLE void overloaded(double) { setObjectName(QStringLiteral("double")); }
Q_INVOKABLE void overloaded(const QString &) { setObjectName(QStringLiteral("string")); }
Q_INVOKABLE void foo(const QString &bla) { setObjectName(bla); }
Q_INVOKABLE void foo(ObjectWithMethod *) { setObjectName(QStringLiteral("ObjectWithMethod")); }
+
+ Q_INVOKABLE void overloaded2(double) { setObjectName(QStringLiteral("double")); }
+ Q_INVOKABLE void overloaded2(const QString &) { setObjectName(QStringLiteral("string")); }
+ Q_INVOKABLE void overloaded2(QQmlV4Function *) { setObjectName(QStringLiteral("javaScript")); }
};
class OverriddenObjectName : public ObjectWithMethod
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index cc8e6a81c5..beaf88cb3f 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -3321,6 +3321,14 @@ void tst_QmlCppCodegen::overriddenProperty()
QCOMPARE(child->objectName(), u"double"_s);
QMetaObject::invokeMethod(child, "doArray");
QCOMPARE(child->objectName(), u"javaScript"_s);
+
+ QMetaObject::invokeMethod(child, "doString2");
+ QCOMPARE(child->objectName(), u"string"_s);
+ QMetaObject::invokeMethod(child, "doNumber2");
+ QCOMPARE(child->objectName(), u"double"_s);
+ QMetaObject::invokeMethod(child, "doArray2");
+ QCOMPARE(child->objectName(), u"javaScript"_s);
+
QMetaObject::invokeMethod(child, "doFoo");
QCOMPARE(child->objectName(), u"ObjectWithMethod"_s);