diff options
author | Jaeyoon Jung <jaeyoon.jung@lge.com> | 2021-09-01 18:47:08 +0900 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-09-02 10:42:56 +0000 |
commit | 784aad8fd0387e11297cd27ed814e875dc5f914b (patch) | |
tree | b9a5b3739c0f0f6bae521650b8689a79711b17f7 /tests | |
parent | e458e4cfd526c6e3288ae08ec4b25fe240e55080 (diff) |
QQmlListModel: Fix C++ owned object getting destroyed
If an object is explicitly set as C++ owned, it should not be turned to
destructible in any case. explicitIndestructibleSet flag is used for
that and thus it should not be unset in any case.
This fixes an issue where a C++ owned object could be destroyed by GC
when it is added to a ListModel. An object is supposed to be set as
destructible implicitly when it is used as a return value from JS unless
explicitIndestructibleSet is set.
Fixes: QTBUG-96167
Change-Id: Iad06847e56e29dd1b20146be108d7f747d8474dc
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Jaeyoon Jung <jaeyoon.jung@lge.com>
(cherry picked from commit 219ca3bf2be65fb4f1741bdc7b53d6dc4a41dd31)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qml/qqmllistmodel/data/objectOwnership.qml | 27 | ||||
-rw-r--r-- | tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp | 35 |
2 files changed, 62 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmllistmodel/data/objectOwnership.qml b/tests/auto/qml/qqmllistmodel/data/objectOwnership.qml new file mode 100644 index 0000000000..0ebb29d75b --- /dev/null +++ b/tests/auto/qml/qqmllistmodel/data/objectOwnership.qml @@ -0,0 +1,27 @@ +import QtQuick + +ListView { + id: root + width: 100 + height: 100 + + delegate: Component { + Item { + property Item myItem: refItem + } + } + + model: ListModel { + id: listModel + objectName: "listModel" + + function addItem() { + append({"refItem": cppOwnedItem}); + } + } + + function checkItem() { + root.currentIndex = 0; + currentItem.myItem.dummy(); + } +} diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index 7f94180274..fae2b8da63 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -137,6 +137,7 @@ private slots: void emptyStringNotUndefined(); void listElementWithTemplateString(); void destroyComponentObject(); + void objectOwnershipFlip(); }; bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -1882,6 +1883,40 @@ void tst_qqmllistmodel::destroyComponentObject() QCOMPARE(list->count(), 1); } +// Used for objectOwnershipFlip +class TestItem : public QQuickItem +{ + Q_OBJECT +public: + // To trigger QQmlData::setImplicitDestructible through QV4::CallArgument::toValue + Q_INVOKABLE TestItem* dummy() { return this; } +}; + +void tst_qqmllistmodel::objectOwnershipFlip() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("objectOwnership.qml")); + QVERIFY(!component.isError()); + QScopedPointer<QObject> root(component.create()); + QVERIFY(!root.isNull()); + QQmlListModel *model = root->findChild<QQmlListModel*>("listModel"); + QVERIFY(model != nullptr); + + QScopedPointer<TestItem> item(new TestItem()); + item->setObjectName("cppOwnedItem"); + QJSEngine::setObjectOwnership(item.data(), QJSEngine::CppOwnership); + QCOMPARE(QJSEngine::objectOwnership(item.data()), QJSEngine::CppOwnership); + + engine.rootContext()->setContextProperty("cppOwnedItem", item.data()); + + QMetaObject::invokeMethod(model, "addItem"); + QCOMPARE(model->count(), 1); + + QMetaObject::invokeMethod(root.data(), "checkItem"); + + QCOMPARE(QJSEngine::objectOwnership(item.data()), QJSEngine::CppOwnership); +} + QTEST_MAIN(tst_qqmllistmodel) #include "tst_qqmllistmodel.moc" |