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_INIT();
161 Q_ALLOCA_VAR(void *, values, numTypes * sizeof(void *));
162
163 for (qsizetype i = 1; i < numTypes; ++i) {
164 const QMetaType argumentType = types[i];
165 if (const qsizetype argumentSize = argumentType.sizeOf()) {
166 Q_ALLOCA_VAR(void, argument, argumentSize);
167 const int argIndex = i - 1;
168 if (argumentType.flags() & QMetaType::NeedsConstruction)
169 argumentType.construct(argument);
170
171 if (argIndex >= argc
172 || !ExecutionEngine::metaTypeFromJS(argv[argIndex], argumentType, argument)) {
173 if (!errorHandler(argumentType, argument, argIndex)) {
174 for (qsizetype j = 1; j < i; ++j) {
175 if (types[j].flags() & QMetaType::NeedsDestruction)
176 types[j].destruct(values[j]);
177 }
178 return Encode::undefined();
179 }
180 }
181
182 values[i] = argument;
183 } else {
184 values[i] = nullptr;
185 }
186 }
187
188 Q_ALLOCA_DECLARE(void, returnValue);
189 if (const qsizetype returnSize = types[0].sizeOf()) {
190 Q_ALLOCA_ASSIGN(void, returnValue, returnSize);
191 constructReturnValue(types[0], returnValue);
192 values[0] = returnValue;
193 } else {
194 values[0] = nullptr;
195 }
196
197 call(values, types, argc);
198
199 const ReturnedValue result = values[0]
200 ? convertReturnValue(engine, types[0], returnValue)
201 : Encode::undefined();
202
203 for (qsizetype i = 1, end = numTypes; i < end; ++i) {
204 if (types[i].flags() & QMetaType::NeedsDestruction)
205 types[i].destruct(values[i]);
206 }
207
208 return result;
209}
210
211template<typename Callable>
212bool convertAndCall(ExecutionEngine *engine, QObject *thisObject,
213 void **a, const QMetaType *types, int argc, Callable call)
214{
215 Scope scope(engine);
216 QV4::JSCallArguments jsCallData(scope, argc);
217
218 for (int ii = 0; ii < argc; ++ii)
219 jsCallData.args[ii] = engine->metaTypeToJS(types[ii + 1], a[ii + 1]);
220
221 ScopedObject jsThisObject(scope);
222 if (thisObject) {
223 // The result of wrap() can only be null, undefined, or an object.
224 jsThisObject = QV4::QObjectWrapper::wrap(engine, thisObject);
225 if (!jsThisObject)
226 jsThisObject = engine->globalObject;
227 } else {
228 jsThisObject = engine->globalObject;
229 }
230
231 ScopedValue jsResult(scope, call(jsThisObject, jsCallData.args, argc));
232 void *result = a[0];
233 if (!result)
234 return !jsResult->isUndefined();
235
236 const QMetaType resultType = types[0];
237 if (scope.hasException()) {
238 // Clear the return value
239 resultType.destruct(result);
240 resultType.construct(result);
241 } else if (resultType == QMetaType::fromType<QVariant>()) {
242 // When the return type is QVariant, JS objects are to be returned as
243 // QJSValue wrapped in QVariant. metaTypeFromJS unwraps them, unfortunately.
244 *static_cast<QVariant *>(result) = ExecutionEngine::toVariant(jsResult, QMetaType {});
245 } else if (!ExecutionEngine::metaTypeFromJS(jsResult, resultType, result)) {
246 // If we cannot convert, also clear the return value.
247 // The caller may have given us an uninitialized QObject*, expecting it to be overwritten.
248 resultType.destruct(result);
249 resultType.construct(result);
250 }
251 return !jsResult->isUndefined();
252}
253
254inline ReturnedValue coerce(
255 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType, bool isList);
256
257inline QObject *coerceQObject(const Value &value, const QQmlType &qmlType)
258{
259 QObject *o;
260 if (const QV4::QObjectWrapper *wrapper = value.as<QV4::QObjectWrapper>())
261 o = wrapper->object();
262 else if (const QV4::QQmlTypeWrapper *wrapper = value.as<QQmlTypeWrapper>())
263 o = wrapper->object();
264 else
265 return nullptr;
266
267 return (o && qmlobject_can_qml_cast(o, qmlType)) ? o : nullptr;
268}
269
275
276Q_QML_EXPORT void warnAboutCoercionToVoid(
277 ExecutionEngine *engine, const Value &value, CoercionProblem problem);
278
280 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType)
281{
282 QMetaType type = qmlType.qListTypeId();
283 const auto metaSequence = [&]() {
284 // TODO: We should really add the metasequence to the same QQmlType that holds
285 // all the other type information. Then we can get rid of the extra
286 // QQmlMetaType::qmlListType() here.
287 return qmlType.isSequentialContainer()
288 ? qmlType.listMetaSequence()
289 : QQmlMetaType::qmlListType(type).listMetaSequence();
290 };
291
292 if (const QV4::Sequence *sequence = value.as<QV4::Sequence>()) {
293 if (sequence->d()->listType() == type)
294 return value.asReturnedValue();
295 }
296
297 if (const QmlListWrapper *list = value.as<QmlListWrapper>()) {
298 if (list->d()->propertyType() == type)
299 return value.asReturnedValue();
300 }
301
302 QMetaType listValueType = qmlType.typeId();
303 if (!listValueType.isValid()) {
304 warnAboutCoercionToVoid(engine, value, InvalidListType);
305 return value.asReturnedValue();
306 }
307
308 QV4::Scope scope(engine);
309
310 const ArrayObject *array = value.as<ArrayObject>();
311 if (!array) {
312 return (listValueType.flags() & QMetaType::PointerToQObject)
313 ? QmlListWrapper::create(engine, listValueType)
314 : SequencePrototype::fromData(engine, type, metaSequence(), nullptr);
315 }
316
317 if (listValueType.flags() & QMetaType::PointerToQObject) {
318 QV4::Scoped<QmlListWrapper> newList(scope, QmlListWrapper::create(engine, type));
319 QQmlListProperty<QObject> *listProperty = newList->d()->property();
320
321 const qsizetype length = array->getLength();
322 qsizetype i = 0;
323 ScopedValue v(scope);
324 for (; i < length; ++i) {
325 v = array->get(i);
326 listProperty->append(listProperty, coerceQObject(v, qmlType));
327 }
328
329 return newList->asReturnedValue();
330 }
331
332 QV4::Scoped<Sequence> sequence(
333 scope, SequencePrototype::fromData(engine, type, metaSequence(), nullptr));
334 const qsizetype length = array->getLength();
335 ScopedValue v(scope);
336 for (qsizetype i = 0; i < length; ++i) {
337 v = array->get(i);
338 sequence->put(PropertyKey::fromArrayIndex(i), v);
339 }
340 return sequence->asReturnedValue();
341}
342
344 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType, bool isList)
345{
346 // These are all the named non-list, non-QObject builtins. Only those need special handling.
347 // Some of them may be wrapped in VariantObject because that is how they are stored in VME
348 // properties.
349 if (isList)
350 return coerceListType(engine, value, qmlType);
351
352 const QMetaType metaType = qmlType.typeId();
353 if (!metaType.isValid()) {
354 if (!value.isUndefined())
355 warnAboutCoercionToVoid(engine, value, InsufficientAnnotation);
356 return value.asReturnedValue();
357 }
358
359 switch (metaType.id()) {
360 case QMetaType::Void:
361 return Encode::undefined();
362 case QMetaType::QVariant:
363 return value.asReturnedValue();
364 case QMetaType::Int:
365 return Encode(value.toInt32());
366 case QMetaType::Double:
367 return value.convertedToNumber();
368 case QMetaType::QString:
369 return value.toString(engine)->asReturnedValue();
370 case QMetaType::Bool:
371 return Encode(value.toBoolean());
372 case QMetaType::QDateTime:
373 if (value.as<DateObject>())
374 return value.asReturnedValue();
375 if (const VariantObject *varObject = value.as<VariantObject>()) {
376 const QVariant &var = varObject->d()->data();
377 switch (var.metaType().id()) {
378 case QMetaType::QDateTime:
379 return engine->newDateObject(var.value<QDateTime>())->asReturnedValue();
380 case QMetaType::QTime:
381 return engine->newDateObject(var.value<QTime>(), nullptr, -1, 0)->asReturnedValue();
382 case QMetaType::QDate:
383 return engine->newDateObject(var.value<QDate>(), nullptr, -1, 0)->asReturnedValue();
384 default:
385 break;
386 }
387 }
388 return engine->newDateObject(QDateTime())->asReturnedValue();
389 case QMetaType::QUrl:
390 if (value.as<UrlObject>())
391 return value.asReturnedValue();
392 if (const VariantObject *varObject = value.as<VariantObject>()) {
393 const QVariant &var = varObject->d()->data();
394 return var.metaType() == QMetaType::fromType<QUrl>()
395 ? engine->newUrlObject(var.value<QUrl>())->asReturnedValue()
396 : engine->newUrlObject()->asReturnedValue();
397 }
398 // Since URL properties are stored as string, we need to support the string conversion here.
399 if (const String *string = value.stringValue())
400 return engine->newUrlObject(QUrl(string->toQString()))->asReturnedValue();
401 return engine->newUrlObject()->asReturnedValue();
402#if QT_CONFIG(regularexpression)
403 case QMetaType::QRegularExpression:
404 if (value.as<RegExpObject>())
405 return value.asReturnedValue();
406 if (const VariantObject *varObject = value.as<VariantObject>()) {
407 const QVariant &var = varObject->d()->data();
408 if (var.metaType() == QMetaType::fromType<QRegularExpression>())
409 return engine->newRegExpObject(var.value<QRegularExpression>())->asReturnedValue();
410 }
411 return engine->newRegExpObject(QString(), 0)->asReturnedValue();
412#endif
413 default:
414 break;
415 }
416
417 if (metaType.flags() & QMetaType::PointerToQObject) {
418 return coerceQObject(value, qmlType)
419 ? value.asReturnedValue()
420 : Encode::null();
421 }
422
423 if (const QQmlValueTypeWrapper *wrapper = value.as<QQmlValueTypeWrapper>()) {
424 if (wrapper->type() == metaType)
425 return value.asReturnedValue();
426 }
427
428 if (void *target = QQmlValueTypeProvider::heapCreateValueType(qmlType, value, engine)) {
429 Heap::QQmlValueTypeWrapper *wrapper = engine->memoryManager->allocate<QQmlValueTypeWrapper>(
430 nullptr, metaType, qmlType.metaObjectForValueType(),
431 nullptr, -1, Heap::ReferenceObject::NoFlag);
432 Q_ASSERT(!wrapper->gadgetPtr());
433 wrapper->setGadgetPtr(target);
434 return wrapper->asReturnedValue();
435 }
436
437 return Encode::undefined();
438}
439
440template<typename Callable>
442 ExecutionEngine *engine,
443 const Function::JSTypedFunction *typedFunction, const CompiledData::Function *compiledFunction,
444 const Value *argv, int argc, Callable call)
445{
446 Scope scope(engine);
447
448 QV4::JSCallArguments jsCallData(scope, typedFunction->types.size() - 1);
449 const CompiledData::Parameter *formals = compiledFunction->formalsTable();
450 for (qsizetype i = 0; i < jsCallData.argc; ++i) {
451 jsCallData.args[i] = coerce(
452 engine, i < argc ? argv[i] : QV4::Value::fromReturnedValue(Encode::undefined()),
453 typedFunction->types[i + 1], formals[i].type.isList());
454 }
455
456 ScopedValue result(scope, call(jsCallData.args, jsCallData.argc));
457 return coerce(engine, result, typedFunction->types[0], compiledFunction->returnType.isList());
458}
459
460// Note: \a to is unininitialized here! This is in contrast to most other related functions.
461inline void coerce(
462 ExecutionEngine *engine, QMetaType fromType, const void *from, QMetaType toType, void *to)
463{
464 if ((fromType.flags() & QMetaType::PointerToQObject)
465 && (toType.flags() & QMetaType::PointerToQObject)) {
466 QObject *fromObj = *static_cast<QObject * const*>(from);
467 *static_cast<QObject **>(to)
468 = (fromObj && fromObj->metaObject()->inherits(toType.metaObject()))
469 ? fromObj
470 : nullptr;
471 return;
472 }
473
474 if (toType == QMetaType::fromType<QVariant>()) {
475 new (to) QVariant(fromType, from);
476 return;
477 }
478
479 if (toType == QMetaType::fromType<QJSPrimitiveValue>()) {
480 new (to) QJSPrimitiveValue(fromType, from);
481 return;
482 }
483
484 if (fromType == QMetaType::fromType<QVariant>()) {
485 const QVariant *fromVariant = static_cast<const QVariant *>(from);
486 if (fromVariant->metaType() == toType)
487 toType.construct(to, fromVariant->data());
488 else
489 coerce(engine, fromVariant->metaType(), fromVariant->data(), toType, to);
490 return;
491 }
492
493 if (fromType == QMetaType::fromType<QJSPrimitiveValue>()) {
494 const QJSPrimitiveValue *fromPrimitive = static_cast<const QJSPrimitiveValue *>(from);
495 if (fromPrimitive->metaType() == toType)
496 toType.construct(to, fromPrimitive->data());
497 else
498 coerce(engine, fromPrimitive->metaType(), fromPrimitive->data(), toType, to);
499 return;
500 }
501
502 // TODO: This is expensive. We might establish a direct C++-to-C++ type coercion, like we have
503 // for JS-to-JS. However, we shouldn't need this very often. Most of the time the compiler
504 // will generate code that passes the right arguments.
505 if (toType.flags() & QMetaType::NeedsConstruction)
506 toType.construct(to);
507 QV4::Scope scope(engine);
508 QV4::ScopedValue value(scope, engine->fromData(fromType, from));
509 if (!ExecutionEngine::metaTypeFromJS(value, toType, to))
510 QMetaType::convert(fromType, from, toType, to);
511}
512
513template<typename TypedFunction, typename Callable>
515 ExecutionEngine *engine, const TypedFunction *typedFunction,
516 void **argv, const QMetaType *types, int argc, Callable call)
517{
518 Q_ALLOCA_INIT();
519 const qsizetype numFunctionArguments = typedFunction->parameterCount();
520
521 Q_ALLOCA_DECLARE(void *, transformedArguments);
522 Q_ALLOCA_DECLARE(void, transformedResult);
523
524 const QMetaType returnType = typedFunction->returnMetaType();
525 const QMetaType frameReturn = types[0];
526 bool returnsQVariantWrapper = false;
527 if (argv[0] && returnType != frameReturn) {
528 Q_ALLOCA_ASSIGN(void *, transformedArguments, (numFunctionArguments + 1) * sizeof(void *));
529 memcpy(transformedArguments, argv, (argc + 1) * sizeof(void *));
530
531 if (frameReturn == QMetaType::fromType<QVariant>()) {
532 QVariant *returnValue = static_cast<QVariant *>(argv[0]);
533 *returnValue = QVariant(returnType);
534 transformedResult = transformedArguments[0] = returnValue->data();
535 returnsQVariantWrapper = true;
536 } else if (returnType.sizeOf() > 0) {
537 Q_ALLOCA_ASSIGN(void, transformedResult, returnType.sizeOf());
538 transformedArguments[0] = transformedResult;
539 if (returnType.flags() & QMetaType::NeedsConstruction)
540 returnType.construct(transformedResult);
541 } else {
542 transformedResult = transformedArguments[0] = &argc; // Some non-null marker value
543 }
544 }
545
546 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
547 const bool isValid = argc > i;
548 const QMetaType frameType = isValid ? types[i + 1] : QMetaType();
549
550 const QMetaType argumentType = typedFunction->parameterMetaType(i);
551 if (isValid && argumentType == frameType)
552 continue;
553
554 if (transformedArguments == nullptr) {
555 Q_ALLOCA_ASSIGN(void *, transformedArguments, (numFunctionArguments + 1) * sizeof(void *));
556 memcpy(transformedArguments, argv, (argc + 1) * sizeof(void *));
557 }
558
559 if (argumentType.sizeOf() == 0) {
560 transformedArguments[i + 1] = nullptr;
561 continue;
562 }
563
564 void *frameVal = isValid ? argv[i + 1] : nullptr;
565 if (isValid && frameType == QMetaType::fromType<QVariant>()) {
566 QVariant *variant = static_cast<QVariant *>(frameVal);
567
568 const QMetaType variantType = variant->metaType();
569 if (variantType == argumentType) {
570 // Slightly nasty, but we're allowed to do this.
571 // We don't want to destruct() the QVariant's data() below.
572 transformedArguments[i + 1] = argv[i + 1] = variant->data();
573 } else {
574 Q_ALLOCA_VAR(void, arg, argumentType.sizeOf());
575 coerce(engine, variantType, variant->constData(), argumentType, arg);
576 transformedArguments[i + 1] = arg;
577 }
578 continue;
579 }
580
581 Q_ALLOCA_VAR(void, arg, argumentType.sizeOf());
582
583 if (isValid)
584 coerce(engine, frameType, frameVal, argumentType, arg);
585 else
586 argumentType.construct(arg);
587
588 transformedArguments[i + 1] = arg;
589 }
590
591 if (!transformedArguments) {
592 call(argv, numFunctionArguments);
593 return;
594 }
595
596 call(transformedArguments, numFunctionArguments);
597
598 if (transformedResult && !returnsQVariantWrapper) {
599 if (frameReturn.sizeOf() > 0) {
600 if (frameReturn.flags() & QMetaType::NeedsDestruction)
601 frameReturn.destruct(argv[0]);
602 coerce(engine, returnType, transformedResult, frameReturn, argv[0]);
603 }
604 if (returnType.flags() & QMetaType::NeedsDestruction)
605 returnType.destruct(transformedResult);
606 }
607
608 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
609 void *arg = transformedArguments[i + 1];
610 if (arg == nullptr)
611 continue;
612 if (i >= argc || arg != argv[i + 1]) {
613 const QMetaType argumentType = typedFunction->parameterMetaType(i);
614 if (argumentType.flags() & QMetaType::NeedsDestruction)
615 argumentType.destruct(arg);
616 }
617 }
618}
619
620} // namespace QV4
621
622QT_END_NAMESPACE
623
624#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