QV4::QObjectWrapper: Clean up CallArgument
Prefer comparison of metatypes by type rather than ID. When still comparing by ID take advantage of switching through the builtin types. Furthermore, restructure the code for more clarity and consistently apply the qml_sequence_type guards. Change-Id: I7572ba644621ac551ae1821a59229b60c1485a1d Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
parent
cdd8fc015f
commit
3b0125f5ec
|
@ -505,7 +505,8 @@ void QObjectWrapper::setProperty(
|
|||
return false;
|
||||
}
|
||||
}();
|
||||
if (!isAliasToAllowed && !property->isVarProperty() && property->propType().id() != qMetaTypeId<QJSValue>()) {
|
||||
if (!isAliasToAllowed && !property->isVarProperty()
|
||||
&& property->propType() != QMetaType::fromType<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())
|
||||
|
@ -586,44 +587,45 @@ void QObjectWrapper::setProperty(
|
|||
void *argv[] = { &o, 0, &status, &flags }; \
|
||||
QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex(), argv);
|
||||
|
||||
const int propType = property->propType().id();
|
||||
const QMetaType propType = property->propType();
|
||||
// functions are already handled, except for the QJSValue case
|
||||
Q_ASSERT(!value.as<FunctionObject>() || propType == qMetaTypeId<QJSValue>());
|
||||
Q_ASSERT(!value.as<FunctionObject>() || propType == QMetaType::fromType<QJSValue>());
|
||||
|
||||
if (value.isNull() && property->isQObject()) {
|
||||
PROPERTY_STORE(QObject*, nullptr);
|
||||
} else if (value.isUndefined() && property->isResettable()) {
|
||||
void *a[] = { nullptr };
|
||||
QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex(), a);
|
||||
} else if (value.isUndefined() && propType == qMetaTypeId<QVariant>()) {
|
||||
} else if (value.isUndefined() && propType == QMetaType::fromType<QVariant>()) {
|
||||
PROPERTY_STORE(QVariant, QVariant());
|
||||
} else if (value.isUndefined() && propType == QMetaType::QJsonValue) {
|
||||
} else if (value.isUndefined() && propType == QMetaType::fromType<QJsonValue>()) {
|
||||
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
|
||||
} else if (propType == qMetaTypeId<QJSValue>()) {
|
||||
} else if (propType == QMetaType::fromType<QJSValue>()) {
|
||||
PROPERTY_STORE(QJSValue, QJSValuePrivate::fromReturnedValue(value.asReturnedValue()));
|
||||
} else if (value.isUndefined() && propType != qMetaTypeId<QQmlScriptString>()) {
|
||||
} else if (value.isUndefined() && propType != QMetaType::fromType<QQmlScriptString>()) {
|
||||
QString error = QLatin1String("Cannot assign [undefined] to ");
|
||||
if (!property->propType().name())
|
||||
if (!propType.name())
|
||||
error += QLatin1String("[unknown property type]");
|
||||
else
|
||||
error += QLatin1String(property->propType().name());
|
||||
error += QLatin1String(propType.name());
|
||||
scope.engine->throwError(error);
|
||||
return;
|
||||
} else if (property->propType().id() == QMetaType::Int && value.isNumber()) {
|
||||
} else if (propType == QMetaType::fromType<int>() && value.isNumber()) {
|
||||
PROPERTY_STORE(int, value.asDouble());
|
||||
} else if (propType == QMetaType::QReal && value.isNumber()) {
|
||||
} else if (propType == QMetaType::fromType<qreal>() && value.isNumber()) {
|
||||
PROPERTY_STORE(qreal, qreal(value.asDouble()));
|
||||
} else if (propType == QMetaType::Float && value.isNumber()) {
|
||||
} else if (propType == QMetaType::fromType<float>() && value.isNumber()) {
|
||||
PROPERTY_STORE(float, float(value.asDouble()));
|
||||
} else if (propType == QMetaType::Double && value.isNumber()) {
|
||||
} else if (propType == QMetaType::fromType<double>() && value.isNumber()) {
|
||||
PROPERTY_STORE(double, double(value.asDouble()));
|
||||
} else if (propType == QMetaType::QString && value.isString()) {
|
||||
} else if (propType == QMetaType::fromType<QString>() && value.isString()) {
|
||||
PROPERTY_STORE(QString, value.toQStringNoThrow());
|
||||
} else if (property->isVarProperty()) {
|
||||
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
|
||||
Q_ASSERT(vmemo);
|
||||
vmemo->setVMEProperty(property->coreIndex(), value);
|
||||
} else if (propType == qMetaTypeId<QQmlScriptString>() && (value.isUndefined() || value.isPrimitive())) {
|
||||
} else if (propType == QMetaType::fromType<QQmlScriptString>()
|
||||
&& (value.isUndefined() || value.isPrimitive())) {
|
||||
QQmlScriptString ss(value.toQStringNoThrow(), nullptr /* context */, object);
|
||||
if (value.isNumber()) {
|
||||
ss.d->numberValue = value.toNumber();
|
||||
|
@ -638,7 +640,7 @@ void QObjectWrapper::setProperty(
|
|||
if (property->isQList())
|
||||
v = scope.engine->toVariant(value, QMetaType::fromType<QList<QObject *> >());
|
||||
else
|
||||
v = scope.engine->toVariant(value, property->propType());
|
||||
v = scope.engine->toVariant(value, propType);
|
||||
|
||||
QQmlRefPointer<QQmlContextData> callingQmlContext = scope.engine->callingQmlContext();
|
||||
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
|
||||
|
@ -646,7 +648,7 @@ void QObjectWrapper::setProperty(
|
|||
? "an unknown type"
|
||||
: QMetaType(v.userType()).name();
|
||||
|
||||
const char *targetTypeName = QMetaType(property->propType()).name();
|
||||
const char *targetTypeName = propType.name();
|
||||
if (!targetTypeName)
|
||||
targetTypeName = "an unregistered type";
|
||||
|
||||
|
@ -1321,8 +1323,11 @@ public:
|
|||
};
|
||||
|
||||
struct CallArgument {
|
||||
inline CallArgument();
|
||||
inline ~CallArgument();
|
||||
Q_DISABLE_COPY_MOVE(CallArgument);
|
||||
|
||||
CallArgument() = default;
|
||||
~CallArgument() { cleanup(); }
|
||||
|
||||
inline void *dataPtr();
|
||||
|
||||
inline void initAsType(QMetaType type);
|
||||
|
@ -1330,12 +1335,14 @@ struct CallArgument {
|
|||
inline ReturnedValue toValue(ExecutionEngine *);
|
||||
|
||||
private:
|
||||
CallArgument(const CallArgument &);
|
||||
// QVariantWrappedType denotes that we're storing a QVariant, but we mean
|
||||
// the type inside the QVariant, not QVariant itself.
|
||||
enum { QVariantWrappedType = -1 };
|
||||
|
||||
inline void cleanup();
|
||||
|
||||
template <class T, class M>
|
||||
void fromContainerValue(const QV4::Object *object, int type, M CallArgument::*member, bool &queryEngine);
|
||||
bool fromContainerValue(const QV4::Value &object, M CallArgument::*member);
|
||||
|
||||
union {
|
||||
float floatValue;
|
||||
|
@ -1343,6 +1350,7 @@ private:
|
|||
quint32 intValue;
|
||||
bool boolValue;
|
||||
QObject *qobjectPtr;
|
||||
#if QT_CONFIG(qml_sequence_object)
|
||||
std::vector<int> *stdVectorIntPtr;
|
||||
std::vector<qreal> *stdVectorRealPtr;
|
||||
std::vector<bool> *stdVectorBoolPtr;
|
||||
|
@ -1350,6 +1358,7 @@ private:
|
|||
std::vector<QUrl> *stdVectorQUrlPtr;
|
||||
#if QT_CONFIG(qml_itemmodel)
|
||||
std::vector<QModelIndex> *stdVectorQModelIndexPtr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
char allocData[MaxSizeOf7<QVariant,
|
||||
|
@ -1374,7 +1383,7 @@ private:
|
|||
QJsonValue *jsonValuePtr;
|
||||
};
|
||||
|
||||
int type;
|
||||
int type = QMetaType::UnknownType;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1789,168 +1798,232 @@ static const QQmlPropertyData *ResolveOverloaded(
|
|||
}
|
||||
}
|
||||
|
||||
CallArgument::CallArgument()
|
||||
: type(QMetaType::UnknownType)
|
||||
{
|
||||
}
|
||||
|
||||
CallArgument::~CallArgument()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void CallArgument::cleanup()
|
||||
{
|
||||
if (type == QMetaType::QString) {
|
||||
switch (type) {
|
||||
case QMetaType::QString:
|
||||
qstringPtr->~QString();
|
||||
} else if (type == QMetaType::QByteArray) {
|
||||
break;
|
||||
case QMetaType::QByteArray:
|
||||
qbyteArrayPtr->~QByteArray();
|
||||
} else if (type == -1 || type == QMetaType::QVariant) {
|
||||
break;
|
||||
case QMetaType::QVariant:
|
||||
case QVariantWrappedType:
|
||||
qvariantPtr->~QVariant();
|
||||
} else if (type == qMetaTypeId<QJSValue>()) {
|
||||
qjsValuePtr->~QJSValue();
|
||||
} else if (type == qMetaTypeId<QList<QObject *> >()) {
|
||||
qlistPtr->~QList<QObject *>();
|
||||
} else if (type == QMetaType::QJsonArray) {
|
||||
break;
|
||||
case QMetaType::QJsonArray:
|
||||
jsonArrayPtr->~QJsonArray();
|
||||
} else if (type == QMetaType::QJsonObject) {
|
||||
break;
|
||||
case QMetaType::QJsonObject:
|
||||
jsonObjectPtr->~QJsonObject();
|
||||
} else if (type == QMetaType::QJsonValue) {
|
||||
break;
|
||||
case QMetaType::QJsonValue:
|
||||
jsonValuePtr->~QJsonValue();
|
||||
break;
|
||||
default:
|
||||
if (type == qMetaTypeId<QJSValue>()) {
|
||||
qjsValuePtr->~QJSValue();
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == qMetaTypeId<QList<QObject *> >()) {
|
||||
qlistPtr->~QList<QObject *>();
|
||||
break;
|
||||
}
|
||||
|
||||
// The sequence types need no cleanup because we don't own them.
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *CallArgument::dataPtr()
|
||||
{
|
||||
if (type == -1)
|
||||
switch (type) {
|
||||
case QMetaType::UnknownType:
|
||||
return nullptr;
|
||||
case QVariantWrappedType:
|
||||
return qvariantPtr->data();
|
||||
else if (type == qMetaTypeId<std::vector<int>>())
|
||||
default:
|
||||
#if QT_CONFIG(qml_sequence_object)
|
||||
if (type == qMetaTypeId<std::vector<int>>())
|
||||
return stdVectorIntPtr;
|
||||
else if (type == qMetaTypeId<std::vector<qreal>>())
|
||||
if (type == qMetaTypeId<std::vector<qreal>>())
|
||||
return stdVectorRealPtr;
|
||||
else if (type == qMetaTypeId<std::vector<bool>>())
|
||||
if (type == qMetaTypeId<std::vector<bool>>())
|
||||
return stdVectorBoolPtr;
|
||||
else if (type == qMetaTypeId<std::vector<QString>>())
|
||||
if (type == qMetaTypeId<std::vector<QString>>())
|
||||
return stdVectorQStringPtr;
|
||||
else if (type == qMetaTypeId<std::vector<QUrl>>())
|
||||
if (type == qMetaTypeId<std::vector<QUrl>>())
|
||||
return stdVectorQUrlPtr;
|
||||
#if QT_CONFIG(qml_itemmodel)
|
||||
else if (type == qMetaTypeId<std::vector<QModelIndex>>())
|
||||
if (type == qMetaTypeId<std::vector<QModelIndex>>())
|
||||
return stdVectorQModelIndexPtr;
|
||||
#endif
|
||||
else if (type != 0)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return (void *)&allocData;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CallArgument::initAsType(QMetaType metaType)
|
||||
{
|
||||
if (type != 0) { cleanup(); type = 0; }
|
||||
const int callType = metaType.id();
|
||||
if (callType == QMetaType::UnknownType || callType == QMetaType::Void) return;
|
||||
if (type != QMetaType::UnknownType)
|
||||
cleanup();
|
||||
|
||||
if (callType == qMetaTypeId<QJSValue>()) {
|
||||
qjsValuePtr = new (&allocData) QJSValue();
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::Int ||
|
||||
callType == QMetaType::UInt ||
|
||||
callType == QMetaType::Bool ||
|
||||
callType == QMetaType::Double ||
|
||||
callType == QMetaType::Float) {
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::QObjectStar) {
|
||||
type = metaType.id();
|
||||
switch (type) {
|
||||
case QMetaType::Void:
|
||||
type = QMetaType::UnknownType;
|
||||
break;
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Int:
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::Bool:
|
||||
case QMetaType::Double:
|
||||
case QMetaType::Float:
|
||||
break;
|
||||
case QMetaType::QObjectStar:
|
||||
qobjectPtr = nullptr;
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::QString) {
|
||||
break;
|
||||
case QMetaType::QString:
|
||||
qstringPtr = new (&allocData) QString();
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::QVariant) {
|
||||
type = callType;
|
||||
break;
|
||||
case QMetaType::QVariant:
|
||||
qvariantPtr = new (&allocData) QVariant();
|
||||
} else if (callType == qMetaTypeId<QList<QObject *> >()) {
|
||||
type = callType;
|
||||
qlistPtr = new (&allocData) QList<QObject *>();
|
||||
} else if (callType == QMetaType::QJsonArray) {
|
||||
type = callType;
|
||||
break;
|
||||
case QMetaType::QJsonArray:
|
||||
jsonArrayPtr = new (&allocData) QJsonArray();
|
||||
} else if (callType == QMetaType::QJsonObject) {
|
||||
type = callType;
|
||||
break;
|
||||
case QMetaType::QJsonObject:
|
||||
jsonObjectPtr = new (&allocData) QJsonObject();
|
||||
} else if (callType == QMetaType::QJsonValue) {
|
||||
type = callType;
|
||||
break;
|
||||
case QMetaType::QJsonValue:
|
||||
jsonValuePtr = new (&allocData) QJsonValue();
|
||||
} else {
|
||||
type = -1;
|
||||
break;
|
||||
default: {
|
||||
if (metaType == QMetaType::fromType<QJSValue>()) {
|
||||
qjsValuePtr = new (&allocData) QJSValue();
|
||||
break;
|
||||
}
|
||||
|
||||
if (metaType == QMetaType::fromType<QList<QObject *>>()) {
|
||||
qlistPtr = new (&allocData) QList<QObject *>();
|
||||
break;
|
||||
}
|
||||
|
||||
type = QVariantWrappedType;
|
||||
qvariantPtr = new (&allocData) QVariant(metaType, (void *)nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if QT_CONFIG(qml_sequence_object)
|
||||
template <class T, class M>
|
||||
void CallArgument::fromContainerValue(const QV4::Object *object, int callType, M CallArgument::*member, bool &queryEngine)
|
||||
bool CallArgument::fromContainerValue(const QV4::Value &value, M CallArgument::*member)
|
||||
{
|
||||
const QV4::Object *object = value.as<QV4::Object>();
|
||||
if (object && object->isListType()) {
|
||||
T* ptr = static_cast<T*>(QV4::SequencePrototype::getRawContainerPtr(object, callType));
|
||||
if (ptr) {
|
||||
if (T* ptr = static_cast<T *>(QV4::SequencePrototype::getRawContainerPtr(object, type))) {
|
||||
(this->*member) = ptr;
|
||||
type = callType;
|
||||
queryEngine = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
(this->*member) = nullptr;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CallArgument::fromValue(QMetaType metaType, QV4::ExecutionEngine *engine, const QV4::Value &value)
|
||||
bool CallArgument::fromValue(
|
||||
QMetaType metaType, QV4::ExecutionEngine *engine, const QV4::Value &value)
|
||||
{
|
||||
if (type != 0) {
|
||||
if (type != QMetaType::UnknownType)
|
||||
cleanup();
|
||||
type = 0;
|
||||
}
|
||||
|
||||
QV4::Scope scope(engine);
|
||||
type = metaType.id();
|
||||
|
||||
const int callType = metaType.id();
|
||||
bool queryEngine = false;
|
||||
if (callType == qMetaTypeId<QJSValue>()) {
|
||||
qjsValuePtr = new (&allocData) QJSValue;
|
||||
QJSValuePrivate::setValue(qjsValuePtr, value.asReturnedValue());
|
||||
type = qMetaTypeId<QJSValue>();
|
||||
} else if (callType == QMetaType::Int) {
|
||||
switch (type) {
|
||||
case QMetaType::Int:
|
||||
intValue = quint32(value.toInt32());
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::UInt) {
|
||||
return true;
|
||||
case QMetaType::UInt:
|
||||
intValue = quint32(value.toUInt32());
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::Bool) {
|
||||
return true;
|
||||
case QMetaType::Bool:
|
||||
boolValue = value.toBoolean();
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::Double) {
|
||||
return true;
|
||||
case QMetaType::Double:
|
||||
doubleValue = double(value.toNumber());
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::Float) {
|
||||
return true;
|
||||
case QMetaType::Float:
|
||||
floatValue = float(value.toNumber());
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::QString) {
|
||||
if (value.isNull() || value.isUndefined())
|
||||
return true;
|
||||
case QMetaType::QString:
|
||||
if (value.isNullOrUndefined())
|
||||
qstringPtr = new (&allocData) QString();
|
||||
else
|
||||
qstringPtr = new (&allocData) QString(value.toQStringNoThrow());
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::QObjectStar) {
|
||||
qobjectPtr = nullptr;
|
||||
type = callType;
|
||||
if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
|
||||
return true;
|
||||
case QMetaType::QObjectStar:
|
||||
if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) {
|
||||
qobjectPtr = qobjectWrapper->object();
|
||||
else if (const QV4::QQmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QQmlTypeWrapper>())
|
||||
queryEngine = qmlTypeWrapper->isSingleton();
|
||||
else if (!value.isNull() && !value.isUndefined()) // null and undefined are nullptr
|
||||
return false;
|
||||
} else if (callType == qMetaTypeId<QVariant>()) {
|
||||
qvariantPtr = new (&allocData) QVariant(scope.engine->toVariant(value, QMetaType {}));
|
||||
type = callType;
|
||||
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const QV4::QQmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QQmlTypeWrapper>()) {
|
||||
if (qmlTypeWrapper->isSingleton()) {
|
||||
// Convert via QVariant below.
|
||||
// TODO: Can't we just do qobjectPtr = qmlTypeWrapper->object() instead?
|
||||
break;
|
||||
}
|
||||
|
||||
// If this is a plain type wrapper without an instance,
|
||||
// then indeed it's an undefined parameter.
|
||||
// (although we might interpret that as const QMetaObject *).
|
||||
// TODO: But what if it's an attached object?
|
||||
type = QMetaType::UnknownType;
|
||||
return true;
|
||||
}
|
||||
|
||||
qobjectPtr = nullptr;
|
||||
return value.isNullOrUndefined(); // null and undefined are nullptr
|
||||
case QMetaType::QVariant:
|
||||
qvariantPtr = new (&allocData) QVariant(engine->toVariant(value, QMetaType {}));
|
||||
return true;
|
||||
case QMetaType::QJsonArray: {
|
||||
QV4::Scope scope(engine);
|
||||
QV4::ScopedArrayObject a(scope, value);
|
||||
jsonArrayPtr = new (&allocData) QJsonArray(QV4::JsonObject::toJsonArray(a));
|
||||
return true;
|
||||
}
|
||||
case QMetaType::QJsonObject: {
|
||||
QV4::Scope scope(engine);
|
||||
QV4::ScopedObject o(scope, value);
|
||||
jsonObjectPtr = new (&allocData) QJsonObject(QV4::JsonObject::toJsonObject(o));
|
||||
return true;
|
||||
}
|
||||
case QMetaType::QJsonValue:
|
||||
jsonValuePtr = new (&allocData) QJsonValue(QV4::JsonObject::toJsonValue(value));
|
||||
return true;
|
||||
case QMetaType::Void:
|
||||
type = QMetaType::UnknownType;
|
||||
// TODO: This only doesn't leak because a default constructed QVariant doesn't allocate.
|
||||
*qvariantPtr = QVariant();
|
||||
return true;
|
||||
default:
|
||||
if (type == qMetaTypeId<QJSValue>()) {
|
||||
qjsValuePtr = new (&allocData) QJSValue;
|
||||
QJSValuePrivate::setValue(qjsValuePtr, value.asReturnedValue());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == qMetaTypeId<QList<QObject*> >()) {
|
||||
qlistPtr = new (&allocData) QList<QObject *>();
|
||||
type = callType;
|
||||
QV4::Scope scope(engine);
|
||||
QV4::ScopedArrayObject array(scope, value);
|
||||
if (array) {
|
||||
Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
|
||||
|
@ -1963,89 +2036,76 @@ bool CallArgument::fromValue(QMetaType metaType, QV4::ExecutionEngine *engine, c
|
|||
o = qobjectWrapper->object();
|
||||
qlistPtr->append(o);
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) {
|
||||
qlistPtr->append(qobjectWrapper->object());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
qlistPtr->append(nullptr);
|
||||
if (!value.isNull() && !value.isUndefined())
|
||||
return false;
|
||||
return value.isNullOrUndefined();
|
||||
}
|
||||
}
|
||||
} else if (callType == QMetaType::QJsonArray) {
|
||||
QV4::ScopedArrayObject a(scope, value);
|
||||
jsonArrayPtr = new (&allocData) QJsonArray(QV4::JsonObject::toJsonArray(a));
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::QJsonObject) {
|
||||
QV4::ScopedObject o(scope, value);
|
||||
jsonObjectPtr = new (&allocData) QJsonObject(QV4::JsonObject::toJsonObject(o));
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::QJsonValue) {
|
||||
jsonValuePtr = new (&allocData) QJsonValue(QV4::JsonObject::toJsonValue(value));
|
||||
type = callType;
|
||||
} else if (callType == QMetaType::Void) {
|
||||
*qvariantPtr = QVariant();
|
||||
#if QT_CONFIG(qml_sequence_object)
|
||||
} else if (callType == qMetaTypeId<std::vector<int>>()
|
||||
|| callType == qMetaTypeId<std::vector<qreal>>()
|
||||
|| callType == qMetaTypeId<std::vector<bool>>()
|
||||
|| callType == qMetaTypeId<std::vector<QString>>()
|
||||
|| callType == qMetaTypeId<std::vector<QUrl>>()
|
||||
#if QT_CONFIG(qml_itemmodel)
|
||||
|| callType == qMetaTypeId<std::vector<QModelIndex>>()
|
||||
#endif
|
||||
) {
|
||||
queryEngine = true;
|
||||
const QV4::Object* object = value.as<QV4::Object>();
|
||||
if (callType == qMetaTypeId<std::vector<int>>()) {
|
||||
stdVectorIntPtr = nullptr;
|
||||
fromContainerValue<std::vector<int>>(object, callType, &CallArgument::stdVectorIntPtr, queryEngine);
|
||||
} else if (callType == qMetaTypeId<std::vector<qreal>>()) {
|
||||
stdVectorRealPtr = nullptr;
|
||||
fromContainerValue<std::vector<qreal>>(object, callType, &CallArgument::stdVectorRealPtr, queryEngine);
|
||||
} else if (callType == qMetaTypeId<std::vector<bool>>()) {
|
||||
stdVectorBoolPtr = nullptr;
|
||||
fromContainerValue<std::vector<bool>>(object, callType, &CallArgument::stdVectorBoolPtr, queryEngine);
|
||||
} else if (callType == qMetaTypeId<std::vector<QString>>()) {
|
||||
stdVectorQStringPtr = nullptr;
|
||||
fromContainerValue<std::vector<QString>>(object, callType, &CallArgument::stdVectorQStringPtr, queryEngine);
|
||||
} else if (callType == qMetaTypeId<std::vector<QUrl>>()) {
|
||||
stdVectorQUrlPtr = nullptr;
|
||||
fromContainerValue<std::vector<QUrl>>(object, callType, &CallArgument::stdVectorQUrlPtr, queryEngine);
|
||||
#if QT_CONFIG(qml_itemmodel)
|
||||
} else if (callType == qMetaTypeId<std::vector<QModelIndex>>()) {
|
||||
stdVectorQModelIndexPtr = nullptr;
|
||||
fromContainerValue<std::vector<QModelIndex>>(object, callType, &CallArgument::stdVectorQModelIndexPtr, queryEngine);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else if (metaType.flags()
|
||||
& (QMetaType::PointerToQObject | QMetaType::PointerToGadget)) {
|
||||
|
||||
if (metaType.flags() & (QMetaType::PointerToQObject | QMetaType::PointerToGadget)) {
|
||||
// You can assign null or undefined to any pointer. The result is a nullptr.
|
||||
if (value.isNull() || value.isUndefined()) {
|
||||
if (value.isNullOrUndefined()) {
|
||||
qvariantPtr = new (&allocData) QVariant(metaType, nullptr);
|
||||
type = callType;
|
||||
} else {
|
||||
queryEngine = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
queryEngine = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (queryEngine) {
|
||||
#if QT_CONFIG(qml_sequence_object)
|
||||
if (type == qMetaTypeId<std::vector<int>>()) {
|
||||
if (fromContainerValue<std::vector<int>>(value, &CallArgument::stdVectorIntPtr))
|
||||
return true;
|
||||
} else if (type == qMetaTypeId<std::vector<qreal>>()) {
|
||||
if (fromContainerValue<std::vector<qreal>>(value, &CallArgument::stdVectorRealPtr))
|
||||
return true;
|
||||
} else if (type == qMetaTypeId<std::vector<bool>>()) {
|
||||
if (fromContainerValue<std::vector<bool>>(value, &CallArgument::stdVectorBoolPtr))
|
||||
return true;
|
||||
} else if (type == qMetaTypeId<std::vector<QString>>()) {
|
||||
if (fromContainerValue<std::vector<QString>>(value, &CallArgument::stdVectorQStringPtr))
|
||||
return true;
|
||||
} else if (type == qMetaTypeId<std::vector<QUrl>>()) {
|
||||
if (fromContainerValue<std::vector<QUrl>>(value, &CallArgument::stdVectorQUrlPtr))
|
||||
return true;
|
||||
#if QT_CONFIG(qml_itemmodel)
|
||||
} else if (type == qMetaTypeId<std::vector<QModelIndex>>()) {
|
||||
if (fromContainerValue<std::vector<QModelIndex>>(
|
||||
value, &CallArgument::stdVectorQModelIndexPtr)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert via QVariant through the QML engine.
|
||||
qvariantPtr = new (&allocData) QVariant();
|
||||
type = -1;
|
||||
type = QVariantWrappedType;
|
||||
|
||||
QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : nullptr;
|
||||
QVariant v = scope.engine->toVariant(value, metaType);
|
||||
const QQmlEnginePrivate *ep = engine->qmlEngine()
|
||||
? QQmlEnginePrivate::get(engine->qmlEngine())
|
||||
: nullptr;
|
||||
QVariant v = engine->toVariant(value, metaType);
|
||||
|
||||
if (v.metaType() == metaType) {
|
||||
*qvariantPtr = v;
|
||||
} else if (v.canConvert(metaType)) {
|
||||
*qvariantPtr = v;
|
||||
*qvariantPtr = std::move(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (v.canConvert(metaType)) {
|
||||
*qvariantPtr = std::move(v);
|
||||
qvariantPtr->convert(metaType);
|
||||
} else {
|
||||
QQmlMetaObject mo = ep ? ep->rawMetaObjectForType(metaType) : QQmlMetaObject();
|
||||
return true;
|
||||
}
|
||||
|
||||
const QQmlMetaObject mo = ep ? ep->rawMetaObjectForType(metaType) : QQmlMetaObject();
|
||||
if (!mo.isNull()) {
|
||||
QObject *obj = QQmlMetaType::toQObject(v);
|
||||
|
||||
|
@ -2061,66 +2121,71 @@ bool CallArgument::fromValue(QMetaType metaType, QV4::ExecutionEngine *engine, c
|
|||
*qvariantPtr = QVariant(metaType, (void *)nullptr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
|
||||
{
|
||||
QV4::Scope scope(engine);
|
||||
|
||||
if (type == qMetaTypeId<QJSValue>()) {
|
||||
// The QJSValue can be passed around via dataPtr()
|
||||
QJSValuePrivate::manageStringOnV4Heap(engine, qjsValuePtr);
|
||||
return QJSValuePrivate::asReturnedValue(qjsValuePtr);
|
||||
} else if (type == QMetaType::Int) {
|
||||
switch (type) {
|
||||
case QMetaType::Int:
|
||||
return QV4::Encode(int(intValue));
|
||||
} else if (type == QMetaType::UInt) {
|
||||
case QMetaType::UInt:
|
||||
return QV4::Encode((uint)intValue);
|
||||
} else if (type == QMetaType::Bool) {
|
||||
case QMetaType::Bool:
|
||||
return QV4::Encode(boolValue);
|
||||
} else if (type == QMetaType::Double) {
|
||||
case QMetaType::Double:
|
||||
return QV4::Encode(doubleValue);
|
||||
} else if (type == QMetaType::Float) {
|
||||
case QMetaType::Float:
|
||||
return QV4::Encode(floatValue);
|
||||
} else if (type == QMetaType::QString) {
|
||||
case QMetaType::QString:
|
||||
return QV4::Encode(engine->newString(*qstringPtr));
|
||||
} else if (type == QMetaType::QByteArray) {
|
||||
case QMetaType::QByteArray:
|
||||
return QV4::Encode(engine->newArrayBuffer(*qbyteArrayPtr));
|
||||
} else if (type == QMetaType::QObjectStar) {
|
||||
QObject *object = qobjectPtr;
|
||||
if (object)
|
||||
QQmlData::get(object, true)->setImplicitDestructible();
|
||||
return QV4::QObjectWrapper::wrap(scope.engine, object);
|
||||
} else if (type == qMetaTypeId<QList<QObject *> >()) {
|
||||
// XXX Can this be made more by using Array as a prototype and implementing
|
||||
// directly against QList<QObject*>?
|
||||
QList<QObject *> &list = *qlistPtr;
|
||||
QV4::ScopedArrayObject array(scope, scope.engine->newArrayObject());
|
||||
array->arrayReserve(list.count());
|
||||
QV4::ScopedValue v(scope);
|
||||
for (int ii = 0; ii < list.count(); ++ii)
|
||||
array->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(scope.engine, list.at(ii))));
|
||||
array->setArrayLengthUnchecked(list.count());
|
||||
return array.asReturnedValue();
|
||||
} else if (type == QMetaType::QJsonArray) {
|
||||
return QV4::JsonObject::fromJsonArray(scope.engine, *jsonArrayPtr);
|
||||
} else if (type == QMetaType::QJsonObject) {
|
||||
return QV4::JsonObject::fromJsonObject(scope.engine, *jsonObjectPtr);
|
||||
} else if (type == QMetaType::QJsonValue) {
|
||||
return QV4::JsonObject::fromJsonValue(scope.engine, *jsonValuePtr);
|
||||
} else if (type == -1 || type == qMetaTypeId<QVariant>()) {
|
||||
QVariant value = *qvariantPtr;
|
||||
QV4::ScopedValue rv(scope, scope.engine->fromVariant(value));
|
||||
case QMetaType::QObjectStar:
|
||||
if (qobjectPtr)
|
||||
QQmlData::get(qobjectPtr, true)->setImplicitDestructible();
|
||||
return QV4::QObjectWrapper::wrap(engine, qobjectPtr);
|
||||
case QMetaType::QJsonArray:
|
||||
return QV4::JsonObject::fromJsonArray(engine, *jsonArrayPtr);
|
||||
case QMetaType::QJsonObject:
|
||||
return QV4::JsonObject::fromJsonObject(engine, *jsonObjectPtr);
|
||||
case QMetaType::QJsonValue:
|
||||
return QV4::JsonObject::fromJsonValue(engine, *jsonValuePtr);
|
||||
case QMetaType::QVariant:
|
||||
case QVariantWrappedType: {
|
||||
QV4::Scope scope(engine);
|
||||
QV4::ScopedValue rv(scope, scope.engine->fromVariant(*qvariantPtr));
|
||||
QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, rv);
|
||||
if (!!qobjectWrapper) {
|
||||
if (QObject *object = qobjectWrapper->object())
|
||||
QQmlData::get(object, true)->setImplicitDestructible();
|
||||
}
|
||||
return rv->asReturnedValue();
|
||||
} else {
|
||||
return QV4::Encode::undefined();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == qMetaTypeId<QJSValue>()) {
|
||||
// The QJSValue can be passed around via dataPtr()
|
||||
QJSValuePrivate::manageStringOnV4Heap(engine, qjsValuePtr);
|
||||
return QJSValuePrivate::asReturnedValue(qjsValuePtr);
|
||||
}
|
||||
|
||||
if (type == qMetaTypeId<QList<QObject *> >()) {
|
||||
// XXX Can this be made more by using Array as a prototype and implementing
|
||||
// directly against QList<QObject*>?
|
||||
QList<QObject *> &list = *qlistPtr;
|
||||
QV4::Scope scope(engine);
|
||||
QV4::ScopedArrayObject array(scope, engine->newArrayObject());
|
||||
array->arrayReserve(list.count());
|
||||
QV4::ScopedValue v(scope);
|
||||
for (int ii = 0; ii < list.count(); ++ii)
|
||||
array->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(engine, list.at(ii))));
|
||||
array->setArrayLengthUnchecked(list.count());
|
||||
return array.asReturnedValue();
|
||||
}
|
||||
|
||||
return QV4::Encode::undefined();
|
||||
}
|
||||
|
||||
ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index)
|
||||
|
|
Loading…
Reference in New Issue