1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 #ifndef QV4ENGINE_H
40 #define QV4ENGINE_H
41
42 //
43 // W A R N I N G
44 // -------------
45 //
46 // This file is not part of the Qt API. It exists purely as an
47 // implementation detail. This header file may change from version to
48 // version without notice, or even be removed.
49 //
50 // We mean it.
51 //
52
53 #include "qv4global_p.h"
54 #include "qv4managed_p.h"
55 #include "qv4context_p.h"
56 #include "qv4stackframe_p.h"
57 #include <private/qintrusivelist_p.h>
58 #include "qv4enginebase_p.h"
59 #include <private/qqmlrefcount_p.h>
60 #include <private/qqmldelayedcallqueue_p.h>
61 #include <QtCore/qelapsedtimer.h>
62 #include <QtCore/qmutex.h>
63
64 #include "qv4function_p.h"
65 #include <private/qv4compileddata_p.h>
66 #include <private/qv4executablecompilationunit_p.h>
67
68 namespace WTF {
69 class BumpPointerAllocator;
70 class PageAllocation;
71 }
72
73 #define V4_DEFINE_EXTENSION(dataclass, datafunction) \
74 static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
75 { \
76 static int extensionId = -1; \
77 if (extensionId == -1) { \
78 QV4::ExecutionEngine::registrationMutex()->lock(); \
79 if (extensionId == -1) \
80 extensionId = QV4::ExecutionEngine::registerExtension(); \
81 QV4::ExecutionEngine::registrationMutex()->unlock(); \
82 } \
83 dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
84 if (!rv) { \
85 rv = new dataclass(engine); \
86 engine->setExtensionData(extensionId, rv); \
87 } \
88 return rv; \
89 } \
90
91
92 QT_BEGIN_NAMESPACE
93
94 #if QT_CONFIG(qml_network)
95 class QNetworkAccessManager;
96
97 namespace QV4 {
98 struct QObjectMethod;
99 namespace detail {
100 QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine);
101 }
102 }
103 #else
104 namespace QV4 { struct QObjectMethod; }
105 #endif // qml_network
106
107 // Used to allow a QObject method take and return raw V4 handles without having to expose
108 // 48 in the public API.
109 // Use like this:
110 // class MyClass : public QObject {
111 // Q_OBJECT
112 // ...
113 // Q_INVOKABLE void myMethod(QQmlV4Function*);
114 // };
115 // The QQmlV8Function - and consequently the arguments and return value - only remains
116 // valid during the call. If the return value isn't set within myMethod(), the will return
117 // undefined.
118
119 class QQmlV4Function
120 {
121 public:
length()122 int length() const { return callData->argc(); }
123 QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
setReturnValue(QV4::ReturnedValue rv)124 void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
v4engine()125 QV4::ExecutionEngine *v4engine() const { return e; }
126 private:
127 friend struct QV4::QObjectMethod;
128 QQmlV4Function();
129 QQmlV4Function(const QQmlV4Function &);
130 QQmlV4Function &operator=(const QQmlV4Function &);
131
QQmlV4Function(QV4::CallData * callData,QV4::Value * retVal,QV4::ExecutionEngine * e)132 QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
133 : callData(callData), retVal(retVal), e(e)
134 {
135 callData->thisObject = QV4::Encode::undefined();
136 }
137
138 QV4::CallData *callData;
139 QV4::Value *retVal;
140 QV4::ExecutionEngine *e;
141 };
142
143 class QQmlError;
144 class QJSEngine;
145 class QQmlEngine;
146 class QQmlContextData;
147
148 namespace QV4 {
149 namespace Debugging {
150 class Debugger;
151 } // namespace Debugging
152 namespace Profiling {
153 class Profiler;
154 } // namespace Profiling
155 namespace CompiledData {
156 struct CompilationUnit;
157 }
158
159 namespace Heap {
160 struct Module;
161 };
162
163 struct Function;
164
165 namespace Promise {
166 class ReactionHandler;
167 };
168
169 struct Q_QML_EXPORT ExecutionEngine : public EngineBase
170 {
171 private:
172 static qint32 maxCallDepth;
173
174 friend struct ExecutionContextSaver;
175 friend struct ExecutionContext;
176 friend struct Heap::ExecutionContext;
177 public:
178 ExecutableAllocator *executableAllocator;
179 ExecutableAllocator *regExpAllocator;
180
181 WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
182
183 WTF::PageAllocation *jsStack;
184
185 WTF::PageAllocation *gcStack;
186
jsAllocaExecutionEngine187 QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) {
188 Value *ptr = jsStackTop;
189 jsStackTop = ptr + nValues;
190 return ptr;
191 }
192
193 Function *globalCode;
194
jsEngineExecutionEngine195 QJSEngine *jsEngine() const { return publicEngine; }
qmlEngineExecutionEngine196 QQmlEngine *qmlEngine() const { return m_qmlEngine; }
197 QJSEngine *publicEngine;
198
199 enum JSObjects {
200 RootContext,
201 ScriptContext,
202 IntegerNull, // Has to come after the RootContext to make the context stack safe
203 ObjectProto,
204 SymbolProto,
205 ArrayProto,
206 ArrayProtoValues,
207 PropertyListProto,
208 StringProto,
209 NumberProto,
210 BooleanProto,
211 DateProto,
212 FunctionProto,
213 GeneratorProto,
214 RegExpProto,
215 ErrorProto,
216 EvalErrorProto,
217 RangeErrorProto,
218 ReferenceErrorProto,
219 SyntaxErrorProto,
220 TypeErrorProto,
221 URIErrorProto,
222 PromiseProto,
223 VariantProto,
224 #if QT_CONFIG(qml_sequence_object)
225 SequenceProto,
226 #endif
227 SharedArrayBufferProto,
228 ArrayBufferProto,
229 DataViewProto,
230 WeakSetProto,
231 SetProto,
232 WeakMapProto,
233 MapProto,
234 IntrinsicTypedArrayProto,
235 ValueTypeProto,
236 SignalHandlerProto,
237 IteratorProto,
238 ForInIteratorProto,
239 SetIteratorProto,
240 MapIteratorProto,
241 ArrayIteratorProto,
242 StringIteratorProto,
243
244 Object_Ctor,
245 String_Ctor,
246 Symbol_Ctor,
247 Number_Ctor,
248 Boolean_Ctor,
249 Array_Ctor,
250 Function_Ctor,
251 GeneratorFunction_Ctor,
252 Date_Ctor,
253 RegExp_Ctor,
254 Error_Ctor,
255 EvalError_Ctor,
256 RangeError_Ctor,
257 ReferenceError_Ctor,
258 SyntaxError_Ctor,
259 TypeError_Ctor,
260 URIError_Ctor,
261 SharedArrayBuffer_Ctor,
262 Promise_Ctor,
263 ArrayBuffer_Ctor,
264 DataView_Ctor,
265 WeakSet_Ctor,
266 Set_Ctor,
267 WeakMap_Ctor,
268 Map_Ctor,
269 IntrinsicTypedArray_Ctor,
270
271 GetSymbolSpecies,
272
273 Eval_Function,
274 GetStack_Function,
275 ThrowerObject,
276 NJSObjects
277 };
278 Value *jsObjects;
279 enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
280
rootContextExecutionEngine281 ExecutionContext *rootContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + RootContext); }
scriptContextExecutionEngine282 ExecutionContext *scriptContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + ScriptContext); }
setScriptContextExecutionEngine283 void setScriptContext(ReturnedValue c) { jsObjects[ScriptContext] = c; }
objectCtorExecutionEngine284 FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
stringCtorExecutionEngine285 FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
symbolCtorExecutionEngine286 FunctionObject *symbolCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Symbol_Ctor); }
numberCtorExecutionEngine287 FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
booleanCtorExecutionEngine288 FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
arrayCtorExecutionEngine289 FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
functionCtorExecutionEngine290 FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
generatorFunctionCtorExecutionEngine291 FunctionObject *generatorFunctionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + GeneratorFunction_Ctor); }
dateCtorExecutionEngine292 FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
regExpCtorExecutionEngine293 FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
errorCtorExecutionEngine294 FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
evalErrorCtorExecutionEngine295 FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
rangeErrorCtorExecutionEngine296 FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
referenceErrorCtorExecutionEngine297 FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
syntaxErrorCtorExecutionEngine298 FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
typeErrorCtorExecutionEngine299 FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
uRIErrorCtorExecutionEngine300 FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
sharedArrayBufferCtorExecutionEngine301 FunctionObject *sharedArrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SharedArrayBuffer_Ctor); }
promiseCtorExecutionEngine302 FunctionObject *promiseCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Promise_Ctor); }
arrayBufferCtorExecutionEngine303 FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
dataViewCtorExecutionEngine304 FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
weakSetCtorExecutionEngine305 FunctionObject *weakSetCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakSet_Ctor); }
setCtorExecutionEngine306 FunctionObject *setCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Set_Ctor); }
weakMapCtorExecutionEngine307 FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
mapCtorExecutionEngine308 FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
intrinsicTypedArrayCtorExecutionEngine309 FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
310 FunctionObject *typedArrayCtors;
311
getSymbolSpeciesExecutionEngine312 FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
313
objectPrototypeExecutionEngine314 Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
symbolPrototypeExecutionEngine315 Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); }
arrayPrototypeExecutionEngine316 Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
arrayProtoValuesExecutionEngine317 Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); }
propertyListPrototypeExecutionEngine318 Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
stringPrototypeExecutionEngine319 Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
numberPrototypeExecutionEngine320 Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
booleanPrototypeExecutionEngine321 Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
datePrototypeExecutionEngine322 Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
functionPrototypeExecutionEngine323 Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
generatorPrototypeExecutionEngine324 Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); }
regExpPrototypeExecutionEngine325 Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
errorPrototypeExecutionEngine326 Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
evalErrorPrototypeExecutionEngine327 Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
rangeErrorPrototypeExecutionEngine328 Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
referenceErrorPrototypeExecutionEngine329 Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
syntaxErrorPrototypeExecutionEngine330 Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
typeErrorPrototypeExecutionEngine331 Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
uRIErrorPrototypeExecutionEngine332 Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
promisePrototypeExecutionEngine333 Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); }
variantPrototypeExecutionEngine334 Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
335 #if QT_CONFIG(qml_sequence_object)
sequencePrototypeExecutionEngine336 Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
337 #endif
338
sharedArrayBufferPrototypeExecutionEngine339 Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); }
arrayBufferPrototypeExecutionEngine340 Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
dataViewPrototypeExecutionEngine341 Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
weakSetPrototypeExecutionEngine342 Object *weakSetPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakSetProto); }
setPrototypeExecutionEngine343 Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); }
weakMapPrototypeExecutionEngine344 Object *weakMapPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakMapProto); }
mapPrototypeExecutionEngine345 Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); }
intrinsicTypedArrayPrototypeExecutionEngine346 Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + IntrinsicTypedArrayProto); }
347 Object *typedArrayPrototype;
348
valueTypeWrapperPrototypeExecutionEngine349 Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
signalHandlerPrototypeExecutionEngine350 Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
iteratorPrototypeExecutionEngine351 Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
forInIteratorPrototypeExecutionEngine352 Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
setIteratorPrototypeExecutionEngine353 Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
mapIteratorPrototypeExecutionEngine354 Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
arrayIteratorPrototypeExecutionEngine355 Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
stringIteratorPrototypeExecutionEngine356 Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
357
evalFunctionExecutionEngine358 EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
getStackFunctionExecutionEngine359 FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
throwerExecutionEngine360 FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
361
362 #if QT_CONFIG(qml_network)
363 QNetworkAccessManager* (*networkAccessManager)(ExecutionEngine*) = detail::getNetworkAccessManager;
364 #endif
365
366 enum JSStrings {
367 String_Empty,
368 String_undefined,
369 String_null,
370 String_true,
371 String_false,
372 String_boolean,
373 String_number,
374 String_string,
375 String_default,
376 String_symbol,
377 String_object,
378 String_function,
379 String_length,
380 String_prototype,
381 String_constructor,
382 String_arguments,
383 String_caller,
384 String_callee,
385 String_this,
386 String___proto__,
387 String_enumerable,
388 String_configurable,
389 String_writable,
390 String_value,
391 String_get,
392 String_set,
393 String_eval,
394 String_uintMax,
395 String_name,
396 String_index,
397 String_input,
398 String_toString,
399 String_toLocaleString,
400 String_destroy,
401 String_valueOf,
402 String_byteLength,
403 String_byteOffset,
404 String_buffer,
405 String_lastIndex,
406 String_next,
407 String_done,
408 String_return,
409 String_throw,
410 String_global,
411 String_ignoreCase,
412 String_multiline,
413 String_unicode,
414 String_sticky,
415 String_source,
416 String_flags,
417
418 NJSStrings
419 };
420 Value *jsStrings;
421
422 enum JSSymbols {
423 Symbol_hasInstance,
424 Symbol_isConcatSpreadable,
425 Symbol_iterator,
426 Symbol_match,
427 Symbol_replace,
428 Symbol_search,
429 Symbol_species,
430 Symbol_split,
431 Symbol_toPrimitive,
432 Symbol_toStringTag,
433 Symbol_unscopables,
434 Symbol_revokableProxy,
435 NJSSymbols
436 };
437 Value *jsSymbols;
438
id_emptyExecutionEngine439 String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
id_undefinedExecutionEngine440 String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
id_nullExecutionEngine441 String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
id_trueExecutionEngine442 String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
id_falseExecutionEngine443 String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
id_booleanExecutionEngine444 String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
id_numberExecutionEngine445 String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
id_stringExecutionEngine446 String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
id_defaultExecutionEngine447 String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); }
id_symbolExecutionEngine448 String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); }
id_objectExecutionEngine449 String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
id_functionExecutionEngine450 String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
id_lengthExecutionEngine451 String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
id_prototypeExecutionEngine452 String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
id_constructorExecutionEngine453 String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
id_argumentsExecutionEngine454 String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
id_callerExecutionEngine455 String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
id_calleeExecutionEngine456 String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
id_thisExecutionEngine457 String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
id___proto__ExecutionEngine458 String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
id_enumerableExecutionEngine459 String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
id_configurableExecutionEngine460 String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
id_writableExecutionEngine461 String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
id_valueExecutionEngine462 String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
id_getExecutionEngine463 String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
id_setExecutionEngine464 String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
id_evalExecutionEngine465 String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
id_uintMaxExecutionEngine466 String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
id_nameExecutionEngine467 String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
id_indexExecutionEngine468 String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
id_inputExecutionEngine469 String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
id_toStringExecutionEngine470 String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
id_toLocaleStringExecutionEngine471 String *id_toLocaleString() const { return reinterpret_cast<String *>(jsStrings + String_toLocaleString); }
id_destroyExecutionEngine472 String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
id_valueOfExecutionEngine473 String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
id_byteLengthExecutionEngine474 String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
id_byteOffsetExecutionEngine475 String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
id_bufferExecutionEngine476 String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
id_lastIndexExecutionEngine477 String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
id_nextExecutionEngine478 String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
id_doneExecutionEngine479 String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
id_returnExecutionEngine480 String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); }
id_throwExecutionEngine481 String *id_throw() const { return reinterpret_cast<String *>(jsStrings + String_throw); }
id_globalExecutionEngine482 String *id_global() const { return reinterpret_cast<String *>(jsStrings + String_global); }
id_ignoreCaseExecutionEngine483 String *id_ignoreCase() const { return reinterpret_cast<String *>(jsStrings + String_ignoreCase); }
id_multilineExecutionEngine484 String *id_multiline() const { return reinterpret_cast<String *>(jsStrings + String_multiline); }
id_unicodeExecutionEngine485 String *id_unicode() const { return reinterpret_cast<String *>(jsStrings + String_unicode); }
id_stickyExecutionEngine486 String *id_sticky() const { return reinterpret_cast<String *>(jsStrings + String_sticky); }
id_sourceExecutionEngine487 String *id_source() const { return reinterpret_cast<String *>(jsStrings + String_source); }
id_flagsExecutionEngine488 String *id_flags() const { return reinterpret_cast<String *>(jsStrings + String_flags); }
489
symbol_hasInstanceExecutionEngine490 Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
symbol_isConcatSpreadableExecutionEngine491 Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
symbol_iteratorExecutionEngine492 Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
symbol_matchExecutionEngine493 Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
symbol_replaceExecutionEngine494 Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
symbol_searchExecutionEngine495 Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
symbol_speciesExecutionEngine496 Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
symbol_splitExecutionEngine497 Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
symbol_toPrimitiveExecutionEngine498 Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
symbol_toStringTagExecutionEngine499 Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
symbol_unscopablesExecutionEngine500 Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
symbol_revokableProxyExecutionEngine501 Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
502
503 QIntrusiveList<ExecutableCompilationUnit, &ExecutableCompilationUnit::nextCompilationUnit> compilationUnits;
504
505 quint32 m_engineId;
506
507 RegExpCache *regExpCache;
508
509 // Scarce resources are "exceptionally high cost" QVariant types where allowing the
510 // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
511 // out-of-resource situations. When such a resource is passed into JavaScript we
512 // add it to the scarceResources list and it is destroyed when we return from the
513 // JavaScript execution that created it. The user can prevent this behavior by
514 // calling preserve() on the object which removes it from this scarceResource list.
515 class ScarceResourceData {
516 public:
dataExecutionEngine517 ScarceResourceData(const QVariant &data = QVariant()) : data(data) {}
518 QVariant data;
519 QIntrusiveListNode node;
520 };
521 QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
522
523 // Normally the JS wrappers for QObjects are stored in the QQmlData/QObjectPrivate,
524 // but any time a QObject is wrapped a second time in another engine, we have to do
525 // bookkeeping.
526 MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects;
527 #if QT_CONFIG(qml_jit)
528 const bool m_canAllocateExecutableMemory;
529 #endif
530
531 quintptr protoIdCount = 1;
532
533 ExecutionEngine(QJSEngine *jsEngine = nullptr);
534 ~ExecutionEngine();
535
536 #if !QT_CONFIG(qml_debug)
debuggerExecutionEngine537 QV4::Debugging::Debugger *debugger() const { return nullptr; }
profilerExecutionEngine538 QV4::Profiling::Profiler *profiler() const { return nullptr; }
539
setDebuggerExecutionEngine540 void setDebugger(Debugging::Debugger *) {}
setProfilerExecutionEngine541 void setProfiler(Profiling::Profiler *) {}
542 #else
debuggerExecutionEngine543 QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
profilerExecutionEngine544 QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); }
545
546 void setDebugger(Debugging::Debugger *debugger);
547 void setProfiler(Profiling::Profiler *profiler);
548 #endif // QT_CONFIG(qml_debug)
549
550 ExecutionContext *currentContext() const;
551
552 // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
newProtoIdExecutionEngine553 quintptr newProtoId() { return (protoIdCount += 2); }
554
555 Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
556
557 Heap::Object *newObject();
558 Heap::Object *newObject(Heap::InternalClass *internalClass);
559
560 Heap::String *newString(const QString &s = QString());
561 Heap::String *newIdentifier(const QString &text);
562
563 Heap::Object *newStringObject(const String *string);
564 Heap::Object *newSymbolObject(const Symbol *symbol);
565 Heap::Object *newNumberObject(double value);
566 Heap::Object *newBooleanObject(bool b);
567
568 Heap::ArrayObject *newArrayObject(int count = 0);
569 Heap::ArrayObject *newArrayObject(const Value *values, int length);
570 Heap::ArrayObject *newArrayObject(const QStringList &list);
571 Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic);
572
573 Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
574 Heap::ArrayBuffer *newArrayBuffer(size_t length);
575
576 Heap::DateObject *newDateObject(const Value &value);
577 Heap::DateObject *newDateObject(const QDateTime &dt);
578 Heap::DateObject *newDateObjectFromTime(const QTime &t);
579
580 Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
581 Heap::RegExpObject *newRegExpObject(RegExp *re);
582 Heap::RegExpObject *newRegExpObject(const QRegExp &re);
583 #if QT_CONFIG(regularexpression)
584 Heap::RegExpObject *newRegExpObject(const QRegularExpression &re);
585 #endif
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 QVariant &v);
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 Heap::QmlContext *qmlContext() const;
611 QObject *qmlScopeObject() const;
612 QQmlContextData *callingQmlContext() const;
613
614
615 StackTrace stackTrace(int frameLimit = -1) const;
616 QUrl resolvedUrl(const QString &file);
617
618 void markObjects(MarkStack *markStack);
619
620 void initRootContext();
621
622 Heap::InternalClass *newClass(Heap::InternalClass *other);
623
624 StackTrace exceptionStackTrace;
625
626 ReturnedValue throwError(const Value &value);
627 ReturnedValue catchException(StackTrace *trace = nullptr);
628
629 ReturnedValue throwError(const QString &message);
630 ReturnedValue throwSyntaxError(const QString &message);
631 ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column);
632 ReturnedValue throwTypeError();
633 ReturnedValue throwTypeError(const QString &message);
634 ReturnedValue throwReferenceError(const Value &value);
635 ReturnedValue throwReferenceError(const QString &name);
636 ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column);
637 ReturnedValue throwRangeError(const Value &value);
638 ReturnedValue throwRangeError(const QString &message);
639 ReturnedValue throwURIError(const Value &msg);
640 ReturnedValue throwUnimplemented(const QString &message);
641
642 // Use only inside catch(...) -- will re-throw if no JS exception
643 QQmlError catchExceptionAsQmlError();
644
645 // variant conversions
646 QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
647 QV4::ReturnedValue fromVariant(const QVariant &);
648
649 QVariantMap variantMapFromJS(const QV4::Object *o);
650
651 bool metaTypeFromJS(const Value *value, int type, void *data);
652 QV4::ReturnedValue metaTypeToJS(int type, const void *data);
653
654 int maxJSStackSize() const;
655 int maxGCStackSize() const;
656
657 bool checkStackLimits();
658
659 bool canJIT(Function *f = nullptr)
660 {
661 #if QT_CONFIG(qml_jit)
662 if (!m_canAllocateExecutableMemory)
663 return false;
664 if (f)
665 return !f->isGenerator() && f->interpreterCallCount >= jitCallCountThreshold;
666 return true;
667 #else
668 Q_UNUSED(f);
669 return false;
670 #endif
671 }
672
673 QV4::ReturnedValue global();
674 void initQmlGlobalObject();
675 void initializeGlobal();
676
677 void freezeObject(const QV4::Value &value);
678
679 // Return the list of illegal id names (the names of the properties on the global object)
680 const QSet<QString> &illegalNames() const;
681
682 #if QT_CONFIG(qml_xml_http_request)
xmlHttpRequestDataExecutionEngine683 void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
684 #endif
685
686 void setQmlEngine(QQmlEngine *engine);
687
delayedCallQueueExecutionEngine688 QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
689
690 // used for console.time(), console.timeEnd()
691 void startTimer(const QString &timerName);
692 qint64 stopTimer(const QString &timerName, bool *wasRunning);
693
694 // used for console.count()
695 int consoleCountHelper(const QString &file, quint16 line, quint16 column);
696
697 struct Deletable {
~DeletableExecutionEngine::Deletable698 virtual ~Deletable() {}
699 };
700
701 static QMutex *registrationMutex();
702 static int registerExtension();
703
704 void setExtensionData(int, Deletable *);
extensionDataExecutionEngine705 Deletable *extensionData(int index) const
706 {
707 if (index < m_extensionData.count())
708 return m_extensionData[index];
709 else
710 return nullptr;
711 }
712
713 double localTZA = 0.0; // local timezone, initialized at startup
714
715 QQmlRefPointer<ExecutableCompilationUnit> compileModule(const QUrl &url);
716 QQmlRefPointer<ExecutableCompilationUnit> compileModule(
717 const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
718
719 mutable QMutex moduleMutex;
720 QHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> modules;
721 void injectModule(const QQmlRefPointer<ExecutableCompilationUnit> &moduleUnit);
722 QQmlRefPointer<ExecutableCompilationUnit> moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const;
723 QQmlRefPointer<ExecutableCompilationUnit> loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr);
724
725 private:
726 #if QT_CONFIG(qml_debug)
727 QScopedPointer<QV4::Debugging::Debugger> m_debugger;
728 QScopedPointer<QV4::Profiling::Profiler> m_profiler;
729 #endif
730 QSet<QString> m_illegalNames;
731 int jitCallCountThreshold;
732
733 // used by generated Promise objects to handle 'then' events
734 QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler;
735
736 #if QT_CONFIG(qml_xml_http_request)
737 void *m_xmlHttpRequestData;
738 #endif
739
740 QQmlEngine *m_qmlEngine;
741
742 QQmlDelayedCallQueue m_delayedCallQueue;
743
744 QElapsedTimer m_time;
745 QHash<QString, qint64> m_startedTimers;
746
747 QHash<QString, quint32> m_consoleCount;
748
749 QVector<Deletable *> m_extensionData;
750
751 int m_maxJSStackSize = 4 * 1024 * 1024;
752 int m_maxGCStackSize = 2 * 1024 * 1024;
753 };
754
755 #define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
756 ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
757
758 struct ExecutionEngineCallDepthRecorder
759 {
760 ExecutionEngine *ee;
761
ExecutionEngineCallDepthRecorderExecutionEngineCallDepthRecorder762 ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; }
~ExecutionEngineCallDepthRecorderExecutionEngineCallDepthRecorder763 ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; }
764 };
765
checkStackLimits()766 inline bool ExecutionEngine::checkStackLimits()
767 {
768 if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) {
769 throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
770 return true;
771 }
772
773 return false;
774 }
775
776 } // namespace QV4
777
778 QT_END_NAMESPACE
779
780 #endif // QV4ENGINE_H
781