From 95cee5d6e514891aab160c8e1fc4814c147ab3a6 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 20 Jan 2012 08:00:27 +0100 Subject: [PATCH] Add QJSValue::call() overload MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This overload takes only an argument list, not a this-object, since that is a very common way of calling stand-alone ("non-member") functions. Now there is no longer a need to pass a dummy value for the this-object. Task-number: QTBUG-23604 Change-Id: Iae952d91fce5bcaa62a05b9978c15f32802da90a Reviewed-by: Simon Hausmann Reviewed-by: Jędrzej Nowacki --- src/declarative/qml/v8/qjsvalue.cpp | 22 ++++++++++++++++++++++ src/declarative/qml/v8/qjsvalue.h | 1 + .../qdeclarativeecmascript/testtypes.cpp | 2 +- tests/auto/declarative/qjsengine/tst_qjsengine.cpp | 22 +++++++++++----------- tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp | 18 +++++++++--------- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/declarative/qml/v8/qjsvalue.cpp b/src/declarative/qml/v8/qjsvalue.cpp index a43dd33..623e24b 100644 --- a/src/declarative/qml/v8/qjsvalue.cpp +++ b/src/declarative/qml/v8/qjsvalue.cpp @@ -696,6 +696,28 @@ QVariant QJSValue::toVariant() const return d->toVariant(); } +/*! + Calls this QJSValue as a function, passing \a args as arguments + to the function, and using the globalObject() as the "this"-object. + Returns the value returned from the function. + + If this QJSValue is not callable, call() does nothing and + returns an undefined QJSValue. + + Calling call() can cause an exception to occur in the script engine; + in that case, call() returns the value that was thrown (typically an + \c{Error} object). You can call + QJSEngine::hasUncaughtException() to determine if an exception + occurred. + + \sa isCallable() +*/ +QJSValue QJSValue::call(const QJSValueList &args) +{ + Q_D(QJSValue); + QScriptIsolate api(d->engine()); + return d->call(/*thisObject=*/0, args); +} /*! Calls this QJSValue as a function, using \a thisObject as diff --git a/src/declarative/qml/v8/qjsvalue.h b/src/declarative/qml/v8/qjsvalue.h index 8a15c4e..b9278c5d 100644 --- a/src/declarative/qml/v8/qjsvalue.h +++ b/src/declarative/qml/v8/qjsvalue.h @@ -141,6 +141,7 @@ public: QJSValue::PropertyFlags propertyFlags(const QString &name) const; bool isCallable() const; + QJSValue call(const QJSValueList &args); QJSValue call(const QJSValue &thisObject = QJSValue(), const QJSValueList &args = QJSValueList()); QJSValue construct(const QJSValueList &args = QJSValueList()); diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index 5d4f579..ccfdfdb 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -127,7 +127,7 @@ static QJSValue readonly_script_api(QDeclarativeEngine *engine, QJSEngine *scrip // now freeze it so that it's read-only QJSValue freezeFunction = scriptEngine->evaluate("(function(obj) { return Object.freeze(obj); })"); - v = freezeFunction.call(QJSValue(), (QJSValueList() << v)); + v = freezeFunction.call(QJSValueList() << v); return v; } diff --git a/tests/auto/declarative/qjsengine/tst_qjsengine.cpp b/tests/auto/declarative/qjsengine/tst_qjsengine.cpp index 7aa5bbc..13c5884 100644 --- a/tests/auto/declarative/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/declarative/qjsengine/tst_qjsengine.cpp @@ -830,15 +830,15 @@ void tst_QJSEngine::jsRegExp() QCOMPARE(r.toString(), QString::fromLatin1("/foo/gim")); QJSValue rxCtor = eng.globalObject().property("RegExp"); - QJSValue r2 = rxCtor.call(QJSValue(), QJSValueList() << r); + QJSValue r2 = rxCtor.call(QJSValueList() << r); QVERIFY(r2.isRegExp()); QVERIFY(r2.strictlyEquals(r)); - QJSValue r3 = rxCtor.call(QJSValue(), QJSValueList() << r << "gim"); + QJSValue r3 = rxCtor.call(QJSValueList() << r << "gim"); QVERIFY(r3.isError()); QVERIFY(r3.toString().contains(QString::fromLatin1("TypeError"))); // Cannot supply flags when constructing one RegExp from another - QJSValue r4 = rxCtor.call(QJSValue(), QJSValueList() << "foo" << "gim"); + QJSValue r4 = rxCtor.call(QJSValueList() << "foo" << "gim"); QVERIFY(r4.isRegExp()); QJSValue r5 = rxCtor.construct(QJSValueList() << r); @@ -1179,7 +1179,7 @@ static QScriptValue myConstructor(QScriptContext *ctx, QScriptEngine *eng) static QScriptValue instanceofJS(const QScriptValue &inst, const QScriptValue &ctor) { return inst.engine()->evaluate("(function(inst, ctor) { return inst instanceof ctor; })") - .call(QScriptValue(), QScriptValueList() << inst << ctor); + .call(QScriptValueList() << inst << ctor); } void tst_QJSEngine::newQMetaObject() @@ -4343,7 +4343,7 @@ void tst_QJSEngine::jsFunctionDeclarationAsStatement() { QJSValue ret = eng.evaluate("foo('bar')"); QVERIFY(ret.isCallable()); - QJSValue ret2 = ret.call(QJSValue()); + QJSValue ret2 = ret.call(); QCOMPARE(ret2.toString(), QString::fromLatin1("bar")); QVERIFY(!eng.globalObject().property("bar").isValid()); QVERIFY(!eng.globalObject().property("baz").isValid()); @@ -4351,7 +4351,7 @@ void tst_QJSEngine::jsFunctionDeclarationAsStatement() { QJSValue ret = eng.evaluate("foo('baz')"); QVERIFY(ret.isCallable()); - QJSValue ret2 = ret.call(QJSValue()); + QJSValue ret2 = ret.call(); QCOMPARE(ret2.toString(), QString::fromLatin1("baz")); QVERIFY(!eng.globalObject().property("bar").isValid()); QVERIFY(!eng.globalObject().property("baz").isValid()); @@ -5459,7 +5459,7 @@ void tst_QJSEngine::translateScript_callQsTrFromCpp() // There is no context, but it shouldn't crash QCOMPARE(engine.globalObject().property("qsTr").call( - QScriptValue(), QScriptValueList() << "One").toString(), QString::fromLatin1("One")); + QScriptValueList() << "One").toString(), QString::fromLatin1("One")); } void tst_QJSEngine::translateWithInvalidArgs_data() @@ -5769,7 +5769,7 @@ void tst_QJSEngine::nativeFunctionScopes() QScriptEngine eng; { QScriptValue fun = eng.newFunction(counter); - QScriptValue cnt = fun.call(QScriptValue(), QScriptValueList() << 123); + QScriptValue cnt = fun.call(QScriptValueList() << 123); QVERIFY(cnt.isCallable()); { QScriptValue ret = cnt.call(); @@ -5780,7 +5780,7 @@ void tst_QJSEngine::nativeFunctionScopes() } { QScriptValue fun = eng.newFunction(counter_hybrid); - QScriptValue cnt = fun.call(QScriptValue(), QScriptValueList() << 123); + QScriptValue cnt = fun.call(QScriptValueList() << 123); QVERIFY(cnt.isCallable()); { QScriptValue ret = cnt.call(); @@ -5941,7 +5941,7 @@ void tst_QJSEngine::evaluateProgram_executeLater() { QScriptValue fun = eng.newFunction(createProgram); QScriptProgram program = qscriptvalue_cast( - fun.call(QScriptValue(), QScriptValueList() << "a + 1")); + fun.call(QScriptValueList() << "a + 1")); QVERIFY(!program.isNull()); eng.globalObject().setProperty("a", QScriptValue()); { @@ -6092,7 +6092,7 @@ void tst_QJSEngine::qRegExpInport() QVERIFY(rexp.isCallable()); QJSValue func = eng.evaluate("(function(string, regexp) { return string.match(regexp); })"); - QJSValue result = func.call(QJSValue(), QJSValueList() << string << rexp); + QJSValue result = func.call(QJSValueList() << string << rexp); rx.indexIn(string); for (int i = 0; i <= rx.captureCount(); i++) { diff --git a/tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp b/tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp index 7fd2eaa..48a65dc 100644 --- a/tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp @@ -2985,7 +2985,7 @@ void tst_QJSValue::call_invalidArguments() { QJSValueList args; args << QJSValue(); - QJSValue ret = fun.call(QJSValue(), args); + QJSValue ret = fun.call(args); QVERIFY(!eng.hasUncaughtException()); QCOMPARE(ret.isValid(), true); QCOMPARE(ret.isUndefined(), true); @@ -2996,7 +2996,7 @@ void tst_QJSValue::call_invalidArguments() { QJSValueList args; args << QJSValue(); - QJSValue ret = fun.call(QJSValue(), args); + QJSValue ret = fun.call(args); QCOMPARE(ret.isValid(), true); QCOMPARE(ret.isUndefined(), true); } @@ -3006,7 +3006,7 @@ void tst_QJSValue::call_invalidArguments() { QJSValueList args; args << QJSValue() << QJSValue(); - QJSValue ret = fun.call(QJSValue(), args); + QJSValue ret = fun.call(args); QCOMPARE(ret.isValid(), true); QCOMPARE(ret.isNumber(), true); QCOMPARE(qIsNaN(ret.toNumber()), true); @@ -3044,7 +3044,7 @@ void tst_QJSValue::call_twoEngines() QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: " "cannot call function with argument created in " "a different engine"); - QCOMPARE(fun.call(QJSValue(), QJSValueList() << QJSValue(&eng, 123)).isValid(), false); + QCOMPARE(fun.call(QJSValueList() << QJSValue(&eng, 123)).isValid(), false); { QJSValue fun = eng.evaluate("Object"); QVERIFY(fun.isCallable()); @@ -3053,7 +3053,7 @@ void tst_QJSValue::call_twoEngines() QJSValueList args; args << objectInDifferentEngine; QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: cannot call function with argument created in a different engine"); - fun.call(QJSValue(), args); + fun.call(args); } } @@ -3540,15 +3540,15 @@ void tst_QJSValue::equals() QJSValue compareFun = eng.evaluate("(function(a, b) { return a == b; })"); QVERIFY(compareFun.isCallable()); { - QJSValue ret = compareFun.call(QJSValue(), QJSValueList() << qobj1 << qobj2); + QJSValue ret = compareFun.call(QJSValueList() << qobj1 << qobj2); QVERIFY(ret.isBool()); - ret = compareFun.call(QJSValue(), QJSValueList() << qobj1 << qobj3); + ret = compareFun.call(QJSValueList() << qobj1 << qobj3); QVERIFY(ret.isBool()); QVERIFY(!ret.toBool()); - ret = compareFun.call(QJSValue(), QJSValueList() << qobj1 << qobj4); + ret = compareFun.call(QJSValueList() << qobj1 << qobj4); QVERIFY(ret.isBool()); QVERIFY(!ret.toBool()); - ret = compareFun.call(QJSValue(), QJSValueList() << qobj1 << obj1); + ret = compareFun.call(QJSValueList() << qobj1 << obj1); QVERIFY(ret.isBool()); QVERIFY(!ret.toBool()); } -- 2.7.4