diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-10-04 16:20:29 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-10-07 08:06:32 +0200 |
commit | 2b371a50cbc1f54284fcea3834834ca58fc28fd0 (patch) | |
tree | 156ec5ad28cbf98fac083a870e79daf0ebb49bf3 | |
parent | 138f09bd63b8070686ed8a282375dbcf3ce7674f (diff) |
qmlRegisterSingletonInstance: Do not crash if instance gets deleted
Use a QPointer, so that we notice if the object has been deleted.
Also ensure that in the documentation the function is in a single line,
as qdoc will otherwise silently omit it.
Change-Id: Idecd370d00089997cd18b3247ad2290a561b2b69
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r-- | src/qml/doc/src/qmlfunctions.qdoc | 3 | ||||
-rw-r--r-- | src/qml/qml/qqml.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 3 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 10 |
4 files changed, 20 insertions, 3 deletions
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index b083012eab..b2d322465d 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -628,8 +628,7 @@ */ /*! - \fn int qmlRegisterSingletonInstance(const char *uri, int versionMajor, int - versionMinor, const char *typeName, QObject* cppObject) + \fn int qmlRegisterSingletonInstance(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject* cppObject) \relates QQmlEngine \since 5.14 diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 8a50b51b5d..5b16a3c9e2 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -79,6 +79,13 @@ int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *q // From qqmlprivate.h QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJSEngine *) { + if (!m_object) { + QQmlError error; + error.setDescription(QLatin1String("The registered singleton has already been deleted. Ensure that it outlives the engine.")); + QQmlEnginePrivate::get(qeng)->warning(qeng, error); + return nullptr; + } + if (qeng->thread() != m_object->thread()) { QQmlError error; error.setDescription(QLatin1String("Registered object must live in the same thread as the engine it was registered with")); diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index e6dd5e0b16..bfd3611fb8 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -58,6 +58,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qvariant.h> #include <QtCore/qurl.h> +#include <QPointer> QT_BEGIN_NAMESPACE @@ -326,7 +327,7 @@ namespace QQmlPrivate { QObject *operator()(QQmlEngine *, QJSEngine *); - QObject *m_object; + QPointer<QObject> m_object; bool alreadyCalled = false; }; } diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index aae42e9ebb..64f167b47e 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -1107,6 +1107,16 @@ void tst_qqmlengine::singletonInstance() SomeQObjectClass * instance = engine.singletonInstance<SomeQObjectClass*>(cppSingletonTypeId); QVERIFY(!instance); } + + { + // deleted object + auto dayfly = new QObject{}; + auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly); + delete dayfly; + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: The registered singleton has already been deleted. Ensure that it outlives the engine."); + QObject *instance = engine.singletonInstance<QObject*>(id); + QVERIFY(!instance); + } } void tst_qqmlengine::aggressiveGc() |