aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier De Cannière <[email protected]>2025-06-24 15:14:53 +0200
committerOlivier De Cannière <[email protected]>2025-07-02 14:44:04 +0200
commit5935a839482f010e13049f89ca30fa2793ee58a3 (patch)
treeb46a602600e6810e5c53886fb28728d9e84ea018
parent6ead474c839c84788e18a6518726c60fd8b6399d (diff)
QtQml: Correctly track alias resolutions skipsHEADdev
When trying to resolve all aliases on an object, we iterate over them one by one. If all are resolved successfully, we return AllAliasesResolved and consider this object done, if an alias fails, we return NoAliasResolved or SomeAliasesResolved and we will try again later. This can be the case for aliases to aliases. We defer resolving the first one until the target alias is resolved first. There was a bug in the logic that counts how many of the aliases were successfully resolved and how many were skipped. When skipping an alias to an alias, we cannot count it among the completed ones. This leads to an alias not being resolved and added to the property cache. Thankfully, a runtime assert then catches the discrepancy between the number of aliases in the property cache and in the compilation unit. Early exit when detecting that the alias points to a non-local unresolved alias to try again later. Also update the aliasIndex as part of the for loop update. Amends 9e1378260a3f3a6eb4cad8d6ae47bc218e6a2b5f Pick-to: 6.10 Change-Id: I6ee7a796a0b4890393d5b17ebea2686c55955394 Reviewed-by: Ulf Hermann <[email protected]>
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/aliasToAliasResolutionSkipCorruption.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp11
4 files changed, 30 insertions, 7 deletions
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index bc4a032fc6..509deed996 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -848,9 +848,8 @@ QQmlComponentAndAliasResolver<QQmlTypeCompiler>::resolveAliasesInObject(
int aliasIndex = 0;
int numSkippedAliases = 0;
- for (QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next) {
+ for (QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next, ++aliasIndex) {
if (resolvedAliases.contains(alias)) {
- ++aliasIndex;
++numSkippedAliases;
continue;
}
@@ -915,7 +914,7 @@ QQmlComponentAndAliasResolver<QQmlTypeCompiler>::resolveAliasesInObject(
alias->localAliasIndex = localAliasIndex;
alias->setIsAliasToLocalAlias(true);
if (!appendAliasToPropertyCache(
- &component, alias, objectIndex, aliasIndex++, -1,
+ &component, alias, objectIndex, aliasIndex, -1,
aliasCacheCreator, error)) {
break;
}
@@ -925,9 +924,7 @@ QQmlComponentAndAliasResolver<QQmlTypeCompiler>::resolveAliasesInObject(
// restore
alias->setIdIndex(idIndex);
// Try again later and resolve the target alias first.
- ++numSkippedAliases;
- ++aliasIndex;
- break;
+ return aliasIndex == numSkippedAliases ? NoAliasResolved : SomeAliasesResolved;
}
}
@@ -986,7 +983,7 @@ QQmlComponentAndAliasResolver<QQmlTypeCompiler>::resolveAliasesInObject(
}
if (!appendAliasToPropertyCache(
- &component, alias, objectIndex, aliasIndex++, propIdx.toEncoded(),
+ &component, alias, objectIndex, aliasIndex, propIdx.toEncoded(),
aliasCacheCreator, error)) {
break;
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index dd5dc3ab73..c3f24cd6a0 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -91,6 +91,7 @@ set(qml_files
Variable.qml
WindowDerived.qml
aliasLookup.qml
+ aliasToAliasResolutionSkipCorruption.qml
ambiguous1/Ambiguous.qml
ambiguous2/Ambiguous.qml
ambiguousAs.qml
diff --git a/tests/auto/qml/qmlcppcodegen/data/aliasToAliasResolutionSkipCorruption.qml b/tests/auto/qml/qmlcppcodegen/data/aliasToAliasResolutionSkipCorruption.qml
new file mode 100644
index 0000000000..e010499eac
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/aliasToAliasResolutionSkipCorruption.qml
@@ -0,0 +1,14 @@
+import QtQuick
+
+Item {
+ property alias dummy: inner.i
+ property alias aai: middle.ai
+ Item {
+ id: middle
+ property alias ai: inner.i
+ Item {
+ id: inner
+ property int i: 0
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 39292d9dd8..f8b67ee7fb 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -44,6 +44,7 @@ private slots:
void accessModelMethodFromOutSide();
void aliasLookup();
+ void aliasToAliasResolutionSkipCorruption();
void ambiguousAs();
void ambiguousSignals();
void anchorsFill();
@@ -584,6 +585,16 @@ void tst_QmlCppCodegen::aliasLookup()
QCOMPARE(t.toString(), u"12"_s);
}
+void tst_QmlCppCodegen::aliasToAliasResolutionSkipCorruption()
+{
+ QQmlEngine engine;
+ QUrl url(https://code.qt.io/u%22qrc:/qt/qml/TestTypes/aliasToAliasResolutionSkipCorruption.qml%22_s);
+ QQmlComponent component(&engine, url);
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+}
+
void tst_QmlCppCodegen::ambiguousAs()
{
QQmlEngine e;