Skip to content

Commit

Permalink
Add QJSValue::callWithInstance() function
Browse files Browse the repository at this point in the history
With the deprecated call() overload, it was confusing what the first
argument was (the this-object or an actual argument passed to the
function). Introduce a dedicated function for the
"explicit this-object" case. This makes code more readable, and
eliminates the need to pass a "dummy" this-object to call() in the
quite common case where you don't care about the this-object.

Task-number: QTBUG-23604
Change-Id: I18f8be6592a848436351516bea266fc7e9195777
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@nokia.com>
  • Loading branch information
Kent Hansen authored and Qt by Nokia committed Jan 20, 2012
1 parent 95cee5d commit 174ee89
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 30 deletions.
20 changes: 16 additions & 4 deletions src/declarative/qml/v8/qjsvalue.cpp
Expand Up @@ -710,7 +710,7 @@ QVariant QJSValue::toVariant() const
QJSEngine::hasUncaughtException() to determine if an exception
occurred.
\sa isCallable()
\sa isCallable(), callWithInstance()
*/
QJSValue QJSValue::call(const QJSValueList &args)
{
Expand All @@ -720,15 +720,15 @@ QJSValue QJSValue::call(const QJSValueList &args)
}

/*!
Calls this QJSValue as a function, using \a thisObject as
Calls this QJSValue as a function, using \a instance as
the `this' object in the function call, and passing \a args
as arguments to the function. Returns the value returned from
the function.
If this QJSValue is not a function, call() does nothing
and returns an invalid QJSValue.
Note that if \a thisObject is not an object, the global object
Note that if \a instance is not an object, the global object
(see \l{QJSEngine::globalObject()}) will be used as the
`this' object.
Expand All @@ -740,7 +740,19 @@ QJSValue QJSValue::call(const QJSValueList &args)
\snippet doc/src/snippets/code/src_script_qjsvalue.cpp 1
\sa construct()
\sa call()
*/
QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList &args)
{
Q_D(QJSValue);
QScriptIsolate api(d->engine());
return d->call(QJSValuePrivate::get(instance), args);
}

/*!
\obsolete
Use callWithInstance() instead.
*/
QJSValue QJSValue::call(const QJSValue& thisObject, const QJSValueList& args)
{
Expand Down
1 change: 1 addition & 0 deletions src/declarative/qml/v8/qjsvalue.h
Expand Up @@ -142,6 +142,7 @@ class Q_DECLARATIVE_EXPORT QJSValue

bool isCallable() const;
QJSValue call(const QJSValueList &args);
QJSValue callWithInstance(const QJSValue &instance, const QJSValueList &args = QJSValueList());
QJSValue call(const QJSValue &thisObject = QJSValue(),
const QJSValueList &args = QJSValueList());
QJSValue construct(const QJSValueList &args = QJSValueList());
Expand Down
22 changes: 11 additions & 11 deletions tests/auto/declarative/qjsengine/tst_qjsengine.cpp
Expand Up @@ -663,7 +663,7 @@ void tst_QJSEngine::newVariant()
QCOMPARE(opaque.prototype().isValid(), true);
QEXPECT_FAIL("", "FIXME: newly created QObject's prototype is an JS Object", Continue);
QCOMPARE(opaque.prototype().isVariant(), true);
QVERIFY(opaque.property("valueOf").call(opaque).isUndefined());
QVERIFY(opaque.property("valueOf").callWithInstance(opaque).isUndefined());
}
}

