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
68namespace WTF {
69class BumpPointerAllocator;
70class 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
92QT_BEGIN_NAMESPACE
93
94#if QT_CONFIG(qml_network)
95class QNetworkAccessManager;
96
97namespace QV4 {
98struct QObjectMethod;
99namespace detail {
100QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine);
101}
102}
103#else
104namespace 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
119class QQmlV4Function
120{
121public:
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()); }
124 void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
125 QV4::ExecutionEngine *v4engine() const { return e; }
126private:
127 friend struct QV4::QObjectMethod;
128 QQmlV4Function();
129 QQmlV4Function(const QQmlV4Function &);
130 QQmlV4Function &operator=(const QQmlV4Function &);
131
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
143class QQmlError;
144class QJSEngine;
145class QQmlEngine;
146class QQmlContextData;
147
148namespace QV4 {
149namespace Debugging {
150class Debugger;
151} // namespace Debugging
152namespace Profiling {
153class Profiler;
154} // namespace Profiling
155namespace CompiledData {
156struct CompilationUnit;
157}
158
159namespace Heap {
160struct Module;
161};
162
163struct Function;
164
165namespace Promise {
166class ReactionHandler;
167};
168
169struct Q_QML_EXPORT ExecutionEngine : public EngineBase
170{
171private:
172 static qint32 maxCallDepth;
173
174 friend struct ExecutionContextSaver;
175 friend struct ExecutionContext;
176 friend struct Heap::ExecutionContext;
177public:
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
187 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
195 QJSEngine *jsEngine() const { return publicEngine; }
196 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
281 ExecutionContext *rootContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + RootContext); }
282 ExecutionContext *scriptContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + ScriptContext); }
283 void setScriptContext(ReturnedValue c) { jsObjects[ScriptContext] = c; }
284 FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
285 FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
286 FunctionObject *symbolCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Symbol_Ctor); }
287 FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
288 FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
289 FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
290 FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
291 FunctionObject *generatorFunctionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + GeneratorFunction_Ctor); }
292 FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
293 FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
294 FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
295 FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
296 FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
297 FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
298 FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
299 FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
300 FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
301 FunctionObject *sharedArrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SharedArrayBuffer_Ctor); }
302 FunctionObject *promiseCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Promise_Ctor); }
303 FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
304 FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
305 FunctionObject *weakSetCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakSet_Ctor); }
306 FunctionObject *setCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Set_Ctor); }
307 FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
308 FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
309 FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
310 FunctionObject *typedArrayCtors;
311
312 FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
313
314 Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
315 Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); }
316 Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
317 Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); }
318 Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
319 Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
320 Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
321 Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
322 Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
323 Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
324 Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); }
325 Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
326 Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
327 Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
328 Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
329 Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
330 Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
331 Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
332 Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
333 Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); }
334 Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
335#if QT_CONFIG(qml_sequence_object)
336 Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
337#endif
338
339 Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); }
340 Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
341 Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
342 Object *weakSetPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakSetProto); }
343 Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); }
344 Object *weakMapPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakMapProto); }
345 Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); }
346 Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + IntrinsicTypedArrayProto); }
347 Object *typedArrayPrototype;
348
349 Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
350 Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
351 Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
352 Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
353 Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
354 Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
355 Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
356 Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
357
358 EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
359 FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
360 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
439 String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
440 String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
441 String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
442 String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
443 String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
444 String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
445 String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
446 String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
447 String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); }
448 String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); }
449 String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
450 String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
451 String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
452 String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
453 String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
454 String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
455 String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
456 String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
457 String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
458 String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
459 String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
460 String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
461 String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
462 String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
463 String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
464 String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
465 String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
466 String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
467 String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
468 String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
469 String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
470 String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
471 String *id_toLocaleString() const { return reinterpret_cast<String *>(jsStrings + String_toLocaleString); }
472 String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
473 String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
474 String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
475 String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
476 String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
477 String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
478 String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
479 String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
480 String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); }
481 String *id_throw() const { return reinterpret_cast<String *>(jsStrings + String_throw); }
482 String *id_global() const { return reinterpret_cast<String *>(jsStrings + String_global); }
483 String *id_ignoreCase() const { return reinterpret_cast<String *>(jsStrings + String_ignoreCase); }
484 String *id_multiline() const { return reinterpret_cast<String *>(jsStrings + String_multiline); }
485 String *id_unicode() const { return reinterpret_cast<String *>(jsStrings + String_unicode); }
486 String *id_sticky() const { return reinterpret_cast<String *>(jsStrings + String_sticky); }
487 String *id_source() const { return reinterpret_cast<String *>(jsStrings + String_source); }
488 String *id_flags() const { return reinterpret_cast<String *>(jsStrings + String_flags); }
489
490 Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
491 Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
492 Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
493 Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
494 Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
495 Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
496 Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
497 Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
498 Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
499 Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
500 Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
501 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:
517 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)
537 QV4::Debugging::Debugger *debugger() const { return nullptr; }
538 QV4::Profiling::Profiler *profiler() const { return nullptr; }
539
540 void setDebugger(Debugging::Debugger *) {}
541 void setProfiler(Profiling::Profiler *) {}
542#else
543 QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
544 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
553 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)
683 void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
684#endif
685
686 void setQmlEngine(QQmlEngine *engine);
687
688 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 {
698 virtual ~Deletable() {}
699 };
700
701 static QMutex *registrationMutex();
702 static int registerExtension();
703
704 void setExtensionData(int, Deletable *);
705 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
725private:
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
758struct ExecutionEngineCallDepthRecorder
759{
760 ExecutionEngine *ee;
761
762 ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; }
763 ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; }
764};
765
766inline 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
778QT_END_NAMESPACE
779
780#endif // QV4ENGINE_H
781

source code of qtdeclarative/src/qml/jsruntime/qv4engine_p.h