diff options
-rw-r--r-- | src/qmlcompiler/qqmljsutils.cpp | 18 | ||||
-rw-r--r-- | tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt | 4 | ||||
-rw-r--r-- | tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias1.qml | 8 | ||||
-rw-r--r-- | tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias2.qml | 8 | ||||
-rw-r--r-- | tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias3.qml | 5 | ||||
-rw-r--r-- | tests/auto/qml/qmltc/QmltcTests/aliases.qml | 29 | ||||
-rw-r--r-- | tests/auto/qml/qmltc/tst_qmltc.cpp | 32 | ||||
-rw-r--r-- | tests/auto/qml/qmltc/tst_qmltc.h | 1 |
8 files changed, 97 insertions, 8 deletions
diff --git a/src/qmlcompiler/qqmljsutils.cpp b/src/qmlcompiler/qqmljsutils.cpp index 229e8f29ad..0ced8254b5 100644 --- a/src/qmlcompiler/qqmljsutils.cpp +++ b/src/qmlcompiler/qqmljsutils.cpp @@ -25,17 +25,23 @@ resolveAlias(ScopeForId scopeForId, const QQmlJSMetaProperty &property, QQmlJSUtils::ResolvedAlias result {}; result.owner = owner; - for (QQmlJSMetaProperty nextProperty = property; nextProperty.isAlias();) { - - // this is a special (seemingly useless) section which is necessary when - // we have an alias pointing to an alias. this way we avoid a check - // whether a property is an alias at the very end of the loop body + // TODO: one could optimize the generated alias code for aliases pointing to aliases + // e.g., if idA.myAlias -> idB.myAlias2 -> idC.myProp, then one could directly generate + // idA.myProp as pointing to idC.myProp. + // This gets complicated when idB.myAlias is in a different Component than where the + // idA.myAlias is defined: scopeForId currently only contains the ids of the current + // component and alias resolution on the ids of a different component fails then. + if (QQmlJSMetaProperty nextProperty = property; nextProperty.isAlias()) { QQmlJSScope::ConstPtr resultOwner = result.owner; result = QQmlJSUtils::ResolvedAlias {}; visitor.reset(); auto aliasExprBits = nextProperty.aliasExpression().split(u'.'); + // do not crash on invalid aliasexprbits when accessing aliasExprBits[0] + if (aliasExprBits.size() < 1) + return {}; + // resolve id first: resultOwner = scopeForId(aliasExprBits[0], resultOwner); if (!resultOwner) @@ -46,8 +52,6 @@ resolveAlias(ScopeForId scopeForId, const QQmlJSMetaProperty &property, aliasExprBits.removeFirst(); // Note: for simplicity, remove the <id> result.owner = resultOwner; result.kind = QQmlJSUtils::AliasTarget_Object; - // reset the property to avoid endless loop when aliasExprBits is empty - nextProperty = QQmlJSMetaProperty {}; for (const QString &bit : std::as_const(aliasExprBits)) { nextProperty = resultOwner->property(bit); diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt index 7712dcf992..36e4d1413b 100644 --- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt +++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt @@ -101,6 +101,7 @@ set(qml_sources appendToQQmlListProperty.qml inlineComponents.qml repeaterCrash.qml + aliases.qml # support types: DefaultPropertySingleChild.qml @@ -110,6 +111,9 @@ set(qml_sources LocalWithOnCompleted.qml LocallyImported_context.qml # SingletonThing.qml + ComponentWithAlias1.qml + ComponentWithAlias2.qml + ComponentWithAlias3.qml badFile.qml ) diff --git a/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias1.qml b/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias1.qml new file mode 100644 index 0000000000..210cf1e159 --- /dev/null +++ b/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias1.qml @@ -0,0 +1,8 @@ +import QtQuick + +Item { + property alias setMe: firstComponent.setMe + ComponentWithAlias2 { + id: firstComponent + } +} diff --git a/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias2.qml b/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias2.qml new file mode 100644 index 0000000000..818f3a464e --- /dev/null +++ b/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias2.qml @@ -0,0 +1,8 @@ +import QtQuick + +Item { + property alias setMe: firstComponent.setMe + ComponentWithAlias3 { + id: firstComponent + } +} diff --git a/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias3.qml b/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias3.qml new file mode 100644 index 0000000000..87b917ad19 --- /dev/null +++ b/tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias3.qml @@ -0,0 +1,5 @@ +import QtQuick + +Item { + property string setMe: "Set me!" +} diff --git a/tests/auto/qml/qmltc/QmltcTests/aliases.qml b/tests/auto/qml/qmltc/QmltcTests/aliases.qml new file mode 100644 index 0000000000..9f13f7b17a --- /dev/null +++ b/tests/auto/qml/qmltc/QmltcTests/aliases.qml @@ -0,0 +1,29 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick + +Item { + property alias aliasToAlias: subItem.aliasToAlias + Item { + id: subItem + property alias aliasToAlias: subsubItem.aliasToAlias + + Item { + id: subsubItem + property alias aliasToAlias: subsubsubItem.value + + Item { + id: subsubsubItem + property string value: "Hello World!" + } + } + } + + property alias aliasToOtherFile: inOtherFile.setMe + + ComponentWithAlias1 { + id: inOtherFile + } +} + diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp index 26265fcb46..2c5a164989 100644 --- a/tests/auto/qml/qmltc/tst_qmltc.cpp +++ b/tests/auto/qml/qmltc/tst_qmltc.cpp @@ -76,7 +76,7 @@ #include "appendtoqqmllistproperty.h" #include "inlinecomponents.h" #include "repeatercrash.h" - +#include "aliases.h" #include "testprivateproperty.h" // Qt: @@ -2930,4 +2930,34 @@ void tst_qmltc::inlineComponents() } } +void tst_qmltc::aliases() +{ + QQmlEngine e; + PREPEND_NAMESPACE(aliases) fromQmltc(&e); + + QQmlComponent component(&e); + component.loadUrl(QUrl("qrc:/qt/qml/QmltcTests/aliases.qml")); + QVERIFY(!component.isError()); + QScopedPointer<QObject> fromComponent(component.create()); + const QString testString = u"myTestString"_s; + + QCOMPARE(fromQmltc.aliasToAlias(), u"Hello World!"_s); + QCOMPARE(fromComponent->property("aliasToAlias"), u"Hello World!"_s); + + fromQmltc.setAliasToAlias(testString); + QVERIFY(fromComponent->setProperty("aliasToAlias", testString)); + + QCOMPARE(fromQmltc.aliasToAlias(), testString); + QCOMPARE(fromComponent->property("aliasToAlias"), testString); + + QCOMPARE(fromQmltc.aliasToOtherFile(), u"Set me!"_s); + QCOMPARE(fromComponent->property("aliasToOtherFile"), u"Set me!"_s); + + fromQmltc.setAliasToOtherFile(testString); + QVERIFY(fromComponent->setProperty("aliasToOtherFile", testString)); + + QCOMPARE(fromQmltc.aliasToOtherFile(), testString); + QCOMPARE(fromComponent->property("aliasToOtherFile"), testString); +} + QTEST_MAIN(tst_qmltc) diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h index 0eea63b0f2..eaa4bed27a 100644 --- a/tests/auto/qml/qmltc/tst_qmltc.h +++ b/tests/auto/qml/qmltc/tst_qmltc.h @@ -88,4 +88,5 @@ private slots: void generalizedGroupedProperty(); void appendToQQmlListProperty(); void inlineComponents(); + void aliases(); }; |