Expand Down Expand Up @@ -734,31 +734,31 @@ void tst_QJSEngine::newVariant_valueOfToString()
QJSEngine eng;
{
QJSValue object = eng.newVariant(QVariant(123));
QJSValue value = object.property("valueOf").call(object);
QJSValue value = object.property("valueOf").callWithInstance(object);
QVERIFY(value.isNumber());
QCOMPARE(value.toInt(), 123);
QCOMPARE(object.toString(), QString::fromLatin1("123"));
QCOMPARE(object.toVariant().toString(), object.toString());
}
{
QJSValue object = eng.newVariant(QVariant(QString::fromLatin1("hello")));
QJSValue value = object.property("valueOf").call(object);
QJSValue value = object.property("valueOf").callWithInstance(object);
QVERIFY(value.isString());
QCOMPARE(value.toString(), QString::fromLatin1("hello"));
QCOMPARE(object.toString(), QString::fromLatin1("hello"));
QCOMPARE(object.toVariant().toString(), object.toString());
}
{
QJSValue object = eng.newVariant(QVariant(false));
QJSValue value = object.property("valueOf").call(object);
QJSValue value = object.property("valueOf").callWithInstance(object);
QVERIFY(value.isBool());
QCOMPARE(value.toBool(), false);
QCOMPARE(object.toString(), QString::fromLatin1("false"));
QCOMPARE(object.toVariant().toString(), object.toString());
}
{
QJSValue object = eng.newVariant(QVariant(QPoint(10, 20)));
QJSValue value = object.property("valueOf").call(object);
QJSValue value = object.property("valueOf").callWithInstance(object);
QVERIFY(value.isObject());
QVERIFY(value.strictlyEquals(object));
QCOMPARE(object.toString(), QString::fromLatin1("QVariant(QPoint)"));
Expand Down Expand Up @@ -2215,7 +2215,7 @@ void tst_QJSEngine::nestedEvaluate()
}
// From QScriptValue::call()
{
QScriptValue result = fun.call(eng.evaluate("p = { id:'foo' }") , QScriptValueList() );
QScriptValue result = fun.callWithInstance(eng.evaluate("p = { id:'foo' }") , QScriptValueList() );
QCOMPARE(result.property("local_bar").toString(), QString("local"));
QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo"));
QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo"));
Expand Down Expand Up @@ -2986,7 +2986,7 @@ void tst_QJSEngine::castWithPrototypeChain()
}

{
QScriptValue ret = toBaz.call(scriptZoo, QScriptValueList() << baz2Value);
QScriptValue ret = toBaz.callWithInstance(scriptZoo, QScriptValueList() << baz2Value);
QVERIFY(ret.isError());
QCOMPARE(ret.toString(), QLatin1String("TypeError: incompatible type of argument(s) in call to toBaz(); candidates were\n toBaz(Bar*)"));
}
Expand All @@ -3008,7 +3008,7 @@ void tst_QJSEngine::castWithPrototypeChain()
}

{
QScriptValue ret = toBaz.call(scriptZoo, QScriptValueList() << baz2Value);
QScriptValue ret = toBaz.callWithInstance(scriptZoo, QScriptValueList() << baz2Value);
QEXPECT_FAIL("", "Cannot convert Baz* to Bar*", Continue);
QVERIFY(!ret.isError());
QEXPECT_FAIL("", "Cannot convert Baz* to Bar*", Continue);
Expand Down Expand Up @@ -5418,7 +5418,7 @@ void tst_QJSEngine::translateScript_crossScript()

static QScriptValue callQsTr(QScriptContext *ctx, QScriptEngine *eng)
{
return eng->globalObject().property("qsTr").call(ctx->thisObject(), ctx->argumentsObject());
return eng->globalObject().property("qsTr").callWithInstance(ctx->thisObject(), ctx->argumentsObject());
}

void tst_QJSEngine::translateScript_callQsTrFromNative()
Expand Down Expand Up @@ -6139,7 +6139,7 @@ void tst_QJSEngine::dateConversionJSQt()
QJSValue jsDate = eng.evaluate(QString::fromLatin1("new Date(%0)").arg(secs * 1000.0));
QDateTime qtDate = jsDate.toDateTime();
QString qtUTCDateStr = qtDate.toUTC().toString(Qt::ISODate);
QString jsUTCDateStr = jsDate.property("toISOString").call(jsDate).toString();
QString jsUTCDateStr = jsDate.property("toISOString").callWithInstance(jsDate).toString();
jsUTCDateStr.remove(jsUTCDateStr.length() - 5, 4); // get rid of milliseconds (".000")
if (qtUTCDateStr != jsUTCDateStr)
QFAIL(qPrintable(jsDate.toString()));
Expand All @@ -6153,7 +6153,7 @@ void tst_QJSEngine::dateConversionQtJS()
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
QJSValue jsDate = eng.newDate(qtDate);
QString jsUTCDateStr = jsDate.property("toISOString").call(jsDate).toString();
QString jsUTCDateStr = jsDate.property("toISOString").callWithInstance(jsDate).toString();
jsUTCDateStr.remove(jsUTCDateStr.length() - 5, 4); // get rid of milliseconds (".000")
QString qtUTCDateStr = qtDate.toUTC().toString(Qt::ISODate);
if (jsUTCDateStr != qtUTCDateStr)
Expand Down
30 changes: 15 additions & 15 deletions tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp
Expand Up @@ -2827,7 +2827,7 @@ void tst_QJSValue::call_object()
QJSEngine eng;
QJSValue Object = eng.evaluate("Object");
QCOMPARE(Object.isCallable(), true);
QJSValue result = Object.call(Object);
QJSValue result = Object.callWithInstance(Object);
QCOMPARE(result.isObject(), true);
}

