diff options
author | Chris Adams <christopher.adams@nokia.com> | 2012-05-15 12:15:35 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-05-16 05:53:49 +0200 |
commit | ea13e0cf3faa3d397deb54a3f213e6a627745f0f (patch) | |
tree | 6ef1fc443a8505885d9392859d6cd40ff4bb4709 /tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | |
parent | 14e247e4b94df17ed62750b4468c2ac25aabe30f (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.cpp | 45 |
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" |