aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp19
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignFunctionThroughAliasToVarProperty.qml9
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp14
3 files changed, 41 insertions, 1 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 200ebfaffd..08d0c6f40e 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -463,7 +463,24 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
QV4::ScopedFunctionObject f(scope, value);
if (f) {
if (!f->isBinding()) {
- if (!property->isVarProperty() && property->propType().id() != qMetaTypeId<QJSValue>()) {
+ const bool isAliasToAllowed = [&]() {
+ if (property->isAlias()) {
+ const QQmlPropertyIndex originalIndex(property->coreIndex(), -1);
+ QObject *targetObject = nullptr;
+ QQmlPropertyIndex targetIndex;
+ QQmlPropertyPrivate::findAliasTarget(object, originalIndex, &targetObject, &targetIndex);
+ Q_ASSERT(targetObject);
+ QQmlPropertyCache *targetCache = QQmlData::get(targetObject)->propertyCache;
+ Q_ASSERT(targetCache);
+ QQmlPropertyData *targetProperty = targetCache->property(targetIndex.coreIndex());
+ object = targetObject;
+ property = targetProperty;
+ return targetProperty->isVarProperty() || targetProperty->propType() == QMetaType::fromType<QJSValue>();
+ } else {
+ return false;
+ }
+ }();
+ if (!isAliasToAllowed && !property->isVarProperty() && property->propType().id() != qMetaTypeId<QJSValue>()) {
// assigning a JS function to a non var or QJSValue property or is not allowed.
QString error = QLatin1String("Cannot assign JavaScript function to ");
if (!QMetaType(property->propType()).name())
diff --git a/tests/auto/qml/qqmlecmascript/data/assignFunctionThroughAliasToVarProperty.qml b/tests/auto/qml/qqmlecmascript/data/assignFunctionThroughAliasToVarProperty.qml
new file mode 100644
index 0000000000..96b55af9d4
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/assignFunctionThroughAliasToVarProperty.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.15
+
+Item {
+ id: root
+ property alias bar: root.foo
+ property var foo: function() { return false }
+
+ Component.onCompleted: root.bar = function() { return true }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 73c2267dca..13b6ad7700 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -79,6 +79,7 @@ private slots:
void assignBasicTypes();
void assignDate_data();
void assignDate();
+ void assignFunctionThroughAliasToVarProperty();
void exportDate_data();
void exportDate();
void checkDate_data();
@@ -562,6 +563,19 @@ void tst_qqmlecmascript::assignDate()
QCOMPARE(object->boolProperty(), true);
}
+void tst_qqmlecmascript::assignFunctionThroughAliasToVarProperty()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("assignFunctionThroughAliasToVarProperty.qml"));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY2(root, qPrintable(component.errorString()));
+
+ QJSValue fooFunc = root->property("foo").value<QJSValue>();
+ QVERIFY(fooFunc.isCallable());
+ QJSValue callResult = fooFunc.call();
+ QVERIFY(callResult.toBool());
+}
+
void tst_qqmlecmascript::exportDate_data()
{
QTest::addColumn<QUrl>("source");