diff options
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"); |