aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-10-22 13:26:08 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-29 10:39:01 +0100
commitffcdbfa03f8bb36b521f8c1a703ee24085fe25bd (patch)
treeddee0370444a4f71cabb7847e7f1eb758622bd9f /src/qml
parentaf22149dd8daf593182fec978f15dc1667c9cf8d (diff)
Protect write accesses to objects
Don't write to objects if we have a pending exception to avoid any side effects. Change-Id: I9f93a9195a652dbae7033cc6ebb355d5d86e9b5e Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp54
-rw-r--r--src/qml/jsruntime/qv4engine.cpp8
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp24
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp3
-rw-r--r--src/qml/jsruntime/qv4object.cpp23
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp4
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp3
-rw-r--r--src/qml/jsruntime/qv4string.cpp5
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp5
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp3
17 files changed, 129 insertions, 23 deletions
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index b1308e12fb..22ad10560e 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -213,6 +213,8 @@ ReturnedValue ArrayPrototype::method_join(SimpleCallContext *ctx)
R += r4;
e = a->getIndexed(i);
+ if (scope.hasException())
+ return Encode::undefined();
if (!e->isNullOrUndefined())
R += e->toString(ctx)->toQString();
}
@@ -231,6 +233,8 @@ ReturnedValue ArrayPrototype::method_join(SimpleCallContext *ctx)
name = Primitive::fromDouble(k).toString(ctx);
r12 = self->get(name);
+ if (scope.hasException())
+ return Encode::undefined();
if (!r12->isNullOrUndefined())
R += r12->toString(ctx)->toQString();
@@ -255,8 +259,12 @@ ReturnedValue ArrayPrototype::method_pop(SimpleCallContext *ctx)
}
ScopedValue result(scope, instance->getIndexed(len - 1));
+ if (scope.hasException())
+ return Encode::undefined();
instance->deleteIndexedProperty(len - 1);
+ if (scope.hasException())
+ return Encode::undefined();
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
else
@@ -334,10 +342,14 @@ ReturnedValue ArrayPrototype::method_reverse(SimpleCallContext *ctx)
bool loExists, hiExists;
lval = instance->getIndexed(lo, &loExists);
hval = instance->getIndexed(hi, &hiExists);
+ if (scope.hasException())
+ return Encode::undefined();
if (hiExists)
instance->putIndexed(lo, hval);
else
instance->deleteIndexedProperty(lo);
+ if (scope.hasException())
+ return Encode::undefined();
if (loExists)
instance->putIndexed(hi, lval);
else
@@ -387,12 +399,16 @@ ReturnedValue ArrayPrototype::method_shift(SimpleCallContext *ctx)
for (uint k = 1; k < len; ++k) {
bool exists;
v = instance->getIndexed(k, &exists);
+ if (scope.hasException())
+ return Encode::undefined();
if (exists)
instance->putIndexed(k - 1, v);
else
instance->deleteIndexedProperty(k - 1);
}
instance->deleteIndexedProperty(len - 1);
+ if (scope.hasException())
+ return Encode::undefined();
}
if (instance->isArrayObject())
@@ -435,9 +451,10 @@ ReturnedValue ArrayPrototype::method_slice(SimpleCallContext *ctx)
for (uint i = start; i < end; ++i) {
bool exists;
v = o->getIndexed(i, &exists);
- if (exists) {
+ if (scope.hasException())
+ return Encode::undefined();
+ if (exists)
result->arraySet(n, v);
- }
++n;
}
return result.asReturnedValue();
@@ -479,6 +496,8 @@ ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx)
newArray->arrayReserve(deleteCount);
for (uint i = 0; i < deleteCount; ++i) {
newArray->arrayData[i].value = instance->getIndexed(start + i);
+ if (scope.hasException())
+ return Encode::undefined();
newArray->arrayDataLen = i + 1;
}
newArray->setArrayLengthUnchecked(deleteCount);
@@ -490,28 +509,42 @@ ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx)
for (uint k = start; k < len - deleteCount; ++k) {
bool exists;
v = instance->getIndexed(k + deleteCount, &exists);
+ if (scope.hasException())
+ return Encode::undefined();
if (exists)
instance->putIndexed(k + itemCount, v);
else
instance->deleteIndexedProperty(k + itemCount);
+ if (scope.hasException())
+ return Encode::undefined();
}
- for (uint k = len; k > len - deleteCount + itemCount; --k)
+ for (uint k = len; k > len - deleteCount + itemCount; --k) {
instance->deleteIndexedProperty(k - 1);
+ if (scope.hasException())
+ return Encode::undefined();
+ }
} else if (itemCount > deleteCount) {
uint k = len - deleteCount;
while (k > start) {
bool exists;
v = instance->getIndexed(k + deleteCount - 1, &exists);
+ if (scope.hasException())
+ return Encode::undefined();
if (exists)
instance->putIndexed(k + itemCount - 1, v);
else
instance->deleteIndexedProperty(k + itemCount - 1);
+ if (scope.hasException())
+ return Encode::undefined();
--k;
}
}
- for (uint i = 0; i < itemCount; ++i)
+ for (uint i = 0; i < itemCount; ++i) {
instance->putIndexed(start + i, ctx->callData->args[i + 2]);
+ if (scope.hasException())
+ return Encode::undefined();
+ }
ctx->strictMode = true;
instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
@@ -582,16 +615,13 @@ ReturnedValue ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
if (!len)
return Encode(-1);
- ScopedValue searchValue(scope);
+ ScopedValue searchValue(scope, ctx->callData->argument(0));
uint fromIndex = 0;
- if (ctx->callData->argc >= 1)
- searchValue = ctx->callData->args[0];
- else
- searchValue = Primitive::undefinedValue();
-
if (ctx->callData->argc >= 2) {
double f = ctx->callData->args[1].toInteger();
+ if (scope.hasException())
+ return Encode::undefined();
if (f >= len)
return Encode(-1);
if (f < 0)
@@ -634,6 +664,8 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
if (ctx->callData->argc >= 2) {
double f = ctx->callData->args[1].toInteger();
+ if (scope.hasException())
+ return Encode::undefined();
if (f > 0)
f = qMin(f, (double)(len - 1));
else if (f < 0) {
@@ -649,6 +681,8 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
--k;
bool exists;
v = instance->getIndexed(k, &exists);
+ if (scope.hasException())
+ return Encode::undefined();
if (exists && __qmljs_strict_equal(v, searchValue))
return Encode(k);
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index cf39d7df4f..bb11011669 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -808,7 +808,13 @@ QmlExtensions *ExecutionEngine::qmlExtensions()
ReturnedValue ExecutionEngine::throwException(const ValueRef value)
{
-// Q_ASSERT(!hasException);
+ // we can get in here with an exception already set, as the runtime
+ // doesn't check after every operation that can throw.
+ // in this case preserve the first exception to give correct error
+ // information
+ if (hasException)
+ return Encode::undefined();
+
hasException = true;
exceptionValue = value;
QV4::Scope scope(this);
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index b2ef86525f..7c61a34190 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -250,6 +250,8 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
}
body = callData->args[callData->argc - 1].toString(ctx)->toQString();
}
+ if (ctx->engine->hasException)
+ return Encode::undefined();
QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}");
@@ -431,6 +433,9 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
{
ExecutionEngine *v4 = that->engine();
Scope scope(v4);
+ if (scope.hasException())
+ return Encode::undefined();
+
Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
InternalClass *ic = v4->objectClass;
@@ -456,6 +461,9 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
void *stackSpace;
ExecutionContext *context = f->engine()->current;
Scope scope(context);
+ if (scope.hasException())
+ return Encode::undefined();
+
CallContext *ctx = context->newCallContext(f, callData);
if (!f->strictMode && !callData->thisObject.isObject()) {
@@ -511,6 +519,9 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
{
ExecutionEngine *v4 = that->engine();
Scope scope(v4);
+ if (scope.hasException())
+ return Encode::undefined();
+
Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
InternalClass *ic = v4->objectClass;
@@ -536,6 +547,9 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
{
ExecutionEngine *v4 = that->engine();
Scope scope(v4);
+ if (scope.hasException())
+ return Encode::undefined();
+
Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f));
@@ -576,6 +590,9 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
BuiltinFunction *f = static_cast<BuiltinFunction *>(that);
ExecutionEngine *v4 = f->engine();
Scope scope(v4);
+ if (scope.hasException())
+ return Encode::undefined();
+
ExecutionContext *context = v4->current;
SimpleCallContext ctx;
@@ -594,6 +611,8 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
ExecutionEngine *v4 = f->engine();
ExecutionContext *context = v4->current;
Scope scope(v4);
+ if (scope.hasException())
+ return Encode::undefined();
SimpleCallContext ctx;
ctx.initSimpleCallContext(f->scope->engine);
@@ -643,6 +662,8 @@ ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
Scope scope(f->scope->engine);
+ if (scope.hasException())
+ return Encode::undefined();
ScopedCallData callData(scope, f->boundArgs.size() + dd->argc);
callData->thisObject = f->boundThis;
@@ -655,6 +676,9 @@ ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
Scope scope(f->scope->engine);
+ if (scope.hasException())
+ return Encode::undefined();
+
ScopedCallData callData(scope, f->boundArgs.size() + dd->argc);
memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(SafeValue));
memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(SafeValue));
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 084b508b52..fca49308cc 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -469,6 +469,10 @@ ReturnedValue GlobalFunctions::method_parseInt(SimpleCallContext *ctx)
// [15.1.2.2] step by step:
String *inputString = string->toString(ctx); // 1
QString trimmed = inputString->toQString().trimmed(); // 2
+
+ if (ctx->engine->hasException)
+ return Encode::undefined();
+
const QChar *pos = trimmed.constData();
const QChar *end = pos + trimmed.length();
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 721843afba..5a8acf803c 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -801,7 +801,7 @@ QString Stringify::JO(ObjectRef o)
name = it.nextPropertyNameAsString(val);
if (name->isNull())
break;
- QString key = name->toQStringNoThrow();
+ QString key = name->toQString();
QString member = makeMember(key, val);
if (!member.isEmpty())
partial += member;
@@ -951,7 +951,7 @@ ReturnedValue JsonObject::method_stringify(SimpleCallContext *ctx)
ScopedValue arg0(scope, ctx->argument(0));
QString result = stringify.Str(QString(), arg0);
- if (result.isEmpty())
+ if (result.isEmpty() || scope.engine->hasException)
return Encode::undefined();
return ctx->engine->newString(result)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index dd13f493f7..098afa8161 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -177,10 +177,9 @@ ReturnedValue NumberPrototype::method_toLocaleString(SimpleCallContext *ctx)
{
Scope scope(ctx);
ScopedValue v(scope, thisNumberValue(ctx));
+ ScopedString str(scope, v->toString(ctx));
if (ctx->engine->hasException)
return Encode::undefined();
-
- ScopedString str(scope, v->toString(ctx));
return str.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index ca02d6703a..3277ea96ab 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -147,6 +147,9 @@ ReturnedValue Object::getValue(const ValueRef thisObject, const Property *p, Pro
void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef value)
{
+ if (internalClass->engine->hasException)
+ return;
+
if (attrs.isAccessor()) {
if (pd->set) {
Scope scope(pd->set->engine());
@@ -689,6 +692,9 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
// Section 8.12.5
void Object::internalPut(const StringRef name, const ValueRef value)
{
+ if (internalClass->engine->hasException)
+ return;
+
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
return putIndexed(idx, value);
@@ -773,6 +779,9 @@ void Object::internalPut(const StringRef name, const ValueRef value)
void Object::internalPutIndexed(uint index, const ValueRef value)
{
+ if (internalClass->engine->hasException)
+ return;
+
Property *pd = 0;
PropertyAttributes attrs;
@@ -842,6 +851,9 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
// Section 8.12.7
bool Object::internalDeleteProperty(const StringRef name)
{
+ if (internalClass->engine->hasException)
+ return false;
+
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
return deleteIndexedProperty(idx);
@@ -865,6 +877,9 @@ bool Object::internalDeleteProperty(const StringRef name)
bool Object::internalDeleteIndexedProperty(uint index)
{
+ if (internalClass->engine->hasException)
+ return false;
+
uint pidx = propertyIndexFromArrayIndex(index);
if (pidx == UINT_MAX)
return true;
@@ -1121,12 +1136,16 @@ ReturnedValue Object::arrayIndexOf(const ValueRef v, uint fromIndex, uint endInd
for (uint i = fromIndex; i < endIndex; ++i) {
bool exists;
value = o->getIndexed(i, &exists);
+ if (scope.hasException())
+ return Encode::undefined();
if (exists && __qmljs_strict_equal(value, v))
return Encode(i);
}
} else if (sparseArray) {
for (SparseArrayNode *n = sparseArray->lowerBound(fromIndex); n != sparseArray->end() && n->key() < endIndex; n = n->nextNode()) {
value = o->getValue(arrayData + n->value, arrayAttributes ? arrayAttributes[n->value] : Attr_Data);
+ if (scope.hasException())
+ return Encode::undefined();
if (__qmljs_strict_equal(value, v))
return Encode(n->key());
}
@@ -1139,6 +1158,8 @@ ReturnedValue Object::arrayIndexOf(const ValueRef v, uint fromIndex, uint endInd
while (pd < end) {
if (!pd->value.isEmpty()) {
value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data);
+ if (scope.hasException())
+ return Encode::undefined();
if (__qmljs_strict_equal(value, v))
return Encode((uint)(pd - arrayData));
}
@@ -1437,7 +1458,7 @@ QStringList ArrayObject::toQStringList() const
uint32_t length = arrayLength();
for (uint32_t i = 0; i < length; ++i) {
v = const_cast<ArrayObject *>(this)->getIndexed(i);
- result.append(v->toString(engine->current)->toQString());
+ result.append(v->toQStringNoThrow());
}
return result;
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 061487f8af..c8202a5bad 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -158,6 +158,8 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(SimpleCallContext
ScopedValue v(scope, ctx->argument(1));
Scoped<String> name(scope, v->toString(ctx));
+ if (scope.hasException())
+ return Encode::undefined();
PropertyAttributes attrs;
Property *desc = O->__getOwnProperty__(name, &attrs);
return fromPropertyDescriptor(ctx, desc, attrs);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index a581e6bc69..acdfc1ba52 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -627,7 +627,7 @@ void QObjectWrapper::put(Managed *m, const StringRef name, const ValueRef value)
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
ExecutionEngine *v4 = m->engine();
- if (QQmlData::wasDeleted(that->m_object))
+ if (v4->hasException || QQmlData::wasDeleted(that->m_object))
return;
QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 8bcddcce0a..4f0f07377f 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -258,6 +258,8 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
QString pattern;
if (!r->isUndefined())
pattern = r->toString(ctx)->toQString();
+ if (scope.hasException())
+ return Encode::undefined();
bool global = false;
bool ignoreCase = false;
@@ -265,6 +267,8 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
if (!f->isUndefined()) {
f = __qmljs_to_string(f, ctx);
QString str = f->stringValue()->toQString();
+ if (scope.hasException())
+ return Encode::undefined();
for (int i = 0; i < str.length(); ++i) {
if (str.at(i) == QChar('g') && !global) {
global = true;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index dbbccdea70..5678294115 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -478,8 +478,6 @@ 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);
}
@@ -571,8 +569,6 @@ 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);
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index f6feb2f170..5a42c7fe35 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -231,6 +231,9 @@ public:
void containerPutIndexed(uint index, const QV4::ValueRef value)
{
+ if (internalClass->engine->hasException)
+ return;
+
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
generateWarning(engine()->current, QLatin1String("Index out of range during indexed set"));
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index fd366d26ac..bd4e2b16b0 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -178,6 +178,8 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty)
void String::put(Managed *m, const StringRef name, const ValueRef value)
{
Scope scope(m->engine());
+ if (scope.hasException())
+ return;
ScopedString that(scope, static_cast<String *>(m));
Scoped<Object> o(scope, that->engine()->newStringObject(that));
o->put(name, value);
@@ -186,6 +188,9 @@ void String::put(Managed *m, const StringRef name, const ValueRef value)
void String::putIndexed(Managed *m, uint index, const ValueRef value)
{
Scope scope(m->engine());
+ if (scope.hasException())
+ return;
+
ScopedString that(scope, static_cast<String *>(m));
Scoped<Object> o(scope, that->engine()->newStringObject(that));
o->putIndexed(index, value);
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 36d1433665..f36c7d84a4 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -597,15 +597,16 @@ ReturnedValue StringPrototype::method_search(SimpleCallContext *ctx)
{
Scope scope(ctx);
QString string = getThisString(ctx);
+ ScopedValue regExpValue(scope, ctx->argument(0));
if (scope.engine->hasException)
return Encode::undefined();
-
- ScopedValue regExpValue(scope, ctx->argument(0));
Scoped<RegExpObject> regExp(scope, regExpValue->as<RegExpObject>());
if (!regExp) {
ScopedCallData callData(scope, 1);
callData->args[0] = regExpValue;
regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(callData);
+ if (scope.engine->hasException)
+ return Encode::undefined();
regExp = regExpValue->as<RegExpObject>();
Q_ASSERT(regExp);
}
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index a187b17a08..d3bcf6d3fd 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -281,6 +281,8 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val
{
ExecutionEngine *v4 = m->engine();
QV4::Scope scope(v4);
+ if (scope.hasException())
+ return;
QV4::Scoped<QmlContextWrapper> wrapper(scope, m->as<QmlContextWrapper>());
if (!wrapper) {
v4->current->throwTypeError();
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index ca53d1a53d..3fb3d19270 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -229,6 +229,8 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value)
{
QmlTypeWrapper *w = m->as<QmlTypeWrapper>();
QV4::ExecutionEngine *v4 = m->engine();
+ if (v4->hasException)
+ return;
if (!w) {
v4->current->throwTypeError();
return;
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index e892fb2c0c..6c9f90cada 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -334,6 +334,9 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v
{
ExecutionEngine *v4 = m->engine();
Scope scope(v4);
+ if (scope.hasException())
+ return;
+
Scoped<QmlValueTypeWrapper> r(scope, m->as<QmlValueTypeWrapper>());
if (!r) {
v4->current->throwTypeError();