qmlcachegen: fix crash on unresolved type with required property
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.10 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>
This commit is contained in:
parent
f2e8a9b49f
commit
c9713681e8
|
@ -1055,16 +1055,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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -74,6 +74,9 @@ private slots:
|
|||
void aotstatsGeneration_data();
|
||||
void aotstatsGeneration();
|
||||
void aotstatsFormatRevisionMissmatch();
|
||||
|
||||
void crash_data();
|
||||
void crash();
|
||||
};
|
||||
|
||||
// A wrapper around QQmlComponent to ensure the temporary reference counts
|
||||
|
@ -122,6 +125,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)
|
||||
{
|
||||
|
@ -1049,6 +1082,27 @@ void tst_qmlcachegen::aotstatsFormatRevisionMissmatch()
|
|||
QVERIFY(!QQmlJS::AotStats::fromJsonDocument(document).has_value());
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue