Skip to content

Commit

Permalink
fix: port upstream fix to qt6-declarative 6.6.0
Browse files Browse the repository at this point in the history
Signed-off-by: ComixHe <[email protected]>
  • Loading branch information
ComixHe authored and deepin-ci-robot committed Dec 22, 2023
1 parent 808a1d8 commit 152cf21
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
6 changes: 6 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
qt6-declarative (6.6.0+dfsg-2deepin1) UNRELEASED; urgency=medium

* Port upstream fix to qt6-declarative 6.6.0

-- YuMing He <[email protected]> Tue, 19 Dec 2023 10:40:12 +0800

qt6-declarative (6.6.0+dfsg-2) UNRELEASED; urgency=medium

[ Patrick Franz ]
Expand Down
163 changes: 163 additions & 0 deletions debian/patches/fix-singleton-emit-signal-crashed.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
From a8ab23b67747fd8c2da7fdcc931f6e9d50d961da Mon Sep 17 00:00:00 2001
From: Fabian Kosmale <[email protected]>
Date: Fri, 06 Oct 2023 16:22:28 +0200
Subject: [PATCH] Fix regression on singletons where declared != actual type

For singletons, we can't rely on the static meta-object of the
registered type, as the create function used for a singleton might
return an instance of a derived type instead.
This could lead to crashes or method-overload resolution failures later
on.
Fix this by always querying the actual meta-object of the singleton,
instead of relying on the meta-object of the registered class.

Leave a comment about the fact that we still have an issue if you have a
derived instance of the registered type when you additionally extend the
type. However, that is pre-existing (given that it only affects QQmlType
itself).

Fixes: QTBUG-117891
Pick-to: 6.5 6.2
Change-Id: Ie12b4c886ace5cc58a5ded59fa48bc425ae58419
Reviewed-by: Ulf Hermann <[email protected]>
(cherry picked from commit 8c2ea501fdd07e44ee68e22dcc6d820ae93116f2)
Reviewed-by: Fabian Kosmale <[email protected]>
---

diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 11f454b..8432703 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -56,8 +56,25 @@
if (!type.isValid())
return nullptr;

- if (type.isSingleton())
- return type.metaObject();
+ if (type.isSingleton()) {
+ auto metaObjectCandidate = type.metaObject();
+ // if the candidate is the same as te baseMetaObject, we know that
+ // we don't have an extended singleton; in that case the
+ // actual instance might be subclass of type instead of type itself
+ // so we need to query the actual object for it's meta-object
+ if (metaObjectCandidate == type.baseMetaObject()) {
+ QQmlEnginePrivate *qmlEngine = QQmlEnginePrivate::get(engine()->qmlEngine());
+ auto object = qmlEngine->singletonInstance<QObject *>(type);
+ if (object)
+ return object->metaObject();
+ }
+ /* if we instead have an extended singleton, the dynamic proxy
+ meta-object must alreday be set up correctly
+ ### TODO: it isn't, as QQmlTypePrivate::init has no way to
+ query the object
+ */
+ return metaObjectCandidate;
+ }

return type.attachedPropertiesType(QQmlEnginePrivate::get(engine()->qmlEngine()));
}
diff --git a/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml b/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml
new file mode 100644
index 0000000..9d2ee43
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml
@@ -0,0 +1,6 @@
+import Qt.test
+import QtQml
+
+QtObject {
+ Component.onCompleted: SingletonInheritanceTest.trackPage("test", {x: 42})
+}
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index d7a585d..ba40b00 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -543,6 +543,8 @@
qmlRegisterType<Sender>("Qt.test", 1,0, "Sender");
qmlRegisterTypesAndRevisions<ReadOnlyBindable>("Qt.test", 1);
qmlRegisterTypesAndRevisions<ResettableGadgetHolder>("Qt.test", 1);
+
+ qmlRegisterTypesAndRevisions<SingletonRegistrationWrapper>("Qt.test", 1);
}

#include "testtypes.moc"
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index 64c079a..99cfb80 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -2069,6 +2069,43 @@
};


+class SingletonBase : public QObject {
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE virtual void trackPage(const QString&) {}
+ Q_INVOKABLE virtual void trackPage(const QString&, const QVariantMap&) {}
+
+ bool m_okay = false;
+};
+
+class SingletonImpl : public SingletonBase {
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE virtual void trackPage(const QString&) override {}
+ Q_INVOKABLE virtual void trackPage(const QString&, const QVariantMap&) override
+ {
+ m_okay = true;
+ }
+};
+
+class SingletonRegistrationWrapper {
+ Q_GADGET
+ QML_FOREIGN(SingletonBase)
+ QML_NAMED_ELEMENT(SingletonInheritanceTest)
+ QML_SINGLETON
+
+public:
+ static SingletonBase* create(QQmlEngine*, QJSEngine*) {
+ return new SingletonImpl();
+ }
+
+private:
+ SingletonRegistrationWrapper() = default;
+};
+
+
void registerTypes();

#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 59d0809..4023824 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -422,6 +422,8 @@

void resetGadet();

+ void methodCallOnDerivedSingleton();
+
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
static void verifyContextLifetime(const QQmlRefPointer<QQmlContextData> &ctxt);
@@ -10478,6 +10480,18 @@
QCOMPARE(resettableGadgetHolder->g().value(), 42);
}

+void tst_qqmlecmascript::methodCallOnDerivedSingleton()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFile("methodCallOnDerivedSingleton.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ auto singleton = engine.singletonInstance<SingletonBase *>("Qt.test", "SingletonInheritanceTest");
+ QVERIFY(singleton);
+ QVERIFY(singleton->m_okay);
+}
+
QTEST_MAIN(tst_qqmlecmascript)

#include "tst_qqmlecmascript.moc"
1 change: 1 addition & 0 deletions debian/patches/series
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fix-singleton-emit-signal-crashed.patch

0 comments on commit 152cf21

Please sign in to comment.