aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/localstorage/localstorage.pro1
-rw-r--r--src/imports/localstorage/plugin.cpp62
-rw-r--r--src/qml/qml/qqmlcomponent.cpp26
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp31
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp97
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp26
-rw-r--r--src/qml/qml/v8/qv8include.cpp15
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp19
8 files changed, 123 insertions, 154 deletions
diff --git a/src/imports/localstorage/localstorage.pro b/src/imports/localstorage/localstorage.pro
index 15753263b8..d3e7182a3b 100644
--- a/src/imports/localstorage/localstorage.pro
+++ b/src/imports/localstorage/localstorage.pro
@@ -4,6 +4,7 @@ TARGETPATH = QtQuick/LocalStorage
IMPORT_VERSION = 2.0
QT = sql qml-private core-private
+CONFIG += exceptions
SOURCES += plugin.cpp
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index f5627984d8..7ce4f43b9d 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -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;
+ }
}
}
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 471d5fca8b..a3f85e243a 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -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);
-
- 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);
- }
+ QV4::Value callback = v8::Handle<v8::Object>(me)->GetInternalField(0)->v4Value();
+
+ 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);
}
}
}
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index d1b12eeaec..838950cbdd 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -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]);
- }
-
- v8::TryCatch try_catch;
+ for (int ii = 0; ii < data->parameterCount; ++ii)
+ args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
- 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.
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 8ebda6f189..938a7e5a8f 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -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::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::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::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;
+ }
- 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);
}
-
- 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);
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 4e8fad369c..bac0c231e2 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -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) {
diff --git a/src/qml/qml/v8/qv8include.cpp b/src/qml/qml/v8/qv8include.cpp
index f3880ec9a2..5c24a96847 100644
--- a/src/qml/qml/v8/qv8include.cpp
+++ b/src/qml/qml/v8/qv8include.cpp
@@ -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);
}
}
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index b10b17f955..2030bf775c 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -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);
}
}