aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-08-07 13:27:38 +0200
committerLars Knoll <lars.knoll@qt.io>2017-08-10 08:18:41 +0000
commitfee680b24a41c177a23f82fc7334ab593931afea (patch)
tree23aa05e538b287ec25830bc3b000c9641cfd9699 /src/qml
parent2ad213cc02094e003802530757fa4010720a22e6 (diff)
Don't throw errors from the internal put methods anymore
Instead do it in the VME, where we can then easily separate into throwing and non throwing versions by bytecode. Change-Id: Ie63bd5b3610bb85f26fb8979179b2e239876cd97 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-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)