aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qmlcompiler/qqmljsutils.cpp18
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias1.qml8
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias2.qml8
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/ComponentWithAlias3.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/aliases.qml29
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp32
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h1
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();
};