summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-05-10 14:53:11 +0200
committerUlf Hermann <ulf.hermann@qt.io>2023-05-11 09:57:13 +0000
commit21d728aff3f157750fa25fa1409c01e516a71667 (patch)
tree7c62daa317a6af9fcf9face48422d1e5ccc8f594
parent1314592f41abecb6f1140d3bfe39bba8a2c4ea7e (diff)
downloadqtdeclarative-21d728aff3f157750fa25fa1409c01e516a71667.tar.gz
QML: Maintain invariant between QObjectMethod members
If the methodCount is 0, the methods have to be nullptr. Otherwise they have to point to the actual method(s). This is important for the method resolution to work correctly. In particular when cloning a method we have to check for 0. Amends commit 17bd07cbc5b6cf54716e991765ab3088a710d7b3. Pick-to: 6.5 Fixes: QTBUG-113484 Change-Id: Ic31d6e391c1d74a162820232f242a19379f5e4df Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp22
-rw-r--r--tests/auto/qml/qqmllanguage/data/UIToolBar.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectMethodClone.qml23
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp12
4 files changed, 64 insertions, 3 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index ba94a7ad95..f308cd7660 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -2340,14 +2340,25 @@ ReturnedValue QObjectMethod::create(
else
method->d()->setObject(object);
- if (cloneFrom->methodCount == 1) {
+ Q_ASSERT(method->d()->methods == nullptr);
+ switch (cloneFrom->methodCount) {
+ case 0:
+ Q_ASSERT(cloneFrom->methods == nullptr);
+ break;
+ case 1:
+ Q_ASSERT(cloneFrom->methods
+ == reinterpret_cast<QQmlPropertyData *>(&cloneFrom->_singleMethod));
method->d()->methods = reinterpret_cast<QQmlPropertyData *>(&method->d()->_singleMethod);
*method->d()->methods = *cloneFrom->methods;
- } else {
+ break;
+ default:
+ Q_ASSERT(cloneFrom->methods != nullptr);
method->d()->methods = new QQmlPropertyData[cloneFrom->methodCount];
memcpy(method->d()->methods, cloneFrom->methods,
cloneFrom->methodCount * sizeof(QQmlPropertyData));
+ break;
}
+
return method.asReturnedValue();
}
@@ -2473,8 +2484,10 @@ QString Heap::QObjectMethod::name() const
void Heap::QObjectMethod::ensureMethodsCache(const QMetaObject *thisMeta)
{
- if (methods)
+ if (methods) {
+ Q_ASSERT(methodCount > 0);
return;
+ }
const QMetaObject *mo = metaObject();
@@ -2511,6 +2524,8 @@ void Heap::QObjectMethod::ensureMethodsCache(const QMetaObject *thisMeta)
*methods = resolvedMethods.at(0);
methodCount = 1;
}
+
+ Q_ASSERT(methodCount > 0);
}
static QObject *qObject(const Value *v)
@@ -2637,6 +2652,7 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value *
};
if (d()->methodCount != 1) {
+ Q_ASSERT(d()->methodCount > 0);
method = ResolveOverloaded(object, d()->methods, d()->methodCount, v4, callData);
if (method == nullptr)
return Encode::undefined();
diff --git a/tests/auto/qml/qqmllanguage/data/UIToolBar.qml b/tests/auto/qml/qqmllanguage/data/UIToolBar.qml
new file mode 100644
index 0000000000..08a22d2492
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/UIToolBar.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ id: root
+ signal doneClicked()
+ signal foo()
+
+ onObjectNameChanged: foo()
+ Component.onCompleted: root.foo.connect(root.doneClicked)
+}
diff --git a/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml b/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml
new file mode 100644
index 0000000000..e21179ea14
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml
@@ -0,0 +1,23 @@
+import QtQml
+
+QtObject {
+ id: window
+
+ property int doneClicks: 0
+
+ property UIToolBar t1: UIToolBar {
+ objectName: window.objectName
+ onDoneClicked: window.doneClicks++
+ }
+
+ property UIToolBar t2: UIToolBar {
+ objectName: window.objectName
+ onDoneClicked: window.doneClicks++
+ }
+
+ property Timer timer: Timer {
+ interval: 10
+ running: true
+ onTriggered: window.objectName = "bar"
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 371179a39e..f171d55d03 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -413,6 +413,8 @@ private slots:
void typedEnums_data();
void typedEnums();
+ void objectMethodClone();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -7974,6 +7976,16 @@ void tst_qqmllanguage::typedEnums()
QCOMPARE(o->property("output2").toDouble(), value);
}
+void tst_qqmllanguage::objectMethodClone()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("objectMethodClone.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QTRY_COMPARE(o->property("doneClicks").toInt(), 2);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"