43 int size =
int(offsetof(QV4::CallData, args)/
sizeof(QV4::Value)) + args->argc;
45 ptr->function = Encode::undefined();
46 ptr->context = Encode::undefined();
47 ptr->accumulator = Encode::undefined();
48 ptr->thisObject = args->thisObject ? args->thisObject->asReturnedValue() : Encode::undefined();
49 ptr->newTarget = Encode::undefined();
50 ptr->setArgc(args->argc);
52 memcpy(ptr->args, args->args, args->argc*
sizeof(Value));
54 ptr->function = f->asReturnedValue();
114 ExecutionEngine *engine,
const Function::AOTCompiledFunction *aotFunction,
115 const Value *thisObject,
const Value *argv,
int argc, Callable call)
117 const qsizetype numFunctionArguments = aotFunction->types.length() - 1;
118 Q_ALLOCA_VAR(
void *, values, (numFunctionArguments + 1) *
sizeof(
void *));
119 Q_ALLOCA_VAR(QMetaType, types, (numFunctionArguments + 1) *
sizeof(QMetaType));
121 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
122 const QMetaType argumentType = aotFunction->types[i + 1];
123 types[i + 1] = argumentType;
124 if (
const qsizetype argumentSize = argumentType.sizeOf()) {
125 Q_ALLOCA_VAR(
void, argument, argumentSize);
126 if (argumentType.flags() & QMetaType::NeedsConstruction) {
127 argumentType.construct(argument);
129 ExecutionEngine::metaTypeFromJS(argv[i], argumentType, argument);
131 || !ExecutionEngine::metaTypeFromJS(argv[i], argumentType, argument)) {
135 argumentType.construct(argument);
138 values[i + 1] = argument;
140 values[i + 1] =
nullptr;
144 Q_ALLOCA_DECLARE(
void, returnValue);
145 types[0] = aotFunction->types[0];
146 if (
const qsizetype returnSize = types[0].sizeOf()) {
147 Q_ALLOCA_ASSIGN(
void, returnValue, returnSize);
148 values[0] = returnValue;
149 if (types[0].flags() & QMetaType::NeedsConstruction)
150 types[0].construct(returnValue);
155 if (
const QV4::QObjectWrapper *cppThisObject = thisObject
156 ? thisObject->as<
QV4::QObjectWrapper>()
158 call(cppThisObject->object(), values, types, argc);
160 call(
nullptr, values, types, argc);
163 ReturnedValue result;
165 result = engine->metaTypeToJS(types[0], values[0]);
166 if (types[0].flags() & QMetaType::NeedsDestruction)
167 types[0].destruct(values[0]);
169 result = Encode::undefined();
172 for (qsizetype i = 1, end = numFunctionArguments + 1; i <
end; ++i) {
173 if (types[i].flags() & QMetaType::NeedsDestruction)
174 types[i].destruct(values[i]);
182 void **a,
const QMetaType *types,
int argc, Callable call)
187 for (
int ii = 0; ii < argc; ++ii)
188 jsCallData.args[ii] = engine->metaTypeToJS(types[ii + 1], a[ii + 1]);
193 jsThisObject = QV4::QObjectWrapper::wrap(engine, thisObject);
195 jsThisObject = engine->globalObject;
197 jsThisObject = engine->globalObject;
203 return !jsResult
->isUndefined();
205 const QMetaType resultType = types[0];
206 if (scope.hasException()) {
208 resultType.destruct(result);
209 resultType.construct(result);
210 }
else if (resultType == QMetaType::fromType<QVariant>()) {
213 *
static_cast<QVariant *>(result) = ExecutionEngine::toVariant(jsResult, QMetaType {});
214 }
else if (!ExecutionEngine::metaTypeFromJS(jsResult, resultType, result)) {
217 resultType.destruct(result);
218 resultType.construct(result);
220 return !jsResult
->isUndefined();
249 ExecutionEngine *engine,
const Value &value,
const QQmlType &qmlType)
251 QMetaType type = qmlType.qListTypeId();
252 const auto metaSequence = [&]() {
256 return qmlType.isSequentialContainer()
257 ? qmlType.listMetaSequence()
258 : QQmlMetaType::qmlListType(type).listMetaSequence();
261 if (
const QV4::Sequence *sequence = value.as<QV4::Sequence>()) {
262 if (sequence->d()->listType() == type)
263 return value.asReturnedValue();
266 if (
const QmlListWrapper *list = value.as<QmlListWrapper>()) {
267 if (list->d()->propertyType() == type)
268 return value.asReturnedValue();
271 QMetaType listValueType = qmlType.typeId();
272 if (!listValueType.isValid()) {
274 return value.asReturnedValue();
279 const ArrayObject *array = value.as<ArrayObject>();
281 return (listValueType.flags() & QMetaType::PointerToQObject)
282 ? QmlListWrapper::create(engine, listValueType)
283 : SequencePrototype::fromData(engine, type, metaSequence(),
nullptr);
286 if (listValueType.flags() & QMetaType::PointerToQObject) {
287 QV4::Scoped<QmlListWrapper> newList(scope, QmlListWrapper::create(engine, type));
288 QQmlListProperty<QObject> *listProperty = newList->d()->property();
290 const qsizetype length = array->getLength();
293 for (; i < length; ++i) {
295 listProperty->append(listProperty, coerceQObject(v, qmlType));
298 return newList->asReturnedValue();
301 QV4::Scoped<Sequence> sequence(
302 scope, SequencePrototype::fromData(engine, type, metaSequence(),
nullptr));
303 const qsizetype length = array->getLength();
305 for (qsizetype i = 0; i < length; ++i) {
309 return sequence->asReturnedValue();
313 ExecutionEngine *engine,
const Value &value,
const QQmlType &qmlType,
bool isList)
319 return coerceListType(engine, value, qmlType);
321 const QMetaType metaType = qmlType.typeId();
322 if (!metaType.isValid()) {
323 if (!value.isUndefined())
325 return value.asReturnedValue();
328 switch (metaType.id()) {
329 case QMetaType::Void:
330 return Encode::undefined();
331 case QMetaType::QVariant:
332 return value.asReturnedValue();
334 return Encode(value.toInt32());
335 case QMetaType::Double:
336 return value.convertedToNumber();
337 case QMetaType::QString:
338 return value.toString(engine)->asReturnedValue();
339 case QMetaType::Bool:
340 return Encode(value.toBoolean());
341 case QMetaType::QDateTime:
343 return value.asReturnedValue();
344 if (
const VariantObject *varObject = value.as<VariantObject>()) {
345 const QVariant &var = varObject->d()->data();
346 switch (var.metaType().id()) {
347 case QMetaType::QDateTime:
348 return engine->newDateObject(var.value<QDateTime>())->asReturnedValue();
349 case QMetaType::QTime:
350 return engine->newDateObject(var.value<QTime>(),
nullptr, -1, 0)->asReturnedValue();
351 case QMetaType::QDate:
352 return engine->newDateObject(var.value<QDate>(),
nullptr, -1, 0)->asReturnedValue();
357 return engine->newDateObject(QDateTime())->asReturnedValue();
358 case QMetaType::QUrl:
359 if (value.as<UrlObject>())
360 return value.asReturnedValue();
361 if (
const VariantObject *varObject = value.as<VariantObject>()) {
362 const QVariant &var = varObject->d()->data();
363 return var.metaType() == QMetaType::fromType<QUrl>()
364 ? engine->newUrlObject(var.value<QUrl>())->asReturnedValue()
365 : engine->newUrlObject()->asReturnedValue();
368 if (
const String *string = value.stringValue())
369 return engine->newUrlObject(QUrl(string->toQString()))->asReturnedValue();
370 return engine->newUrlObject()->asReturnedValue();
371#if QT_CONFIG(regularexpression)
372 case QMetaType::QRegularExpression:
373 if (value.as<RegExpObject>())
374 return value.asReturnedValue();
375 if (
const VariantObject *varObject = value.as<VariantObject>()) {
376 const QVariant &var = varObject->d()->data();
377 if (var.metaType() == QMetaType::fromType<QRegularExpression>())
378 return engine->newRegExpObject(var.value<QRegularExpression>())->asReturnedValue();
380 return engine->newRegExpObject(QString(), 0)->asReturnedValue();
386 if (metaType.flags() & QMetaType::PointerToQObject) {
387 return coerceQObject(value, qmlType)
388 ? value.asReturnedValue()
392 if (
const QQmlValueTypeWrapper *wrapper = value.as<QQmlValueTypeWrapper>()) {
393 if (wrapper->type() == metaType)
394 return value.asReturnedValue();
397 if (
void *target = QQmlValueTypeProvider::heapCreateValueType(qmlType, value, engine)) {
398 Heap::QQmlValueTypeWrapper *wrapper = engine->memoryManager->allocate<QQmlValueTypeWrapper>(
399 nullptr, metaType, qmlType.metaObjectForValueType(),
400 nullptr, -1, Heap::ReferenceObject::NoFlag);
401 Q_ASSERT(!wrapper->gadgetPtr());
402 wrapper->setGadgetPtr(target);
403 return wrapper->asReturnedValue();
406 return Encode::undefined();
411 ExecutionEngine *engine,
412 const Function::JSTypedFunction *typedFunction,
const CompiledData::Function *compiledFunction,
413 const Value *argv,
int argc, Callable call)
418 const CompiledData::Parameter *formals = compiledFunction->formalsTable();
419 for (qsizetype i = 0; i < jsCallData
.argc; ++i) {
420 jsCallData.args[i] = coerce(
421 engine, i < argc ? argv[i] : QV4::Value::fromReturnedValue(Encode::undefined()),
422 typedFunction->types[i + 1], formals[i].type.isList());
426 return coerce(engine, result, typedFunction->types[0], compiledFunction->returnType.isList());
431 ExecutionEngine *engine, QMetaType fromType,
const void *from, QMetaType toType,
void *to)
433 if ((fromType.flags() & QMetaType::PointerToQObject)
434 && (toType.flags() & QMetaType::PointerToQObject)) {
435 QObject *fromObj = *
static_cast<QObject *
const*>(from);
436 *
static_cast<QObject **>(to)
437 = (fromObj && fromObj->metaObject()->inherits(toType.metaObject()))
443 if (toType == QMetaType::fromType<QVariant>()) {
444 new (to) QVariant(fromType, from);
448 if (toType == QMetaType::fromType<QJSPrimitiveValue>()) {
449 new (to) QJSPrimitiveValue(fromType, from);
453 if (fromType == QMetaType::fromType<QVariant>()) {
454 const QVariant *fromVariant =
static_cast<
const QVariant *>(from);
455 if (fromVariant->metaType() == toType)
456 toType.construct(to, fromVariant->data());
458 coerce(engine, fromVariant->metaType(), fromVariant->data(), toType, to);
462 if (fromType == QMetaType::fromType<QJSPrimitiveValue>()) {
463 const QJSPrimitiveValue *fromPrimitive =
static_cast<
const QJSPrimitiveValue *>(from);
464 if (fromPrimitive->metaType() == toType)
465 toType.construct(to, fromPrimitive->data());
467 coerce(engine, fromPrimitive->metaType(), fromPrimitive->data(), toType, to);
474 if (toType.flags() & QMetaType::NeedsConstruction)
475 toType.construct(to);
478 if (!ExecutionEngine::metaTypeFromJS(value, toType, to))
479 QMetaType::convert(fromType, from, toType, to);
484 ExecutionEngine *engine,
const TypedFunction *typedFunction,
485 void **argv,
const QMetaType *types,
int argc, Callable call)
487 const qsizetype numFunctionArguments = typedFunction->parameterCount();
489 Q_ALLOCA_DECLARE(
void *, transformedArguments);
490 Q_ALLOCA_DECLARE(
void, transformedResult);
492 const QMetaType returnType = typedFunction->returnMetaType();
493 const QMetaType frameReturn = types[0];
494 bool returnsQVariantWrapper =
false;
495 if (argv[0] && returnType != frameReturn) {
496 Q_ALLOCA_ASSIGN(
void *, transformedArguments, (numFunctionArguments + 1) *
sizeof(
void *));
497 memcpy(transformedArguments, argv, (argc + 1) *
sizeof(
void *));
499 if (frameReturn == QMetaType::fromType<QVariant>()) {
500 QVariant *returnValue =
static_cast<QVariant *>(argv[0]);
501 *returnValue = QVariant(returnType);
502 transformedResult = transformedArguments[0] = returnValue->data();
503 returnsQVariantWrapper =
true;
504 }
else if (returnType.sizeOf() > 0) {
505 Q_ALLOCA_ASSIGN(
void, transformedResult, returnType.sizeOf());
506 transformedArguments[0] = transformedResult;
507 if (returnType.flags() & QMetaType::NeedsConstruction)
508 returnType.construct(transformedResult);
510 transformedResult = transformedArguments[0] = &argc;
514 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
515 const bool isValid = argc > i;
516 const QMetaType frameType = isValid ? types[i + 1] : QMetaType();
518 const QMetaType argumentType = typedFunction->parameterMetaType(i);
519 if (isValid && argumentType == frameType)
522 if (transformedArguments ==
nullptr) {
523 Q_ALLOCA_ASSIGN(
void *, transformedArguments, (numFunctionArguments + 1) *
sizeof(
void *));
524 memcpy(transformedArguments, argv, (argc + 1) *
sizeof(
void *));
527 if (argumentType.sizeOf() == 0) {
528 transformedArguments[i + 1] =
nullptr;
532 void *frameVal = isValid ? argv[i + 1] :
nullptr;
533 if (isValid && frameType == QMetaType::fromType<QVariant>()) {
534 QVariant *variant =
static_cast<QVariant *>(frameVal);
536 const QMetaType variantType = variant->metaType();
537 if (variantType == argumentType) {
540 transformedArguments[i + 1] = argv[i + 1] = variant->data();
542 Q_ALLOCA_VAR(
void, arg, argumentType.sizeOf());
543 coerce(engine, variantType, variant->constData(), argumentType, arg);
544 transformedArguments[i + 1] = arg;
549 Q_ALLOCA_VAR(
void, arg, argumentType.sizeOf());
552 coerce(engine, frameType, frameVal, argumentType, arg);
554 argumentType.construct(arg);
556 transformedArguments[i + 1] = arg;
559 if (!transformedArguments) {
560 call(argv, numFunctionArguments);
564 call(transformedArguments, numFunctionArguments);
566 if (transformedResult && !returnsQVariantWrapper) {
567 if (frameReturn.sizeOf() > 0) {
568 if (frameReturn.flags() & QMetaType::NeedsDestruction)
569 frameReturn.destruct(argv[0]);
570 coerce(engine, returnType, transformedResult, frameReturn, argv[0]);
572 if (returnType.flags() & QMetaType::NeedsDestruction)
573 returnType.destruct(transformedResult);
576 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
577 void *arg = transformedArguments[i + 1];
580 if (i >= argc || arg != argv[i + 1]) {
581 const QMetaType argumentType = typedFunction->parameterMetaType(i);
582 if (argumentType.flags() & QMetaType::NeedsDestruction)
583 argumentType.destruct(arg);