aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
diff options
context:
space:
mode:
authorChris Adams <christopher.adams@nokia.com>2012-05-15 12:15:35 +1000
committerQt by Nokia <qt-info@nokia.com>2012-05-16 05:53:49 +0200
commitea13e0cf3faa3d397deb54a3f213e6a627745f0f (patch)
tree6ef1fc443a8505885d9392859d6cd40ff4bb4709 /tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
parent14e247e4b94df17ed62750b4468c2ac25aabe30f (diff)
Ensure that we don't attempt to dispose handle twice
If a weak ref callback causes disposal of a v8object associated with a qobject, the later qqmldata::destroyed() handler could cause a double dispose, due to 753d9f4be5960be8b11ad067b29fc87c168ee663. Change-Id: I07c1c8e2e7b444a7e873da26bc4d0c19bcfe57b5 Reviewed-by: Matthew Vogt <matthew.vogt@nokia.com>
Diffstat (limited to 'tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp')
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index b910ec7b83..0ea4e2a413 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -263,6 +263,7 @@ private slots:
void bindingSuppression();
void signalEmitted();
void threadSignal();
+ void qqmldataDestroyed();
private:
static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -6648,6 +6649,7 @@ void tst_qqmlecmascript::replaceBinding()
void tst_qqmlecmascript::deleteRootObjectInCreation()
{
+ {
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("deleteRootObjectInCreation.qml"));
QObject *obj = c.create();
@@ -6657,6 +6659,15 @@ void tst_qqmlecmascript::deleteRootObjectInCreation()
QTest::qWait(1);
QVERIFY(obj->property("childDestructible").toBool());
delete obj;
+ }
+
+ {
+ QQmlComponent c(&engine, testFileUrl("deleteRootObjectInCreation.2.qml"));
+ QObject *object = c.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("testConditionsMet").toBool());
+ delete object;
+ }
}
void tst_qqmlecmascript::onDestruction()
@@ -6768,6 +6779,40 @@ void tst_qqmlecmascript::threadSignal()
delete object;
}
+// ensure that the qqmldata::destroyed() handler doesn't cause problems
+void tst_qqmlecmascript::qqmldataDestroyed()
+{
+ // gc cleans up a qobject, later the qqmldata destroyed handler will run.
+ {
+ QQmlComponent c(&engine, testFileUrl("qqmldataDestroyed.qml"));
+ QObject *object = c.create();
+ QVERIFY(object != 0);
+ // now gc causing the collection of the dynamically constructed object.
+ engine.collectGarbage();
+ engine.collectGarbage();
+ // now process events to allow deletion (calling qqmldata::destroyed())
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+ // shouldn't crash.
+ delete object;
+ }
+
+ // in this case, the object has CPP ownership, and the gc will
+ // be triggered during its beginCreate stage.
+ {
+ QQmlComponent c(&engine, testFileUrl("qqmldataDestroyed.2.qml"));
+ QObject *object = c.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("testConditionsMet").toBool());
+ // the gc() within the handler will have triggered the weak
+ // qobject reference callback. If that incorrectly disposes
+ // the handle, when the qqmldata::destroyed() handler is
+ // called due to object deletion we will see a crash.
+ delete object;
+ // shouldn't have crashed.
+ }
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"