From c31026c9ca7ff0c745dba577f9ac2c14d1ef68c5 Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Fri, 27 Apr 2012 16:12:09 +1000 Subject: 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 --- .../qml/qqmlcomponent/data/onDestructionCount.qml | 16 ++++++++ .../qml/qqmlcomponent/data/onDestructionLookup.qml | 25 +++++++++++++ tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp | 43 ++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 tests/auto/qml/qqmlcomponent/data/onDestructionCount.qml create mode 100644 tests/auto/qml/qqmlcomponent/data/onDestructionLookup.qml (limited to 'tests/auto/qml/qqmlcomponent') 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 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 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" -- cgit v1.2.3