Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4jscall_p.h
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4#ifndef QV4JSCALL_H
5#define QV4JSCALL_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qqmllistwrapper_p.h>
19#include <private/qqmlvaluetypewrapper_p.h>
20
21#include <private/qv4alloca_p.h>
22#include <private/qv4dateobject_p.h>
23#include <private/qv4function_p.h>
24#include <private/qv4functionobject_p.h>
25#include <private/qv4qobjectwrapper_p.h>
26#include <private/qv4regexpobject_p.h>
27#include <private/qv4scopedvalue_p.h>
28#include <private/qv4sequenceobject_p.h>
29#include <private/qv4urlobject_p.h>
30#include <private/qv4variantobject_p.h>
31
32#if QT_CONFIG(regularexpression)
33#include <QtCore/qregularexpression.h>
34#endif
35
37
38namespace QV4 {
39
40template<typename Args>
41CallData *callDatafromJS(const Scope &scope, const Args *args, const FunctionObject *f)
42{
43 int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + args->argc;
44 CallData *ptr = reinterpret_cast<CallData *>(scope.alloc(size));
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);
51 if (args->argc)
52 memcpy(ptr->args, args->args, args->argc*sizeof(Value));
53 if (f)
54 ptr->function = f->asReturnedValue();
55 return ptr;
56}
57
59{
60 JSCallArguments(const Scope &scope, int argc = 0)
61 : thisObject(scope.constructUndefined(1)), args(scope.constructUndefined (argc)), argc(argc)
62 {
63 }
64
65 CallData *callData(const Scope &scope, const FunctionObject *f = nullptr) const
66 {
67 return callDatafromJS(scope, this, f);
68 }
69
70 Value *thisObject;
71 Value *args;
72 const int argc;
73};
74
76{
77 JSCallData(const Value *thisObject, const Value *argv, int argc)
78 : thisObject(thisObject), args(argv), argc(argc)
79 {
80 }
81
86
87 CallData *callData(const Scope &scope, const FunctionObject *f = nullptr) const
88 {
89 return callDatafromJS(scope, this, f);
90 }
91
92 const Value *thisObject;
93 const Value *args;
94 const int argc;
95};
96
97inline
102
103inline
108
109void populateJSCallArguments(ExecutionEngine *v4, JSCallArguments &jsCall, int argc,
110 void **args, const QMetaType *types);
111
112inline QObject *cppThisObject(const Value *thisObject)
113{
114 if (!thisObject)
115 return nullptr;
116 if (const QV4::QObjectWrapper *wrapper = thisObject->as<QV4::QObjectWrapper>())
117 return wrapper->object();
118 return nullptr;
119}
120
121inline void defaultConstructReturnValue(QMetaType returnType, void *returnValue)
122{
123 if (returnType.flags() & QMetaType::NeedsConstruction)
124 returnType.construct(returnValue);
125}
126
128 ExecutionEngine *engine, QMetaType returnType, void *returnValue)
129{
130 const ReturnedValue result = engine->metaTypeToJS(returnType, returnValue);
131 if (returnType.flags() & QMetaType::NeedsDestruction)
132 returnType.destruct(returnValue);
133 return result;
134}
135
136inline bool defaultConversionErrorHandler(QMetaType argumentType, void *argument, qsizetype i)
137{
138 Q_UNUSED(i);
139
140 // If we can't convert the argument, we need to default-construct it even if it
141 // doesn't formally need construction. For example:
142 // - An int doesn't need construction, but we still want it to be 0.
143 // - A QObject* should be nullptr by default, rather than some random value.
144 if (!(argumentType.flags() & QMetaType::NeedsConstruction))
145 argumentType.construct(argument);
146 return true;
147}
148
149template<typename Callable,
150 typename ConstructReturnValue = decltype(defaultConstructReturnValue),
151 typename ConvertReturnValue = decltype(defaultConvertReturnValue),
152 typename ConversionErrorHandler = decltype(defaultConversionErrorHandler)>
154 ExecutionEngine *engine, const QMetaType *types, int numTypes,
155 const Value *argv, int argc, Callable &&call,
156 ConstructReturnValue &&constructReturnValue = defaultConstructReturnValue,
157 ConvertReturnValue &&convertReturnValue = defaultConvertReturnValue,
158 ConversionErrorHandler &&errorHandler = defaultConversionErrorHandler)
159{
160 Q_ALLOCA_VAR(void *, values, numTypes * sizeof(void *));
161
162 for (qsizetype i = 1; i < numTypes; ++i) {
163 const QMetaType argumentType = types[i];
164 if (const qsizetype argumentSize = argumentType.sizeOf()) {
165 Q_ALLOCA_VAR(void, argument, argumentSize);
166 const int argIndex = i - 1;
167 if (argumentType.flags() & QMetaType::NeedsConstruction)
168 argumentType.construct(argument);
169
170 if (argIndex >= argc
171 || !ExecutionEngine::metaTypeFromJS(argv[argIndex], argumentType, argument)) {
172 if (!errorHandler(argumentType, argument, argIndex)) {
173 for (qsizetype j = 1; j < i; ++j) {
174 if (types[j].flags() & QMetaType::NeedsDestruction)
175 types[j].destruct(values[j]);
176 }
177 return Encode::undefined();
178 }
179 }
180
181 values[i] = argument;
182 } else {
183 values[i] = nullptr;
184 }
185 }
186
187 Q_ALLOCA_DECLARE(void, returnValue);
188 if (const qsizetype returnSize = types[0].sizeOf()) {
189 Q_ALLOCA_ASSIGN(void, returnValue, returnSize);
190 constructReturnValue(types[0], returnValue);
191 values[0] = returnValue;
192 } else {
193 values[0] = nullptr;
194 }
195
196 call(values, types, argc);
197
198 const ReturnedValue result = values[0]
199 ? convertReturnValue(engine, types[0], returnValue)
200 : Encode::undefined();
201
202 for (qsizetype i = 1, end = numTypes; i < end; ++i) {
203 if (types[i].flags() & QMetaType::NeedsDestruction)
204 types[i].destruct(values[i]);
205 }
206
207 return result;
208}
209
210template<typename Callable>
211bool convertAndCall(ExecutionEngine *engine, QObject *thisObject,
212 void **a, const QMetaType *types, int argc, Callable call)
213{
214 Scope scope(engine);
215 QV4::JSCallArguments jsCallData(scope, argc);
216
217 for (int ii = 0; ii < argc; ++ii)
218 jsCallData.args[ii] = engine->metaTypeToJS(types[ii + 1], a[ii + 1]);
219
220 ScopedObject jsThisObject(scope);
221 if (thisObject) {
222 // The result of wrap() can only be null, undefined, or an object.
223 jsThisObject = QV4::QObjectWrapper::wrap(engine, thisObject);
224 if (!jsThisObject)
225 jsThisObject = engine->globalObject;
226 } else {
227 jsThisObject = engine->globalObject;
228 }
229
230 ScopedValue jsResult(scope, call(jsThisObject, jsCallData.args, argc));
231 void *result = a[0];
232 if (!result)
233 return !jsResult->isUndefined();
234
235 const QMetaType resultType = types[0];
236 if (scope.hasException()) {
237 // Clear the return value
238 resultType.destruct(result);
239 resultType.construct(result);
240 } else if (resultType == QMetaType::fromType<QVariant>()) {
241 // When the return type is QVariant, JS objects are to be returned as
242 // QJSValue wrapped in QVariant. metaTypeFromJS unwraps them, unfortunately.
243 *static_cast<QVariant *>(result) = ExecutionEngine::toVariant(jsResult, QMetaType {});
244 } else if (!ExecutionEngine::metaTypeFromJS(jsResult, resultType, result)) {
245 // If we cannot convert, also clear the return value.
246 // The caller may have given us an uninitialized QObject*, expecting it to be overwritten.
247 resultType.destruct(result);
248 resultType.construct(result);
249 }
250 return !jsResult->isUndefined();
251}
252
253inline ReturnedValue coerce(
254 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType, bool isList);
255
256inline QObject *coerceQObject(const Value &value, const QQmlType &qmlType)
257{
258 QObject *o;
259 if (const QV4::QObjectWrapper *wrapper = value.as<QV4::QObjectWrapper>())
260 o = wrapper->object();
261 else if (const QV4::QQmlTypeWrapper *wrapper = value.as<QQmlTypeWrapper>())
262 o = wrapper->object();
263 else
264 return nullptr;
265
266 return (o && qmlobject_can_qml_cast(o, qmlType)) ? o : nullptr;
267}
268
274
275Q_QML_EXPORT void warnAboutCoercionToVoid(
276 ExecutionEngine *engine, const Value &value, CoercionProblem problem);
277
279 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType)
280{
281 QMetaType type = qmlType.qListTypeId();
282 const auto metaSequence = [&]() {
283 // TODO: We should really add the metasequence to the same QQmlType that holds
284 // all the other type information. Then we can get rid of the extra
285 // QQmlMetaType::qmlListType() here.
286 return qmlType.isSequentialContainer()
287 ? qmlType.listMetaSequence()
288 : QQmlMetaType::qmlListType(type).listMetaSequence();
289 };
290
291 if (const QV4::Sequence *sequence = value.as<QV4::Sequence>()) {
292 if (sequence->d()->listType() == type)
293 return value.asReturnedValue();
294 }
295
296 if (const QmlListWrapper *list = value.as<QmlListWrapper>()) {
297 if (list->d()->propertyType() == type)
298 return value.asReturnedValue();
299 }
300
301 QMetaType listValueType = qmlType.typeId();
302 if (!listValueType.isValid()) {
303 warnAboutCoercionToVoid(engine, value, InvalidListType);
304 return value.asReturnedValue();
305 }
306
307 QV4::Scope scope(engine);
308
309 const ArrayObject *array = value.as<ArrayObject>();
310 if (!array) {
311 return (listValueType.flags() & QMetaType::PointerToQObject)
312 ? QmlListWrapper::create(engine, listValueType)
313 : SequencePrototype::fromData(engine, type, metaSequence(), nullptr);
314 }
315
316 if (listValueType.flags() & QMetaType::PointerToQObject) {
317 QV4::Scoped<QmlListWrapper> newList(scope, QmlListWrapper::create(engine, type));
318 QQmlListProperty<QObject> *listProperty = newList->d()->property();
319
320 const qsizetype length = array->getLength();
321 qsizetype i = 0;
322 ScopedValue v(scope);
323 for (; i < length; ++i) {
324 v = array->get(i);
325 listProperty->append(listProperty, coerceQObject(v, qmlType));
326 }
327
328 return newList->asReturnedValue();
329 }
330
331 QV4::Scoped<Sequence> sequence(
332 scope, SequencePrototype::fromData(engine, type, metaSequence(), nullptr));
333 const qsizetype length = array->getLength();
334 ScopedValue v(scope);
335 for (qsizetype i = 0; i < length; ++i) {
336 v = array->get(i);
337 sequence->put(PropertyKey::fromArrayIndex(i), v);
338 }
339 return sequence->asReturnedValue();
340}
341
343 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType, bool isList)
344{
345 // These are all the named non-list, non-QObject builtins. Only those need special handling.
346 // Some of them may be wrapped in VariantObject because that is how they are stored in VME
347 // properties.
348 if (isList)
349 return coerceListType(engine, value, qmlType);
350
351 const QMetaType metaType = qmlType.typeId();
352 if (!metaType.isValid()) {
353 if (!value.isUndefined())
354 warnAboutCoercionToVoid(engine, value, InsufficientAnnotation);
355 return value.asReturnedValue();
356 }
357
358 switch (metaType.id()) {
359 case QMetaType::Void:
360 return Encode::undefined();
361 case QMetaType::QVariant:
362 return value.asReturnedValue();
363 case QMetaType::Int:
364 return Encode(value.toInt32());
365 case QMetaType::Double:
366 return value.convertedToNumber();
367 case QMetaType::QString:
368 return value.toString(engine)->asReturnedValue();
369 case QMetaType::Bool:
370 return Encode(value.toBoolean());
371 case QMetaType::QDateTime:
372 if (value.as<DateObject>())
373 return value.asReturnedValue();
374 if (const VariantObject *varObject = value.as<VariantObject>()) {
375 const QVariant &var = varObject->d()->data();
376 switch (var.metaType().id()) {
377 case QMetaType::QDateTime:
378 return engine->newDateObject(var.value<QDateTime>())->asReturnedValue();
379 case QMetaType::QTime:
380 return engine->newDateObject(var.value<QTime>(), nullptr, -1, 0)->asReturnedValue();
381 case QMetaType::QDate:
382 return engine->newDateObject(var.value<QDate>(), nullptr, -1, 0)->asReturnedValue();
383 default:
384 break;
385 }
386 }
387 return engine->newDateObject(QDateTime())->asReturnedValue();
388 case QMetaType::QUrl:
389 if (value.as<UrlObject>())
390 return value.asReturnedValue();
391 if (const VariantObject *varObject = value.as<VariantObject>()) {
392 const QVariant &var = varObject->d()->data();
393 return var.metaType() == QMetaType::fromType<QUrl>()
394 ? engine->newUrlObject(var.value<QUrl>())->asReturnedValue()
395 : engine->newUrlObject()->asReturnedValue();
396 }
397 // Since URL properties are stored as string, we need to support the string conversion here.
398 if (const String *string = value.stringValue())
399 return engine->newUrlObject(QUrl(string->toQString()))->asReturnedValue();
400 return engine->newUrlObject()->asReturnedValue();
401#if QT_CONFIG(regularexpression)
402 case QMetaType::QRegularExpression:
403 if (value.as<RegExpObject>())
404 return value.asReturnedValue();
405 if (const VariantObject *varObject = value.as<VariantObject>()) {
406 const QVariant &var = varObject->d()->data();
407 if (var.metaType() == QMetaType::fromType<QRegularExpression>())
408 return engine->newRegExpObject(var.value<QRegularExpression>())->asReturnedValue();
409 }
410 return engine->newRegExpObject(QString(), 0)->asReturnedValue();
411#endif
412 default:
413 break;
414 }
415
416 if (metaType.flags() & QMetaType::PointerToQObject) {
417 return coerceQObject(value, qmlType)
418 ? value.asReturnedValue()
419 : Encode::null();
420 }
421
422 if (const QQmlValueTypeWrapper *wrapper = value.as<QQmlValueTypeWrapper>()) {
423 if (wrapper->type() == metaType)
424 return value.asReturnedValue();
425 }
426
427 if (void *target = QQmlValueTypeProvider::heapCreateValueType(qmlType, value, engine)) {
428 Heap::QQmlValueTypeWrapper *wrapper = engine->memoryManager->allocate<QQmlValueTypeWrapper>(
429 nullptr, metaType, qmlType.metaObjectForValueType(),
430 nullptr, -1, Heap::ReferenceObject::NoFlag);
431 Q_ASSERT(!wrapper->gadgetPtr());
432 wrapper->setGadgetPtr(target);
433 return wrapper->asReturnedValue();
434 }
435
436 return Encode::undefined();
437}
438
439template<typename Callable>
441 ExecutionEngine *engine,
442 const Function::JSTypedFunction *typedFunction, const CompiledData::Function *compiledFunction,
443 const Value *argv, int argc, Callable call)
444{
445 Scope scope(engine);
446
447 QV4::JSCallArguments jsCallData(scope, typedFunction->types.size() - 1);
448 const CompiledData::Parameter *formals = compiledFunction->formalsTable();
449 for (qsizetype i = 0; i < jsCallData.argc; ++i) {
450 jsCallData.args[i] = coerce(
451 engine, i < argc ? argv[i] : QV4::Value::fromReturnedValue(Encode::undefined()),
452 typedFunction->types[i + 1], formals[i].type.isList());
453 }
454
455 ScopedValue result(scope, call(jsCallData.args, jsCallData.argc));
456 return coerce(engine, result, typedFunction->types[0], compiledFunction->returnType.isList());
457}
458
459// Note: \a to is unininitialized here! This is in contrast to most other related functions.
460inline void coerce(
461 ExecutionEngine *engine, QMetaType fromType, const void *from, QMetaType toType, void *to)
462{
463 if ((fromType.flags() & QMetaType::PointerToQObject)
464 && (toType.flags() & QMetaType::PointerToQObject)) {
465 QObject *fromObj = *static_cast<QObject * const*>(from);
466 *static_cast<QObject **>(to)
467 = (fromObj && fromObj->metaObject()->inherits(toType.metaObject()))
468 ? fromObj
469 : nullptr;
470 return;
471 }
472
473 if (toType == QMetaType::fromType<QVariant>()) {
474 new (to) QVariant(fromType, from);
475 return;
476 }
477
478 if (toType == QMetaType::fromType<QJSPrimitiveValue>()) {
479 new (to) QJSPrimitiveValue(fromType, from);
480 return;
481 }
482
483 if (fromType == QMetaType::fromType<QVariant>()) {
484 const QVariant *fromVariant = static_cast<const QVariant *>(from);
485 if (fromVariant->metaType() == toType)
486 toType.construct(to, fromVariant->data());
487 else
488 coerce(engine, fromVariant->metaType(), fromVariant->data(), toType, to);
489 return;
490 }
491
492 if (fromType == QMetaType::fromType<QJSPrimitiveValue>()) {
493 const QJSPrimitiveValue *fromPrimitive = static_cast<const QJSPrimitiveValue *>(from);
494 if (fromPrimitive->metaType() == toType)
495 toType.construct(to, fromPrimitive->data());
496 else
497 coerce(engine, fromPrimitive->metaType(), fromPrimitive->data(), toType, to);
498 return;
499 }
500
501 // TODO: This is expensive. We might establish a direct C++-to-C++ type coercion, like we have
502 // for JS-to-JS. However, we shouldn't need this very often. Most of the time the compiler
503 // will generate code that passes the right arguments.
504 if (toType.flags() & QMetaType::NeedsConstruction)
505 toType.construct(to);
506 QV4::Scope scope(engine);
507 QV4::ScopedValue value(scope, engine->fromData(fromType, from));
508 if (!ExecutionEngine::metaTypeFromJS(value, toType, to))
509 QMetaType::convert(fromType, from, toType, to);
510}
511
512template<typename TypedFunction, typename Callable>
514 ExecutionEngine *engine, const TypedFunction *typedFunction,
515 void **argv, const QMetaType *types, int argc, Callable call)
516{
517 const qsizetype numFunctionArguments = typedFunction->parameterCount();
518
519 Q_ALLOCA_DECLARE(void *, transformedArguments);
520 Q_ALLOCA_DECLARE(void, transformedResult);
521
522 const QMetaType returnType = typedFunction->returnMetaType();
523 const QMetaType frameReturn = types[0];
524 bool returnsQVariantWrapper = false;
525 if (argv[0] && returnType != frameReturn) {
526 Q_ALLOCA_ASSIGN(void *, transformedArguments, (numFunctionArguments + 1) * sizeof(void *));
527 memcpy(transformedArguments, argv, (argc + 1) * sizeof(void *));
528
529 if (frameReturn == QMetaType::fromType<QVariant>()) {
530 QVariant *returnValue = static_cast<QVariant *>(argv[0]);
531 *returnValue = QVariant(returnType);
532 transformedResult = transformedArguments[0] = returnValue->data();
533 returnsQVariantWrapper = true;
534 } else if (returnType.sizeOf() > 0) {
535 Q_ALLOCA_ASSIGN(void, transformedResult, returnType.sizeOf());
536 transformedArguments[0] = transformedResult;
537 if (returnType.flags() & QMetaType::NeedsConstruction)
538 returnType.construct(transformedResult);
539 } else {
540 transformedResult = transformedArguments[0] = &argc; // Some non-null marker value
541 }
542 }
543
544 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
545 const bool isValid = argc > i;
546 const QMetaType frameType = isValid ? types[i + 1] : QMetaType();
547
548 const QMetaType argumentType = typedFunction->parameterMetaType(i);
549 if (isValid && argumentType == frameType)
550 continue;
551
552 if (transformedArguments == nullptr) {
553 Q_ALLOCA_ASSIGN(void *, transformedArguments, (numFunctionArguments + 1) * sizeof(void *));
554 memcpy(transformedArguments, argv, (argc + 1) * sizeof(void *));
555 }
556
557 if (argumentType.sizeOf() == 0) {
558 transformedArguments[i + 1] = nullptr;
559 continue;
560 }
561
562 void *frameVal = isValid ? argv[i + 1] : nullptr;
563 if (isValid && frameType == QMetaType::fromType<QVariant>()) {
564 QVariant *variant = static_cast<QVariant *>(frameVal);
565
566 const QMetaType variantType = variant->metaType();
567 if (variantType == argumentType) {
568 // Slightly nasty, but we're allowed to do this.
569 // We don't want to destruct() the QVariant's data() below.
570 transformedArguments[i + 1] = argv[i + 1] = variant->data();
571 } else {
572 Q_ALLOCA_VAR(void, arg, argumentType.sizeOf());
573 coerce(engine, variantType, variant->constData(), argumentType, arg);
574 transformedArguments[i + 1] = arg;
575 }
576 continue;
577 }
578
579 Q_ALLOCA_VAR(void, arg, argumentType.sizeOf());
580
581 if (isValid)
582 coerce(engine, frameType, frameVal, argumentType, arg);
583 else
584 argumentType.construct(arg);
585
586 transformedArguments[i + 1] = arg;
587 }
588
589 if (!transformedArguments) {
590 call(argv, numFunctionArguments);
591 return;
592 }
593
594 call(transformedArguments, numFunctionArguments);
595
596 if (transformedResult && !returnsQVariantWrapper) {
597 if (frameReturn.sizeOf() > 0) {
598 if (frameReturn.flags() & QMetaType::NeedsDestruction)
599 frameReturn.destruct(argv[0]);
600 coerce(engine, returnType, transformedResult, frameReturn, argv[0]);
601 }
602 if (returnType.flags() & QMetaType::NeedsDestruction)
603 returnType.destruct(transformedResult);
604 }
605
606 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
607 void *arg = transformedArguments[i + 1];
608 if (arg == nullptr)
609 continue;
610 if (i >= argc || arg != argv[i + 1]) {
611 const QMetaType argumentType = typedFunction->parameterMetaType(i);
612 if (argumentType.flags() & QMetaType::NeedsDestruction)
613 argumentType.destruct(arg);
614 }
615 }
616}
617
618} // namespace QV4
619
620QT_END_NAMESPACE
621
622#endif // QV4JSCALL_H
Combined button and popup list for selecting options.
Definition qjsvalue.h:24
QObject * cppThisObject(const Value *thisObject)
ReturnedValue coerceListType(ExecutionEngine *engine, const Value &value, const QQmlType &qmlType)
void coerce(ExecutionEngine *engine, QMetaType fromType, const void *from, QMetaType toType, void *to)
@ STRING_HINT
@ PREFERREDTYPE_HINT
@ NUMBER_HINT
CoercionProblem
@ InvalidListType
@ InsufficientAnnotation
ReturnedValue coerce(ExecutionEngine *engine, const Value &value, const QQmlType &qmlType, bool isList)
void populateJSCallArguments(ExecutionEngine *v4, JSCallArguments &jsCall, int argc, void **args, const QMetaType *types)
Definition qv4jscall.cpp:19
uint Bool
ReturnedValue defaultConvertReturnValue(ExecutionEngine *engine, QMetaType returnType, void *returnValue)
Scoped< Object > ScopedObject
QObject * coerceQObject(const Value &value, const QQmlType &qmlType)
bool convertAndCall(ExecutionEngine *engine, QObject *thisObject, void **a, const QMetaType *types, int argc, Callable call)
void coerceAndCall(ExecutionEngine *engine, const TypedFunction *typedFunction, void **argv, const QMetaType *types, int argc, Callable call)
ReturnedValue coerceAndCall(ExecutionEngine *engine, const Function::JSTypedFunction *typedFunction, const CompiledData::Function *compiledFunction, const Value *argv, int argc, Callable call)
bool defaultConversionErrorHandler(QMetaType argumentType, void *argument, qsizetype i)
ReturnedValue convertAndCall(ExecutionEngine *engine, const QMetaType *types, int numTypes, const Value *argv, int argc, Callable &&call, ConstructReturnValue &&constructReturnValue=defaultConstructReturnValue, ConvertReturnValue &&convertReturnValue=defaultConvertReturnValue, ConversionErrorHandler &&errorHandler=defaultConversionErrorHandler)
Q_QML_EXPORT void warnAboutCoercionToVoid(ExecutionEngine *engine, const Value &value, CoercionProblem problem)
Definition qv4jscall.cpp:26
CallData * callDatafromJS(const Scope &scope, const Args *args, const FunctionObject *f)
Definition qv4jscall_p.h:41
void defaultConstructReturnValue(QMetaType returnType, void *returnValue)
Q_STATIC_ASSERT(sizeof(SharedImageHeader) % 4==0)
DEFINE_MANAGED_VTABLE(ArrayData)
JSCallArguments(const Scope &scope, int argc=0)
Definition qv4jscall_p.h:60
CallData * callData(const Scope &scope, const FunctionObject *f=nullptr) const
Definition qv4jscall_p.h:65
const int argc
Definition qv4jscall_p.h:94
CallData * callData(const Scope &scope, const FunctionObject *f=nullptr) const
Definition qv4jscall_p.h:87
const Value * thisObject
Definition qv4jscall_p.h:92
JSCallData(const Value *thisObject, const Value *argv, int argc)
Definition qv4jscall_p.h:77
const Value * args
Definition qv4jscall_p.h:93
static PropertyKey fromArrayIndex(uint idx)
Scope(ExecutionEngine *e)
ScopedValue(const Scope &scope)
const SparseArrayNode * end() const