diff options
Diffstat (limited to 'src/qml/jsruntime')
47 files changed, 1331 insertions, 1200 deletions
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 05a7176061..3f0ff10e58 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -77,19 +77,16 @@ ReturnedValue ArrayBufferCtor::call(const Managed *that, CallData *callData) return construct(that, callData); } -void ArrayBufferCtor::method_isView(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayBufferCtor::method_isView(const BuiltinFunction *, CallData *callData) { - QV4::Scoped<TypedArray> a(scope, callData->argument(0)); - if (!!a) { - scope.result = Encode(true); - return; - } - QV4::Scoped<DataView> v(scope, callData->argument(0)); - if (!!v) { - scope.result = Encode(true); - return; - } - scope.result = Encode(false); + if (callData->argc < 1) + return Encode(false); + + if (callData->args[0].as<TypedArray>() || + callData->args[0].as<DataView>()) + return Encode(true); + + return Encode(false); } @@ -159,47 +156,52 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("toString"), method_toString, 0); } -void ArrayBufferPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayBufferPrototype::method_get_byteLength(const BuiltinFunction *b, CallData *callData) { - Scoped<ArrayBuffer> v(scope, callData->thisObject); - if (!v) - THROW_TYPE_ERROR(); + ArrayBuffer *a = callData->thisObject.as<ArrayBuffer>(); + if (!a) + return b->engine()->throwTypeError(); - scope.result = Encode(v->d()->data->size); + return Encode(a->d()->data->size); } -void ArrayBufferPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayBufferPrototype::method_slice(const BuiltinFunction *b, CallData *callData) { - Scoped<ArrayBuffer> a(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + ArrayBuffer *a = callData->thisObject.as<ArrayBuffer>(); if (!a) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double start = callData->argc > 0 ? callData->args[0].toInteger() : 0; double end = (callData->argc < 2 || callData->args[1].isUndefined()) ? a->d()->data->size : callData->args[1].toInteger(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size); double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size); + Scope scope(v4); ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor())); if (!constructor) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); ScopedCallData cData(scope, 1); double newLen = qMax(final - first, 0.); cData->args[0] = QV4::Encode(newLen); QV4::Scoped<ArrayBuffer> newBuffer(scope, constructor->construct(cData)); if (!newBuffer || newBuffer->d()->data->size < (int)newLen) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); memcpy(newBuffer->d()->data->data(), a->d()->data->data() + (uint)first, newLen); + return Encode::undefined(); } -void ArrayBufferPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayBufferPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { - Scoped<ArrayBuffer> a(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + ArrayBuffer *a = callData->thisObject.as<ArrayBuffer>(); if (!a) RETURN_UNDEFINED(); - scope.result = scope.engine->newString(QString::fromUtf8(a->asByteArray())); + return Encode(v4->newString(QString::fromUtf8(a->asByteArray()))); } diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index 1b3f09dea8..b35324c472 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -81,7 +81,7 @@ struct ArrayBufferCtor: FunctionObject static ReturnedValue construct(const Managed *m, CallData *callData); static ReturnedValue call(const Managed *that, CallData *callData); - static void method_isView(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_isView(const BuiltinFunction *, CallData *callData); }; @@ -104,9 +104,9 @@ struct ArrayBufferPrototype: Object { void init(ExecutionEngine *engine, Object *ctor); - static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_slice(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_get_byteLength(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_slice(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 4663faa640..7e32c948ac 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -118,14 +118,15 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("reduceRight"), method_reduceRight, 1); } -void ArrayPrototype::method_isArray(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_isArray(const BuiltinFunction *, CallData *callData) { bool isArray = callData->argc && callData->args[0].as<ArrayObject>(); - scope.result = Encode(isArray); + return Encode(isArray); } -void ArrayPrototype::method_toString(const BuiltinFunction *builtin, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_toString(const BuiltinFunction *builtin, CallData *callData) { + Scope scope(builtin); ScopedObject o(scope, callData->thisObject, ScopedObject::Convert); CHECK_EXCEPTION(); ScopedString s(scope, scope.engine->newString(QStringLiteral("join"))); @@ -133,19 +134,19 @@ void ArrayPrototype::method_toString(const BuiltinFunction *builtin, Scope &scop if (!!f) { ScopedCallData d(scope, 0); d->thisObject = callData->thisObject; - scope.result = f->call(d); - return; + return f->call(d); } - ObjectPrototype::method_toString(builtin, scope, callData); + return ObjectPrototype::method_toString(builtin, callData); } -void ArrayPrototype::method_toLocaleString(const BuiltinFunction *builtin, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_toLocaleString(const BuiltinFunction *builtin, CallData *callData) { - return method_toString(builtin, scope, callData); + return method_toString(builtin, callData); } -void ArrayPrototype::method_concat(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_concat(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject thisObject(scope, callData->thisObject.toObject(scope.engine)); if (!thisObject) RETURN_UNDEFINED(); @@ -179,11 +180,12 @@ void ArrayPrototype::method_concat(const BuiltinFunction *, Scope &scope, CallDa } } - scope.result = result; + return result.asReturnedValue(); } -void ArrayPrototype::method_find(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_find(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -199,6 +201,7 @@ void ArrayPrototype::method_find(const BuiltinFunction *, Scope &scope, CallData cData->args[2] = instance; ScopedValue v(scope); + ScopedValue result(scope); for (uint k = 0; k < len; ++k) { v = instance->getIndexed(k); @@ -206,18 +209,19 @@ void ArrayPrototype::method_find(const BuiltinFunction *, Scope &scope, CallData cData->args[0] = v; cData->args[1] = Primitive::fromDouble(k); - scope.result = callback->call(cData); + result = callback->call(cData); CHECK_EXCEPTION(); - if (scope.result.toBoolean()) - RETURN_RESULT(v); + if (result->toBoolean()) + return v->asReturnedValue(); } RETURN_UNDEFINED(); } -void ArrayPrototype::method_findIndex(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_findIndex(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -233,6 +237,7 @@ void ArrayPrototype::method_findIndex(const BuiltinFunction *, Scope &scope, Cal cData->args[2] = instance; ScopedValue v(scope); + ScopedValue result(scope); for (uint k = 0; k < len; ++k) { v = instance->getIndexed(k); @@ -240,25 +245,24 @@ void ArrayPrototype::method_findIndex(const BuiltinFunction *, Scope &scope, Cal cData->args[0] = v; cData->args[1] = Primitive::fromDouble(k); - scope.result = callback->call(cData); + result = callback->call(cData); CHECK_EXCEPTION(); - if (scope.result.toBoolean()) - RETURN_RESULT(Encode(k)); + if (result->toBoolean()) + return Encode(k); } - RETURN_RESULT(Encode(-1)); + return Encode(-1); } -void ArrayPrototype::method_join(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_join(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedValue arg(scope, callData->argument(0)); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); - if (!instance) { - scope.result = scope.engine->newString(); - return; - } + if (!instance) + return Encode(scope.engine->newString()); QString r4; if (arg->isUndefined()) @@ -269,10 +273,8 @@ void ArrayPrototype::method_join(const BuiltinFunction *, Scope &scope, CallData ScopedValue length(scope, instance->get(scope.engine->id_length())); const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32(); - if (!r2) { - scope.result = scope.engine->newString(); - return; - } + if (!r2) + return Encode(scope.engine->newString()); QString R; @@ -310,11 +312,12 @@ void ArrayPrototype::method_join(const BuiltinFunction *, Scope &scope, CallData } } - scope.result = scope.engine->newString(R); + return Encode(scope.engine->newString(R)); } -void ArrayPrototype::method_pop(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_pop(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -337,11 +340,12 @@ void ArrayPrototype::method_pop(const BuiltinFunction *, Scope &scope, CallData instance->setArrayLength(len - 1); else instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1))); - scope.result = result; + return result->asReturnedValue(); } -void ArrayPrototype::method_push(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_push(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -364,11 +368,9 @@ void ArrayPrototype::method_push(const BuiltinFunction *, Scope &scope, CallData instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen))); else { ScopedString str(scope, scope.engine->newString(QStringLiteral("Array.prototype.push: Overflow"))); - scope.result = scope.engine->throwRangeError(str); - return; + return scope.engine->throwRangeError(str); } - scope.result = Encode(newLen); - return; + return Encode(newLen); } if (!callData->argc) @@ -386,11 +388,12 @@ void ArrayPrototype::method_push(const BuiltinFunction *, Scope &scope, CallData else instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len))); - scope.result = Encode(len); + return Encode(len); } -void ArrayPrototype::method_reverse(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_reverse(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -416,11 +419,12 @@ void ArrayPrototype::method_reverse(const BuiltinFunction *, Scope &scope, CallD else instance->deleteIndexedProperty(hi); } - scope.result = instance; + return instance->asReturnedValue(); } -void ArrayPrototype::method_shift(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_shift(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -436,10 +440,11 @@ void ArrayPrototype::method_shift(const BuiltinFunction *, Scope &scope, CallDat RETURN_UNDEFINED(); } + ScopedValue result(scope); if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len && instance->arrayData()->type != Heap::ArrayData::Custom) { - scope.result = instance->arrayData()->vtable()->pop_front(instance); + result = instance->arrayData()->vtable()->pop_front(instance); } else { - scope.result = instance->getIndexed(0); + result = instance->getIndexed(0); CHECK_EXCEPTION(); ScopedValue v(scope); // do it the slow way @@ -461,10 +466,13 @@ void ArrayPrototype::method_shift(const BuiltinFunction *, Scope &scope, CallDat instance->setArrayLengthUnchecked(len - 1); else instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1))); + + return result->asReturnedValue(); } -void ArrayPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_slice(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->thisObject.toObject(scope.engine)); if (!o) RETURN_UNDEFINED(); @@ -500,11 +508,12 @@ void ArrayPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallDat result->arraySet(n, v); ++n; } - scope.result = result; + return result->asReturnedValue(); } -void ArrayPrototype::method_sort(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_sort(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -513,11 +522,12 @@ void ArrayPrototype::method_sort(const BuiltinFunction *, Scope &scope, CallData ScopedValue comparefn(scope, callData->argument(0)); ArrayData::sort(scope.engine, instance, comparefn, len); - scope.result = callData->thisObject; + return callData->thisObject.asReturnedValue(); } -void ArrayPrototype::method_splice(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_splice(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -587,12 +597,13 @@ void ArrayPrototype::method_splice(const BuiltinFunction *, Scope &scope, CallDa scope.engine->current->strictMode = true; instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount))); - scope.result = newArray; scope.engine->current->strictMode = wasStrict; + return newArray->asReturnedValue(); } -void ArrayPrototype::method_unshift(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_unshift(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -625,20 +636,19 @@ void ArrayPrototype::method_unshift(const BuiltinFunction *, Scope &scope, CallD else instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen))); - scope.result = Encode(newLen); + return Encode(newLen); } -void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_indexOf(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); uint len = instance->getLength(); - if (!len) { - scope.result = Encode(-1); - return; - } + if (!len) + return Encode(-1); ScopedValue searchValue(scope, callData->argument(0)); uint fromIndex = 0; @@ -646,10 +656,8 @@ void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallD if (callData->argc >= 2) { double f = callData->args[1].toInteger(); CHECK_EXCEPTION(); - if (f >= len) { - scope.result = Encode(-1); - return; - } + if (f >= len) + return Encode(-1); if (f < 0) f = qMax(len + f, 0.); fromIndex = (uint) f; @@ -660,13 +668,10 @@ void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallD for (uint k = fromIndex; k < len; ++k) { bool exists; v = instance->getIndexed(k, &exists); - if (exists && RuntimeHelpers::strictEqual(v, searchValue)) { - scope.result = Encode(k); - return; - } + if (exists && RuntimeHelpers::strictEqual(v, searchValue)) + return Encode(k); } - scope.result = Encode(-1); - return; + return Encode(-1); } ScopedValue value(scope); @@ -678,14 +683,11 @@ void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallD bool exists; value = instance->getIndexed(i, &exists); CHECK_EXCEPTION(); - if (exists && RuntimeHelpers::strictEqual(value, searchValue)) { - scope.result = Encode(i); - return; - } + if (exists && RuntimeHelpers::strictEqual(value, searchValue)) + return Encode(i); } } else if (!instance->arrayData()) { - scope.result = Encode(-1); - return; + return Encode(-1); } else { Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex); Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>(); @@ -695,27 +697,24 @@ void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallD while (idx < len) { value = sa->data(idx); CHECK_EXCEPTION(); - if (RuntimeHelpers::strictEqual(value, searchValue)) { - scope.result = Encode(idx); - return; - } + if (RuntimeHelpers::strictEqual(value, searchValue)) + return Encode(idx); ++idx; } } - scope.result = Encode(-1); + return Encode(-1); } -void ArrayPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_lastIndexOf(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); uint len = instance->getLength(); - if (!len) { - scope.result = Encode(-1); - return; - } + if (!len) + return Encode(-1); ScopedValue searchValue(scope); uint fromIndex = len; @@ -732,10 +731,8 @@ void ArrayPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, C f = qMin(f, (double)(len - 1)); else if (f < 0) { f = len + f; - if (f < 0) { - scope.result = Encode(-1); - return; - } + if (f < 0) + return Encode(-1); } fromIndex = (uint) f + 1; } @@ -746,16 +743,15 @@ void ArrayPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, C bool exists; v = instance->getIndexed(k, &exists); CHECK_EXCEPTION(); - if (exists && RuntimeHelpers::strictEqual(v, searchValue)) { - scope.result = Encode(k); - return; - } + if (exists && RuntimeHelpers::strictEqual(v, searchValue)) + return Encode(k); } - scope.result = Encode(-1); + return Encode(-1); } -void ArrayPrototype::method_every(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_every(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -784,11 +780,12 @@ void ArrayPrototype::method_every(const BuiltinFunction *, Scope &scope, CallDat r = callback->call(cData); ok = r->toBoolean(); } - scope.result = Encode(ok); + return Encode(ok); } -void ArrayPrototype::method_some(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_some(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -803,6 +800,7 @@ void ArrayPrototype::method_some(const BuiltinFunction *, Scope &scope, CallData cData->thisObject = callData->argument(1); cData->args[2] = instance; ScopedValue v(scope); + ScopedValue result(scope); for (uint k = 0; k < len; ++k) { bool exists; @@ -812,17 +810,16 @@ void ArrayPrototype::method_some(const BuiltinFunction *, Scope &scope, CallData cData->args[0] = v; cData->args[1] = Primitive::fromDouble(k); - scope.result = callback->call(cData); - if (scope.result.toBoolean()) { - scope.result = Encode(true); - return; - } + result = callback->call(cData); + if (result->toBoolean()) + return Encode(true); } - scope.result = Encode(false); + return Encode(false); } -void ArrayPrototype::method_forEach(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_forEach(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -846,13 +843,14 @@ void ArrayPrototype::method_forEach(const BuiltinFunction *, Scope &scope, CallD cData->args[0] = v; cData->args[1] = Primitive::fromDouble(k); - scope.result = callback->call(cData); + callback->call(cData); } RETURN_UNDEFINED(); } -void ArrayPrototype::method_map(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_map(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -884,11 +882,12 @@ void ArrayPrototype::method_map(const BuiltinFunction *, Scope &scope, CallData mapped = callback->call(cData); a->arraySet(k, mapped); } - scope.result = a.asReturnedValue(); + return a.asReturnedValue(); } -void ArrayPrototype::method_filter(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_filter(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -924,11 +923,12 @@ void ArrayPrototype::method_filter(const BuiltinFunction *, Scope &scope, CallDa ++to; } } - scope.result = a.asReturnedValue(); + return a.asReturnedValue(); } -void ArrayPrototype::method_reduce(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_reduce(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -973,11 +973,12 @@ void ArrayPrototype::method_reduce(const BuiltinFunction *, Scope &scope, CallDa } ++k; } - scope.result = acc->asReturnedValue(); + return acc->asReturnedValue(); } -void ArrayPrototype::method_reduceRight(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ArrayPrototype::method_reduceRight(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) RETURN_UNDEFINED(); @@ -991,8 +992,7 @@ void ArrayPrototype::method_reduceRight(const BuiltinFunction *, Scope &scope, C if (len == 0) { if (callData->argc == 1) THROW_TYPE_ERROR(); - scope.result = callData->argument(1); - return; + return callData->argument(1); } uint k = len; @@ -1027,6 +1027,6 @@ void ArrayPrototype::method_reduceRight(const BuiltinFunction *, Scope &scope, C } --k; } - scope.result = acc->asReturnedValue(); + return acc->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index b6ee5c5dac..7c4b86dac5 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -78,30 +78,30 @@ struct ArrayPrototype: ArrayObject { void init(ExecutionEngine *engine, Object *ctor); - static void method_isArray(const BuiltinFunction *, Scope &, CallData *callData); - static void method_toString(const BuiltinFunction *, Scope &, CallData *callData); - static void method_toLocaleString(const BuiltinFunction *builtin, Scope &, CallData *callData); - static void method_concat(const BuiltinFunction *, Scope &, CallData *callData); - static void method_find(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_findIndex(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_join(const BuiltinFunction *, Scope &, CallData *callData); - static void method_pop(const BuiltinFunction *, Scope &, CallData *callData); - static void method_push(const BuiltinFunction *, Scope &, CallData *callData); - static void method_reverse(const BuiltinFunction *, Scope &, CallData *callData); - static void method_shift(const BuiltinFunction *, Scope &, CallData *callData); - static void method_slice(const BuiltinFunction *, Scope &, CallData *callData); - static void method_sort(const BuiltinFunction *, Scope &, CallData *callData); - static void method_splice(const BuiltinFunction *, Scope &, CallData *callData); - static void method_unshift(const BuiltinFunction *, Scope &, CallData *callData); - static void method_indexOf(const BuiltinFunction *, Scope &, CallData *callData); - static void method_lastIndexOf(const BuiltinFunction *, Scope &, CallData *callData); - static void method_every(const BuiltinFunction *, Scope &, CallData *callData); - static void method_some(const BuiltinFunction *, Scope &, CallData *callData); - static void method_forEach(const BuiltinFunction *, Scope &, CallData *callData); - static void method_map(const BuiltinFunction *, Scope &, CallData *callData); - static void method_filter(const BuiltinFunction *, Scope &, CallData *callData); - static void method_reduce(const BuiltinFunction *, Scope &, CallData *callData); - static void method_reduceRight(const BuiltinFunction *, Scope &, CallData *callData); + static ReturnedValue method_isArray(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLocaleString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_concat(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_find(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_findIndex(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_join(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_pop(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_push(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_reverse(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_shift(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_slice(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_sort(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_splice(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_unshift(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_indexOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_lastIndexOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_every(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_some(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_forEach(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_map(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_filter(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_reduce(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_reduceRight(const BuiltinFunction *, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 0ed8471753..d74750fa8c 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -73,31 +73,30 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(engine->id_valueOf(), method_valueOf); } -void BooleanPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue BooleanPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); bool result; if (callData->thisObject.isBoolean()) { result = callData->thisObject.booleanValue(); } else { const BooleanObject *thisObject = callData->thisObject.as<BooleanObject>(); if (!thisObject) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); result = thisObject->value(); } - scope.result = result ? scope.engine->id_true() : scope.engine->id_false(); + return Encode(result ? v4->id_true() : v4->id_false()); } -void BooleanPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue BooleanPrototype::method_valueOf(const BuiltinFunction *b, CallData *callData) { - if (callData->thisObject.isBoolean()) { - scope.result = callData->thisObject.asReturnedValue(); - return; - } + if (callData->thisObject.isBoolean()) + return callData->thisObject.asReturnedValue(); const BooleanObject *thisObject = callData->thisObject.as<BooleanObject>(); if (!thisObject) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); - scope.result = Encode(thisObject->value()); + return Encode(thisObject->value()); } diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h index 9a004c7749..78fe59cc7e 100644 --- a/src/qml/jsruntime/qv4booleanobject_p.h +++ b/src/qml/jsruntime/qv4booleanobject_p.h @@ -79,8 +79,8 @@ struct BooleanPrototype: BooleanObject V4_PROTOTYPE(objectPrototype) void init(ExecutionEngine *engine, Object *ctor); - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_valueOf(const BuiltinFunction *, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index b1fb017f99..db85bc6cef 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -232,7 +232,7 @@ bool ExecutionContext::deleteProperty(String *name) } // Do a standard call with this execution context as the outer scope -void ExecutionContext::call(Scope &scope, CallData *callData, Function *function, const FunctionObject *f) +ReturnedValue ExecutionContext::call(Scope &scope, CallData *callData, Function *function, const FunctionObject *f) { ExecutionContextSaver ctxSaver(scope); @@ -241,14 +241,16 @@ void ExecutionContext::call(Scope &scope, CallData *callData, Function *function ctx->d()->function.set(scope.engine, f->d()); scope.engine->pushContext(ctx); - scope.result = Q_V4_PROFILE(scope.engine, function); + ReturnedValue res = Q_V4_PROFILE(scope.engine, function); if (function->hasQmlDependencies) QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope); + + return res; } // Do a simple, fast call with this execution context as the outer scope -void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Function *function) +ReturnedValue QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Function *function) { Q_ASSERT(function->canUseSimpleFunction()); @@ -266,11 +268,13 @@ void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Functio scope.engine->pushContext(ctx); Q_ASSERT(scope.engine->current == ctx); - scope.result = Q_V4_PROFILE(scope.engine, function); + ReturnedValue res = Q_V4_PROFILE(scope.engine, function); if (function->hasQmlDependencies) QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope); scope.engine->memoryManager->freeSimpleCallContext(); + + return res; } void ExecutionContext::setProperty(String *name, const Value &value) diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 9408f85d66..bb8f9b13fa 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -223,8 +223,8 @@ struct Q_QML_EXPORT ExecutionContext : public Managed return d()->callData->argument(i); } - void call(Scope &scope, CallData *callData, QV4::Function *function, const QV4::FunctionObject *f = 0); - void simpleCall(Scope &scope, CallData *callData, QV4::Function *function); + ReturnedValue call(Scope &scope, CallData *callData, QV4::Function *function, const QV4::FunctionObject *f = 0); + ReturnedValue simpleCall(Scope &scope, CallData *callData, QV4::Function *function); }; struct Q_QML_EXPORT CallContext : public ExecutionContext diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index b4e21b7ce5..57b5045f57 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -119,60 +119,60 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0); } -void DataViewPrototype::method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_get_buffer(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); - scope.result = v->d()->buffer; + return v->d()->buffer->asReturnedValue(); } -void DataViewPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_get_byteLength(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); - scope.result = Encode(v->d()->byteLength); + return Encode(v->d()->byteLength); } -void DataViewPrototype::method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_get_byteOffset(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); - scope.result = Encode(v->d()->byteOffset); + return Encode(v->d()->byteOffset); } template <typename T> -void DataViewPrototype::method_getChar(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_getChar(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v || callData->argc < 1) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); idx += v->d()->byteOffset; T t = T(v->d()->buffer->data->data()[idx]); - scope.result = Encode((int)t); + return Encode((int)t); } template <typename T> -void DataViewPrototype::method_get(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_get(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v || callData->argc < 1) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); idx += v->d()->byteOffset; bool littleEndian = callData->argc < 2 ? false : callData->args[1].toBoolean(); @@ -181,19 +181,19 @@ void DataViewPrototype::method_get(const BuiltinFunction *, Scope &scope, CallDa ? qFromLittleEndian<T>((uchar *)v->d()->buffer->data->data() + idx) : qFromBigEndian<T>((uchar *)v->d()->buffer->data->data() + idx); - scope.result = Encode(t); + return Encode(t); } template <typename T> -void DataViewPrototype::method_getFloat(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_getFloat(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v || callData->argc < 1) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); idx += v->d()->byteOffset; bool littleEndian = callData->argc < 2 ? false : callData->args[1].toBoolean(); @@ -207,7 +207,7 @@ void DataViewPrototype::method_getFloat(const BuiltinFunction *, Scope &scope, C u.i = littleEndian ? qFromLittleEndian<uint>((uchar *)v->d()->buffer->data->data() + idx) : qFromBigEndian<uint>((uchar *)v->d()->buffer->data->data() + idx); - scope.result = Encode(u.f); + return Encode(u.f); } else { Q_ASSERT(sizeof(T) == 8); union { @@ -217,20 +217,20 @@ void DataViewPrototype::method_getFloat(const BuiltinFunction *, Scope &scope, C u.i = littleEndian ? qFromLittleEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx) : qFromBigEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx); - scope.result = Encode(u.d); + return Encode(u.d); } } template <typename T> -void DataViewPrototype::method_setChar(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_setChar(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v || callData->argc < 1) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); idx += v->d()->byteOffset; int val = callData->argc >= 2 ? callData->args[1].toInt32() : 0; @@ -240,15 +240,15 @@ void DataViewPrototype::method_setChar(const BuiltinFunction *, Scope &scope, Ca } template <typename T> -void DataViewPrototype::method_set(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_set(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v || callData->argc < 1) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); idx += v->d()->byteOffset; int val = callData->argc >= 2 ? callData->args[1].toInt32() : 0; @@ -264,15 +264,15 @@ void DataViewPrototype::method_set(const BuiltinFunction *, Scope &scope, CallDa } template <typename T> -void DataViewPrototype::method_setFloat(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DataViewPrototype::method_setFloat(const BuiltinFunction *b, CallData *callData) { - Scoped<DataView> v(scope, callData->thisObject); + DataView *v = callData->thisObject.as<DataView>(); if (!v || callData->argc < 1) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - THROW_TYPE_ERROR(); + return b->engine()->throwTypeError(); idx += v->d()->byteOffset; double val = callData->argc >= 2 ? callData->args[1].toNumber() : qt_qnan(); diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h index 123a290e28..2d1a5d8be9 100644 --- a/src/qml/jsruntime/qv4dataview_p.h +++ b/src/qml/jsruntime/qv4dataview_p.h @@ -93,21 +93,21 @@ struct DataViewPrototype: Object { void init(ExecutionEngine *engine, Object *ctor); - static void method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_get_buffer(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_byteLength(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_byteOffset(const BuiltinFunction *, CallData *callData); template <typename T> - static void method_getChar(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_getChar(const BuiltinFunction *, CallData *callData); template <typename T> - static void method_get(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_get(const BuiltinFunction *, CallData *callData); template <typename T> - static void method_getFloat(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_getFloat(const BuiltinFunction *, CallData *callData); template <typename T> - static void method_setChar(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_setChar(const BuiltinFunction *, CallData *callData); template <typename T> - static void method_set(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_set(const BuiltinFunction *, CallData *callData); template <typename T> - static void method_setFloat(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_setFloat(const BuiltinFunction *, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 0e681f9946..2802483ff9 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -796,25 +796,25 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("toJSON"), method_toJSON, 1); } -double DatePrototype::getThisDate(Scope &scope, CallData *callData) +double DatePrototype::getThisDate(ExecutionEngine *v4, CallData *callData) { if (DateObject *thisObject = callData->thisObject.as<DateObject>()) return thisObject->date(); else { - scope.engine->throwTypeError(); + v4->throwTypeError(); return 0; } } -void DatePrototype::method_parse(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_parse(const BuiltinFunction *, CallData *callData) { if (!callData->argc) - scope.result = Encode(qt_qnan()); + return Encode(qt_qnan()); else - scope.result = Encode(ParseString(callData->args[0].toQString())); + return Encode(ParseString(callData->args[0].toQString())); } -void DatePrototype::method_UTC(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_UTC(const BuiltinFunction *, CallData *callData) { const int numArgs = callData->argc; if (numArgs >= 2) { @@ -829,306 +829,349 @@ void DatePrototype::method_UTC(const BuiltinFunction *, Scope &scope, CallData * year += 1900; double t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms)); - scope.result = Encode(TimeClip(t)); - return; + return Encode(TimeClip(t)); } RETURN_UNDEFINED(); } -void DatePrototype::method_now(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_now(const BuiltinFunction *, CallData *callData) { Q_UNUSED(callData); - double t = currentTime(); - scope.result = Encode(t); + return Encode(currentTime()); } -void DatePrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toString(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); - scope.result = scope.engine->newString(ToString(t)); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); + return Encode(v4->newString(ToString(t))); } -void DatePrototype::method_toDateString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toDateString(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); - scope.result = scope.engine->newString(ToDateString(t)); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); + return Encode(v4->newString(ToDateString(t))); } -void DatePrototype::method_toTimeString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toTimeString(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); - scope.result = scope.engine->newString(ToTimeString(t)); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); + return Encode(v4->newString(ToTimeString(t))); } -void DatePrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toLocaleString(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); - scope.result = scope.engine->newString(ToLocaleString(t)); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); + return Encode(v4->newString(ToLocaleString(t))); } -void DatePrototype::method_toLocaleDateString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toLocaleDateString(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); - scope.result = scope.engine->newString(ToLocaleDateString(t)); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); + return Encode(v4->newString(ToLocaleDateString(t))); } -void DatePrototype::method_toLocaleTimeString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toLocaleTimeString(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); - scope.result = scope.engine->newString(ToLocaleTimeString(t)); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); + return Encode(v4->newString(ToLocaleTimeString(t))); } -void DatePrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_valueOf(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); - scope.result = Encode(t); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); + return Encode(t); } -void DatePrototype::method_getTime(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getTime(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); - scope.result = Encode(t); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); + return Encode(t); } -void DatePrototype::method_getYear(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getYear(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = YearFromTime(LocalTime(t)) - 1900; - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getFullYear(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getFullYear(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = YearFromTime(LocalTime(t)); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getUTCFullYear(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = YearFromTime(t); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getMonth(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getMonth(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = MonthFromTime(LocalTime(t)); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getUTCMonth(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = MonthFromTime(t); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getDate(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getDate(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = DateFromTime(LocalTime(t)); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getUTCDate(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = DateFromTime(t); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getDay(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getDay(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = WeekDay(LocalTime(t)); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getUTCDay(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getUTCDay(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = WeekDay(t); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getHours(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getHours(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = HourFromTime(LocalTime(t)); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getUTCHours(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = HourFromTime(t); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getMinutes(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getMinutes(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = MinFromTime(LocalTime(t)); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getUTCMinutes(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = MinFromTime(t); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getSeconds(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getSeconds(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = SecFromTime(LocalTime(t)); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getUTCSeconds(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = SecFromTime(t); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getMilliseconds(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = msFromTime(LocalTime(t)); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getUTCMilliseconds(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = msFromTime(t); - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_getTimezoneOffset(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_getTimezoneOffset(const BuiltinFunction *b, CallData *callData) { - double t = getThisDate(scope, callData); + ExecutionEngine *v4 = b->engine(); + double t = getThisDate(v4, callData); if (!std::isnan(t)) t = (t - LocalTime(t)) / msPerMinute; - scope.result = Encode(t); + return Encode(t); } -void DatePrototype::method_setTime(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setTime(const BuiltinFunction *b, CallData *callData) { - Scoped<DateObject> self(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); self->setDate(TimeClip(t)); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setMilliseconds(const BuiltinFunction *b, CallData *callData) { - Scoped<DateObject> self(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = LocalTime(self->date()); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double ms = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setUTCMilliseconds(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double ms = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setSeconds(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setSeconds(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = LocalTime(self->date()); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double sec = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double ms = (callData->argc < 2) ? msFromTime(t) : callData->args[1].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setUTCSeconds(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); double sec = callData->argc ? callData->args[0].toNumber() : qt_qnan(); double ms = (callData->argc < 2) ? msFromTime(t) : callData->args[1].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setMinutes(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setMinutes(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = LocalTime(self->date()); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double min = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double sec = (callData->argc < 2) ? SecFromTime(t) : callData->args[1].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double ms = (callData->argc < 3) ? msFromTime(t) : callData->args[2].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setUTCMinutes(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); double min = callData->argc ? callData->args[0].toNumber() : qt_qnan(); @@ -1136,35 +1179,42 @@ void DatePrototype::method_setUTCMinutes(const BuiltinFunction *, Scope &scope, double ms = (callData->argc < 3) ? msFromTime(t) : callData->args[2].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setHours(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setHours(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = LocalTime(self->date()); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double hour = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double min = (callData->argc < 2) ? MinFromTime(t) : callData->args[1].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double sec = (callData->argc < 3) ? SecFromTime(t) : callData->args[2].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double ms = (callData->argc < 4) ? msFromTime(t) : callData->args[3].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setUTCHours(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); double hour = callData->argc ? callData->args[0].toNumber() : qt_qnan(); @@ -1173,75 +1223,87 @@ void DatePrototype::method_setUTCHours(const BuiltinFunction *, Scope &scope, Ca double ms = (callData->argc < 4) ? msFromTime(t) : callData->args[3].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setDate(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setDate(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = LocalTime(self->date()); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double date = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setUTCDate(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double date = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setMonth(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setMonth(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = LocalTime(self->date()); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double month = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double date = (callData->argc < 2) ? DateFromTime(t) : callData->args[1].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setUTCMonth(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); double month = callData->argc ? callData->args[0].toNumber() : qt_qnan(); double date = (callData->argc < 2) ? DateFromTime(t) : callData->args[1].toNumber(); t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setYear(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setYear(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); if (std::isnan(t)) @@ -1260,14 +1322,15 @@ void DatePrototype::method_setYear(const BuiltinFunction *, Scope &scope, CallDa r = TimeClip(r); } self->setDate(r); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setUTCFullYear(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); double year = callData->argc ? callData->args[0].toNumber() : qt_qnan(); @@ -1275,38 +1338,44 @@ void DatePrototype::method_setUTCFullYear(const BuiltinFunction *, Scope &scope, double date = (callData->argc < 3) ? DateFromTime(t) : callData->args[2].toNumber(); t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_setFullYear(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_setFullYear(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = LocalTime(self->date()); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); if (std::isnan(t)) t = 0; double year = callData->argc ? callData->args[0].toNumber() : qt_qnan(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double month = (callData->argc < 2) ? MonthFromTime(t) : callData->args[1].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); double date = (callData->argc < 3) ? DateFromTime(t) : callData->args[2].toNumber(); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); self->setDate(t); - scope.result = Encode(self->date()); + return Encode(self->date()); } -void DatePrototype::method_toUTCString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toUTCString(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); - scope.result = scope.engine->newString(ToUTCString(t)); + return Encode(v4->newString(ToUTCString(t))); } static void addZeroPrefixedInt(QString &str, int num, int nDigits) @@ -1322,21 +1391,22 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits) } } -void DatePrototype::method_toISOString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toISOString(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); DateObject *self = callData->thisObject.as<DateObject>(); if (!self) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); double t = self->date(); if (!std::isfinite(t)) - RETURN_RESULT(scope.engine->throwRangeError(callData->thisObject)); + RETURN_RESULT(v4->throwRangeError(callData->thisObject)); QString result; int year = (int)YearFromTime(t); if (year < 0 || year > 9999) { if (qAbs(year) >= 1000000) - RETURN_RESULT(scope.engine->newString(QStringLiteral("Invalid Date"))); + RETURN_RESULT(v4->newString(QStringLiteral("Invalid Date"))); result += year < 0 ? QLatin1Char('-') : QLatin1Char('+'); year = qAbs(year); addZeroPrefixedInt(result, year, 6); @@ -1357,29 +1427,32 @@ void DatePrototype::method_toISOString(const BuiltinFunction *, Scope &scope, Ca addZeroPrefixedInt(result, msFromTime(t), 3); result += QLatin1Char('Z'); - scope.result = scope.engine->newString(result); + return Encode(v4->newString(result)); } -void DatePrototype::method_toJSON(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue DatePrototype::method_toJSON(const BuiltinFunction *b, CallData *callData) { - ScopedObject O(scope, callData->thisObject.toObject(scope.engine)); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + Scope scope(v4); + ScopedObject O(scope, callData->thisObject.toObject(v4)); + if (v4->hasException) + return QV4::Encode::undefined(); ScopedValue tv(scope, RuntimeHelpers::toPrimitive(O, NUMBER_HINT)); if (tv->isNumber() && !std::isfinite(tv->toNumber())) RETURN_RESULT(Encode::null()); - ScopedString s(scope, scope.engine->newString(QStringLiteral("toISOString"))); + ScopedString s(scope, v4->newString(QStringLiteral("toISOString"))); ScopedValue v(scope, O->get(s)); FunctionObject *toIso = v->as<FunctionObject>(); if (!toIso) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); ScopedCallData cData(scope); cData->thisObject = callData->thisObject; - scope.result = toIso->call(cData); + return toIso->call(cData); } void DatePrototype::timezoneUpdated() diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index 2455861319..a1f6dd9a7d 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -118,57 +118,57 @@ struct DatePrototype: Object void init(ExecutionEngine *engine, Object *ctor); - static double getThisDate(Scope &scope, CallData *callData); - - static void method_parse(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_UTC(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_now(const BuiltinFunction *, Scope &scope, CallData *callData); - - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toDateString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toTimeString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toLocaleDateString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toLocaleTimeString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getTime(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getYear(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getFullYear(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getMonth(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getDate(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getDay(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getUTCDay(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getHours(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getMinutes(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getSeconds(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getTimezoneOffset(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setTime(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setSeconds(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setMinutes(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setHours(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setDate(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setMonth(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setYear(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setFullYear(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_setUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toUTCString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toISOString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toJSON(const BuiltinFunction *, Scope &scope, CallData *callData); + static double getThisDate(ExecutionEngine *v4, CallData *callData); + + static ReturnedValue method_parse(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_UTC(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_now(const BuiltinFunction *, CallData *callData); + + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toDateString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toTimeString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLocaleString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLocaleDateString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLocaleTimeString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_valueOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getTime(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getYear(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getFullYear(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getUTCFullYear(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getMonth(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getUTCMonth(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getDate(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getUTCDate(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getDay(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getUTCDay(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getHours(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getUTCHours(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getMinutes(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getUTCMinutes(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getSeconds(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getUTCSeconds(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getMilliseconds(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getUTCMilliseconds(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getTimezoneOffset(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setTime(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setMilliseconds(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setUTCMilliseconds(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setSeconds(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setUTCSeconds(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setMinutes(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setUTCMinutes(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setHours(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setUTCHours(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setDate(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setUTCDate(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setMonth(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setUTCMonth(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setYear(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setFullYear(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_setUTCFullYear(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toUTCString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toISOString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toJSON(const BuiltinFunction *, CallData *callData); static void timezoneUpdated(); }; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 8d0f401f58..ad090682cc 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -101,9 +101,9 @@ using namespace QV4; static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1); -void throwTypeError(const BuiltinFunction *, Scope &scope, CallData *) +ReturnedValue throwTypeError(const BuiltinFunction *b, CallData *) { - scope.result = scope.engine->throwTypeError(); + return b->engine()->throwTypeError(); } @@ -1554,11 +1554,6 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data) return 0; } -void ExecutionEngine::failStackLimitCheck(Scope &scope) -{ - scope.result = throwRangeError(QStringLiteral("Maximum call stack size exceeded.")); -} - // Converts a JS value to a meta-type. // data must point to a place that can store a value of the given type. // Returns true if conversion succeeded, false otherwise. diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 922c65fbe8..a628af94cd 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -449,11 +449,9 @@ public: bool metaTypeFromJS(const Value *value, int type, void *data); QV4::ReturnedValue metaTypeToJS(int type, const void *data); - bool checkStackLimits(Scope &scope); + bool checkStackLimits(); private: - void failStackLimitCheck(Scope &scope); - #ifndef QT_NO_QML_DEBUGGER QV4::Debugging::Debugger *m_debugger; QV4::Profiling::Profiler *m_profiler; @@ -535,7 +533,7 @@ inline void Managed::mark(MarkStack *markStack) m()->mark(markStack); } -#define CHECK_STACK_LIMITS(v4, scope) if ((v4)->checkStackLimits(scope)) return Encode::undefined(); \ +#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \ ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4); struct ExecutionEngineCallDepthRecorder @@ -546,10 +544,10 @@ struct ExecutionEngineCallDepthRecorder ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; } }; -inline bool ExecutionEngine::checkStackLimits(Scope &scope) +inline bool ExecutionEngine::checkStackLimits() { if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) { - failStackLimitCheck(scope); + throwRangeError(QStringLiteral("Maximum call stack size exceeded.")); return true; } diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index aef4e64964..be2bc0be9b 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -152,11 +152,12 @@ const char *ErrorObject::className(Heap::ErrorObject::ErrorType t) Q_UNREACHABLE(); } -void ErrorObject::method_get_stack(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ErrorObject::method_get_stack(const BuiltinFunction *b, CallData *callData) { - Scoped<ErrorObject> This(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + ErrorObject *This = callData->thisObject.as<ErrorObject>(); if (!This) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); if (!This->d()->stack) { QString trace; for (int i = 0; i < This->d()->stackTrace->count(); ++i) { @@ -167,9 +168,9 @@ void ErrorObject::method_get_stack(const BuiltinFunction *, Scope &scope, CallDa if (frame.line >= 0) trace += QLatin1Char(':') + QString::number(frame.line); } - This->d()->stack.set(scope.engine, scope.engine->newString(trace)); + This->d()->stack.set(v4, v4->newString(trace)); } - scope.result = This->d()->stack; + return This->d()->stack->asReturnedValue(); } DEFINE_OBJECT_VTABLE(ErrorObject); @@ -315,12 +316,14 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, He obj->defineDefaultProperty(engine->id_toString(), method_toString, 0); } -void ErrorPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ErrorPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); Object *o = callData->thisObject.as<Object>(); if (!o) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); + Scope scope(v4); ScopedValue name(scope, o->get(scope.engine->id_name())); QString qname; if (name->isUndefined()) @@ -343,5 +346,5 @@ void ErrorPrototype::method_toString(const BuiltinFunction *, Scope &scope, Call str = qname + QLatin1String(": ") + qmessage; } - scope.result = scope.engine->newString(str)->asReturnedValue(); + return scope.engine->newString(str)->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 2a0d15a63c..8e235a32de 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -175,7 +175,7 @@ struct ErrorObject: Object { static const char *className(Heap::ErrorObject::ErrorType t); - static void method_get_stack(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_get_stack(const BuiltinFunction *, CallData *callData); }; template<> @@ -286,7 +286,7 @@ struct ErrorPrototype : ErrorObject void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this, Heap::ErrorObject::Error); } static void init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t); - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); }; struct EvalErrorPrototype : ErrorObject diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 9a88ee326a..061971ec30 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -254,20 +254,23 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) } -void FunctionPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue FunctionPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); FunctionObject *fun = callData->thisObject.as<FunctionObject>(); if (!fun) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); - scope.result = scope.engine->newString(QStringLiteral("function() { [code] }")); + return Encode(v4->newString(QStringLiteral("function() { [code] }"))); } -void FunctionPrototype::method_apply(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue FunctionPrototype::method_apply(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); + Scope scope(v4); FunctionObject *o = callData->thisObject.as<FunctionObject>(); if (!o) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); ScopedValue arg(scope, callData->argument(1)); @@ -277,7 +280,7 @@ void FunctionPrototype::method_apply(const BuiltinFunction *, Scope &scope, Call if (!arr) { len = 0; if (!arg->isNullOrUndefined()) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); } else { len = arr->getLength(); } @@ -307,14 +310,15 @@ void FunctionPrototype::method_apply(const BuiltinFunction *, Scope &scope, Call } cData->thisObject = callData->argument(0); - scope.result = o->call(cData); + return o->call(cData); } -void FunctionPrototype::method_call(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue FunctionPrototype::method_call(const BuiltinFunction *b, CallData *callData) { + QV4::Scope scope(b); FunctionObject *o = callData->thisObject.as<FunctionObject>(); if (!o) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); ScopedCallData cData(scope, callData->argc ? callData->argc - 1 : 0); if (callData->argc) { @@ -323,14 +327,15 @@ void FunctionPrototype::method_call(const BuiltinFunction *, Scope &scope, CallD } cData->thisObject = callData->argument(0); - scope.result = o->call(cData); + return o->call(cData); } -void FunctionPrototype::method_bind(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue FunctionPrototype::method_bind(const BuiltinFunction *b, CallData *callData) { + QV4::Scope scope(b); FunctionObject *target = callData->thisObject.as<FunctionObject>(); if (!target) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); ScopedValue boundThis(scope, callData->argument(0)); Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0); @@ -342,7 +347,7 @@ void FunctionPrototype::method_bind(const BuiltinFunction *, Scope &scope, CallD } ExecutionContext *global = scope.engine->rootContext(); - scope.result = BoundFunction::create(global, target, boundThis, boundArgs); + return BoundFunction::create(global, target, boundThis, boundArgs)->asReturnedValue(); } DEFINE_OBJECT_VTABLE(ScriptFunction); @@ -352,10 +357,9 @@ ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData) ExecutionEngine *v4 = that->engine(); if (Q_UNLIKELY(v4->hasException)) return Encode::undefined(); + CHECK_STACK_LIMITS(v4); Scope scope(v4); - CHECK_STACK_LIMITS(v4, scope); - ExecutionContextSaver ctxSaver(scope); Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that)); @@ -369,16 +373,17 @@ ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData) Q_ASSERT(v4Function); ScopedContext c(scope, f->scope()); + ScopedValue result(scope); if (v4Function->canUseSimpleCall) - c->simpleCall(scope, callData, v4Function); + result = c->simpleCall(scope, callData, v4Function); else - c->call(scope, callData, v4Function, f); + result = c->call(scope, callData, v4Function, f); if (Q_UNLIKELY(v4->hasException)) return Encode::undefined(); - else if (!scope.result.isObject()) + else if (!result->isObject()) return obj.asReturnedValue(); - return Encode(scope.result); + return result->asReturnedValue(); } ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData) @@ -386,10 +391,9 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData) ExecutionEngine *v4 = that->engine(); if (Q_UNLIKELY(v4->hasException)) return Encode::undefined(); + CHECK_STACK_LIMITS(v4); Scope scope(v4); - CHECK_STACK_LIMITS(v4, scope); - Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that)); QV4::Function *v4Function = f->function(); @@ -397,10 +401,9 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData) ScopedContext c(scope, f->scope()); if (v4Function->canUseSimpleCall) - c->simpleCall(scope, callData, v4Function); + return c->simpleCall(scope, callData, v4Function); else - c->call(scope, callData, v4Function, f); - return Encode(scope.result); + return c->call(scope, callData, v4Function, f); } void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) @@ -447,7 +450,7 @@ InternalClass *ScriptFunction::classForConstructor() const DEFINE_OBJECT_VTABLE(BuiltinFunction); -void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *)) +void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(const QV4::BuiltinFunction *, CallData *)) { Heap::FunctionObject::init(scope, name); this->code = code; @@ -465,9 +468,7 @@ ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData) if (v4->hasException) return Encode::undefined(); - Scope scope(v4); - f->d()->code(f, scope, callData); - return Encode(scope.result); + return f->d()->code(f, callData); } @@ -477,10 +478,9 @@ ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callDa ExecutionEngine *v4 = f->engine(); if (v4->hasException) return Encode::undefined(); + CHECK_STACK_LIMITS(v4); Scope scope(v4); - CHECK_STACK_LIMITS(v4, scope); - ExecutionContextSaver ctxSaver(scope); CallContext::Data *ctx = v4->memoryManager->allocSimpleCallContext(); @@ -489,9 +489,9 @@ ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callDa v4->pushContext(ctx); Q_ASSERT(v4->current == ctx); - scope.result = f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext), f->d()->index); + ReturnedValue result = f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext), f->d()->index); v4->memoryManager->freeSimpleCallContext(); - return Encode(scope.result); + return result; } DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index e62ffae20b..5eea262e2e 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -96,14 +96,9 @@ struct FunctionPrototype : FunctionObject { void init(); }; -struct Q_QML_EXPORT OldBuiltinFunction : FunctionObject { - void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)); - ReturnedValue (*code)(QV4::CallContext *); -}; - struct Q_QML_EXPORT BuiltinFunction : FunctionObject { - void init(QV4::ExecutionContext *scope, QV4::String *name, void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *)); - void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *); + void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(const QV4::BuiltinFunction *, CallData *)); + ReturnedValue (*code)(const QV4::BuiltinFunction *, CallData *); }; struct IndexedBuiltinFunction : FunctionObject { @@ -188,17 +183,17 @@ struct FunctionPrototype: FunctionObject void init(ExecutionEngine *engine, Object *ctor); - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_apply(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_call(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_bind(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_apply(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_call(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_bind(const BuiltinFunction *, CallData *callData); }; struct Q_QML_EXPORT BuiltinFunction : FunctionObject { V4_OBJECT2(BuiltinFunction, FunctionObject) V4_INTERNALCLASS(BuiltinFunction) - static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *)) + static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(const BuiltinFunction *, CallData *)) { return scope->engine()->memoryManager->allocObject<BuiltinFunction>(scope, name, code); } diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 35961e6f75..dab6de572d 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -414,8 +414,9 @@ static inline int toInt(const QChar &qc, int R) } // parseInt [15.1.2.2] -void GlobalFunctions::method_parseInt(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_parseInt(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedValue inputString(scope, callData->argument(0)); ScopedValue radix(scope, callData->argument(1)); int R = radix->isUndefined() ? 0 : radix->toInt32(); @@ -494,8 +495,9 @@ void GlobalFunctions::method_parseInt(const BuiltinFunction *, Scope &scope, Cal } // parseFloat [15.1.2.3] -void GlobalFunctions::method_parseFloat(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_parseFloat(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); // [15.1.2.3] step by step: ScopedString inputString(scope, callData->argument(0), ScopedString::Convert); CHECK_EXCEPTION(); @@ -520,7 +522,7 @@ void GlobalFunctions::method_parseFloat(const BuiltinFunction *, Scope &scope, C } /// isNaN [15.1.2.4] -void GlobalFunctions::method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_isNaN(const BuiltinFunction *, CallData *callData) { if (!callData->argc) // undefined gets converted to NaN @@ -534,7 +536,7 @@ void GlobalFunctions::method_isNaN(const BuiltinFunction *, Scope &scope, CallDa } /// isFinite [15.1.2.5] -void GlobalFunctions::method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_isFinite(const BuiltinFunction *, CallData *callData) { if (!callData->argc) // undefined gets converted to NaN @@ -548,87 +550,97 @@ void GlobalFunctions::method_isFinite(const BuiltinFunction *, Scope &scope, Cal } /// decodeURI [15.1.3.1] -void GlobalFunctions::method_decodeURI(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_decodeURI(const BuiltinFunction *b, CallData *callData) { if (callData->argc == 0) RETURN_UNDEFINED(); + ExecutionEngine *v4 = b->engine(); QString uriString = callData->args[0].toQString(); bool ok; QString out = decode(uriString, DecodeNonReserved, &ok); if (!ok) { + Scope scope(v4); ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence"))); RETURN_RESULT(scope.engine->throwURIError(s)); } - RETURN_RESULT(scope.engine->newString(out)); + RETURN_RESULT(v4->newString(out)); } /// decodeURIComponent [15.1.3.2] -void GlobalFunctions::method_decodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_decodeURIComponent(const BuiltinFunction *b, CallData *callData) { if (callData->argc == 0) RETURN_UNDEFINED(); + ExecutionEngine *v4 = b->engine(); QString uriString = callData->args[0].toQString(); bool ok; QString out = decode(uriString, DecodeAll, &ok); if (!ok) { + Scope scope(v4); ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence"))); RETURN_RESULT(scope.engine->throwURIError(s)); } - RETURN_RESULT(scope.engine->newString(out)); + RETURN_RESULT(v4->newString(out)); } /// encodeURI [15.1.3.3] -void GlobalFunctions::method_encodeURI(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_encodeURI(const BuiltinFunction *b, CallData *callData) { if (callData->argc == 0) RETURN_UNDEFINED(); + ExecutionEngine *v4 = b->engine(); QString uriString = callData->args[0].toQString(); bool ok; QString out = encode(uriString, uriUnescapedReserved, &ok); if (!ok) { + Scope scope(v4); ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence"))); RETURN_RESULT(scope.engine->throwURIError(s)); } - RETURN_RESULT(scope.engine->newString(out)); + RETURN_RESULT(v4->newString(out)); } /// encodeURIComponent [15.1.3.4] -void GlobalFunctions::method_encodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_encodeURIComponent(const BuiltinFunction *b, CallData *callData) { if (callData->argc == 0) RETURN_UNDEFINED(); + ExecutionEngine *v4 = b->engine(); QString uriString = callData->args[0].toQString(); bool ok; QString out = encode(uriString, uriUnescaped, &ok); if (!ok) { + Scope scope(v4); ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence"))); RETURN_RESULT(scope.engine->throwURIError(s)); } - RETURN_RESULT(scope.engine->newString(out)); + RETURN_RESULT(v4->newString(out)); } -void GlobalFunctions::method_escape(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_escape(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); if (!callData->argc) - RETURN_RESULT(scope.engine->newString(QStringLiteral("undefined"))); + RETURN_RESULT(v4->newString(QStringLiteral("undefined"))); QString str = callData->args[0].toQString(); - RETURN_RESULT(scope.engine->newString(escape(str))); + RETURN_RESULT(v4->newString(escape(str))); } -void GlobalFunctions::method_unescape(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue GlobalFunctions::method_unescape(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); if (!callData->argc) - RETURN_RESULT(scope.engine->newString(QStringLiteral("undefined"))); + RETURN_RESULT(v4->newString(QStringLiteral("undefined"))); QString str = callData->args[0].toQString(); - RETURN_RESULT(scope.engine->newString(unescape(str))); + RETURN_RESULT(v4->newString(unescape(str))); } diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index 152b69001b..5489a9fbb0 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -76,16 +76,16 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject struct GlobalFunctions { - static void method_parseInt(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_parseFloat(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_decodeURI(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_decodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_encodeURI(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_encodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_escape(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_unescape(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_parseInt(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_parseFloat(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isNaN(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isFinite(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_decodeURI(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_decodeURIComponent(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_encodeURI(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_encodeURIComponent(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_escape(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_unescape(const BuiltinFunction *, CallData *callData); }; } diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 2f00022659..49ccb7c2e9 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -195,8 +195,9 @@ void QV4Include::finished() /* Documented in qv8engine.cpp */ -void QV4Include::method_include(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) +QV4::ReturnedValue QV4Include::method_include(const QV4::BuiltinFunction *b, QV4::CallData *callData) { + QV4::Scope scope(b); if (!callData->argc) RETURN_UNDEFINED(); @@ -260,13 +261,13 @@ void QV4Include::method_include(const QV4::BuiltinFunction *, QV4::Scope &scope, callback(callbackFunction, result); } - scope.result = result; #else QV4::ScopedValue result(scope); result = resultValue(scope.engine, NetworkError); callback(callbackFunction, result); - scope.result = result; #endif + + return result->asReturnedValue(); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h index 5908d6bfde..68537ba2e8 100644 --- a/src/qml/jsruntime/qv4include_p.h +++ b/src/qml/jsruntime/qv4include_p.h @@ -77,7 +77,7 @@ public: Exception = 3 }; - static void method_include(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static QV4::ReturnedValue method_include(const QV4::BuiltinFunction *, QV4::CallData *callData); private Q_SLOTS: void finished(); diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 60d1f13358..27cce52512 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -883,25 +883,28 @@ void Heap::JsonObject::init() } -void JsonObject::method_parse(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue JsonObject::method_parse(const BuiltinFunction *b, CallData *callData) { - ScopedValue v(scope, callData->argument(0)); - QString jtext = v->toQString(); + ExecutionEngine *v4 = b->engine(); + QString jtext; + if (callData->argc > 0) + jtext = callData->args[0].toQString(); DEBUG << "parsing source = " << jtext; - JsonParser parser(scope.engine, jtext.constData(), jtext.length()); + JsonParser parser(v4, jtext.constData(), jtext.length()); QJsonParseError error; - ScopedValue result(scope, parser.parse(&error)); + ReturnedValue result = parser.parse(&error); if (error.error != QJsonParseError::NoError) { DEBUG << "parse error" << error.errorString(); - RETURN_RESULT(scope.engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"))); + RETURN_RESULT(v4->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"))); } - scope.result = result; + return result; } -void JsonObject::method_stringify(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue JsonObject::method_stringify(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); Stringify stringify(scope.engine); ScopedObject o(scope, callData->argument(1)); @@ -946,7 +949,7 @@ void JsonObject::method_stringify(const BuiltinFunction *, Scope &scope, CallDat QString result = stringify.Str(QString(), arg0); if (result.isEmpty() || scope.engine->hasException) RETURN_UNDEFINED(); - scope.result = scope.engine->newString(result); + return Encode(scope.engine->newString(result)); } diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index a73ce1c74e..19dba14aef 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -88,8 +88,8 @@ private: typedef QSet<ObjectItem> V4ObjectSet; public: - static void method_parse(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_stringify(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_parse(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_stringify(const BuiltinFunction *, CallData *callData); static ReturnedValue fromJsonValue(ExecutionEngine *engine, const QJsonValue &value); static ReturnedValue fromJsonObject(ExecutionEngine *engine, const QJsonObject &object); diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 98a5e5f1f7..2c1fefe9f8 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -92,7 +92,7 @@ static Q_ALWAYS_INLINE double copySign(double x, double y) return ::copysign(x, y); } -void MathObject::method_abs(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_abs(const BuiltinFunction *, CallData *callData) { if (!callData->argc) RETURN_RESULT(Encode(qt_qnan())); @@ -109,7 +109,7 @@ void MathObject::method_abs(const BuiltinFunction *, Scope &scope, CallData *cal RETURN_RESULT(Encode(v < 0 ? -v : v)); } -void MathObject::method_acos(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_acos(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : 2; if (v > 1) @@ -118,7 +118,7 @@ void MathObject::method_acos(const BuiltinFunction *, Scope &scope, CallData *ca RETURN_RESULT(Encode(std::acos(v))); } -void MathObject::method_asin(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_asin(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : 2; if (v > 1) @@ -127,7 +127,7 @@ void MathObject::method_asin(const BuiltinFunction *, Scope &scope, CallData *ca RETURN_RESULT(Encode(std::asin(v))); } -void MathObject::method_atan(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_atan(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (v == 0.0) @@ -136,7 +136,7 @@ void MathObject::method_atan(const BuiltinFunction *, Scope &scope, CallData *ca RETURN_RESULT(Encode(std::atan(v))); } -void MathObject::method_atan2(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_atan2(const BuiltinFunction *, CallData *callData) { double v1 = callData->argc ? callData->args[0].toNumber() : qt_qnan(); double v2 = callData->argc > 1 ? callData->args[1].toNumber() : qt_qnan(); @@ -154,7 +154,7 @@ void MathObject::method_atan2(const BuiltinFunction *, Scope &scope, CallData *c RETURN_RESULT(Encode(std::atan2(v1, v2))); } -void MathObject::method_ceil(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_ceil(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (v < 0.0 && v > -1.0) @@ -163,13 +163,13 @@ void MathObject::method_ceil(const BuiltinFunction *, Scope &scope, CallData *ca RETURN_RESULT(Encode(std::ceil(v))); } -void MathObject::method_cos(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_cos(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); RETURN_RESULT(Encode(std::cos(v))); } -void MathObject::method_exp(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_exp(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (qt_is_inf(v)) { @@ -182,7 +182,7 @@ void MathObject::method_exp(const BuiltinFunction *, Scope &scope, CallData *cal } } -void MathObject::method_floor(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_floor(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); Value result = Primitive::fromDouble(std::floor(v)); @@ -190,7 +190,7 @@ void MathObject::method_floor(const BuiltinFunction *, Scope &scope, CallData *c RETURN_RESULT(result); } -void MathObject::method_log(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_log(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (v < 0) @@ -199,7 +199,7 @@ void MathObject::method_log(const BuiltinFunction *, Scope &scope, CallData *cal RETURN_RESULT(Encode(std::log(v))); } -void MathObject::method_max(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_max(const BuiltinFunction *, CallData *callData) { double mx = -qt_inf(); for (int i = 0; i < callData->argc; ++i) { @@ -210,7 +210,7 @@ void MathObject::method_max(const BuiltinFunction *, Scope &scope, CallData *cal RETURN_RESULT(Encode(mx)); } -void MathObject::method_min(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_min(const BuiltinFunction *, CallData *callData) { double mx = qt_inf(); for (int i = 0; i < callData->argc; ++i) { @@ -223,7 +223,7 @@ void MathObject::method_min(const BuiltinFunction *, Scope &scope, CallData *cal RETURN_RESULT(Encode(mx)); } -void MathObject::method_pow(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_pow(const BuiltinFunction *, CallData *callData) { double x = callData->argc > 0 ? callData->args[0].toNumber() : qt_qnan(); double y = callData->argc > 1 ? callData->args[1].toNumber() : qt_qnan(); @@ -275,12 +275,12 @@ void MathObject::method_pow(const BuiltinFunction *, Scope &scope, CallData *cal Q_GLOBAL_STATIC(QThreadStorage<bool *>, seedCreatedStorage); -void MathObject::method_random(const BuiltinFunction *, Scope &scope, CallData *) +ReturnedValue MathObject::method_random(const BuiltinFunction *b, CallData *) { if (!seedCreatedStorage()->hasLocalData()) { int msecs = QTime(0,0,0).msecsTo(QTime::currentTime()); Q_ASSERT(msecs >= 0); - qsrand(uint(uint(msecs) ^ reinterpret_cast<quintptr>(scope.engine))); + qsrand(uint(uint(msecs) ^ reinterpret_cast<quintptr>(b))); seedCreatedStorage()->setLocalData(new bool(true)); } // rand()/qrand() return a value where the upperbound is RAND_MAX inclusive. So, instead of @@ -289,14 +289,14 @@ void MathObject::method_random(const BuiltinFunction *, Scope &scope, CallData * RETURN_RESULT(Encode(qrand() / double(upperLimit))); } -void MathObject::method_round(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_round(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); v = copySign(std::floor(v + 0.5), v); RETURN_RESULT(Encode(v)); } -void MathObject::method_sign(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_sign(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); @@ -309,19 +309,19 @@ void MathObject::method_sign(const BuiltinFunction *, Scope &scope, CallData *ca RETURN_RESULT(Encode(std::signbit(v) ? -1 : 1)); } -void MathObject::method_sin(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_sin(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); RETURN_RESULT(Encode(std::sin(v))); } -void MathObject::method_sqrt(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_sqrt(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); RETURN_RESULT(Encode(std::sqrt(v))); } -void MathObject::method_tan(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue MathObject::method_tan(const BuiltinFunction *, CallData *callData) { double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (v == 0.0) diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h index e617712905..016f0c16ca 100644 --- a/src/qml/jsruntime/qv4mathobject_p.h +++ b/src/qml/jsruntime/qv4mathobject_p.h @@ -69,25 +69,25 @@ struct MathObject: Object V4_OBJECT2(MathObject, Object) Q_MANAGED_TYPE(MathObject) - static void method_abs(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_acos(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_asin(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_atan(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_atan2(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_ceil(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_cos(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_exp(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_floor(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_log(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_max(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_min(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_pow(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_random(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_round(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_sign(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_sin(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_sqrt(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_tan(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_abs(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_acos(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_asin(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_atan(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_atan2(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_ceil(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_cos(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_exp(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_floor(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_log(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_max(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_min(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_pow(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_random(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_round(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_sign(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_sin(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_sqrt(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_tan(const BuiltinFunction *, CallData *callData); }; } diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 40586b558b..1db5079355 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -124,117 +124,99 @@ QT_WARNING_POP defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision, 1); } -inline ReturnedValue thisNumberValue(Scope &scope, CallData *callData) +inline ReturnedValue thisNumberValue(ExecutionEngine *v4, CallData *callData) { if (callData->thisObject.isNumber()) return callData->thisObject.asReturnedValue(); NumberObject *n = callData->thisObject.as<NumberObject>(); if (!n) { - scope.engine->throwTypeError(); + v4->throwTypeError(); return Encode::undefined(); } return Encode(n->value()); } -inline double thisNumber(Scope &scope, CallData *callData) +inline double thisNumber(ExecutionEngine *engine, CallData *callData) { if (callData->thisObject.isNumber()) return callData->thisObject.asDouble(); NumberObject *n = callData->thisObject.as<NumberObject>(); if (!n) { - scope.engine->throwTypeError(); + engine->throwTypeError(); return 0; } return n->value(); } -void NumberPrototype::method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_isFinite(const BuiltinFunction *, CallData *callData) { - if (!callData->argc) { - scope.result = Encode(false); - return; - } + if (!callData->argc) + return Encode(false); double v = callData->args[0].toNumber(); - scope.result = Encode(!std::isnan(v) && !qt_is_inf(v)); + return Encode(!std::isnan(v) && !qt_is_inf(v)); } -void NumberPrototype::method_isInteger(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_isInteger(const BuiltinFunction *, CallData *callData) { - if (!callData->argc) { - scope.result = Encode(false); - return; - } + if (!callData->argc) + return Encode(false); const Value &v = callData->args[0]; - if (!v.isNumber()) { - scope.result = Encode(false); - return; - } + if (!v.isNumber()) + return Encode(false); double dv = v.toNumber(); - if (std::isnan(dv) || qt_is_inf(dv)) { - scope.result = Encode(false); - return; - } + if (std::isnan(dv) || qt_is_inf(dv)) + return Encode(false); double iv = v.toInteger(); - scope.result = Encode(dv == iv); + return Encode(dv == iv); } -void NumberPrototype::method_isSafeInteger(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_isSafeInteger(const BuiltinFunction *, CallData *callData) { - if (!callData->argc) { - scope.result = Encode(false); - return; - } + if (!callData->argc) + return Encode(false); const Value &v = callData->args[0]; - if (!v.isNumber()) { - scope.result = Encode(false); - return; - } + if (!v.isNumber()) + return Encode(false); double dv = v.toNumber(); - if (std::isnan(dv) || qt_is_inf(dv)) { - scope.result = Encode(false); - return; - } + if (std::isnan(dv) || qt_is_inf(dv)) + return Encode(false); double iv = v.toInteger(); - scope.result = Encode(dv == iv && std::fabs(iv) <= (2^53)-1); + return Encode(dv == iv && std::fabs(iv) <= (2^53)-1); } -void NumberPrototype::method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_isNaN(const BuiltinFunction *, CallData *callData) { - if (!callData->argc) { - scope.result = Encode(false); - return; - } + if (!callData->argc) + return Encode(false); double v = callData->args[0].toNumber(); - scope.result = Encode(std::isnan(v)); + return Encode(std::isnan(v)); } -void NumberPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { - double num = thisNumber(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + double num = thisNumber(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); if (callData->argc && !callData->args[0].isUndefined()) { int radix = callData->args[0].toInt32(); if (radix < 2 || radix > 36) { - scope.result = scope.engine->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix") - .arg(radix)); - return; + return v4->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix").arg(radix)); } if (std::isnan(num)) { - scope.result = scope.engine->newString(QStringLiteral("NaN")); - return; + return Encode(v4->newString(QStringLiteral("NaN"))); } else if (qt_is_inf(num)) { - scope.result = scope.engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity")); - return; + return Encode(v4->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))); } if (radix != 10) { @@ -264,30 +246,31 @@ void NumberPrototype::method_toString(const BuiltinFunction *, Scope &scope, Cal } if (negative) str.prepend(QLatin1Char('-')); - scope.result = scope.engine->newString(str); - return; + return Encode(v4->newString(str)); } } - scope.result = Primitive::fromDouble(num).toString(scope.engine); + return Encode(Primitive::fromDouble(num).toString(v4)); } -void NumberPrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_toLocaleString(const BuiltinFunction *b, CallData *callData) { - ScopedValue v(scope, thisNumberValue(scope, callData)); - scope.result = v->toString(scope.engine); - CHECK_EXCEPTION(); + Scope scope(b); + ScopedValue v(scope, thisNumberValue(b->engine(), callData)); + return Encode(v->toString(scope.engine)); } -void NumberPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_valueOf(const BuiltinFunction *b, CallData *callData) { - scope.result = thisNumberValue(scope, callData); + return thisNumberValue(b->engine(), callData); } -void NumberPrototype::method_toFixed(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_toFixed(const BuiltinFunction *b, CallData *callData) { - double v = thisNumber(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + double v = thisNumber(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); double fdigits = 0; @@ -297,10 +280,8 @@ void NumberPrototype::method_toFixed(const BuiltinFunction *, Scope &scope, Call if (std::isnan(fdigits)) fdigits = 0; - if (fdigits < 0 || fdigits > 20) { - scope.result = scope.engine->throwRangeError(callData->thisObject); - return; - } + if (fdigits < 0 || fdigits > 20) + return v4->throwRangeError(callData->thisObject); QString str; if (std::isnan(v)) @@ -310,49 +291,51 @@ void NumberPrototype::method_toFixed(const BuiltinFunction *, Scope &scope, Call else if (v < 1.e21) str = NumberLocale::instance()->toString(v, 'f', int(fdigits)); else { - scope.result = RuntimeHelpers::stringFromNumber(scope.engine, v); - return; + return Encode(RuntimeHelpers::stringFromNumber(v4, v)); } - scope.result = scope.engine->newString(str); + return Encode(v4->newString(str)); } -void NumberPrototype::method_toExponential(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_toExponential(const BuiltinFunction *b, CallData *callData) { - double d = thisNumber(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + double d = thisNumber(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); + int fdigits = NumberLocale::instance()->defaultDoublePrecision; if (callData->argc && !callData->args[0].isUndefined()) { fdigits = callData->args[0].toInt32(); if (fdigits < 0 || fdigits > 20) { - ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range"))); - scope.result = scope.engine->throwRangeError(error); - return; + Scope scope(v4); + ScopedString error(scope, v4->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range"))); + return v4->throwRangeError(error); } } QString result = NumberLocale::instance()->toString(d, 'e', fdigits); - scope.result = scope.engine->newString(result); + return Encode(v4->newString(result)); } -void NumberPrototype::method_toPrecision(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue NumberPrototype::method_toPrecision(const BuiltinFunction *b, CallData *callData) { - ScopedValue v(scope, thisNumberValue(scope, callData)); - CHECK_EXCEPTION(); + Scope scope(b); + ScopedValue v(scope, thisNumberValue(scope.engine, callData)); + if (scope.engine->hasException) + return QV4::Encode::undefined(); - if (!callData->argc || callData->args[0].isUndefined()) { - scope.result = v->toString(scope.engine); - return; - } + + if (!callData->argc || callData->args[0].isUndefined()) + return Encode(v->toString(scope.engine)); int precision = callData->args[0].toInt32(); if (precision < 1 || precision > 21) { ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range"))); - scope.result = scope.engine->throwRangeError(error); - return; + return scope.engine->throwRangeError(error); } QString result = NumberLocale::instance()->toString(v->asDouble(), 'g', precision); - scope.result = scope.engine->newString(result); + return Encode(scope.engine->newString(result)); } diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index 5622bf4728..6a2b5953a6 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -88,16 +88,16 @@ struct NumberPrototype: NumberObject V4_PROTOTYPE(objectPrototype) void init(ExecutionEngine *engine, Object *ctor); - static void method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isInteger(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isSafeInteger(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toFixed(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toExponential(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toPrecision(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_isFinite(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isInteger(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isSafeInteger(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isNaN(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLocaleString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_valueOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toFixed(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toExponential(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toPrecision(const BuiltinFunction *, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 9c1cbf2357..543968f6ec 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -153,7 +153,7 @@ void Object::defineDefaultProperty(const QString &name, const Value &value) defineDefaultProperty(s, value); } -void Object::defineDefaultProperty(const QString &name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount) +void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(const BuiltinFunction *, CallData *), int argumentCount) { ExecutionEngine *e = engine(); Scope scope(e); @@ -164,7 +164,7 @@ void Object::defineDefaultProperty(const QString &name, void (*code)(const Built defineDefaultProperty(s, function); } -void Object::defineDefaultProperty(String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount) +void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(const BuiltinFunction *, CallData *), int argumentCount) { ExecutionEngine *e = engine(); Scope scope(e); @@ -174,8 +174,8 @@ void Object::defineDefaultProperty(String *name, void (*code)(const BuiltinFunct defineDefaultProperty(name, function); } -void Object::defineAccessorProperty(const QString &name, void (*getter)(const BuiltinFunction *, Scope &, CallData *), - void (*setter)(const BuiltinFunction *, Scope &, CallData *)) +void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const BuiltinFunction *, CallData *), + ReturnedValue (*setter)(const BuiltinFunction *, CallData *)) { ExecutionEngine *e = engine(); Scope scope(e); @@ -183,8 +183,8 @@ void Object::defineAccessorProperty(const QString &name, void (*getter)(const Bu defineAccessorProperty(s, getter, setter); } -void Object::defineAccessorProperty(String *name, void (*getter)(const BuiltinFunction *, Scope &, CallData *), - void (*setter)(const BuiltinFunction *, Scope &, CallData *)) +void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(const BuiltinFunction *, CallData *), + ReturnedValue (*setter)(const BuiltinFunction *, CallData *)) { ExecutionEngine *v4 = engine(); QV4::Scope scope(v4); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 5c642bef0a..fc9a42921e 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -288,12 +288,12 @@ struct Q_QML_EXPORT Object: Managed { insertMember(name, value, Attr_Data|Attr_NotEnumerable); } void defineDefaultProperty(const QString &name, const Value &value); - void defineDefaultProperty(const QString &name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount = 0); - void defineDefaultProperty(String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount = 0); - void defineAccessorProperty(const QString &name, void (*getter)(const BuiltinFunction *, Scope &, CallData *), - void (*setter)(const BuiltinFunction *, Scope &, CallData *)); - void defineAccessorProperty(String *name, void (*getter)(const BuiltinFunction *, Scope &, CallData *), - void (*setter)(const BuiltinFunction *, Scope &, CallData *)); + void defineDefaultProperty(const QString &name, ReturnedValue (*code)(const BuiltinFunction *, CallData *), int argumentCount = 0); + void defineDefaultProperty(String *name, ReturnedValue (*code)(const BuiltinFunction *, CallData *), int argumentCount = 0); + void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const BuiltinFunction *, CallData *), + ReturnedValue (*setter)(const BuiltinFunction *, CallData *)); + void defineAccessorProperty(String *name, ReturnedValue (*getter)(const BuiltinFunction *, CallData *), + ReturnedValue (*setter)(const BuiltinFunction *, CallData *)); /* Fixed: Writable: false, Enumerable: false, Configurable: false */ void defineReadonlyProperty(const QString &name, const Value &value); void defineReadonlyProperty(String *name, const Value &value); diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 27bab52064..6dff3107cf 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -125,58 +125,78 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor) insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable); } -void ObjectPrototype::method_getPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_getPrototypeOf(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); + if (callData->argc < 1) + return scope.engine->throwTypeError(); + ScopedObject o(scope, callData->args[0].toObject(scope.engine)); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedObject p(scope, o->prototype()); - scope.result = !!p ? p->asReturnedValue() : Encode::null(); + return (!!p ? p->asReturnedValue() : Encode::null()); } -void ObjectPrototype::method_getOwnPropertyDescriptor(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); + if (callData->argc < 1) + return scope.engine->throwTypeError(); + ScopedObject O(scope, callData->args[0].toObject(scope.engine)); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); if (ArgumentsObject::isNonStrictArgumentsObject(O)) static_cast<ArgumentsObject *>(O.getPointer())->fullyCreate(); ScopedValue v(scope, callData->argument(1)); ScopedString name(scope, v->toString(scope.engine)); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); PropertyAttributes attrs; ScopedProperty desc(scope); O->getOwnProperty(name, &attrs, desc); - scope.result = fromPropertyDescriptor(scope.engine, desc, attrs); + return fromPropertyDescriptor(scope.engine, desc, attrs); } -void ObjectPrototype::method_getOwnPropertyNames(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_getOwnPropertyNames(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); + if (callData->argc < 1) + return scope.engine->throwTypeError(); + ScopedObject O(scope, callData->args[0].toObject(scope.engine)); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); - scope.result = getOwnPropertyNames(scope.engine, callData->args[0]); + return Encode(getOwnPropertyNames(scope.engine, callData->args[0])); } // 19.1.2.1 -void ObjectPrototype::method_assign(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_assign(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); + if (callData->argc < 1) + return scope.engine->throwTypeError(); + ScopedObject to(scope, callData->args[0].toObject(scope.engine)); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); - if (callData->argc == 1) { - scope.result = to; - return; - } + if (callData->argc == 1) + return to.asReturnedValue(); for (int i = 1; i < callData->argc; ++i) { if (callData->args[i].isUndefined() || callData->args[i].isNull()) continue; ScopedObject from(scope, callData->args[i].toObject(scope.engine)); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); QV4::ScopedArrayObject keys(scope, QV4::ObjectPrototype::getOwnPropertyNames(scope.engine, from)); quint32 length = keys->getLength(); @@ -197,64 +217,66 @@ void ObjectPrototype::method_assign(const BuiltinFunction *, Scope &scope, CallD propValue = from->get(nextKey); to->set(nextKey, propValue, Object::DoThrowOnRejection); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); } } - scope.result = to; + return to.asReturnedValue(); } -void ObjectPrototype::method_create(const BuiltinFunction *builtin, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_create(const BuiltinFunction *builtin, CallData *callData) { + Scope scope(builtin); ScopedValue O(scope, callData->argument(0)); - if (!O->isObject() && !O->isNull()) { - scope.result = scope.engine->throwTypeError(); - return; - } + if (!O->isObject() && !O->isNull()) + return scope.engine->throwTypeError(); ScopedObject newObject(scope, scope.engine->newObject()); newObject->setPrototype(O->as<Object>()); if (callData->argc > 1 && !callData->args[1].isUndefined()) { callData->args[0] = newObject; - method_defineProperties(builtin, scope, callData); - return; + return method_defineProperties(builtin, callData); } - scope.result = newObject; + return newObject.asReturnedValue(); } -void ObjectPrototype::method_defineProperty(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_defineProperty(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject O(scope, callData->argument(0)); - if (!O) { - scope.result = scope.engine->throwTypeError(); - return; - } + if (!O) + return scope.engine->throwTypeError(); ScopedString name(scope, callData->argument(1), ScopedString::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedValue attributes(scope, callData->argument(2)); ScopedProperty pd(scope); PropertyAttributes attrs; toPropertyDescriptor(scope.engine, attributes, pd, &attrs); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); if (!O->__defineOwnProperty__(scope.engine, name, pd, attrs)) THROW_TYPE_ERROR(); - scope.result = O; + return O.asReturnedValue(); } -void ObjectPrototype::method_defineProperties(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_defineProperties(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject O(scope, callData->argument(0)); if (!O) THROW_TYPE_ERROR(); ScopedObject o(scope, callData->argument(1), ScopedObject::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedValue val(scope); @@ -271,7 +293,8 @@ void ObjectPrototype::method_defineProperties(const BuiltinFunction *, Scope &sc PropertyAttributes nattrs; val = o->getValue(pd->value, attrs); toPropertyDescriptor(scope.engine, val, n, &nattrs); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); bool ok; if (name) ok = O->__defineOwnProperty__(scope.engine, name, n, nattrs); @@ -281,17 +304,16 @@ void ObjectPrototype::method_defineProperties(const BuiltinFunction *, Scope &sc THROW_TYPE_ERROR(); } - scope.result = O; + return O.asReturnedValue(); } -void ObjectPrototype::method_seal(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_seal(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->argument(0)); - if (!o) { + if (!o) // 19.1.2.17, 1 - scope.result = callData->argument(0); - return; - } + return callData->argument(0); o->setInternalClass(o->internalClass()->sealed()); @@ -303,17 +325,16 @@ void ObjectPrototype::method_seal(const BuiltinFunction *, Scope &scope, CallDat } } - scope.result = o; + return o.asReturnedValue(); } -void ObjectPrototype::method_freeze(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_freeze(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->argument(0)); - if (!o) { + if (!o) // 19.1.2.5, 1 - scope.result = callData->argument(0); - return; - } + return callData->argument(0); if (ArgumentsObject::isNonStrictArgumentsObject(o)) static_cast<ArgumentsObject *>(o.getPointer())->fullyCreate(); @@ -329,116 +350,94 @@ void ObjectPrototype::method_freeze(const BuiltinFunction *, Scope &scope, CallD o->arrayData()->attrs[i].setWritable(false); } } - scope.result = o; + return o.asReturnedValue(); } -void ObjectPrototype::method_preventExtensions(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_preventExtensions(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->args[0].toObject(scope.engine)); - if (!o) { - scope.result = callData->argument(0); - return; - } + if (!o) + return callData->argument(0); o->setInternalClass(o->internalClass()->nonExtensible()); - scope.result = o; + return o.asReturnedValue(); } -void ObjectPrototype::method_isSealed(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_isSealed(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->args[0].toObject(scope.engine)); - if (!o) { - scope.result = Encode(true); - return; - } + if (!o) + return Encode(true); - if (o->isExtensible()) { - scope.result = Encode(false); - return; - } + if (o->isExtensible()) + return Encode(false); - if (o->internalClass() != o->internalClass()->sealed()) { - scope.result = Encode(false); - return; - } + if (o->internalClass() != o->internalClass()->sealed()) + return Encode(false); - if (!o->arrayData() || !o->arrayData()->length()) { - scope.result = Encode(true); - return; - } + if (!o->arrayData() || !o->arrayData()->length()) + return Encode(true); Q_ASSERT(o->arrayData() && o->arrayData()->length()); - if (!o->arrayData()->attrs) { - scope.result = Encode(false); - return; - } + if (!o->arrayData()->attrs) + return Encode(false); for (uint i = 0; i < o->arrayData()->values.alloc; ++i) { if (!o->arrayData()->isEmpty(i)) - if (o->arrayData()->attributes(i).isConfigurable()) { - scope.result = Encode(false); - return; - } + if (o->arrayData()->attributes(i).isConfigurable()) + return Encode(false); } - scope.result = Encode(true); + return Encode(true); } -void ObjectPrototype::method_isFrozen(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_isFrozen(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->args[0].toObject(scope.engine)); - if (!o) { - scope.result = Encode(true); - return; - } + if (!o) + return Encode(true); - if (o->isExtensible()) { - scope.result = Encode(false); - return; - } + if (o->isExtensible()) + return Encode(false); - if (o->internalClass() != o->internalClass()->frozen()) { - scope.result = Encode(false); - return; - } + if (o->internalClass() != o->internalClass()->frozen()) + return Encode(false); - if (!o->arrayData() || !o->arrayData()->length()) { - scope.result = Encode(true); - return; - } + if (!o->arrayData() || !o->arrayData()->length()) + return Encode(true); Q_ASSERT(o->arrayData() && o->arrayData()->length()); - if (!o->arrayData()->attrs) { - scope.result = Encode(false); - return; - } + if (!o->arrayData()->attrs) + return Encode(false); for (uint i = 0; i < o->arrayData()->values.alloc; ++i) { if (!o->arrayData()->isEmpty(i)) - if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) { - scope.result = Encode(false); - return; - } + if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) + return Encode(false); } - scope.result = Encode(true); + return Encode(true); } -void ObjectPrototype::method_isExtensible(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_isExtensible(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->args[0].toObject(scope.engine)); - if (!o) { - scope.result = Encode(false); - return; - } + if (!o) + return Encode(false); - scope.result = Encode((bool)o->isExtensible()); + return Encode((bool)o->isExtensible()); } -void ObjectPrototype::method_keys(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_keys(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->args[0].toObject(scope.engine)); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedArrayObject a(scope, scope.engine->newArrayObject()); @@ -451,24 +450,27 @@ void ObjectPrototype::method_keys(const BuiltinFunction *, Scope &scope, CallDat a->push_back(name); } - scope.result = a; + return a.asReturnedValue(); } -void ObjectPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); if (callData->thisObject.isUndefined()) { - scope.result = scope.engine->newString(QStringLiteral("[object Undefined]")); + return Encode(v4->newString(QStringLiteral("[object Undefined]"))); } else if (callData->thisObject.isNull()) { - scope.result = scope.engine->newString(QStringLiteral("[object Null]")); + return Encode(v4->newString(QStringLiteral("[object Null]"))); } else { + Scope scope(v4); ScopedObject obj(scope, callData->thisObject.toObject(scope.engine)); QString className = obj->className(); - scope.result = scope.engine->newString(QStringLiteral("[object %1]").arg(className)); + return Encode(v4->newString(QStringLiteral("[object %1]").arg(className))); } } -void ObjectPrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_toLocaleString(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->thisObject.toObject(scope.engine)); if (!o) RETURN_UNDEFINED(); @@ -478,61 +480,66 @@ void ObjectPrototype::method_toLocaleString(const BuiltinFunction *, Scope &scop THROW_TYPE_ERROR(); ScopedCallData cData(scope); cData->thisObject = o; - scope.result = f->call(callData); + return f->call(callData); } -void ObjectPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_valueOf(const BuiltinFunction *b, CallData *callData) { - scope.result = callData->thisObject.toObject(scope.engine); + return Encode(callData->thisObject.toObject(b->engine())); } -void ObjectPrototype::method_hasOwnProperty(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_hasOwnProperty(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedString P(scope, callData->argument(0), ScopedString::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedObject O(scope, callData->thisObject, ScopedObject::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); bool r = O->hasOwnProperty(P); if (!r) r = !O->query(P).isEmpty(); - scope.result = Encode(r); + return Encode(r); } -void ObjectPrototype::method_isPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_isPrototypeOf(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject V(scope, callData->argument(0)); - if (!V) { - scope.result = Encode(false); - return; - } + if (!V) + return Encode(false); ScopedObject O(scope, callData->thisObject, ScopedObject::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedObject proto(scope, V->prototype()); while (proto) { - if (O->d() == proto->d()) { - scope.result = Encode(true); - return; - } + if (O->d() == proto->d()) + return Encode(true); proto = proto->prototype(); } - scope.result = Encode(false); + return Encode(false); } -void ObjectPrototype::method_propertyIsEnumerable(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_propertyIsEnumerable(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedString p(scope, callData->argument(0), ScopedString::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedObject o(scope, callData->thisObject, ScopedObject::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); PropertyAttributes attrs; o->getOwnProperty(p, &attrs); - scope.result = Encode(attrs.isEnumerable()); + return Encode(attrs.isEnumerable()); } -void ObjectPrototype::method_defineGetter(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_defineGetter(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); if (callData->argc < 2) THROW_TYPE_ERROR(); @@ -541,7 +548,8 @@ void ObjectPrototype::method_defineGetter(const BuiltinFunction *, Scope &scope, THROW_TYPE_ERROR(); ScopedString prop(scope, callData->argument(0), ScopedString::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedObject o(scope, callData->thisObject); if (!o) { @@ -557,8 +565,9 @@ void ObjectPrototype::method_defineGetter(const BuiltinFunction *, Scope &scope, RETURN_UNDEFINED(); } -void ObjectPrototype::method_defineSetter(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_defineSetter(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); if (callData->argc < 2) THROW_TYPE_ERROR(); @@ -567,7 +576,8 @@ void ObjectPrototype::method_defineSetter(const BuiltinFunction *, Scope &scope, THROW_TYPE_ERROR(); ScopedString prop(scope, callData->argument(0), ScopedString::Convert); - CHECK_EXCEPTION(); + if (scope.engine->hasException) + return QV4::Encode::undefined(); ScopedObject o(scope, callData->thisObject); if (!o) { @@ -583,17 +593,19 @@ void ObjectPrototype::method_defineSetter(const BuiltinFunction *, Scope &scope, RETURN_UNDEFINED(); } -void ObjectPrototype::method_get_proto(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_get_proto(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->thisObject.as<Object>()); if (!o) THROW_TYPE_ERROR(); - scope.result = o->prototype(); + return Encode(o->prototype()); } -void ObjectPrototype::method_set_proto(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue ObjectPrototype::method_set_proto(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); ScopedObject o(scope, callData->thisObject); if (!o || !callData->argc) THROW_TYPE_ERROR(); @@ -612,10 +624,8 @@ void ObjectPrototype::method_set_proto(const BuiltinFunction *, Scope &scope, Ca ok = o->setPrototype(p); } } - if (!ok) { - scope.result = scope.engine->throwTypeError(QStringLiteral("Cyclic __proto__ value")); - return; - } + if (!ok) + return scope.engine->throwTypeError(QStringLiteral("Cyclic __proto__ value")); RETURN_UNDEFINED(); } diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h index d1383df192..c3c63de8ce 100644 --- a/src/qml/jsruntime/qv4objectproto_p.h +++ b/src/qml/jsruntime/qv4objectproto_p.h @@ -78,33 +78,33 @@ struct ObjectPrototype: Object { void init(ExecutionEngine *engine, Object *ctor); - static void method_getPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getOwnPropertyDescriptor(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_getOwnPropertyNames(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_assign(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_create(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_defineProperty(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_defineProperties(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_seal(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_freeze(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_preventExtensions(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isSealed(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isFrozen(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isExtensible(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_keys(const BuiltinFunction *, Scope &scope, CallData *callData); - - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_hasOwnProperty(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_isPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_propertyIsEnumerable(const BuiltinFunction *, Scope &scope, CallData *callData); - - static void method_defineGetter(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_defineSetter(const BuiltinFunction *, Scope &scope, CallData *callData); - - static void method_get_proto(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_set_proto(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_getPrototypeOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getOwnPropertyDescriptor(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_getOwnPropertyNames(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_assign(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_create(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_defineProperty(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_defineProperties(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_seal(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_freeze(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_preventExtensions(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isSealed(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isFrozen(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isExtensible(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_keys(const BuiltinFunction *, CallData *callData); + + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLocaleString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_valueOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_hasOwnProperty(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_isPrototypeOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_propertyIsEnumerable(const BuiltinFunction *, CallData *callData); + + static ReturnedValue method_defineGetter(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_defineSetter(const BuiltinFunction *, CallData *callData); + + static ReturnedValue method_get_proto(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_set_proto(const BuiltinFunction *, CallData *callData); static void toPropertyDescriptor(ExecutionEngine *engine, const Value &v, Property *desc, PropertyAttributes *attrs); static ReturnedValue fromPropertyDescriptor(ExecutionEngine *engine, const Property *desc, PropertyAttributes attrs); diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index b710fd8444..d7f10ece97 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -899,8 +899,10 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase } // namespace QV4 -void QObjectWrapper::method_connect(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue QObjectWrapper::method_connect(const BuiltinFunction *b, CallData *callData) { + QV4::Scope scope(b); + if (callData->argc == 0) THROW_GENERIC_ERROR("Function.prototype.connect: no arguments given"); @@ -949,8 +951,10 @@ void QObjectWrapper::method_connect(const BuiltinFunction *, Scope &scope, CallD RETURN_UNDEFINED(); } -void QObjectWrapper::method_disconnect(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue QObjectWrapper::method_disconnect(const BuiltinFunction *b, CallData *callData) { + QV4::Scope scope(b); + if (callData->argc == 0) THROW_GENERIC_ERROR("Function.prototype.disconnect: no arguments given"); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 9188bba990..3999b641f9 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -198,8 +198,8 @@ protected: static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); static void markObjects(Heap::Base *that, QV4::MarkStack *markStack); - static void method_connect(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_disconnect(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_connect(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_disconnect(const BuiltinFunction *, CallData *callData); private: Q_NEVER_INLINE static ReturnedValue wrap_slowPath(ExecutionEngine *engine, QObject *object); diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 4df9d47e7d..8a23da24cc 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -313,11 +313,12 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor) defineDefaultProperty(QStringLiteral("compile"), method_compile, 2); } -void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue RegExpPrototype::method_exec(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>()); if (!r) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); ScopedValue arg(scope, callData->argument(0)); ScopedString str(scope, arg->toString(scope.engine)); @@ -366,35 +367,36 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat if (r->global()) r->setLastIndex(matchOffsets[1]); - scope.result = array; + return array.asReturnedValue(); } -void RegExpPrototype::method_test(const BuiltinFunction *b, Scope &scope, CallData *callData) +ReturnedValue RegExpPrototype::method_test(const BuiltinFunction *b, CallData *callData) { - method_exec(b, scope, callData); - scope.result = Encode(!scope.result.isNull()); + Value res = Value::fromReturnedValue(method_exec(b, callData)); + return Encode(!res.isNull()); } -void RegExpPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue RegExpPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { - Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>()); + ExecutionEngine *v4 = b->engine(); + RegExpObject *r = callData->thisObject.as<RegExpObject>(); if (!r) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); - scope.result = scope.engine->newString(r->toString()); + return Encode(v4->newString(r->toString())); } -void RegExpPrototype::method_compile(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue RegExpPrototype::method_compile(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>()); if (!r) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); ScopedCallData cData(scope, callData->argc); memcpy(cData->args, callData->args, callData->argc*sizeof(Value)); - scope.result = scope.engine->regExpCtor()->as<FunctionObject>()->construct(cData); - Scoped<RegExpObject> re(scope, scope.result.asReturnedValue()); + Scoped<RegExpObject> re(scope, scope.engine->regExpCtor()->as<FunctionObject>()->construct(cData)); r->d()->value.set(scope.engine, re->value()); r->d()->global = re->global(); @@ -402,39 +404,45 @@ void RegExpPrototype::method_compile(const BuiltinFunction *, Scope &scope, Call } template <int index> -void RegExpPrototype::method_get_lastMatch_n(const BuiltinFunction *, Scope &scope, CallData *) +ReturnedValue RegExpPrototype::method_get_lastMatch_n(const BuiltinFunction *b, CallData *) { + Scope scope(b); ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch()); - scope.result = lastMatch ? lastMatch->getIndexed(index) : Encode::undefined(); - if (scope.result.isUndefined()) - scope.result = scope.engine->newString(); + ScopedValue res(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined()); + if (res->isUndefined()) + res = scope.engine->newString(); + return res->asReturnedValue(); } -void RegExpPrototype::method_get_lastParen(const BuiltinFunction *, Scope &scope, CallData *) +ReturnedValue RegExpPrototype::method_get_lastParen(const BuiltinFunction *b, CallData *) { + Scope scope(b); ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch()); - scope.result = lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined(); - if (scope.result.isUndefined()) - scope.result = scope.engine->newString(); + ScopedValue res(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined()); + if (res->isUndefined()) + res = scope.engine->newString(); + return res->asReturnedValue(); } -void RegExpPrototype::method_get_input(const BuiltinFunction *, Scope &scope, CallData *) +ReturnedValue RegExpPrototype::method_get_input(const BuiltinFunction *b, CallData *) { - scope.result = static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastInput(); + return static_cast<RegExpCtor*>(b->engine()->regExpCtor())->lastInput()->asReturnedValue(); } -void RegExpPrototype::method_get_leftContext(const BuiltinFunction *, Scope &scope, CallData *) +ReturnedValue RegExpPrototype::method_get_leftContext(const BuiltinFunction *b, CallData *) { + Scope scope(b); Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor()); QString lastInput = regExpCtor->lastInput()->toQString(); - scope.result = scope.engine->newString(lastInput.left(regExpCtor->lastMatchStart())); + return Encode(scope.engine->newString(lastInput.left(regExpCtor->lastMatchStart()))); } -void RegExpPrototype::method_get_rightContext(const BuiltinFunction *, Scope &scope, CallData *) +ReturnedValue RegExpPrototype::method_get_rightContext(const BuiltinFunction *b, CallData *) { + Scope scope(b); Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor()); QString lastInput = regExpCtor->lastInput()->toQString(); - scope.result = scope.engine->newString(lastInput.mid(regExpCtor->lastMatchEnd())); + return Encode(scope.engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index ea16591445..f04940255b 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -158,17 +158,17 @@ struct RegExpPrototype: RegExpObject { void init(ExecutionEngine *engine, Object *ctor); - static void method_exec(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_test(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_compile(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_exec(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_test(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_compile(const BuiltinFunction *, CallData *callData); template <int index> - static void method_get_lastMatch_n(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_lastParen(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_input(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_leftContext(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_rightContext(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_get_lastMatch_n(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_lastParen(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_input(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_leftContext(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_rightContext(const BuiltinFunction *, CallData *callData); }; } diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 04a0c74133..7df723e9d0 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -71,50 +71,39 @@ struct ScopedValue; #define CHECK_EXCEPTION() \ do { \ if (scope.hasException()) { \ - scope.result = QV4::Encode::undefined(); \ - return; \ + return QV4::Encode::undefined(); \ } \ } while (false) #define RETURN_UNDEFINED() \ - do { \ - scope.result = QV4::Encode::undefined(); \ - return; \ - } while (false) + return QV4::Encode::undefined() #define RETURN_RESULT(r) \ - do { \ - scope.result = r; \ - return; \ - } while (false) + return QV4::Encode(r) #define THROW_TYPE_ERROR() \ - do { \ - scope.result = scope.engine->throwTypeError(); \ - return; \ - } while (false) + return scope.engine->throwTypeError() #define THROW_GENERIC_ERROR(str) \ - do { \ - scope.result = scope.engine->throwError(QString::fromUtf8(str)); \ - return; \ - } while (false) + return scope.engine->throwError(QString::fromUtf8(str)) struct Scope { inline Scope(ExecutionContext *ctx) : engine(ctx->engine()) , mark(engine->jsStackTop) - , result(*engine->jsAlloca(1)) { - result = Encode::undefined(); } explicit Scope(ExecutionEngine *e) : engine(e) , mark(engine->jsStackTop) - , result(*engine->jsAlloca(1)) { - result = Encode::undefined(); + } + + inline Scope(const Managed *m) + : engine(m->engine()) + , mark(engine->jsStackTop) + { } ~Scope() { @@ -139,7 +128,6 @@ struct Scope { ExecutionEngine *engine; Value *mark; - Value &result; private: Q_DISABLE_COPY(Scope) diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 7868b1a7d2..019fa54fb0 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -159,10 +159,9 @@ ReturnedValue Script::run() ScopedCallData callData(valueScope); callData->thisObject = Primitive::undefinedValue(); if (vmFunction->canUseSimpleFunction()) - qml->simpleCall(valueScope, callData, vmFunction); + return qml->simpleCall(valueScope, callData, vmFunction); else - qml->call(valueScope, callData, vmFunction); - return valueScope.result.asReturnedValue(); + return qml->call(valueScope, callData, vmFunction); } } diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index ec3ff0ea1d..08c64aaa27 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -450,8 +450,9 @@ public: storeReference(); } - static void method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData) + static QV4::ReturnedValue method_get_length(const BuiltinFunction *b, CallData *callData) { + QV4::Scope scope(b); QV4::Scoped<QQmlSequence<Container> > This(scope, callData->thisObject.as<QQmlSequence<Container> >()); if (!This) THROW_TYPE_ERROR(); @@ -464,8 +465,9 @@ public: RETURN_RESULT(Encode(qint32(This->d()->container->size()))); } - static void method_set_length(const BuiltinFunction *, Scope &scope, CallData *callData) + static QV4::ReturnedValue method_set_length(const BuiltinFunction *b, CallData *callData) { + QV4::Scope scope(b); QV4::Scoped<QQmlSequence<Container> > This(scope, callData->thisObject.as<QQmlSequence<Container> >()); if (!This) THROW_TYPE_ERROR(); @@ -647,14 +649,20 @@ void SequencePrototype::init() } #undef REGISTER_QML_SEQUENCE_METATYPE -void SequencePrototype::method_sort(const BuiltinFunction *b, Scope &scope, CallData *callData) +ReturnedValue SequencePrototype::method_valueOf(const BuiltinFunction *f, CallData *callData) { + return Encode(callData->thisObject.toString(f->engine())); +} + +ReturnedValue SequencePrototype::method_sort(const BuiltinFunction *b, CallData *callData) +{ + Scope scope(b); QV4::ScopedObject o(scope, callData->thisObject); if (!o || !o->isListType()) THROW_TYPE_ERROR(); if (callData->argc >= 2) - RETURN_RESULT(o); + return o.asReturnedValue(); #define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \ if (QQml##SequenceElementTypeName##List *s = o->as<QQml##SequenceElementTypeName##List>()) { \ @@ -665,7 +673,7 @@ void SequencePrototype::method_sort(const BuiltinFunction *b, Scope &scope, Call #undef CALL_SORT {} - RETURN_RESULT(o); + return o.asReturnedValue(); } #define IS_SEQUENCE(unused1, unused2, SequenceType, unused3) \ diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h index 2b8d1ea716..169a48c2f9 100644 --- a/src/qml/jsruntime/qv4sequenceobject_p.h +++ b/src/qml/jsruntime/qv4sequenceobject_p.h @@ -68,12 +68,8 @@ struct SequencePrototype : public QV4::Object V4_PROTOTYPE(arrayPrototype) void init(); - static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) - { - scope.result = callData->thisObject.toString(scope.engine); - } - - static void method_sort(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_valueOf(const BuiltinFunction *f, CallData *callData); + static ReturnedValue method_sort(const BuiltinFunction *, CallData *callData); static bool isSequenceType(int sequenceTypeId); static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded); diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 16998c4728..d21dd4808f 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -207,35 +207,38 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("trim"), method_trim); } -static QString getThisString(Scope &scope, CallData *callData) +static QString getThisString(ExecutionEngine *v4, CallData *callData) { - ScopedValue t(scope, callData->thisObject); + Value *t = &callData->thisObject; if (String *s = t->stringValue()) return s->toQString(); if (StringObject *thisString = t->as<StringObject>()) return thisString->d()->string->toQString(); if (t->isUndefined() || t->isNull()) { - scope.engine->throwTypeError(); + v4->throwTypeError(); return QString(); } return t->toQString(); } -void StringPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { if (callData->thisObject.isString()) RETURN_RESULT(callData->thisObject); + ExecutionEngine *v4 = b->engine(); StringObject *o = callData->thisObject.as<StringObject>(); if (!o) - THROW_TYPE_ERROR(); - scope.result = o->d()->string; + return v4->throwTypeError(); + return o->d()->string->asReturnedValue(); } -void StringPrototype::method_charAt(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_charAt(const BuiltinFunction *b, CallData *callData) { - const QString str = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString str = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); int pos = 0; if (callData->argc > 0) @@ -245,13 +248,15 @@ void StringPrototype::method_charAt(const BuiltinFunction *, Scope &scope, CallD if (pos >= 0 && pos < str.length()) result += str.at(pos); - scope.result = scope.engine->newString(result); + return Encode(v4->newString(result)); } -void StringPrototype::method_charCodeAt(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_charCodeAt(const BuiltinFunction *b, CallData *callData) { - const QString str = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString str = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); int pos = 0; if (callData->argc > 0) @@ -261,35 +266,41 @@ void StringPrototype::method_charCodeAt(const BuiltinFunction *, Scope &scope, C if (pos >= 0 && pos < str.length()) RETURN_RESULT(Encode(str.at(pos).unicode())); - scope.result = Encode(qt_qnan()); + return Encode(qt_qnan()); } -void StringPrototype::method_concat(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_concat(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); + Scope scope(v4); ScopedString s(scope); for (int i = 0; i < callData->argc; ++i) { s = callData->args[i].toString(scope.engine); - CHECK_EXCEPTION(); + if (v4->hasException) + return QV4::Encode::undefined(); Q_ASSERT(s->isString()); value += s->toQString(); } - scope.result = scope.engine->newString(value); + return Encode(v4->newString(value)); } -void StringPrototype::method_endsWith(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_endsWith(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); QString searchString; if (callData->argc) { if (callData->args[0].as<RegExpObject>()) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); searchString = callData->args[0].toQString(); } @@ -301,13 +312,15 @@ void StringPrototype::method_endsWith(const BuiltinFunction *, Scope &scope, Cal RETURN_RESULT(Encode(value.endsWith(searchString))); QStringRef stringToSearch = value.leftRef(pos); - scope.result = Encode(stringToSearch.endsWith(searchString)); + return Encode(stringToSearch.endsWith(searchString)); } -void StringPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_indexOf(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); QString searchString; if (callData->argc) @@ -321,26 +334,28 @@ void StringPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, Call if (! value.isEmpty()) index = value.indexOf(searchString, qMin(qMax(pos, 0), value.length())); - scope.result = Encode(index); + return Encode(index); } -void StringPrototype::method_includes(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_includes(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); QString searchString; if (callData->argc) { if (callData->args[0].as<RegExpObject>()) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); searchString = callData->args[0].toQString(); } int pos = 0; if (callData->argc > 1) { - ScopedValue posArg(scope, callData->argument(1)); - pos = (int) posArg->toInteger(); - if (!posArg->isInteger() && posArg->isNumber() && qIsInf(posArg->toNumber())) + Value &posArg = callData->args[1]; + pos = (int) posArg.toInteger(); + if (!posArg.isInteger() && posArg.isNumber() && qIsInf(posArg.toNumber())) pos = value.length(); } @@ -348,20 +363,21 @@ void StringPrototype::method_includes(const BuiltinFunction *, Scope &scope, Cal RETURN_RESULT(Encode(value.contains(searchString))); QStringRef stringToSearch = value.midRef(pos); - scope.result = Encode(stringToSearch.contains(searchString)); + return Encode(stringToSearch.contains(searchString)); } -void StringPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_lastIndexOf(const BuiltinFunction *b, CallData *callData) { - const QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); QString searchString; if (callData->argc) searchString = callData->args[0].toQString(); - ScopedValue posArg(scope, callData->argument(1)); - double position = RuntimeHelpers::toNumber(posArg); + double position = callData->argc > 1 ? RuntimeHelpers::toNumber(callData->args[1]) : +qInf(); if (std::isnan(position)) position = +qInf(); else @@ -373,24 +389,30 @@ void StringPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, if (searchString.isNull() && pos == 0) RETURN_RESULT(Encode(-1)); int index = value.lastIndexOf(searchString, pos); - scope.result = Encode(index); + return Encode(index); } -void StringPrototype::method_localeCompare(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_localeCompare(const BuiltinFunction *b, CallData *callData) { - const QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); + + if (callData->argc < 1) + callData->args[0] = Encode::undefined(); - ScopedValue v(scope, callData->argument(0)); - const QString that = v->toQString(); - scope.result = Encode(QString::localeAwareCompare(value, that)); + const QString that = callData->args[0].toQString(); + return Encode(QString::localeAwareCompare(value, that)); } -void StringPrototype::method_match(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_match(const BuiltinFunction *b, CallData *callData) { + ExecutionEngine *v4 = b->engine(); if (callData->thisObject.isUndefined() || callData->thisObject.isNull()) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); + Scope scope(v4); ScopedString s(scope, callData->thisObject.toString(scope.engine)); ScopedValue regexp(scope, callData->argument(0)); @@ -403,7 +425,7 @@ void StringPrototype::method_match(const BuiltinFunction *, Scope &scope, CallDa if (!rx) // ### CHECK - THROW_TYPE_ERROR(); + return v4->throwTypeError(); bool global = rx->global(); @@ -414,10 +436,8 @@ void StringPrototype::method_match(const BuiltinFunction *, Scope &scope, CallDa ScopedCallData cData(scope, 1); cData->thisObject = rx; cData->args[0] = s; - if (!global) { - scope.result = exec->call(cData); - return; - } + if (!global) + return exec->call(cData); ScopedString lastIndex(scope, scope.engine->newString(QStringLiteral("lastIndex"))); rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0))); @@ -427,11 +447,12 @@ void StringPrototype::method_match(const BuiltinFunction *, Scope &scope, CallDa uint n = 0; ScopedValue matchStr(scope); ScopedValue index(scope); + ScopedValue result(scope); while (1) { - scope.result = exec->call(cData); - if (scope.result.isNull()) + result = exec->call(cData); + if (result->isNull()) break; - assert(scope.result.isObject()); + assert(result->isObject()); index = rx->get(lastIndex, 0); double thisIndex = index->toInteger(); if (previousLastIndex == thisIndex) { @@ -440,29 +461,30 @@ void StringPrototype::method_match(const BuiltinFunction *, Scope &scope, CallDa } else { previousLastIndex = thisIndex; } - matchStr = scope.result.objectValue()->getIndexed(0); + matchStr = result->objectValue()->getIndexed(0); a->arraySet(n, matchStr); ++n; } if (!n) - scope.result = Encode::null(); + result = Encode::null(); else - scope.result = a; + result = a.asReturnedValue(); + return result->asReturnedValue(); } -void StringPrototype::method_repeat(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_repeat(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); double repeats = callData->args[0].toInteger(); - if (repeats < 0 || qIsInf(repeats)) { - scope.result = scope.engine->throwRangeError(QLatin1String("Invalid count value")); - return; - } + if (repeats < 0 || qIsInf(repeats)) + return v4->throwRangeError(QLatin1String("Invalid count value")); - scope.result = scope.engine->newString(value.repeated(int(repeats))); + return Encode(v4->newString(value.repeated(int(repeats)))); } static void appendReplacementString(QString *result, const QString &input, const QString& replaceValue, uint* matchOffsets, int captureCount) @@ -511,7 +533,7 @@ static void appendReplacementString(QString *result, const QString &input, const } } -void StringPrototype::method_replace(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_replace(const BuiltinFunction *b, CallData *callData) { QString string; if (StringObject *thisString = callData->thisObject.as<StringObject>()) @@ -526,6 +548,7 @@ void StringPrototype::method_replace(const BuiltinFunction *, Scope &scope, Call uint _matchOffsets[64]; uint *matchOffsets = _matchOffsets; + Scope scope(b); ScopedValue searchValue(scope, callData->argument(0)); Scoped<RegExpObject> regExp(scope, searchValue); if (regExp) { @@ -622,38 +645,44 @@ void StringPrototype::method_replace(const BuiltinFunction *, Scope &scope, Call if (matchOffsets != _matchOffsets) free(matchOffsets); - scope.result = scope.engine->newString(result); + return Encode(scope.engine->newString(result)); } -void StringPrototype::method_search(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_search(const BuiltinFunction *b, CallData *callData) { - QString string = getThisString(scope, callData); - scope.result = callData->argument(0); - CHECK_EXCEPTION(); + Scope scope(b); + ScopedValue regExpObj(scope); + QString string = getThisString(scope.engine, callData); + regExpObj = callData->argument(0); + if (scope.engine->hasException) + return QV4::Encode::undefined(); - Scoped<RegExpObject> regExp(scope, scope.result.as<RegExpObject>()); + RegExpObject *regExp = regExpObj->as<RegExpObject>(); if (!regExp) { ScopedCallData callData(scope, 1); - callData->args[0] = scope.result; - scope.result = scope.engine->regExpCtor()->construct(callData); - CHECK_EXCEPTION(); + callData->args[0] = regExpObj; + regExpObj = scope.engine->regExpCtor()->construct(callData); + if (scope.engine->hasException) + return QV4::Encode::undefined(); - regExp = scope.result.as<RegExpObject>(); + regExp = regExpObj->as<RegExpObject>(); Q_ASSERT(regExp); } Scoped<RegExp> re(scope, regExp->value()); Q_ALLOCA_VAR(uint, matchOffsets, regExp->value()->captureCount() * 2 * sizeof(uint)); uint result = re->match(string, /*offset*/0, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) - scope.result = Encode(-1); + return Encode(-1); else - scope.result = Encode(result); + return Encode(result); } -void StringPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_slice(const BuiltinFunction *b, CallData *callData) { - const QString text = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString text = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); const double length = text.length(); @@ -675,14 +704,17 @@ void StringPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallDa const int intEnd = int(end); int count = qMax(0, intEnd - intStart); - scope.result = scope.engine->newString(text.mid(intStart, count)); + return Encode(v4->newString(text.mid(intStart, count))); } -void StringPrototype::method_split(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_split(const BuiltinFunction *b, CallData *callData) { - QString text = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + QString text = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); + Scope scope(v4); ScopedValue separatorValue(scope, callData->argument(0)); ScopedValue limitValue(scope, callData->argument(1)); @@ -692,7 +724,7 @@ void StringPrototype::method_split(const BuiltinFunction *, Scope &scope, CallDa if (limitValue->isUndefined()) { ScopedString s(scope, scope.engine->newString(text)); array->push_back(s); - RETURN_RESULT(array); + return array.asReturnedValue(); } RETURN_RESULT(scope.engine->newString(text.left(limitValue->toInteger()))); } @@ -700,7 +732,7 @@ void StringPrototype::method_split(const BuiltinFunction *, Scope &scope, CallDa uint limit = limitValue->isUndefined() ? UINT_MAX : limitValue->toUInt32(); if (limit == 0) - RETURN_RESULT(array); + return array.asReturnedValue(); Scoped<RegExpObject> re(scope, separatorValue); if (re) { @@ -741,7 +773,7 @@ void StringPrototype::method_split(const BuiltinFunction *, Scope &scope, CallDa if (separator.isEmpty()) { for (uint i = 0; i < qMin(limit, uint(text.length())); ++i) array->push_back((s = scope.engine->newString(text.mid(i, 1)))); - RETURN_RESULT(array); + return array.asReturnedValue(); } int start = 0; @@ -755,18 +787,20 @@ void StringPrototype::method_split(const BuiltinFunction *, Scope &scope, CallDa if (array->getLength() < limit && start != -1) array->push_back((s = scope.engine->newString(text.mid(start)))); } - RETURN_RESULT(array); + return array.asReturnedValue(); } -void StringPrototype::method_startsWith(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_startsWith(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); QString searchString; if (callData->argc) { if (callData->args[0].as<RegExpObject>()) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); searchString = callData->args[0].toQString(); } @@ -775,16 +809,18 @@ void StringPrototype::method_startsWith(const BuiltinFunction *, Scope &scope, C pos = (int) callData->args[1].toInteger(); if (pos == 0) - RETURN_RESULT(Encode(value.startsWith(searchString))); + return Encode(value.startsWith(searchString)); QStringRef stringToSearch = value.midRef(pos); RETURN_RESULT(Encode(stringToSearch.startsWith(searchString))); } -void StringPrototype::method_substr(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_substr(const BuiltinFunction *b, CallData *callData) { - const QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); double start = 0; if (callData->argc > 0) @@ -802,13 +838,15 @@ void StringPrototype::method_substr(const BuiltinFunction *, Scope &scope, CallD qint32 x = Primitive::toInt32(start); qint32 y = Primitive::toInt32(length); - scope.result = scope.engine->newString(value.mid(x, y)); + return Encode(v4->newString(value.mid(x, y))); } -void StringPrototype::method_substring(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_substring(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); int length = value.length(); @@ -818,9 +856,8 @@ void StringPrototype::method_substring(const BuiltinFunction *, Scope &scope, Ca if (callData->argc > 0) start = callData->args[0].toInteger(); - ScopedValue endValue(scope, callData->argument(1)); - if (!endValue->isUndefined()) - end = endValue->toInteger(); + if (callData->argc > 1 && !callData->args[1].isUndefined()) + end = callData->args[1].toInteger(); if (std::isnan(start) || start < 0) start = 0; @@ -842,36 +879,40 @@ void StringPrototype::method_substring(const BuiltinFunction *, Scope &scope, Ca qint32 x = (int)start; qint32 y = (int)(end - start); - scope.result = scope.engine->newString(value.mid(x, y)); + return Encode(v4->newString(value.mid(x, y))); } -void StringPrototype::method_toLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_toLowerCase(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); - scope.result = scope.engine->newString(value.toLower()); + return Encode(v4->newString(value.toLower())); } -void StringPrototype::method_toLocaleLowerCase(const BuiltinFunction *b, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_toLocaleLowerCase(const BuiltinFunction *b, CallData *callData) { - method_toLowerCase(b, scope, callData); + return method_toLowerCase(b, callData); } -void StringPrototype::method_toUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_toUpperCase(const BuiltinFunction *b, CallData *callData) { - QString value = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + const QString value = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); - scope.result = scope.engine->newString(value.toUpper()); + return Encode(v4->newString(value.toUpper())); } -void StringPrototype::method_toLocaleUpperCase(const BuiltinFunction *b, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_toLocaleUpperCase(const BuiltinFunction *b, CallData *callData) { - return method_toUpperCase(b, scope, callData); + return method_toUpperCase(b, callData); } -void StringPrototype::method_fromCharCode(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_fromCharCode(const BuiltinFunction *b, CallData *callData) { QString str(callData->argc, Qt::Uninitialized); QChar *ch = str.data(); @@ -879,13 +920,15 @@ void StringPrototype::method_fromCharCode(const BuiltinFunction *, Scope &scope, *ch = QChar(callData->args[i].toUInt16()); ++ch; } - scope.result = scope.engine->newString(str); + return Encode(b->engine()->newString(str)); } -void StringPrototype::method_trim(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue StringPrototype::method_trim(const BuiltinFunction *b, CallData *callData) { - QString s = getThisString(scope, callData); - CHECK_EXCEPTION(); + ExecutionEngine *v4 = b->engine(); + QString s = getThisString(v4, callData); + if (v4->hasException) + return QV4::Encode::undefined(); const QChar *chars = s.constData(); int start, end; @@ -898,5 +941,5 @@ void StringPrototype::method_trim(const BuiltinFunction *, Scope &scope, CallDat break; } - scope.result = scope.engine->newString(QString(chars + start, end - start + 1)); + return Encode(v4->newString(QString(chars + start, end - start + 1))); } diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index f1c0c2904e..af5a5bead5 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -115,30 +115,30 @@ struct StringPrototype: StringObject V4_PROTOTYPE(objectPrototype) void init(ExecutionEngine *engine, Object *ctor); - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_charAt(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_charCodeAt(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_concat(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_endsWith(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_includes(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_localeCompare(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_match(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_repeat(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_replace(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_search(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_slice(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_split(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_startsWith(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_substr(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_substring(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toLocaleLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toLocaleUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_fromCharCode(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_trim(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_charAt(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_charCodeAt(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_concat(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_endsWith(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_indexOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_includes(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_lastIndexOf(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_localeCompare(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_match(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_repeat(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_replace(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_search(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_slice(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_split(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_startsWith(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_substr(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_substring(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLowerCase(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLocaleLowerCase(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toUpperCase(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toLocaleUpperCase(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_fromCharCode(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_trim(const BuiltinFunction *, CallData *callData); }; } diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 1944e0b87e..12b01bd578 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -413,47 +413,52 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor) defineDefaultProperty(QStringLiteral("subarray"), method_subarray, 0); } -void TypedArrayPrototype::method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue TypedArrayPrototype::method_get_buffer(const BuiltinFunction *b, CallData *callData) { - Scoped<TypedArray> v(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + TypedArray *v = callData->thisObject.as<TypedArray>(); if (!v) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); - scope.result = v->d()->buffer; + return v->d()->buffer->asReturnedValue(); } -void TypedArrayPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue TypedArrayPrototype::method_get_byteLength(const BuiltinFunction *b, CallData *callData) { - Scoped<TypedArray> v(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + TypedArray *v = callData->thisObject.as<TypedArray>(); if (!v) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); - scope.result = Encode(v->d()->byteLength); + return Encode(v->d()->byteLength); } -void TypedArrayPrototype::method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue TypedArrayPrototype::method_get_byteOffset(const BuiltinFunction *b, CallData *callData) { - Scoped<TypedArray> v(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + TypedArray *v = callData->thisObject.as<TypedArray>(); if (!v) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); - scope.result = Encode(v->d()->byteOffset); + return Encode(v->d()->byteOffset); } -void TypedArrayPrototype::method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue TypedArrayPrototype::method_get_length(const BuiltinFunction *b, CallData *callData) { - Scoped<TypedArray> v(scope, callData->thisObject); + ExecutionEngine *v4 = b->engine(); + TypedArray *v = callData->thisObject.as<TypedArray>(); if (!v) - THROW_TYPE_ERROR(); + return v4->throwTypeError(); - scope.result = Encode(v->d()->byteLength/v->d()->type->bytesPerElement); + return Encode(v->d()->byteLength/v->d()->type->bytesPerElement); } -void TypedArrayPrototype::method_set(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue TypedArrayPrototype::method_set(const BuiltinFunction *b, CallData *callData) { + Scope scope(b); Scoped<TypedArray> a(scope, callData->thisObject); if (!a) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); Scoped<ArrayBuffer> buffer(scope, a->d()->buffer); if (!buffer) scope.engine->throwTypeError(); @@ -472,12 +477,12 @@ void TypedArrayPrototype::method_set(const BuiltinFunction *, Scope &scope, Call // src is a regular object ScopedObject o(scope, callData->args[0].toObject(scope.engine)); if (scope.engine->hasException || !o) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); double len = ScopedValue(scope, o->get(scope.engine->id_length()))->toNumber(); uint l = (uint)len; if (scope.engine->hasException || l != len) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); if (offset + l > a->length()) RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"))); @@ -499,7 +504,7 @@ void TypedArrayPrototype::method_set(const BuiltinFunction *, Scope &scope, Call // src is a typed array Scoped<ArrayBuffer> srcBuffer(scope, srcTypedArray->d()->buffer); if (!srcBuffer) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); uint l = srcTypedArray->length(); if (offset + l > a->length()) @@ -537,16 +542,17 @@ void TypedArrayPrototype::method_set(const BuiltinFunction *, Scope &scope, Call RETURN_UNDEFINED(); } -void TypedArrayPrototype::method_subarray(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue TypedArrayPrototype::method_subarray(const BuiltinFunction *builtin, CallData *callData) { + Scope scope(builtin); Scoped<TypedArray> a(scope, callData->thisObject); if (!a) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); Scoped<ArrayBuffer> buffer(scope, a->d()->buffer); if (!buffer) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); int len = a->length(); double b = callData->argc > 0 ? callData->args[0].toInteger() : 0; @@ -568,11 +574,11 @@ void TypedArrayPrototype::method_subarray(const BuiltinFunction *, Scope &scope, ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor())); if (!constructor) - THROW_TYPE_ERROR(); + return scope.engine->throwTypeError(); ScopedCallData cData(scope, 3); cData->args[0] = buffer; cData->args[1] = Encode(a->d()->byteOffset + begin*a->d()->type->bytesPerElement); cData->args[2] = Encode(newLen); - scope.result = constructor->construct(cData); + return constructor->construct(cData); } diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h index fad7901428..fc7aa78cda 100644 --- a/src/qml/jsruntime/qv4typedarray_p.h +++ b/src/qml/jsruntime/qv4typedarray_p.h @@ -153,13 +153,13 @@ struct TypedArrayPrototype : Object void init(ExecutionEngine *engine, TypedArrayCtor *ctor); - static void method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_get_buffer(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_byteLength(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_byteOffset(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_get_length(const BuiltinFunction *, CallData *callData); - static void method_set(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_subarray(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_set(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_subarray(const BuiltinFunction *, CallData *callData); }; inline void diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index e34ee0ccbe..b6f2e837ba 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -667,30 +667,35 @@ struct Encode { return Primitive::nullValue().rawValue(); } - Encode(bool b) { + explicit Encode(bool b) { val = Primitive::fromBoolean(b).rawValue(); } - Encode(double d) { + explicit Encode(double d) { val = Primitive::fromDouble(d).rawValue(); } - Encode(int i) { + explicit Encode(int i) { val = Primitive::fromInt32(i).rawValue(); } - Encode(uint i) { + explicit Encode(uint i) { val = Primitive::fromUInt32(i).rawValue(); } - Encode(ReturnedValue v) { + explicit Encode(ReturnedValue v) { val = v; } Encode(Value v) { val = v.rawValue(); } - Encode(Heap::Base *o) { + explicit Encode(Heap::Base *o) { Q_ASSERT(o); val = Value::fromHeapObject(o).asReturnedValue(); } + explicit Encode(Value *o) { + Q_ASSERT(o); + val = o->asReturnedValue(); + } + static ReturnedValue smallestNumber(double d) { if (static_cast<int>(d) == d && !(d == 0. && std::signbit(d))) return Encode(static_cast<int>(d)); @@ -703,7 +708,7 @@ struct Encode { } quint64 val; private: - Encode(void *); + explicit Encode(void *); }; template<typename T> diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index f2ff5d307e..00be90b3c2 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -113,17 +113,17 @@ void VariantPrototype::init() defineDefaultProperty(engine()->id_toString(), method_toString, 0); } -void VariantPrototype::method_preserve(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue VariantPrototype::method_preserve(const BuiltinFunction *, CallData *callData) { - Scoped<VariantObject> o(scope, callData->thisObject.as<QV4::VariantObject>()); + VariantObject *o = callData->thisObject.as<QV4::VariantObject>(); if (o && o->d()->isScarce()) o->d()->addVmePropertyReference(); RETURN_UNDEFINED(); } -void VariantPrototype::method_destroy(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue VariantPrototype::method_destroy(const BuiltinFunction *, CallData *callData) { - Scoped<VariantObject> o(scope, callData->thisObject.as<QV4::VariantObject>()); + VariantObject *o = callData->thisObject.as<QV4::VariantObject>(); if (o) { if (o->d()->isScarce()) o->d()->addVmePropertyReference(); @@ -132,9 +132,10 @@ void VariantPrototype::method_destroy(const BuiltinFunction *, Scope &scope, Cal RETURN_UNDEFINED(); } -void VariantPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue VariantPrototype::method_toString(const BuiltinFunction *b, CallData *callData) { - Scoped<VariantObject> o(scope, callData->thisObject.as<QV4::VariantObject>()); + ExecutionEngine *v4 = b->engine(); + VariantObject *o = callData->thisObject.as<QV4::VariantObject>(); if (!o) RETURN_UNDEFINED(); QString result = o->d()->data().toString(); @@ -143,38 +144,33 @@ void VariantPrototype::method_toString(const BuiltinFunction *, Scope &scope, Ca + QLatin1String(o->d()->data().typeName()) + QLatin1Char(')'); } - scope.result = scope.engine->newString(result); + return Encode(v4->newString(result)); } -void VariantPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) +ReturnedValue VariantPrototype::method_valueOf(const BuiltinFunction *b, CallData *callData) { - Scoped<VariantObject> o(scope, callData->thisObject.as<QV4::VariantObject>()); + VariantObject *o = callData->thisObject.as<QV4::VariantObject>(); if (o) { QVariant v = o->d()->data(); switch (v.type()) { case QVariant::Invalid: - scope.result = Encode::undefined(); - return; + return Encode::undefined(); case QVariant::String: - scope.result = scope.engine->newString(v.toString()); - return; + return Encode(b->engine()->newString(v.toString())); case QVariant::Int: - scope.result = Encode(v.toInt()); - return; + return Encode(v.toInt()); case QVariant::Double: case QVariant::UInt: - scope.result = Encode(v.toDouble()); - return; + return Encode(v.toDouble()); case QVariant::Bool: - scope.result = Encode(v.toBool()); - return; + return Encode(v.toBool()); default: if (QMetaType::typeFlags(v.userType()) & QMetaType::IsEnumeration) RETURN_RESULT(Encode(v.toInt())); break; } } - scope.result = callData->thisObject; + return callData->thisObject.asReturnedValue(); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index a7c6fa320c..07b3310e91 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -108,10 +108,10 @@ public: V4_PROTOTYPE(objectPrototype) void init(); - static void method_preserve(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_destroy(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); - static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static ReturnedValue method_preserve(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_destroy(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData); + static ReturnedValue method_valueOf(const BuiltinFunction *, CallData *callData); }; } |