Expand All @@ -2840,7 +2840,7 @@ void tst_QJSValue::call_newObjects()
QCOMPARE(Object.isCallable(), true);
QJSValueList args;
args << QJSValue(&eng, 123);
QJSValue result = Number.call(Object, args);
QJSValue result = Number.callWithInstance(Object, args);
QCOMPARE(result.strictlyEquals(args.at(0)), true);
}

Expand All @@ -2852,7 +2852,7 @@ void tst_QJSValue::call_this()
QCOMPARE(fun.isCallable(), true);

QJSValue numberObject = QJSValue(&eng, 123.0).toObject();
QJSValue result = fun.call(numberObject);
QJSValue result = fun.callWithInstance(numberObject);
QCOMPARE(result.isObject(), true);
QCOMPARE(result.toNumber(), 123.0);
}
Expand All @@ -2865,29 +2865,29 @@ void tst_QJSValue::call_arguments()
QJSValue fun = eng.evaluate("(function() { return arguments[0]; })");
QCOMPARE(fun.isCallable(), true);
{
QJSValue result = fun.call(eng.undefinedValue());
QJSValue result = fun.callWithInstance(eng.undefinedValue());
QCOMPARE(result.isUndefined(), true);
}
{
QJSValueList args;
args << QJSValue(&eng, 123.0);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QCOMPARE(result.isNumber(), true);
QCOMPARE(result.toNumber(), 123.0);
}
// V2 constructors
{
QJSValueList args;
args << QJSValue(123.0);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QCOMPARE(result.isNumber(), true);
QCOMPARE(result.toNumber(), 123.0);
}
#if 0 // FIXME: The feature of interpreting a passed array as argument list has been removed from the API
{
QJSValue args = eng.newArray();
args.setProperty(0, 123);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QVERIFY(result.isNumber());
QCOMPARE(result.toNumber(), 123.0);
}
Expand All @@ -2904,7 +2904,7 @@ void tst_QJSValue::call()
{
QJSValueList args;
args << QJSValue(&eng, 123.0) << QJSValue(&eng, 456.0);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QCOMPARE(result.isNumber(), true);
QCOMPARE(result.toNumber(), 456.0);
}
Expand All @@ -2913,7 +2913,7 @@ void tst_QJSValue::call()
QJSValue args = eng.newArray();
args.setProperty(0, 123);
args.setProperty(1, 456);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QVERIFY(result.isNumber());
QCOMPARE(result.toNumber(), 456.0);
}
Expand All @@ -2938,7 +2938,7 @@ void tst_QJSValue::call()
{
QJSValueList args;
args << QJSValue(&eng, 123.0);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QVERIFY(!eng.hasUncaughtException());
QCOMPARE(result.isNumber(), true);
QCOMPARE(result.toNumber(), 123.0);
Expand All @@ -2947,15 +2947,15 @@ void tst_QJSValue::call()
{
QJSValueList args;
args << QJSValue(123.0);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QCOMPARE(result.isNumber(), true);
QCOMPARE(result.toNumber(), 123.0);
}
#if 0 // FIXME: The feature of interpreting a passed array as argument list has been removed from the API
{
QJSValue args = eng.newArray();
args.setProperty(0, 123);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QVERIFY(result.isNumber());
QCOMPARE(result.toNumber(), 123.0);
}
Expand All @@ -2966,7 +2966,7 @@ void tst_QJSValue::call()
{
QJSValueList args;
args << QJSValue(&eng, 123.0);
QJSValue result = fun.call(eng.undefinedValue(), args);
QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
QVERIFY(!eng.hasUncaughtException());
QCOMPARE(result.isNumber(), true);
QCOMPARE(result.toNumber(), 123.0);
Expand All @@ -2985,7 +2985,7 @@ void tst_QJSValue::call_invalidArguments()
{
QJSValueList args;
args << QJSValue();
QJSValue ret = fun.call(args);
QJSValue ret = fun.callWithInstance(args);
QVERIFY(!eng.hasUncaughtException());
QCOMPARE(ret.isValid(), true);
QCOMPARE(ret.isUndefined(), true);
Expand Down Expand Up @@ -3040,7 +3040,7 @@ void tst_QJSValue::call_twoEngines()
QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: "
"cannot call function with thisObject created in "
"a different engine");
QCOMPARE(fun.call(object).isValid(), false);
QCOMPARE(fun.callWithInstance(object).isValid(), false);
QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: "
"cannot call function with argument created in "
"a different engine");
Expand Down

0 comments on commit 174ee89

Please sign in to comment.