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
112template<typename Callable>
114 ExecutionEngine *engine, const Function::AOTCompiledFunction *aotFunction,
115 const Value *thisObject, const Value *argv, int argc, Callable call)
116{
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));
120
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);
128 if (i < argc)
129 ExecutionEngine::metaTypeFromJS(argv[i], argumentType, argument);
130 } else if (i >= argc
131 || !ExecutionEngine::metaTypeFromJS(argv[i], argumentType, argument)) {
132 // If we can't convert the argument, we need to default-construct it even if it
133 // doesn't formally need construction.
134 // E.g. an int doesn't need construction, but we still want it to be 0.
135 argumentType.construct(argument);
136 }
137
138 values[i + 1] = argument;
139 } else {
140 values[i + 1] = nullptr;
141 }
142 }
143
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);
151 } else {
152 values[0] = nullptr;
153 }
154
155 if (const QV4::QObjectWrapper *cppThisObject = thisObject
156 ? thisObject->as<QV4::QObjectWrapper>()
157 : nullptr) {
158 call(cppThisObject->object(), values, types, argc);
159 } else {
160 call(nullptr, values, types, argc);
161 }
162
163 ReturnedValue result;
164 if (values[0]) {
165 result = engine->metaTypeToJS(types[0], values[0]);
166 if (types[0].flags() & QMetaType::NeedsDestruction)
167 types[0].destruct(values[0]);
168 } else {
169 result = Encode::undefined();
170 }
171
172 for (qsizetype i = 1, end = numFunctionArguments + 1; i < end; ++i) {
173 if (types[i].flags() & QMetaType::NeedsDestruction)
174 types[i].destruct(values[i]);
175 }
176
177 return result;
178}
179
180template<typename Callable>
181bool convertAndCall(ExecutionEngine *engine, QObject *thisObject,
182 void **a, const QMetaType *types, int argc, Callable call)
183{
184 Scope scope(engine);
185 QV4::JSCallArguments jsCallData(scope, argc);
186
187 for (int ii = 0; ii < argc; ++ii)
188 jsCallData.args[ii] = engine->metaTypeToJS(types[ii + 1], a[ii + 1]);
189
190 ScopedObject jsThisObject(scope);
191 if (thisObject) {
192 // The result of wrap() can only be null, undefined, or an object.
193 jsThisObject = QV4::QObjectWrapper::wrap(engine, thisObject);
194 if (!jsThisObject)
195 jsThisObject = engine->globalObject;
196 } else {
197 jsThisObject = engine->globalObject;
198 }
199
200 ScopedValue jsResult(scope, call(jsThisObject, jsCallData.args, argc));
201 void *result = a[0];
202 if (!result)
203 return !jsResult->isUndefined();
204
205 const QMetaType resultType = types[0];
206 if (scope.hasException()) {
207 // Clear the return value
208 resultType.destruct(result);
209 resultType.construct(result);
210 } else if (resultType == QMetaType::fromType<QVariant>()) {
211 // When the return type is QVariant, JS objects are to be returned as
212 // QJSValue wrapped in QVariant. metaTypeFromJS unwraps them, unfortunately.
213 *static_cast<QVariant *>(result) = ExecutionEngine::toVariant(jsResult, QMetaType {});
214 } else if (!ExecutionEngine::metaTypeFromJS(jsResult, resultType, result)) {
215 // If we cannot convert, also clear the return value.
216 // The caller may have given us an uninitialized QObject*, expecting it to be overwritten.
217 resultType.destruct(result);
218 resultType.construct(result);
219 }
220 return !jsResult->isUndefined();
221}
222
223inline ReturnedValue coerce(
224 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType, bool isList);
225
226inline QObject *coerceQObject(const Value &value, const QQmlType &qmlType)
227{
228 QObject *o;
229 if (const QV4::QObjectWrapper *wrapper = value.as<QV4::QObjectWrapper>())
230 o = wrapper->object();
231 else if (const QV4::QQmlTypeWrapper *wrapper = value.as<QQmlTypeWrapper>())
232 o = wrapper->object();
233 else
234 return nullptr;
235
236 return (o && qmlobject_can_qml_cast(o, qmlType)) ? o : nullptr;
237}
238
244
245Q_QML_EXPORT void warnAboutCoercionToVoid(
246 ExecutionEngine *engine, const Value &value, CoercionProblem problem);
247
249 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType)
250{
251 QMetaType type = qmlType.qListTypeId();
252 const auto metaSequence = [&]() {
253 // TODO: We should really add the metasequence to the same QQmlType that holds
254 // all the other type information. Then we can get rid of the extra
255 // QQmlMetaType::qmlListType() here.
256 return qmlType.isSequentialContainer()
257 ? qmlType.listMetaSequence()
258 : QQmlMetaType::qmlListType(type).listMetaSequence();
259 };
260
261 if (const QV4::Sequence *sequence = value.as<QV4::Sequence>()) {
262 if (sequence->d()->listType() == type)
263 return value.asReturnedValue();
264 }
265
266 if (const QmlListWrapper *list = value.as<QmlListWrapper>()) {
267 if (list->d()->propertyType() == type)
268 return value.asReturnedValue();
269 }
270
271 QMetaType listValueType = qmlType.typeId();
272 if (!listValueType.isValid()) {
273 warnAboutCoercionToVoid(engine, value, InvalidListType);
274 return value.asReturnedValue();
275 }
276
277 QV4::Scope scope(engine);
278
279 const ArrayObject *array = value.as<ArrayObject>();
280 if (!array) {
281 return (listValueType.flags() & QMetaType::PointerToQObject)
282 ? QmlListWrapper::create(engine, listValueType)
283 : SequencePrototype::fromData(engine, type, metaSequence(), nullptr);
284 }
285
286 if (listValueType.flags() & QMetaType::PointerToQObject) {
287 QV4::Scoped<QmlListWrapper> newList(scope, QmlListWrapper::create(engine, type));
288 QQmlListProperty<QObject> *listProperty = newList->d()->property();
289
290 const qsizetype length = array->getLength();
291 qsizetype i = 0;
292 ScopedValue v(scope);
293 for (; i < length; ++i) {
294 v = array->get(i);
295 listProperty->append(listProperty, coerceQObject(v, qmlType));
296 }
297
298 return newList->asReturnedValue();
299 }
300
301 QV4::Scoped<Sequence> sequence(
302 scope, SequencePrototype::fromData(engine, type, metaSequence(), nullptr));
303 const qsizetype length = array->getLength();
304 ScopedValue v(scope);
305 for (qsizetype i = 0; i < length; ++i) {
306 v = array->get(i);
307 sequence->put(PropertyKey::fromArrayIndex(i), v);
308 }
309 return sequence->asReturnedValue();
310}
311
313 ExecutionEngine *engine, const Value &value, const QQmlType &qmlType, bool isList)
314{
315 // These are all the named non-list, non-QObject builtins. Only those need special handling.
316 // Some of them may be wrapped in VariantObject because that is how they are stored in VME
317 // properties.
318 if (isList)
319 return coerceListType(engine, value, qmlType);
320
321 const QMetaType metaType = qmlType.typeId();
322 if (!metaType.isValid()) {
323 if (!value.isUndefined())
324 warnAboutCoercionToVoid(engine, value, InsufficientAnnotation);
325 return value.asReturnedValue();
326 }
327
328 switch (metaType.id()) {
329 case QMetaType::Void:
330 return Encode::undefined();
331 case QMetaType::QVariant:
332 return value.asReturnedValue();
333 case QMetaType::Int:
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:
342 if (value.as<DateObject>())
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();
353 default:
354 break;
355 }
356 }
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();
366 }
367 // Since URL properties are stored as string, we need to support the string conversion here.
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();
379 }
380 return engine->newRegExpObject(QString(), 0)->asReturnedValue();
381#endif
382 default:
383 break;
384 }
385
386 if (metaType.flags() & QMetaType::PointerToQObject) {
387 return coerceQObject(value, qmlType)
388 ? value.asReturnedValue()
389 : Encode::null();
390 }
391
392 if (const QQmlValueTypeWrapper *wrapper = value.as<QQmlValueTypeWrapper>()) {
393 if (wrapper->type() == metaType)
394 return value.asReturnedValue();
395 }
396
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();
404 }
405
406 return Encode::undefined();
407}
408
409template<typename Callable>
411 ExecutionEngine *engine,
412 const Function::JSTypedFunction *typedFunction, const CompiledData::Function *compiledFunction,
413 const Value *argv, int argc, Callable call)
414{
415 Scope scope(engine);
416
417 QV4::JSCallArguments jsCallData(scope, typedFunction->types.size() - 1);
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());
423 }
424
425 ScopedValue result(scope, call(jsCallData.args, jsCallData.argc));
426 return coerce(engine, result, typedFunction->types[0], compiledFunction->returnType.isList());
427}
428
429// Note: \a to is unininitialized here! This is in contrast to most other related functions.
430inline void coerce(
431 ExecutionEngine *engine, QMetaType fromType, const void *from, QMetaType toType, void *to)
432{
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()))
438 ? fromObj
439 : nullptr;
440 return;
441 }
442
443 if (toType == QMetaType::fromType<QVariant>()) {
444 new (to) QVariant(fromType, from);
445 return;
446 }
447
448 if (toType == QMetaType::fromType<QJSPrimitiveValue>()) {
449 new (to) QJSPrimitiveValue(fromType, from);
450 return;
451 }
452
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());
457 else
458 coerce(engine, fromVariant->metaType(), fromVariant->data(), toType, to);
459 return;
460 }
461
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());
466 else
467 coerce(engine, fromPrimitive->metaType(), fromPrimitive->data(), toType, to);
468 return;
469 }
470
471 // TODO: This is expensive. We might establish a direct C++-to-C++ type coercion, like we have
472 // for JS-to-JS. However, we shouldn't need this very often. Most of the time the compiler
473 // will generate code that passes the right arguments.
474 if (toType.flags() & QMetaType::NeedsConstruction)
475 toType.construct(to);
476 QV4::Scope scope(engine);
477 QV4::ScopedValue value(scope, engine->fromData(fromType, from));
478 if (!ExecutionEngine::metaTypeFromJS(value, toType, to))
479 QMetaType::convert(fromType, from, toType, to);
480}
481
482template<typename TypedFunction, typename Callable>
484 ExecutionEngine *engine, const TypedFunction *typedFunction,
485 void **argv, const QMetaType *types, int argc, Callable call)
486{
487 const qsizetype numFunctionArguments = typedFunction->parameterCount();
488
489 Q_ALLOCA_DECLARE(void *, transformedArguments);
490 Q_ALLOCA_DECLARE(void, transformedResult);
491
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 *));
498
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);
509 } else {
510 transformedResult = transformedArguments[0] = &argc; // Some non-null marker value
511 }
512 }
513
514 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
515 const bool isValid = argc > i;
516 const QMetaType frameType = isValid ? types[i + 1] : QMetaType();
517
518 const QMetaType argumentType = typedFunction->parameterMetaType(i);
519 if (isValid && argumentType == frameType)
520 continue;
521
522 if (transformedArguments == nullptr) {
523 Q_ALLOCA_ASSIGN(void *, transformedArguments, (numFunctionArguments + 1) * sizeof(void *));
524 memcpy(transformedArguments, argv, (argc + 1) * sizeof(void *));
525 }
526
527 if (argumentType.sizeOf() == 0) {
528 transformedArguments[i + 1] = nullptr;
529 continue;
530 }
531
532 void *frameVal = isValid ? argv[i + 1] : nullptr;
533 if (isValid && frameType == QMetaType::fromType<QVariant>()) {
534 QVariant *variant = static_cast<QVariant *>(frameVal);
535
536 const QMetaType variantType = variant->metaType();
537 if (variantType == argumentType) {
538 // Slightly nasty, but we're allowed to do this.
539 // We don't want to destruct() the QVariant's data() below.
540 transformedArguments[i + 1] = argv[i + 1] = variant->data();
541 } else {
542 Q_ALLOCA_VAR(void, arg, argumentType.sizeOf());
543 coerce(engine, variantType, variant->constData(), argumentType, arg);
544 transformedArguments[i + 1] = arg;
545 }
546 continue;
547 }
548
549 Q_ALLOCA_VAR(void, arg, argumentType.sizeOf());
550
551 if (isValid)
552 coerce(engine, frameType, frameVal, argumentType, arg);
553 else
554 argumentType.construct(arg);
555
556 transformedArguments[i + 1] = arg;
557 }
558
559 if (!transformedArguments) {
560 call(argv, numFunctionArguments);
561 return;
562 }
563
564 call(transformedArguments, numFunctionArguments);
565
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]);
571 }
572 if (returnType.flags() & QMetaType::NeedsDestruction)
573 returnType.destruct(transformedResult);
574 }
575
576 for (qsizetype i = 0; i < numFunctionArguments; ++i) {
577 void *arg = transformedArguments[i + 1];
578 if (arg == nullptr)
579 continue;
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);
584 }
585 }
586}
587
588} // namespace QV4
589
590QT_END_NAMESPACE
591
592#endif // QV4JSCALL_H
Definition qjsvalue.h:23
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
ReturnedValue convertAndCall(ExecutionEngine *engine, const Function::AOTCompiledFunction *aotFunction, const Value *thisObject, const Value *argv, int argc, Callable call)
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
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)
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
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