diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-09-01 11:48:15 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-09-02 07:12:17 +0000 |
commit | 74c8fe86755af485f8d0a47799d6d50f00070f05 (patch) | |
tree | 9e3d8c51d46d9f0fa2555cc77d184d6b3ee1be7d | |
parent | a91383545c6f487cff61f401d11f1e85939222e9 (diff) |
Always set the correct FunctionObject when calling JS functions
Renamed ScopedCallData to JSCall, enforced passing a JS
FunctionObject to it, and added call() and callAsConstructor()
methods to it.
Change-Id: I30db65c9765c2896b5909fe2105c0934c6dad861
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
31 files changed, 320 insertions, 315 deletions
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 5f3cfc43c4..795103cd26 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -414,12 +414,12 @@ static ReturnedValue qmlsqldatabase_changeVersion(const QV4::BuiltinFunction *b, ok = false; db.transaction(); - ScopedCallData callData(scope, 1); - callData->thisObject = scope.engine->globalObject; - callData->args[0] = w; + JSCall jsCall(scope, callback, 1); + jsCall->thisObject = scope.engine->globalObject; + jsCall->args[0] = w; TransactionRollback rollbackOnException(&db, &w->d()->inTransaction); - callback->call(callData); + jsCall.call(); rollbackOnException.clear(); if (!db.commit()) { db.rollback(); @@ -464,11 +464,11 @@ static ReturnedValue qmlsqldatabase_transaction_shared(const QV4::BuiltinFunctio db.transaction(); if (callback) { - ScopedCallData callData(scope, 1); - callData->thisObject = scope.engine->globalObject; - callData->args[0] = w; + JSCall jsCall(scope, callback, 1); + jsCall->thisObject = scope.engine->globalObject; + jsCall->args[0] = w; TransactionRollback rollbackOnException(&db, &w->d()->inTransaction); - callback->call(callData); + jsCall.call(); rollbackOnException.clear(); if (!db.commit()) @@ -763,10 +763,10 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) *db->d()->version = version; if (created && dbcreationCallback) { - ScopedCallData callData(scope, 1); - callData->thisObject = scope.engine->globalObject; - callData->args[0] = db; - dbcreationCallback->call(callData); + JSCall jsCall(scope, dbcreationCallback, 1); + jsCall->thisObject = scope.engine->globalObject; + jsCall->args[0] = db; + jsCall.call(); } args->setReturnValue(db.asReturnedValue()); diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index 3e2d0ccef0..afd2b1560f 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -657,17 +657,17 @@ QJSValue QJSValue::call(const QJSValueList &args) Q_ASSERT(engine); Scope scope(engine); - ScopedCallData callData(scope, f, args.length()); - callData->thisObject = engine->globalObject; + JSCall jsCall(scope, f, args.length()); + jsCall->thisObject = engine->globalObject; for (int i = 0; i < args.size(); ++i) { if (!QJSValuePrivate::checkEngine(engine, args.at(i))) { qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); return QJSValue(); } - callData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i)); + jsCall->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i)); } - ScopedValue result(scope, callData.call()); + ScopedValue result(scope, jsCall.call()); if (engine->hasException) result = engine->catchException(); @@ -713,17 +713,17 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList return QJSValue(); } - ScopedCallData callData(scope, args.size()); - callData->thisObject = QJSValuePrivate::convertedToValue(engine, instance); + JSCall jsCall(scope, f, args.size()); + jsCall->thisObject = QJSValuePrivate::convertedToValue(engine, instance); for (int i = 0; i < args.size(); ++i) { if (!QJSValuePrivate::checkEngine(engine, args.at(i))) { qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); return QJSValue(); } - callData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i)); + jsCall->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i)); } - ScopedValue result(scope, f->call(callData)); + ScopedValue result(scope, jsCall.call()); if (engine->hasException) result = engine->catchException(); @@ -762,16 +762,16 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args) Q_ASSERT(engine); Scope scope(engine); - ScopedCallData callData(scope, args.size()); + JSCall jsCall(scope, f, args.size()); for (int i = 0; i < args.size(); ++i) { if (!QJSValuePrivate::checkEngine(engine, args.at(i))) { qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine"); return QJSValue(); } - callData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i)); + jsCall->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i)); } - ScopedValue result(scope, f->construct(callData)); + ScopedValue result(scope, jsCall.callAsConstructor()); if (engine->hasException) result = engine->catchException(); diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index b90a186551..1a60725d27 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -139,10 +139,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con if (isMapped && attrs.isData()) { Q_ASSERT(arrayData()); ScopedFunctionObject setter(scope, map->setter()); - ScopedCallData callData(scope, setter, 1); - callData->thisObject = this->asReturnedValue(); - callData->args[0] = desc->value; - callData.call(); + JSCall jsCall(scope, setter, 1); + jsCall->thisObject = this->asReturnedValue(); + jsCall->args[0] = desc->value; + jsCall.call(); if (attrs.isWritable()) { setArrayAttributes(index, mapAttrs); diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 33ef7fa6df..bd47d0bc77 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -187,10 +187,10 @@ ReturnedValue ArrayBufferPrototype::method_slice(const BuiltinFunction *b, CallD if (!constructor) return v4->throwTypeError(); - ScopedCallData cData(scope, 1); + JSCall jsCall(scope, constructor, 1); double newLen = qMax(final - first, 0.); - cData->args[0] = QV4::Encode(newLen); - QV4::Scoped<ArrayBuffer> newBuffer(scope, constructor->construct(cData)); + jsCall->args[0] = QV4::Encode(newLen); + QV4::Scoped<ArrayBuffer> newBuffer(scope, jsCall.callAsConstructor()); if (!newBuffer || newBuffer->d()->data->size < (int)newLen) return v4->throwTypeError(); diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index fe9736ea9b..55b6370b42 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -673,15 +673,14 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const return false; if (v2.isUndefined() || v2.isEmpty()) return true; - ScopedObject o(scope, m_comparefn); + ScopedFunctionObject o(scope, m_comparefn); if (o) { Scope scope(o->engine()); ScopedValue result(scope); - ScopedCallData callData(scope, 2); - callData->thisObject = Primitive::undefinedValue(); - callData->args[0] = v1; - callData->args[1] = v2; - result = QV4::Runtime::method_callValue(scope.engine, m_comparefn, callData); + JSCall jsCall(scope, o, 2); + jsCall->args[0] = v1; + jsCall->args[1] = v2; + result = jsCall.call(); return result->toNumber() < 0; } @@ -755,7 +754,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c if (!arrayData || !arrayData->length()) return; - if (!(comparefn.isUndefined() || comparefn.as<Object>())) { + if (!comparefn.isUndefined() && !comparefn.isFunctionObject()) { engine->throwTypeError(); return; } @@ -834,7 +833,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c } - ArrayElementLessThan lessThan(engine, thisObject, comparefn); + ArrayElementLessThan lessThan(engine, thisObject, static_cast<const FunctionObject &>(comparefn)); Value *begin = thisObject->arrayData()->values.values; sortHelper(begin, begin + len, *begin, lessThan); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index f7486471ee..7796da5c70 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -126,16 +126,17 @@ ReturnedValue ArrayPrototype::method_isArray(const BuiltinFunction *, 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"))); - ScopedFunctionObject f(scope, o->get(s)); - if (!!f) { - ScopedCallData d(scope, 0); - d->thisObject = callData->thisObject; - return f->call(d); + ExecutionEngine *v4 = builtin->engine(); + if (!callData->thisObject.isObject()) { + callData->thisObject = callData->thisObject.toObject(v4); + if (v4->hasException) + return QV4::Encode::undefined(); } + + callData->accumulator = v4->newString(QStringLiteral("join")); + callData->function = static_cast<Object &>(callData->thisObject).get(static_cast<String *>(&callData->accumulator)); + if (callData->function.isFunctionObject()) + return static_cast<FunctionObject &>(callData->function).call(callData); return ObjectPrototype::method_toString(builtin, callData); } @@ -197,8 +198,8 @@ ReturnedValue ArrayPrototype::method_find(const BuiltinFunction *b, CallData *ca if (!callback) THROW_TYPE_ERROR(); - ScopedCallData cData(scope, 3); - cData->thisObject = callData->argument(1); + JSCall jsCall(scope, callback, 3); + jsCall->thisObject = callData->argument(1); ScopedValue v(scope); ScopedValue result(scope); @@ -207,10 +208,10 @@ ReturnedValue ArrayPrototype::method_find(const BuiltinFunction *b, CallData *ca v = instance->getIndexed(k); CHECK_EXCEPTION(); - cData->args[0] = v; - cData->args[1] = Primitive::fromDouble(k); - cData->args[2] = instance; - result = callback->call(cData); + jsCall->args[0] = v; + jsCall->args[1] = Primitive::fromDouble(k); + jsCall->args[2] = instance; + result = jsCall.call(); CHECK_EXCEPTION(); if (result->toBoolean()) @@ -233,8 +234,8 @@ ReturnedValue ArrayPrototype::method_findIndex(const BuiltinFunction *b, CallDat if (!callback) THROW_TYPE_ERROR(); - ScopedCallData cData(scope, 3); - cData->thisObject = callData->argument(1); + JSCall jsCall(scope, callback, 3); + jsCall->thisObject = callData->argument(1); ScopedValue v(scope); ScopedValue result(scope); @@ -243,10 +244,10 @@ ReturnedValue ArrayPrototype::method_findIndex(const BuiltinFunction *b, CallDat v = instance->getIndexed(k); CHECK_EXCEPTION(); - cData->args[0] = v; - cData->args[1] = Primitive::fromDouble(k); - cData->args[2] = instance; - result = callback->call(cData); + jsCall->args[0] = v; + jsCall->args[1] = Primitive::fromDouble(k); + jsCall->args[2] = instance; + result = jsCall.call(); CHECK_EXCEPTION(); if (result->toBoolean()) @@ -789,8 +790,8 @@ ReturnedValue ArrayPrototype::method_every(const BuiltinFunction *b, CallData *c if (!callback) THROW_TYPE_ERROR(); - ScopedCallData cData(scope, 3); - cData->thisObject = callData->argument(1); + JSCall jsCall(scope, callback, 3); + jsCall->thisObject = callData->argument(1); ScopedValue r(scope); ScopedValue v(scope); @@ -801,10 +802,10 @@ ReturnedValue ArrayPrototype::method_every(const BuiltinFunction *b, CallData *c if (!exists) continue; - cData->args[0] = v; - cData->args[1] = Primitive::fromDouble(k); - cData->args[2] = instance; - r = callback->call(cData); + jsCall->args[0] = v; + jsCall->args[1] = Primitive::fromDouble(k); + jsCall->args[2] = instance; + r = jsCall.call(); ok = r->toBoolean(); } return Encode(ok); @@ -823,8 +824,8 @@ ReturnedValue ArrayPrototype::method_some(const BuiltinFunction *b, CallData *ca if (!callback) THROW_TYPE_ERROR(); - ScopedCallData cData(scope, 3); - cData->thisObject = callData->argument(1); + JSCall jsCall(scope, callback, 3); + jsCall->thisObject = callData->argument(1); ScopedValue v(scope); ScopedValue result(scope); @@ -834,10 +835,10 @@ ReturnedValue ArrayPrototype::method_some(const BuiltinFunction *b, CallData *ca if (!exists) continue; - cData->args[0] = v; - cData->args[1] = Primitive::fromDouble(k); - cData->args[2] = instance; - result = callback->call(cData); + jsCall->args[0] = v; + jsCall->args[1] = Primitive::fromDouble(k); + jsCall->args[2] = instance; + result = jsCall.call(); if (result->toBoolean()) return Encode(true); } @@ -857,8 +858,8 @@ ReturnedValue ArrayPrototype::method_forEach(const BuiltinFunction *b, CallData if (!callback) THROW_TYPE_ERROR(); - ScopedCallData cData(scope, 3); - cData->thisObject = callData->argument(1); + JSCall jsCall(scope, callback, 3); + jsCall->thisObject = callData->argument(1); ScopedValue v(scope); for (uint k = 0; k < len; ++k) { @@ -867,10 +868,10 @@ ReturnedValue ArrayPrototype::method_forEach(const BuiltinFunction *b, CallData if (!exists) continue; - cData->args[0] = v; - cData->args[1] = Primitive::fromDouble(k); - cData->args[2] = instance; - callback->call(cData); + jsCall->args[0] = v; + jsCall->args[1] = Primitive::fromDouble(k); + jsCall->args[2] = instance; + jsCall.call(); } RETURN_UNDEFINED(); } @@ -893,8 +894,8 @@ ReturnedValue ArrayPrototype::method_map(const BuiltinFunction *b, CallData *cal a->setArrayLengthUnchecked(len); ScopedValue mapped(scope); - ScopedCallData cData(scope, 3); - cData->thisObject = callData->argument(1); + JSCall jsCall(scope, callback, 3); + jsCall->thisObject = callData->argument(1); ScopedValue v(scope); for (uint k = 0; k < len; ++k) { @@ -903,10 +904,10 @@ ReturnedValue ArrayPrototype::method_map(const BuiltinFunction *b, CallData *cal if (!exists) continue; - cData->args[0] = v; - cData->args[1] = Primitive::fromDouble(k); - cData->args[2] = instance; - mapped = callback->call(cData); + jsCall->args[0] = v; + jsCall->args[1] = Primitive::fromDouble(k); + jsCall->args[2] = instance; + mapped = jsCall.call(); a->arraySet(k, mapped); } return a.asReturnedValue(); @@ -930,8 +931,8 @@ ReturnedValue ArrayPrototype::method_filter(const BuiltinFunction *b, CallData * ScopedValue selected(scope); ScopedValue v(scope); - ScopedCallData cData(scope, 3); - cData->thisObject = callData->argument(1); + JSCall jsCall(scope, callback, 3); + jsCall->thisObject = callData->argument(1); uint to = 0; for (uint k = 0; k < len; ++k) { @@ -940,10 +941,10 @@ ReturnedValue ArrayPrototype::method_filter(const BuiltinFunction *b, CallData * if (!exists) continue; - cData->args[0] = v; - cData->args[1] = Primitive::fromDouble(k); - cData->args[2] = instance; - selected = callback->call(cData); + jsCall->args[0] = v; + jsCall->args[1] = Primitive::fromDouble(k); + jsCall->args[2] = instance; + selected = jsCall.call(); if (selected->toBoolean()) { a->arraySet(to, v); ++to; @@ -983,18 +984,17 @@ ReturnedValue ArrayPrototype::method_reduce(const BuiltinFunction *b, CallData * THROW_TYPE_ERROR(); } - ScopedCallData cData(scope, 4); - cData->thisObject = Primitive::undefinedValue(); + JSCall jsCall(scope, callback, 4); while (k < len) { bool kPresent; v = instance->getIndexed(k, &kPresent); if (kPresent) { - cData->args[0] = acc; - cData->args[1] = v; - cData->args[2] = Primitive::fromDouble(k); - cData->args[3] = instance; - acc = callback->call(cData); + jsCall->args[0] = acc; + jsCall->args[1] = v; + jsCall->args[2] = Primitive::fromDouble(k); + jsCall->args[3] = instance; + acc = jsCall.call(); } ++k; } @@ -1037,18 +1037,18 @@ ReturnedValue ArrayPrototype::method_reduceRight(const BuiltinFunction *b, CallD THROW_TYPE_ERROR(); } - ScopedCallData cData(scope, 4); - cData->thisObject = Primitive::undefinedValue(); + JSCall jsCall(scope, callback, 4); + jsCall->thisObject = Primitive::undefinedValue(); while (k > 0) { bool kPresent; v = instance->getIndexed(k - 1, &kPresent); if (kPresent) { - cData->args[0] = acc; - cData->args[1] = v; - cData->args[2] = Primitive::fromDouble(k - 1); - cData->args[3] = instance; - acc = callback->call(cData); + jsCall->args[0] = acc; + jsCall->args[1] = v; + jsCall->args[2] = Primitive::fromDouble(k - 1); + jsCall->args[3] = instance; + acc = jsCall.call(); } --k; } diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 5ac2a43b19..64aecfe352 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -1451,9 +1451,9 @@ ReturnedValue DatePrototype::method_toJSON(const BuiltinFunction *b, CallData *c if (!toIso) return v4->throwTypeError(); - ScopedCallData cData(scope); - cData->thisObject = callData->thisObject; - return toIso->call(cData); + JSCall jsCall(scope, toIso); + jsCall->thisObject = callData->thisObject; + return jsCall.call(); } void DatePrototype::timezoneUpdated() diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 4a6890c651..3f971fcca5 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -286,49 +286,48 @@ ReturnedValue FunctionPrototype::method_apply(const BuiltinFunction *b, CallData len = arr->getLength(); } - ScopedCallData cData(scope, len); + JSCall jsCall(scope, o, len); if (len) { if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) { QV4::ArgumentsObject *a = arr->cast<ArgumentsObject>(); int l = qMin(len, (uint)a->d()->context->argc()); - memcpy(cData->args, a->d()->context->args(), l*sizeof(Value)); + memcpy(jsCall->args, a->d()->context->args(), l*sizeof(Value)); for (quint32 i = l; i < len; ++i) - cData->args[i] = Primitive::undefinedValue(); + jsCall->args[i] = Primitive::undefinedValue(); } else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) { auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData()); uint alen = sad ? sad->values.size : 0; if (alen > len) alen = len; for (uint i = 0; i < alen; ++i) - cData->args[i] = sad->data(i); + jsCall->args[i] = sad->data(i); for (quint32 i = alen; i < len; ++i) - cData->args[i] = Primitive::undefinedValue(); + jsCall->args[i] = Primitive::undefinedValue(); } else { for (quint32 i = 0; i < len; ++i) - cData->args[i] = arr->getIndexed(i); + jsCall->args[i] = arr->getIndexed(i); } } - cData->thisObject = callData->argument(0); - return o->call(cData); + jsCall->thisObject = callData->argument(0); + return jsCall.call(); } ReturnedValue FunctionPrototype::method_call(const BuiltinFunction *b, CallData *callData) { - QV4::Scope scope(b); - FunctionObject *o = callData->thisObject.as<FunctionObject>(); - if (!o) - return scope.engine->throwTypeError(); - - ScopedCallData cData(scope, callData->argc ? callData->argc - 1 : 0); + if (!callData->thisObject.isFunctionObject()) { + ExecutionEngine *e = b->engine(); + return e->throwTypeError(); + } + callData->function = callData->thisObject; + callData->thisObject = callData->argc ? callData->args[0] : Primitive::undefinedValue(); if (callData->argc) { - for (int i = 1; i < callData->argc; ++i) - cData->args[i - 1] = callData->args[i]; + --callData->argc; + for (int i = 0; i < callData->argc; ++i) + callData->args[i] = callData->args[i + 1]; } - cData->thisObject = callData->argument(0); - - return o->call(cData); + return static_cast<FunctionObject &>(callData->function).call(callData); } ReturnedValue FunctionPrototype::method_bind(const BuiltinFunction *b, CallData *callData) @@ -488,16 +487,15 @@ ReturnedValue BoundFunction::call(const Managed *that, CallData *dd) return Encode::undefined(); Scoped<MemberData> boundArgs(scope, f->boundArgs()); - ScopedCallData callData(scope, (boundArgs ? boundArgs->size() : 0) + dd->argc); - callData->thisObject = f->boundThis(); - Value *argp = callData->args; + JSCall jsCall(scope, f->target(), (boundArgs ? boundArgs->size() : 0) + dd->argc); + jsCall->thisObject = f->boundThis(); + Value *argp = jsCall->args; if (boundArgs) { memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value)); argp += boundArgs->size(); } memcpy(argp, dd->args, dd->argc*sizeof(Value)); - ScopedFunctionObject t(scope, f->target()); - return t->call(callData); + return jsCall.call(); } ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd) @@ -509,13 +507,12 @@ ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd) return Encode::undefined(); Scoped<MemberData> boundArgs(scope, f->boundArgs()); - ScopedCallData callData(scope, (boundArgs ? boundArgs->size() : 0) + dd->argc); - Value *argp = callData->args; + JSCall jsCall(scope, f->target(), (boundArgs ? boundArgs->size() : 0) + dd->argc); + Value *argp = jsCall->args; if (boundArgs) { memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value)); argp += boundArgs->size(); } memcpy(argp, dd->args, dd->argc*sizeof(Value)); - ScopedFunctionObject t(scope, f->target()); - return t->construct(callData); + return jsCall.callAsConstructor(); } diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 74173f6a6a..11105dfdcb 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -374,12 +374,12 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const if (function->isStrict() || (ctx->d()->v4Function->isStrict())) { ScopedFunctionObject e(scope, FunctionObject::createScriptFunction(ctx, function)); - ScopedCallData callData(scope, 0); + JSCall jsCall(scope, e, 0); if (directCall) - callData->thisObject = scope.engine->currentStackFrame->thisObject(); + jsCall->thisObject = scope.engine->currentStackFrame->thisObject(); else - callData->thisObject = scope.engine->globalObject; - return e->call(callData); + jsCall->thisObject = scope.engine->globalObject; + return jsCall.call(); } ContextStateSaver stateSaver(scope, ctx); @@ -387,10 +387,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const // set the correct v4 function for the context ctx->d()->v4Function = function; - ScopedCallData cData(scope); - cData->thisObject = scope.engine->currentStackFrame->thisObject(); - cData->context = *ctx; - return function->call(cData); + JSCall jsCall(scope, nullptr); + jsCall->thisObject = scope.engine->currentStackFrame->thisObject(); + jsCall->context = *ctx; + return function->call(jsCall); } diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 3c378bf398..8983bea1a8 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -119,10 +119,10 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status) if (!f) return; - QV4::ScopedCallData callData(scope, 1); - callData->thisObject = v4->globalObject->asReturnedValue(); - callData->args[0] = status; - f->call(callData); + QV4::JSCall jsCall(scope, f, 1); + jsCall->thisObject = v4->globalObject->asReturnedValue(); + jsCall->args[0] = status; + jsCall.call(); if (scope.hasException()) scope.engine->catchException(); } diff --git a/src/qml/jsruntime/qv4jscall_p.h b/src/qml/jsruntime/qv4jscall_p.h index f871034789..c78337a89f 100644 --- a/src/qml/jsruntime/qv4jscall_p.h +++ b/src/qml/jsruntime/qv4jscall_p.h @@ -60,16 +60,15 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct ScopedCallData { - ScopedCallData(const Scope &scope, int argc = 0) +struct JSCall { + JSCall(const Scope &scope, std::nullptr_t, int argc = 0) { int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + qMax(argc , int(QV4::Global::ReservedArgumentCount)); ptr = reinterpret_cast<CallData *>(scope.alloc(size)); ptr->tag = quint32(QV4::Value::ValueTypeInternal::Integer); ptr->argc = argc; } - - ScopedCallData(const Scope &scope, const FunctionObject *function, int argc = 0) + JSCall(const Scope &scope, const FunctionObject *function, int argc = 0) { int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + qMax(argc , int(QV4::Global::ReservedArgumentCount)); ptr = reinterpret_cast<CallData *>(scope.alloc(size)); @@ -77,6 +76,14 @@ struct ScopedCallData { ptr->argc = argc; ptr->function = *function; } + JSCall(const Scope &scope, Heap::FunctionObject *function, int argc = 0) + { + int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + qMax(argc , int(QV4::Global::ReservedArgumentCount)); + ptr = reinterpret_cast<CallData *>(scope.alloc(size)); + ptr->tag = quint32(QV4::Value::ValueTypeInternal::Integer); + ptr->argc = argc; + ptr->function = function; + } CallData *operator->() { return ptr; @@ -90,6 +97,10 @@ struct ScopedCallData { return static_cast<FunctionObject &>(ptr->function).call(ptr); } + ReturnedValue callAsConstructor() const { + return static_cast<FunctionObject &>(ptr->function).construct(ptr); + } + CallData *ptr; }; diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 88fc0d6b3c..83cfb434dc 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -697,21 +697,21 @@ QString Stringify::Str(const QString &key, const Value &v) ScopedString s(scope, v4->newString(QStringLiteral("toJSON"))); ScopedFunctionObject toJSON(scope, o->get(s)); if (!!toJSON) { - ScopedCallData callData(scope, 1); - callData->thisObject = value; - callData->args[0] = v4->newString(key); - value = toJSON->call(callData); + JSCall jsCall(scope, toJSON, 1); + jsCall->thisObject = value; + jsCall->args[0] = v4->newString(key); + value = jsCall.call(); } } if (replacerFunction) { ScopedObject holder(scope, v4->newObject()); holder->put(scope.engine->id_empty(), value); - ScopedCallData callData(scope, 2); - callData->args[0] = v4->newString(key); - callData->args[1] = value; - callData->thisObject = holder; - value = replacerFunction->call(callData); + JSCall jsCall(scope, replacerFunction, 2); + jsCall->args[0] = v4->newString(key); + jsCall->args[1] = value; + jsCall->thisObject = holder; + value = jsCall.call(); } o = value->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 392ab565b0..c612e8450c 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -400,9 +400,9 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, ExecutionEngine *engine, const if (!getter) return Encode::undefined(); - ScopedCallData callData(scope, 0); - callData->thisObject = object; - return getter->call(callData); + JSCall jsCall(scope, getter, 0); + jsCall->thisObject = object; + return jsCall.call(); } } l->getter = getterFallback; @@ -422,9 +422,9 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, ExecutionEngine *engine, const if (!getter) return Encode::undefined(); - ScopedCallData callData(scope, 0); - callData->thisObject = object; - return getter->call(callData); + JSCall jsCall(scope, getter, 0); + jsCall->thisObject = object; + return jsCall.call(); } } l->getter = getterFallback; @@ -447,9 +447,9 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, ExecutionEngine *engine, const if (!getter) return Encode::undefined(); - ScopedCallData callData(scope, 0); - callData->thisObject = object; - return getter->call(callData); + JSCall jsCall(scope, getter, 0); + jsCall->thisObject = object; + return jsCall.call(); } } } @@ -502,9 +502,9 @@ ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, ExecutionEngine *engin if (!getter) return Encode::undefined(); - ScopedCallData callData(scope, 0); - callData->thisObject = object; - return getter->call(callData); + JSCall jsCall(scope, getter, 0); + jsCall->thisObject = object; + return jsCall.call(); } } l->getter = getterGeneric; @@ -522,9 +522,9 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin if (!getter) return Encode::undefined(); - ScopedCallData callData(scope, 0); - callData->thisObject = object; - return getter->call(callData); + JSCall jsCall(scope, getter, 0); + jsCall->thisObject = object; + return jsCall.call(); } } l->getter = getterGeneric; @@ -641,9 +641,8 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine) if (!getter) return Encode::undefined(); - ScopedCallData callData(scope, 0); - callData->thisObject = Primitive::undefinedValue(); - return getter->call(callData); + JSCall jsCall(scope, getter, 0); + return jsCall.call(); } l->globalGetter = globalGetterGeneric; return globalGetterGeneric(l, engine); @@ -659,9 +658,8 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine) if (!getter) return Encode::undefined(); - ScopedCallData callData(scope, 0); - callData->thisObject = Primitive::undefinedValue(); - return getter->call(callData); + JSCall jsCall(scope, getter, 0); + return jsCall.call(); } l->globalGetter = globalGetterGeneric; return globalGetterGeneric(l, engine); @@ -680,9 +678,8 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine) if (!getter) return Encode::undefined(); - ScopedCallData callData(scope, 0); - callData->thisObject = Primitive::undefinedValue(); - return getter->call(callData); + JSCall jsCall(scope, getter, 0); + return jsCall.call(); } } } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index b778a064be..d310c4b114 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -107,9 +107,9 @@ ReturnedValue Object::getValue(const Value &thisObject, const Value &v, Property return Encode::undefined(); Scope scope(f->engine()); - ScopedCallData callData(scope); - callData->thisObject = thisObject; - return f->call(callData); + JSCall jsCall(scope, f); + jsCall->thisObject = thisObject; + return jsCall.call(); } bool Object::putValue(uint memberIndex, const Value &value) @@ -125,10 +125,10 @@ bool Object::putValue(uint memberIndex, const Value &value) if (set) { Scope scope(ic->engine); ScopedFunctionObject setter(scope, set); - ScopedCallData callData(scope, 1); - callData->args[0] = value; - callData->thisObject = this; - setter->call(callData); + JSCall jsCall(scope, setter, 1); + jsCall->args[0] = value; + jsCall->thisObject = this; + jsCall.call(); return !ic->engine->hasException; } return false; @@ -764,11 +764,11 @@ bool Object::internalPut(String *name, const Value &value) Scope scope(engine); ScopedFunctionObject setter(scope, *memberIndex); - ScopedCallData callData(scope, 1); - callData->args[0] = value; - callData->thisObject = this; - setter->call(callData); - return !internalClass()->engine->hasException; + JSCall jsCall(scope, setter, 1); + jsCall->args[0] = value; + jsCall->thisObject = this; + jsCall.call(); + return !engine->hasException; } insertMember(name, value); @@ -829,11 +829,11 @@ bool Object::internalPutIndexed(uint index, const Value &value) Scope scope(engine); ScopedFunctionObject setter(scope, *arrayIndex); - ScopedCallData callData(scope, 1); - callData->args[0] = value; - callData->thisObject = this; - setter->call(callData); - return !internalClass()->engine->hasException; + JSCall jsCall(scope, setter, 1); + jsCall->args[0] = value; + jsCall->thisObject = this; + jsCall.call(); + return !engine->hasException; } arraySet(index, value); diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index e7ef9d93cf..0f60881db1 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -479,9 +479,9 @@ ReturnedValue ObjectPrototype::method_toLocaleString(const BuiltinFunction *b, C ScopedFunctionObject f(scope, o->get(scope.engine->id_toString())); if (!f) THROW_TYPE_ERROR(); - ScopedCallData cData(scope); - cData->thisObject = o; - return f->call(callData); + JSCall jsCall(scope, f); + jsCall->thisObject = o; + return jsCall.call(); } ReturnedValue ObjectPrototype::method_valueOf(const BuiltinFunction *b, CallData *callData) diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index ddce96f9ca..40dfeefdcc 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -816,18 +816,18 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase QV4::Scope scope(v4); QV4::ScopedFunctionObject f(scope, This->function.value()); - QV4::ScopedCallData callData(scope, argCount); - callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value(); + QV4::JSCall jsCall(scope, f, argCount); + jsCall->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value(); for (int ii = 0; ii < argCount; ++ii) { int type = argsTypes[ii + 1]; if (type == qMetaTypeId<QVariant>()) { - callData->args[ii] = v4->fromVariant(*((QVariant *)metaArgs[ii + 1])); + jsCall->args[ii] = v4->fromVariant(*((QVariant *)metaArgs[ii + 1])); } else { - callData->args[ii] = v4->fromVariant(QVariant(type, metaArgs[ii + 1])); + jsCall->args[ii] = v4->fromVariant(QVariant(type, metaArgs[ii + 1])); } } - f->call(callData); + jsCall.call(); if (scope.hasException()) { QQmlError error = v4->catchExceptionAsQmlError(); if (error.description().isEmpty()) { diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 4124188b59..db5551f99c 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -394,10 +394,10 @@ ReturnedValue RegExpPrototype::method_compile(const BuiltinFunction *b, CallData if (!r) return scope.engine->throwTypeError(); - ScopedCallData cData(scope, callData->argc); - memcpy(cData->args, callData->args, callData->argc*sizeof(Value)); + JSCall jsCall(scope, scope.engine->regExpCtor(), callData->argc); + memcpy(jsCall->args, callData->args, callData->argc*sizeof(Value)); - Scoped<RegExpObject> re(scope, scope.engine->regExpCtor()->as<FunctionObject>()->construct(cData)); + Scoped<RegExpObject> re(scope, jsCall.callAsConstructor()); r->d()->value.set(scope.engine, re->value()); r->d()->global = re->global(); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 187cd7c313..f09d803d0b 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -424,12 +424,13 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH qSwap(meth1, meth2); Scope scope(engine); - ScopedCallData callData(scope, 0); - callData->thisObject = *object; + JSCall jsCall(scope, nullptr, 0); + jsCall->thisObject = *object; ScopedValue conv(scope, object->get(meth1)); if (FunctionObject *o = conv->as<FunctionObject>()) { - ScopedValue r(scope, o->call(callData)); + jsCall->function = o; + ScopedValue r(scope, jsCall.call()); if (r->isPrimitive()) return r->asReturnedValue(); } @@ -439,7 +440,8 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH conv = object->get(meth2); if (FunctionObject *o = conv->as<FunctionObject>()) { - ScopedValue r(scope, o->call(callData)); + jsCall->function = o; + ScopedValue r(scope, jsCall.call()); if (r->isPrimitive()) return r->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 598c12ffd4..c3200fbcea 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -152,16 +152,16 @@ ReturnedValue Script::run() ContextStateSaver stateSaver(valueScope, scope); scope->d()->v4Function = vmFunction; - QV4::ScopedCallData cData(scope); - cData->thisObject = engine->globalObject; - cData->context = *scope; - return vmFunction->call(cData); + QV4::JSCall jsCall(scope, nullptr); + jsCall->thisObject = engine->globalObject; + jsCall->context = *scope; + return vmFunction->call(jsCall); } else { Scoped<QmlContext> qml(valueScope, qmlContext.value()); - ScopedCallData callData(valueScope); - callData->thisObject = Primitive::undefinedValue(); - callData->context = *qml; - return vmFunction->call(callData); + JSCall jsCall(valueScope, nullptr); + jsCall->thisObject = Primitive::undefinedValue(); + jsCall->context = *qml; + return vmFunction->call(jsCall); } } diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index ed9f798cd7..28b20169d9 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -417,12 +417,14 @@ public: bool operator()(typename Container::value_type lhs, typename Container::value_type rhs) { QV4::Scope scope(m_v4); - ScopedObject compare(scope, m_compareFn); - ScopedCallData callData(scope, 2); - callData->args[0] = convertElementToValue(m_v4, lhs); - callData->args[1] = convertElementToValue(m_v4, rhs); - callData->thisObject = m_v4->globalObject; - QV4::ScopedValue result(scope, compare->call(callData)); + ScopedFunctionObject compare(scope, m_compareFn); + if (!compare) + return m_v4->throwTypeError(); + JSCall jsCall(scope, compare, 2); + jsCall->args[0] = convertElementToValue(m_v4, lhs); + jsCall->args[1] = convertElementToValue(m_v4, rhs); + jsCall->thisObject = m_v4->globalObject; + QV4::ScopedValue result(scope, jsCall.call()); return result->toNumber() < 0; } diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 4964769b88..66ad5e79d2 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -411,9 +411,9 @@ ReturnedValue StringPrototype::method_match(const BuiltinFunction *b, CallData * ScopedValue regexp(scope, callData->argument(0)); Scoped<RegExpObject> rx(scope, regexp); if (!rx) { - ScopedCallData callData(scope, 1); - callData->args[0] = regexp; - rx = scope.engine->regExpCtor()->construct(callData); + JSCall jsCall(scope, scope.engine->regExpCtor(), 1); + jsCall->args[0] = regexp; + rx = jsCall.callAsConstructor(); } if (!rx) @@ -426,11 +426,11 @@ ReturnedValue StringPrototype::method_match(const BuiltinFunction *b, CallData * ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec"))); ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString)); - ScopedCallData cData(scope, 1); - cData->thisObject = rx; - cData->args[0] = s; + JSCall jsCall(scope, exec, 1); + jsCall->thisObject = rx; + jsCall->args[0] = s; if (!global) - return exec->call(cData); + return jsCall.call(); ScopedString lastIndex(scope, scope.engine->newString(QStringLiteral("lastIndex"))); rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0))); @@ -442,7 +442,7 @@ ReturnedValue StringPrototype::method_match(const BuiltinFunction *b, CallData * ScopedValue index(scope); ScopedValue result(scope); while (1) { - result = exec->call(cData); + result = jsCall.call(); if (result->isNull()) break; assert(result->isObject()); @@ -590,8 +590,8 @@ ReturnedValue StringPrototype::method_replace(const BuiltinFunction *b, CallData ScopedFunctionObject searchCallback(scope, replaceValue); if (!!searchCallback) { result.reserve(string.length() + 10*numStringMatches); - ScopedCallData callData(scope, numCaptures + 2); - callData->thisObject = Primitive::undefinedValue(); + JSCall jsCall(scope, searchCallback, numCaptures + 2); + jsCall->thisObject = Primitive::undefinedValue(); int lastEnd = 0; ScopedValue entry(scope); for (int i = 0; i < numStringMatches; ++i) { @@ -602,15 +602,15 @@ ReturnedValue StringPrototype::method_replace(const BuiltinFunction *b, CallData entry = Primitive::undefinedValue(); if (start != JSC::Yarr::offsetNoMatch && end != JSC::Yarr::offsetNoMatch) entry = scope.engine->newString(string.mid(start, end - start)); - callData->args[k] = entry; + jsCall->args[k] = entry; } uint matchStart = matchOffsets[i * numCaptures * 2]; Q_ASSERT(matchStart >= static_cast<uint>(lastEnd)); uint matchEnd = matchOffsets[i * numCaptures * 2 + 1]; - callData->args[numCaptures] = Primitive::fromUInt32(matchStart); - callData->args[numCaptures + 1] = scope.engine->newString(string); + jsCall->args[numCaptures] = Primitive::fromUInt32(matchStart); + jsCall->args[numCaptures + 1] = scope.engine->newString(string); - replacement = searchCallback->call(callData); + replacement = jsCall.call(); result += string.midRef(lastEnd, matchStart - lastEnd); result += replacement->toQString(); lastEnd = matchEnd; @@ -652,9 +652,9 @@ ReturnedValue StringPrototype::method_search(const BuiltinFunction *b, CallData RegExpObject *regExp = regExpObj->as<RegExpObject>(); if (!regExp) { - ScopedCallData callData(scope, 1); - callData->args[0] = regExpObj; - regExpObj = scope.engine->regExpCtor()->construct(callData); + JSCall jsCall(scope, scope.engine->regExpCtor(), 1); + jsCall->args[0] = regExpObj; + regExpObj = jsCall.callAsConstructor(); if (scope.engine->hasException) return QV4::Encode::undefined(); diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 3d0acb19b9..5bec5046fe 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -572,9 +572,9 @@ ReturnedValue TypedArrayPrototype::method_subarray(const BuiltinFunction *builti if (!constructor) 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); - return constructor->construct(cData); + JSCall jsCall(scope, constructor, 3); + jsCall->args[0] = buffer; + jsCall->args[1] = Encode(a->d()->byteOffset + begin*a->d()->type->bytesPerElement); + jsCall->args[2] = Encode(newLen); + return jsCall.callAsConstructor(); } diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 20c84b34e6..ba2f37eb2d 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -193,35 +193,35 @@ void QQmlBoundSignalExpression::evaluate(void **a) int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, &storage, 0); int argCount = argsTypes ? *argsTypes : 0; - QV4::ScopedCallData callData(scope, argCount); + QV4::JSCall jsCall(scope, nullptr, argCount); for (int ii = 0; ii < argCount; ++ii) { int type = argsTypes[ii + 1]; //### ideally we would use metaTypeToJS, however it currently gives different results // for several cases (such as QVariant type and QObject-derived types) //args[ii] = engine->metaTypeToJS(type, a[ii + 1]); if (type == qMetaTypeId<QJSValue>()) { - if (QV4::Value *v4Value = QJSValuePrivate::valueForData(reinterpret_cast<QJSValue *>(a[ii + 1]), &callData->args[ii])) - callData->args[ii] = *v4Value; + if (QV4::Value *v4Value = QJSValuePrivate::valueForData(reinterpret_cast<QJSValue *>(a[ii + 1]), &jsCall->args[ii])) + jsCall->args[ii] = *v4Value; else - callData->args[ii] = QV4::Encode::undefined(); + jsCall->args[ii] = QV4::Encode::undefined(); } else if (type == QMetaType::QVariant) { - callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1])); + jsCall->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1])); } else if (type == QMetaType::Int) { //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise - callData->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1])); + jsCall->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1])); } else if (type == qMetaTypeId<QQmlV4Handle>()) { - callData->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]); + jsCall->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]); } else if (ep->isQObject(type)) { if (!*reinterpret_cast<void* const *>(a[ii + 1])) - callData->args[ii] = QV4::Primitive::nullValue(); + jsCall->args[ii] = QV4::Primitive::nullValue(); else - callData->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1])); + jsCall->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1])); } else { - callData->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1])); + jsCall->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1])); } } - QQmlJavaScriptExpression::evaluate(callData, 0); + QQmlJavaScriptExpression::evaluate(jsCall, 0); ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. } @@ -238,12 +238,12 @@ void QQmlBoundSignalExpression::evaluate(const QList<QVariant> &args) ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. - QV4::ScopedCallData callData(scope, args.count()); + QV4::JSCall jsCall(scope, nullptr, args.count()); for (int ii = 0; ii < args.count(); ++ii) { - callData->args[ii] = scope.engine->fromVariant(args[ii]); + jsCall->args[ii] = scope.engine->fromVariant(args[ii]); } - QQmlJavaScriptExpression::evaluate(callData, 0); + QQmlJavaScriptExpression::evaluate(jsCall, 0); ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. } diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 4affc5a453..dd0d2096ce 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1547,10 +1547,10 @@ void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s) QV4::ScopedFunctionObject f(scope, d()->statusChanged); if (f) { - QV4::ScopedCallData callData(scope, 1); - callData->thisObject = this; - callData->args[0] = QV4::Primitive::fromUInt32(s); - f->call(callData); + QV4::JSCall jsCall(scope, f, 1); + jsCall->thisObject = this; + jsCall->args[0] = QV4::Primitive::fromUInt32(s); + jsCall.call(); if (scope.hasException()) { QQmlError error = scope.engine->catchExceptionAsQmlError(); QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error); diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp index 87b6fac10e..1537657e0d 100644 --- a/src/qml/qml/qqmldelayedcallqueue.cpp +++ b/src/qml/qml/qqmldelayedcallqueue.cpp @@ -64,17 +64,17 @@ void QQmlDelayedCallQueue::DelayedFunctionCall::execute(QV4::ExecutionEngine *en QV4::Scope scope(engine); QV4::ArrayObject *array = m_args.as<QV4::ArrayObject>(); + const QV4::FunctionObject *callback = m_function.as<QV4::FunctionObject>(); + Q_ASSERT(callback); const int argCount = array ? array->getLength() : 0; - QV4::ScopedCallData callData(scope, argCount); - callData->thisObject = QV4::Encode::undefined(); + QV4::JSCall jsCall(scope, callback, argCount); + jsCall->thisObject = QV4::Encode::undefined(); for (int i = 0; i < argCount; i++) { - callData->args[i] = array->getIndexed(i); + jsCall->args[i] = array->getIndexed(i); } - const QV4::FunctionObject *callback = m_function.as<QV4::FunctionObject>(); - Q_ASSERT(callback); - callback->call(callData); + jsCall.call(); if (scope.engine->hasException) { QQmlError error = scope.engine->catchExceptionAsQmlError(); diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 36881f02ba..e40795283a 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -185,9 +185,9 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined) { QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_context->engine); QV4::Scope scope(v4); - QV4::ScopedCallData callData(scope); + QV4::JSCall jsCall(scope, nullptr); - return evaluate(callData, isUndefined); + return evaluate(jsCall, isUndefined); } QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined) diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 3510367fd3..2b54819ad0 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -951,14 +951,13 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * } const unsigned int parameterCount = function->formalParameterCount(); - QV4::ScopedCallData callData(scope, parameterCount); - callData->thisObject = ep->v8engine()->global(); + QV4::JSCall jsCall(scope, function, parameterCount); + jsCall->thisObject = ep->v8engine()->global(); for (uint ii = 0; ii < parameterCount; ++ii) - callData->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]); + jsCall->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]); - QV4::ScopedValue result(scope); - result = function->call(callData); + QV4::ScopedValue result(scope, jsCall.call()); if (scope.hasException()) { QQmlError error = scope.engine->catchExceptionAsQmlError(); if (error.isValid()) diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index a77c4c5678..21f1fb30b0 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1576,9 +1576,7 @@ void QQmlXMLHttpRequest::dispatchCallback(Object *thisObj, QQmlContextData *cont return; } - QV4::ScopedCallData callData(scope); - callData->thisObject = Encode::undefined(); - callback->call(callData); + QV4::JSCall(scope, callback).call(); if (scope.engine->hasException) { QQmlError error = scope.engine->catchExceptionAsQmlError(); diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index a26bd81c8b..6df15c2513 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -248,10 +248,10 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage"))); QV4::ScopedValue function(scope, QV4::BuiltinFunction::create(globalContext, name, QQuickWorkerScriptEnginePrivate::method_sendMessage)); - QV4::ScopedCallData callData(scope, 1); - callData->args[0] = function; - callData->thisObject = global(); - createsend.set(scope.engine, createsendconstructor->call(callData)); + QV4::JSCall jsCall(scope, createsendconstructor, 1); + jsCall->args[0] = function; + jsCall->thisObject = global(); + createsend.set(scope.engine, jsCall.call()); } // Requires handle and context scope @@ -265,10 +265,10 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i QV4::ScopedFunctionObject f(scope, createsend.value()); QV4::ScopedValue v(scope); - QV4::ScopedCallData callData(scope, 1); - callData->args[0] = QV4::Primitive::fromInt32(id); - callData->thisObject = global(); - v = f->call(callData); + QV4::JSCall jsCall(scope, f, 1); + jsCall->args[0] = QV4::Primitive::fromInt32(id); + jsCall->thisObject = global(); + v = jsCall.call(); if (scope.hasException()) v = scope.engine->catchException(); return v->asReturnedValue(); @@ -366,11 +366,11 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d QV4::Scoped<QV4::QmlContext> qmlContext(scope, script->qmlContext.value()); Q_ASSERT(!!qmlContext); - QV4::ScopedCallData callData(scope, 2); - callData->thisObject = workerEngine->global(); - callData->args[0] = qmlContext->d()->qml(); // ### - callData->args[1] = value; - f->call(callData); + QV4::JSCall jsCall(scope, f, 2); + jsCall->thisObject = workerEngine->global(); + jsCall->args[0] = qmlContext->d()->qml(); // ### + jsCall->args[1] = value; + jsCall.call(); if (scope.hasException()) { QQmlError error = scope.engine->catchExceptionAsQmlError(); reportScriptException(script, error); diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index ddf34666a2..ff90a74c43 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -729,13 +729,13 @@ void QQuickCanvasItem::updatePolish() QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(qmlEngine(this)); QV4::Scope scope(v4); - QV4::ScopedCallData callData(scope, 1); - callData->thisObject = QV4::QObjectWrapper::wrap(v4, this); + QV4::JSCall jsCall(scope, nullptr, 1); + jsCall->thisObject = QV4::QObjectWrapper::wrap(v4, this); for (auto it = animationCallbacks.cbegin(), end = animationCallbacks.cend(); it != end; ++it) { - QV4::ScopedFunctionObject f(scope, it.value().value()); - callData->args[0] = QV4::Primitive::fromUInt32(QDateTime::currentMSecsSinceEpoch() / 1000); - f->call(callData); + jsCall->function = it.value().value(); + jsCall->args[0] = QV4::Primitive::fromUInt32(QDateTime::currentMSecsSinceEpoch() / 1000); + jsCall.call(); } } else { diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index f36e260642..5f6b0a056e 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -2347,10 +2347,10 @@ static inline bool evaluate_error(QV8Engine *engine, const QV4::Value &o, const scope.engine->catchException(); return true; } - QV4::ScopedCallData d(scope, 1); - d->args[0] = o; - d->thisObject = engine->global(); - function->call(d); + QV4::JSCall jsCall(scope, function, 1); + jsCall->args[0] = o; + jsCall->thisObject = engine->global(); + jsCall.call(); if (scope.engine->hasException) { scope.engine->catchException(); return true; @@ -2377,10 +2377,10 @@ static inline bool evaluate_value(QV8Engine *engine, const QV4::Value &o, return false; QV4::ScopedValue value(scope); - QV4::ScopedCallData d(scope, 1); - d->args[0] = o; - d->thisObject = engine->global(); - value = function->call(d); + QV4::JSCall jsCall(scope, function, 1); + jsCall->args[0] = o; + jsCall->thisObject = engine->global(); + value = jsCall.call(); if (scope.engine->hasException) { scope.engine->catchException(); return false; @@ -2406,10 +2406,10 @@ static inline QV4::ReturnedValue evaluate(QV8Engine *engine, const QV4::Value &o } if (!function) return QV4::Encode::undefined(); - QV4::ScopedCallData d(scope, 1); - d->args[0] = o; - d->thisObject = engine->global(); - QV4::ScopedValue result(scope, function->call(d)); + QV4::JSCall jsCall(scope, function, 1); + jsCall->args[0] = o; + jsCall->thisObject = engine->global(); + QV4::ScopedValue result(scope, jsCall.call()); if (scope.engine->hasException) { scope.engine->catchException(); return QV4::Encode::undefined(); |