add exceptionhandler code for connected signals/JS methods

- there wasn't any error information if a C++ triggered signal resulted
   in a JS method which has an error, now it will create an exception for it
 - creating messagebox inside the lib is something what we want to avoid,
   so the developer itself is responsible to catch these exceptions
 - most cases of the installer code does that already

Change-Id: I07486f73be9de13a486de235f14e3a7d7b54f5b1
Reviewed-by: Karsten Heimrich <karsten.heimrich@digia.com>
This commit is contained in:
Tim Jenssen 2013-05-29 15:21:59 +02:00
parent c2cfa6dd83
commit dfbb731676
5 changed files with 73 additions and 6 deletions

View File

@ -209,6 +209,8 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core)
globalObject().property(QLatin1String("installer"))
.setProperty(QLatin1String("components"), scriptComponentsObject);
connect(this, SIGNAL(signalHandlerException(QScriptValue)), SLOT(handleException(QScriptValue)));
}
ScriptEngine::~ScriptEngine()
@ -279,6 +281,12 @@ QScriptValue ScriptEngine::loadInConext(const QString &context, const QString &f
return scriptContext;
}
void ScriptEngine::handleException(const QScriptValue &value)
{
if (!value.engine())
return;
throw Error(uncaughtExceptionString(this, tr("Fatal error while evaluating a script.")));
}
/*!
Tries to call the method with \a name within the script and returns the result. If the method

View File

@ -71,11 +71,12 @@ public:
explicit ScriptEngine(PackageManagerCore *core);
~ScriptEngine();
void setGuiQObject(QObject *guiQObject);
QScriptValue callScriptMethod(const QScriptValue &scriptContext, const QString &name,
const QScriptValueList &parameters = QScriptValueList()) const;
QScriptValue callScriptMethod(const QScriptValue &scriptContext, const QString &methodName,
const QScriptValueList &arguments = QScriptValueList()) const;
QScriptValue loadInConext(const QString &context, const QString &fileName, const QString &scriptInjection = QString());
private slots:
void handleException(const QScriptValue &value);
private:
QScriptValue generateMessageBoxObject();
QScriptValue generateDesktopServicesObject();

View File

@ -0,0 +1,11 @@
function BrokenConnect()
{
emiter.emitted.connect(receive)
}
function receive()
{
print("function receive()");
// this should throw an exception, "foo" does not exist
foo.bar = "test";
}

View File

@ -3,5 +3,6 @@
<file>data/auto-install.qs</file>
<file>data/component1.qs</file>
<file>data/component2.qs</file>
<file>data/broken_connect.qs</file>
</qresource>
</RCC>

View File

@ -11,8 +11,6 @@
using namespace QInstaller;
// -- InstallerGui
class TestGui : public QInstaller::PackageManagerGui
{
Q_OBJECT
@ -34,6 +32,18 @@ public:
}
};
class EmitSignalObject : public QObject
{
Q_OBJECT
public:
EmitSignalObject() {}
~EmitSignalObject() {}
void produceSignal() { emit emitted(); }
signals:
void emitted();
};
class tst_ScriptEngine : public QObject
{
@ -54,6 +64,42 @@ private slots:
m_scriptEngine = m_core.scriptEngine();
}
void testBrokenJSMethodConnect()
{
EmitSignalObject emiter;
m_scriptEngine->globalObject().setProperty(QLatin1String("emiter"),
m_scriptEngine->newQObject(&emiter));
QScriptValue context = m_scriptEngine->loadInConext(QLatin1String("BrokenConnect"),
":///data/broken_connect.qs");
QVERIFY(context.isValid());
if (m_scriptEngine->hasUncaughtException()) {
QFAIL(qPrintable(QString::fromLatin1("ScriptEngine hasUncaughtException:\n %1").arg(
uncaughtExceptionString(m_scriptEngine))));
}
const QString debugMesssage(
"create Error-Exception: \"Fatal error while evaluating a script.\n\n"
"ReferenceError: Can't find variable: foo\n\n"
"Backtrace:\n"
#if QT_VERSION < 0x050000
"\t<anonymous>()@:///data/broken_connect.qs:10\" ");
#else
"\treceive() at :///data/broken_connect.qs:10\n"
"\t<global>() at -1\" ");
#endif
try {
// ignore Output from script
setExpectedScriptOutput("function receive()");
setExpectedScriptOutput(qPrintable(debugMesssage));
emiter.produceSignal();
} catch (const Error &error) {
QVERIFY2(debugMesssage.contains(error.message()), "There was some unexpected error.");
}
}
void testScriptPrint()
{
setExpectedScriptOutput("test");
@ -199,7 +245,7 @@ private:
PackageManagerCore m_core;
Component *m_component;
QScriptEngine *m_scriptEngine;
ScriptEngine *m_scriptEngine;
};