aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2019-07-03 15:13:46 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2019-07-09 16:52:55 +0200
commit910f98031fdd834a22af0da21c9ff6ae145f61c5 (patch)
tree03062e2ec8ccca2a1bbdc2c6e69587de1eedbe76 /src/qml/qml
parentf2cb10ebc4946b10526fa22581913ccc04cea164 (diff)
Add support for C++ accessible typed parameters and return types in qml functions
These can be declared using the new typescript-like syntax and using type names that are also used for signal parameters and property types. This merely affects their signature on the C++ side and allows the corresponding invocation. Change-Id: Icaed4ee0dc7aa71330f99d96e073a2a63d409bbe Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlirloader.cpp5
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp7
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h4
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h13
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp28
5 files changed, 43 insertions, 14 deletions
diff --git a/src/qml/qml/qqmlirloader.cpp b/src/qml/qml/qqmlirloader.cpp
index 8c01c81e7d..82cad8eba8 100644
--- a/src/qml/qml/qqmlirloader.cpp
+++ b/src/qml/qml/qqmlirloader.cpp
@@ -188,11 +188,12 @@ QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *seriali
f->index = functionIndices.count() - 1;
f->location = compiledFunction->location;
f->nameIndex = compiledFunction->nameIndex;
+ f->returnType = compiledFunction->returnType;
f->formals.allocate(pool, int(compiledFunction->nFormals));
- const quint32_le *formalNameIdx = compiledFunction->formalsTable();
+ const QV4::CompiledData::Parameter *formalNameIdx = compiledFunction->formalsTable();
for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
- f->formals[i] = *formalNameIdx;
+ *static_cast<QV4::CompiledData::Parameter*>(&f->formals[i]) = *formalNameIdx;
object->functions->append(f);
}
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 48c4216d54..69957ab282 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -348,17 +348,18 @@ void QQmlPropertyCache::appendSignal(const QString &name, QQmlPropertyData::Flag
}
void QQmlPropertyCache::appendMethod(const QString &name, QQmlPropertyData::Flags flags,
- int coreIndex, const QList<QByteArray> &names)
+ int coreIndex, int returnType, const QList<QByteArray> &names,
+ const QVector<int> &parameterTypes)
{
int argumentCount = names.count();
QQmlPropertyData data;
- data.setPropType(QMetaType::QVariant);
+ data.setPropType(returnType);
data.setCoreIndex(coreIndex);
QQmlPropertyCacheMethodArguments *args = createArgumentsObject(argumentCount, names);
for (int ii = 0; ii < argumentCount; ++ii)
- args->arguments[ii + 1] = QMetaType::QVariant;
+ args->arguments[ii + 1] = parameterTypes.at(ii);
args->argumentsValid = true;
data.setArguments(args);
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 72692ee522..bfd78eef88 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -103,8 +103,8 @@ public:
int propType, int revision, int notifyIndex);
void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex,
const int *types = nullptr, const QList<QByteArray> &names = QList<QByteArray>());
- void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
- const QList<QByteArray> &names = QList<QByteArray>());
+ void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex, int returnType,
+ const QList<QByteArray> &names, const QVector<int> &parameterTypes);
void appendEnum(const QString &, const QVector<QQmlEnumValue> &);
const QMetaObject *metaObject() const;
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index a207ea7e86..247145ac0c 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -453,14 +453,23 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator<ObjectContainer>::crea
// protect against overriding change signals or methods with properties.
QList<QByteArray> parameterNames;
+ QVector<int> parameterTypes;
auto formal = function->formalsBegin();
auto end = function->formalsEnd();
for ( ; formal != end; ++formal) {
flags.hasArguments = true;
- parameterNames << stringAt(*formal).toUtf8();
+ parameterNames << stringAt(formal->nameIndex).toUtf8();
+ int type = metaTypeForParameter(formal->type);
+ if (type == QMetaType::UnknownType)
+ type = QMetaType::QVariant;
+ parameterTypes << type;
}
- cache->appendMethod(slotName, flags, effectiveMethodIndex++, parameterNames);
+ int returnType = metaTypeForParameter(function->returnType);
+ if (returnType == QMetaType::UnknownType)
+ returnType = QMetaType::QVariant;
+
+ cache->appendMethod(slotName, flags, effectiveMethodIndex++, returnType, parameterNames, parameterTypes);
}
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 458f26b465..b9d8fed243 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -58,6 +58,7 @@
#include <private/qv4jscall_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <private/qqmlpropertycachecreator_p.h>
+#include <private/qqmlpropertycachemethodarguments_p.h>
QT_BEGIN_NAMESPACE
@@ -917,21 +918,38 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
return -1; // The dynamic method with that id is not available.
}
- const unsigned int parameterCount = function->formalParameterCount();
+ auto methodData = cache->method(_id);
+ auto arguments = methodData->hasArguments() ? methodData->arguments() : nullptr;
+
+ const unsigned int parameterCount = (arguments && arguments->names) ? arguments->names->count() : 0;
+ Q_ASSERT(parameterCount == function->formalParameterCount());
+
QV4::JSCallData jsCallData(scope, parameterCount);
*jsCallData->thisObject = v4->global();
- for (uint ii = 0; ii < parameterCount; ++ii)
- jsCallData->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]);
+ for (uint ii = 0; ii < parameterCount; ++ii) {
+ jsCallData->args[ii] = scope.engine->metaTypeToJS(arguments->arguments[ii + 1], a[ii + 1]);
+ }
+ const int returnType = methodData->propType();
QV4::ScopedValue result(scope, function->call(jsCallData));
if (scope.hasException()) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
if (error.isValid())
ep->warning(error);
- if (a[0]) *(QVariant *)a[0] = QVariant();
+ if (a[0]) {
+ QMetaType::destruct(returnType, a[0]);
+ QMetaType::construct(returnType, a[0], nullptr);
+ }
} else {
- if (a[0]) *(QVariant *)a[0] = scope.engine->toVariant(result, 0);
+ if (a[0]) {
+ // When the return type is QVariant, JS objects are to be returned as QJSValue wrapped in
+ // QVariant.
+ if (returnType == QMetaType::QVariant)
+ *(QVariant *)a[0] = scope.engine->toVariant(result, 0);
+ else
+ scope.engine->metaTypeFromJS(result, returnType, a[0]);
+ }
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.