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