aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsapi/qjsengine.cpp2
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp106
-rw-r--r--src/qml/jsruntime/qv4context.cpp26
-rw-r--r--src/qml/jsruntime/qv4context_p.h2
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp68
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h20
-rw-r--r--src/qml/jsruntime/qv4object.cpp80
-rw-r--r--src/qml/jsruntime/qv4object_p.h21
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp25
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h6
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp7
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp15
12 files changed, 185 insertions, 193 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 6eede17ab4..1c7540778b 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -446,7 +446,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
QV4::ScopedValue result(scope);
QV4::Script script(ctx, program, fileName, lineNumber);
- script.strictMode = ctx->d()->v4Function->isStrict();
+ script.strictMode = ctx->d()->strictMode;
script.inheritContext = true;
script.parse();
if (!scope.engine->hasException)
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 383c395b1b..67781bcbb1 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -173,6 +173,7 @@ ReturnedValue ArrayPrototype::method_concat(const BuiltinFunction *b, CallData *
const uint startIndex = result->getLength();
for (int i = 0, len = eltAsObj->getLength(); i < len; ++i) {
entry = eltAsObj->getIndexed(i);
+ // spec says not to throw if this fails
result->putIndexed(startIndex + i, entry);
}
} else {
@@ -356,17 +357,19 @@ ReturnedValue ArrayPrototype::method_push(const BuiltinFunction *b, CallData *ca
uint len = instance->getLength();
if (len + callData->argc < len) {
- // ughh...
+ // ughh... this goes beyond UINT_MAX
double l = len;
ScopedString s(scope);
for (int i = 0; i < callData->argc; ++i) {
s = Primitive::fromDouble(l + i).toString(scope.engine);
- instance->put(s, callData->args[i]);
+ if (!instance->put(s, callData->args[i]))
+ return scope.engine->throwTypeError();
}
double newLen = l + callData->argc;
- if (!instance->isArrayObject())
- instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
- else {
+ if (!instance->isArrayObject()) {
+ if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen))))
+ return scope.engine->throwTypeError();
+ } else {
ScopedString str(scope, scope.engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
return scope.engine->throwRangeError(str);
}
@@ -380,13 +383,16 @@ ReturnedValue ArrayPrototype::method_push(const BuiltinFunction *b, CallData *ca
len = instance->arrayData()->length();
} else {
for (int i = 0; i < callData->argc; ++i)
- instance->putIndexed(len + i, callData->args[i]);
+ if (!instance->putIndexed(len + i, callData->args[i]))
+ return scope.engine->throwTypeError();
len += callData->argc;
}
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len);
- else
- instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len)));
+ else {
+ if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len))))
+ return scope.engine->throwTypeError();
+ }
return Encode(len);
}
@@ -409,15 +415,19 @@ ReturnedValue ArrayPrototype::method_reverse(const BuiltinFunction *b, CallData
lval = instance->getIndexed(lo, &loExists);
hval = instance->getIndexed(hi, &hiExists);
CHECK_EXCEPTION();
+ bool ok;
if (hiExists)
- instance->putIndexed(lo, hval);
- else
- instance->deleteIndexedProperty(lo);
- CHECK_EXCEPTION();
- if (loExists)
- instance->putIndexed(hi, lval);
+ ok = instance->putIndexed(lo, hval);
else
- instance->deleteIndexedProperty(hi);
+ ok = instance->deleteIndexedProperty(lo);
+ if (ok) {
+ if (loExists)
+ ok = instance->putIndexed(hi, lval);
+ else
+ ok = instance->deleteIndexedProperty(hi);
+ }
+ if (!ok)
+ return scope.engine->throwTypeError();
}
return instance->asReturnedValue();
}
@@ -436,7 +446,8 @@ ReturnedValue ArrayPrototype::method_shift(const BuiltinFunction *b, CallData *c
if (!len) {
if (!instance->isArrayObject())
- instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
+ if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0))))
+ return scope.engine->throwTypeError();
RETURN_UNDEFINED();
}
@@ -452,20 +463,26 @@ ReturnedValue ArrayPrototype::method_shift(const BuiltinFunction *b, CallData *c
bool exists;
v = instance->getIndexed(k, &exists);
CHECK_EXCEPTION();
+ bool ok;
if (exists)
- instance->putIndexed(k - 1, v);
+ ok = instance->putIndexed(k - 1, v);
else
- instance->deleteIndexedProperty(k - 1);
- CHECK_EXCEPTION();
+ ok = instance->deleteIndexedProperty(k - 1);
+ if (!ok)
+ return scope.engine->throwTypeError();
}
- instance->deleteIndexedProperty(len - 1);
- CHECK_EXCEPTION();
+ bool ok = instance->deleteIndexedProperty(len - 1);
+ if (!ok)
+ return scope.engine->throwTypeError();
}
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
- else
- instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ else {
+ bool ok = instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ if (!ok)
+ return scope.engine->throwTypeError();
+ }
return result->asReturnedValue();
}
@@ -563,11 +580,13 @@ ReturnedValue ArrayPrototype::method_splice(const BuiltinFunction *b, CallData *
bool exists;
v = instance->getIndexed(k + deleteCount, &exists);
CHECK_EXCEPTION();
+ bool ok;
if (exists)
- instance->putIndexed(k + itemCount, v);
+ ok = instance->putIndexed(k + itemCount, v);
else
- instance->deleteIndexedProperty(k + itemCount);
- CHECK_EXCEPTION();
+ ok = instance->deleteIndexedProperty(k + itemCount);
+ if (!ok)
+ return scope.engine->throwTypeError();
}
for (uint k = len; k > len - deleteCount + itemCount; --k) {
instance->deleteIndexedProperty(k - 1);
@@ -579,21 +598,22 @@ ReturnedValue ArrayPrototype::method_splice(const BuiltinFunction *b, CallData *
bool exists;
v = instance->getIndexed(k + deleteCount - 1, &exists);
CHECK_EXCEPTION();
+ bool ok;
if (exists)
- instance->putIndexed(k + itemCount - 1, v);
+ ok = instance->putIndexed(k + itemCount - 1, v);
else
- instance->deleteIndexedProperty(k + itemCount - 1);
- CHECK_EXCEPTION();
+ ok = instance->deleteIndexedProperty(k + itemCount - 1);
+ if (!ok)
+ return scope.engine->throwTypeError();
--k;
}
}
- for (uint i = 0; i < itemCount; ++i) {
+ for (uint i = 0; i < itemCount; ++i)
instance->putIndexed(start + i, callData->args[i + 2]);
- CHECK_EXCEPTION();
- }
- instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
+ if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount))))
+ return scope.engine->throwTypeError();
return newArray->asReturnedValue();
}
@@ -618,20 +638,28 @@ ReturnedValue ArrayPrototype::method_unshift(const BuiltinFunction *b, CallData
for (uint k = len; k > 0; --k) {
bool exists;
v = instance->getIndexed(k - 1, &exists);
+ bool ok;
if (exists)
- instance->putIndexed(k + callData->argc - 1, v);
+ ok = instance->putIndexed(k + callData->argc - 1, v);
else
- instance->deleteIndexedProperty(k + callData->argc - 1);
+ ok = instance->deleteIndexedProperty(k + callData->argc - 1);
+ if (!ok)
+ return scope.engine->throwTypeError();
+ }
+ for (int i = 0; i < callData->argc; ++i) {
+ bool ok = instance->putIndexed(i, callData->args[i]);
+ if (!ok)
+ return scope.engine->throwTypeError();
}
- for (int i = 0; i < callData->argc; ++i)
- instance->putIndexed(i, callData->args[i]);
}
uint newLen = len + callData->argc;
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(newLen);
- else
- instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
+ else {
+ if (!instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen))))
+ return scope.engine->throwTypeError();
+ }
return Encode(newLen);
}
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 8678529916..add007fdfb 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -280,7 +280,7 @@ ReturnedValue QV4::ExecutionContext::simpleCall(ExecutionEngine *engine, CallDat
return res;
}
-void ExecutionContext::setProperty(String *name, const Value &value)
+bool ExecutionContext::setProperty(String *name, const Value &value)
{
name->makeIdentifier();
Identifier *id = name->identifier();
@@ -294,7 +294,7 @@ void ExecutionContext::setProperty(String *name, const Value &value)
Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx);
if (c->exceptionVarName->isEqualTo(name->d())) {
c->exceptionValue.set(v4, value);
- return;
+ return true;
}
break;
}
@@ -302,10 +302,8 @@ void ExecutionContext::setProperty(String *name, const Value &value)
// the semantics are different from the setProperty calls of other activations
Scope scope(v4);
ScopedObject w(scope, ctx->activation);
- if (w->hasProperty(name)) {
- w->put(name, value);
- return;
- }
+ if (w->hasProperty(name))
+ return w->put(name, value);
break;
}
case Heap::ExecutionContext::Type_CallContext:
@@ -321,7 +319,7 @@ void ExecutionContext::setProperty(String *name, const Value &value)
index -= c->v4Function->nFormals;
static_cast<Heap::CallContext *>(c)->locals.set(v4, index, value);
}
- return;
+ return true;
}
}
}
@@ -332,26 +330,22 @@ void ExecutionContext::setProperty(String *name, const Value &value)
if (member < UINT_MAX) {
Scope scope(v4);
ScopedObject a(scope, ctx->activation);
- a->putValue(member, value);
- return;
+ return a->putValue(member, value);
}
}
break;
case Heap::ExecutionContext::Type_QmlContext: {
Scope scope(v4);
ScopedObject activation(scope, ctx->activation);
- activation->put(name, value);
- return;
+ return activation->put(name, value);
}
}
}
- if (d()->strictMode) {
- engine()->throwReferenceError(*name);
- return;
- }
- engine()->globalObject->put(name, value);
+ if (d()->strictMode)
+ return false;
+ return engine()->globalObject->put(name, value);
}
ReturnedValue ExecutionContext::getProperty(String *name)
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 0945087de2..67f50e5c25 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -200,7 +200,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
void createMutableBinding(String *name, bool deletable);
- void setProperty(String *name, const Value &value);
+ bool setProperty(String *name, const Value &value);
ReturnedValue getProperty(String *name);
ReturnedValue getPropertyAndBase(String *name, Value *base);
bool deleteProperty(String *name);
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index ae74e0d14c..8d2d18fa2a 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -689,87 +689,88 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
return globalGetterGeneric(l, engine);
}
-void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Scope scope(engine);
ScopedObject o(scope, object);
if (!o) {
o = RuntimeHelpers::convertToObject(scope.engine, object);
if (!o) // type error
- return;
+ return false;
ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]);
- o->put(name, value);
- return;
+ return o->put(name, value);
}
- o->setLookup(l, value);
+ return o->setLookup(l, value);
}
-void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Lookup l1 = *l;
if (Object *o = object.as<Object>()) {
- o->setLookup(l, value);
+ if (!o->setLookup(l, value))
+ return false;
if (l->setter == Lookup::setter0 || l->setter == Lookup::setter0Inline) {
l->setter = setter0setter0;
l->classList[1] = l1.classList[0];
l->index2 = l1.index;
- return;
+ return true;
}
}
l->setter = setterFallback;
- setterFallback(l, engine, object, value);
+ return setterFallback(l, engine, object, value);
}
-void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
QV4::Scope scope(engine);
QV4::ScopedObject o(scope, object.toObject(scope.engine));
- if (o) {
- ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]);
- o->put(name, value);
- }
+ if (!o)
+ return false;
+
+ ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[l->nameIndex]);
+ return o->put(name, value);
}
-void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Object *o = static_cast<Object *>(object.managed());
if (o && o->internalClass() == l->classList[0]) {
o->setProperty(engine, l->index, value);
- return;
+ return true;
}
- setterTwoClasses(l, engine, object, value);
+ return setterTwoClasses(l, engine, object, value);
}
-void Lookup::setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Object *o = static_cast<Object *>(object.managed());
if (o && o->internalClass() == l->classList[0]) {
o->d()->setInlineProperty(engine, l->index, value);
- return;
+ return true;
}
- setterTwoClasses(l, engine, object, value);
+ return setterTwoClasses(l, engine, object, value);
}
-void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Object *o = static_cast<Object *>(object.managed());
if (o && o->internalClass() == l->classList[0]) {
Q_ASSERT(!o->prototype());
o->setInternalClass(l->classList[3]);
o->setProperty(l->index, value);
- return;
+ return true;
}
l->setter = setterFallback;
- setterFallback(l, engine, object, value);
+ return setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Object *o = static_cast<Object *>(object.managed());
if (o && o->internalClass() == l->classList[0]) {
@@ -779,15 +780,15 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, co
Q_ASSERT(!p->prototype());
o->setInternalClass(l->classList[3]);
o->setProperty(l->index, value);
- return;
+ return true;
}
}
l->setter = setterFallback;
- setterFallback(l, engine, object, value);
+ return setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Object *o = static_cast<Object *>(object.managed());
if (o && o->internalClass() == l->classList[0]) {
@@ -800,32 +801,31 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, co
Q_ASSERT(!p->prototype());
o->setInternalClass(l->classList[3]);
o->setProperty(l->index, value);
- return;
+ return true;
}
}
}
l->setter = setterFallback;
- setterFallback(l, engine, object, value);
+ return setterFallback(l, engine, object, value);
}
-void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Object *o = static_cast<Object *>(object.managed());
if (o) {
if (o->internalClass() == l->classList[0]) {
o->setProperty(l->index, value);
- return;
+ return true;
}
if (o->internalClass() == l->classList[1]) {
o->setProperty(l->index2, value);
- return;
+ return true;
}
}
l->setter = setterFallback;
- setterFallback(l, engine, object, value);
-
+ return setterFallback(l, engine, object, value);
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index aa4cdd0d57..826760aa2d 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -69,7 +69,7 @@ struct Lookup {
union {
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
- void (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
+ bool (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
};
union {
InternalClass *classList[Size];
@@ -123,15 +123,15 @@ struct Lookup {
static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionEngine *engine);
static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionEngine *engine);
- static void setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static void setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static void setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static void setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static void setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static void setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static void setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static void setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
ReturnedValue lookup(const Value &thisObject, Object *obj, PropertyAttributes *attrs);
ReturnedValue lookup(const Object *obj, PropertyAttributes *attrs);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 659f02d264..718f6278d0 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -130,19 +130,14 @@ bool Object::putValue(uint memberIndex, const Value &value)
setter->call(callData);
return !ic->engine->hasException;
}
- goto reject;
+ return false;
}
if (!attrs.isWritable())
- goto reject;
+ return false;
setProperty(memberIndex, value);
return true;
-
- reject:
- if (engine()->current->strictMode)
- engine()->throwTypeError();
- return false;
}
void Object::defineDefaultProperty(const QString &name, const Value &value)
@@ -509,7 +504,7 @@ ReturnedValue Object::getLookup(const Managed *m, Lookup *l)
return Encode::undefined();
}
-void Object::setLookup(Managed *m, Lookup *l, const Value &value)
+bool Object::setLookup(Managed *m, Lookup *l, const Value &value)
{
Scope scope(static_cast<Object *>(m)->engine());
ScopedObject o(scope, static_cast<Object *>(m));
@@ -523,42 +518,44 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->index = idx;
l->setter = idx < o->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0;
o->setProperty(idx, value);
- return;
+ return true;
}
- if (idx != UINT_MAX) {
- o->putValue(idx, value);
- return;
- }
+ if (idx != UINT_MAX)
+ return o->putValue(idx, value);
}
- o->put(name, value);
+ if (!o->put(name, value)) {
+ l->setter = Lookup::setterFallback;
+ return false;
+ }
if (o->internalClass() == c)
- return;
+ return true;
idx = o->internalClass()->find(name);
- if (idx == UINT_MAX)
- return;
+ if (idx == UINT_MAX) // ### can this even happen?
+ return false;
l->classList[0] = c;
l->classList[3] = o->internalClass();
l->index = idx;
if (!o->prototype()) {
l->setter = Lookup::setterInsert0;
- return;
+ return true;
}
o = o->prototype();
l->classList[1] = o->internalClass();
if (!o->prototype()) {
l->setter = Lookup::setterInsert1;
- return;
+ return true;
}
o = o->prototype();
l->classList[2] = o->internalClass();
if (!o->prototype()) {
l->setter = Lookup::setterInsert2;
- return;
+ return true;
}
l->setter = Lookup::setterGeneric;
+ return true;
}
void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
@@ -722,9 +719,9 @@ bool Object::internalPut(String *name, const Value &value)
if (attrs.isAccessor()) {
if (memberIndex->as<FunctionObject>())
goto cont;
- goto reject;
+ return false;
} else if (!attrs.isWritable())
- goto reject;
+ return false;
else if (isArrayObject() && name->equals(engine->id_length())) {
bool ok;
uint l = value.asArrayLength(&ok);
@@ -734,14 +731,14 @@ bool Object::internalPut(String *name, const Value &value)
}
ok = setArrayLength(l);
if (!ok)
- goto reject;
+ return false;
} else {
memberIndex.set(engine, value);
}
return true;
} else if (!prototype()) {
if (!isExtensible())
- goto reject;
+ return false;
} else {
// clause 4
Scope scope(engine);
@@ -749,12 +746,12 @@ bool Object::internalPut(String *name, const Value &value)
if (!memberIndex.isNull()) {
if (attrs.isAccessor()) {
if (!memberIndex->as<FunctionObject>())
- goto reject;
+ return false;
} else if (!isExtensible() || !attrs.isWritable()) {
- goto reject;
+ return false;
}
} else if (!isExtensible()) {
- goto reject;
+ return false;
}
}
@@ -775,15 +772,6 @@ bool Object::internalPut(String *name, const Value &value)
insertMember(name, value);
return true;
-
- reject:
- // ### this should be removed once everything is ported to use Object::set()
- if (engine->current->strictMode) {
- QString message = QLatin1String("Cannot assign to read-only property \"") +
- name->toQString() + QLatin1Char('\"');
- engine->throwTypeError(message);
- }
- return false;
}
bool Object::internalPutIndexed(uint index, const Value &value)
@@ -799,7 +787,7 @@ bool Object::internalPutIndexed(uint index, const Value &value)
if (arrayIndex.isNull() && isStringObject()) {
if (index < static_cast<StringObject *>(this)->length())
// not writable
- goto reject;
+ return false;
}
// clause 1
@@ -807,15 +795,15 @@ bool Object::internalPutIndexed(uint index, const Value &value)
if (attrs.isAccessor()) {
if (arrayIndex->as<FunctionObject>())
goto cont;
- goto reject;
+ return false;
} else if (!attrs.isWritable())
- goto reject;
+ return false;
arrayIndex.set(engine, value);
return true;
} else if (!prototype()) {
if (!isExtensible())
- goto reject;
+ return false;
} else {
// clause 4
Scope scope(engine);
@@ -823,12 +811,12 @@ bool Object::internalPutIndexed(uint index, const Value &value)
if (!arrayIndex.isNull()) {
if (attrs.isAccessor()) {
if (!arrayIndex->as<FunctionObject>())
- goto reject;
+ return false;
} else if (!isExtensible() || !attrs.isWritable()) {
- goto reject;
+ return false;
}
} else if (!isExtensible()) {
- goto reject;
+ return false;
}
}
@@ -849,12 +837,6 @@ bool Object::internalPutIndexed(uint index, const Value &value)
arraySet(index, value);
return true;
-
- reject:
- // ### this should be removed once everything is ported to use Object::setIndexed()
- if (engine->current->strictMode)
- engine->throwTypeError();
- return false;
}
// Section 8.12.7
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index fc9a42921e..2bb230412d 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -186,7 +186,7 @@ struct ObjectVTable
bool (*deleteProperty)(Managed *m, String *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
ReturnedValue (*getLookup)(const Managed *m, Lookup *l);
- void (*setLookup)(Managed *m, Lookup *l, const Value &v);
+ bool (*setLookup)(Managed *m, Lookup *l, const Value &v);
uint (*getLength)(const Managed *m);
void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
ReturnedValue (*instanceOf)(const Object *typeObject, const Value &var);
@@ -409,19 +409,6 @@ public:
return ret;
}
- inline bool setIndexed(uint idx, const Value &v, ThrowOnFailure shouldThrow)
- {
- bool ret = vtable()->putIndexed(this, idx, v);
- if (!ret && shouldThrow == ThrowOnFailure::DoThrowOnRejection) {
- ExecutionEngine *e = engine();
- if (!e->hasException) { // allow a custom set impl to throw itself
- e->throwTypeError();
- }
- }
- return ret;
- }
-
-
PropertyAttributes query(String *name) const
{ return vtable()->query(this, name); }
PropertyAttributes queryIndexed(uint index) const
@@ -432,8 +419,8 @@ public:
{ return vtable()->deleteIndexedProperty(this, index); }
ReturnedValue getLookup(Lookup *l) const
{ return vtable()->getLookup(this, l); }
- void setLookup(Lookup *l, const Value &v)
- { vtable()->setLookup(this, l, v); }
+ bool setLookup(Lookup *l, const Value &v)
+ { return vtable()->setLookup(this, l, v); }
void advanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
uint getLength() const { return vtable()->getLength(this); }
@@ -456,7 +443,7 @@ protected:
static bool deleteProperty(Managed *m, String *name);
static bool deleteIndexedProperty(Managed *m, uint index);
static ReturnedValue getLookup(const Managed *m, Lookup *l);
- static void setLookup(Managed *m, Lookup *l, const Value &v);
+ static bool setLookup(Managed *m, Lookup *l, const Value &v);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 9292fa674b..cbcf585f94 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -589,14 +589,14 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu
return (mm->alloc<String>(sleft->d(), sright->d()))->asReturnedValue();
}
-void Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
+bool Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
{
Scope scope(engine);
ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject o(scope, object.toObject(engine));
if (!o)
- return;
- o->put(name, value);
+ return false;
+ return o->put(name, value);
}
static Q_NEVER_INLINE ReturnedValue getElementIntFallback(ExecutionEngine *engine, const Value &object, uint idx)
@@ -675,12 +675,12 @@ ReturnedValue Runtime::method_getElement(ExecutionEngine *engine, const Value &o
return getElementFallback(engine, object, index);
}
-static Q_NEVER_INLINE void setElementFallback(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
+static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
{
Scope scope(engine);
ScopedObject o(scope, object.toObject(engine));
if (engine->hasException)
- return;
+ return false;
uint idx;
if (index.asArrayIndex(idx)) {
@@ -688,18 +688,17 @@ static Q_NEVER_INLINE void setElementFallback(ExecutionEngine *engine, const Val
Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->values.size) {
s->setData(engine, idx, value);
- return;
+ return true;
}
}
- o->putIndexed(idx, value);
- return;
+ return o->putIndexed(idx, value);
}
ScopedString name(scope, index.toString(engine));
- o->put(name, value);
+ return o->put(name, value);
}
-void Runtime::method_setElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
+bool Runtime::method_setElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
{
uint idx;
if (index.asArrayIndex(idx)) {
@@ -710,7 +709,7 @@ void Runtime::method_setElement(ExecutionEngine *engine, const Value &object, co
Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->values.size) {
s->setData(engine, idx, value);
- return;
+ return true;
}
}
}
@@ -740,11 +739,11 @@ ReturnedValue Runtime::method_foreachNextPropertyName(const Value &foreach_itera
}
-void Runtime::method_setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value)
+bool Runtime::method_setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
ScopedString name(scope, engine->current->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- engine->currentContext->setProperty(name, value);
+ return engine->currentContext->setProperty(name, value);
}
ReturnedValue Runtime::method_getProperty(ExecutionEngine *engine, const Value &object, int nameIndex)
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index e0f7bd8706..ba4a55f864 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -108,9 +108,9 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(ReturnedValue, constructValue, (ExecutionEngine *engine, const Value &func, CallData *callData)) \
\
/* set & get */ \
- F(void, setActivationProperty, (ExecutionEngine *engine, int nameIndex, const Value &value)) \
- F(void, setProperty, (ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)) \
- F(void, setElement, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)) \
+ F(bool, setActivationProperty, (ExecutionEngine *engine, int nameIndex, const Value &value)) \
+ F(bool, setProperty, (ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)) \
+ F(bool, setElement, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)) \
F(ReturnedValue, getProperty, (ExecutionEngine *engine, const Value &object, int nameIndex)) \
F(ReturnedValue, getActivationProperty, (ExecutionEngine *engine, int nameIndex)) \
F(ReturnedValue, getElement, (ExecutionEngine *engine, const Value &object, const Value &index)) \
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 12b01bd578..6e237b2e23 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -384,15 +384,10 @@ bool TypedArray::putIndexed(Managed *m, uint index, const Value &value)
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
if (byteOffset + bytesPerElement > (uint)a->d()->buffer->byteLength())
- goto reject;
+ return false;
a->d()->type->write(scope.engine, a->d()->buffer->data->data(), byteOffset, value);
return true;
-
-reject:
- if (scope.engine->current->strictMode)
- scope.engine->throwTypeError();
- return false;
}
void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 48c52ab52c..17c2b07105 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -539,7 +539,11 @@ QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunctio
MOTH_END_INSTR(GetGlobalLookup)
MOTH_BEGIN_INSTR(StoreName)
- Runtime::method_setActivationProperty(engine, instr.name, accumulator);
+ if (!Runtime::method_setActivationProperty(engine, instr.name, accumulator) && function->isStrict()) {
+ Scope scope(engine);
+ ScopedString n(scope, function->compilationUnit->runtimeStrings[instr.name]);
+ engine->throwReferenceError(n);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreName)
@@ -552,7 +556,8 @@ QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunctio
MOTH_END_INSTR(LoadElementA)
MOTH_BEGIN_INSTR(StoreElement)
- Runtime::method_setElement(engine, STACK_VALUE(instr.base), STACK_VALUE(instr.index), accumulator);
+ if (!Runtime::method_setElement(engine, STACK_VALUE(instr.base), STACK_VALUE(instr.index), accumulator) && function->isStrict())
+ engine->throwTypeError();
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
@@ -575,13 +580,15 @@ QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunctio
MOTH_END_INSTR(GetLookupA)
MOTH_BEGIN_INSTR(StoreProperty)
- Runtime::method_setProperty(engine, STACK_VALUE(instr.base), instr.name, accumulator);
+ if (!Runtime::method_setProperty(engine, STACK_VALUE(instr.base), instr.name, accumulator) && function->isStrict())
+ engine->throwTypeError();
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreProperty)
MOTH_BEGIN_INSTR(SetLookup)
QV4::Lookup *l = function->compilationUnit->runtimeLookups + instr.index;
- l->setter(l, engine, STACK_VALUE(instr.base), accumulator);
+ if (!l->setter(l, engine, STACK_VALUE(instr.base), accumulator) && function->isStrict())
+ engine->throwTypeError();
CHECK_EXCEPTION;
MOTH_END_INSTR(SetLookup)