Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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(QQmlV4FunctionPtr);
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;
112class QQmlTypeLoader;
113
114namespace QV4 {
115namespace Debugging {
116class Debugger;
117} // namespace Debugging
118namespace Profiling {
119class Profiler;
120} // namespace Profiling
121namespace CompiledData {
122struct CompilationUnit;
123}
124
125namespace Heap {
126struct Module;
127};
128
129struct Function;
130
131namespace Promise {
132class ReactionHandler;
133};
134
135struct Q_QML_EXPORT ExecutionEngine : public EngineBase
136{
137private:
138 friend struct ExecutionContextSaver;
139 friend struct ExecutionContext;
140 friend struct Heap::ExecutionContext;
141public:
142 enum class DiskCache {
143 Disabled = 0,
144 AotByteCode = 1 << 0,
145 AotNative = 1 << 1,
146 QmlcRead = 1 << 2,
147 QmlcWrite = 1 << 3,
148 Aot = AotByteCode | AotNative,
149 Qmlc = QmlcRead | QmlcWrite,
150 Enabled = Aot | Qmlc,
151
152 };
153
154 Q_DECLARE_FLAGS(DiskCacheOptions, DiskCache);
155
158
159 WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
160
161 WTF::PageAllocation *jsStack;
162
163 WTF::PageAllocation *gcStack;
164
166 Value *ptr = jsStackTop;
167 jsStackTop = ptr + nValues;
168 return ptr;
169 }
170
172
173 QJSEngine *jsEngine() const { return publicEngine; }
174 QQmlEngine *qmlEngine() const { return m_qmlEngine; }
176
177 template<typename TypeLoader = QQmlTypeLoader>
178 TypeLoader *typeLoader()
179 {
180 if (m_qmlEngine)
181 return TypeLoader::get(m_qmlEngine);
182 return nullptr;
183 }
184
188 IntegerNull, // Has to come after the RootContext to make the context stack safe
229
258
260
264 NJSObjects
265 };
267 enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
268
269 ExecutionContext *rootContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + RootContext); }
270 ExecutionContext *scriptContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + ScriptContext); }
271 void setScriptContext(ReturnedValue c) { jsObjects[ScriptContext] = c; }
272 FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
273 FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
274 FunctionObject *symbolCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Symbol_Ctor); }
275 FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
276 FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
277 FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
278 FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
279 FunctionObject *generatorFunctionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + GeneratorFunction_Ctor); }
280 FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
281 FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
282 FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
283 FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
284 FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
285 FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
286 FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
287 FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
288 FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
289 FunctionObject *sharedArrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SharedArrayBuffer_Ctor); }
290 FunctionObject *promiseCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Promise_Ctor); }
291 FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
292 FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
293 FunctionObject *weakSetCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakSet_Ctor); }
294 FunctionObject *setCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Set_Ctor); }
295 FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
296 FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
297 FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
299 {
300 return reinterpret_cast<FunctionObject *>(jsObjects + Url_Ctor);
301 }
303 {
304 return reinterpret_cast<FunctionObject *>(jsObjects + UrlSearchParams_Ctor);
305 }
307
308 FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
309
310 Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
311 Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); }
312 Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
313 Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); }
314 Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
315 Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
316 Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
317 Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
318 Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
319 Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
320 Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); }
321 Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
322 Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
323 Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
324 Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
325 Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
326 Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
327 Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
328 Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
329 Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); }
330 Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
331 Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
332
333 Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); }
334 Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
335 Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
336 Object *weakSetPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakSetProto); }
337 Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); }
338 Object *weakMapPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakMapProto); }
339 Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); }
340 Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + IntrinsicTypedArrayProto); }
342
343 Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
344 Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
345 Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
346 Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
347 Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
348 Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
349 Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
350 Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
351 Object *urlPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlProto); }
352 Object *urlSearchParamsPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlSearchParamsProto); }
353
354 EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
355 FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
356 FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
357
358#if QT_CONFIG(qml_network)
359 QNetworkAccessManager* (*networkAccessManager)(ExecutionEngine*) = detail::getNetworkAccessManager;
360#endif
361
417
434
435 String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
436 String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
437 String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
438 String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
439 String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
440 String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
441 String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
442 String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
443 String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); }
444 String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); }
445 String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
446 String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
447 String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
448 String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
449 String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
450 String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
451 String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
452 String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
453 String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
454 String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
455 String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
456 String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
457 String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
458 String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
459 String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
460 String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
461 String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
462 String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
463 String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
464 String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
465 String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
466 String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
467 String *id_toLocaleString() const { return reinterpret_cast<String *>(jsStrings + String_toLocaleString); }
468 String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
469 String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
470 String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
471 String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
472 String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
473 String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
474 String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
475 String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
476 String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); }
477 String *id_throw() const { return reinterpret_cast<String *>(jsStrings + String_throw); }
478 String *id_global() const { return reinterpret_cast<String *>(jsStrings + String_global); }
479 String *id_ignoreCase() const { return reinterpret_cast<String *>(jsStrings + String_ignoreCase); }
480 String *id_multiline() const { return reinterpret_cast<String *>(jsStrings + String_multiline); }
481 String *id_unicode() const { return reinterpret_cast<String *>(jsStrings + String_unicode); }
482 String *id_sticky() const { return reinterpret_cast<String *>(jsStrings + String_sticky); }
483 String *id_source() const { return reinterpret_cast<String *>(jsStrings + String_source); }
484 String *id_flags() const { return reinterpret_cast<String *>(jsStrings + String_flags); }
485
486 Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
487 Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
488 Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
489 Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
490 Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
491 Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
492 Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
493 Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
494 Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
495 Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
496 Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
497 Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
498
500
502
503 // Scarce resources are "exceptionally high cost" QVariant types where allowing the
504 // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
505 // out-of-resource situations. When such a resource is passed into JavaScript we
506 // add it to the scarceResources list and it is destroyed when we return from the
507 // JavaScript execution that created it. The user can prevent this behavior by
508 // calling preserve() on the object which removes it from this scarceResource list.
516 QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
517
518 // Normally the JS wrappers for QObjects are stored in the QQmlData/QObjectPrivate,
519 // but any time a QObject is wrapped a second time in another engine, we have to do
520 // bookkeeping.
522#if QT_CONFIG(qml_jit)
523 const bool m_canAllocateExecutableMemory;
524#endif
525
526 quintptr protoIdCount = 1;
527
528 ExecutionEngine(QJSEngine *jsEngine = nullptr);
530
531#if !QT_CONFIG(qml_debug)
532 QV4::Debugging::Debugger *debugger() const { return nullptr; }
533 QV4::Profiling::Profiler *profiler() const { return nullptr; }
534
537#else
538 QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
539 QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); }
540
541 void setDebugger(Debugging::Debugger *debugger);
542 void setProfiler(Profiling::Profiler *profiler);
543#endif // QT_CONFIG(qml_debug)
544
545 // We don't want to #include <private/qv4stackframe_p.h> here, but we still want
546 // currentContext() to be inline. Therefore we shift the requirement to provide the
547 // complete type of CppStackFrame to the caller by making this a template.
548 template<typename StackFrame = CppStackFrame>
550 {
551 return static_cast<const StackFrame *>(currentStackFrame)->context();
552 }
553
554 // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
555 quintptr newProtoId() { return (protoIdCount += 2); }
556
557 Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
558
559 Heap::Object *newObject();
560 Heap::Object *newObject(Heap::InternalClass *internalClass);
561
562 Heap::String *newString(char16_t c) { return newString(QChar(c)); }
563 Heap::String *newString(const QString &s = QString());
564 Heap::String *newIdentifier(const QString &text);
565
566 Heap::Object *newStringObject(const String *string);
567 Heap::Object *newSymbolObject(const Symbol *symbol);
568 Heap::Object *newNumberObject(double value);
569 Heap::Object *newBooleanObject(bool b);
570
571 Heap::ArrayObject *newArrayObject(int count = 0);
572 Heap::ArrayObject *newArrayObject(const Value *values, int length);
573 Heap::ArrayObject *newArrayObject(const QStringList &list);
574 Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic);
575
576 Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
577 Heap::ArrayBuffer *newArrayBuffer(size_t length);
578
579 Heap::DateObject *newDateObject(double dateTime);
580 Heap::DateObject *newDateObject(const QDateTime &dateTime);
581 Heap::DateObject *newDateObject(QDate date, Heap::Object *parent, int index, uint flags);
582 Heap::DateObject *newDateObject(QTime time, Heap::Object *parent, int index, uint flags);
583 Heap::DateObject *newDateObject(QDateTime dateTime, Heap::Object *parent, int index, uint flags);
584
585 Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
586 Heap::RegExpObject *newRegExpObject(RegExp *re);
587#if QT_CONFIG(regularexpression)
588 Heap::RegExpObject *newRegExpObject(const QRegularExpression &re);
589#endif
590
591 Heap::UrlObject *newUrlObject();
592 Heap::UrlObject *newUrlObject(const QUrl &url);
593 Heap::UrlSearchParamsObject *newUrlSearchParamsObject();
594
595 Heap::Object *newErrorObject(const Value &value);
596 Heap::Object *newErrorObject(const QString &message);
597 Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
598 Heap::Object *newSyntaxErrorObject(const QString &message);
599 Heap::Object *newReferenceErrorObject(const QString &message);
600 Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column);
601 Heap::Object *newTypeErrorObject(const QString &message);
602 Heap::Object *newRangeErrorObject(const QString &message);
603 Heap::Object *newURIErrorObject(const QString &message);
604 Heap::Object *newURIErrorObject(const Value &message);
605 Heap::Object *newEvalErrorObject(const QString &message);
606
607 Heap::PromiseObject *newPromiseObject();
608 Heap::Object *newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability);
609 Promise::ReactionHandler *getPromiseReactionHandler();
610
611 Heap::Object *newVariantObject(const QMetaType type, const void *data);
612
613 Heap::Object *newForInIteratorObject(Object *o);
614 Heap::Object *newSetIteratorObject(Object *o);
615 Heap::Object *newMapIteratorObject(Object *o);
616 Heap::Object *newArrayIteratorObject(Object *o);
617
618 static Heap::ExecutionContext *qmlContext(Heap::ExecutionContext *ctx)
619 {
620 Heap::ExecutionContext *outer = ctx->outer;
621
622 if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !outer)
623 return nullptr;
624
625 while (outer && outer->type != Heap::ExecutionContext::Type_GlobalContext) {
626 ctx = outer;
627 outer = ctx->outer;
628 }
629
630 Q_ASSERT(ctx);
631 if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
632 return nullptr;
633
634 return ctx;
635 }
636
637 Heap::QmlContext *qmlContext() const;
638 QObject *qmlScopeObject() const;
639 QQmlRefPointer<QQmlContextData> callingQmlContext() const;
640
641
642 StackTrace stackTrace(int frameLimit = -1) const;
644
645 void markObjects(MarkStack *markStack);
646
647 void initRootContext();
648
650
652
653 ReturnedValue throwError(const Value &value);
654 ReturnedValue catchException(StackTrace *trace = nullptr);
655
656 ReturnedValue throwError(const QString &message);
657 ReturnedValue throwSyntaxError(const QString &message);
658 ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column);
661 ReturnedValue throwReferenceError(const Value &value);
662 ReturnedValue throwReferenceError(const QString &name);
663 ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column);
664 ReturnedValue throwRangeError(const Value &value);
665 ReturnedValue throwRangeError(const QString &message);
666 ReturnedValue throwURIError(const Value &msg);
667 ReturnedValue throwUnimplemented(const QString &message);
668
669 // Use only inside catch(...) -- will re-throw if no JS exception
670 QQmlError catchExceptionAsQmlError();
671
672 // variant conversions
673 static QVariant toVariant(
674 const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols = true);
675 static QVariant toVariantLossy(const QV4::Value &value);
676 QV4::ReturnedValue fromVariant(const QVariant &);
677 QV4::ReturnedValue fromVariant(
678 const QVariant &variant, Heap::Object *parent, int property, uint flags);
679
680 static QVariantMap variantMapFromJS(const QV4::Object *o);
681
682 static bool metaTypeFromJS(const Value &value, QMetaType type, void *data);
683 QV4::ReturnedValue metaTypeToJS(QMetaType type, const void *data);
684
685 int maxJSStackSize() const;
686 int maxGCStackSize() const;
687
688 bool checkStackLimits();
689 int safeForAllocLength(qint64 len64);
690
691 bool canJIT(Function *f = nullptr)
692 {
693#if QT_CONFIG(qml_jit)
694 if (!m_canAllocateExecutableMemory)
695 return false;
696 if (f) {
697 return f->kind != Function::AotCompiled
698 && !f->isGenerator()
699 && f->interpreterCallCount >= s_jitCallCountThreshold;
700 }
701 return true;
702#else
703 Q_UNUSED(f);
704 return false;
705#endif
706 }
707
709 void initQmlGlobalObject();
710 void initializeGlobal();
711 void createQtObject();
712
713 void freezeObject(const QV4::Value &value);
714 void lockObject(const QV4::Value &value);
715
716 // Return the list of illegal id names (the names of the properties on the global object)
717 const QSet<QString> &illegalNames() const;
718
719#if QT_CONFIG(qml_xml_http_request)
720 void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
721#endif
722
723 void setQmlEngine(QQmlEngine *engine);
724
725 QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
726
727 // used for console.time(), console.timeEnd()
728 void startTimer(const QString &timerName);
729 qint64 stopTimer(const QString &timerName, bool *wasRunning);
730
731 // used for console.count()
732 int consoleCountHelper(const QString &file, quint16 line, quint16 column);
733
734 struct Deletable {
735 virtual ~Deletable() {}
736 };
737
738 static QMutex *registrationMutex();
739 static int registerExtension();
740
741 void setExtensionData(int, Deletable *);
743 {
744 if (index < m_extensionData.size())
745 return m_extensionData[index];
746 else
747 return nullptr;
748 }
749
750 double localTZA = 0.0; // local timezone, initialized at startup
751
752 QQmlRefPointer<ExecutableCompilationUnit> compileModule(const QUrl &url);
753 QQmlRefPointer<ExecutableCompilationUnit> compileModule(
754 const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
755
756 QQmlRefPointer<ExecutableCompilationUnit> compilationUnitForUrl(const QUrl &url) const;
757
758 QQmlRefPointer<ExecutableCompilationUnit> executableCompilationUnit(
759 QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&unit);
760
761 QQmlRefPointer<ExecutableCompilationUnit> insertCompilationUnit(
762 QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&unit);
763
764 QMultiHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> compilationUnits() const
765 {
766 return m_compilationUnits;
767 }
768 void clearCompilationUnits() { m_compilationUnits.clear(); }
769 void trimCompilationUnits();
770
771 QV4::Value *registerNativeModule(const QUrl &url, const QV4::Value &module);
772
773 struct Module {
774 QQmlRefPointer<ExecutableCompilationUnit> compiled;
775
776 // We can pass a raw value pointer here, but nowhere else. See below.
777 Value *native = nullptr;
778 };
779
780 Module moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const;
781 Module loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr);
782
783 DiskCacheOptions diskCacheOptions() const;
784
785 void callInContext(QV4::Function *function, QObject *self, QV4::ExecutionContext *ctxt,
786 int argc, void **args, QMetaType *types);
787 QV4::ReturnedValue callInContext(QV4::Function *function, QObject *self,
788 QV4::ExecutionContext *ctxt, int argc, const QV4::Value *argv);
789
790 QV4::ReturnedValue fromData(
791 QMetaType type, const void *ptr,
792 Heap::Object *parent = nullptr, int property = -1, uint flags = 0);
793
794
795 static void setMaxCallDepth(int maxCallDepth) { s_maxCallDepth = maxCallDepth; }
796 static int maxCallDepth() { return s_maxCallDepth; }
797
798 template<typename Value>
800 {
801 if (v->isUndefined())
803 if (v->isNull())
805 if (v->isBoolean())
806 return QJSPrimitiveValue(v->toBoolean());
807 if (v->isInteger())
808 return QJSPrimitiveValue(v->integerValue());
809 if (v->isDouble())
810 return QJSPrimitiveValue(v->doubleValue());
811 bool ok;
812 const QString result = v->toQString(&ok);
814 }
815
816private:
817 template<int Frames>
819
820 static void initializeStaticMembers();
821
822 bool inStack(const void *current) const
823 {
824#if Q_STACK_GROWTH_DIRECTION > 0
825 return current < cppStackLimit && current >= cppStackBase;
826#else
827 return current > cppStackLimit && current <= cppStackBase;
828#endif
829 }
830
831 bool hasCppStackOverflow()
832 {
833 if (s_maxCallDepth >= 0)
834 return callDepth >= s_maxCallDepth;
835
836 if (inStack(currentStackPointer()))
837 return false;
838
839 // Double check the stack limits on failure.
840 // We may have moved to a different thread.
841 const StackProperties stack = stackProperties();
842 cppStackBase = stack.base;
843 cppStackLimit = stack.softLimit;
844 return !inStack(currentStackPointer());
845 }
846
847 bool hasJsStackOverflow() const
848 {
849 return jsStackTop > jsStackLimit;
850 }
851
852 bool hasStackOverflow()
853 {
854 return hasJsStackOverflow() || hasCppStackOverflow();
855 }
856
857 static int s_maxCallDepth;
858 static int s_jitCallCountThreshold;
859 static int s_maxJSStackSize;
860 static int s_maxGCStackSize;
861
862#if QT_CONFIG(qml_debug)
863 QScopedPointer<QV4::Debugging::Debugger> m_debugger;
864 QScopedPointer<QV4::Profiling::Profiler> m_profiler;
865#endif
866 QSet<QString> m_illegalNames;
867
868 // used by generated Promise objects to handle 'then' events
869 QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler;
870
871#if QT_CONFIG(qml_xml_http_request)
872 void *m_xmlHttpRequestData;
873#endif
874
875 QQmlEngine *m_qmlEngine;
876
877 QQmlDelayedCallQueue m_delayedCallQueue;
878
879 QElapsedTimer m_time;
880 QHash<QString, qint64> m_startedTimers;
881
882 QHash<QString, quint32> m_consoleCount;
883
884 QVector<Deletable *> m_extensionData;
885
886 QMultiHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> m_compilationUnits;
887
888 // QV4::PersistentValue would be preferred, but using QHash will create copies,
889 // and QV4::PersistentValue doesn't like creating copies.
890 // Instead, we allocate a raw pointer using the same manual memory management
891 // technique in QV4::PersistentValue.
892 QHash<QUrl, Value *> nativeModules;
893};
894
895#define CHECK_STACK_LIMITS(v4) \
896 if (v4->checkStackLimits()) \
897 return Encode::undefined(); \
898 ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
899
900template<int Frames = 1>
902{
904
906 {
907 if (ExecutionEngine::s_maxCallDepth >= 0)
908 ee->callDepth += Frames;
909 }
910
912 {
913 if (ExecutionEngine::s_maxCallDepth >= 0)
914 ee->callDepth -= Frames;
915 }
916
917 bool hasOverflow() const
918 {
919 return ee->hasCppStackOverflow();
920 }
921};
922
924{
925 if (Q_UNLIKELY(hasStackOverflow())) {
926 throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
927 return true;
928 }
929
930 return false;
931}
932
933Q_DECLARE_OPERATORS_FOR_FLAGS(ExecutionEngine::DiskCacheOptions);
934
935} // namespace QV4
936
938
939#endif // QV4ENGINE_H
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatetime.h:283
\inmodule QtCore \reentrant
Definition qdatetime.h:29
\inmodule QtCore
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:75
\inmodule QtCore
Definition qmetatype.h:341
\inmodule QtCore
Definition qmutex.h:281
The QNetworkAccessManager class allows the application to send network requests and receive replies.
\inmodule QtCore
Definition qobject.h:103
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
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
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
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore \reentrant
Definition qdatetime.h:215
\inmodule QtCore
Definition qurl.h:94
ScarceResourceData(const QMetaType type, const void *data)
\inmodule QtCore
Definition qvariant.h:65
EGLContext ctx
QString text
QDate date
[1]
Combined button and popup list for selecting options.
@ NTypedArrayTypes
quint64 ReturnedValue
StackProperties stackProperties()
const void * currentStackPointer()
Definition qctf_p.h:75
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
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLenum type
GLbitfield flags
GLuint GLsizei const GLchar * message
GLuint name
GLenum GLenum GLsizei void GLsizei void * column
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLenum array
GLuint64EXT * result
[6]
GLubyte * pattern
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:75
static QUrl resolvedUrl(const QUrl &url, const QQmlRefPointer< QQmlContextData > &context)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
#define Q_UNUSED(x)
#define QML_NEARLY_ALWAYS_INLINE
unsigned int quint32
Definition qtypes.h:50
unsigned short quint16
Definition qtypes.h:48
size_t quintptr
Definition qtypes.h:167
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, JSToQVariantConversionBehavior conversionBehavior, 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
QMultiHash< QUrl, QQmlRefPointer< ExecutableCompilationUnit > > compilationUnits() const
Object * numberPrototype() const
String * id_lastIndex() const
String * id_false() const
FunctionObject * urlCtor() const
QML_NEARLY_ALWAYS_INLINE Value * jsAlloca(int nValues)
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
Heap::String * newString(char16_t c)
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
TypeLoader * typeLoader()
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