diff options
8 files changed, 68 insertions, 20 deletions
diff --git a/examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro b/examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro index 3c94d48ac4..7658a9a813 100644 --- a/examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro +++ b/examples/quick/scenegraph/d3d11underqml/d3d11underqml.pro @@ -1,3 +1,5 @@ +!win32: error("This example requires Windows") + QT += qml quick HEADERS += d3d11squircle.h diff --git a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro index c8ea7ce478..5b11606946 100644 --- a/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro +++ b/examples/quick/scenegraph/metaltextureimport/metaltextureimport.pro @@ -1,3 +1,5 @@ +!macos: error("This example requires macOS") + QT += qml quick HEADERS += metaltextureimport.h diff --git a/examples/quick/scenegraph/metalunderqml/metalunderqml.pro b/examples/quick/scenegraph/metalunderqml/metalunderqml.pro index 9b27638a6d..9fd131fe1b 100644 --- a/examples/quick/scenegraph/metalunderqml/metalunderqml.pro +++ b/examples/quick/scenegraph/metalunderqml/metalunderqml.pro @@ -1,3 +1,5 @@ +!macos: error("This example requires macOS") + QT += qml quick HEADERS += metalsquircle.h diff --git a/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro b/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro index 9a0a87c9f0..9ea57b91c3 100644 --- a/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro +++ b/examples/quick/scenegraph/vulkanunderqml/vulkanunderqml.pro @@ -1,3 +1,5 @@ +!qtConfig(vulkan): error("This example requires Qt built with Vulkan support") + QT += qml quick HEADERS += vulkansquircle.h diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index d68815cbc1..e0a66e7170 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -634,7 +634,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles) mo->updateValues(*roles); } -void ListModel::set(int elementIndex, QV4::Object *object) +void ListModel::set(int elementIndex, QV4::Object *object, ListModel::SetElement reason) { if (!object) return; @@ -684,7 +684,7 @@ void ListModel::set(int elementIndex, QV4::Object *object) } else if (QV4::DateObject *date = propertyValue->as<QV4::DateObject>()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime); if (r.type == ListLayout::Role::DateTime) { - QDateTime dt = date->toQDateTime();; + QDateTime dt = date->toQDateTime(); e->setDateTimePropertyFast(r, dt); } } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) { @@ -699,9 +699,16 @@ void ListModel::set(int elementIndex, QV4::Object *object) e->setVariantMapFast(role, o); } } else if (propertyValue->isNullOrUndefined()) { - const ListLayout::Role *r = m_layout->getExistingRole(propertyName); - if (r) - e->clearProperty(*r); + if (reason == SetElement::WasJustInserted) { + QQmlError err; + auto memberName = propertyName->toString(m_modelCache->engine())->toQString(); + err.setDescription(QString::fromLatin1("%1 is %2. Adding an object with a %2 member does not create a role for it.").arg(memberName, propertyValue->isNull() ? QLatin1String("null") : QLatin1String("undefined"))); + qmlWarning(nullptr, err); + } else { + const ListLayout::Role *r = m_layout->getExistingRole(propertyName); + if (r) + e->clearProperty(*r); + } } } } @@ -725,13 +732,13 @@ QVector<std::function<void()>> ListModel::remove(int index, int count) void ListModel::insert(int elementIndex, QV4::Object *object) { insertElement(elementIndex); - set(elementIndex, object); + set(elementIndex, object, SetElement::WasJustInserted); } int ListModel::append(QV4::Object *object) { int elementIndex = appendElement(); - set(elementIndex, object); + set(elementIndex, object, SetElement::WasJustInserted); return elementIndex; } diff --git a/src/qmlmodels/qqmllistmodel_p_p.h b/src/qmlmodels/qqmllistmodel_p_p.h index a0d0e9ad89..2ad5158050 100644 --- a/src/qmlmodels/qqmllistmodel_p_p.h +++ b/src/qmlmodels/qqmllistmodel_p_p.h @@ -381,8 +381,10 @@ public: return elements.count(); } + enum class SetElement {WasJustInserted, IsCurrentlyUpdated}; + void set(int elementIndex, QV4::Object *object, QVector<int> *roles); - void set(int elementIndex, QV4::Object *object); + void set(int elementIndex, QV4::Object *object, SetElement reason = SetElement::IsCurrentlyUpdated); int append(QV4::Object *object); void insert(int elementIndex, QV4::Object *object); diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index b47062ee94..75a932b6f4 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -129,6 +129,7 @@ private slots: void crash_append_empty_array(); void dynamic_roles_crash_QTBUG_38907(); void nestedListModelIteration(); + void undefinedAppendShouldCauseError(); }; bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -1694,6 +1695,35 @@ void tst_qqmllistmodel::nestedListModelIteration() QScopedPointer<QObject>(component.create()); } +// QTBUG-63569 +void tst_qqmllistmodel::undefinedAppendShouldCauseError() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData( + R"(import QtQuick 2.5 + Item { + width: 640 + height: 480 + ListModel { + id : model + } + Component.onCompleted: { + var tempData = { + faulty: undefined + } + model.insert(0, tempData) + tempData.faulty = null + model.insert(0, tempData) + } + })", + QUrl()); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: faulty is undefined. Adding an object with a undefined member does not create a role for it."); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: faulty is null. Adding an object with a null member does not create a role for it."); + QScopedPointer<QObject>(component.create()); +} + + QTEST_MAIN(tst_qqmllistmodel) #include "tst_qqmllistmodel.moc" diff --git a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp index 308fba9049..157d0f2a62 100644 --- a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp +++ b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 basysKom GmbH. ** Contact: https://www.qt.io/licensing/ ** @@ -110,8 +111,8 @@ void tst_qv4identifiertable::sweepCenterEntryInBucket() table.asPropertyKey(entry2); table.asPropertyKey(entry3); - QCOMPARE(table.size, 3); - QCOMPARE(table.alloc, 5); + QCOMPARE(table.size, 3u); + QCOMPARE(table.alloc, 5u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -153,8 +154,8 @@ void tst_qv4identifiertable::sweepLastEntryInBucket() table.asPropertyKey(entry2); table.asPropertyKey(entry3); - QCOMPARE(table.size, 3); - QCOMPARE(table.alloc, 5); + QCOMPARE(table.size, 3u); + QCOMPARE(table.alloc, 5u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -193,8 +194,8 @@ void tst_qv4identifiertable::sweepFirstEntryInSameBucketWithDifferingHash() table.asPropertyKey(entry1); table.asPropertyKey(entry2); - QCOMPARE(table.size, 2); - QCOMPARE(table.alloc, 5); + QCOMPARE(table.size, 2u); + QCOMPARE(table.alloc, 5u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -231,8 +232,8 @@ void tst_qv4identifiertable::dontSweepAcrossBucketBoundaries() table.asPropertyKey(entry1); table.asPropertyKey(entry2); - QCOMPARE(table.size, 2); - QCOMPARE(table.alloc, 5); + QCOMPARE(table.size, 2u); + QCOMPARE(table.alloc, 5u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -279,8 +280,8 @@ void tst_qv4identifiertable::sweepAcrossBucketBoundariesIfFirstBucketFull() table.asPropertyKey(entry3); table.asPropertyKey(entry4); - QCOMPARE(table.size, 4); - QCOMPARE(table.alloc, 11); + QCOMPARE(table.size, 4u); + QCOMPARE(table.alloc, 11u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); @@ -336,8 +337,8 @@ void tst_qv4identifiertable::sweepBucketGap() table.asPropertyKey(entry3); table.asPropertyKey(entry4); - QCOMPARE(table.size, 4); - QCOMPARE(table.alloc, 11); + QCOMPARE(table.size, 4u); + QCOMPARE(table.alloc, 11u); QCOMPARE(table.entriesByHash[0], entry1); QCOMPARE(table.entriesByHash[1], entry2); |