aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-03-15 10:03:02 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-15 16:00:38 +0100
commitaf41170bc5e4c1be194bb9bbe883b00c2f7062b7 (patch)
tree60d7d2a502972ccc96c9cab0893de194a89078dc
parent3affc261aaa12105dbad60bfa7014126ce4dfcca (diff)
Fix crash on shutdown with states
When populating deferred properties, we must not set the rootObjectInCreation flags on the root context and (consequently) on any sub-objects objects created when initializing deferred properties. Doing so otherwise will end up us incorrectly linking QQmlContextData together, causing QQmlData::linkedContext to point to iself and crash on exit upon deletion. Task-number: QTBUG-37484 Change-Id: Ia5dc92a04e0f66499f15fbac10f14859d387b021 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp1
-rw-r--r--tests/auto/qml/qqmllanguage/data/SubType.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/rootObjectInCreationNotForSubObjects.qml7
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp2
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h17
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp27
6 files changed, 57 insertions, 0 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 50fe5861a6..d0852bbef2 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -241,6 +241,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
{
QQmlData *declarativeData = QQmlData::get(instance);
context = declarativeData->deferredData->context;
+ sharedState->rootContext = context;
const int objectIndex = declarativeData->deferredData->deferredIdx;
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
diff --git a/tests/auto/qml/qqmllanguage/data/SubType.qml b/tests/auto/qml/qqmllanguage/data/SubType.qml
new file mode 100644
index 0000000000..0698ae2349
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SubType.qml
@@ -0,0 +1,3 @@
+import QtQml 2.0
+QtObject {
+}
diff --git a/tests/auto/qml/qqmllanguage/data/rootObjectInCreationNotForSubObjects.qml b/tests/auto/qml/qqmllanguage/data/rootObjectInCreationNotForSubObjects.qml
new file mode 100644
index 0000000000..afba278ade
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/rootObjectInCreationNotForSubObjects.qml
@@ -0,0 +1,7 @@
+import QtQml 2.0
+import Test 1.0
+RootObjectInCreationTester {
+ subObject: SubType {
+ property int testValue: 42;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index fad5c1e65d..c37845840b 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -92,6 +92,8 @@ void registerTypes()
qmlRegisterType<MyCreateableDerivedClass,1>("Test", 1, 1, "MyCreateableDerivedClass");
qmlRegisterCustomType<CustomBinding>("Test", 1, 0, "CustomBinding", new CustomBindingParser);
+
+ qmlRegisterType<RootObjectInCreationTester>("Test", 1, 0, "RootObjectInCreationTester");
}
QVariant myCustomVariantTypeConverter(const QString &data)
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index a1e2b76bd1..6ed363e363 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -1104,6 +1104,23 @@ class CustomBindingParser : public QQmlCustomParser
virtual void setCustomData(QObject *object, const QByteArray &data);
};
+class RootObjectInCreationTester : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject *subObject READ subObject WRITE setSubObject FINAL)
+ Q_CLASSINFO("DeferredPropertyNames", "subObject");
+public:
+ RootObjectInCreationTester()
+ : obj(0)
+ {}
+
+ QObject *subObject() const { return obj; }
+ void setSubObject(QObject *o) { obj = o; }
+
+private:
+ QObject *obj;
+};
+
void registerTypes();
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index fa0c393d66..f48e405dff 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -222,6 +222,8 @@ private slots:
void preservePropertyCacheOnGroupObjects();
void propertyCacheInSync();
+ void rootObjectInCreationNotForSubObjects();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -3624,6 +3626,31 @@ void tst_qqmllanguage::propertyCacheInSync()
QCOMPARE(anchors->property("margins").toInt(), 50);
}
+void tst_qqmllanguage::rootObjectInCreationNotForSubObjects()
+{
+ QQmlComponent component(&engine, testFile("rootObjectInCreationNotForSubObjects.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ // QQmlComponent should have set this back to false anyway
+ QQmlData *ddata = QQmlData::get(o.data());
+ QVERIFY(!ddata->rootObjectInCreation);
+
+ QObject *subObject = qvariant_cast<QObject*>(o->property("subObject"));
+ QVERIFY(!subObject);
+
+ qmlExecuteDeferred(o.data());
+
+ subObject = qvariant_cast<QObject*>(o->property("subObject"));
+ QVERIFY(subObject);
+
+ ddata = QQmlData::get(subObject);
+ // This should never have been set in the first place as there is no
+ // QQmlComponent to set it back to false.
+ QVERIFY(!ddata->rootObjectInCreation);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"