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
94namespace QV4 { struct QObjectMethod; }
95
96// Used to allow a QObject method take and return raw V4 handles without having to expose
97// 48 in the public API.
98// Use like this:
99// class MyClass : public QObject {
100// Q_OBJECT
101// ...
102// Q_INVOKABLE void myMethod(QQmlV4Function*);
103// };
104// The QQmlV8Function - and consequently the arguments and return value - only remains
105// valid during the call. If the return value isn't set within myMethod(), the will return
106// undefined.
107
108class QQmlV4Function
109{
110public:
111 int length() const { return callData->argc(); }
112 QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
113 void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
114 QV4::ExecutionEngine *v4engine() const { return e; }
115private:
116 friend struct QV4::QObjectMethod;
117 QQmlV4Function();
118 QQmlV4Function(const QQmlV4Function &);
119 QQmlV4Function &operator=(const QQmlV4Function &);
120
121 QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
122 : callData(callData), retVal(retVal), e(e)
123 {
124 callData->thisObject = QV4::Encode::undefined();
125 }
126
127 QV4::CallData *callData;
128 QV4::Value *retVal;
129 QV4::ExecutionEngine *e;
130};
131
132class QQmlError;
133class QJSEngine;
134class QQmlEngine;
135class QQmlContextData;
136
137namespace QV4 {
138namespace Debugging {
139class Debugger;
140} // namespace Debugging
141namespace Profiling {
142class Profiler;
143} // namespace Profiling
144namespace CompiledData {
145struct CompilationUnit;
146}
147
148namespace Heap {
149struct Module;
150};
151
152struct Function;
153
154namespace Promise {
155class ReactionHandler;
156};
157
158struct Q_QML_EXPORT ExecutionEngine : public EngineBase
159{
160private:
161 static qint32 maxCallDepth;
162
163 friend struct ExecutionContextSaver;
164 friend struct ExecutionContext;
165 friend struct Heap::ExecutionContext;
166public:
167 ExecutableAllocator *executableAllocator;
168 ExecutableAllocator *regExpAllocator;
169
170 WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
171
172 WTF::PageAllocation *jsStack;
173
174 WTF::PageAllocation *gcStack;
175
176 QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) {
177 Value *ptr = jsStackTop;
178 jsStackTop = ptr + nValues;
179 return ptr;
180 }
181
182 Function *globalCode;
183
184 QJSEngine *jsEngine() const { return publicEngine; }
185 QQmlEngine *qmlEngine() const { return m_qmlEngine; }
186 QJSEngine *publicEngine;
187
188 enum JSObjects {
189 RootContext,
190 ScriptContext,
191 IntegerNull, // Has to come after the RootContext to make the context stack safe
192 ObjectProto,
193 SymbolProto,
194 ArrayProto,
195 ArrayProtoValues,
196 PropertyListProto,
197 StringProto,
198 NumberProto,
199 BooleanProto,
200 DateProto,
201 FunctionProto,
202 GeneratorProto,
203 RegExpProto,
204 ErrorProto,
205 EvalErrorProto,
206 RangeErrorProto,
207 ReferenceErrorProto,
208 SyntaxErrorProto,
209 TypeErrorProto,
210 URIErrorProto,
211 PromiseProto,
212 VariantProto,
213#if QT_CONFIG(qml_sequence_object)
214 SequenceProto,
215#endif
216 SharedArrayBufferProto,
217 ArrayBufferProto,
218 DataViewProto,
219 WeakSetProto,
220 SetProto,
221 WeakMapProto,
222 MapProto,
223 IntrinsicTypedArrayProto,
224 ValueTypeProto,
225 SignalHandlerProto,
226 IteratorProto,
227 ForInIteratorProto,
228 SetIteratorProto,
229 MapIteratorProto,
230 ArrayIteratorProto,
231 StringIteratorProto,
232
233 Object_Ctor,
234 String_Ctor,
235 Symbol_Ctor,
236 Number_Ctor,
237 Boolean_Ctor,
238 Array_Ctor,
239 Function_Ctor,
240 GeneratorFunction_Ctor,
241 Date_Ctor,
242 RegExp_Ctor,
243 Error_Ctor,
244 EvalError_Ctor,
245 RangeError_Ctor,
246 ReferenceError_Ctor,
247 SyntaxError_Ctor,
248 TypeError_Ctor,
249 URIError_Ctor,
250 SharedArrayBuffer_Ctor,
251 Promise_Ctor,
252 ArrayBuffer_Ctor,
253 DataView_Ctor,
254 WeakSet_Ctor,
255 Set_Ctor,
256 WeakMap_Ctor,
257 Map_Ctor,
258 IntrinsicTypedArray_Ctor,
259
260 GetSymbolSpecies,
261
262 Eval_Function,
263 GetStack_Function,
264 ThrowerObject,
265 NJSObjects
266 };
267 Value *jsObjects;
268 enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
269
270 ExecutionContext *rootContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + RootContext); }
271 ExecutionContext *scriptContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + ScriptContext); }
272 void setScriptContext(ReturnedValue c) { jsObjects[ScriptContext] = c; }
273 FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
274 FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
275 FunctionObject *symbolCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Symbol_Ctor); }
276 FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
277 FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
278 FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
279 FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
280 FunctionObject *generatorFunctionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + GeneratorFunction_Ctor); }
281 FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
282 FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
283 FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
284 FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
285 FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
286 FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
287 FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
288 FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
289 FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
290 FunctionObject *sharedArrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SharedArrayBuffer_Ctor); }
291 FunctionObject *promiseCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Promise_Ctor); }
292 FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
293 FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
294 FunctionObject *weakSetCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakSet_Ctor); }
295 FunctionObject *setCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Set_Ctor); }
296 FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
297 FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
298 FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
299 FunctionObject *typedArrayCtors;
300
301 FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
302
303 Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
304 Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); }
305 Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
306 Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); }
307 Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
308 Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
309 Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
310 Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
311 Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
312 Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
313 Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); }
314 Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
315 Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
316 Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
317 Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
318 Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
319 Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
320 Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
321 Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
322 Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); }
323 Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
324#if QT_CONFIG(qml_sequence_object)
325 Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
326#endif
327
328 Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); }
329 Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
330 Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
331 Object *weakSetPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakSetProto); }
332 Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); }
333 Object *weakMapPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakMapProto); }
334 Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); }
335 Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + IntrinsicTypedArrayProto); }
336 Object *typedArrayPrototype;
337
338 Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
339 Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
340 Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
341 Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
342 Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
343 Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
344 Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
345 Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
346
347 EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
348 FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
349 FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
350
351 enum JSStrings {
352 String_Empty,
353 String_undefined,
354 String_null,
355 String_true,
356 String_false,
357 String_boolean,
358 String_number,
359 String_string,
360 String_default,
361 String_symbol,
362 String_object,
363 String_function,
364 String_length,
365 String_prototype,
366 String_constructor,
367 String_arguments,
368 String_caller,
369 String_callee,
370 String_this,
371 String___proto__,
372 String_enumerable,
373 String_configurable,
374 String_writable,
375 String_value,
376 String_get,
377 String_set,
378 String_eval,
379 String_uintMax,
380 String_name,
381 String_index,
382 String_input,
383 String_toString,
384 String_toLocaleString,
385 String_destroy,
386 String_valueOf,
387 String_byteLength,
388 String_byteOffset,
389 String_buffer,
390 String_lastIndex,
391 String_next,
392 String_done,
393 String_return,
394 String_throw,
395 String_global,
396 String_ignoreCase,
397 String_multiline,
398 String_unicode,
399 String_sticky,
400 String_source,
401 String_flags,
402
403 NJSStrings
404 };
405 Value *jsStrings;
406
407 enum JSSymbols {
408 Symbol_hasInstance,
409 Symbol_isConcatSpreadable,
410 Symbol_iterator,
411 Symbol_match,
412 Symbol_replace,
413 Symbol_search,
414 Symbol_species,
415 Symbol_split,
416 Symbol_toPrimitive,
417 Symbol_toStringTag,
418 Symbol_unscopables,
419 Symbol_revokableProxy,
420 NJSSymbols
421 };
422 Value *jsSymbols;
423
424 String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
425 String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
426 String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
427 String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
428 String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
429 String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
430 String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
431 String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
432 String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); }
433 String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); }
434 String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
435 String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
436 String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
437 String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
438 String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
439 String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
440 String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
441 String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
442 String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
443 String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
444 String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
445 String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
446 String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
447 String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
448 String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
449 String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
450 String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
451 String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
452 String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
453 String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
454 String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
455 String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
456 String *id_toLocaleString() const { return reinterpret_cast<String *>(jsStrings + String_toLocaleString); }
457 String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
458 String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
459 String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
460 String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
461 String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
462 String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
463 String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
464 String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
465 String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); }
466 String *id_throw() const { return reinterpret_cast<String *>(jsStrings + String_throw); }
467 String *id_global() const { return reinterpret_cast<String *>(jsStrings + String_global); }
468 String *id_ignoreCase() const { return reinterpret_cast<String *>(jsStrings + String_ignoreCase); }
469 String *id_multiline() const { return reinterpret_cast<String *>(jsStrings + String_multiline); }
470 String *id_unicode() const { return reinterpret_cast<String *>(jsStrings + String_unicode); }
471 String *id_sticky() const { return reinterpret_cast<String *>(jsStrings + String_sticky); }
472 String *id_source() const { return reinterpret_cast<String *>(jsStrings + String_source); }
473 String *id_flags() const { return reinterpret_cast<String *>(jsStrings + String_flags); }
474
475 Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
476 Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
477 Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
478 Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
479 Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
480 Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
481 Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
482 Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
483 Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
484 Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
485 Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
486 Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
487
488 QIntrusiveList<ExecutableCompilationUnit, &ExecutableCompilationUnit::nextCompilationUnit> compilationUnits;
489
490 quint32 m_engineId;
491
492 RegExpCache *regExpCache;
493
494 // Scarce resources are "exceptionally high cost" QVariant types where allowing the
495 // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
496 // out-of-resource situations. When such a resource is passed into JavaScript we
497 // add it to the scarceResources list and it is destroyed when we return from the
498 // JavaScript execution that created it. The user can prevent this behavior by
499 // calling preserve() on the object which removes it from this scarceResource list.
500 class ScarceResourceData {
501 public:
502 ScarceResourceData(const QVariant &data = QVariant()) : data(data) {}
503 QVariant data;
504 QIntrusiveListNode node;
505 };
506 QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
507
508 // Normally the JS wrappers for QObjects are stored in the QQmlData/QObjectPrivate,
509 // but any time a QObject is wrapped a second time in another engine, we have to do
510 // bookkeeping.
511 MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects;
512#if QT_CONFIG(qml_jit)
513 const bool m_canAllocateExecutableMemory;
514#endif
515
516 quintptr protoIdCount = 1;
517
518 ExecutionEngine(QJSEngine *jsEngine = nullptr);
519 ~ExecutionEngine();
520
521#if !QT_CONFIG(qml_debug)
522 QV4::Debugging::Debugger *debugger() const { return nullptr; }
523 QV4::Profiling::Profiler *profiler() const { return nullptr; }
524
525 void setDebugger(Debugging::Debugger *) {}
526 void setProfiler(Profiling::Profiler *) {}
527#else
528 QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
529 QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); }
530
531 void setDebugger(Debugging::Debugger *debugger);
532 void setProfiler(Profiling::Profiler *profiler);
533#endif // QT_CONFIG(qml_debug)
534
535 ExecutionContext *currentContext() const;
536
537 // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
538 quintptr newProtoId() { return (protoIdCount += 2); }
539
540 Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
541
542 Heap::Object *newObject();
543 Heap::Object *newObject(Heap::InternalClass *internalClass);
544
545 Heap::String *newString(const QString &s = QString());
546 Heap::String *newIdentifier(const QString &text);
547
548 Heap::Object *newStringObject(const String *string);
549 Heap::Object *newSymbolObject(const Symbol *symbol);
550 Heap::Object *newNumberObject(double value);
551 Heap::Object *newBooleanObject(bool b);
552
553 Heap::ArrayObject *newArrayObject(int count = 0);
554 Heap::ArrayObject *newArrayObject(const Value *values, int length);
555 Heap::ArrayObject *newArrayObject(const QStringList &list);
556 Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic);
557
558 Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
559 Heap::ArrayBuffer *newArrayBuffer(size_t length);
560
561 Heap::DateObject *newDateObject(const Value &value);
562 Heap::DateObject *newDateObject(const QDateTime &dt);
563 Heap::DateObject *newDateObjectFromTime(const QTime &t);
564
565 Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
566 Heap::RegExpObject *newRegExpObject(RegExp *re);
567 Heap::RegExpObject *newRegExpObject(const QRegExp &re);
568#if QT_CONFIG(regularexpression)
569 Heap::RegExpObject *newRegExpObject(const QRegularExpression &re);
570#endif
571
572 Heap::Object *newErrorObject(const Value &value);
573 Heap::Object *newErrorObject(const QString &message);
574 Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
575 Heap::Object *newSyntaxErrorObject(const QString &message);
576 Heap::Object *newReferenceErrorObject(const QString &message);
577 Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column);
578 Heap::Object *newTypeErrorObject(const QString &message);
579 Heap::Object *newRangeErrorObject(const QString &message);
580 Heap::Object *newURIErrorObject(const QString &message);
581 Heap::Object *newURIErrorObject(const Value &message);
582 Heap::Object *newEvalErrorObject(const QString &message);
583
584 Heap::PromiseObject *newPromiseObject();
585 Heap::Object *newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability);
586 Promise::ReactionHandler *getPromiseReactionHandler();
587
588 Heap::Object *newVariantObject(const QVariant &v);
589
590 Heap::Object *newForInIteratorObject(Object *o);
591 Heap::Object *newSetIteratorObject(Object *o);
592 Heap::Object *newMapIteratorObject(Object *o);
593 Heap::Object *newArrayIteratorObject(Object *o);
594
595 Heap::QmlContext *qmlContext() const;
596 QObject *qmlScopeObject() const;
597 QQmlContextData *callingQmlContext() const;
598
599
600 StackTrace stackTrace(int frameLimit = -1) const;
601 QUrl resolvedUrl(const QString &file);
602
603 void markObjects(MarkStack *markStack);
604
605 void initRootContext();
606
607 Heap::InternalClass *newClass(Heap::InternalClass *other);
608
609 StackTrace exceptionStackTrace;
610
611 ReturnedValue throwError(const Value &value);
612 ReturnedValue catchException(StackTrace *trace = nullptr);
613
614 ReturnedValue throwError(const QString &message);
615 ReturnedValue throwSyntaxError(const QString &message);
616 ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column);
617 ReturnedValue throwTypeError();
618 ReturnedValue throwTypeError(const QString &message);
619 ReturnedValue throwReferenceError(const Value &value);
620 ReturnedValue throwReferenceError(const QString &name);
621 ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column);
622 ReturnedValue throwRangeError(const Value &value);
623 ReturnedValue throwRangeError(const QString &message);
624 ReturnedValue throwURIError(const Value &msg);
625 ReturnedValue throwUnimplemented(const QString &message);
626
627 // Use only inside catch(...) -- will re-throw if no JS exception
628 QQmlError catchExceptionAsQmlError();
629
630 // variant conversions
631 QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
632 QV4::ReturnedValue fromVariant(const QVariant &);
633
634 QVariantMap variantMapFromJS(const QV4::Object *o);
635
636 bool metaTypeFromJS(const Value *value, int type, void *data);
637 QV4::ReturnedValue metaTypeToJS(int type, const void *data);
638
639 int maxJSStackSize() const;
640 int maxGCStackSize() const;
641
642 bool checkStackLimits();
643
644 bool canJIT(Function *f = nullptr)
645 {
646#if QT_CONFIG(qml_jit)
647 if (!m_canAllocateExecutableMemory)
648 return false;
649 if (f)
650 return !f->isGenerator() && f->interpreterCallCount >= jitCallCountThreshold;
651 return true;
652#else
653 Q_UNUSED(f);
654 return false;
655#endif
656 }
657
658 QV4::ReturnedValue global();
659 void initQmlGlobalObject();
660 void initializeGlobal();
661
662 void freezeObject(const QV4::Value &value);
663
664 // Return the list of illegal id names (the names of the properties on the global object)
665 const QSet<QString> &illegalNames() const;
666
667#if QT_CONFIG(qml_xml_http_request)
668 void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
669#endif
670
671 void setQmlEngine(QQmlEngine *engine);
672
673 QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
674
675 // used for console.time(), console.timeEnd()
676 void startTimer(const QString &timerName);
677 qint64 stopTimer(const QString &timerName, bool *wasRunning);
678
679 // used for console.count()
680 int consoleCountHelper(const QString &file, quint16 line, quint16 column);
681
682 struct Deletable {
683 virtual ~Deletable() {}
684 };
685
686 static QMutex *registrationMutex();
687 static int registerExtension();
688
689 void setExtensionData(int, Deletable *);
690 Deletable *extensionData(int index) const
691 {
692 if (index < m_extensionData.count())
693 return m_extensionData[index];
694 else
695 return nullptr;
696 }
697
698 double localTZA = 0.0; // local timezone, initialized at startup
699
700 QQmlRefPointer<ExecutableCompilationUnit> compileModule(const QUrl &url);
701 QQmlRefPointer<ExecutableCompilationUnit> compileModule(
702 const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
703
704 mutable QMutex moduleMutex;
705 QHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> modules;
706 void injectModule(const QQmlRefPointer<ExecutableCompilationUnit> &moduleUnit);
707 QQmlRefPointer<ExecutableCompilationUnit> moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const;
708 QQmlRefPointer<ExecutableCompilationUnit> loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr);
709
710private:
711#if QT_CONFIG(qml_debug)
712 QScopedPointer<QV4::Debugging::Debugger> m_debugger;
713 QScopedPointer<QV4::Profiling::Profiler> m_profiler;
714#endif
715 QSet<QString> m_illegalNames;
716 int jitCallCountThreshold;
717
718 // used by generated Promise objects to handle 'then' events
719 QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler;
720
721#if QT_CONFIG(qml_xml_http_request)
722 void *m_xmlHttpRequestData;
723#endif
724
725 QQmlEngine *m_qmlEngine;
726
727 QQmlDelayedCallQueue m_delayedCallQueue;
728
729 QElapsedTimer m_time;
730 QHash<QString, qint64> m_startedTimers;
731
732 QHash<QString, quint32> m_consoleCount;
733
734 QVector<Deletable *> m_extensionData;
735
736 int m_maxJSStackSize = 4 * 1024 * 1024;
737 int m_maxGCStackSize = 2 * 1024 * 1024;
738};
739
740#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
741 ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
742
743struct ExecutionEngineCallDepthRecorder
744{
745 ExecutionEngine *ee;
746
747 ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; }
748 ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; }
749};
750
751inline bool ExecutionEngine::checkStackLimits()
752{
753 if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) {
754 throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
755 return true;
756 }
757
758 return false;
759}
760
761} // namespace QV4
762
763QT_END_NAMESPACE
764
765#endif // QV4ENGINE_H
766