From af22149dd8daf593182fec978f15dc1667c9cf8d Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 21 Oct 2013 09:57:58 +0200 Subject: Avoid side effects when en exception has been thrown. We don't want to check for exceptions after every single line on our runtime methods. A better way to handle this is to add the check in all methods that have direct side effects (as e.g. writing to a property of the JS stack). We also need to return whereever we throw an exception. To simplify the code, ExecutionContext::throwXxx methods now return a ReturnedValue (always undefined) for convenience. Change-Id: Ide6c804f819c731a3f14c6c43121d08029c9fb90 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4argumentsobject.cpp | 6 +-- src/qml/jsruntime/qv4arrayobject.cpp | 62 ++++++++++++++++++----- src/qml/jsruntime/qv4booleanobject.cpp | 4 +- src/qml/jsruntime/qv4context.cpp | 51 ++++++++++--------- src/qml/jsruntime/qv4context_p.h | 22 ++++---- src/qml/jsruntime/qv4dateobject.cpp | 40 +++++++-------- src/qml/jsruntime/qv4engine.cpp | 6 +-- src/qml/jsruntime/qv4engine_p.h | 2 +- src/qml/jsruntime/qv4errorobject.cpp | 4 +- src/qml/jsruntime/qv4functionobject.cpp | 25 +++++----- src/qml/jsruntime/qv4functionobject_p.h | 3 +- src/qml/jsruntime/qv4globalobject.cpp | 11 ++-- src/qml/jsruntime/qv4jsonobject.cpp | 10 ++-- src/qml/jsruntime/qv4lookup.cpp | 4 +- src/qml/jsruntime/qv4managed.cpp | 9 ++-- src/qml/jsruntime/qv4numberobject.cpp | 26 ++++++---- src/qml/jsruntime/qv4object.cpp | 10 ++-- src/qml/jsruntime/qv4objectproto.cpp | 86 ++++++++++++++++++++++---------- src/qml/jsruntime/qv4qobjectwrapper.cpp | 15 +++--- src/qml/jsruntime/qv4regexpobject.cpp | 12 ++--- src/qml/jsruntime/qv4runtime.cpp | 76 +++++++++++++++++++++------- src/qml/jsruntime/qv4sequenceobject.cpp | 6 +-- src/qml/jsruntime/qv4stringobject.cpp | 44 ++++++++++++++-- src/qml/qml/qqmlcomponent.cpp | 10 ++-- src/qml/qml/qqmlcontextwrapper.cpp | 8 ++- src/qml/qml/qqmllistwrapper.cpp | 4 +- src/qml/qml/qqmllocale.cpp | 76 ++++++++++++++++++---------- src/qml/qml/qqmltypewrapper.cpp | 7 ++- src/qml/qml/qqmlvaluetypewrapper.cpp | 15 ++++-- src/qml/qml/qqmlxmlhttprequest.cpp | 42 +++++++++------- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 24 ++++----- src/qml/qml/v8/qv4domerrors_p.h | 2 +- src/qml/qml/v8/qv8engine_p.h | 4 +- src/qml/types/qqmldelegatemodel.cpp | 23 ++++----- src/qml/util/qqmladaptormodel.cpp | 16 +++--- 35 files changed, 485 insertions(+), 280 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 47b149c9d5..fb4fcb7b1a 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -139,7 +139,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const } if (ctx->strictMode && !result) - ctx->throwTypeError(); + return ctx->throwTypeError(); return result; } @@ -152,7 +152,7 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData) Scoped g(scope, static_cast(getter)); Scoped o(scope, callData->thisObject.as()); if (!o) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); Q_ASSERT(g->index < o->context->callData->argc); return o->context->argument(g->index); @@ -167,7 +167,7 @@ ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData) Scoped s(scope, static_cast(setter)); Scoped o(scope, callData->thisObject.as()); if (!o) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); Q_ASSERT(s->index < o->context->callData->argc); o->context->callData->args[s->index] = callData->argc ? callData->args[0].asReturnedValue() : Encode::undefined(); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 3913b9ffe7..b1308e12fb 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -65,7 +65,7 @@ ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData) len = callData->args[0].asArrayLength(&ok); if (!ok) - v4->current->throwRangeError(callData->args[0]); + return v4->current->throwRangeError(callData->args[0]); if (len < 0x1000) a->arrayReserve(len); @@ -141,6 +141,8 @@ ReturnedValue ArrayPrototype::method_toString(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject o(scope, ctx->callData->thisObject, ScopedObject::Convert); + if (ctx->engine->hasException) + return Encode::undefined(); ScopedString s(scope, ctx->engine->newString("join")); ScopedFunctionObject f(scope, o->get(s)); if (!!f) { @@ -162,6 +164,8 @@ ReturnedValue ArrayPrototype::method_concat(SimpleCallContext *ctx) ScopedObject result(scope, ctx->engine->newArrayObject()); ScopedObject thisObject(scope, ctx->callData->thisObject.toObject(ctx)); + if (!thisObject) + return Encode::undefined(); ScopedArrayObject instance(scope, thisObject); if (instance) { result->copyArrayData(instance.getPointer()); @@ -240,6 +244,8 @@ ReturnedValue ArrayPrototype::method_pop(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); if (!len) { @@ -262,6 +268,8 @@ ReturnedValue ArrayPrototype::method_push(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); if (len + ctx->callData->argc < len) { @@ -277,7 +285,7 @@ ReturnedValue ArrayPrototype::method_push(SimpleCallContext *ctx) instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen))); else { ScopedString str(scope, ctx->engine->newString(QStringLiteral("Array.prototype.push: Overflow"))); - ctx->throwRangeError(str); + return ctx->throwRangeError(str); } return Encode(newLen); } @@ -314,6 +322,8 @@ ReturnedValue ArrayPrototype::method_reverse(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint length = getLength(ctx, instance); int lo = 0, hi = length - 1; @@ -340,6 +350,8 @@ ReturnedValue ArrayPrototype::method_shift(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); if (!len) { @@ -394,6 +406,8 @@ ReturnedValue ArrayPrototype::method_slice(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject o(scope, ctx->callData->thisObject.toObject(ctx)); + if (!o) + return Encode::undefined(); Scoped result(scope, ctx->engine->newArrayObject()); uint len = getLength(ctx, o); @@ -433,6 +447,8 @@ ReturnedValue ArrayPrototype::method_sort(SimpleCallContext *ctx) { Scope scope(ctx); Scoped instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); @@ -445,6 +461,8 @@ ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); Scoped newArray(scope, ctx->engine->newArrayObject()); @@ -505,6 +523,8 @@ ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); ScopedValue v(scope); @@ -556,6 +576,8 @@ ReturnedValue ArrayPrototype::method_indexOf(SimpleCallContext *ctx) Scope scope(ctx); ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); if (!len) return Encode(-1); @@ -596,6 +618,8 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx) Scope scope(ctx); ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); if (!len) return Encode(-1); @@ -635,12 +659,14 @@ ReturnedValue ArrayPrototype::method_every(SimpleCallContext *ctx) { Scope scope(ctx); Scoped instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); Scoped callback(scope, ctx->argument(0)); if (!callback) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedCallData callData(scope, 3); callData->args[2] = instance; @@ -667,12 +693,14 @@ ReturnedValue ArrayPrototype::method_some(SimpleCallContext *ctx) { Scope scope(ctx); Scoped instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); Scoped callback(scope, ctx->argument(0)); if (!callback) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedCallData callData(scope, 3); callData->thisObject = ctx->argument(1); @@ -699,12 +727,14 @@ ReturnedValue ArrayPrototype::method_forEach(SimpleCallContext *ctx) { Scope scope(ctx); Scoped instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); Scoped callback(scope, ctx->argument(0)); if (!callback) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedCallData callData(scope, 3); callData->thisObject = ctx->argument(1); @@ -728,12 +758,14 @@ ReturnedValue ArrayPrototype::method_map(SimpleCallContext *ctx) { Scope scope(ctx); Scoped instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); Scoped callback(scope, ctx->argument(0)); if (!callback) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped a(scope, ctx->engine->newArrayObject()); a->arrayReserve(len); @@ -763,12 +795,14 @@ ReturnedValue ArrayPrototype::method_filter(SimpleCallContext *ctx) { Scope scope(ctx); Scoped instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); Scoped callback(scope, ctx->argument(0)); if (!callback) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped a(scope, ctx->engine->newArrayObject()); a->arrayReserve(len); @@ -802,12 +836,14 @@ ReturnedValue ArrayPrototype::method_reduce(SimpleCallContext *ctx) { Scope scope(ctx); Scoped instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); Scoped callback(scope, ctx->argument(0)); if (!callback) - ctx->throwTypeError(); + return ctx->throwTypeError(); uint k = 0; ScopedValue acc(scope); @@ -824,7 +860,7 @@ ReturnedValue ArrayPrototype::method_reduce(SimpleCallContext *ctx) ++k; } if (!kPresent) - ctx->throwTypeError(); + return ctx->throwTypeError(); } ScopedCallData callData(scope, 4); @@ -850,16 +886,18 @@ ReturnedValue ArrayPrototype::method_reduceRight(SimpleCallContext *ctx) { Scope scope(ctx); Scoped instance(scope, ctx->callData->thisObject.toObject(ctx)); + if (!instance) + return Encode::undefined(); uint len = getLength(ctx, instance); Scoped callback(scope, ctx->argument(0)); if (!callback) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (len == 0) { if (ctx->callData->argc == 1) - ctx->throwTypeError(); + return ctx->throwTypeError(); return ctx->argument(1); } @@ -877,7 +915,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(SimpleCallContext *ctx) --k; } if (!kPresent) - ctx->throwTypeError(); + return ctx->throwTypeError(); } ScopedCallData callData(scope, 4); diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 025f98351f..d9de6d9fba 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -86,7 +86,7 @@ ReturnedValue BooleanPrototype::method_toString(SimpleCallContext *ctx) Scope scope(ctx); Scoped thisObject(scope, ctx->callData->thisObject); if (!thisObject) - ctx->throwTypeError(); + return ctx->throwTypeError(); result = thisObject->value.booleanValue(); } @@ -101,7 +101,7 @@ ReturnedValue BooleanPrototype::method_valueOf(SimpleCallContext *ctx) Scope scope(ctx); Scoped thisObject(scope, ctx->callData->thisObject); if (!thisObject) - ctx->throwTypeError(); + return ctx->throwTypeError(); return thisObject->value.asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index c14d987171..42db229c9b 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -392,6 +392,7 @@ void ExecutionContext::setProperty(const StringRef name, const ValueRef value) if (strictMode || name->equals(engine->id_this)) { ScopedValue n(scope, name.asReturnedValue()); throwReferenceError(n); + return; } engine->globalObject->put(name, value); } @@ -457,8 +458,7 @@ ReturnedValue ExecutionContext::getProperty(const StringRef name) } } ScopedValue n(scope, name.asReturnedValue()); - throwReferenceError(n); - return 0; + return throwReferenceError(n); } ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectRef base) @@ -527,58 +527,57 @@ ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectR } } ScopedValue n(scope, name.asReturnedValue()); - throwReferenceError(n); - return 0; + return throwReferenceError(n); } -void ExecutionContext::throwError(const ValueRef value) +ReturnedValue ExecutionContext::throwError(const ValueRef value) { - engine->throwException(value); + return engine->throwException(value); } -void ExecutionContext::throwError(const QString &message) +ReturnedValue ExecutionContext::throwError(const QString &message) { Scope scope(this); ScopedValue v(scope, engine->newString(message)); v = engine->newErrorObject(v); - throwError(v); + return throwError(v); } -void ExecutionContext::throwSyntaxError(const QString &message, const QString &fileName, int line, int column) +ReturnedValue ExecutionContext::throwSyntaxError(const QString &message, const QString &fileName, int line, int column) { Scope scope(this); Scoped error(scope, engine->newSyntaxErrorObject(message, fileName, line, column)); - throwError(error); + return throwError(error); } -void ExecutionContext::throwSyntaxError(const QString &message) +ReturnedValue ExecutionContext::throwSyntaxError(const QString &message) { Scope scope(this); Scoped error(scope, engine->newSyntaxErrorObject(message)); - throwError(error); + return throwError(error); } -void ExecutionContext::throwTypeError() +ReturnedValue ExecutionContext::throwTypeError() { Scope scope(this); Scoped error(scope, engine->newTypeErrorObject(QStringLiteral("Type error"))); - throwError(error); + return throwError(error); } -void ExecutionContext::throwTypeError(const QString &message) +ReturnedValue ExecutionContext::throwTypeError(const QString &message) { Scope scope(this); Scoped error(scope, engine->newTypeErrorObject(message)); - throwError(error); + return throwError(error); } -void ExecutionContext::throwUnimplemented(const QString &message) +ReturnedValue ExecutionContext::throwUnimplemented(const QString &message) { Scope scope(this); ScopedValue v(scope, engine->newString(QStringLiteral("Unimplemented ") + message)); v = engine->newErrorObject(v); - throwError(v); + return throwError(v); } ReturnedValue ExecutionContext::catchException(StackTrace *trace) @@ -586,37 +585,37 @@ ReturnedValue ExecutionContext::catchException(StackTrace *trace) return engine->catchException(this, trace); } -void ExecutionContext::throwReferenceError(const ValueRef value) +ReturnedValue ExecutionContext::throwReferenceError(const ValueRef value) { Scope scope(this); Scoped s(scope, value->toString(this)); QString msg = s->toQString() + QStringLiteral(" is not defined"); Scoped error(scope, engine->newReferenceErrorObject(msg)); - throwError(error); + return throwError(error); } -void ExecutionContext::throwReferenceError(const QString &message, const QString &fileName, int line, int column) +ReturnedValue ExecutionContext::throwReferenceError(const QString &message, const QString &fileName, int line, int column) { Scope scope(this); QString msg = message + QStringLiteral(" is not defined"); Scoped error(scope, engine->newReferenceErrorObject(msg, fileName, line, column)); - throwError(error); + return throwError(error); } -void ExecutionContext::throwRangeError(const ValueRef value) +ReturnedValue ExecutionContext::throwRangeError(const ValueRef value) { Scope scope(this); ScopedString s(scope, value->toString(this)); QString msg = s->toQString() + QStringLiteral(" out of range"); ScopedObject error(scope, engine->newRangeErrorObject(msg)); - throwError(error); + return throwError(error); } -void ExecutionContext::throwURIError(const ValueRef msg) +ReturnedValue ExecutionContext::throwURIError(const ValueRef msg) { Scope scope(this); ScopedObject error(scope, engine->newURIErrorObject(msg)); - throwError(error); + return throwError(error); } void SimpleCallContext::initSimpleCallContext(ExecutionEngine *engine) diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index e85350451b..bd779f23f4 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -127,17 +127,17 @@ struct Q_QML_EXPORT ExecutionContext void createMutableBinding(const StringRef name, bool deletable); - void throwError(const QV4::ValueRef value); - void throwError(const QString &message); - void throwSyntaxError(const QString &message); - void throwSyntaxError(const QString &message, const QString &fileName, int line, int column); - void throwTypeError(); - void throwTypeError(const QString &message); - void throwReferenceError(const ValueRef value); - void throwReferenceError(const QString &value, const QString &fileName, int line, int column); - void throwRangeError(const ValueRef value); - void throwURIError(const ValueRef msg); - void throwUnimplemented(const QString &message); + ReturnedValue throwError(const QV4::ValueRef value); + ReturnedValue throwError(const QString &message); + ReturnedValue throwSyntaxError(const QString &message); + ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int line, int column); + ReturnedValue throwTypeError(); + ReturnedValue throwTypeError(const QString &message); + ReturnedValue throwReferenceError(const ValueRef value); + ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int line, int column); + ReturnedValue throwRangeError(const ValueRef value); + ReturnedValue throwURIError(const ValueRef msg); + ReturnedValue throwUnimplemented(const QString &message); void setProperty(const StringRef name, const ValueRef value); ReturnedValue getProperty(const StringRef name); diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index ffc5fa891a..cfc4843ec9 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -1003,7 +1003,7 @@ ReturnedValue DatePrototype::method_setTime(SimpleCallContext *ctx) Scope scope(ctx); Scoped self(scope, ctx->callData->thisObject); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); self->value.setDouble(TimeClip(t)); @@ -1015,7 +1015,7 @@ ReturnedValue DatePrototype::method_setMilliseconds(SimpleCallContext *ctx) Scope scope(ctx); Scoped self(scope, ctx->callData->thisObject); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); double ms = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1027,7 +1027,7 @@ ReturnedValue DatePrototype::method_setUTCMilliseconds(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); double ms = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1039,7 +1039,7 @@ ReturnedValue DatePrototype::method_setSeconds(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); double sec = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1053,7 +1053,7 @@ ReturnedValue DatePrototype::method_setUTCSeconds(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); double sec = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1067,7 +1067,7 @@ ReturnedValue DatePrototype::method_setMinutes(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); double min = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1082,7 +1082,7 @@ ReturnedValue DatePrototype::method_setUTCMinutes(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); double min = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1097,7 +1097,7 @@ ReturnedValue DatePrototype::method_setHours(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); double hour = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1113,7 +1113,7 @@ ReturnedValue DatePrototype::method_setUTCHours(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); double hour = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1129,7 +1129,7 @@ ReturnedValue DatePrototype::method_setDate(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); double date = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1142,7 +1142,7 @@ ReturnedValue DatePrototype::method_setUTCDate(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); double date = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1155,7 +1155,7 @@ ReturnedValue DatePrototype::method_setMonth(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); double month = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1169,7 +1169,7 @@ ReturnedValue DatePrototype::method_setUTCMonth(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); double month = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1183,7 +1183,7 @@ ReturnedValue DatePrototype::method_setYear(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); if (std::isnan(t)) @@ -1209,7 +1209,7 @@ ReturnedValue DatePrototype::method_setUTCFullYear(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); double year = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); @@ -1224,7 +1224,7 @@ ReturnedValue DatePrototype::method_setFullYear(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); if (std::isnan(t)) @@ -1241,7 +1241,7 @@ ReturnedValue DatePrototype::method_toUTCString(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); return ctx->engine->newString(ToUTCString(t))->asReturnedValue(); @@ -1264,11 +1264,11 @@ ReturnedValue DatePrototype::method_toISOString(SimpleCallContext *ctx) { DateObject *self = ctx->callData->thisObject.asDateObject(); if (!self) - ctx->throwTypeError(); + return ctx->throwTypeError(); double t = self->value.asDouble(); if (!std::isfinite(t)) - ctx->throwRangeError(ctx->callData->thisObject); + return ctx->throwRangeError(ctx->callData->thisObject); QString result; int year = (int)YearFromTime(t); @@ -1312,7 +1312,7 @@ ReturnedValue DatePrototype::method_toJSON(SimpleCallContext *ctx) FunctionObject *toIso = v->asFunctionObject(); if (!toIso) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedCallData callData(scope, 0); callData->thisObject = ctx->callData->thisObject; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index b0ede6fa20..cf39d7df4f 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -81,8 +81,7 @@ static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1); static ReturnedValue throwTypeError(SimpleCallContext *ctx) { - ctx->throwTypeError(); - return Encode::undefined(); + return ctx->throwTypeError(); } ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory) @@ -807,7 +806,7 @@ QmlExtensions *ExecutionEngine::qmlExtensions() return m_qmlExtensions; } -void ExecutionEngine::throwException(const ValueRef value) +ReturnedValue ExecutionEngine::throwException(const ValueRef value) { // Q_ASSERT(!hasException); hasException = true; @@ -822,6 +821,7 @@ void ExecutionEngine::throwException(const ValueRef value) if (debugger) debugger->aboutToThrow(value); + return Encode::undefined(); } ReturnedValue ExecutionEngine::catchException(ExecutionContext *catchingContext, StackTrace *trace) diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 94a4dff5b4..f6db36b0d0 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -326,7 +326,7 @@ struct Q_QML_EXPORT ExecutionEngine quint32 hasException; StackTrace exceptionStackTrace; - void throwException(const ValueRef value); + ReturnedValue throwException(const ValueRef value); ReturnedValue catchException(ExecutionContext *catchingContext, StackTrace *trace); // Use only inside catch(...) -- will re-throw if no JS exception diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index ef9dc473f3..12ac4218bd 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -172,7 +172,7 @@ ReturnedValue ErrorObject::method_get_stack(SimpleCallContext *ctx) Scope scope(ctx); Scoped This(scope, ctx->callData->thisObject); if (!This) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (!This->stack) { QString trace; for (int i = 0; i < This->stackTrace.count(); ++i) { @@ -389,7 +389,7 @@ ReturnedValue ErrorPrototype::method_toString(SimpleCallContext *ctx) Object *o = ctx->callData->thisObject.asObject(); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedValue name(scope, o->get(ctx->engine->id_name)); QString qname; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 3e28024bbf..b2ef86525f 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -166,8 +166,10 @@ bool FunctionObject::hasInstance(Managed *that, const ValueRef value) return false; Scoped o(scope, f->get(scope.engine->id_prototype)); - if (!o) + if (!o) { scope.engine->current->throwTypeError(); + return false; + } while (v) { v = v->prototype(); @@ -259,13 +261,13 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData) const bool parsed = parser.parseExpression(); if (!parsed) - f->engine()->current->throwSyntaxError(0); + return f->engine()->current->throwSyntaxError(0); using namespace QQmlJS::AST; FunctionExpression *fe = QQmlJS::AST::cast(parser.rootNode()); ExecutionEngine *v4 = f->engine(); if (!fe) - v4->current->throwSyntaxError(0); + return v4->current->throwSyntaxError(0); QQmlJS::V4IR::Module module(v4->debugger != 0); @@ -312,7 +314,7 @@ ReturnedValue FunctionPrototype::method_toString(SimpleCallContext *ctx) { FunctionObject *fun = ctx->callData->thisObject.asFunctionObject(); if (!fun) - ctx->throwTypeError(); + return ctx->throwTypeError(); return ctx->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue(); } @@ -322,7 +324,7 @@ ReturnedValue FunctionPrototype::method_apply(SimpleCallContext *ctx) Scope scope(ctx); FunctionObject *o = ctx->callData->thisObject.asFunctionObject(); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedValue arg(scope, ctx->argument(1)); @@ -331,10 +333,8 @@ ReturnedValue FunctionPrototype::method_apply(SimpleCallContext *ctx) quint32 len; if (!arr) { len = 0; - if (!arg->isNullOrUndefined()) { - ctx->throwTypeError(); - return Encode::undefined(); - } + if (!arg->isNullOrUndefined()) + return ctx->throwTypeError(); } else { len = ArrayPrototype::getLength(ctx, arr); } @@ -364,7 +364,7 @@ ReturnedValue FunctionPrototype::method_call(SimpleCallContext *ctx) FunctionObject *o = ctx->callData->thisObject.asFunctionObject(); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedCallData callData(scope, ctx->callData->argc ? ctx->callData->argc - 1 : 0); if (ctx->callData->argc) { @@ -380,7 +380,7 @@ ReturnedValue FunctionPrototype::method_bind(SimpleCallContext *ctx) Scope scope(ctx); Scoped target(scope, ctx->callData->thisObject); if (!target) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedValue boundThis(scope, ctx->argument(0)); QVector boundArgs; @@ -568,8 +568,7 @@ BuiltinFunction::BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue BuiltinFunction::construct(Managed *f, CallData *) { - f->engine()->current->throwTypeError(); - return Encode::undefined(); + return f->engine()->current->throwTypeError(); } ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index eeb041ddc0..fe69625061 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -197,8 +197,7 @@ struct IndexedBuiltinFunction: FunctionObject static ReturnedValue construct(Managed *m, CallData *) { - m->engine()->current->throwTypeError(); - return Encode::undefined(); + return m->engine()->current->throwTypeError(); } static ReturnedValue call(Managed *that, CallData *callData); diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index d95ab9791f..084b508b52 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -545,6 +545,9 @@ ReturnedValue GlobalFunctions::method_parseFloat(SimpleCallContext *ctx) // [15.1.2.3] step by step: Scoped inputString(scope, ctx->argument(0), Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); + QString trimmed = inputString->toQString().trimmed(); // 2 // 4: @@ -604,7 +607,7 @@ ReturnedValue GlobalFunctions::method_decodeURI(SimpleCallContext *context) if (!ok) { Scope scope(context); ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence"))); - context->throwURIError(s); + return context->throwURIError(s); } return context->engine->newString(out)->asReturnedValue(); @@ -622,7 +625,7 @@ ReturnedValue GlobalFunctions::method_decodeURIComponent(SimpleCallContext *cont if (!ok) { Scope scope(context); ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence"))); - context->throwURIError(s); + return context->throwURIError(s); } return context->engine->newString(out)->asReturnedValue(); @@ -640,7 +643,7 @@ ReturnedValue GlobalFunctions::method_encodeURI(SimpleCallContext *context) if (!ok) { Scope scope(context); ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence"))); - context->throwURIError(s); + return context->throwURIError(s); } return context->engine->newString(out)->asReturnedValue(); @@ -658,7 +661,7 @@ ReturnedValue GlobalFunctions::method_encodeURIComponent(SimpleCallContext *cont if (!ok) { Scope scope(context); ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence"))); - context->throwURIError(s); + return context->throwURIError(s); } return context->engine->newString(out)->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 331b528409..721843afba 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -779,8 +779,10 @@ QString Stringify::makeMember(const QString &key, ValueRef v) QString Stringify::JO(ObjectRef o) { - if (stack.contains(o.getPointer())) + if (stack.contains(o.getPointer())) { ctx->throwTypeError(); + return QString(); + } Scope scope(ctx); @@ -834,8 +836,10 @@ QString Stringify::JO(ObjectRef o) QString Stringify::JA(ArrayObjectRef a) { - if (stack.contains(a.getPointer())) + if (stack.contains(a.getPointer())) { ctx->throwTypeError(); + return QString(); + } Scope scope(a->engine()); @@ -901,7 +905,7 @@ ReturnedValue JsonObject::method_parse(SimpleCallContext *ctx) ScopedValue result(scope, parser.parse(&error)); if (error.error != QJsonParseError::NoError) { DEBUG << "parse error" << error.errorString(); - ctx->throwSyntaxError("JSON.parse: Parse error"); + return ctx->throwSyntaxError("JSON.parse: Parse error"); } return result.asReturnedValue(); diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 4ee24d29eb..10c94734d6 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -97,7 +97,7 @@ ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object) switch (object->type()) { case Value::Undefined_Type: case Value::Null_Type: - engine->current->throwTypeError(); + return engine->current->throwTypeError(); case Value::Boolean_Type: proto = engine->booleanClass->prototype; break; @@ -439,6 +439,8 @@ void Lookup::setterGeneric(Lookup *l, const ValueRef object, const ValueRef valu ScopedObject o(scope, object); if (!o) { o = __qmljs_convert_to_object(scope.engine->current, object); + if (!o) // type error + return; ScopedString s(scope, l->name); o->put(s, value); return; diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp index 31bb8f2b94..4d40b72bab 100644 --- a/src/qml/jsruntime/qv4managed.cpp +++ b/src/qml/jsruntime/qv4managed.cpp @@ -174,23 +174,22 @@ QString Managed::className() const bool Managed::hasInstance(Managed *m, const ValueRef) { - m->engine()->current->throwTypeError(); + return m->engine()->current->throwTypeError(); } ReturnedValue Managed::construct(Managed *m, CallData *) { - m->engine()->current->throwTypeError(); + return m->engine()->current->throwTypeError(); } ReturnedValue Managed::call(Managed *m, CallData *) { - m->engine()->current->throwTypeError(); + return m->engine()->current->throwTypeError(); } ReturnedValue Managed::getLookup(Managed *m, Lookup *) { - m->engine()->current->throwTypeError(); - return 0; + return m->engine()->current->throwTypeError(); } void Managed::setLookup(Managed *m, Lookup *, const ValueRef) diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 8a09de5349..dd13f493f7 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -107,7 +107,7 @@ inline ReturnedValue thisNumberValue(ExecutionContext *ctx) return ctx->callData->thisObject.asReturnedValue(); NumberObject *n = ctx->callData->thisObject.asNumberObject(); if (!n) - ctx->throwTypeError(); + return ctx->throwTypeError(); return n->value.asReturnedValue(); } @@ -117,21 +117,21 @@ inline double thisNumber(ExecutionContext *ctx) return ctx->callData->thisObject.asDouble(); NumberObject *n = ctx->callData->thisObject.asNumberObject(); if (!n) - ctx->throwTypeError(); + return ctx->throwTypeError(); return n->value.asDouble(); } ReturnedValue NumberPrototype::method_toString(SimpleCallContext *ctx) { double num = thisNumber(ctx); + if (ctx->engine->hasException) + return Encode::undefined(); if (ctx->callData->argc && !ctx->callData->args[0].isUndefined()) { int radix = ctx->callData->args[0].toInt32(); - if (radix < 2 || radix > 36) { - ctx->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix") + if (radix < 2 || radix > 36) + return ctx->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix") .arg(radix)); - return Encode::undefined(); - } if (std::isnan(num)) { return ctx->engine->newString(QStringLiteral("NaN"))->asReturnedValue(); @@ -177,6 +177,8 @@ ReturnedValue NumberPrototype::method_toLocaleString(SimpleCallContext *ctx) { Scope scope(ctx); ScopedValue v(scope, thisNumberValue(ctx)); + if (ctx->engine->hasException) + return Encode::undefined(); ScopedString str(scope, v->toString(ctx)); return str.asReturnedValue(); @@ -190,6 +192,8 @@ ReturnedValue NumberPrototype::method_valueOf(SimpleCallContext *ctx) ReturnedValue NumberPrototype::method_toFixed(SimpleCallContext *ctx) { double v = thisNumber(ctx); + if (ctx->engine->hasException) + return Encode::undefined(); double fdigits = 0; @@ -200,7 +204,7 @@ ReturnedValue NumberPrototype::method_toFixed(SimpleCallContext *ctx) fdigits = 0; if (fdigits < 0 || fdigits > 20) - ctx->throwRangeError(ctx->callData->thisObject); + return ctx->throwRangeError(ctx->callData->thisObject); QString str; if (std::isnan(v)) @@ -218,6 +222,8 @@ ReturnedValue NumberPrototype::method_toExponential(SimpleCallContext *ctx) { Scope scope(ctx); double d = thisNumber(ctx); + if (ctx->engine->hasException) + return Encode::undefined(); int fdigits = -1; @@ -225,7 +231,7 @@ ReturnedValue NumberPrototype::method_toExponential(SimpleCallContext *ctx) int fdigits = ctx->callData->args[0].toInt32(); if (fdigits < 0 || fdigits > 20) { ScopedString error(scope, ctx->engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range"))); - ctx->throwRangeError(error); + return ctx->throwRangeError(error); } } @@ -241,6 +247,8 @@ ReturnedValue NumberPrototype::method_toPrecision(SimpleCallContext *ctx) { Scope scope(ctx); ScopedValue v(scope, thisNumberValue(ctx)); + if (ctx->engine->hasException) + return Encode::undefined(); if (!ctx->callData->argc || ctx->callData->args[0].isUndefined()) return __qmljs_to_string(v, ctx); @@ -248,7 +256,7 @@ ReturnedValue NumberPrototype::method_toPrecision(SimpleCallContext *ctx) double precision = ctx->callData->args[0].toInt32(); if (precision < 1 || precision > 21) { ScopedString error(scope, ctx->engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range"))); - ctx->throwRangeError(error); + return ctx->throwRangeError(error); } char str[100]; diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index b04c65196e..ca02d6703a 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -168,7 +168,6 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef val reject: if (engine()->current->strictMode) engine()->current->throwTypeError(); - } void Object::defineDefaultProperty(const StringRef name, ValueRef value) @@ -715,8 +714,10 @@ void Object::internalPut(const StringRef name, const ValueRef value) else if (isArrayObject() && name->equals(engine()->id_length)) { bool ok; uint l = value->asArrayLength(&ok); - if (!ok) + if (!ok) { engine()->current->throwRangeError(value); + return; + } ok = setArrayLength(l); if (!ok) goto reject; @@ -914,6 +915,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name, if (!ok) { ScopedValue v(scope, p.value); ctx->throwRangeError(v); + return false; } succeeded = setArrayLength(l); } @@ -1230,8 +1232,10 @@ void Object::arraySort(ExecutionContext *context, ObjectRef thisObject, const Va } } - if (!(comparefn->isUndefined() || comparefn->asObject())) + if (!(comparefn->isUndefined() || comparefn->asObject())) { context->throwTypeError(); + return; + } ArrayElementLessThan lessThan(context, thisObject, comparefn); diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 7cfda589e5..061487f8af 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -143,7 +143,7 @@ ReturnedValue ObjectPrototype::method_getPrototypeOf(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->argument(0)); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped p(scope, o->prototype()); return !!p ? p->asReturnedValue() : Encode::null(); @@ -154,7 +154,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(SimpleCallContext Scope scope(ctx); Scoped O(scope, ctx->argument(0)); if (!O) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedValue v(scope, ctx->argument(1)); Scoped name(scope, v->toString(ctx)); @@ -168,7 +168,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyNames(SimpleCallContext *con Scope scope(context); ScopedObject O(scope, context->argument(0)); if (!O) - context->throwTypeError(); + return context->throwTypeError(); ScopedArrayObject array(scope, getOwnPropertyNames(context->engine, context->callData->args[0])); return array.asReturnedValue(); @@ -179,7 +179,7 @@ ReturnedValue ObjectPrototype::method_create(SimpleCallContext *ctx) Scope scope(ctx); ScopedValue O(scope, ctx->argument(0)); if (!O->isObject() && !O->isNull()) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped newObject(scope, ctx->engine->newObject()); newObject->setPrototype(O->asObject()); @@ -197,17 +197,21 @@ ReturnedValue ObjectPrototype::method_defineProperty(SimpleCallContext *ctx) Scope scope(ctx); Scoped O(scope, ctx->argument(0)); if (!O) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped name(scope, ctx->argument(1), Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); ScopedValue attributes(scope, ctx->argument(2)); Property pd; PropertyAttributes attrs; toPropertyDescriptor(ctx, attributes, &pd, &attrs); + if (scope.engine->hasException) + return Encode::undefined(); if (!O->__defineOwnProperty__(ctx, name, pd, attrs)) - ctx->throwTypeError(); + return ctx->throwTypeError(); return O.asReturnedValue(); } @@ -217,9 +221,11 @@ ReturnedValue ObjectPrototype::method_defineProperties(SimpleCallContext *ctx) Scope scope(ctx); Scoped O(scope, ctx->argument(0)); if (!O) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped o(scope, ctx->argument(1), Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); ScopedValue val(scope); ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly); @@ -234,13 +240,15 @@ ReturnedValue ObjectPrototype::method_defineProperties(SimpleCallContext *ctx) PropertyAttributes nattrs; val = o->getValue(pd, attrs); toPropertyDescriptor(ctx, val, &n, &nattrs); + if (scope.engine->hasException) + return Encode::undefined(); bool ok; if (name) ok = O->__defineOwnProperty__(ctx, name, n, nattrs); else ok = O->__defineOwnProperty__(ctx, index, n, nattrs); if (!ok) - ctx->throwTypeError(); + return ctx->throwTypeError(); } return O.asReturnedValue(); @@ -251,7 +259,7 @@ ReturnedValue ObjectPrototype::method_seal(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->argument(0)); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); o->extensible = false; @@ -271,7 +279,7 @@ ReturnedValue ObjectPrototype::method_freeze(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->argument(0)); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); o->extensible = false; @@ -292,7 +300,7 @@ ReturnedValue ObjectPrototype::method_preventExtensions(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->argument(0)); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); o->extensible = false; return o.asReturnedValue(); @@ -303,7 +311,7 @@ ReturnedValue ObjectPrototype::method_isSealed(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->argument(0)); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (o->extensible) return Encode(false); @@ -331,7 +339,7 @@ ReturnedValue ObjectPrototype::method_isFrozen(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->argument(0)); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (o->extensible) return Encode(false); @@ -359,7 +367,7 @@ ReturnedValue ObjectPrototype::method_isExtensible(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->argument(0)); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); return Encode((bool)o->extensible); } @@ -369,7 +377,7 @@ ReturnedValue ObjectPrototype::method_keys(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->argument(0)); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped a(scope, ctx->engine->newArrayObject()); @@ -403,9 +411,11 @@ ReturnedValue ObjectPrototype::method_toLocaleString(SimpleCallContext *ctx) { Scope scope(ctx); ScopedObject o(scope, ctx->callData->thisObject.toObject(ctx)); + if (!o) + return Encode::undefined(); Scoped f(scope, o->get(ctx->engine->id_toString)); if (!f) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedCallData callData(scope, 0); callData->thisObject = o; return f->call(callData); @@ -415,6 +425,8 @@ ReturnedValue ObjectPrototype::method_valueOf(SimpleCallContext *ctx) { Scope scope(ctx); ScopedValue v(scope, ctx->callData->thisObject.toObject(ctx)); + if (ctx->engine->hasException) + return Encode::undefined(); return v.asReturnedValue(); } @@ -422,7 +434,11 @@ ReturnedValue ObjectPrototype::method_hasOwnProperty(SimpleCallContext *ctx) { Scope scope(ctx); Scoped P(scope, ctx->argument(0), Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); Scoped O(scope, ctx->callData->thisObject, Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); bool r = O->__getOwnProperty__(P) != 0; if (!r) r = !O->query(P).isEmpty(); @@ -437,6 +453,8 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(SimpleCallContext *ctx) return Encode(false); Scoped O(scope, ctx->callData->thisObject, Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); Scoped proto(scope, V->prototype()); while (proto) { if (O.getPointer() == proto.getPointer()) @@ -450,8 +468,12 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(SimpleCallContext *ct { Scope scope(ctx); Scoped p(scope, ctx->argument(0), Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); Scoped o(scope, ctx->callData->thisObject, Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); PropertyAttributes attrs; o->__getOwnProperty__(p, &attrs); return Encode(attrs.isEnumerable()); @@ -460,14 +482,16 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(SimpleCallContext *ct ReturnedValue ObjectPrototype::method_defineGetter(SimpleCallContext *ctx) { if (ctx->callData->argc < 2) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scope scope(ctx); Scoped prop(scope, ctx->argument(0), Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); Scoped f(scope, ctx->argument(1)); if (!f) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped o(scope, ctx->callData->thisObject); if (!o) { @@ -484,14 +508,16 @@ ReturnedValue ObjectPrototype::method_defineGetter(SimpleCallContext *ctx) ReturnedValue ObjectPrototype::method_defineSetter(SimpleCallContext *ctx) { if (ctx->callData->argc < 2) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scope scope(ctx); Scoped prop(scope, ctx->argument(0), Scoped::Convert); + if (scope.engine->hasException) + return Encode::undefined(); Scoped f(scope, ctx->argument(1)); if (!f) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped o(scope, ctx->callData->thisObject); if (!o) { @@ -510,7 +536,7 @@ ReturnedValue ObjectPrototype::method_get_proto(SimpleCallContext *ctx) Scope scope(ctx); ScopedObject o(scope, ctx->callData->thisObject.asObject()); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); return o->prototype()->asReturnedValue(); } @@ -520,7 +546,7 @@ ReturnedValue ObjectPrototype::method_set_proto(SimpleCallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->callData->thisObject); if (!o || !ctx->callData->argc) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (ctx->callData->args[0].isNull()) { o->setPrototype(0); @@ -537,7 +563,7 @@ ReturnedValue ObjectPrototype::method_set_proto(SimpleCallContext *ctx) } } if (!ok) - ctx->throwTypeError(QStringLiteral("Cyclic __proto__ value")); + return ctx->throwTypeError(QStringLiteral("Cyclic __proto__ value")); return Encode::undefined(); } @@ -545,8 +571,10 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef { Scope scope(ctx); ScopedObject o(scope, v); - if (!o) + if (!o) { ctx->throwTypeError(); + return; + } attrs->clear(); desc->setGetter(0); @@ -568,6 +596,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef desc->setGetter((FunctionObject *)0x1); } else { ctx->throwTypeError(); + return; } attrs->setType(PropertyAttributes::Accessor); } @@ -581,21 +610,26 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef desc->setSetter((FunctionObject *)0x1); } else { ctx->throwTypeError(); + return; } attrs->setType(PropertyAttributes::Accessor); } if (o->__hasProperty__(ctx->engine->id_writable)) { - if (attrs->isAccessor()) + if (attrs->isAccessor()) { ctx->throwTypeError(); + return; + } attrs->setWritable((tmp = o->get(ctx->engine->id_writable))->toBoolean()); // writable forces it to be a data descriptor desc->value = Primitive::undefinedValue(); } if (o->__hasProperty__(ctx->engine->id_value)) { - if (attrs->isAccessor()) + if (attrs->isAccessor()) { ctx->throwTypeError(); + return; + } desc->value = o->get(ctx->engine->id_value); attrs->setType(PropertyAttributes::Data); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 05d5532f8f..a581e6bc69 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -436,7 +436,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC if (!result->isWritable() && !result->isQList()) { QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"'); - ctx->throwTypeError(error); + return ctx->throwTypeError(error); } QQmlBinding *newBinding = 0; @@ -451,6 +451,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC else error += QLatin1String(QMetaType::typeName(result->propType)); ctx->throwError(error); + return false; } } else { // binding assignment. @@ -504,6 +505,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC else error += QLatin1String(QMetaType::typeName(result->propType)); ctx->throwError(error); + return false; } else if (value->asFunctionObject()) { // this is handled by the binding creation above } else if (result->propType == QMetaType::Int && value->isNumber()) { @@ -542,6 +544,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC QLatin1String(" to ") + QLatin1String(targetTypeName); ctx->throwError(error); + return false; } } @@ -1281,7 +1284,7 @@ static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &d if (returnType == QMetaType::UnknownType) { QString typeName = QString::fromLatin1(unknownTypeError); QString error = QString::fromLatin1("Unknown method return type: %1").arg(typeName); - QV8Engine::getV4(engine)->current->throwError(error); + return QV8Engine::getV4(engine)->current->throwError(error); } if (data.hasArguments()) { @@ -1295,12 +1298,12 @@ static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &d if (!args) { QString typeName = QString::fromLatin1(unknownTypeError); QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName); - QV8Engine::getV4(engine)->current->throwError(error); + return QV8Engine::getV4(engine)->current->throwError(error); } if (args[0] > callArgs->argc) { QString error = QLatin1String("Insufficient arguments"); - QV8Engine::getV4(engine)->current->throwError(error); + return QV8Engine::getV4(engine)->current->throwError(error); } return CallMethod(object, data.coreIndex, returnType, args[0], args + 1, engine, callArgs); @@ -1399,7 +1402,7 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData candidate = RelatedMethod(object, candidate, dummy); } - QV8Engine::getV4(engine)->current->throwError(error); + return QV8Engine::getV4(engine)->current->throwError(error); } } @@ -1697,7 +1700,7 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con if (!m_object) return Encode::undefined(); if (QQmlData::keepAliveDuringGarbageCollection(m_object)) - ctx->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object")); + return ctx->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object")); int delay = 0; if (argc > 0) diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 6eaa8c387d..8bcddcce0a 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -249,7 +249,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) Scoped re(scope, r); if (re) { if (!f->isUndefined()) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scoped newRe(scope, re->value); return Encode(ctx->engine->newRegExpObject(newRe, re->global)); @@ -273,14 +273,14 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) } else if (str.at(i) == QChar('m') && !multiLine) { multiLine = true; } else { - ctx->throwSyntaxError(0); + return ctx->throwSyntaxError(0); } } } Scoped regexp(scope, RegExp::create(ctx->engine, pattern, ignoreCase, multiLine)); if (!regexp->isValid()) - ctx->throwSyntaxError(0); + return ctx->throwSyntaxError(0); return Encode(ctx->engine->newRegExpObject(regexp, global)); } @@ -314,7 +314,7 @@ ReturnedValue RegExpPrototype::method_exec(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedValue arg(scope, ctx->argument(0)); arg = __qmljs_to_string(arg, ctx); @@ -366,7 +366,7 @@ ReturnedValue RegExpPrototype::method_toString(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); return ctx->engine->newString(r->toString())->asReturnedValue(); } @@ -376,7 +376,7 @@ ReturnedValue RegExpPrototype::method_compile(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); ScopedCallData callData(scope, ctx->callData->argc); memcpy(callData->args, ctx->callData->args, ctx->callData->argc*sizeof(SafeValue)); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 1eed693c3d..dbbccdea70 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -284,6 +284,8 @@ ReturnedValue __qmljs_delete_member(ExecutionContext *ctx, const ValueRef base, { Scope scope(ctx); ScopedObject obj(scope, base->toObject(ctx)); + if (scope.engine->hasException) + return Encode::undefined(); return Encode(obj->deleteProperty(name)); } @@ -315,7 +317,7 @@ QV4::ReturnedValue __qmljs_instanceof(ExecutionContext *ctx, const ValueRef left { Object *o = right->asObject(); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); bool r = o->hasInstance(left); return Encode(r); @@ -324,9 +326,11 @@ QV4::ReturnedValue __qmljs_instanceof(ExecutionContext *ctx, const ValueRef left QV4::ReturnedValue __qmljs_in(ExecutionContext *ctx, const ValueRef left, const ValueRef right) { if (!right->isObject()) - ctx->throwTypeError(); + return ctx->throwTypeError(); Scope scope(ctx); ScopedString s(scope, left->toString(ctx)); + if (scope.hasException()) + return Encode::undefined(); bool r = right->objectValue()->__hasProperty__(s); return Encode(r); } @@ -382,6 +386,9 @@ ReturnedValue __qmljs_object_default_value(Object *object, int typeHint) } ExecutionEngine *engine = object->internalClass->engine; + if (engine->hasException) + return Encode::undefined(); + SafeString *meth1 = &engine->id_toString; SafeString *meth2 = &engine->id_valueOf; @@ -400,6 +407,9 @@ ReturnedValue __qmljs_object_default_value(Object *object, int typeHint) return r->asReturnedValue(); } + if (engine->hasException) + return Encode::undefined(); + conv = object->get(*meth2); if (FunctionObject *o = conv->asFunctionObject()) { ScopedValue r(scope, o->call(callData)); @@ -407,8 +417,7 @@ ReturnedValue __qmljs_object_default_value(Object *object, int typeHint) return r->asReturnedValue(); } - ctx->throwTypeError(); - return Encode::undefined(); + return ctx->throwTypeError(); } Bool __qmljs_to_boolean(const ValueRef value) @@ -424,6 +433,7 @@ Returned *__qmljs_convert_to_object(ExecutionContext *ctx, const ValueRe case Value::Undefined_Type: case Value::Null_Type: ctx->throwTypeError(); + return 0; case Value::Boolean_Type: return ctx->engine->newBooleanObject(value); case Value::Managed_Type: @@ -468,6 +478,8 @@ void __qmljs_set_property(ExecutionContext *ctx, const ValueRef object, const St { Scope scope(ctx); ScopedObject o(scope, object->toObject(ctx)); + if (scope.engine->hasException) + return; o->put(name, value); } @@ -490,10 +502,12 @@ ReturnedValue __qmljs_get_element(ExecutionContext *ctx, const ValueRef object, if (object->isNullOrUndefined()) { QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQStringNoThrow()).arg(object->toQStringNoThrow()); - ctx->throwTypeError(message); + return ctx->throwTypeError(message); } o = __qmljs_convert_to_object(ctx, object); + if (!o) // type error + return Encode::undefined(); } if (idx < UINT_MAX) { @@ -509,6 +523,8 @@ ReturnedValue __qmljs_get_element(ExecutionContext *ctx, const ValueRef object, } ScopedString name(scope, index->toString(ctx)); + if (scope.hasException()) + return Encode::undefined(); return o->get(name); } @@ -516,6 +532,8 @@ void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const Val { Scope scope(ctx); ScopedObject o(scope, object->toObject(ctx)); + if (scope.engine->hasException) + return; uint idx = index->asArrayIndex(); if (idx < UINT_MAX) { @@ -553,6 +571,8 @@ void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const Val } ScopedString name(scope, index->toString(ctx)); + if (scope.hasException()) + return; o->put(name, value); } @@ -592,10 +612,12 @@ ReturnedValue __qmljs_get_property(ExecutionContext *ctx, const ValueRef object, if (object->isNullOrUndefined()) { QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object->toQStringNoThrow()); - ctx->throwTypeError(message); + return ctx->throwTypeError(message); } o = __qmljs_convert_to_object(ctx, object); + if (!o) // type error + return Encode::undefined(); return o->get(name); } @@ -753,7 +775,7 @@ ReturnedValue __qmljs_call_global_lookup(ExecutionContext *context, uint index, Lookup *l = context->lookups + index; Scoped o(scope, l->globalGetter(l, context)); if (!o) - context->throwTypeError(); + return context->throwTypeError(); if (o.getPointer() == context->engine->evalFunction && l->name->equals(context->engine->id_eval)) return static_cast(o.getPointer())->evalCall(callData, true); @@ -781,7 +803,7 @@ ReturnedValue __qmljs_call_activation_property(ExecutionContext *context, const if (base) objectAsString = ScopedValue(scope, base.asReturnedValue())->toQStringNoThrow(); QString msg = QStringLiteral("Property '%1' of object %2 is not a function").arg(name->toQString()).arg(objectAsString); - context->throwTypeError(msg); + return context->throwTypeError(msg); } if (o == context->engine->evalFunction && name->equals(context->engine->id_eval)) { @@ -799,17 +821,19 @@ ReturnedValue __qmljs_call_property(ExecutionContext *context, const StringRef n Q_ASSERT(!callData->thisObject.isEmpty()); if (callData->thisObject.isNullOrUndefined()) { QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQStringNoThrow()); - context->throwTypeError(message); + return context->throwTypeError(message); } baseObject = __qmljs_convert_to_object(context, ValueRef(&callData->thisObject)); + if (!baseObject) // type error + return Encode::undefined(); callData->thisObject = baseObject.asReturnedValue(); } Scoped o(scope, baseObject->get(name)); if (!o) { QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQStringNoThrow()); - context->throwTypeError(error); + return context->throwTypeError(error); } return o->call(callData); @@ -822,7 +846,7 @@ ReturnedValue __qmljs_call_property_lookup(ExecutionContext *context, uint index Lookup *l = context->lookups + index; Scoped o(scope, l->getter(l, callData->thisObject)); if (!o) - context->throwTypeError(); + return context->throwTypeError(); return o->call(callData); } @@ -831,12 +855,15 @@ ReturnedValue __qmljs_call_element(ExecutionContext *context, const ValueRef ind { Scope scope(context); ScopedObject baseObject(scope, callData->thisObject.toObject(context)); + ScopedString s(scope, index->toString(context)); + + if (scope.engine->hasException) + return Encode::undefined(); callData->thisObject = baseObject; - ScopedString s(scope, index->toString(context)); ScopedObject o(scope, baseObject->get(s)); if (!o) - context->throwTypeError(); + return context->throwTypeError(); return o->call(callData); } @@ -845,7 +872,7 @@ ReturnedValue __qmljs_call_value(ExecutionContext *context, const ValueRef func, { Object *o = func->asObject(); if (!o) - context->throwTypeError(); + return context->throwTypeError(); return o->call(callData); } @@ -859,7 +886,7 @@ ReturnedValue __qmljs_construct_global_lookup(ExecutionContext *context, uint in Lookup *l = context->lookups + index; Scoped f(scope, l->globalGetter(l, context)); if (!f) - context->throwTypeError(); + return context->throwTypeError(); return f->construct(callData); } @@ -874,7 +901,7 @@ ReturnedValue __qmljs_construct_activation_property(ExecutionContext *context, c Object *f = func->asObject(); if (!f) - context->throwTypeError(); + return context->throwTypeError(); return f->construct(callData); } @@ -883,7 +910,7 @@ ReturnedValue __qmljs_construct_value(ExecutionContext *context, const ValueRef { Object *f = func->asObject(); if (!f) - context->throwTypeError(); + return context->throwTypeError(); return f->construct(callData); } @@ -892,10 +919,12 @@ ReturnedValue __qmljs_construct_property(ExecutionContext *context, const ValueR { Scope scope(context); ScopedObject thisObject(scope, base->toObject(context)); + if (scope.engine->hasException) + return Encode::undefined(); Scoped f(scope, thisObject->get(name)); if (!f) - context->throwTypeError(); + return context->throwTypeError(); return f->construct(callData); } @@ -948,6 +977,8 @@ QV4::ReturnedValue __qmljs_builtin_typeof_member(ExecutionContext *context, cons { Scope scope(context); ScopedObject obj(scope, base->toObject(context)); + if (scope.engine->hasException) + return Encode::undefined(); ScopedValue prop(scope, obj->get(name)); return __qmljs_builtin_typeof(context, prop); } @@ -957,6 +988,8 @@ QV4::ReturnedValue __qmljs_builtin_typeof_element(ExecutionContext *context, con Scope scope(context); ScopedString name(scope, index->toString(context)); ScopedObject obj(scope, base->toObject(context)); + if (scope.engine->hasException) + return Encode::undefined(); ScopedValue prop(scope, obj->get(name)); return __qmljs_builtin_typeof(context, prop); } @@ -1097,7 +1130,12 @@ QV4::ReturnedValue __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::Valu { if (value->isObject()) return value.asReturnedValue(); - return Encode(__qmljs_convert_to_object(ctx, value)); + + Returned *o = __qmljs_convert_to_object(ctx, value); + if (!o) // type error + return Encode::undefined(); + + return Encode(o); } ReturnedValue __qmljs_value_to_double(const ValueRef value) diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 320646805b..f6feb2f170 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -400,7 +400,7 @@ public: QV4::Scope scope(ctx); QV4::Scoped > This(scope, ctx->callData->thisObject.as >()); if (!This) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (This->m_isReference) { if (!This->m_object) @@ -415,7 +415,7 @@ public: QV4::Scope scope(ctx); QV4::Scoped > This(scope, ctx->callData->thisObject.as >()); if (!This) - ctx->throwTypeError(); + return ctx->throwTypeError(); quint32 newLength = ctx->callData->args[0].toUInt32(); /* Qt containers have int (rather than uint) allowable indexes. */ @@ -553,7 +553,7 @@ QV4::ReturnedValue SequencePrototype::method_sort(QV4::SimpleCallContext *ctx) QV4::Scope scope(ctx); QV4::ScopedObject o(scope, ctx->callData->thisObject); if (!o || !o->isListType()) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (ctx->callData->argc >= 2) return o.asReturnedValue(); diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 25e1ea55c2..36d1433665 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -124,8 +124,10 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index) ExecutionEngine *v4 = m->engine(); Scope scope(v4); Scoped o(scope, m->asStringObject()); - if (!o) + if (!o) { v4->current->throwTypeError(); + return false; + } if (index < o->value.stringValue()->toQString().length()) { if (v4->current->strictMode) @@ -237,8 +239,10 @@ static QString getThisString(ExecutionContext *ctx) return t->stringValue()->toQString(); if (StringObject *thisString = t->asStringObject()) return thisString->value.stringValue()->toQString(); - if (t->isUndefined() || t->isNull()) + if (t->isUndefined() || t->isNull()) { ctx->throwTypeError(); + return QString(); + } return t->toQString(); } @@ -249,13 +253,15 @@ ReturnedValue StringPrototype::method_toString(SimpleCallContext *context) StringObject *o = context->callData->thisObject.asStringObject(); if (!o) - context->throwTypeError(); + return context->throwTypeError(); return o->value.asReturnedValue(); } ReturnedValue StringPrototype::method_charAt(SimpleCallContext *context) { const QString str = getThisString(context); + if (context->engine->hasException) + return Encode::undefined(); int pos = 0; if (context->callData->argc > 0) @@ -271,6 +277,8 @@ ReturnedValue StringPrototype::method_charAt(SimpleCallContext *context) ReturnedValue StringPrototype::method_charCodeAt(SimpleCallContext *context) { const QString str = getThisString(context); + if (context->engine->hasException) + return Encode::undefined(); int pos = 0; if (context->callData->argc > 0) @@ -288,6 +296,8 @@ ReturnedValue StringPrototype::method_concat(SimpleCallContext *context) Scope scope(context); QString value = getThisString(context); + if (scope.engine->hasException) + return Encode::undefined(); ScopedValue v(scope); for (int i = 0; i < context->callData->argc; ++i) { @@ -302,6 +312,8 @@ ReturnedValue StringPrototype::method_concat(SimpleCallContext *context) ReturnedValue StringPrototype::method_indexOf(SimpleCallContext *context) { QString value = getThisString(context); + if (context->engine->hasException) + return Encode::undefined(); QString searchString; if (context->callData->argc) @@ -323,6 +335,8 @@ ReturnedValue StringPrototype::method_lastIndexOf(SimpleCallContext *context) Scope scope(context); const QString value = getThisString(context); + if (scope.engine->hasException) + return Encode::undefined(); QString searchString; if (context->callData->argc) @@ -348,6 +362,9 @@ ReturnedValue StringPrototype::method_localeCompare(SimpleCallContext *context) { Scope scope(context); const QString value = getThisString(context); + if (scope.engine->hasException) + return Encode::undefined(); + ScopedValue v(scope, context->callData->argument(0)); const QString that = v->toQString(); return Encode(QString::localeAwareCompare(value, that)); @@ -356,7 +373,7 @@ ReturnedValue StringPrototype::method_localeCompare(SimpleCallContext *context) ReturnedValue StringPrototype::method_match(SimpleCallContext *context) { if (context->callData->thisObject.isUndefined() || context->callData->thisObject.isNull()) - context->throwTypeError(); + return context->throwTypeError(); Scope scope(context); ScopedString s(scope, context->callData->thisObject.toString(context)); @@ -371,7 +388,7 @@ ReturnedValue StringPrototype::method_match(SimpleCallContext *context) if (!rx) // ### CHECK - context->throwTypeError(); + return context->throwTypeError(); bool global = rx->global; @@ -580,6 +597,8 @@ ReturnedValue StringPrototype::method_search(SimpleCallContext *ctx) { Scope scope(ctx); QString string = getThisString(ctx); + if (scope.engine->hasException) + return Encode::undefined(); ScopedValue regExpValue(scope, ctx->argument(0)); Scoped regExp(scope, regExpValue->as()); @@ -600,6 +619,9 @@ ReturnedValue StringPrototype::method_search(SimpleCallContext *ctx) ReturnedValue StringPrototype::method_slice(SimpleCallContext *ctx) { const QString text = getThisString(ctx); + if (ctx->engine->hasException) + return Encode::undefined(); + const double length = text.length(); double start = ctx->callData->argc ? ctx->callData->args[0].toInteger() : 0; @@ -627,6 +649,8 @@ ReturnedValue StringPrototype::method_split(SimpleCallContext *ctx) { Scope scope(ctx); QString text = getThisString(ctx); + if (scope.engine->hasException) + return Encode::undefined(); ScopedValue separatorValue(scope, ctx->argument(0)); ScopedValue limitValue(scope, ctx->argument(1)); @@ -705,6 +729,8 @@ ReturnedValue StringPrototype::method_split(SimpleCallContext *ctx) ReturnedValue StringPrototype::method_substr(SimpleCallContext *context) { const QString value = getThisString(context); + if (context->engine->hasException) + return Encode::undefined(); double start = 0; if (context->callData->argc > 0) @@ -728,6 +754,8 @@ ReturnedValue StringPrototype::method_substr(SimpleCallContext *context) ReturnedValue StringPrototype::method_substring(SimpleCallContext *context) { QString value = getThisString(context); + if (context->engine->hasException) + return Encode::undefined(); int length = value.length(); double start = 0; @@ -767,6 +795,8 @@ ReturnedValue StringPrototype::method_substring(SimpleCallContext *context) ReturnedValue StringPrototype::method_toLowerCase(SimpleCallContext *ctx) { QString value = getThisString(ctx); + if (ctx->engine->hasException) + return Encode::undefined(); return ctx->engine->newString(value.toLower())->asReturnedValue(); } @@ -778,6 +808,8 @@ ReturnedValue StringPrototype::method_toLocaleLowerCase(SimpleCallContext *ctx) ReturnedValue StringPrototype::method_toUpperCase(SimpleCallContext *ctx) { QString value = getThisString(ctx); + if (ctx->engine->hasException) + return Encode::undefined(); return ctx->engine->newString(value.toUpper())->asReturnedValue(); } @@ -800,6 +832,8 @@ ReturnedValue StringPrototype::method_fromCharCode(SimpleCallContext *context) ReturnedValue StringPrototype::method_trim(SimpleCallContext *ctx) { QString s = getThisString(ctx); + if (ctx->engine->hasException) + return Encode::undefined(); const QChar *chars = s.constData(); int start, end; diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 0314e4d2a9..01e87537f5 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1451,7 +1451,7 @@ QV4::ReturnedValue QmlIncubatorObject::method_get_object(QV4::SimpleCallContext QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); return QV4::QObjectWrapper::wrap(ctx->engine, o->incubator->object()); } @@ -1461,7 +1461,7 @@ QV4::ReturnedValue QmlIncubatorObject::method_forceCompletion(QV4::SimpleCallCon QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); o->incubator->forceCompletion(); @@ -1473,7 +1473,7 @@ QV4::ReturnedValue QmlIncubatorObject::method_get_status(QV4::SimpleCallContext QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); return QV4::Encode(o->incubator->status()); } @@ -1483,7 +1483,7 @@ QV4::ReturnedValue QmlIncubatorObject::method_get_statusChanged(QV4::SimpleCallC QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); return o->m_statusChanged.asReturnedValue(); } @@ -1493,7 +1493,7 @@ QV4::ReturnedValue QmlIncubatorObject::method_set_statusChanged(QV4::SimpleCallC QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o || ctx->callData->argc < 1) - ctx->throwTypeError(); + return ctx->throwTypeError(); o->m_statusChanged = ctx->callData->args[0]; diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index c867b6e126..a187b17a08 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -135,7 +135,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has QV4::Scope scope(v4); QmlContextWrapper *resource = m->as(); if (!resource) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); // In V8 the JS global object would come _before_ the QML global object, // so simulate that here. @@ -282,8 +282,10 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val ExecutionEngine *v4 = m->engine(); QV4::Scope scope(v4); QV4::Scoped wrapper(scope, m->as()); - if (!wrapper) + if (!wrapper) { v4->current->throwTypeError(); + return; + } if (wrapper->isNullWrapper) { if (wrapper && wrapper->readOnly) { @@ -291,6 +293,7 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val QLatin1Char('"'); Scoped e(scope, v4->current->engine->newString(error)); v4->current->throwError(e); + return; } Object::put(m, name, value); @@ -341,6 +344,7 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val QString error = QLatin1String("Invalid write to global property \"") + name->toQString() + QLatin1Char('"'); v4->current->throwError(error); + return; } Object::put(m, name, value); diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index 0364659ecc..12ebc102ee 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -106,7 +106,7 @@ ReturnedValue QmlListWrapper::get(Managed *m, const StringRef name, bool *hasPro QV4::ExecutionEngine *v4 = m->engine(); QmlListWrapper *w = m->as(); if (!w) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); if (name->equals(v4->id_length) && !w->object.isNull()) { quint32 count = w->property.count ? w->property.count(&w->property) : 0; @@ -125,7 +125,7 @@ ReturnedValue QmlListWrapper::getIndexed(Managed *m, uint index, bool *hasProper QV4::ExecutionEngine *e = m->engine(); QmlListWrapper *w = m->as(); if (!w) - e->current->throwTypeError(); + return e->current->throwTypeError(); quint32 count = w->property.count ? w->property.count(&w->property) : 0; if (index < count && w->property.at) diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index aca18d8ef4..81a6ffc590 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -67,11 +67,13 @@ public: QLocale locale; - static QLocale &getThisLocale(QV4::SimpleCallContext *ctx) { + static QLocale *getThisLocale(QV4::SimpleCallContext *ctx) { QQmlLocaleData *thisObject = ctx->callData->thisObject.asObject()->as(); - if (!thisObject) + if (!thisObject) { ctx->throwTypeError(); - return thisObject->locale; + return 0; + } + return &thisObject->locale; } static QV4::ReturnedValue method_currencySymbol(QV4::SimpleCallContext *ctx); @@ -516,8 +518,10 @@ QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::SimpleCallC QV4::ReturnedValue QQmlLocaleData::method_get_firstDayOfWeek(QV4::SimpleCallContext *ctx) { - QLocale locale = getThisLocale(ctx); - int fdow = int(locale.firstDayOfWeek()); + QLocale *locale = getThisLocale(ctx); + if (!locale) + return QV4::Encode::undefined(); + int fdow = int(locale->firstDayOfWeek()); if (fdow == 7) fdow = 0; // Qt::Sunday = 7, but Sunday is 0 in JS Date return QV4::Encode(fdow); @@ -525,21 +529,29 @@ QV4::ReturnedValue QQmlLocaleData::method_get_firstDayOfWeek(QV4::SimpleCallCont QV4::ReturnedValue QQmlLocaleData::method_get_measurementSystem(QV4::SimpleCallContext *ctx) { - QLocale locale = getThisLocale(ctx); - return QV4::Encode(locale.measurementSystem()); + QLocale *locale = getThisLocale(ctx); + if (!locale) + return QV4::Encode::undefined(); + return QV4::Encode(locale->measurementSystem()); } QV4::ReturnedValue QQmlLocaleData::method_get_textDirection(QV4::SimpleCallContext *ctx) { - QLocale locale = getThisLocale(ctx); - return QV4::Encode(locale.textDirection()); + QLocale *locale = getThisLocale(ctx); + if (!locale) + return QV4::Encode::undefined(); + + return QV4::Encode(locale->textDirection()); } QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::SimpleCallContext *ctx) { QV4::Scope scope(ctx); - QLocale locale = getThisLocale(ctx); - QList days = locale.weekdays(); + QLocale *locale = getThisLocale(ctx); + if (!locale) + return QV4::Encode::undefined(); + + QList days = locale->weekdays(); QV4::Scoped result(scope, ctx->engine->newArrayObject()); result->arrayReserve(days.size()); @@ -558,8 +570,11 @@ QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::SimpleCallContext *c QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::SimpleCallContext *ctx) { QV4::Scope scope(ctx); - QLocale locale = getThisLocale(ctx); - QStringList langs = locale.uiLanguages(); + QLocale *locale = getThisLocale(ctx); + if (!locale) + return QV4::Encode::undefined(); + + QStringList langs = locale->uiLanguages(); QV4::Scoped result(scope, ctx->engine->newArrayObject()); result->arrayReserve(langs.size()); for (int i = 0; i < langs.size(); ++i) { @@ -574,7 +589,10 @@ QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::SimpleCallContext QV4::ReturnedValue QQmlLocaleData::method_currencySymbol(QV4::SimpleCallContext *ctx) { - QLocale locale = getThisLocale(ctx); + QLocale *locale = getThisLocale(ctx); + if (!locale) + return QV4::Encode::undefined(); + if (ctx->callData->argc > 1) V4THROW_ERROR("Locale: currencySymbol(): Invalid arguments"); @@ -584,12 +602,14 @@ QV4::ReturnedValue QQmlLocaleData::method_currencySymbol(QV4::SimpleCallContext format = QLocale::CurrencySymbolFormat(intFormat); } - return ctx->engine->newString(locale.currencySymbol(format))->asReturnedValue(); + return ctx->engine->newString(locale->currencySymbol(format))->asReturnedValue(); } #define LOCALE_FORMAT(FUNC) \ QV4::ReturnedValue QQmlLocaleData::method_ ##FUNC (QV4::SimpleCallContext *ctx) { \ - QLocale locale = getThisLocale(ctx); \ + QLocale *locale = getThisLocale(ctx); \ + if (!locale) \ + return QV4::Encode::undefined(); \ if (ctx->callData->argc > 1) \ V4THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \ QLocale::FormatType format = QLocale::LongFormat;\ @@ -597,7 +617,7 @@ QV4::ReturnedValue QQmlLocaleData::method_ ##FUNC (QV4::SimpleCallContext *ctx) quint32 intFormat = ctx->callData->args[0].toUInt32(); \ format = QLocale::FormatType(intFormat); \ } \ - return ctx->engine->newString(locale. FUNC (format))->asReturnedValue(); \ + return ctx->engine->newString(locale-> FUNC (format))->asReturnedValue(); \ } LOCALE_FORMAT(dateTimeFormat) @@ -607,7 +627,9 @@ LOCALE_FORMAT(dateFormat) // +1 added to idx because JS is 0-based, whereas QLocale months begin at 1. #define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::SimpleCallContext *ctx) {\ - QLocale locale = getThisLocale(ctx); \ + QLocale *locale = getThisLocale(ctx); \ + if (!locale) \ + return QV4::Encode::undefined(); \ if (ctx->callData->argc < 1 || ctx->callData->argc > 2) \ V4THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \ QLocale::FormatType enumFormat = QLocale::LongFormat; \ @@ -619,12 +641,12 @@ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::SimpleCallContext * if (ctx->callData->args[1].isNumber()) { \ quint32 intFormat = ctx->callData->args[1].toUInt32(); \ QLocale::FormatType format = QLocale::FormatType(intFormat); \ - name = locale. VARIABLE(idx, format); \ + name = locale-> VARIABLE(idx, format); \ } else { \ V4THROW_ERROR("Locale: Invalid datetime format"); \ } \ } else { \ - name = locale. VARIABLE(idx, enumFormat); \ + name = locale-> VARIABLE(idx, enumFormat); \ } \ return ctx->engine->newString(name)->asReturnedValue(); \ } @@ -632,7 +654,9 @@ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::SimpleCallContext * // 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date #define LOCALE_FORMATTED_DAYNAME(VARIABLE) \ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::SimpleCallContext *ctx) {\ - QLocale locale = getThisLocale(ctx); \ + QLocale *locale = getThisLocale(ctx); \ + if (!locale) \ + return QV4::Encode::undefined(); \ if (ctx->callData->argc < 1 || ctx->callData->argc > 2) \ V4THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \ QLocale::FormatType enumFormat = QLocale::LongFormat; \ @@ -645,12 +669,12 @@ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::SimpleCallContext * if (ctx->callData->args[1].isNumber()) { \ quint32 intFormat = ctx->callData->args[1].toUInt32(); \ QLocale::FormatType format = QLocale::FormatType(intFormat); \ - name = locale. VARIABLE(idx, format); \ + name = locale-> VARIABLE(idx, format); \ } else { \ V4THROW_ERROR("Locale: Invalid datetime format"); \ } \ } else { \ - name = locale. VARIABLE(idx, enumFormat); \ + name = locale-> VARIABLE(idx, enumFormat); \ } \ return ctx->engine->newString(name)->asReturnedValue(); \ } @@ -662,8 +686,10 @@ LOCALE_FORMATTED_DAYNAME(standaloneDayName) #define LOCALE_STRING_PROPERTY(VARIABLE) QV4::ReturnedValue QQmlLocaleData::method_get_ ## VARIABLE (QV4::SimpleCallContext* ctx) \ { \ - QLocale locale = getThisLocale(ctx); \ - return ctx->engine->newString(locale. VARIABLE())->asReturnedValue();\ + QLocale *locale = getThisLocale(ctx); \ + if (!locale) \ + return QV4::Encode::undefined(); \ + return ctx->engine->newString(locale-> VARIABLE())->asReturnedValue();\ } LOCALE_STRING_PROPERTY(name) diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index de2386daf1..ca53d1a53d 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -121,7 +121,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro Scoped w(scope, m->as()); if (!w) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); if (hasProperty) @@ -229,8 +229,10 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value) { QmlTypeWrapper *w = m->as(); QV4::ExecutionEngine *v4 = m->engine(); - if (!w) + if (!w) { v4->current->throwTypeError(); + return; + } QV4::Scope scope(v4); QV8Engine *v8engine = v4->v8Engine; @@ -255,6 +257,7 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value) if (!apiprivate) { QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"'); v4->current->throwError(error); + return; } else { apiprivate->put(name, value); } diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 6477f63daf..e892fb2c0c 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -208,8 +208,10 @@ PropertyAttributes QmlValueTypeWrapper::query(const Managed *m, StringRef name) { const QmlValueTypeWrapper *r = m->as(); QV4::ExecutionEngine *v4 = m->engine(); - if (!r) + if (!r) { v4->current->throwTypeError(); + return PropertyAttributes(); + } QQmlPropertyData local; QQmlPropertyData *result = 0; @@ -246,10 +248,10 @@ ReturnedValue QmlValueTypeWrapper::method_toString(SimpleCallContext *ctx) { Object *o = ctx->callData->thisObject.asObject(); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); QmlValueTypeWrapper *w = o->as(); if (!w) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (w->objectType == QmlValueTypeWrapper::Reference) { QmlValueTypeReference *reference = static_cast(w); @@ -271,7 +273,7 @@ ReturnedValue QmlValueTypeWrapper::get(Managed *m, const StringRef name, bool *h QmlValueTypeWrapper *r = m->as(); QV4::ExecutionEngine *v4 = m->engine(); if (!r) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); // Note: readReferenceValue() can change the reference->type. if (r->objectType == QmlValueTypeWrapper::Reference) { @@ -333,8 +335,10 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v ExecutionEngine *v4 = m->engine(); Scope scope(v4); Scoped r(scope, m->as()); - if (!r) + if (!r) { v4->current->throwTypeError(); + return; + } QByteArray propName = name->toQString().toUtf8(); if (r->objectType == QmlValueTypeWrapper::Reference) { @@ -359,6 +363,7 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v QString error = QLatin1String("Cannot assign JavaScript function to value-type property"); Scoped e(scope, r->v8->toString(error)); v4->current->throwError(e); + return; } QQmlContextData *context = r->v8->callingContext(); diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 8445b58430..e0666a1a57 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -422,7 +422,7 @@ ReturnedValue NodePrototype::method_get_nodeName(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); QString name; switch (r->d->type) { @@ -447,7 +447,7 @@ ReturnedValue NodePrototype::method_get_nodeValue(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (r->d->type == NodeImpl::Document || r->d->type == NodeImpl::DocumentFragment || @@ -466,7 +466,7 @@ ReturnedValue NodePrototype::method_get_nodeType(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); return Encode(r->d->type); } @@ -476,7 +476,7 @@ ReturnedValue NodePrototype::method_get_parentNode(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV8Engine *engine = ctx->engine->v8Engine; @@ -491,7 +491,7 @@ ReturnedValue NodePrototype::method_get_childNodes(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV8Engine *engine = ctx->engine->v8Engine; @@ -503,7 +503,7 @@ ReturnedValue NodePrototype::method_get_firstChild(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV8Engine *engine = ctx->engine->v8Engine; @@ -518,7 +518,7 @@ ReturnedValue NodePrototype::method_get_lastChild(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV8Engine *engine = ctx->engine->v8Engine; @@ -533,7 +533,7 @@ ReturnedValue NodePrototype::method_get_previousSibling(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV8Engine *engine = ctx->engine->v8Engine; @@ -557,7 +557,7 @@ ReturnedValue NodePrototype::method_get_nextSibling(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV8Engine *engine = ctx->engine->v8Engine; @@ -581,7 +581,7 @@ ReturnedValue NodePrototype::method_get_attributes(SimpleCallContext *ctx) Scope scope(ctx); Scoped r(scope, ctx->callData->thisObject.as()); if (!r) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV8Engine *engine = ctx->engine->v8Engine; @@ -907,7 +907,7 @@ ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty QV4::ExecutionEngine *v4 = m->engine(); NamedNodeMap *r = m->as(); if (!r) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); QV8Engine *engine = v4->v8Engine; @@ -926,7 +926,7 @@ ReturnedValue NamedNodeMap::get(Managed *m, const StringRef name, bool *hasPrope NamedNodeMap *r = m->as(); QV4::ExecutionEngine *v4 = m->engine(); if (!r) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); name->makeIdentifier(); if (name->equals(v4->id_length)) @@ -962,7 +962,7 @@ ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty) QV4::ExecutionEngine *v4 = m->engine(); NodeList *r = m->as(); if (!r) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); QV8Engine *engine = v4->v8Engine; @@ -981,7 +981,7 @@ ReturnedValue NodeList::get(Managed *m, const StringRef name, bool *hasProperty) QV4::ExecutionEngine *v4 = m->engine(); NodeList *r = m->as(); if (!r) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); name->makeIdentifier(); @@ -1540,13 +1540,17 @@ void QQmlXMLHttpRequest::dispatchCallback(const ValueRef me) QV4::Scope scope(v4); try { Scoped o(scope, me); - if (!o) + if (!o) { ctx->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject")); + return; + } ScopedString s(scope, v4->newString(QStringLiteral("ThisObject"))); Scoped thisObj(scope, o->get(s)); - if (!thisObj) + if (!thisObj) { ctx->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject")); + return; + } s = v4->newString(QStringLiteral("onreadystatechange")); Scoped callback(scope, thisObj->get(s)); @@ -1557,8 +1561,10 @@ void QQmlXMLHttpRequest::dispatchCallback(const ValueRef me) s = v4->newString(QStringLiteral("ActivationObject")); Scoped activationObject(scope, o->get(s)); - if (!activationObject) + if (!activationObject) { v4->current->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ActivationObject")); + return; + } QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject); if (callingContext) { @@ -1645,7 +1651,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject Scope scope(that->engine()); Scoped ctor(scope, that->as()); if (!ctor) - that->engine()->current->throwTypeError(); + return that->engine()->current->throwTypeError(); QV8Engine *engine = that->engine()->v8Engine; QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(engine, engine->networkAccessManager()); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index f9aca08d5a..047faabd1a 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1012,8 +1012,7 @@ ReturnedValue QtObject::method_createQmlObject(SimpleCallContext *ctx) if (component.isError()) { ScopedValue v(scope, Error::create(ctx->engine, component.errors())); - ctx->throwError(v); - return QV4::Encode::undefined(); + return ctx->throwError(v); } if (!component.isReady()) @@ -1037,8 +1036,7 @@ ReturnedValue QtObject::method_createQmlObject(SimpleCallContext *ctx) if (component.isError()) { ScopedValue v(scope, Error::create(ctx->engine, component.errors())); - ctx->throwError(v); - return QV4::Encode::undefined(); + return ctx->throwError(v); } Q_ASSERT(obj); @@ -1080,7 +1078,7 @@ use \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}. ReturnedValue QtObject::method_createComponent(SimpleCallContext *ctx) { if (ctx->callData->argc < 1 || ctx->callData->argc > 3) - ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); + return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); Scope scope(ctx); @@ -1108,13 +1106,13 @@ ReturnedValue QtObject::method_createComponent(SimpleCallContext *ctx) if (ctx->callData->args[1].isInteger()) { int mode = ctx->callData->args[1].integerValue(); if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous)) - ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); + return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); compileMode = QQmlComponent::CompilationMode(mode); consumedCount += 1; } else { // The second argument could be the parent only if there are exactly two args if ((ctx->callData->argc != 2) || !(lastArg->isObject() || lastArg->isNull())) - ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); + return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); } if (consumedCount < ctx->callData->argc) { @@ -1123,11 +1121,11 @@ ReturnedValue QtObject::method_createComponent(SimpleCallContext *ctx) if (qobjectWrapper) parentArg = qobjectWrapper->object(); if (!parentArg) - ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object")); + return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object")); } else if (lastArg->isNull()) { parentArg = 0; } else { - ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object")); + return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object")); } } } @@ -1272,10 +1270,10 @@ ReturnedValue QtObject::method_get_platform(SimpleCallContext *ctx) // ### inefficient. Should be just a value based getter Object *o = ctx->callData->thisObject.asObject(); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); QtObject *qt = o->as(); if (!qt) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (!qt->m_platform) // Only allocate a platform object once @@ -1289,10 +1287,10 @@ ReturnedValue QtObject::method_get_application(SimpleCallContext *ctx) // ### inefficient. Should be just a value based getter Object *o = ctx->callData->thisObject.asObject(); if (!o) - ctx->throwTypeError(); + return ctx->throwTypeError(); QtObject *qt = o->as(); if (!qt) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (!qt->m_application) // Only allocate an application object once diff --git a/src/qml/qml/v8/qv4domerrors_p.h b/src/qml/qml/v8/qv4domerrors_p.h index 44662e8cba..faf52ce1ad 100644 --- a/src/qml/qml/v8/qv4domerrors_p.h +++ b/src/qml/qml/v8/qv4domerrors_p.h @@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE QV4::ScopedValue v(scope, ctx->engine->newString(QStringLiteral(string))); \ QV4::Scoped ex(scope, ctx->engine->newErrorObject(v)); \ ex->put(QV4::ScopedString(scope, ctx->engine->newIdentifier(QStringLiteral("code"))), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(error))); \ - ctx->throwError(ex); \ + return ctx->throwError(ex); \ } namespace QV4 { diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index a92d03ac50..e37b0d4920 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -86,10 +86,10 @@ namespace QV4 { // #define QML_GLOBAL_HANDLE_DEBUGGING #define V4THROW_ERROR(string) \ - ctx->throwError(QString::fromUtf8(string)); + return ctx->throwError(QString::fromUtf8(string)); #define V4THROW_TYPE(string) \ - ctx->throwTypeError(QStringLiteral(string)); + return ctx->throwTypeError(QStringLiteral(string)); #define V8_DEFINE_EXTENSION(dataclass, datafunction) \ static inline dataclass *datafunction(QV8Engine *engine) \ diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 10f957ab40..a1163f0a98 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -76,8 +76,7 @@ struct DelegateModelGroupFunction: QV4::FunctionObject static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *) { - m->engine()->current->throwTypeError(); - return QV4::Primitive::undefinedValue().asReturnedValue(); + return m->engine()->current->throwTypeError(); } static QV4::ReturnedValue call(QV4::Managed *that, QV4::CallData *callData) @@ -87,7 +86,7 @@ struct DelegateModelGroupFunction: QV4::FunctionObject QV4::Scoped f(scope, that, QV4::Scoped::Cast); QV4::Scoped o(scope, callData->thisObject); if (!o) - v4->current->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return v4->current->throwTypeError(QStringLiteral("Not a valid VisualData object")); QV4::ScopedValue v(scope, callData->argument(0)); return f->code(o->item, f->flag, v); @@ -1711,7 +1710,7 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_model(QV4::SimpleCallContext *ctx) QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); if (!o->item->metaType->model) return QV4::Encode::undefined(); @@ -1723,7 +1722,7 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_groups(QV4::SimpleCallContext *ctx QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); QStringList groups; for (int i = 1; i < o->item->metaType->groupCount; ++i) { @@ -1739,9 +1738,9 @@ QV4::ReturnedValue QQmlDelegateModelItem::set_groups(QV4::SimpleCallContext *ctx QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); if (!ctx->callData->argc) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (!o->item->metaType->model) return QV4::Encode::undefined(); @@ -3153,21 +3152,21 @@ struct QQmlDelegateModelGroupChange : QV4::Object QV4::Scope scope(ctx); QV4::Scoped that(scope, ctx->callData->thisObject.as()); if (!that) - ctx->throwTypeError(); + return ctx->throwTypeError(); return QV4::Encode(that->change.index); } static QV4::ReturnedValue method_get_count(QV4::SimpleCallContext *ctx) { QV4::Scope scope(ctx); QV4::Scoped that(scope, ctx->callData->thisObject.as()); if (!that) - ctx->throwTypeError(); + return ctx->throwTypeError(); return QV4::Encode(that->change.count); } static QV4::ReturnedValue method_get_moveId(QV4::SimpleCallContext *ctx) { QV4::Scope scope(ctx); QV4::Scoped that(scope, ctx->callData->thisObject.as()); if (!that) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (that->change.moveId < 0) return QV4::Encode::undefined(); return QV4::Encode(that->change.moveId); @@ -3199,7 +3198,7 @@ public: QV4::Scope scope(v4); QV4::Scoped array(scope, m->as()); if (!array) - v4->current->throwTypeError(); + return v4->current->throwTypeError(); if (index >= array->count()) { if (hasProperty) @@ -3223,7 +3222,7 @@ public: { QQmlDelegateModelGroupChangeArray *array = m->as(); if (!array) - m->engine()->current->throwTypeError(); + return m->engine()->current->throwTypeError(); if (name->equals(m->engine()->id_length)) { if (hasProperty) diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index 39ebd6bd4c..e8efd46039 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -68,7 +68,7 @@ static QV4::ReturnedValue get_index(QV4::SimpleCallContext *ctx) QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); return QV4::Encode(o->item->index); } @@ -200,7 +200,7 @@ public: QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); const QQmlAdaptorModel *const model = static_cast(o->item)->type->model; if (o->item->index >= 0 && *model) { @@ -344,7 +344,7 @@ QV4::ReturnedValue QQmlDMCachedModelData::get_property(QV4::SimpleCallContext *c QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); QQmlDMCachedModelData *modelData = static_cast(o->item); if (o->item->index == -1) { @@ -364,9 +364,9 @@ QV4::ReturnedValue QQmlDMCachedModelData::set_property(QV4::SimpleCallContext *c QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); if (!ctx->callData->argc) - ctx->throwTypeError(); + return ctx->throwTypeError(); if (o->item->index == -1) { QQmlDMCachedModelData *modelData = static_cast(o->item); @@ -584,7 +584,7 @@ public: QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); return ctx->engine->v8Engine->fromVariant(static_cast(o->item)->cachedData); } @@ -594,9 +594,9 @@ public: QV4::Scope scope(ctx); QV4::Scoped o(scope, ctx->callData->thisObject.as()); if (!o) - ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object")); if (!ctx->callData->argc) - ctx->throwTypeError(); + return ctx->throwTypeError(); static_cast(o->item)->setModelData(ctx->engine->v8Engine->toVariant(ctx->callData->args[0], QVariant::Invalid)); return QV4::Encode::undefined(); -- cgit v1.2.3