Handle exceptions inside QV8QObjectConnectionList::qt_metacall

Previously, exceptions were not handled in the connectionlist.
This could cause v8 to assert under certain circumstances.

Task-number: QTBUG-23375
Change-Id: Ie5f043b50bb6b02a77be464ca18ea8e3bbb0f501
Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
This commit is contained in:
Chris Adams 2011-12-29 10:32:52 +10:00 committed by Qt by Nokia
parent 7810092782
commit 8eec0518d6
3 changed files with 51 additions and 0 deletions

View File

@ -51,6 +51,7 @@
#include <private/qjsvalue_p.h> #include <private/qjsvalue_p.h>
#include <private/qscript_impl_p.h> #include <private/qscript_impl_p.h>
#include <private/qdeclarativeaccessors_p.h> #include <private/qdeclarativeaccessors_p.h>
#include <private/qdeclarativeexpression_p.h>
#include <QtDeclarative/qjsvalue.h> #include <QtDeclarative/qjsvalue.h>
#include <QtCore/qvarlengtharray.h> #include <QtCore/qvarlengtharray.h>
@ -1229,11 +1230,22 @@ int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, v
Connection &connection = connections[ii]; Connection &connection = connections[ii];
if (connection.needsDestroy) if (connection.needsDestroy)
continue; continue;
v8::TryCatch try_catch;
if (connection.thisObject.IsEmpty()) { if (connection.thisObject.IsEmpty()) {
connection.function->Call(engine->global(), argCount, args.data()); connection.function->Call(engine->global(), argCount, args.data());
} else { } else {
connection.function->Call(connection.thisObject, argCount, args.data()); connection.function->Call(connection.thisObject, argCount, args.data());
} }
if (try_catch.HasCaught()) {
QDeclarativeError error;
error.setDescription(QString(QLatin1String("Unknown exception occurred during evaluation of connected function: %1")).arg(engine->toString(connection.function->GetName())));
v8::Local<v8::Message> message = try_catch.Message();
if (!message.IsEmpty())
QDeclarativeExpressionPrivate::exceptionToError(message, error);
QDeclarativeEnginePrivate::get(engine->engine())->warning(error);
}
} }
connectionList.connectionsInUse--; connectionList.connectionsInUse--;

View File

@ -0,0 +1,24 @@
import QtQuick 2.0
Item {
id: root
property int first: 5
property bool test: false
Item {
id: exceptional
function exceptionalFunction() {
var obj = undefined;
var prop = undefined;
return obj[prop];
}
}
Component.onCompleted: {
root["firstChanged"].connect(exceptional.exceptionalFunction);
root["firstChanged"].connect(exceptional.exceptionalFunction);
root["firstChanged"].connect(exceptional.exceptionalFunction);
first = 6;
test = true;
}
}

View File

@ -199,6 +199,7 @@ private slots:
void qtbug_11606(); void qtbug_11606();
void qtbug_11600(); void qtbug_11600();
void qtbug_21864(); void qtbug_21864();
void qobjectConnectionListExceptionHandling();
void nonscriptable(); void nonscriptable();
void deleteLater(); void deleteLater();
void in(); void in();
@ -5181,6 +5182,20 @@ void tst_qdeclarativeecmascript::qtbug_21864()
delete o; delete o;
} }
void tst_qdeclarativeecmascript::qobjectConnectionListExceptionHandling()
{
// QTBUG-23375
QDeclarativeComponent component(&engine, testFileUrl("qobjectConnectionListExceptionHandling.qml"));
QString warning = component.url().toString() + QLatin1String(":13: TypeError: Cannot read property 'undefined' of undefined");
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QObject *o = component.create();
QVERIFY(o != 0);
QCOMPARE(o->property("test").toBool(), true);
delete o;
}
// Reading and writing non-scriptable properties should fail // Reading and writing non-scriptable properties should fail
void tst_qdeclarativeecmascript::nonscriptable() void tst_qdeclarativeecmascript::nonscriptable()
{ {