aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/localstorage/plugin.cpp8
-rw-r--r--src/imports/testlib/main.cpp4
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp20
-rw-r--r--src/qml/jsapi/qjsengine.cpp5
-rw-r--r--src/qml/jsapi/qjsvalue.cpp49
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp4
-rw-r--r--src/qml/jsruntime/qv4context.cpp27
-rw-r--r--src/qml/jsruntime/qv4context_p.h4
-rw-r--r--src/qml/jsruntime/qv4engine.cpp8
-rw-r--r--src/qml/jsruntime/qv4engine_p.h10
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4exception.cpp55
-rw-r--r--src/qml/jsruntime/qv4exception_gcc.cpp13
-rw-r--r--src/qml/jsruntime/qv4exception_p.h27
-rw-r--r--src/qml/jsruntime/qv4function_p.h2
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp30
-rw-r--r--src/qml/jsruntime/qv4global_p.h10
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4include.cpp14
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp8
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp3
-rw-r--r--src/qml/jsruntime/qv4script.cpp8
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp4
-rw-r--r--src/qml/jsruntime/qv4value.cpp15
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp14
-rw-r--r--src/qml/qml/qqmlcomponent.cpp6
-rw-r--r--src/qml/qml/qqmlerror.cpp24
-rw-r--r--src/qml/qml/qqmlerror.h7
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp62
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h8
-rw-r--r--src/qml/qml/qqmltypeloader.cpp6
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp6
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp15
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp16
-rw-r--r--src/qml/types/qquickworkerscript.cpp17
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp12
-rw-r--r--tools/v4/main.cpp13
40 files changed, 258 insertions, 292 deletions
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index c4e3d51d49..4cfc6a04b3 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -362,9 +362,9 @@ static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx)
callData->args[0] = w;
try {
callback->call(callData);
- } catch (Exception &) {
+ } catch (...) {
db.rollback();
- throw;
+ ctx->rethrowException();
}
if (!db.commit()) {
db.rollback();
@@ -418,10 +418,10 @@ static ReturnedValue qmlsqldatabase_transaction_shared(SimpleCallContext *ctx, b
callData->args[0] = w;
try {
callback->call(callData);
- } catch (Exception &) {
+ } catch (...) {
w->inTransaction = false;
db.rollback();
- throw;
+ ctx->rethrowException();
}
w->inTransaction = false;
diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp
index 3d0954768a..f73674fd38 100644
--- a/src/imports/testlib/main.cpp
+++ b/src/imports/testlib/main.cpp
@@ -114,7 +114,7 @@ public Q_SLOTS:
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine->handle());
QV4::Scope scope(v4);
- QVector<QV4::ExecutionEngine::StackFrame> stack = v4->stackTrace(frameIndex + 2);
+ QVector<QV4::StackFrame> stack = v4->stackTrace(frameIndex + 2);
if (stack.size() > frameIndex + 1) {
QV4::ScopedValue s(scope, v4->newString(stack.at(frameIndex + 1).source));
return QQmlV4Handle(s);
@@ -126,7 +126,7 @@ public Q_SLOTS:
QQmlEngine *engine = qmlEngine(this);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine->handle());
- QVector<QV4::ExecutionEngine::StackFrame> stack = v4->stackTrace(frameIndex + 2);
+ QVector<QV4::StackFrame> stack = v4->stackTrace(frameIndex + 2);
if (stack.size() > frameIndex + 1)
return stack.at(frameIndex + 1).line;
return -1;
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index 6afbee2400..850dc64b99 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -796,22 +796,24 @@ static void *tryWrapper(ExecutionContext *context, void *localsPtr, MiddleOfFunc
exceptionVar = Primitive::undefinedValue();
void *addressToContinueAt = 0;
SafeValue *jsStackTop = context->engine->jsStackTop;
+ bool caughtException = false;
try {
addressToContinueAt = tryBody(context, localsPtr);
- } catch (Exception& ex) {
+ } catch (...) {
context->engine->jsStackTop = jsStackTop;
- ex.accept(context);
- exceptionVar = ex.value();
+ exceptionVar = context->catchException();
+ caughtException = true;
+ }
+ // Can't nest try { ... } catch (...) {} due to inability of nesting foreign exceptions
+ // with common CXX ABI.
+ if (caughtException) {
try {
- QV4::Scope scope(context);
- QV4::ScopedValue exception(scope, ex.value());
- ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, exception, context);
+ ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, exceptionVar, context);
addressToContinueAt = catchBody(catchContext, localsPtr);
context = __qmljs_builtin_pop_scope(catchContext);
- } catch (Exception& ex) {
+ } catch (...) {
context->engine->jsStackTop = jsStackTop;
- exceptionVar = ex.value();
- ex.accept(context);
+ exceptionVar = context->catchException();
addressToContinueAt = catchBody(context, localsPtr);
}
}
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 57647a49d3..d42cabd81c 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -269,9 +269,8 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
script.inheritContext = true;
script.parse();
result = script.run();
- } catch (QV4::Exception& ex) {
- ex.accept(ctx);
- result = ex.value();
+ } catch (...) {
+ result = ctx->catchException();
}
return new QJSValuePrivate(d->m_v4Engine, result);
}
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 8bcdccc507..ba94afadc6 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -380,8 +380,8 @@ double QJSValue::toNumber() const
QV4::ExecutionContext *ctx = d->engine ? d->engine->current : 0;
try {
return d->value.toNumber();
- } catch (Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
return 0;
}
}
@@ -403,8 +403,8 @@ bool QJSValue::toBool() const
QV4::ExecutionContext *ctx = d->engine ? d->engine->current : 0;
try {
return d->value.toBoolean();
- } catch (Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
return false;
}
}
@@ -426,8 +426,8 @@ qint32 QJSValue::toInt() const
QV4::ExecutionContext *ctx = d->engine ? d->engine->current : 0;
try {
return d->value.toInt32();
- } catch (Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
return 0;
}
}
@@ -449,8 +449,8 @@ quint32 QJSValue::toUInt() const
QV4::ExecutionContext *ctx = d->engine ? d->engine->current : 0;
try {
return d->value.toUInt32();
- } catch (Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
return 0;
}
}
@@ -521,9 +521,8 @@ QJSValue QJSValue::call(const QJSValueList &args)
QV4::ExecutionContext *ctx = engine->current;
try {
result = f->call(callData);
- } catch (Exception &e) {
- e.accept(ctx);
- result = e.value();
+ } catch (...) {
+ result = ctx->catchException();
}
return new QJSValuePrivate(engine, result);
@@ -578,9 +577,8 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
QV4::ExecutionContext *ctx = engine->current;
try {
result = f->call(callData);
- } catch (Exception &e) {
- e.accept(ctx);
- result = e.value();
+ } catch (...) {
+ result = ctx->catchException();
}
return new QJSValuePrivate(engine, result);
@@ -627,9 +625,8 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
QV4::ExecutionContext *ctx = engine->current;
try {
result = f->construct(callData);
- } catch (Exception &e) {
- e.accept(ctx);
- result = e.value();
+ } catch (...) {
+ result = ctx->catchException();
}
return new QJSValuePrivate(engine, result);
@@ -819,9 +816,8 @@ QJSValue QJSValue::property(const QString& name) const
QV4::ScopedValue result(scope);
try {
result = o->get(s);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- result = e.value();
+ } catch (...) {
+ result = ctx->catchException();
}
return new QJSValuePrivate(engine, result);
}
@@ -853,9 +849,8 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
QV4::ScopedValue result(scope);
try {
result = arrayIndex == UINT_MAX ? o->get(engine->id_uintMax) : o->getIndexed(arrayIndex);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- result = e.value();
+ } catch (...) {
+ result = ctx->catchException();
}
return new QJSValuePrivate(engine, result);
}
@@ -899,8 +894,8 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
try {
QV4::ScopedValue v(scope, value.d->getValue(engine));
o->put(s, v);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
}
}
@@ -934,8 +929,8 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
o->putIndexed(arrayIndex, v);
else
o->put(engine->id_uintMax, v);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
}
}
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index e1786f06cd..fd5f709e14 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -211,8 +211,8 @@ QJSValue QJSValueIterator::value() const
return QJSValue();
}
return new QJSValuePrivate(engine, v);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
return QJSValue();
}
}
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 0e08f025c2..78bf662c26 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -48,6 +48,7 @@
#include <qv4argumentsobject_p.h>
#include "qv4function_p.h"
#include "qv4errorobject_p.h"
+#include "qv4exception_p.h"
using namespace QV4;
@@ -597,7 +598,7 @@ ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectR
void ExecutionContext::throwError(const ValueRef value)
{
- __qmljs_throw(this, value);
+ Exception::throwException(this, value);
}
void ExecutionContext::throwError(const QString &message)
@@ -644,6 +645,30 @@ void ExecutionContext::throwUnimplemented(const QString &message)
throwError(v);
}
+ReturnedValue ExecutionContext::catchException(StackTrace *trace)
+{
+ if (!engine->hasException)
+ throw;
+ while (engine->current != this)
+ engine->popContext();
+ if (trace)
+ *trace = engine->exceptionStackTrace;
+ engine->exceptionStackTrace.clear();
+ engine->hasException = false;
+ ReturnedValue res = engine->exceptionValue.asReturnedValue();
+ engine->exceptionValue = Encode::undefined();
+ return res;
+}
+
+void ExecutionContext::rethrowException()
+{
+ if (engine->hasException) {
+ while (engine->current != this)
+ engine->popContext();
+ }
+ throw;
+}
+
void ExecutionContext::throwReferenceError(const ValueRef value)
{
Scope scope(this);
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index d368dc6c81..2535161713 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -143,6 +143,10 @@ struct Q_QML_EXPORT ExecutionContext
ReturnedValue getPropertyAndBase(const StringRef name, ObjectRef base);
bool deleteProperty(const StringRef name);
+ // Can only be called from within catch(...), rethrows if no JS exception.
+ ReturnedValue catchException(StackTrace *trace = 0);
+ void Q_NORETURN rethrowException();
+
void mark();
inline CallContext *asCallContext();
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 8032197174..ba7241b081 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -67,6 +67,7 @@
#include "qv4qobjectwrapper_p.h"
#include "qv4qmlextensions_p.h"
#include "qv4stacktrace_p.h"
+#include "qv4exception_p.h"
#ifdef V4_ENABLE_JIT
#include "qv4isel_masm_p.h"
@@ -103,6 +104,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
MemoryManager::GCBlocker gcBlocker(memoryManager);
exceptionValue = Encode::undefined();
+ hasException = false;
if (!factory) {
@@ -572,7 +574,7 @@ namespace {
{
}
- void resolve(ExecutionEngine::StackFrame *frame, ExecutionContext *context, Function *function)
+ void resolve(StackFrame *frame, ExecutionContext *context, Function *function)
{
if (context->interpreterInstructionPointer) {
qptrdiff offset = *context->interpreterInstructionPointer - 1 - function->codeData;
@@ -589,7 +591,7 @@ namespace {
};
}
-QVector<ExecutionEngine::StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
+QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
{
LineNumberResolver lineNumbers(this);
@@ -628,7 +630,7 @@ QVector<ExecutionEngine::StackFrame> ExecutionEngine::stackTrace(int frameLimit)
return stack;
}
-ExecutionEngine::StackFrame ExecutionEngine::currentStackFrame() const
+StackFrame ExecutionEngine::currentStackFrame() const
{
StackFrame frame;
frame.line = -1;
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 79a4d3bef6..9a83ddc2a2 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -111,6 +111,7 @@ class MultiplyWrappedQObjectMap;
class RegExp;
class RegExpCache;
struct QmlExtensions;
+struct Exception;
struct Q_QML_EXPORT ExecutionEngine
{
@@ -237,6 +238,8 @@ struct Q_QML_EXPORT ExecutionEngine
RegExpCache *regExpCache;
SafeValue exceptionValue;
+ bool hasException;
+ StackTrace exceptionStackTrace;
// Scarce resources are "exceptionally high cost" QVariant types where allowing the
// normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
@@ -305,13 +308,6 @@ struct Q_QML_EXPORT ExecutionEngine
Returned<Object> *qmlContextObject() const;
- struct StackFrame {
- QString source;
- QString function;
- int line;
- int column;
- };
- typedef QVector<StackFrame> StackTrace;
StackTrace stackTrace(int frameLimit = -1) const;
StackFrame currentStackFrame() const;
QUrl resolvedUrl(const QString &file);
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index b247c1533d..58375ea51e 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -152,7 +152,7 @@ ErrorObject::ErrorObject(InternalClass *ic, const QString &message, const QStrin
defineDefaultProperty(QStringLiteral("name"), (s = ic->engine->newString(className())));
stackTrace = ic->engine->stackTrace();
- ExecutionEngine::StackFrame frame;
+ StackFrame frame;
frame.source = fileName;
frame.line = line;
frame.column = column;
@@ -177,7 +177,7 @@ ReturnedValue ErrorObject::method_get_stack(SimpleCallContext *ctx)
for (int i = 0; i < This->stackTrace.count(); ++i) {
if (i > 0)
trace += QLatin1Char('\n');
- const ExecutionEngine::StackFrame &frame = This->stackTrace[i];
+ const StackFrame &frame = This->stackTrace[i];
trace += frame.function;
trace += QLatin1Char('@');
trace += frame.source;
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index d48edfa15e..ff43f54f3e 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -70,7 +70,7 @@ struct ErrorObject: Object {
SyntaxErrorObject *asSyntaxError();
- ExecutionEngine::StackTrace stackTrace;
+ StackTrace stackTrace;
String *stack;
static ReturnedValue method_get_stack(SimpleCallContext *ctx);
diff --git a/src/qml/jsruntime/qv4exception.cpp b/src/qml/jsruntime/qv4exception.cpp
index 64e6bef1fd..f55dc949a9 100644
--- a/src/qml/jsruntime/qv4exception.cpp
+++ b/src/qml/jsruntime/qv4exception.cpp
@@ -58,6 +58,17 @@ using namespace QV4;
void Exception::throwException(ExecutionContext *context, const ValueRef value)
{
+ ExecutionEngine *engine = context->engine;
+ Q_ASSERT(!engine->hasException);
+ engine->hasException = true;
+ engine->exceptionValue = value;
+ QV4::Scope scope(engine);
+ QV4::Scoped<ErrorObject> error(scope, value);
+ if (!!error)
+ engine->exceptionStackTrace = error->stackTrace;
+ else
+ engine->exceptionStackTrace = engine->stackTrace();
+
if (context->engine->debugger)
context->engine->debugger->aboutToThrow(value);
@@ -83,48 +94,16 @@ void Exception::throwException(ExecutionContext *context, const ValueRef value)
printf("stack walked. throwing exception now...\n");
#endif
- throwInternal(context, value);
-}
-
-Exception::Exception(ExecutionContext *throwingContext, const ValueRef exceptionValue)
- : e(throwingContext->engine)
-{
- e->exceptionValue = exceptionValue;
- this->throwingContext = throwingContext->engine->current;
- accepted = false;
- if (ErrorObject *error = exceptionValue->asErrorObject())
- m_stackTrace = error->stackTrace;
- else
- m_stackTrace = throwingContext->engine->stackTrace();
-}
-
-Exception::~Exception()
-{
- assert(accepted);
- e->exceptionValue = Primitive::undefinedValue();
-}
-
-void Exception::accept(ExecutionContext *catchingContext)
-{
- assert(!accepted);
- accepted = true;
- partiallyUnwindContext(catchingContext);
-}
-
-void Exception::partiallyUnwindContext(ExecutionContext *catchingContext)
-{
- if (!throwingContext)
- return;
- ExecutionContext *context = throwingContext;
- while (context != catchingContext)
- context = context->engine->popContext();
- throwingContext = context;
+ throwInternal();
}
#if !defined(V4_CXX_ABI_EXCEPTION)
-void Exception::throwInternal(ExecutionContext *throwingContext, const ValueRef exceptionValue)
+struct DummyException
+{};
+
+void Exception::throwInternal()
{
- throw Exception(throwingContext, exceptionValue);
+ throw DummyException();
}
#endif
diff --git a/src/qml/jsruntime/qv4exception_gcc.cpp b/src/qml/jsruntime/qv4exception_gcc.cpp
index 5eb5fc2178..0d230ea3fb 100644
--- a/src/qml/jsruntime/qv4exception_gcc.cpp
+++ b/src/qml/jsruntime/qv4exception_gcc.cpp
@@ -100,25 +100,30 @@ static void exception_cleanup(_Unwind_Reason_Code, _Unwind_Exception *ex)
}
}
+struct DummyException
+{
+ virtual ~DummyException() {}
+};
+
static void exception_destructor(void *ex)
{
- reinterpret_cast<QV4::Exception *>(ex)->~Exception();
+ reinterpret_cast<DummyException *>(ex)->~DummyException();
}
QT_BEGIN_NAMESPACE
using namespace QV4;
-void Exception::throwInternal(ExecutionContext *throwingContext, const ValueRef exceptionValue)
+void Exception::throwInternal()
{
void *rawException = abi::__cxa_allocate_exception(sizeof(QV4::Exception));
gcc_refcounted_compatible_exception *refCountedException = reinterpret_cast<gcc_refcounted_compatible_exception *>(rawException) - 1;
cxa_exception *exception = &refCountedException->x;
- (void)new (rawException) Exception(throwingContext, exceptionValue);
+ (void)new (rawException) DummyException();
refCountedException->refCount = 1;
- exception->typeInfo = const_cast<std::type_info*>(&typeid(Exception));
+ exception->typeInfo = const_cast<std::type_info*>(&typeid(DummyException));
exception->exceptionDestructor = &exception_destructor;
exception->unexpectedHandler = std::unexpected;
exception->terminateHandler = std::terminate;
diff --git a/src/qml/jsruntime/qv4exception_p.h b/src/qml/jsruntime/qv4exception_p.h
index a373ef205b..1f02d11f65 100644
--- a/src/qml/jsruntime/qv4exception_p.h
+++ b/src/qml/jsruntime/qv4exception_p.h
@@ -38,8 +38,8 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QV4EXCEPTION_GNU_P
-#define QV4EXCEPTION_GNU_P
+#ifndef QV4EXCEPTION_P
+#define QV4EXCEPTION_P
#include <qglobal.h>
#include "qv4value_p.h"
@@ -52,31 +52,12 @@ namespace QV4 {
struct Q_QML_EXPORT Exception {
static void Q_NORETURN throwException(ExecutionContext *throwingContext, const ValueRef exceptionValue);
- ~Exception();
-
- void accept(ExecutionContext *catchingContext);
-
- void partiallyUnwindContext(ExecutionContext *catchingContext);
-
- ReturnedValue value() const { return e->exceptionValue.asReturnedValue(); }
-
- ExecutionEngine::StackTrace stackTrace() const { return m_stackTrace; }
- ExecutionEngine *engine() const { return e; }
-
private:
- void *operator new(size_t, void *p) { return p; }
-
- explicit Exception(ExecutionContext *throwingContext, const ValueRef exceptionValue);
-
- ExecutionEngine *e;
- ExecutionContext *throwingContext;
- bool accepted;
- ExecutionEngine::StackTrace m_stackTrace;
- static void Q_NORETURN throwInternal(ExecutionContext *throwingContext, const ValueRef exceptionValue);
+ static void Q_NORETURN throwInternal();
};
} // namespace QV4
QT_END_NAMESPACE
-#endif // QV4EXCEPTION_GNU_P
+#endif // QV4EXCEPTION_P
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index ca984e0059..34ab5df73a 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -91,7 +91,7 @@ struct Function {
return codePtr(ctx, data);
} catch (...) {
ctx->engine->jsStackTop = stack;
- throw;
+ ctx->rethrowException();
}
}
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 7ef0b96f17..305efba1d6 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -450,9 +450,8 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
SAVE_JS_STACK(f->scope);
try {
result = f->function->code(ctx, f->function->codeData);
- } catch (Exception &ex) {
- ex.partiallyUnwindContext(context);
- throw;
+ } catch (...) {
+ context->rethrowException();
}
CHECK_JS_STACK(f->scope);
ctx->engine->popContext();
@@ -482,9 +481,8 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
SAVE_JS_STACK(f->scope);
try {
result = f->function->code(ctx, f->function->codeData);
- } catch (Exception &ex) {
- ex.partiallyUnwindContext(context);
- throw;
+ } catch (...) {
+ context->rethrowException();
}
CHECK_JS_STACK(f->scope);
ctx->engine->popContext();
@@ -553,9 +551,8 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
if (!result)
return obj.asReturnedValue();
return result.asReturnedValue();
- } catch (Exception &ex) {
- ex.partiallyUnwindContext(context);
- throw;
+ } catch (...) {
+ context->rethrowException();
}
}
@@ -581,9 +578,8 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
SAVE_JS_STACK(f->scope);
try {
result = f->function->code(ctx, f->function->codeData);
- } catch (Exception &ex) {
- ex.partiallyUnwindContext(context);
- throw;
+ } catch (...) {
+ context->rethrowException();
}
CHECK_JS_STACK(f->scope);
ctx->engine->popContext();
@@ -625,9 +621,8 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
ScopedValue result(scope);
try {
result = f->code(&ctx);
- } catch (Exception &ex) {
- ex.partiallyUnwindContext(context);
- throw;
+ } catch (...) {
+ context->rethrowException();
}
context->engine->popContext();
@@ -650,9 +645,8 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
ScopedValue result(scope);
try {
result = f->code(&ctx, f->index);
- } catch (Exception &ex) {
- ex.partiallyUnwindContext(context);
- throw;
+ } catch (...) {
+ context->rethrowException();
}
context->engine->popContext();
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 01c5245a54..3569247459 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -43,7 +43,7 @@
#define QV4GLOBAL_H
#include <QtCore/qglobal.h>
-
+#include <QString>
#include <qtqmlglobal.h>
#if defined(Q_CC_MSVC)
@@ -232,6 +232,14 @@ struct PropertyAttributes
}
};
+struct StackFrame {
+ QString source;
+ QString function;
+ int line;
+ int column;
+};
+typedef QVector<StackFrame> StackTrace;
+
}
Q_DECLARE_TYPEINFO(QV4::PropertyAttributes, Q_PRIMITIVE_TYPE);
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index cbf6ddc1c6..a465fdc729 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -412,13 +412,11 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
ScopedValue result(scope);
try {
result = function->code(ctx, function->codeData);
- } catch (Exception &ex) {
+ } catch (...) {
ctx->strictMode = cstrict;
ctx->currentEvalCode = evalCode.next;
ctx->compilationUnit = oldCompilationUnit;
- if (strictMode)
- ex.partiallyUnwindContext(parentContext);
- throw;
+ ctx->rethrowException();
}
ctx->strictMode = cstrict;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 37db745622..44ba05990b 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -115,8 +115,8 @@ void QV4Include::callback(const QV4::ValueRef callback, const QV4::ValueRef stat
callData->thisObject = v4->globalObject->asReturnedValue();
callData->args[0] = status;
f->call(callData);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
}
}
@@ -162,10 +162,9 @@ void QV4Include::finished()
script.parse();
script.run();
resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Ok)));
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ QV4::ScopedValue ex(scope, ctx->catchException());
resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Exception)));
- QV4::ScopedValue ex(scope, e.value());
resultObj->put(QV4::ScopedString(scope, v4->newString("exception")), ex);
}
} else {
@@ -228,10 +227,9 @@ QV4::ReturnedValue QV4Include::method_include(QV4::SimpleCallContext *ctx)
script.parse();
script.run();
result = resultValue(v4, Ok);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ QV4::ScopedValue ex(scope, ctx->catchException());
result = resultValue(v4, Exception);
- QV4::ScopedValue ex(scope, e.value());
result->asObject()->put(QV4::ScopedString(scope, v4->newString("exception")), ex);
}
} else {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 8be1343ac5..6e474ecc5d 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -453,7 +453,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
// binding assignment.
QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine);
- QV4::ExecutionEngine::StackFrame frame = ctx->engine->currentStackFrame();
+ QV4::StackFrame frame = ctx->engine->currentStackFrame();
newBinding = new QQmlBinding(value, object, callingQmlContext, frame.source,
qmlSourceCoordinate(frame.line), qmlSourceCoordinate(frame.column));
@@ -723,10 +723,8 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
try {
f->call(callData);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
if (error.description().isEmpty())
error.setDescription(QString(QLatin1String("Unknown exception occurred during evaluation of connected function: %1")).arg(f->name->toQString()));
QQmlEnginePrivate::get(v4->v8Engine->engine())->warning(error);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 6002346678..b8b62c1bb7 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -49,7 +49,6 @@
#include "qv4argumentsobject_p.h"
#include "qv4lookup_p.h"
#include "qv4function_p.h"
-#include "qv4exception_p.h"
#include "private/qlocale_tools_p.h"
#include "qv4scopedvalue_p.h"
@@ -878,7 +877,7 @@ ReturnedValue __qmljs_construct_property(ExecutionContext *context, const ValueR
void __qmljs_throw(ExecutionContext *context, const ValueRef value)
{
- Exception::throwException(context, value);
+ context->throwError(value);
}
ReturnedValue __qmljs_builtin_typeof(ExecutionContext *ctx, const ValueRef value)
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 0dddbe87e7..e320656664 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -252,11 +252,11 @@ ReturnedValue Script::run()
QV4::ScopedValue result(valueScope);
try {
result = vmFunction->code(scope, vmFunction->codeData);
- } catch (Exception &e) {
+ } catch (...) {
scope->strictMode = strict;
scope->lookups = oldLookups;
scope->compilationUnit = oldCompilationUnit;
- throw;
+ scope->rethrowException();
}
scope->lookups = oldLookups;
@@ -379,8 +379,8 @@ QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &scr
try {
qmlScript.parse();
return qmlScript.run();
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
}
return Encode::undefined();
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 5c8f7db97e..8d3dd97e83 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -63,7 +63,7 @@ static void generateWarning(QV4::ExecutionContext *ctx, const QString& descripti
QQmlError retn;
retn.setDescription(description);
- QV4::ExecutionEngine::StackFrame frame = ctx->engine->currentStackFrame();
+ QV4::StackFrame frame = ctx->engine->currentStackFrame();
retn.setLine(frame.line);
retn.setUrl(QUrl(frame.source));
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index 7d3214e8f8..d38897c37c 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -283,8 +283,8 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
try {
str = s->asString();
val = o->get(str);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
}
serialize(data, val, engine);
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 623f9ae3b6..3c9db5edea 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -124,19 +124,24 @@ QString Value::toQStringNoThrow() const
{
ExecutionContext *ctx = objectValue()->internalClass->engine->current;
Scope scope(ctx);
+ ScopedValue ex(scope);
+ bool caughtException = false;
try {
ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), STRING_HINT));
if (prim->isPrimitive())
return prim->toQStringNoThrow();
- } catch (Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ex = ctx->catchException();
+ caughtException = true;
+ }
+ // Can't nest try/catch due to CXX ABI limitations for foreign exception nesting.
+ if (caughtException) {
try {
- ScopedValue ex(scope, e.value());
ScopedValue prim(scope, __qmljs_to_primitive(ex, STRING_HINT));
if (prim->isPrimitive())
return prim->toQStringNoThrow();
- } catch(Exception &e) {
- e.accept(ctx);
+ } catch(...) {
+ ctx->catchException();
}
}
return QString();
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index a3fc43b39c..e933376a13 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -368,14 +368,17 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_BEGIN_INSTR(EnterTry)
VALUE(instr.exceptionVar) = QV4::Primitive::undefinedValue();
+ bool caughtException = false;
try {
const uchar *tryCode = ((uchar *)&instr.tryOffset) + instr.tryOffset;
run(context, tryCode, stack, stackSize);
code = tryCode;
context->interpreterInstructionPointer = &code;
- } catch (QV4::Exception &ex) {
- ex.accept(context);
- STOREVALUE(instr.exceptionVar, ex.value());
+ } catch (...) {
+ STOREVALUE(instr.exceptionVar, context->catchException());
+ caughtException = true;
+ }
+ if (caughtException) {
try {
QV4::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(runtimeStrings[instr.exceptionVarName], VALUEPTR(instr.exceptionVar), context);
const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
@@ -383,9 +386,8 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *&code,
code = catchCode;
context->interpreterInstructionPointer = &code;
context = __qmljs_builtin_pop_scope(catchContext);
- } catch (QV4::Exception &ex) {
- ex.accept(context);
- STOREVALUE(instr.exceptionVar, ex.value());
+ } catch (...) {
+ STOREVALUE(instr.exceptionVar, context->catchException());
const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
run(context, catchCode, stack, stackSize);
code = catchCode;
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 2d3e9006b2..c4bc242bd9 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1542,10 +1542,8 @@ void QmlIncubatorObject::statusChanged(Status s)
callData->thisObject = this;
callData->args[0] = QV4::Primitive::fromUInt32(s);
f->call(callData);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlJavaScriptExpression::exceptionToError(e, error);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v8->engine()), error);
}
}
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp
index 0c8e46bd8d..3a4179717a 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qml/qqmlerror.cpp
@@ -46,6 +46,8 @@
#include <QtCore/qfile.h>
#include <QtCore/qstringlist.h>
+#include <private/qv4errorobject_p.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -136,6 +138,28 @@ QQmlError::~QQmlError()
delete d; d = 0;
}
+QQmlError QQmlError::catchJavaScriptException(QV4::ExecutionContext *context)
+{
+ QV4::StackTrace trace;
+ QV4::Scope scope(context);
+ QV4::ScopedValue exception(scope, context->catchException(&trace));
+ QQmlError error;
+ if (!trace.isEmpty()) {
+ QV4::StackFrame frame = trace.first();
+ error.setUrl(QUrl(frame.source));
+ error.setLine(frame.line);
+ error.setColumn(frame.column);
+ }
+ QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception);
+ if (!!errorObj && errorObj->asSyntaxError()) {
+ QV4::ScopedString m(scope, errorObj->engine()->newString("message"));
+ QV4::ScopedValue v(scope, errorObj->get(m));
+ error.setDescription(v->toQStringNoThrow());
+ } else
+ error.setDescription(exception->toQStringNoThrow());
+ return error;
+}
+
/*!
Returns true if this error is valid, otherwise false.
*/
diff --git a/src/qml/qml/qqmlerror.h b/src/qml/qml/qqmlerror.h
index e69b3c15ba..50491b911c 100644
--- a/src/qml/qml/qqmlerror.h
+++ b/src/qml/qml/qqmlerror.h
@@ -49,6 +49,10 @@
QT_BEGIN_NAMESPACE
+namespace QV4 {
+struct ExecutionContext;
+}
+
class QDebug;
class QQmlErrorPrivate;
class Q_QML_EXPORT QQmlError
@@ -59,6 +63,9 @@ public:
QQmlError &operator=(const QQmlError &);
~QQmlError();
+ // Use only inside catch(...) -- will re-throw if no JS exception
+ static QQmlError catchJavaScriptException(QV4::ExecutionContext *context);
+
bool isValid() const;
QUrl url() const;
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 938b14a15f..8751d9c500 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -84,18 +84,9 @@ void QQmlDelayedError::setErrorObject(QObject *object)
m_error.setObject(object);
}
-void QQmlDelayedError::setError(const QV4::Exception &e)
+void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionContext *context)
{
- m_error.setDescription(QV4::Value::fromReturnedValue(e.value()).toQStringNoThrow());
- QV4::ExecutionEngine::StackTrace trace = e.stackTrace();
- if (!trace.isEmpty()) {
- QV4::ExecutionEngine::StackFrame frame = trace.first();
- m_error.setUrl(QUrl(frame.source));
- m_error.setLine(frame.line);
- m_error.setColumn(frame.column);
- }
-
- m_error.setColumn(-1);
+ m_error = QQmlError::catchJavaScriptException(context);
}
@@ -183,19 +174,13 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
if (!watcher.wasDeleted() && hasDelayedError())
delayedError()->clearError();
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QV4::ScopedValue ex(scope, e.value());
+ } catch (...) {
+ if (watcher.wasDeleted())
+ ctx->catchException(); // ignore exception
+ else
+ delayedError()->catchJavaScriptException(ctx);
if (isUndefined)
*isUndefined = true;
- if (!watcher.wasDeleted()) {
- if (!ex->isUndefined()) {
- delayedError()->setError(e);
- } else {
- if (hasDelayedError())
- delayedError()->clearError();
- }
- }
}
if (capture.errorString) {
@@ -302,27 +287,6 @@ QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
return &m_vtable.value();
}
-void QQmlJavaScriptExpression::exceptionToError(const QV4::Exception &e, QQmlError &error)
-{
- QV4::Scope scope(e.engine());
- QV4::ExecutionEngine::StackTrace trace = e.stackTrace();
- if (!trace.isEmpty()) {
- QV4::ExecutionEngine::StackFrame frame = trace.first();
- error.setUrl(QUrl(frame.source));
- error.setLine(frame.line);
- error.setColumn(frame.column);
- }
- QV4::Scoped<QV4::ErrorObject> errorObj(scope, e.value());
- if (!!errorObj && errorObj->asSyntaxError()) {
- QV4::ScopedString m(scope, errorObj->engine()->newString("message"));
- QV4::ScopedValue v(scope, errorObj->get(m));
- error.setDescription(v->toQStringNoThrow());
- } else {
- QV4::ScopedValue v(scope, e.value());
- error.setDescription(v->toQStringNoThrow());
- }
-}
-
QV4::ReturnedValue
QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObject,
const QString &code, const QString &filename, quint16 line,
@@ -341,10 +305,8 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
try {
script.parse();
result = script.run();
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
if (error.description().isEmpty())
error.setDescription(QLatin1String("Exception occurred during function evaluation"));
if (error.line() == -1)
@@ -377,10 +339,8 @@ QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, Q
try {
script.parse();
result = script.qmlBinding();
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
if (error.description().isEmpty())
error.setDescription(QLatin1String("Exception occurred during function evaluation"));
if (error.line() == -1)
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 031cc2d2c1..efea961bd2 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -61,6 +61,10 @@
QT_BEGIN_NAMESPACE
+namespace QV4 {
+struct ExecutionContext;
+}
+
class QQmlDelayedError
{
public:
@@ -85,7 +89,8 @@ public:
void setErrorDescription(const QString &description);
void setErrorObject(QObject *object);
- void setError(const QV4::Exception &e);
+ // Call only from catch(...) -- will re-throw if no JS exception
+ void catchJavaScriptException(QV4::ExecutionContext *context);
private:
@@ -142,7 +147,6 @@ public:
void clearGuards();
QQmlDelayedError *delayedError();
- static void exceptionToError(const QV4::Exception &e, QQmlError &);
static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope,
const QString &code, const QString &filename,
quint16 line,
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 3209d5a454..76cb0ce38f 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2766,10 +2766,8 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
try {
m_program->qml = qmlglobal;
m_program->run();
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
if (error.isValid())
ep->warning(error);
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 656e9dfe3a..6477f63daf 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -372,7 +372,7 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v
cacheData.valueTypeCoreIndex = index;
cacheData.valueTypePropType = p.userType();
- QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame();
+ QV4::StackFrame frame = v4->currentStackFrame();
newBinding = new QQmlBinding(value, reference->object, context,
frame.source, qmlSourceCoordinate(frame.line), qmlSourceCoordinate(frame.column));
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index ecc6287823..7c033acf47 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -944,10 +944,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
try {
result = function->call(callData);
if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result, 0);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
if (error.isValid())
ep->warning(error);
if (a[0]) *(QVariant *)a[0] = QVariant();
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 2b9bd6196f..6aeabf9221 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1105,7 +1105,6 @@ private:
PersistentValue m_me;
void dispatchCallback(const ValueRef me);
- void printError(const Exception &e);
int m_status;
QString m_statusText;
@@ -1568,20 +1567,12 @@ void QQmlXMLHttpRequest::dispatchCallback(const ValueRef me)
// 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(Exception &e) {
- e.accept(ctx);
- printError(e);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
+ QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v4->v8Engine->engine()), error);
}
}
-// Must have a handle scope
-void QQmlXMLHttpRequest::printError(const Exception &e)
-{
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
- QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v4->v8Engine->engine()), error);
-}
-
void QQmlXMLHttpRequest::destroyNetwork()
{
if (m_network) {
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index a53a1ef1ec..595c75da45 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1333,10 +1333,10 @@ enum ConsoleLogTypes {
static QString jsStack(QV4::ExecutionEngine *engine) {
QString stack;
- QVector<QV4::ExecutionEngine::StackFrame> stackTrace = engine->stackTrace(10);
+ QVector<QV4::StackFrame> stackTrace = engine->stackTrace(10);
for (int i = 0; i < stackTrace.count(); i++) {
- const QV4::ExecutionEngine::StackFrame &frame = stackTrace.at(i);
+ const QV4::StackFrame &frame = stackTrace.at(i);
QString stackFrame;
if (frame.column >= 0)
@@ -1377,7 +1377,7 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, SimpleCallCont
result.append(jsStack(v4));
}
- QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame();
+ QV4::StackFrame frame = v4->currentStackFrame();
QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData());
switch (logType) {
case Log:
@@ -1418,7 +1418,7 @@ QV4::ReturnedValue ConsoleObject::method_profile(SimpleCallContext *ctx)
QString title;
QV4::ExecutionEngine *v4 = ctx->engine;
- QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame();
+ QV4::StackFrame frame = v4->currentStackFrame();
QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData());
if (QQmlProfilerService::startProfiling()) {
QV8ProfilerService::instance()->startProfiling(title);
@@ -1440,7 +1440,7 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(SimpleCallContext *ctx)
QV4::ExecutionEngine *v4 = ctx->engine;
- QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame();
+ QV4::StackFrame frame = v4->currentStackFrame();
QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData());
if (QQmlProfilerService::stopProfiling()) {
@@ -1495,7 +1495,7 @@ QV4::ReturnedValue ConsoleObject::method_count(SimpleCallContext *ctx)
QV4::ExecutionEngine *v4 = ctx->engine;
QV8Engine *v8engine = ctx->engine->v8Engine;
- QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame();
+ QV4::StackFrame frame = v4->currentStackFrame();
QString scriptName = frame.source;
@@ -1517,7 +1517,7 @@ QV4::ReturnedValue ConsoleObject::method_trace(SimpleCallContext *ctx)
QString stack = jsStack(v4);
- QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame();
+ QV4::StackFrame frame = v4->currentStackFrame();
QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData());
logger.debug("%s", qPrintable(stack));
@@ -1547,7 +1547,7 @@ QV4::ReturnedValue ConsoleObject::method_assert(SimpleCallContext *ctx)
QString stack = jsStack(v4);
- QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame();
+ QV4::StackFrame frame = v4->currentStackFrame();
QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData());
logger.critical("%s\n%s", qPrintable(message), qPrintable(stack));
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index f789f999a4..9b8616d5e7 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -258,9 +258,8 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i
callData->args[0] = QV4::Primitive::fromInt32(id);
callData->thisObject = global();
v = f->call(callData);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- v = e.value();
+ } catch (...) {
+ v = ctx->catchException();
}
return v.asReturnedValue();
}
@@ -367,10 +366,8 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
callData->args[0] = script->object.value();
callData->args[1] = value;
f->call(callData);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
reportScriptException(script, error);
}
}
@@ -406,10 +403,8 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
try {
program.parse();
program.run();
- } catch (QV4::Exception &e) {
- e.accept(ctx);
- QQmlError error;
- QQmlExpressionPrivate::exceptionToError(e, error);
+ } catch (...) {
+ QQmlError error = QQmlError::catchJavaScriptException(ctx);
reportScriptException(script, error);
}
} else {
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 82ceea9c46..ea8a1fe6c7 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -2280,8 +2280,8 @@ static inline bool evaluate_error(QV8Engine *engine, const QV4::ValueRef o, cons
d->args[0] = o;
d->thisObject = engine->global();
function->call(d);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
return true;
}
return false;
@@ -2310,8 +2310,8 @@ static inline bool evaluate_value(QV8Engine *engine, const QV4::ValueRef o,
d->thisObject = engine->global();
value = function->call(d);
return __qmljs_strict_equal(value, result);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
}
return false;
}
@@ -2335,8 +2335,8 @@ static inline QV4::ReturnedValue evaluate(QV8Engine *engine, const QV4::ValueRef
d->args[0] = o;
d->thisObject = engine->global();
return function->call(d);
- } catch (QV4::Exception &e) {
- e.accept(ctx);
+ } catch (...) {
+ ctx->catchException();
}
return QV4::Encode::undefined();
}
diff --git a/tools/v4/main.cpp b/tools/v4/main.cpp
index 38329b8289..3d79e8990f 100644
--- a/tools/v4/main.cpp
+++ b/tools/v4/main.cpp
@@ -113,10 +113,10 @@ DEFINE_MANAGED_VTABLE(GC);
} // builtins
-static void showException(QV4::ExecutionContext *ctx, const QV4::Exception &exception)
+static void showException(QV4::ExecutionContext *ctx, const QV4::ValueRef exception, const QV4::StackTrace &trace)
{
QV4::Scope scope(ctx);
- QV4::ScopedValue ex(scope, exception.value());
+ QV4::ScopedValue ex(scope, *exception);
QV4::ErrorObject *e = ex->asErrorObject();
if (!e) {
std::cerr << "Uncaught exception: " << qPrintable(ex->toString(ctx)->toQString()) << std::endl;
@@ -126,7 +126,7 @@ static void showException(QV4::ExecutionContext *ctx, const QV4::Exception &exce
std::cerr << "Uncaught exception: " << qPrintable(message->toQStringNoThrow()) << std::endl;
}
- foreach (const QV4::ExecutionEngine::StackFrame &frame, exception.stackTrace()) {
+ foreach (const QV4::StackFrame &frame, trace) {
std::cerr << " at " << qPrintable(frame.function) << " (" << qPrintable(frame.source);
if (frame.line >= 0)
std::cerr << ":" << frame.line;
@@ -212,9 +212,10 @@ int main(int argc, char *argv[])
if (! qgetenv("SHOW_EXIT_VALUE").isEmpty())
std::cout << "exit value: " << qPrintable(result->toString(ctx)->toQString()) << std::endl;
}
- } catch (QV4::Exception& ex) {
- ex.accept(ctx);
- showException(ctx, ex);
+ } catch (...) {
+ QV4::StackTrace trace;
+ QV4::ScopedValue ex(scope, ctx->catchException(&trace));
+ showException(ctx, ex, trace);
return EXIT_FAILURE;
}