summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qmlengine_p.h3
-rw-r--r--src/declarative/qml/qmlglobalscriptclass.cpp16
-rw-r--r--src/declarative/qml/qmlglobalscriptclass_p.h4
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp251
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h17
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp9
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h20
-rw-r--r--tests/auto/declarative/qmlecmascript/data/methods.1.qml2
-rw-r--r--tests/auto/declarative/qmlecmascript/qmlecmascript.pro2
-rw-r--r--tests/auto/declarative/qmlecmascript/testtypes.h46
-rw-r--r--tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp406
-rw-r--r--tests/auto/declarative/qmllanguage/data/assignSignal.qml2
-rw-r--r--tests/auto/declarative/qmllanguage/testtypes.h2
-rw-r--r--tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp2
14 files changed, 761 insertions, 21 deletions
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 2f177a2..490a4ce 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -101,6 +101,7 @@ class QmlListScriptClass;
class QmlCleanup;
class QmlBindingData;
class QmlWorkerScriptEngine;
+class QmlGlobalScriptClass;
class QmlScriptEngine : public QScriptEngine
{
@@ -160,7 +161,7 @@ public:
QmlTypeNameScriptClass *typeNameClass;
QmlListScriptClass *listClass;
// Global script class
- QScriptClass *globalClass;
+ QmlGlobalScriptClass *globalClass;
// Registered cleanup handlers
QmlCleanup *cleanup;
diff --git a/src/declarative/qml/qmlglobalscriptclass.cpp b/src/declarative/qml/qmlglobalscriptclass.cpp
index 5387e03..13c1017 100644
--- a/src/declarative/qml/qmlglobalscriptclass.cpp
+++ b/src/declarative/qml/qmlglobalscriptclass.cpp
@@ -101,5 +101,21 @@ void QmlGlobalScriptClass::setProperty(QScriptValue &object,
engine()->currentContext()->throwError(error);
}
+void QmlGlobalScriptClass::explicitSetProperty(const QString &name, const QScriptValue &value)
+{
+ QScriptValue v = engine()->newObject();
+ globalObject = engine()->globalObject();
+
+ QScriptValueIterator iter(globalObject);
+ while (iter.hasNext()) {
+ iter.next();
+ v.setProperty(iter.scriptName(), iter.value());
+ }
+
+ v.setProperty(name, value);
+ v.setScriptClass(this);
+ engine()->setGlobalObject(v);
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlglobalscriptclass_p.h b/src/declarative/qml/qmlglobalscriptclass_p.h
index 1658c27..56c91fe 100644
--- a/src/declarative/qml/qmlglobalscriptclass_p.h
+++ b/src/declarative/qml/qmlglobalscriptclass_p.h
@@ -57,7 +57,7 @@
QT_BEGIN_NAMESPACE
-class QmlGlobalScriptClass : public QScriptClass
+class Q_AUTOTEST_EXPORT QmlGlobalScriptClass : public QScriptClass
{
public:
QmlGlobalScriptClass(QScriptEngine *);
@@ -72,6 +72,8 @@ public:
virtual void setProperty(QScriptValue &object, const QScriptString &name,
uint id, const QScriptValue &value);
+ void explicitSetProperty(const QString &, const QScriptValue &);
+
private:
QScriptValue globalObject;
};
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
index 5de42b9..485d240 100644
--- a/src/declarative/qml/qmlobjectscriptclass.cpp
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -51,6 +51,9 @@
#include "qmlvmemetaobject_p.h"
#include <QtCore/qtimer.h>
+#include <QtCore/qvarlengtharray.h>
+
+Q_DECLARE_METATYPE(QScriptValue);
QT_BEGIN_NAMESPACE
@@ -66,8 +69,8 @@ struct ObjectData : public QScriptDeclarativeClass::Object {
QtScript for QML.
*/
QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
-: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), lastData(0),
- engine(bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), methods(bindEngine),
+ lastData(0), engine(bindEngine)
{
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
@@ -223,9 +226,10 @@ QmlObjectScriptClass::property(QObject *obj, const Identifier &name)
if (lastData->flags & QmlPropertyCache::Data::IsVMEFunction) {
return Value(scriptEngine, ((QmlVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
} else {
- // ### Optimize
- QScriptValue sobj = scriptEngine->newQObject(obj);
- return Value(scriptEngine, sobj.property(toString(name)));
+ // Uncomment to use QtScript method call logic
+ // QScriptValue sobj = scriptEngine->newQObject(obj);
+ // return Value(scriptEngine, sobj.property(toString(name)));
+ return Value(scriptEngine, methods.newMethod(obj, lastData));
}
} else {
if (enginePriv->captureProperties && !(lastData->flags & QmlPropertyCache::Data::IsConstant)) {
@@ -424,5 +428,242 @@ QStringList QmlObjectScriptClass::propertyNames(Object *object)
return cache->propertyNames();
}
+struct MethodData : public QScriptDeclarativeClass::Object {
+ MethodData(QObject *o, const QmlPropertyCache::Data &d) : object(o), data(d) {}
+
+ QmlGuard<QObject> object;
+ QmlPropertyCache::Data data;
+};
+
+QmlObjectMethodScriptClass::QmlObjectMethodScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)),
+ engine(bindEngine)
+{
+ setSupportsCall(true);
+}
+
+QmlObjectMethodScriptClass::~QmlObjectMethodScriptClass()
+{
+}
+
+QScriptValue QmlObjectMethodScriptClass::newMethod(QObject *object, const QmlPropertyCache::Data *method)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, new MethodData(object, *method));
+}
+
+namespace {
+struct MetaCallArgument {
+ inline MetaCallArgument();
+ inline ~MetaCallArgument();
+ inline void *dataPtr();
+
+ inline void initAsType(int type, QmlEngine *);
+ void fromScriptValue(int type, QmlEngine *, const QScriptValue &);
+ inline QScriptDeclarativeClass::Value toValue(QmlEngine *);
+
+private:
+ MetaCallArgument(const MetaCallArgument &);
+
+ inline void cleanup();
+
+ char *data[16];
+ int type;
+};
+}
+
+MetaCallArgument::MetaCallArgument()
+: type(QVariant::Invalid)
+{
+}
+
+MetaCallArgument::~MetaCallArgument()
+{
+ cleanup();
+}
+
+void MetaCallArgument::cleanup()
+{
+ if (type == QMetaType::QString) {
+ ((QString *)data)->~QString();
+ } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
+ ((QVariant *)data)->~QVariant();
+ } else if (type == qMetaTypeId<QScriptValue>()) {
+ ((QScriptValue *)data)->~QScriptValue();
+ }
+}
+
+void *MetaCallArgument::dataPtr()
+{
+ if (type == -1)
+ return ((QVariant *)data)->data();
+ else
+ return (void *)data;
+}
+
+void MetaCallArgument::initAsType(int callType, QmlEngine *e)
+{
+ if (type != 0) { cleanup(); type = 0; }
+ if (callType == 0) return;
+
+ QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(e);
+
+ if (callType == qMetaTypeId<QScriptValue>()) {
+ new (data) QScriptValue(engine->undefinedValue());
+ 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) {
+ *((QObject **)data) = 0;
+ type = callType;
+ } else if (callType == QMetaType::QString) {
+ new (data) QString();
+ type = callType;
+ } else if (callType == qMetaTypeId<QVariant>()) {
+ type = qMetaTypeId<QVariant>();
+ new (data) QVariant();
+ } else {
+ type = -1;
+ new (data) QVariant(callType, (void *)0);
+ }
+}
+
+void MetaCallArgument::fromScriptValue(int callType, QmlEngine *engine, const QScriptValue &value)
+{
+ if (type != 0) { cleanup(); type = 0; }
+
+ if (callType == qMetaTypeId<QScriptValue>()) {
+ new (data) QScriptValue(value);
+ type = qMetaTypeId<QScriptValue>();
+ } else if (callType == QMetaType::Int) {
+ *((int *)data) = int(value.toInt32());
+ type = callType;
+ } else if (callType == QMetaType::UInt) {
+ *((uint *)data) = uint(value.toUInt32());
+ type = callType;
+ } else if (callType == QMetaType::Bool) {
+ *((bool *)data) = value.toBool();
+ type = callType;
+ } else if (callType == QMetaType::Double) {
+ *((double *)data) = double(value.toNumber());
+ type = callType;
+ } else if (callType == QMetaType::Float) {
+ *((float *)data) = float(value.toNumber());
+ type = callType;
+ } else if (callType == QMetaType::QString) {
+ if (value.isNull() || value.isUndefined())
+ new (data) QString();
+ else
+ new (data) QString(value.toString());
+ type = callType;
+ } else if (callType == QMetaType::QObjectStar) {
+ *((QObject **)data) = value.toQObject();
+ type = callType;
+ } else if (callType == qMetaTypeId<QVariant>()) {
+ new (data) QVariant(QmlScriptClass::toVariant(engine, value));
+ type = callType;
+ } else {
+ new (data) QVariant();
+ type = -1;
+
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+ if (v.userType() == callType) {
+ *((QVariant *)data) = v;
+ } else if (v.canConvert((QVariant::Type)callType)) {
+ *((QVariant *)data) = v;
+ ((QVariant *)data)->convert((QVariant::Type)callType);
+ } else {
+ *((QVariant *)data) = QVariant(callType, (void *)0);
+ }
+ }
+}
+
+QScriptDeclarativeClass::Value MetaCallArgument::toValue(QmlEngine *e)
+{
+ QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(e);
+
+ if (type == qMetaTypeId<QScriptValue>()) {
+ return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)data));
+ } else if (type == QMetaType::Int) {
+ return QScriptDeclarativeClass::Value(engine, *((int *)data));
+ } else if (type == QMetaType::UInt) {
+ return QScriptDeclarativeClass::Value(engine, *((uint *)data));
+ } else if (type == QMetaType::Bool) {
+ return QScriptDeclarativeClass::Value(engine, *((bool *)data));
+ } else if (type == QMetaType::Double) {
+ return QScriptDeclarativeClass::Value(engine, *((double *)data));
+ } else if (type == QMetaType::Float) {
+ return QScriptDeclarativeClass::Value(engine, *((float *)data));
+ } else if (type == QMetaType::QString) {
+ return QScriptDeclarativeClass::Value(engine, *((QString *)data));
+ } else if (type == QMetaType::QObjectStar) {
+ return QScriptDeclarativeClass::Value(engine, QmlEnginePrivate::get(e)->objectClass->newQObject(*((QObject **)data)));
+ } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
+ return QScriptDeclarativeClass::Value(engine, QmlEnginePrivate::get(e)->scriptValueFromVariant(*((QVariant *)data)));
+ } else {
+ return QScriptDeclarativeClass::Value();
+ }
+}
+
+QmlObjectMethodScriptClass::Value QmlObjectMethodScriptClass::call(Object *o, QScriptContext *ctxt)
+{
+ MethodData *method = static_cast<MethodData *>(o);
+
+ if (method->data.flags & QmlPropertyCache::Data::HasArguments) {
+
+ QMetaMethod m = method->object->metaObject()->method(method->data.coreIndex);
+ QList<QByteArray> argTypeNames = m.parameterTypes();
+ QVarLengthArray<int, 9> argTypes(argTypeNames.count());
+
+ // ### Cache
+ for (int ii = 0; ii < argTypeNames.count(); ++ii) {
+ argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
+ if (argTypes[ii] == QVariant::Invalid)
+ return Value(ctxt, ctxt->throwError(QString(QLatin1String("Unknown method parameter type: %1")).arg(QLatin1String(argTypeNames.at(ii)))));
+ }
+
+ if (argTypes.count() > ctxt->argumentCount())
+ return Value(ctxt, ctxt->throwError("Insufficient arguments"));
+
+ QVarLengthArray<MetaCallArgument, 9> args(argTypes.count() + 1);
+ args[0].initAsType(method->data.propType, engine);
+
+ for (int ii = 0; ii < argTypes.count(); ++ii)
+ args[ii + 1].fromScriptValue(argTypes[ii], engine, ctxt->argument(ii));
+
+ QVarLengthArray<void *, 9> argData(args.count());
+ for (int ii = 0; ii < args.count(); ++ii)
+ argData[ii] = args[ii].dataPtr();
+
+ QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, argData.data());
+
+ return args[0].toValue(engine);
+
+ } else if (method->data.propType != 0) {
+
+ MetaCallArgument arg;
+ arg.initAsType(method->data.propType, engine);
+
+ void *args[] = { arg.dataPtr() };
+
+ QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, args);
+
+ return arg.toValue(engine);
+
+ } else {
+
+ void *args[] = { 0 };
+ QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, args);
+ return Value();
+
+ }
+ return Value();
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h
index 457eb2b..025e491 100644
--- a/src/declarative/qml/qmlobjectscriptclass_p.h
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -66,6 +66,21 @@ class QmlEngine;
class QScriptContext;
class QScriptEngine;
class QmlContext;
+
+class Q_AUTOTEST_EXPORT QmlObjectMethodScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlObjectMethodScriptClass(QmlEngine *);
+ ~QmlObjectMethodScriptClass();
+
+ QScriptValue newMethod(QObject *, const QmlPropertyCache::Data *);
+protected:
+ virtual Value call(Object *, QScriptContext *);
+
+private:
+ QmlEngine *engine;
+};
+
class Q_AUTOTEST_EXPORT QmlObjectScriptClass : public QScriptDeclarativeClass
{
public:
@@ -101,6 +116,8 @@ protected:
virtual QObject *toQObject(Object *, bool *ok = 0);
private:
+ QmlObjectMethodScriptClass methods;
+
QmlTypeNameCache::Data *lastTNData;
QmlPropertyCache::Data *lastData;
QmlPropertyCache::Data local;
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
index 3bbf1fe..77a3a47 100644
--- a/src/declarative/qml/qmlpropertycache.cpp
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -84,6 +84,15 @@ void QmlPropertyCache::Data::load(const QMetaMethod &m)
{
coreIndex = m.methodIndex();
flags |= Data::IsFunction;
+ propType = QVariant::Invalid;
+
+ const char *returnType = m.typeName();
+ if (returnType)
+ propType = QMetaType::type(returnType);
+
+ QList<QByteArray> params = m.parameterTypes();
+ if (!params.isEmpty())
+ flags |= Data::HasArguments;
}
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
index a94b2a1..8c3b75e 100644
--- a/src/declarative/qml/qmlpropertycache_p.h
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -81,15 +81,19 @@ public:
IsConstant = 0x00000001,
IsWritable = 0x00000002,
- // These are mutually exclusive
+ // These are mutualy exclusive
IsFunction = 0x00000004,
- IsVMEFunction = 0x00000008,
- IsQObjectDerived = 0x00000010,
- IsEnumType = 0x00000020,
- IsQmlList = 0x00000040,
- IsQList = 0x00000080,
- IsQmlBinding = 0x00000100,
- IsQScriptValue = 0x00000200
+ IsQObjectDerived = 0x00000008,
+ IsEnumType = 0x00000010,
+ IsQmlList = 0x00000020,
+ IsQList = 0x00000040,
+ IsQmlBinding = 0x00000080,
+ IsQScriptValue = 0x00000100,
+
+ // Apply only to IsFunctions
+ IsVMEFunction = 0x00000200,
+ HasArguments = 0x00000400
+
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/tests/auto/declarative/qmlecmascript/data/methods.1.qml b/tests/auto/declarative/qmlecmascript/data/methods.1.qml
index 8ba300f..42ed9a5 100644
--- a/tests/auto/declarative/qmlecmascript/data/methods.1.qml
+++ b/tests/auto/declarative/qmlecmascript/data/methods.1.qml
@@ -2,5 +2,5 @@ import Qt.test 1.0
MyQmlObject {
id: MyObject
- onBasicSignal: MyObject.method()
+ onBasicSignal: MyObject.methodNoArgs()
}
diff --git a/tests/auto/declarative/qmlecmascript/qmlecmascript.pro b/tests/auto/declarative/qmlecmascript/qmlecmascript.pro
index 46ae045..9f592e8 100644
--- a/tests/auto/declarative/qmlecmascript/qmlecmascript.pro
+++ b/tests/auto/declarative/qmlecmascript/qmlecmascript.pro
@@ -1,5 +1,5 @@
load(qttest_p4)
-contains(QT_CONFIG,declarative): QT += declarative
+contains(QT_CONFIG,declarative): QT += declarative script
macx:CONFIG -= app_bundle
SOURCES += tst_qmlecmascript.cpp \
diff --git a/tests/auto/declarative/qmlecmascript/testtypes.h b/tests/auto/declarative/qmlecmascript/testtypes.h
index b275b8a..fff9246 100644
--- a/tests/auto/declarative/qmlecmascript/testtypes.h
+++ b/tests/auto/declarative/qmlecmascript/testtypes.h
@@ -48,6 +48,7 @@
#include <QtCore/qsize.h>
#include <QtDeclarative/qmllist.h>
#include <QtCore/qrect.h>
+#include <QtScript/qscriptvalue.h>
class MyQmlAttachedObject : public QObject
{
@@ -126,7 +127,7 @@ signals:
public slots:
void deleteMe() { delete this; }
- void method() { m_methodCalled = true; }
+ void methodNoArgs() { m_methodCalled = true; }
void method(int a) { if(a == 163) m_methodIntCalled = true; }
void setString(const QString &s) { m_string = s; }
@@ -331,5 +332,48 @@ public:
};
QML_DECLARE_TYPE(MyTypeObject);
+Q_DECLARE_METATYPE(QScriptValue);
+class MyInvokableObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyInvokableObject() { reset(); }
+
+ int invoked() const { return m_invoked; }
+ bool error() const { return m_invokedError; }
+ const QVariantList &actuals() const { return m_actuals; }
+ void reset() { m_invoked = -1; m_invokedError = false; m_actuals.clear(); }
+
+ Q_INVOKABLE QPointF method_get_QPointF() { return QPointF(99.3, -10.2); }
+ Q_INVOKABLE QPoint method_get_QPoint() { return QPoint(9, 12); }
+
+ Q_INVOKABLE void method_NoArgs() { invoke(0); }
+ Q_INVOKABLE int method_NoArgs_int() { invoke(1); return 6; }
+ Q_INVOKABLE qreal method_NoArgs_real() { invoke(2); return 19.7; }
+ Q_INVOKABLE QPointF method_NoArgs_QPointF() { invoke(3); return QPointF(123, 4.5); }
+ Q_INVOKABLE QObject *method_NoArgs_QObject() { invoke(4); return this; }
+ Q_INVOKABLE MyInvokableObject *method_NoArgs_unknown() { invoke(5); return this; }
+ Q_INVOKABLE QScriptValue method_NoArgs_QScriptValue() { invoke(6); return QScriptValue("Hello world"); }
+ Q_INVOKABLE QVariant method_NoArgs_QVariant() { invoke(7); return QVariant("QML rocks"); }
+
+ Q_INVOKABLE void method_int(int a) { invoke(8); m_actuals << a; }
+ Q_INVOKABLE void method_intint(int a, int b) { invoke(9); m_actuals << a << b; }
+ Q_INVOKABLE void method_real(qreal a) { invoke(10); m_actuals << a; }
+ Q_INVOKABLE void method_QString(QString a) { invoke(11); m_actuals << a; }
+ Q_INVOKABLE void method_QPointF(QPointF a) { invoke(12); m_actuals << a; }
+ Q_INVOKABLE void method_QObject(QObject *a) { invoke(13); m_actuals << qVariantFromValue(a); }
+ Q_INVOKABLE void method_QScriptValue(QScriptValue a) { invoke(14); m_actuals << qVariantFromValue(a); }
+ Q_INVOKABLE void method_intQScriptValue(int a, QScriptValue b) { invoke(15); m_actuals << a << qVariantFromValue(b); }
+
+ Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; }
+ Q_INVOKABLE void method_overload(int a, int b) { invoke(17); m_actuals << a << b; }
+
+private:
+ void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;}
+ int m_invoked;
+ bool m_invokedError;
+ QVariantList m_actuals;
+};
+
#endif // TESTTYPES_H
diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
index 3aa1aff..ba23ef8 100644
--- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
+++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
@@ -47,6 +47,9 @@
#include <QtCore/qdebug.h>
#include <QtCore/private/qguard_p.h>
#include <QtCore/qdir.h>
+#include <QtCore/qnumeric.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlglobalscriptclass_p.h>
#include "testtypes.h"
/*
@@ -115,6 +118,7 @@ private slots:
void bug1();
+ void callQtInvokables();
private:
QmlEngine engine;
};
@@ -1078,6 +1082,408 @@ void tst_qmlecmascript::bug1()
delete object;
}
+void tst_qmlecmascript::callQtInvokables()
+{
+ MyInvokableObject o;
+
+ QmlEngine qmlengine;
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(&qmlengine);
+ QScriptEngine *engine = &ep->scriptEngine;
+ ep->globalClass->explicitSetProperty("object", ep->objectClass->newQObject(&o));
+
+ // Non-existant methods
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_nonexistant()").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_nonexistant(10, 11)").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ // Insufficient arguments
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ // Excessive arguments
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 9);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
+ QCOMPARE(o.actuals().at(1), QVariant(11));
+
+ // Test return types
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 0);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.7)));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 2);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ {
+ QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
+ QVERIFY(ret.isVariant());
+ QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 3);
+ QCOMPARE(o.actuals().count(), 0);
+ }
+
+ o.reset();
+ {
+ QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
+ QVERIFY(ret.isQObject());
+ QCOMPARE(ret.toQObject(), (QObject *)&o);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 4);
+ QCOMPARE(o.actuals().count(), 0);
+ }
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 5);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ {
+ QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString("Hello world"));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 6);
+ QCOMPARE(o.actuals().count(), 0);
+ }
+
+ o.reset();
+ QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 7);
+ QCOMPARE(o.actuals().count(), 0);
+
+ // Test arg types
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(94));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(94));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 8);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 9);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(122));
+ QCOMPARE(o.actuals().at(1), QVariant(9));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(94.3));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(94.3));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 10);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant("19"));
+
+ o.reset();
+ {
+ QString expected = "MyInvokableObject(0x" + QString::number((intptr_t)&o, 16) + ")";
+ QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(expected));
+ }
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QString()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 11);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QString()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 12);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 13);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 14);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 14);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 14);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 14);
+ QCOMPARE(o.actuals().count(), 1);
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 15);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(4));
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 15);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(8));
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 15);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(3));
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 15);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(44));
+ QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
+
+ // Test overloads - QML will always invoke the *last* method
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_overload(10)").isError(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -1);
+ QCOMPARE(o.actuals().count(), 0);
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 17);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
+ QCOMPARE(o.actuals().at(1), QVariant(11));
+}
+
QTEST_MAIN(tst_qmlecmascript)
#include "tst_qmlecmascript.moc"
diff --git a/tests/auto/declarative/qmllanguage/data/assignSignal.qml b/tests/auto/declarative/qmllanguage/data/assignSignal.qml
index 3abc04d..2a48df8 100644
--- a/tests/auto/declarative/qmllanguage/data/assignSignal.qml
+++ b/tests/auto/declarative/qmllanguage/data/assignSignal.qml
@@ -1,5 +1,5 @@
import Test 1.0
MyQmlObject {
onBasicSignal: basicSlot()
- onBasicParameterizedSignal: basicSlot(parameter)
+ onBasicParameterizedSignal: basicSlotWithArgs(parameter)
}
diff --git a/tests/auto/declarative/qmllanguage/testtypes.h b/tests/auto/declarative/qmllanguage/testtypes.h
index 0f2cdf9..d6ca898 100644
--- a/tests/auto/declarative/qmllanguage/testtypes.h
+++ b/tests/auto/declarative/qmllanguage/testtypes.h
@@ -139,7 +139,7 @@ public:
void setCustomType(const MyCustomVariantType &v) { m_custom = v; }
public slots:
void basicSlot() { qWarning("MyQmlObject::basicSlot"); }
- void basicSlot(int v) { qWarning("MyQmlObject::basicSlot(%d)", v); }
+ void basicSlotWithArgs(int v) { qWarning("MyQmlObject::basicSlotWithArgs(%d)", v); }
signals:
void basicSignal();
diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
index e3a81cb..976dc76 100644
--- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
+++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
@@ -541,7 +541,7 @@ void tst_qmllanguage::assignSignal()
QVERIFY(object != 0);
QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
emit object->basicSignal();
- QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot(9)");
+ QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)");
emit object->basicParameterizedSignal(9);
}