Remove half the v8::TryCatch statements

Replacing the other half requires a replacement for v8::Script.

Change-Id: I40fe99302fba23f286773ec1adaf8d3751db901d
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
Lars Knoll 2013-05-20 22:12:41 +02:00 committed by Simon Hausmann
parent 71e263abc4
commit e1a6612d3a
8 changed files with 124 additions and 155 deletions

View File

@ -4,6 +4,7 @@ TARGETPATH = QtQuick/LocalStorage
IMPORT_VERSION = 2.0
QT = sql qml-private core-private
CONFIG += exceptions
SOURCES += plugin.cpp

View File

@ -341,15 +341,17 @@ static QV4::Value qmlsqldatabase_changeVersion(const v8::Arguments& args)
ok = false;
db.transaction();
v8::TryCatch tc;
v8::Handle<v8::Value> callbackArgs[] = { instance };
v8::Handle<v8::Function>::Cast(callback)->Call(v8::Value::fromV4Value(engine->global()), 1, callbackArgs);
if (tc.HasCaught()) {
QV4::Value callbackArgs[] = { instance->v4Value() };
QV4::FunctionObject *f = callback->v4Value().asFunctionObject();
QV4::ExecutionContext *ctx = f->engine()->current;
try {
f->call(engine->global(), callbackArgs, 1);
} catch (QV4::Exception &e) {
e.accept(ctx);
db.rollback();
tc.ReThrow();
return QV4::Value::undefinedValue();
} else if (!db.commit()) {
throw;
}
if (!db.commit()) {
db.rollback();
V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR,QQmlEngine::tr("SQL transaction failed"));
} else {
@ -393,18 +395,23 @@ static QV4::Value qmlsqldatabase_transaction_shared(const v8::Arguments& args, b
instance->SetExternalResource(q);
db.transaction();
v8::TryCatch tc;
v8::Handle<v8::Value> callbackArgs[] = { instance };
callback->Call(v8::Value::fromV4Value(engine->global()), 1, callbackArgs);
QV4::FunctionObject *f = callback->v4Value().asFunctionObject();
if (f) {
QV4::ExecutionContext *ctx = f->engine()->current;
QV4::Value callbackArgs[] = { instance->v4Value() };
try {
f->call(engine->global(), callbackArgs, 1);
} catch (QV4::Exception &e) {
e.accept(ctx);
q->inTransaction = false;
db.rollback();
throw;
}
q->inTransaction = false;
q->inTransaction = false;
if (tc.HasCaught()) {
db.rollback();
tc.ReThrow();
return QV4::Value::undefinedValue();
} else if (!db.commit()) {
db.rollback();
if (!db.commit())
db.rollback();
}
return QV4::Value::undefinedValue();
@ -674,14 +681,17 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
r->version = version;
instance->SetExternalResource(r);
if (created && dbcreationCallback->IsFunction()) {
v8::TryCatch tc;
v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(dbcreationCallback);
v8::Handle<v8::Value> args[] = { instance };
callback->Call(v8::Value::fromV4Value(engine->global()), 1, args);
if (tc.HasCaught()) {
tc.ReThrow();
return;
if (created) {
QV4::FunctionObject *f = dbcreationCallback->v4Value().asFunctionObject();
if (f) {
QV4::ExecutionContext *ctx = f->engine()->current;
QV4::Value args[] = { instance->v4Value() };
try {
f->call(engine->global(), args, 1);
} catch (QV4::Exception &e) {
e.accept(ctx);
throw;
}
}
}

View File

@ -1475,20 +1475,18 @@ void QV8IncubatorResource::statusChanged(Status s)
}
if (!me.isEmpty()) { // Will be false in synchronous mode
v8::Handle<v8::Value> callback = v8::Handle<v8::Object>(me)->GetInternalField(0);
QV4::Value callback = v8::Handle<v8::Object>(me)->GetInternalField(0)->v4Value();
if (!callback.IsEmpty() && !callback->IsUndefined()) {
if (callback->IsFunction()) {
v8::Handle<v8::Function> f = v8::Handle<v8::Function>::Cast(callback);
v8::Handle<v8::Value> args[] = { v8::Integer::NewFromUnsigned(s) };
v8::TryCatch tc;
f->Call(me.value(), 1, args);
if (tc.HasCaught()) {
QQmlError error;
QQmlJavaScriptExpression::exceptionToError(tc.Message(), error);
QQmlEnginePrivate::warning(QQmlEnginePrivate::get(engine->engine()), error);
}
if (QV4::FunctionObject *f = callback.asFunctionObject()) {
QV4::ExecutionContext *ctx = f->engine()->current;
QV4::Value args[] = { QV4::Value::fromUInt32(s) };
try {
f->call(me.value(), args, 1);
} catch (QV4::Exception &e) {
e.accept(ctx);
QQmlError error;
QQmlJavaScriptExpression::exceptionToError(e, error);
QQmlEnginePrivate::warning(QQmlEnginePrivate::get(engine->engine()), error);
}
}
}

View File

@ -54,6 +54,7 @@
#include <private/qv4object_p.h>
#include <private/qv4variantobject_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@ -911,8 +912,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(ctxt->engine);
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
v8::Handle<v8::Function> function = method(id);
if (function.IsEmpty()) {
QV4::FunctionObject *function = method(id)->v4Value().asFunctionObject();
if (!function) {
// The function was not compiled. There are some exceptional cases which the
// expression rewriter does not rewrite properly (e.g., \r-terminated lines
// are not rewritten correctly but this bug is deemed out-of-scope to fix for
@ -926,27 +927,23 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QQmlVMEMetaData::MethodData *data = metaData->methodData() + id;
v8::Handle<v8::Value> *args = 0;
QVarLengthArray<QV4::Value, 9> args;
if (data->parameterCount) {
args = new v8::Handle<v8::Value>[data->parameterCount];
for (int ii = 0; ii < data->parameterCount; ++ii)
args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
}
for (int ii = 0; ii < data->parameterCount; ++ii)
args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
v8::TryCatch try_catch;
v8::Handle<v8::Value> result = function->Call(v8::Value::fromV4Value(ep->v8engine()->global()), data->parameterCount, args);
QVariant rv;
if (try_catch.HasCaught()) {
QV4::Value result = QV4::Value::undefinedValue();
QV4::ExecutionContext *ctx = function->engine()->current;
try {
result = function->call(ep->v8engine()->global(), args.data(), data->parameterCount);
if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result, 0);
} catch (QV4::Exception &e) {
e.accept(ctx);
QQmlError error;
QQmlExpressionPrivate::exceptionToError(try_catch.Message(), error);
QQmlExpressionPrivate::exceptionToError(e, error);
if (error.isValid())
ep->warning(error);
if (a[0]) *(QVariant *)a[0] = QVariant();
} else {
if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result->v4Value(), 0);
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.

View File

@ -999,6 +999,7 @@ private slots:
private:
void requestFromUrl(const QUrl &url);
QV4::ExecutionEngine *v4;
State m_state;
bool m_errorFlag;
bool m_sendFlag;
@ -1027,7 +1028,7 @@ private:
QV4::PersistentValue m_me;
void dispatchCallback(const QV4::Value &me);
void printError(v8::Handle<v8::Message>);
void printError(const QV4::Exception &e);
int m_status;
QString m_statusText;
@ -1040,8 +1041,9 @@ private:
};
QQmlXMLHttpRequest::QQmlXMLHttpRequest(QV8Engine *engine, QNetworkAccessManager *manager)
: QV8ObjectResource(engine), m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
: QV8ObjectResource(engine), v4(QV8Engine::getV4(engine))
, m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
, m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
{
}
@ -1085,9 +1087,7 @@ QV4::Value QQmlXMLHttpRequest::open(v8::Handle<v8::Object> me, const QString &me
m_method = method;
m_url = url;
m_state = Opened;
v8::TryCatch tc;
dispatchCallback(me->v4Value());
if (tc.HasCaught()) printError(tc.Message());
return QV4::Value::undefinedValue();
}
@ -1228,9 +1228,7 @@ QV4::Value QQmlXMLHttpRequest::abort(v8::Handle<v8::Object> me)
m_state = Done;
m_sendFlag = false;
v8::TryCatch tc;
dispatchCallback(me->v4Value());
if (tc.HasCaught()) printError(tc.Message());
}
m_state = Unsent;
@ -1259,18 +1257,14 @@ void QQmlXMLHttpRequest::readyRead()
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
v8::TryCatch tc;
dispatchCallback(m_me.value());
if (tc.HasCaught()) printError(tc.Message());
}
bool wasEmpty = m_responseEntityBody.isEmpty();
m_responseEntityBody.append(m_network->readAll());
if (wasEmpty && !m_responseEntityBody.isEmpty())
m_state = Loading;
v8::TryCatch tc;
dispatchCallback(m_me.value());
if (tc.HasCaught()) printError(tc.Message());
}
static const char *errorToString(QNetworkReply::NetworkError error)
@ -1308,9 +1302,7 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
error == QNetworkReply::ContentReSendError ||
error == QNetworkReply::UnknownContentError) {
m_state = Loading;
v8::TryCatch tc;
dispatchCallback(m_me.value());
if (tc.HasCaught()) printError(tc.Message());
} else {
m_errorFlag = true;
m_responseEntityBody = QByteArray();
@ -1318,9 +1310,7 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
m_state = Done;
v8::TryCatch tc;
dispatchCallback(m_me.value());
if (tc.HasCaught()) printError(tc.Message());
}
#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
@ -1347,9 +1337,7 @@ void QQmlXMLHttpRequest::finished()
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
v8::TryCatch tc;
dispatchCallback(m_me);
if (tc.HasCaught()) printError(tc.Message());
}
m_responseEntityBody.append(m_network->readAll());
readEncoding();
@ -1366,15 +1354,11 @@ void QQmlXMLHttpRequest::finished()
destroyNetwork();
if (m_state < Loading) {
m_state = Loading;
v8::TryCatch tc;
dispatchCallback(m_me);
if (tc.HasCaught()) printError(tc.Message());
}
m_state = Done;
v8::TryCatch tc;
dispatchCallback(m_me);
if (tc.HasCaught()) printError(tc.Message());
setMe(v8::Handle<v8::Object>());
}
@ -1454,52 +1438,51 @@ const QByteArray &QQmlXMLHttpRequest::rawResponseBody() const
return m_responseEntityBody;
}
// Requires a TryCatch scope
void QQmlXMLHttpRequest::dispatchCallback(const QV4::Value &me)
{
if (me.isEmpty() || me.isUndefined() || me.isNull()) {
v8::ThrowException(v8::Exception::Error(v8::String::New("Unable to dispatch QQmlXmlHttpRequest callback: invalid object")));
return;
QV4::ExecutionContext *ctx = v4->current;
try {
QV4::Object *o = me.asObject();
if (!o)
__qmljs_throw(ctx, QV4::Value::fromObject(
v4->newErrorObject(QV4::Value::fromString(ctx, QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject")))), -1);
QV4::Object *thisObj = o->get(v4->newString(QStringLiteral("ThisObject"))).asObject();
if (!thisObj)
__qmljs_throw(ctx, QV4::Value::fromObject(
v4->newErrorObject(QV4::Value::fromString(ctx, QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject")))), -1);
QV4::FunctionObject *callback = thisObj->get(v4->newString(QStringLiteral("onreadystatechange"))).asFunctionObject();
if (!callback) {
// not an error, but no onreadystatechange function to call.
return;
}
QV4::Value activationObject = o->get(v4->newString(QStringLiteral("ActivationObject")));
if (!activationObject.asObject()) {
v8::ThrowException(v8::Exception::Error(v8::String::New("QQmlXMLHttpRequest: internal error: empty ActivationObject")));
return;
}
QQmlContextData *callingContext = engine->contextWrapper()->context(activationObject);
if (callingContext)
callback->call(v4->current, activationObject, 0, 0);
// if the callingContext object is no longer valid, then it has been
// deleted explicitly (e.g., by a Loader deleting the itemContext when
// the source is changed). We do nothing in this case, as the evaluation
// cannot succeed.
} catch(QV4::Exception &e) {
e.accept(ctx);
printError(e);
}
QV4::Object *o = me.asObject();
if (!o)
v8::ThrowException(v8::Exception::Error(v8::String::New("QQmlXMLHttpRequest: internal error: empty ThisObject")));
QV4::ExecutionEngine *v4 = o->engine();
QV4::Object *thisObj = o->get(v4->newString(QStringLiteral("ThisObject"))).asObject();
if (!thisObj) {
v8::ThrowException(v8::Exception::Error(v8::String::New("QQmlXMLHttpRequest: internal error: empty ThisObject")));
return;
}
QV4::FunctionObject *callback = thisObj->get(v4->newString(QStringLiteral("onreadystatechange"))).asFunctionObject();
if (!callback) {
// not an error, but no onreadystatechange function to call.
return;
}
QV4::Value activationObject = o->get(v4->newString(QStringLiteral("ActivationObject")));
if (!activationObject.asObject()) {
v8::ThrowException(v8::Exception::Error(v8::String::New("QQmlXMLHttpRequest: internal error: empty ActivationObject")));
return;
}
QQmlContextData *callingContext = engine->contextWrapper()->context(activationObject);
if (callingContext)
callback->call(v4->current, activationObject, 0, 0);
// if the callingContext object is no longer valid, then it has been
// deleted explicitly (e.g., by a Loader deleting the itemContext when
// the source is changed). We do nothing in this case, as the evaluation
// cannot succeed.
}
// Must have a handle scope
void QQmlXMLHttpRequest::printError(v8::Handle<v8::Message> message)
void QQmlXMLHttpRequest::printError(const QV4::Exception &e)
{
QQmlError error;
QQmlExpressionPrivate::exceptionToError(message, error);
QQmlExpressionPrivate::exceptionToError(e, error);
QQmlEnginePrivate::warning(QQmlEnginePrivate::get(engine->engine()), error);
}

View File

@ -118,30 +118,8 @@ QV4::Value console(ConsoleLogTypes logType, const v8::Arguments &args,
if (i != 0)
result.append(QLatin1Char(' '));
v8::Handle<v8::Value> value = args[i];
v8::TryCatch tryCatch;
v8::Handle<v8::String> toString = value->ToString();
if (tryCatch.HasCaught()) {
// toString() threw Exception
// Is it possible for value to be anything other than Object?
QString str;
if (value->IsObject()) {
str = QStringLiteral("[object Object]");
} else {
toString = tryCatch.Exception()->ToString();
str = QStringLiteral("toString() threw exception: %1")
.arg(toString->v4Value().toQString());
}
result.append(str);
continue;
}
QString tmp = toString->v4Value().toQString();
if (value->IsArray())
result.append(QStringLiteral("[%1]").arg(tmp));
else
result.append(tmp);
QV4::Value value = args[i]->v4Value();
result.append(value.toQString());
}
if (printStack) {

View File

@ -49,6 +49,7 @@
#include <private/qqmlengine_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@ -92,10 +93,16 @@ v8::Handle<v8::Object> QV8Include::resultValue(Status status)
void QV8Include::callback(QV8Engine *engine, v8::Handle<v8::Function> callback, v8::Handle<v8::Object> status)
{
if (!callback.IsEmpty()) {
v8::Handle<v8::Value> args[] = { status };
v8::TryCatch tc;
callback->Call(v8::Value::fromV4Value(engine->global()), 1, args);
QV4::FunctionObject *f = callback->v4Value().asFunctionObject();
if (!f)
return;
QV4::Value args[] = { status->v4Value() };
QV4::ExecutionContext *ctx = f->engine()->current;
try {
f->call(engine->global(), args, 1);
} catch (QV4::Exception &e) {
e.accept(ctx);
}
}

View File

@ -1323,21 +1323,16 @@ int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, v
if (connection.needsDestroy)
continue;
v8::TryCatch try_catch;
QV4::FunctionObject *f = connection.function.value().asFunctionObject();
QV4::ExecutionEngine *v4 = f->internalClass->engine;
if (connection.thisObject.isEmpty()) {
f->call(v4->current, engine->global(), args.data(), argCount);
} else {
f->call(v4->current, connection.thisObject, args.data(), argCount);
}
if (try_catch.HasCaught()) {
QV4::ExecutionContext *ctx = v4->current;
try {
f->call(v4->current, connection.thisObject.isEmpty() ? engine->global() : connection.thisObject.value(), args.data(), argCount);
} catch (QV4::Exception &e) {
QQmlError error;
error.setDescription(QString(QLatin1String("Unknown exception occurred during evaluation of connected function: %1")).arg(f->name->toQString()));
v8::Handle<v8::Message> message = try_catch.Message();
if (!message.IsEmpty())
QQmlExpressionPrivate::exceptionToError(message, error);
QQmlExpressionPrivate::exceptionToError(e, error);
if (error.description().isEmpty())
error.setDescription(QString(QLatin1String("Unknown exception occurred during evaluation of connected function: %1")).arg(f->name->toQString()));
QQmlEnginePrivate::get(engine->engine())->warning(error);
}
}