Connections: Don't crash when target is deleted

Pick-to: 6.4 6.2
Fixes: QTBUG-108697
Change-Id: I019edf3a0a702ad1dca340473265933e4d131e99
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Fabian Kosmale 2022-11-07 15:52:54 +01:00 committed by Ulf Hermann
parent b6ba7e9c90
commit 6cd8d209ec
3 changed files with 57 additions and 8 deletions

View File

@ -24,15 +24,13 @@ Q_LOGGING_CATEGORY(lcQmlConnections, "qt.qml.connections")
class QQmlConnectionsPrivate : public QObjectPrivate
{
public:
QQmlConnectionsPrivate() : target(nullptr), enabled(true), targetSet(false), ignoreUnknownSignals(false), componentcomplete(true) {}
QList<QQmlBoundSignal*> boundsignals;
QObject *target;
QQmlGuard<QObject> target;
bool enabled;
bool targetSet;
bool ignoreUnknownSignals;
bool componentcomplete;
bool enabled = true;
bool targetSet = false;
bool ignoreUnknownSignals = false;
bool componentcomplete = true;
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
QList<const QV4::CompiledData::Binding *> bindings;
@ -119,7 +117,7 @@ QQmlConnections::QQmlConnections(QObject *parent) :
QObject *QQmlConnections::target() const
{
Q_D(const QQmlConnections);
return d->targetSet ? d->target : parent();
return d->targetSet ? d->target.data() : parent();
}
class QQmlBoundSignalDeleter : public QObject

View File

@ -0,0 +1,31 @@
import QtQml
QtObject {
id: root
objectName: button.objectName
property QtObject b: QtObject {
objectName: "button"
id: button
signal clicked
}
property Connections c: Connections {
id: connections
target: null
function onClicked() { button.destroy(); }
}
property Timer t: Timer {
interval: 10
running: true
onTriggered: {
root.objectName = connections.target.objectName
}
}
Component.onCompleted: {
connections.target = button;
button.clicked()
}
}

View File

@ -53,6 +53,7 @@ private slots:
void noAcceleratedGlobalLookup();
void bindToPropertyWithUnderscoreChangeHandler();
void invalidTarget();
private:
QQmlEngine engine;
@ -465,6 +466,25 @@ void tst_qqmlconnections::bindToPropertyWithUnderscoreChangeHandler()
QVERIFY(root->property("success").toBool());
}
void tst_qqmlconnections::invalidTarget()
{
QQmlEngine engine;
const QUrl url = testFileUrl("invalidTarget.qml");
QQmlComponent component(&engine, url);
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
QScopedPointer<QObject> root {component.create()};
QVERIFY(root);
QCOMPARE(root->objectName(), QStringLiteral("button"));
QTest::ignoreMessage(
QtWarningMsg,
qPrintable(
url.toString()
+ QLatin1String(":5:5: TypeError: Cannot read property 'objectName' of null")));
QTRY_VERIFY(root->objectName().isEmpty());
}
QTEST_MAIN(tst_qqmlconnections)
#include "tst_qqmlconnections.moc"