178 lines
6.1 KiB
Diff
178 lines
6.1 KiB
Diff
|
From 79079a0c6df5e02c4c47003fb88656c37aaf3d0a Mon Sep 17 00:00:00 2001
|
||
|
From: Sami Shalayel <sami.shalayel@qt.io>
|
||
|
Date: Thu, 5 Jun 2025 10:51:46 +0200
|
||
|
Subject: [PATCH] qmlcachegen: fix crash on unresolved type with required
|
||
|
property
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
qmlcachegen can't resolve all types when importing QtQuick.Controls, so
|
||
|
scopes from QtQuick.Controls might be unresolved.
|
||
|
Check the scope before creating a fix suggesion when checking the
|
||
|
required properties, and add a test that tests a file with required
|
||
|
properties on an unresolved base type "Tumbler".
|
||
|
|
||
|
This also fixes the crashes from QTBUG-137196 and QTBUG-136998 it seems.
|
||
|
|
||
|
Pick-to: 6.9 6.8 6.5
|
||
|
Fixes: QTBUG-137411
|
||
|
Fixes: QTBUG-137196
|
||
|
Fixes: QTBUG-136998
|
||
|
Change-Id: Ibf461b54abf84ba13bff8c4833940c7359cf2d8e
|
||
|
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
|
||
|
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
||
|
(cherry picked from commit c9713681e8d0ee7b7a69d38c5972ee73e8ee4b78)
|
||
|
---
|
||
|
src/qmlcompiler/qqmljsimportvisitor.cpp | 21 ++++----
|
||
|
.../data/crashes/buggyFixSuggestion.qml | 25 +++++++++
|
||
|
.../auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 54 +++++++++++++++++++
|
||
|
3 files changed, 90 insertions(+), 10 deletions(-)
|
||
|
create mode 100644 tests/auto/qml/qmlcachegen/data/crashes/buggyFixSuggestion.qml
|
||
|
|
||
|
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
|
||
|
index 2a1f31e..e2371a5 100644
|
||
|
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
|
||
|
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
|
||
|
@@ -1041,16 +1041,17 @@ void QQmlJSImportVisitor::checkRequiredProperties()
|
||
|
: u"here"_s;
|
||
|
|
||
|
if (!prevRequiredScope.isNull()) {
|
||
|
- auto sourceScope = prevRequiredScope->baseType();
|
||
|
- suggestion = QQmlJSFixSuggestion{
|
||
|
- "%1:%2:%3: Property marked as required in %4."_L1
|
||
|
- .arg(sourceScope->filePath())
|
||
|
- .arg(sourceScope->sourceLocation().startLine)
|
||
|
- .arg(sourceScope->sourceLocation().startColumn)
|
||
|
- .arg(requiredScopeName),
|
||
|
- sourceScope->sourceLocation()
|
||
|
- };
|
||
|
- suggestion->setFilename(sourceScope->filePath());
|
||
|
+ if (auto sourceScope = prevRequiredScope->baseType()) {
|
||
|
+ suggestion = QQmlJSFixSuggestion{
|
||
|
+ "%1:%2:%3: Property marked as required in %4."_L1
|
||
|
+ .arg(sourceScope->filePath())
|
||
|
+ .arg(sourceScope->sourceLocation().startLine)
|
||
|
+ .arg(sourceScope->sourceLocation().startColumn)
|
||
|
+ .arg(requiredScopeName),
|
||
|
+ sourceScope->sourceLocation()
|
||
|
+ };
|
||
|
+ suggestion->setFilename(sourceScope->filePath());
|
||
|
+ }
|
||
|
} else {
|
||
|
message += " (marked as required by %1)"_L1.arg(requiredScopeName);
|
||
|
}
|
||
|
diff --git a/tests/auto/qml/qmlcachegen/data/crashes/buggyFixSuggestion.qml b/tests/auto/qml/qmlcachegen/data/crashes/buggyFixSuggestion.qml
|
||
|
new file mode 100644
|
||
|
index 0000000..f435d2e
|
||
|
--- /dev/null
|
||
|
+++ b/tests/auto/qml/qmlcachegen/data/crashes/buggyFixSuggestion.qml
|
||
|
@@ -0,0 +1,25 @@
|
||
|
+import QtQuick
|
||
|
+
|
||
|
+Item {
|
||
|
+ id: root
|
||
|
+
|
||
|
+ Item {
|
||
|
+ id: inner
|
||
|
+
|
||
|
+ Tumbler {
|
||
|
+ id: year
|
||
|
+
|
||
|
+ delegate: Rectangle {
|
||
|
+ required property var modelData
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ Tumbler {
|
||
|
+ id: month
|
||
|
+
|
||
|
+ delegate: Rectangle {
|
||
|
+ required property var modelData
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
|
||
|
index 3c602f5..bb8fc5c 100644
|
||
|
--- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
|
||
|
+++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
|
||
|
@@ -73,6 +73,9 @@ private slots:
|
||
|
void aotstatsSerialization();
|
||
|
void aotstatsGeneration_data();
|
||
|
void aotstatsGeneration();
|
||
|
+
|
||
|
+ void crash_data();
|
||
|
+ void crash();
|
||
|
};
|
||
|
|
||
|
// A wrapper around QQmlComponent to ensure the temporary reference counts
|
||
|
@@ -121,6 +124,36 @@ static bool generateCache(const QString &qmlFileName, QByteArray *capturedStderr
|
||
|
return proc.exitCode() == 0;
|
||
|
}
|
||
|
|
||
|
+static bool generateCpp(const QString &qmlFileName, QByteArray *capturedStderr = nullptr)
|
||
|
+{
|
||
|
+#if defined(QTEST_CROSS_COMPILED)
|
||
|
+ QTest::qFail("You cannot call qmlcachegen on the target.", __FILE__, __LINE__);
|
||
|
+ return false;
|
||
|
+#endif
|
||
|
+ QProcess proc;
|
||
|
+ if (capturedStderr == nullptr)
|
||
|
+ proc.setProcessChannelMode(QProcess::ForwardedChannels);
|
||
|
+ proc.setProgram(QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath)
|
||
|
+ + QLatin1String("/qmlcachegen"));
|
||
|
+ QTemporaryDir outputDir;
|
||
|
+ const QString outputFile = outputDir.filePath("output.cpp"_L1);
|
||
|
+ proc.setArguments(QStringList{ "--resource-path"_L1, "qrc:/qt/qml/Crashes/testFile.qml"_L1,
|
||
|
+ "-o"_L1, outputFile, qmlFileName });
|
||
|
+ proc.start();
|
||
|
+ if (!proc.waitForFinished())
|
||
|
+ return false;
|
||
|
+
|
||
|
+ if (capturedStderr)
|
||
|
+ *capturedStderr = proc.readAllStandardError();
|
||
|
+
|
||
|
+ if (!QFile::exists(outputFile))
|
||
|
+ return false;
|
||
|
+
|
||
|
+ if (proc.exitStatus() != QProcess::NormalExit)
|
||
|
+ return false;
|
||
|
+ return proc.exitCode() == 0;
|
||
|
+}
|
||
|
+
|
||
|
tst_qmlcachegen::tst_qmlcachegen()
|
||
|
: QQmlDataTest(QT_QMLTEST_DATADIR)
|
||
|
{
|
||
|
@@ -1023,6 +1056,27 @@ void tst_qmlcachegen::aotstatsGeneration()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+void tst_qmlcachegen::crash_data()
|
||
|
+{
|
||
|
+ QTest::addColumn<QString>("fileName");
|
||
|
+
|
||
|
+ QTest::addRow("buggyFixSuggestion") << u"buggyFixSuggestion.qml"_s;
|
||
|
+}
|
||
|
+
|
||
|
+void tst_qmlcachegen::crash()
|
||
|
+{
|
||
|
+#if defined(QTEST_CROSS_COMPILED)
|
||
|
+ QSKIP("Cannot call qmlcachegen on cross-compiled target.");
|
||
|
+#endif
|
||
|
+
|
||
|
+ QFETCH(QString, fileName);
|
||
|
+ const QString filePath = testFile("crashes/" + fileName);
|
||
|
+
|
||
|
+ QFile file(filePath);
|
||
|
+ QVERIFY(file.exists());
|
||
|
+ QVERIFY(generateCpp(filePath));
|
||
|
+}
|
||
|
+
|
||
|
const QQmlScriptString &ScriptStringProps::undef() const
|
||
|
{
|
||
|
return m_undef;
|
||
|
--
|
||
|
2.49.0
|
||
|
|