diff options
author | Sami Shalayel <[email protected]> | 2025-09-03 10:42:24 +0200 |
---|---|---|
committer | Sami Shalayel <[email protected]> | 2025-09-10 11:56:48 +0200 |
commit | aef089a81d83b883470036cc510949249d64aeb6 (patch) | |
tree | c9c8b7dcf0fc484169ee0e01618657e77108a9fe | |
parent | 7232c76aebc2875a19d7caa1abad7343458fb1fa (diff) |
QQmlCodeModel: populate files after loading them
Populate the QML file after loading it, to avoid crashes later on.
UpdateItemInSnapshot would write the DomItem of the qml file inside the
snapshot, and then populate the lazy parts of the qml file while
checking whether the file should be added to the valid snapshot too.
This leaves the snapshot in an invalid state where the main
thread responding to requests might access and use the
only-partially-populated snapshot and crash, for example in the case of
the document symbols that expect the Qml file to not be empty.
Therefore, make sure that the qml file is populated by the qml file
loading thread before writing it inside the snapshot.
Note that addFileWatches() populates the file, so the crashes only
happened when the CMake feature is disabled. Add a test to make sure
that we don't load unpopulated files when the CMake feature is disabled.
Task-number: QTBUG-119163
Change-Id: I6e73420f750e873898b7b426fe333edaf4d6a7c0
Reviewed-by: Ulf Hermann <[email protected]>
-rw-r--r-- | src/qmlls/qqmlcodemodel.cpp | 4 | ||||
-rw-r--r-- | tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp | 14 | ||||
-rw-r--r-- | tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h | 1 |
3 files changed, 19 insertions, 0 deletions
diff --git a/src/qmlls/qqmlcodemodel.cpp b/src/qmlls/qqmlcodemodel.cpp index 82182f5ec7..2c7b531254 100644 --- a/src/qmlls/qqmlcodemodel.cpp +++ b/src/qmlls/qqmlcodemodel.cpp @@ -565,6 +565,10 @@ void QQmlCodeModel::newDocForOpenFile(const QByteArray &url, int version, const [&p, this](Path, const DomItem &, const DomItem &newValue) { const DomItem file = newValue.fileObject(); p = file.canonicalPath(); + // Force population of the file by accessing isValid field. We + // don't want to populate the file after adding the file to the + // snapshot in updateItemInSnapshot. + file.field(Fields::isValid); if (cmakeStatus() == HasCMake) addFileWatches(file); }); diff --git a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp index a1c18ddcb2..3150d1f02f 100644 --- a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp +++ b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.cpp @@ -165,10 +165,24 @@ QString tst_qmlls_qqmlcodemodel::readFile(const QString &filename) const return f.readAll(); } +void tst_qmlls_qqmlcodemodel::openFiles_data() +{ + QTest::addColumn<bool>("cmakeEnabled"); + + QTest::addRow("withCMake") << true; + QTest::addRow("withoutCMake") << false; +} + void tst_qmlls_qqmlcodemodel::openFiles() { + QFETCH(bool, cmakeEnabled); + QmlLsp::QQmlCodeModel model; + // disabling CMake should not make the test fail! + if (!cmakeEnabled) + model.disableCMakeCalls(); + const QByteArray fileAUrl = testFileUrl(u"FileA.qml"_s).toEncoded(); const QString fileAPath = testFile(u"FileA.qml"_s); diff --git a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h index 6f3865d98d..80ad61ed57 100644 --- a/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h +++ b/tests/auto/qmlls/qqmlcodemodel/tst_qmlls_qqmlcodemodel.h @@ -31,6 +31,7 @@ private slots: void fileNamesToWatch(); void findFilePathsFromFileNames_data(); void findFilePathsFromFileNames(); + void openFiles_data(); void openFiles(); void importPathViaSettings(); void reloadLotsOfFiles(); |