diff options
-rw-r--r-- | src/qml/jsapi/qjsengine.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 106 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 26 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup.cpp | 68 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup_p.h | 20 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 80 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 21 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 25 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtimeapi_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4typedarray.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 15 |
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) |