diff options
author | Olivier De Cannière <[email protected]> | 2025-06-24 15:14:53 +0200 |
---|---|---|
committer | Olivier De Cannière <[email protected]> | 2025-07-02 14:44:04 +0200 |
commit | 5935a839482f010e13049f89ca30fa2793ee58a3 (patch) | |
tree | b46a602600e6810e5c53886fb28728d9e84ea018 | |
parent | 6ead474c839c84788e18a6518726c60fd8b6399d (diff) |
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]>
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; |