aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsapi/qjsengine.cpp6
-rw-r--r--src/qml/jsapi/qjsengine.h13
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp65
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h3
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp5
5 files changed, 63 insertions, 29 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index c15b5c1ccd..8b0b650c1f 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -920,6 +920,12 @@ bool QJSEngine::convertMetaType(QMetaType fromType, const void *from, QMetaType
return QV4::ExecutionEngine::metaTypeFromJS(handle()->fromData(fromType, from), toType, to);
}
+QString QJSEngine::convertQObjectToString(QObject *object)
+{
+ return QV4::QObjectWrapper::objectToString(
+ handle(), object ? object->metaObject() : nullptr, object);
+}
+
/*! \fn template <typename T> QJSValue QJSEngine::toScriptValue(const T &value)
Creates a QJSValue with the given \a value.
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index db78e1b9a9..9af6fd6e7c 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -101,6 +101,13 @@ public:
if constexpr (std::is_same_v<T, QJSManagedValue>)
return toManagedValue(value);
+ if constexpr (std::is_same_v<T, QString>) {
+ if (targetType.flags() & QMetaType::PointerToQObject) {
+ return convertQObjectToString(
+ *reinterpret_cast<QObject *const *>(value.constData()));
+ }
+ }
+
if (sourceType == QMetaType::fromType<QJSValue>())
return fromScriptValue<T>(*reinterpret_cast<const QJSValue *>(value.constData()));
@@ -148,6 +155,11 @@ public:
if constexpr (std::is_same_v<To, QVariant>)
return QVariant::fromValue(from);
+ if constexpr (std::is_same_v<To, QString>
+ && std::is_base_of_v<QObject, std::remove_const_t<std::remove_pointer_t<To>>>) {
+ return convertQObjectToString(from);
+ }
+
if constexpr (std::is_same_v<To, std::remove_const_t<std::remove_pointer_t<To>> const *>) {
using nonConstTo = std::remove_const_t<std::remove_pointer_t<To>> *;
if constexpr (std::is_same_v<From, nonConstTo>)
@@ -220,6 +232,7 @@ private:
bool convertVariant(const QVariant &value, QMetaType metaType, void *ptr);
bool convertMetaType(QMetaType fromType, const void *from, QMetaType toType, void *to);
+ QString convertQObjectToString(QObject *object);
template<typename T>
friend inline T qjsvalue_cast(const QJSValue &);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index e83c111251..2d33b5f36e 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1023,6 +1023,38 @@ int QObjectWrapper::virtualMetacall(Object *object, QMetaObject::Call call, int
return 0;
}
+QString QObjectWrapper::objectToString(
+ ExecutionEngine *engine, const QMetaObject *metaObject, QObject *object)
+{
+ if (!metaObject)
+ return QLatin1String("null");
+
+ if (!object)
+ return QString::fromUtf8(metaObject->className()) + QLatin1String("(0x0)");
+
+ const int id = metaObject->indexOfMethod("toString()");
+ if (id >= 0) {
+ const QMetaMethod method = metaObject->method(id);
+ const QMetaType returnType = method.returnMetaType();
+ QVariant result(returnType);
+ method.invoke(object, QGenericReturnArgument(returnType.name(), result.data()));
+ if (result.metaType() == QMetaType::fromType<QString>())
+ return result.toString();
+ QV4::Scope scope(engine);
+ QV4::ScopedValue value(scope, engine->fromVariant(result));
+ return value->toQString();
+ }
+
+ QString result;
+ result += QString::fromUtf8(metaObject->className()) +
+ QLatin1String("(0x") + QString::number(quintptr(object), 16);
+ QString objectName = object->objectName();
+ if (!objectName.isEmpty())
+ result += QLatin1String(", \"") + objectName + QLatin1Char('\"');
+ result += QLatin1Char(')');
+ return result;
+}
+
struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
{
PersistentValue function;
@@ -2385,12 +2417,9 @@ static QObject *qObject(const Value *v)
return nullptr;
}
-ReturnedValue QObjectMethod::method_toString(ExecutionEngine *engine, const QV4::Value *thisObject) const
+ReturnedValue QObjectMethod::method_toString(
+ ExecutionEngine *engine, const QV4::Value *thisObject) const
{
- const auto encode = [engine](const QString &result) {
- return engine->newString(result)->asReturnedValue();
- };
-
QObject *o = qObject(thisObject);
d()->assertIntegrity(o);
@@ -2398,31 +2427,9 @@ ReturnedValue QObjectMethod::method_toString(ExecutionEngine *engine, const QV4:
const QMetaObject *metaObject = d()->metaObject();
if (!metaObject && o)
metaObject = o->metaObject();
- if (metaObject) {
- if (QObject *qobject = o ? o : d()->object()) {
- const int id = metaObject->indexOfMethod("toString()");
- if (id >= 0) {
- const QMetaMethod method = metaObject->method(id);
- const QMetaType returnType = method.returnMetaType();
- QVariant result(returnType);
- method.invoke(qobject, QGenericReturnArgument(returnType.name(), result.data()));
- return engine->fromVariant(result);
- }
-
- QString result;
- result += QString::fromUtf8(metaObject->className()) +
- QLatin1String("(0x") + QString::number(quintptr(qobject), 16);
- QString objectName = qobject->objectName();
- if (!objectName.isEmpty())
- result += QLatin1String(", \"") + objectName + QLatin1Char('\"');
- result += QLatin1Char(')');
- return encode(result);
- } else {
- return encode(QString::fromUtf8(metaObject->className()) + QLatin1String("(0x0)"));
- }
- }
- return encode(QLatin1String("null"));
+ return engine->newString(QObjectWrapper::objectToString(
+ engine, metaObject, o ? o : d()->object()))->asReturnedValue();
}
ReturnedValue QObjectMethod::method_destroy(ExecutionEngine *engine, const QV4::Value *thisObject, const Value *args, int argc) const
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 043afe79e7..d17b12ea4a 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -194,6 +194,9 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
static int virtualMetacall(Object *object, QMetaObject::Call call, int index, void **a);
+ static QString objectToString(
+ ExecutionEngine *engine, const QMetaObject *metaObject, QObject *object);
+
protected:
static bool virtualIsEqualTo(Managed *that, Managed *o);
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
index e360644b08..adbe591045 100644
--- a/src/qmlcompiler/qqmljscodegenerator.cpp
+++ b/src/qmlcompiler/qqmljscodegenerator.cpp
@@ -2898,6 +2898,11 @@ QString QQmlJSCodeGenerator::conversion(const QQmlJSScope::ConstPtr &from,
return retrieve;
}
+ if (from->isReferenceType() && m_typeResolver->equals(to, m_typeResolver->stringType())) {
+ return u"aotContext->engine->coerceValue<"_s + castTargetName(from) + u", "
+ + castTargetName(to) + u">("_s + variable + u')';
+ }
+
// TODO: add more conversions
reject(u"conversion from "_s + from->internalName() + u" to "_s + to->internalName());