From 475c74a9926efcd968572563e678988e53804603 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 8 Jan 2018 13:33:27 -0600 Subject: Hold internal reference to incubator object while incubating Task-number: QTBUG-53111 Change-Id: Ifaef6a855914d79155f8028b0de7ccca3c9a00f5 Reviewed-by: Simon Hausmann --- .../qml/qqmlincubator/data/garbageCollection.qml | 19 ++++++++++++++ tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp | 30 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 tests/auto/qml/qqmlincubator/data/garbageCollection.qml (limited to 'tests/auto/qml/qqmlincubator') diff --git a/tests/auto/qml/qqmlincubator/data/garbageCollection.qml b/tests/auto/qml/qqmlincubator/data/garbageCollection.qml new file mode 100644 index 0000000000..6866a02a00 --- /dev/null +++ b/tests/auto/qml/qqmlincubator/data/garbageCollection.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 + +QtObject { + id: root + + property var incubator + + function getAndClearIncubator() { + var result = incubator + incubator = null + return result + } + + Component.onCompleted: { + var c = Qt.createComponent("statusChanged.qml"); // use existing simple type for convenience + var incubator = c.incubateObject(root); + incubator.onStatusChanged = function(status) { if (status === 1) root.incubator = incubator } + } +} diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp index 8f0e04e12e..8e25079703 100644 --- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp +++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp @@ -39,6 +39,7 @@ #include #include #include "../../shared/util.h" +#include #include #include @@ -68,6 +69,7 @@ private slots: void chainedAsynchronousClear(); void selfDelete(); void contextDelete(); + void garbageCollection(); private: QQmlIncubationController controller; @@ -1144,6 +1146,34 @@ void tst_qqmlincubator::contextDelete() } } +// QTBUG-53111 +void tst_qqmlincubator::garbageCollection() +{ + QQmlComponent component(&engine, testFileUrl("garbageCollection.qml")); + QScopedPointer obj(component.create()); + + engine.collectGarbage(); + + bool b = true; + controller.incubateWhile(&b); + + // verify incubation completed (the incubator was not prematurely collected) + QVariant incubatorVariant; + QMetaObject::invokeMethod(obj.data(), "getAndClearIncubator", Q_RETURN_ARG(QVariant, incubatorVariant)); + QJSValue strongRef = incubatorVariant.value(); + QVERIFY(!strongRef.isNull() && !strongRef.isUndefined()); + + // turn the last strong reference to the incubator into a weak one and collect + QV4::WeakValue weakIncubatorRef; + weakIncubatorRef.set(QQmlEnginePrivate::getV4Engine(&engine), *QJSValuePrivate::getValue(&strongRef)); + strongRef = QJSValue(); + incubatorVariant.clear(); + + // verify incubator is correctly collected now that incubation is complete and all references are gone + engine.collectGarbage(); + QVERIFY(weakIncubatorRef.isNullOrUndefined()); +} + QTEST_MAIN(tst_qqmlincubator) #include "tst_qqmlincubator.moc" -- cgit v1.2.3