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
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// Qt-Security score:significant
4#ifndef QV4ENGINE_H
5#define QV4ENGINE_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/qintrusivelist_p.h>
19#include <private/qqmldelayedcallqueue_p.h>
20#include <private/qqmlrefcount_p.h>
21#include <private/qv4compileddata_p.h>
22#include <private/qv4context_p.h>
23#include <private/qv4enginebase_p.h>
24#include <private/qv4executablecompilationunit_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
57QT_BEGIN_NAMESPACE
58
59#if QT_CONFIG(qml_network)
60class QNetworkAccessManager;
61#endif // qml_network
62namespace QV4 { struct QObjectMethod; }
63
64// Used to allow a QObject method take and return raw V4 handles without having to expose
65// 48 in the public API.
66// Use like this:
67// class MyClass : public QObject {
68// Q_OBJECT
69// ...
70// Q_INVOKABLE void myMethod(QQmlV4FunctionPtr);
71// };
72// The QQmlV8Function - and consequently the arguments and return value - only remains
73// valid during the call. If the return value isn't set within myMethod(), the will return
74// undefined.
75
77{
78public:
79 int length() const { return callData->argc(); }
80 QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
81 void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
82 QV4::ExecutionEngine *v4engine() const { return e; }
83private:
84 friend struct QV4::QObjectMethod;
85 QQmlV4Function();
86 QQmlV4Function(const QQmlV4Function &);
87 QQmlV4Function &operator=(const QQmlV4Function &);
88
89 QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
90 : callData(callData), retVal(retVal), e(e)
91 {
92 callData->thisObject = QV4::Encode::undefined();
93 }
94
95 QV4::CallData *callData;
96 QV4::Value *retVal;
97 QV4::ExecutionEngine *e;
98};
99
100class QQmlError;
101class QJSEngine;
102class QQmlEngine;
103class QQmlContextData;
104class QQmlTypeLoader;
105
106namespace QV4 {
107namespace Debugging {
108class Debugger;
109} // namespace Debugging
110namespace Profiling {
111class Profiler;
112} // namespace Profiling
113namespace CompiledData {
114struct CompilationUnit;
115}
116
117namespace Heap {
118struct Module;
119};
120
121struct Function;
122
123namespace Promise {
124class ReactionHandler;
125};
126
127struct Q_QML_EXPORT ExecutionEngine : public EngineBase
128{
129private:
131 friend struct ExecutionContext;
132 friend struct Heap::ExecutionContext;
133public:
134 enum class DiskCache : quint8 {
136 AotByteCode = 1 << 0,
137 AotNative = 1 << 1,
138 QmlcRead = 1 << 2,
139 QmlcWrite = 1 << 3,
143
144 };
145
147
150
151 WTF::BumpPointerAllocator *bumperPointerAllocator = nullptr; // Used by Yarr Regex engine.
152
154
156
157 // Using jsAlloca directly can be dangerous as it temporarily, until
158 // some initialization is performed, leaves an element on the
159 // stack that is garbage memory.
160 // That element could be accessed by other parts of the system
161 // before an initialization step is performed, involuntary
162 // interacting with that memory.
163 //
164 // For example, any allocation performed by the MemoryManager
165 // might run the garbage collector, which in turn has a chance of
166 // accessing all current elements on the stack, including the
167 // garbage memory that can be left on the stack by a call to this
168 // method.
169 //
170 // Thus care needs to be taken when using jsAlloca, such that all
171 // allocated stack slots are initialized as soon as possible and
172 // without any heap allocation or other accesses to the new stack
173 // elements in the middle.
179
181
182 QJSEngine *jsEngine() const { return publicEngine; }
183 QQmlEngine *qmlEngine() const { return m_qmlEngine; }
185
186 template<typename TypeLoader = QQmlTypeLoader>
188 {
189 if (!m_typeLoader)
191 return m_typeLoader.get();
192 }
193
197 IntegerNull, // Has to come after the RootContext to make the context stack safe
240
269
271
276 };
277 Value *jsObjects = nullptr;
278 enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
279
280 ExecutionContext *rootContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + RootContext); }
281 ExecutionContext *scriptContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + ScriptContext); }
283 FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
284 FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
285 FunctionObject *symbolCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Symbol_Ctor); }
286 FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
287 FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
288 FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
289 FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
291 FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
292 FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
293 FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
294 FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
295 FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
297 FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
298 FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
299 FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
301 FunctionObject *promiseCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Promise_Ctor); }
302 FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
303 FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
304 FunctionObject *weakSetCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakSet_Ctor); }
305 FunctionObject *setCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Set_Ctor); }
306 FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
307 FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
310 {
311 return reinterpret_cast<FunctionObject *>(jsObjects + Url_Ctor);
312 }
314 {
315 return reinterpret_cast<FunctionObject *>(jsObjects + UrlSearchParams_Ctor);
316 }
318
319 FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
320
321 Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
322 Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); }
323 Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
324 Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); }
325 Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
326 Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
327 Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
328 Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
329 Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
330 Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
331 Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); }
332 Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
333 Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
334 Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
335 Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
336 Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
337 Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
338 Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
339 Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
340 Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); }
341 Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
343 Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
344
345 Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); }
346 Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
347 Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
348 Object *weakSetPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakSetProto); }
349 Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); }
350 Object *weakMapPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakMapProto); }
351 Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); }
354
355 Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
356 Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
357 Object *typeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeWrapperProto); }
358 Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
359 Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
360 Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
361 Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
362 Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
363 Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
364 Object *urlPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlProto); }
365 Object *urlSearchParamsPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlSearchParamsProto); }
366
367 EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
369 FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
370
371#if QT_CONFIG(qml_network)
374#endif
375
430 Value *jsStrings = nullptr;
431
447 Value *jsSymbols = nullptr;
448
449 String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
450 String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
451 String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
452 String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
453 String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
454 String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
455 String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
456 String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
457 String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); }
458 String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); }
459 String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
460 String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
461 String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
462 String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
463 String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
464 String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
465 String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
466 String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
467 String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
468 String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
469 String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
470 String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
471 String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
472 String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
473 String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
474 String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
475 String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
476 String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
477 String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
478 String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
479 String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
480 String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
481 String *id_toLocaleString() const { return reinterpret_cast<String *>(jsStrings + String_toLocaleString); }
482 String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
483 String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
484 String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
485 String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
486 String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
487 String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
488 String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
489 String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
490 String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); }
491 String *id_throw() const { return reinterpret_cast<String *>(jsStrings + String_throw); }
492 String *id_global() const { return reinterpret_cast<String *>(jsStrings + String_global); }
493 String *id_ignoreCase() const { return reinterpret_cast<String *>(jsStrings + String_ignoreCase); }
494 String *id_multiline() const { return reinterpret_cast<String *>(jsStrings + String_multiline); }
495 String *id_unicode() const { return reinterpret_cast<String *>(jsStrings + String_unicode); }
496 String *id_sticky() const { return reinterpret_cast<String *>(jsStrings + String_sticky); }
497 String *id_source() const { return reinterpret_cast<String *>(jsStrings + String_source); }
498 String *id_flags() const { return reinterpret_cast<String *>(jsStrings + String_flags); }
499
500 Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
502 Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
503 Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
504 Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
505 Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
506 Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
507 Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
508 Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
509 Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
510 Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
511 Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
512
514
516
517 // Scarce resources are "exceptionally high cost" QVariant types where allowing the
518 // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
519 // out-of-resource situations. When such a resource is passed into JavaScript we
520 // add it to the scarceResources list and it is destroyed when we return from the
521 // JavaScript execution that created it. The user can prevent this behavior by
522 // calling preserve() on the object which removes it from this scarceResource list.
531
532 // Normally the JS wrappers for QObjects are stored in the QQmlData/QObjectPrivate,
533 // but any time a QObject is wrapped a second time in another engine, we have to do
534 // bookkeeping.
536#if QT_CONFIG(qml_jit)
537 const bool m_canAllocateExecutableMemory = false;
538#endif
539
541
544
545#if !QT_CONFIG(qml_debug)
546 QV4::Debugging::Debugger *debugger() const { return nullptr; }
547 QV4::Profiling::Profiler *profiler() const { return nullptr; }
548
551 static void setPreviewing(bool) {}
552#else
553 QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
554 QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); }
555
558 static void setPreviewing(bool enabled);
559#endif // QT_CONFIG(qml_debug)
560
561 // We don't want to #include <private/qv4stackframe_p.h> here, but we still want
562 // currentContext() to be inline. Therefore we shift the requirement to provide the
563 // complete type of CppStackFrame to the caller by making this a template.
564 template<typename StackFrame = CppStackFrame>
566 {
567 return static_cast<const StackFrame *>(currentStackFrame)->context();
568 }
569
570 // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
571 quintptr newProtoId() { return (protoIdCount += 2); }
572
574
577
578 Heap::String *newString(char16_t c) { return newString(QChar(c)); }
579 Heap::String *newString(const QString &s = QString());
581
586
591
594
600
603#if QT_CONFIG(regularexpression)
605#endif
606
610
622
626
627 Heap::Object *newVariantObject(const QMetaType type, const void *data);
628
633
635 {
637
639 return nullptr;
640
642 ctx = outer;
643 outer = ctx->outer;
644 }
645
646 Q_ASSERT(ctx);
648 return nullptr;
649
650 return ctx;
651 }
652
653 Heap::QmlContext *qmlContext() const;
654 QObject *qmlScopeObject() const;
656
657
658 StackTrace stackTrace(int frameLimit = -1) const;
660
662
663 void initRootContext();
664
666
668
671
684
685 // Use only inside catch(...) -- will re-throw if no JS exception
687
688 void amendException();
689
690 // variant conversions
691 static QVariant toVariant(
693 static QVariant toVariantLossy(const QV4::Value &value);
697
698 static QVariantMap variantMapFromJS(const QV4::Object *o);
699 static QVariantHash variantHashFromJS(const QV4::Object *o);
700
701 static bool metaTypeFromJS(const Value &value, QMetaType type, void *data);
703
704 int maxJSStackSize() const;
705 int maxGCStackSize() const;
706
707 bool checkStackLimits();
709
710 template<typename Jittable>
712 {
713#if QT_CONFIG(qml_jit)
715 && jittable->isJittable()
717#else
719 return false;
720#endif
721 }
722
724 void initQmlGlobalObject();
725 void initializeGlobal();
726 void createQtObject();
727
728 void freezeObject(const QV4::Value &value);
729 void lockObject(const QV4::Value &value);
730
731#if QT_CONFIG(qml_xml_http_request)
733 void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
734#endif
735
737 void resetQmlEngine() { m_qmlEngine = nullptr; }
738
740
741 // used for console.time(), console.timeEnd()
742 void startTimer(const QString &timerName);
744
745 // used for console.count()
747
748 struct Deletable {
749 virtual ~Deletable() {}
750 };
751
752 static QMutex *registrationMutex();
753 static int registerExtension();
754
755 void setExtensionData(int, Deletable *);
757 {
758 if (index < m_extensionData.size())
759 return m_extensionData[index];
760 else
761 return nullptr;
762 }
763
764 double localTZA = 0.0; // local timezone, initialized at startup
765
767
770
773
778
781
783
786
788
790 int argc, void **args, QMetaType *types);
792 QV4::ExecutionContext *ctxt, int argc, const QV4::Value *argv);
793
795 QMetaType type, const void *ptr,
796 Heap::Object *parent = nullptr, int property = -1, uint flags = 0);
797
798
800 static int maxCallDepth() { return s_maxCallDepth; }
801
802 template<typename Value>
804 {
805 if (v->isUndefined())
807 if (v->isNull())
809 if (v->isBoolean())
810 return QJSPrimitiveValue(v->toBoolean());
811 if (v->isInteger())
813 if (v->isDouble())
815 bool ok;
816 const QString result = v->toQString(&ok);
818 }
819
820private:
821 template<int Frames>
823
824 static void initializeStaticMembers();
825
826 bool inStack(const void *current) const
827 {
828#if Q_STACK_GROWTH_DIRECTION > 0
830#else
832#endif
833 }
834
836 {
837 if (s_maxCallDepth >= 0)
838 return callDepth >= s_maxCallDepth;
839
841 return false;
842
843 // Double check the stack limits on failure.
844 // We may have moved to a different thread.
848 return !inStack(currentStackPointer());
849 }
850
851 bool hasJsStackOverflow() const
852 {
853 return jsStackTop > jsStackLimit;
854 }
855
856 bool hasStackOverflow()
857 {
859 }
860
861 static int s_maxCallDepth;
862 static int s_jitCallCountThreshold;
863 static int s_maxJSStackSize;
864 static int s_maxGCStackSize;
865
866#if QT_CONFIG(qml_debug)
869#endif
870
871 // used by generated Promise objects to handle 'then' events
873
874#if QT_CONFIG(qml_xml_http_request)
875 void *m_xmlHttpRequestData = nullptr;
876#endif
877
879 QQmlEngine *m_qmlEngine = nullptr;
880
882
885
887
889
891};
892
893#define CHECK_STACK_LIMITS(v4)
894 if (v4->checkStackLimits())
895 return Encode::undefined();
896 ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
897
898template<int Frames = 1>
900{
902
904 {
905 if (ExecutionEngine::s_maxCallDepth >= 0)
906 ee->callDepth += Frames;
907 }
908
910 {
911 if (ExecutionEngine::s_maxCallDepth >= 0)
912 ee->callDepth -= Frames;
913 }
914
915 bool hasOverflow() const
916 {
917 return ee->hasCppStackOverflow();
918 }
919};
920
922{
924 throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
925 return true;
926 }
927
928 return false;
929}
930
932
933} // namespace QV4
934
935QT_END_NAMESPACE
936
937#endif // QV4ENGINE_H
friend class QJSEngine
QV4::ExecutionEngine * v4engine() const
Definition qv4engine_p.h:82
QV4::ReturnedValue operator[](int idx) const
Definition qv4engine_p.h:80
int length() const
Definition qv4engine_p.h:79
void setReturnValue(QV4::ReturnedValue rv)
Definition qv4engine_p.h:81
Definition qjsvalue.h:23
ExecutionEngineCallDepthRecorder(ExecutionEngine *e)