aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMatthew Vogt <matthew.vogt@nokia.com>2012-04-27 16:12:09 +1000
committerQt by Nokia <qt-info@nokia.com>2012-05-04 03:41:33 +0200
commitc31026c9ca7ff0c745dba577f9ac2c14d1ef68c5 (patch)
treedd3150dd95af2fa9759852d61d9c87b86322852a /tests
parent6318560eca7e3247a63620ce24d2d7e291dd5d84 (diff)
Emit Component.onDestruction before context is invalidated
When a component no longer has any live references, emit the destruction signal immediately so that handlers are run before the associated V8 resources are invalidated. Also, when the root context of the engine is destroyed, emit the destruction signal before destroying any resources needed to process the resulting binding invocations. Change-Id: I722dd6e4b60c499b533fc45e33b61e95bca6187f Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/qqmlcomponent/data/onDestructionCount.qml16
-rw-r--r--tests/auto/qml/qqmlcomponent/data/onDestructionLookup.qml25
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp43
-rw-r--r--tests/auto/qml/qqmlecmascript/data/OnDestructionComponent.qml9
-rw-r--r--tests/auto/qml/qqmlecmascript/data/onDestruction.qml18
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp26
7 files changed, 139 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmlcomponent/data/onDestructionCount.qml b/tests/auto/qml/qqmlcomponent/data/onDestructionCount.qml
new file mode 100644
index 0000000000..3938acf6a5
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/onDestructionCount.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Item {
+ Component {
+ id: internalComponent
+
+ Item {
+ Component.onDestruction: console.warn('Component.onDestruction')
+ }
+ }
+
+ Component.onCompleted: {
+ internalComponent.createObject()
+ gc()
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/onDestructionLookup.qml b/tests/auto/qml/qqmlcomponent/data/onDestructionLookup.qml
new file mode 100644
index 0000000000..a49a86e1f3
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/onDestructionLookup.qml
@@ -0,0 +1,25 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ property bool success: false
+
+ Component {
+ id: internalComponent
+
+ Item {
+ id: internalRoot
+
+ property string foo: ''
+
+ Component.onCompleted: { internalRoot.foo = 'bar' }
+ Component.onDestruction: { root.success = (internalRoot.foo == 'bar') }
+ }
+ }
+
+ Component.onCompleted: {
+ internalComponent.createObject()
+ gc()
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index b534d0c788..bf76ed962b 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -112,6 +112,8 @@ private slots:
void async();
void asyncHierarchy();
void componentUrlCanonicalization();
+ void onDestructionLookup();
+ void onDestructionCount();
private:
QQmlEngine engine;
@@ -366,6 +368,47 @@ void tst_qqmlcomponent::componentUrlCanonicalization()
}
}
+void tst_qqmlcomponent::onDestructionLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("onDestructionLookup.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->property("success").toBool());
+}
+
+void tst_qqmlcomponent::onDestructionCount()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("onDestructionCount.qml"));
+
+ QLatin1String warning("Component.onDestruction");
+
+ {
+ // Warning should be emitted during create()
+ QTest::ignoreMessage(QtWarningMsg, warning.data());
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != 0);
+ }
+
+ // Warning should not be emitted any further
+ QCOMPARE(engine.outputWarningsToStandardError(), true);
+
+ warnings.clear();
+ QtMsgHandler old = qInstallMsgHandler(msgHandler);
+
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+
+ qInstallMsgHandler(old);
+
+ engine.setOutputWarningsToStandardError(false);
+ QCOMPARE(engine.outputWarningsToStandardError(), false);
+
+ QCOMPARE(warnings.count(), 0);
+}
+
QTEST_MAIN(tst_qqmlcomponent)
#include "tst_qqmlcomponent.moc"
diff --git a/tests/auto/qml/qqmlecmascript/data/OnDestructionComponent.qml b/tests/auto/qml/qqmlecmascript/data/OnDestructionComponent.qml
new file mode 100644
index 0000000000..dcf46725cd
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/OnDestructionComponent.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+import Qt.test 1.0 as ModApi
+
+Item {
+ id: sec
+
+ property int a: 10
+ Component.onDestruction: ModApi.setSpecificProperty(sec, "a", 20);
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/onDestruction.qml b/tests/auto/qml/qqmlecmascript/data/onDestruction.qml
new file mode 100644
index 0000000000..b2963a1d41
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/onDestruction.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ property Component comp: OnDestructionComponent {
+ property int b: 50
+ onParentChanged: b += a
+ }
+
+ property Item compInstance
+
+ Component.onCompleted: {
+ compInstance = comp.createObject(root);
+ compInstance.destroy();
+ }
+}
+
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index f39d5d913d..a289d97fd2 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -1021,6 +1021,8 @@ public:
Q_INVOKABLE void setTrackedObjectProperty(const QString &propName) const { m_trackedObject->setProperty(qPrintable(propName), QVariant(5)); }
Q_INVOKABLE QVariant trackedObjectProperty(const QString &propName) const { return m_trackedObject->property(qPrintable(propName)); }
+ Q_INVOKABLE void setSpecificProperty(QObject *obj, const QString & propName, const QVariant & v) const { obj->setProperty(qPrintable(propName), v); }
+
int qobjectTestProperty() const { return m_testProperty; }
void setQObjectTestProperty(int tp) { m_testProperty = tp; emit qobjectTestPropertyChanged(tp); }
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 4e7f1a255c..11819c5cf0 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -257,6 +257,8 @@ private slots:
void tryStatement();
void replaceBinding();
void deleteRootObjectInCreation();
+ void onDestruction();
+
private:
static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
QQmlEngine engine;
@@ -6632,6 +6634,30 @@ void tst_qqmlecmascript::deleteRootObjectInCreation()
delete obj;
}
+void tst_qqmlecmascript::onDestruction()
+{
+ {
+ // Delete object manually to invoke the associated handlers,
+ // prior to engine destruction.
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("onDestruction.qml"));
+ QObject *obj = c.create();
+ QVERIFY(obj != 0);
+ delete obj;
+ }
+
+ {
+ // In this case, the teardown of the engine causes deletion
+ // of contexts and child items. This triggers the
+ // onDestruction handler of a (previously .destroy()ed)
+ // component instance. This shouldn't crash.
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("onDestruction.qml"));
+ QObject *obj = c.create();
+ QVERIFY(obj != 0);
+ }
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"