Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qv4engine_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 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#ifndef QV4ENGINE_H
4#define QV4ENGINE_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <private/qintrusivelist_p.h>
18#include <private/qqmldelayedcallqueue_p.h>
19#include <private/qqmlrefcount_p.h>
20#include <private/qv4compileddata_p.h>
21#include <private/qv4context_p.h>
22#include <private/qv4enginebase_p.h>
23#include <private/qv4executablecompilationunit_p.h>
24#include <private/qv4function_p.h>
25#include <private/qv4global_p.h>
26#include <private/qv4stacklimits_p.h>
27
28#include <QtCore/qelapsedtimer.h>
29#include <QtCore/qmutex.h>
30#include <QtCore/qprocessordetection.h>
31#include <QtCore/qset.h>
32
33namespace WTF {
34class BumpPointerAllocator;
35class PageAllocation;
36}
37
38#define V4_DEFINE_EXTENSION(dataclass, datafunction) \
39 static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
40 { \
41 static int extensionId = -1; \
42 if (extensionId == -1) { \
43 QV4::ExecutionEngine::registrationMutex()->lock(); \
44 if (extensionId == -1) \
45 extensionId = QV4::ExecutionEngine::registerExtension(); \
46 QV4::ExecutionEngine::registrationMutex()->unlock(); \
47 } \
48 dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
49 if (!rv) { \
50 rv = new dataclass(engine); \
51 engine->setExtensionData(extensionId, rv); \
52 } \
53 return rv; \
54 } \
55
56
58
59#if QT_CONFIG(qml_network)
61
62namespace QV4 {
63struct QObjectMethod;
64namespace detail {
65QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine);
66}
67}
68#else
69namespace QV4 { struct QObjectMethod; }
70#endif // qml_network
71
72// Used to allow a QObject method take and return raw V4 handles without having to expose
73// 48 in the public API.
74// Use like this:
75// class MyClass : public QObject {
76// Q_OBJECT
77// ...
78// Q_INVOKABLE void myMethod(QQmlV4Function*);
79// };
80// The QQmlV8Function - and consequently the arguments and return value - only remains
81// valid during the call. If the return value isn't set within myMethod(), the will return
82// undefined.
83
85{
86public:
87 int length() const { return callData->argc(); }
88 QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
89 void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
90 QV4::ExecutionEngine *v4engine() const { return e; }
91private:
92 friend struct QV4::QObjectMethod;
95 QQmlV4Function &operator=(const QQmlV4Function &);
96
98 : callData(callData), retVal(retVal), e(e)
99 {
101 }
102
103 QV4::CallData *callData;
104 QV4::Value *retVal;
106};
107
108class QQmlError;
109class QJSEngine;
110class QQmlEngine;
111class QQmlContextData;
112
113namespace QV4 {
114namespace Debugging {
115class Debugger;
116} // namespace Debugging
117namespace Profiling {
118class Profiler;
119} // namespace Profiling
120namespace CompiledData {
121struct CompilationUnit;
122}
123
124namespace Heap {
125struct Module;
126};
127
128struct Function;
129
130namespace Promise {
131class ReactionHandler;
132};
133
134struct Q_QML_EXPORT ExecutionEngine : public EngineBase
135{
136private:
137 friend struct ExecutionContextSaver;
138 friend struct ExecutionContext;
139 friend struct Heap::ExecutionContext;
140public:
141 enum class DiskCache {
142 Disabled = 0,
143 AotByteCode = 1 << 0,
144 AotNative = 1 << 1,
145 QmlcRead = 1 << 2,
146 QmlcWrite = 1 << 3,
147 Aot = AotByteCode | AotNative,
148 Qmlc = QmlcRead | QmlcWrite,
149 Enabled = Aot | Qmlc,
150
151 };
152
153 Q_DECLARE_FLAGS(DiskCacheOptions, DiskCache);
154
157
158 WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
159
160 WTF::PageAllocation *jsStack;
161
162 WTF::PageAllocation *gcStack;
163
165 Value *ptr = jsStackTop;
166 jsStackTop = ptr + nValues;
167 return ptr;
168 }
169
171
172 QJSEngine *jsEngine() const { return publicEngine; }
173 QQmlEngine *qmlEngine() const { return m_qmlEngine; }
175
179 IntegerNull, // Has to come after the RootContext to make the context stack safe
220
249
251
255 NJSObjects
256 };
258 enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
259
260 ExecutionContext *rootContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + RootContext); }
261 ExecutionContext *scriptContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + ScriptContext); }
262 void setScriptContext(ReturnedValue c) { jsObjects[ScriptContext] = c; }
263 FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
264 FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
265 FunctionObject *symbolCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Symbol_Ctor); }
266 FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
267 FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
268 FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
269 FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
270 FunctionObject *generatorFunctionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + GeneratorFunction_Ctor); }
271 FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
272 FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
273 FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
274 FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
275 FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
276 FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
277 FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
278 FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
279 FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
280 FunctionObject *sharedArrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SharedArrayBuffer_Ctor); }
281 FunctionObject *promiseCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Promise_Ctor); }
282 FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
283 FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
284 FunctionObject *weakSetCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakSet_Ctor); }
285 FunctionObject *setCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Set_Ctor); }
286 FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
287 FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
288 FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
290 {
291 return reinterpret_cast<FunctionObject *>(jsObjects + Url_Ctor);
292 }
294 {
295 return reinterpret_cast<FunctionObject *>(jsObjects + UrlSearchParams_Ctor);
296 }
298
299 FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
300
301 Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
302 Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); }
303 Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
304 Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); }
305 Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
306 Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
307 Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
308 Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
309 Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
310 Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
311 Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); }
312 Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
313 Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
314 Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
315 Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
316 Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
317 Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
318 Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
319 Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
320 Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); }
321 Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
322 Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
323
324 Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); }
325 Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
326 Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
327 Object *weakSetPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakSetProto); }
328 Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); }
329 Object *weakMapPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakMapProto); }
330 Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); }
331 Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + IntrinsicTypedArrayProto); }
333
334 Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
335 Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
336 Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
337 Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
338 Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
339 Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
340 Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
341 Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
342 Object *urlPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlProto); }
343 Object *urlSearchParamsPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlSearchParamsProto); }
344
345 EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
346 FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
347 FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
348
349#if QT_CONFIG(qml_network)
350 QNetworkAccessManager* (*networkAccessManager)(ExecutionEngine*) = detail::getNetworkAccessManager;
351#endif
352
404
405 NJSStrings
406 };
408
422 NJSSymbols
423 };
425
426 String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
427 String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
428 String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
429 String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
430 String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
431 String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
432 String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
433 String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
434 String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); }
435 String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); }
436 String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
437 String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
438 String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
439 String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
440 String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
441 String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
442 String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
443 String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
444 String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
445 String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
446 String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
447 String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
448 String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
449 String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
450 String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
451 String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
452 String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
453 String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
454 String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
455 String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
456 String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
457 String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
458 String *id_toLocaleString() const { return reinterpret_cast<String *>(jsStrings + String_toLocaleString); }
459 String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
460 String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
461 String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
462 String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
463 String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
464 String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
465 String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
466 String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
467 String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); }
468 String *id_throw() const { return reinterpret_cast<String *>(jsStrings + String_throw); }
469 String *id_global() const { return reinterpret_cast<String *>(jsStrings + String_global); }
470 String *id_ignoreCase() const { return reinterpret_cast<String *>(jsStrings + String_ignoreCase); }
471 String *id_multiline() const { return reinterpret_cast<String *>(jsStrings + String_multiline); }
472 String *id_unicode() const { return reinterpret_cast<String *>(jsStrings + String_unicode); }
473 String *id_sticky() const { return reinterpret_cast<String *>(jsStrings + String_sticky); }
474 String *id_source() const { return reinterpret_cast<String *>(jsStrings + String_source); }
475 String *id_flags() const { return reinterpret_cast<String *>(jsStrings + String_flags); }
476
477 Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
478 Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
479 Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
480 Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
481 Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
482 Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
483 Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
484 Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
485 Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
486 Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
487 Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
488 Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
489
491
493
495
496 // Scarce resources are "exceptionally high cost" QVariant types where allowing the
497 // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
498 // out-of-resource situations. When such a resource is passed into JavaScript we
499 // add it to the scarceResources list and it is destroyed when we return from the
500 // JavaScript execution that created it. The user can prevent this behavior by
501 // calling preserve() on the object which removes it from this scarceResource list.
503 public:
505 ScarceResourceData(const QMetaType type, const void *data) : data(type, data) {}
508 };
510
511 // Normally the JS wrappers for QObjects are stored in the QQmlData/QObjectPrivate,
512 // but any time a QObject is wrapped a second time in another engine, we have to do
513 // bookkeeping.
515#if QT_CONFIG(qml_jit)
516 const bool m_canAllocateExecutableMemory;
517#endif
518
519 quintptr protoIdCount = 1;
520
521 ExecutionEngine(QJSEngine *jsEngine = nullptr);
523
524#if !QT_CONFIG(qml_debug)
525 QV4::Debugging::Debugger *debugger() const { return nullptr; }
526 QV4::Profiling::Profiler *profiler() const { return nullptr; }
527
530#else
531 QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
532 QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); }
533
534 void setDebugger(Debugging::Debugger *debugger);
535 void setProfiler(Profiling::Profiler *profiler);
536#endif // QT_CONFIG(qml_debug)
537
538 // We don't want to #include <private/qv4stackframe_p.h> here, but we still want
539 // currentContext() to be inline. Therefore we shift the requirement to provide the
540 // complete type of CppStackFrame to the caller by making this a template.
541 template<typename StackFrame = CppStackFrame>
543 {
544 return static_cast<const StackFrame *>(currentStackFrame)->context();
545 }
546
547 // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
548 quintptr newProtoId() { return (protoIdCount += 2); }
549
550 Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
551
552 Heap::Object *newObject();
553 Heap::Object *newObject(Heap::InternalClass *internalClass);
554
555 Heap::String *newString(const QString &s = QString());
556 Heap::String *newIdentifier(const QString &text);
557
558 Heap::Object *newStringObject(const String *string);
559 Heap::Object *newSymbolObject(const Symbol *symbol);
560 Heap::Object *newNumberObject(double value);
561 Heap::Object *newBooleanObject(bool b);
562
563 Heap::ArrayObject *newArrayObject(int count = 0);
564 Heap::ArrayObject *newArrayObject(const Value *values, int length);
565 Heap::ArrayObject *newArrayObject(const QStringList &list);
566 Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic);
567
568 Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
569 Heap::ArrayBuffer *newArrayBuffer(size_t length);
570
571 Heap::DateObject *newDateObject(double dateTime);
572 Heap::DateObject *newDateObject(const QDateTime &dateTime);
573 Heap::DateObject *newDateObject(QDate date, Heap::Object *parent, int index, uint flags);
574 Heap::DateObject *newDateObject(QTime time, Heap::Object *parent, int index, uint flags);
575 Heap::DateObject *newDateObject(QDateTime dateTime, Heap::Object *parent, int index, uint flags);
576
577 Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
578 Heap::RegExpObject *newRegExpObject(RegExp *re);
579#if QT_CONFIG(regularexpression)
580 Heap::RegExpObject *newRegExpObject(const QRegularExpression &re);
581#endif
582
583 Heap::UrlObject *newUrlObject();
584 Heap::UrlObject *newUrlObject(const QUrl &url);
585 Heap::UrlSearchParamsObject *newUrlSearchParamsObject();
586
587 Heap::Object *newErrorObject(const Value &value);
588 Heap::Object *newErrorObject(const QString &message);
589 Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
590 Heap::Object *newSyntaxErrorObject(const QString &message);
591 Heap::Object *newReferenceErrorObject(const QString &message);
592 Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column);
593 Heap::Object *newTypeErrorObject(const QString &message);
594 Heap::Object *newRangeErrorObject(const QString &message);
595 Heap::Object *newURIErrorObject(const QString &message);
596 Heap::Object *newURIErrorObject(const Value &message);
597 Heap::Object *newEvalErrorObject(const QString &message);
598
599 Heap::PromiseObject *newPromiseObject();
600 Heap::Object *newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability);
601 Promise::ReactionHandler *getPromiseReactionHandler();
602
603 Heap::Object *newVariantObject(const QMetaType type, const void *data);
604
605 Heap::Object *newForInIteratorObject(Object *o);
606 Heap::Object *newSetIteratorObject(Object *o);
607 Heap::Object *newMapIteratorObject(Object *o);
608 Heap::Object *newArrayIteratorObject(Object *o);
609
610 static Heap::ExecutionContext *qmlContext(Heap::ExecutionContext *ctx)
611 {
612 Heap::ExecutionContext *outer = ctx->outer;
613
614 if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !outer)
615 return nullptr;
616
617 while (outer && outer->type != Heap::ExecutionContext::Type_GlobalContext) {
618 ctx = outer;
619 outer = ctx->outer;
620 }
621
622 Q_ASSERT(ctx);
623 if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
624 return nullptr;
625
626 return ctx;
627 }
628
629 Heap::QmlContext *qmlContext() const;
630 QObject *qmlScopeObject() const;
631 QQmlRefPointer<QQmlContextData> callingQmlContext() const;
632
633
634 StackTrace stackTrace(int frameLimit = -1) const;
636
637 void markObjects(MarkStack *markStack);
638
639 void initRootContext();
640
642
644
645 ReturnedValue throwError(const Value &value);
646 ReturnedValue catchException(StackTrace *trace = nullptr);
647
648 ReturnedValue throwError(const QString &message);
649 ReturnedValue throwSyntaxError(const QString &message);
650 ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column);
653 ReturnedValue throwReferenceError(const Value &value);
654 ReturnedValue throwReferenceError(const QString &name);
655 ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column);
656 ReturnedValue throwRangeError(const Value &value);
657 ReturnedValue throwRangeError(const QString &message);
658 ReturnedValue throwURIError(const Value &msg);
659 ReturnedValue throwUnimplemented(const QString &message);
660
661 // Use only inside catch(...) -- will re-throw if no JS exception
662 QQmlError catchExceptionAsQmlError();
663
664 // variant conversions
665 static QVariant toVariant(
666 const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols = true);
667 QV4::ReturnedValue fromVariant(const QVariant &);
668 QV4::ReturnedValue fromVariant(
669 const QVariant &variant, Heap::Object *parent, int property, uint flags);
670
671 static QVariantMap variantMapFromJS(const QV4::Object *o);
672
673 static bool metaTypeFromJS(const Value &value, QMetaType type, void *data);
674 QV4::ReturnedValue metaTypeToJS(QMetaType type, const void *data);
675
676 int maxJSStackSize() const;
677 int maxGCStackSize() const;
678
679 bool checkStackLimits();
680 int safeForAllocLength(qint64 len64);
681
682 bool canJIT(Function *f = nullptr)
683 {
684#if QT_CONFIG(qml_jit)
685 if (!m_canAllocateExecutableMemory)
686 return false;
687 if (f) {
688 return f->kind != Function::AotCompiled
689 && !f->isGenerator()
690 && f->interpreterCallCount >= s_jitCallCountThreshold;
691 }
692 return true;
693#else
694 Q_UNUSED(f);
695 return false;
696#endif
697 }
698
700 void initQmlGlobalObject();
701 void initializeGlobal();
702 void createQtObject();
703
704 void freezeObject(const QV4::Value &value);
705 void lockObject(const QV4::Value &value);
706
707 // Return the list of illegal id names (the names of the properties on the global object)
708 const QSet<QString> &illegalNames() const;
709
710#if QT_CONFIG(qml_xml_http_request)
711 void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
712#endif
713
714 void setQmlEngine(QQmlEngine *engine);
715
716 QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
717
718 // used for console.time(), console.timeEnd()
719 void startTimer(const QString &timerName);
720 qint64 stopTimer(const QString &timerName, bool *wasRunning);
721
722 // used for console.count()
723 int consoleCountHelper(const QString &file, quint16 line, quint16 column);
724
725 struct Deletable {
726 virtual ~Deletable() {}
727 };
728
729 static QMutex *registrationMutex();
730 static int registerExtension();
731
732 void setExtensionData(int, Deletable *);
734 {
735 if (index < m_extensionData.size())
736 return m_extensionData[index];
737 else
738 return nullptr;
739 }
740
741 double localTZA = 0.0; // local timezone, initialized at startup
742
745 const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
746
747 void injectCompiledModule(const QQmlRefPointer<ExecutableCompilationUnit> &moduleUnit);
748 QV4::Value *registerNativeModule(const QUrl &url, const QV4::Value &module);
749
750 struct Module {
752
753 // We can pass a raw value pointer here, but nowhere else. See below.
754 Value *native = nullptr;
755 };
756
757 Module moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const;
758 Module loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr);
759
760 DiskCacheOptions diskCacheOptions() const;
761
762 void callInContext(QV4::Function *function, QObject *self, QV4::ExecutionContext *ctxt,
763 int argc, void **args, QMetaType *types);
764 QV4::ReturnedValue callInContext(QV4::Function *function, QObject *self,
765 QV4::ExecutionContext *ctxt, int argc, const QV4::Value *argv);
766
767 QV4::ReturnedValue fromData(
768 QMetaType type, const void *ptr,
769 Heap::Object *parent = nullptr, int property = -1, uint flags = 0);
770
771
772 static void setMaxCallDepth(int maxCallDepth) { s_maxCallDepth = maxCallDepth; }
773 static int maxCallDepth() { return s_maxCallDepth; }
774
775 template<typename Value>
777 {
778 if (v->isUndefined())
780 if (v->isNull())
782 if (v->isBoolean())
783 return QJSPrimitiveValue(v->toBoolean());
784 if (v->isInteger())
785 return QJSPrimitiveValue(v->integerValue());
786 if (v->isDouble())
787 return QJSPrimitiveValue(v->doubleValue());
788 bool ok;
789 const QString result = v->toQString(&ok);
791 }
792
793private:
794 template<int Frames>
796
797 static void initializeStaticMembers();
798
799 bool inStack(const void *current) const
800 {
801#if Q_STACK_GROWTH_DIRECTION > 0
802 return current < cppStackLimit && current >= cppStackBase;
803#else
804 return current > cppStackLimit && current <= cppStackBase;
805#endif
806 }
807
808 bool hasCppStackOverflow()
809 {
810 if (s_maxCallDepth >= 0)
811 return callDepth >= s_maxCallDepth;
812
813 if (inStack(currentStackPointer()))
814 return false;
815
816 // Double check the stack limits on failure.
817 // We may have moved to a different thread.
818 const StackProperties stack = stackProperties();
819 cppStackBase = stack.base;
820 cppStackLimit = stack.softLimit;
821 return !inStack(currentStackPointer());
822 }
823
824 bool hasJsStackOverflow() const
825 {
826 return jsStackTop > jsStackLimit;
827 }
828
829 bool hasStackOverflow()
830 {
831 return hasJsStackOverflow() || hasCppStackOverflow();
832 }
833
834 static int s_maxCallDepth;
835 static int s_jitCallCountThreshold;
836 static int s_maxJSStackSize;
837 static int s_maxGCStackSize;
838
839#if QT_CONFIG(qml_debug)
842#endif
843 QSet<QString> m_illegalNames;
844
845 // used by generated Promise objects to handle 'then' events
847
848#if QT_CONFIG(qml_xml_http_request)
849 void *m_xmlHttpRequestData;
850#endif
851
852 QQmlEngine *m_qmlEngine;
853
854 QQmlDelayedCallQueue m_delayedCallQueue;
855
856 QElapsedTimer m_time;
857 QHash<QString, qint64> m_startedTimers;
858
859 QHash<QString, quint32> m_consoleCount;
860
861 QVector<Deletable *> m_extensionData;
862
863 mutable QMutex moduleMutex;
865
866 // QV4::PersistentValue would be preferred, but using QHash will create copies,
867 // and QV4::PersistentValue doesn't like creating copies.
868 // Instead, we allocate a raw pointer using the same manual memory management
869 // technique in QV4::PersistentValue.
870 QHash<QUrl, Value *> nativeModules;
871};
872
873#define CHECK_STACK_LIMITS(v4) \
874 if (v4->checkStackLimits()) \
875 return Encode::undefined(); \
876 ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
877
878template<int Frames = 1>
880{
882
884 {
885 if (ExecutionEngine::s_maxCallDepth >= 0)
886 ee->callDepth += Frames;
887 }
888
890 {
891 if (ExecutionEngine::s_maxCallDepth >= 0)
892 ee->callDepth -= Frames;
893 }
894
895 bool hasOverflow() const
896 {
897 return ee->hasCppStackOverflow();
898 }
899};
900
902{
903 if (Q_UNLIKELY(hasStackOverflow())) {
904 throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
905 return true;
906 }
907
908 return false;
909}
910
911Q_DECLARE_OPERATORS_FOR_FLAGS(ExecutionEngine::DiskCacheOptions);
912
913} // namespace QV4
914
916
917#endif // QV4ENGINE_H
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatetime.h:257
\inmodule QtCore \reentrant
Definition qdatetime.h:27
\inmodule QtCore
\inmodule QtCore
Definition qhash.h:818
The QIntrusiveList class is a template class that provides a list of objects using static storage.
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:26
The QJSPrimitiveValue class operates on primitive types in JavaScript semantics.
Definition qlist.h:74
\inmodule QtCore
Definition qmetatype.h:320
\inmodule QtCore
Definition qmutex.h:285
The QNetworkAccessManager class allows the application to send network requests and receive replies.
\inmodule QtCore
Definition qobject.h:90
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
QV4::ExecutionEngine * v4engine() const
Definition qv4engine_p.h:90
QV4::ReturnedValue operator[](int idx) const
Definition qv4engine_p.h:88
int length() const
Definition qv4engine_p.h:87
void setReturnValue(QV4::ReturnedValue rv)
Definition qv4engine_p.h:89
\inmodule QtCore \reentrant
\inmodule QtCore
Definition qset.h:18
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\inmodule QtCore \reentrant
Definition qdatetime.h:189
\inmodule QtCore
Definition qurl.h:94
ScarceResourceData(const QMetaType type, const void *data)
\inmodule QtCore
Definition qvariant.h:64
EGLContext ctx
QString text
QDate date
[1]
double e
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
@ NTypedArrayTypes
quint64 ReturnedValue
StackProperties stackProperties()
const void * currentStackPointer()
Definition qctf_p.h:77
static void * context
#define Q_UNLIKELY(x)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
Definition qflags.h:194
static ControlElement< T > * ptr(QWidget *widget)
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint index
[2]
GLsizei GLenum GLenum * types
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLenum type
GLbitfield flags
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLenum GLenum GLsizei void GLsizei void * column
const GLubyte * c
GLenum array
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLubyte * pattern
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
static QUrl resolvedUrl(const QUrl &url, const QQmlRefPointer< QQmlContextData > &context)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
static DebuggerProgram debugger
#define Q_UNUSED(x)
#define QML_NEARLY_ALWAYS_INLINE
unsigned int quint32
Definition qtypes.h:45
unsigned short quint16
Definition qtypes.h:43
size_t quintptr
Definition qtypes.h:72
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols, V4ObjectSet *visitedObjects)
ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
const char property[13]
Definition qwizard.cpp:101
QList< int > list
[14]
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
QVariant variant
[1]
QDateTime dateTime
[12]
QSharedPointer< T > other(t)
[5]
QJSValueList args
QJSValue global
QJSEngine engine
[0]
An empty marker type to signify the JavaScript null value. \inmodule QtQml.
An empty marker type to signify the JavaScript Undefined type and its single value....
StaticValue args[1]
int argc() const
StaticValue thisObject
static constexpr ReturnedValue undefined()
ExecutionEngineCallDepthRecorder(ExecutionEngine *e)
QQmlRefPointer< ExecutableCompilationUnit > compiled
String * id_sticky() const
Symbol * symbol_isConcatSpreadable() const
FunctionObject * promiseCtor() const
FunctionObject * getSymbolSpecies() const
WTF::PageAllocation * gcStack
Symbol * symbol_split() const
Object * typeErrorPrototype() const
String * id_unicode() const
ExecutionContext * rootContext() const
Q_DECLARE_FLAGS(DiskCacheOptions, DiskCache)
String * id_byteLength() const
Symbol * symbol_iterator() const
String * id_flags() const
StackTrace exceptionStackTrace
WTF::PageAllocation * jsStack
Object * iteratorPrototype() const
FunctionObject * objectCtor() const
FunctionObject * urlSearchParamsCtor() const
FunctionObject * regExpCtor() const
QIntrusiveList< ScarceResourceData, &ScarceResourceData::node > scarceResources
QJSEngine * publicEngine
QV4::Debugging::Debugger * debugger() const
String * id_true() const
String * id_arguments() const
String * id_uintMax() const
Symbol * symbol_toPrimitive() const
FunctionObject * booleanCtor() const
String * id_callee() const
Object * urlPrototype() const
Object * dataViewPrototype() const
QQmlDelayedCallQueue * delayedCallQueue()
ReturnedValue throwRangeError(const Value &value)
Object * stringPrototype() const
FunctionObject * dateCtor() const
String * id_length() const
Object * signalHandlerPrototype() const
void setProfiler(Profiling::Profiler *)
String * id_this() const
Object * arrayPrototype() const
String * id_constructor() const
String * id_global() const
static int maxCallDepth()
FunctionObject * evalErrorCtor() const
String * id_multiline() const
String * id_ignoreCase() const
Object * weakSetPrototype() const
String * id_string() const
Symbol * symbol_replace() const
Object * stringIteratorPrototype() const
String * id_buffer() const
String * id_value() const
FunctionObject * typedArrayCtors
Object * variantPrototype() const
String * id_destroy() const
String * id_get() const
Object * weakMapPrototype() const
String * id_writable() const
Deletable * extensionData(int index) const
String * id_toString() const
Object * mapIteratorPrototype() const
String * id_prototype() const
Object * numberPrototype() const
String * id_lastIndex() const
String * id_false() const
FunctionObject * urlCtor() const
QML_NEARLY_ALWAYS_INLINE Value * jsAlloca(int nValues)
QIntrusiveList< ExecutableCompilationUnit, &ExecutableCompilationUnit::nextCompilationUnit > compilationUnits
String * id_caller() const
String * id_byteOffset() const
String * id_null() const
String * id___proto__() const
FunctionObject * typeErrorCtor() const
String * id_toLocaleString() const
FunctionObject * referenceErrorCtor() const
Object * rangeErrorPrototype() const
String * id_name() const
ExecutableAllocator * executableAllocator
Object * setPrototype() const
Object * valueTypeWrapperPrototype() const
String * id_eval() const
Symbol * symbol_toStringTag() const
FunctionObject * arrayBufferCtor() const
Object * forInIteratorPrototype() const
String * id_index() const
String * id_undefined() const
String * id_default() const
Symbol * symbol_revokableProxy() const
String * id_boolean() const
ExecutionContext * scriptContext() const
Object * uRIErrorPrototype() const
String * id_enumerable() const
Object * datePrototype() const
EvalFunction * evalFunction() const
FunctionObject * functionCtor() const
FunctionObject * syntaxErrorCtor() const
String * id_empty() const
WTF::BumpPointerAllocator * bumperPointerAllocator
String * id_input() const
ExecutableAllocator * regExpAllocator
Object * intrinsicTypedArrayPrototype() const
static void setMaxCallDepth(int maxCallDepth)
Object * objectPrototype() const
String * id_number() const
Symbol * symbol_hasInstance() const
FunctionObject * errorCtor() const
Symbol * symbol_species() const
FunctionObject * symbolCtor() const
QJSEngine * jsEngine() const
Object * syntaxErrorPrototype() const
RegExpCache * regExpCache
Object * sharedArrayBufferPrototype() const
static QJSPrimitiveValue createPrimitive(const Value &v)
FunctionObject * mapCtor() const
Object * booleanPrototype() const
Object * setIteratorPrototype() const
void setDebugger(Debugging::Debugger *)
String * id_set() const
Object * symbolPrototype() const
Object * functionPrototype() const
FunctionObject * uRIErrorCtor() const
FunctionObject * generatorFunctionCtor() const
String * id_object() const
Object * urlSearchParamsPrototype() const
bool canJIT(Function *f=nullptr)
String * id_next() const
QQmlEngine * qmlEngine() const
void setScriptContext(ReturnedValue c)
String * id_throw() const
FunctionObject * arrayCtor() const
Object * promisePrototype() const
String * id_symbol() const
FunctionObject * setCtor() const
Object * arrayProtoValues() const
Symbol * symbol_match() const
String * id_configurable() const
static Heap::ExecutionContext * qmlContext(Heap::ExecutionContext *ctx)
Object * arrayIteratorPrototype() const
FunctionObject * thrower() const
Object * sequencePrototype() const
String * id_done() const
Object * arrayBufferPrototype() const
FunctionObject * intrinsicTypedArrayCtor() const
FunctionObject * rangeErrorCtor() const
FunctionObject * dataViewCtor() const
Object * typedArrayPrototype
String * id_source() const
String * id_return() const
Object * propertyListPrototype() const
Object * evalErrorPrototype() const
String * id_valueOf() const
Object * regExpPrototype() const
Symbol * symbol_unscopables() const
FunctionObject * weakSetCtor() const
FunctionObject * weakMapCtor() const
FunctionObject * stringCtor() const
MultiplyWrappedQObjectMap * m_multiplyWrappedQObjects
FunctionObject * numberCtor() const
FunctionObject * sharedArrayBufferCtor() const
Object * mapPrototype() const
Object * errorPrototype() const
QV4::Profiling::Profiler * profiler() const
Symbol * symbol_search() const
FunctionObject * getStackFunction() const
ExecutionContext * currentContext() const
Object * generatorPrototype() const
Object * referenceErrorPrototype() const
String * id_function() const
constexpr ReturnedValue asReturnedValue() const
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent