Don't crash with deferred properties
There are cases where a qmlExecuteDeferred(o) can be postponed until the context of o is being destroyed, at which point it's too late to create an object in that context. Task-number: QTBUG-33112 Change-Id: I7f981b5e34e3cb8a52c00de4742a7242d7e4df54 Reviewed-by: Christopher Adams <chris.adams@jollamobile.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
da91b1c731
commit
fac5337abf
|
|
@ -1287,7 +1287,7 @@ void qmlExecuteDeferred(QObject *object)
|
|||
{
|
||||
QQmlData *data = QQmlData::get(object);
|
||||
|
||||
if (data && data->deferredData) {
|
||||
if (data && data->deferredData && !data->wasDeleted(object)) {
|
||||
QQmlObjectCreatingProfiler prof;
|
||||
if (prof.enabled) {
|
||||
QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
import Qt.test 1.0
|
||||
|
||||
MyVeryDeferredObject {
|
||||
id: root
|
||||
objectProperty: MyQmlObject { }
|
||||
}
|
||||
|
|
@ -252,6 +252,7 @@ void registerTypes()
|
|||
qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObjectAlias");
|
||||
qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObject");
|
||||
qmlRegisterType<MyDeferredObject>("Qt.test", 1,0, "MyDeferredObject");
|
||||
qmlRegisterType<MyVeryDeferredObject>("Qt.test", 1,0, "MyVeryDeferredObject");
|
||||
qmlRegisterType<MyQmlContainer>("Qt.test", 1,0, "MyQmlContainer");
|
||||
qmlRegisterExtendedType<MyBaseExtendedObject, BaseExtensionObject>("Qt.test", 1,0, "MyBaseExtendedObject");
|
||||
qmlRegisterExtendedType<MyExtendedObject, ExtensionObject>("Qt.test", 1,0, "MyExtendedObject");
|
||||
|
|
|
|||
|
|
@ -376,6 +376,34 @@ private:
|
|||
QObject *m_object2;
|
||||
};
|
||||
|
||||
class MyVeryDeferredObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
//For inDestruction test
|
||||
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
|
||||
Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty)
|
||||
Q_CLASSINFO("DeferredPropertyNames", "objectProperty")
|
||||
|
||||
public:
|
||||
MyVeryDeferredObject() : m_value(0), m_object(0) {}
|
||||
~MyVeryDeferredObject() {
|
||||
qmlExecuteDeferred(this); //Not a realistic case, see QTBUG-33112 to see how this could happen in practice
|
||||
}
|
||||
|
||||
int value() const { return m_value; }
|
||||
void setValue(int v) { m_value = v; emit valueChanged(); }
|
||||
|
||||
QObject *objectProperty() const { return m_object; }
|
||||
void setObjectProperty(QObject *obj) { m_object = obj; }
|
||||
|
||||
signals:
|
||||
void valueChanged();
|
||||
|
||||
private:
|
||||
int m_value;
|
||||
QObject *m_object;
|
||||
};
|
||||
|
||||
class MyBaseExtendedObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ private slots:
|
|||
void deferredProperties();
|
||||
void deferredPropertiesErrors();
|
||||
void deferredPropertiesInComponents();
|
||||
void deferredPropertiesInDestruction();
|
||||
void extensionObjects();
|
||||
void overrideExtensionProperties();
|
||||
void attachedProperties();
|
||||
|
|
@ -924,6 +925,19 @@ void tst_qqmlecmascript::deferredPropertiesInComponents()
|
|||
delete object;
|
||||
}
|
||||
|
||||
void tst_qqmlecmascript::deferredPropertiesInDestruction()
|
||||
{
|
||||
//Test that the component does not get created at all if creation is deferred until the containing context is destroyed
|
||||
//Very specific operation ordering is needed for this to occur, currently accessing object from object destructor.
|
||||
//
|
||||
QQmlComponent component(&engine, testFileUrl("deferredPropertiesInDestruction.qml"));
|
||||
QObject *object = component.create();
|
||||
if (!object)
|
||||
qDebug() << component.errorString();
|
||||
QVERIFY(object != 0);
|
||||
delete object; //QTBUG-33112 was that this used to cause a crash
|
||||
}
|
||||
|
||||
void tst_qqmlecmascript::extensionObjects()
|
||||
{
|
||||
QQmlComponent component(&engine, testFileUrl("extensionObjects.qml"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue