diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2019-07-03 15:13:46 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2019-07-09 16:52:55 +0200 |
commit | 910f98031fdd834a22af0da21c9ff6ae145f61c5 (patch) | |
tree | 03062e2ec8ccca2a1bbdc2c6e69587de1eedbe76 /src/qml/qml | |
parent | f2cb10ebc4946b10526fa22581913ccc04cea164 (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.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycachecreator_p.h | 13 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 28 |
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> ¶meterTypes) { 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> ¶meterTypes); 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. |