1 | // Copyright (C) 2016 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | #ifndef QV4ENGINE_H |
4 | #define QV4ENGINE_H |
5 | |
6 | // |
7 | // W A R N I N G |
8 | // ------------- |
9 | // |
10 | // This file is not part of the Qt API. It exists purely as an |
11 | // implementation detail. This header file may change from version to |
12 | // version without notice, or even be removed. |
13 | // |
14 | // We mean it. |
15 | // |
16 | |
17 | #include <private/qintrusivelist_p.h> |
18 | #include <private/qqmldelayedcallqueue_p.h> |
19 | #include <private/qqmlrefcount_p.h> |
20 | #include <private/qv4compileddata_p.h> |
21 | #include <private/qv4context_p.h> |
22 | #include <private/qv4enginebase_p.h> |
23 | #include <private/qv4executablecompilationunit_p.h> |
24 | #include <private/qv4function_p.h> |
25 | #include <private/qv4global_p.h> |
26 | #include <private/qv4stacklimits_p.h> |
27 | |
28 | #include <QtCore/qelapsedtimer.h> |
29 | #include <QtCore/qmutex.h> |
30 | #include <QtCore/qprocessordetection.h> |
31 | #include <QtCore/qset.h> |
32 | |
33 | namespace WTF { |
34 | class BumpPointerAllocator; |
35 | class PageAllocation; |
36 | } |
37 | |
38 | #define V4_DEFINE_EXTENSION(dataclass, datafunction) \ |
39 | static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \ |
40 | { \ |
41 | static int extensionId = -1; \ |
42 | if (extensionId == -1) { \ |
43 | QV4::ExecutionEngine::registrationMutex()->lock(); \ |
44 | if (extensionId == -1) \ |
45 | extensionId = QV4::ExecutionEngine::registerExtension(); \ |
46 | QV4::ExecutionEngine::registrationMutex()->unlock(); \ |
47 | } \ |
48 | dataclass *rv = (dataclass *)engine->extensionData(extensionId); \ |
49 | if (!rv) { \ |
50 | rv = new dataclass(engine); \ |
51 | engine->setExtensionData(extensionId, rv); \ |
52 | } \ |
53 | return rv; \ |
54 | } \ |
55 | |
56 | |
57 | QT_BEGIN_NAMESPACE |
58 | |
59 | #if QT_CONFIG(qml_network) |
60 | class QNetworkAccessManager; |
61 | |
62 | namespace QV4 { |
63 | struct QObjectMethod; |
64 | namespace detail { |
65 | QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine); |
66 | } |
67 | } |
68 | #else |
69 | namespace QV4 { struct QObjectMethod; } |
70 | #endif // qml_network |
71 | |
72 | // Used to allow a QObject method take and return raw V4 handles without having to expose |
73 | // 48 in the public API. |
74 | // Use like this: |
75 | // class MyClass : public QObject { |
76 | // Q_OBJECT |
77 | // ... |
78 | // Q_INVOKABLE void myMethod(QQmlV4FunctionPtr); |
79 | // }; |
80 | // The QQmlV8Function - and consequently the arguments and return value - only remains |
81 | // valid during the call. If the return value isn't set within myMethod(), the will return |
82 | // undefined. |
83 | |
84 | class QQmlV4Function |
85 | { |
86 | public: |
87 | int length() const { return callData->argc(); } |
88 | QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); } |
89 | void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; } |
90 | QV4::ExecutionEngine *v4engine() const { return e; } |
91 | private: |
92 | friend struct QV4::QObjectMethod; |
93 | QQmlV4Function(); |
94 | QQmlV4Function(const QQmlV4Function &); |
95 | QQmlV4Function &operator=(const QQmlV4Function &); |
96 | |
97 | QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e) |
98 | : callData(callData), retVal(retVal), e(e) |
99 | { |
100 | callData->thisObject = QV4::Encode::undefined(); |
101 | } |
102 | |
103 | QV4::CallData *callData; |
104 | QV4::Value *retVal; |
105 | QV4::ExecutionEngine *e; |
106 | }; |
107 | |
108 | class QQmlError; |
109 | class QJSEngine; |
110 | class QQmlEngine; |
111 | class QQmlContextData; |
112 | class QQmlTypeLoader; |
113 | |
114 | namespace QV4 { |
115 | namespace Debugging { |
116 | class Debugger; |
117 | } // namespace Debugging |
118 | namespace Profiling { |
119 | class Profiler; |
120 | } // namespace Profiling |
121 | namespace CompiledData { |
122 | struct CompilationUnit; |
123 | } |
124 | |
125 | namespace Heap { |
126 | struct Module; |
127 | }; |
128 | |
129 | struct Function; |
130 | |
131 | namespace Promise { |
132 | class ReactionHandler; |
133 | }; |
134 | |
135 | struct Q_QML_EXPORT ExecutionEngine : public EngineBase |
136 | { |
137 | private: |
138 | friend struct ExecutionContextSaver; |
139 | friend struct ExecutionContext; |
140 | friend struct Heap::ExecutionContext; |
141 | public: |
142 | enum class DiskCache { |
143 | Disabled = 0, |
144 | AotByteCode = 1 << 0, |
145 | AotNative = 1 << 1, |
146 | QmlcRead = 1 << 2, |
147 | QmlcWrite = 1 << 3, |
148 | Aot = AotByteCode | AotNative, |
149 | Qmlc = QmlcRead | QmlcWrite, |
150 | Enabled = Aot | Qmlc, |
151 | |
152 | }; |
153 | |
154 | Q_DECLARE_FLAGS(DiskCacheOptions, DiskCache); |
155 | |
156 | ExecutableAllocator *executableAllocator; |
157 | ExecutableAllocator *regExpAllocator; |
158 | |
159 | WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine. |
160 | |
161 | WTF::PageAllocation *jsStack; |
162 | |
163 | WTF::PageAllocation *gcStack; |
164 | |
165 | QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) { |
166 | Value *ptr = jsStackTop; |
167 | jsStackTop = ptr + nValues; |
168 | return ptr; |
169 | } |
170 | |
171 | Function *globalCode; |
172 | |
173 | QJSEngine *jsEngine() const { return publicEngine; } |
174 | QQmlEngine *qmlEngine() const { return m_qmlEngine; } |
175 | QJSEngine *publicEngine; |
176 | |
177 | template<typename TypeLoader = QQmlTypeLoader> |
178 | TypeLoader *typeLoader() |
179 | { |
180 | if (m_qmlEngine) |
181 | return TypeLoader::get(m_qmlEngine); |
182 | return nullptr; |
183 | } |
184 | |
185 | enum JSObjects { |
186 | RootContext, |
187 | ScriptContext, |
188 | IntegerNull, // Has to come after the RootContext to make the context stack safe |
189 | ObjectProto, |
190 | SymbolProto, |
191 | ArrayProto, |
192 | ArrayProtoValues, |
193 | PropertyListProto, |
194 | StringProto, |
195 | NumberProto, |
196 | BooleanProto, |
197 | DateProto, |
198 | FunctionProto, |
199 | GeneratorProto, |
200 | RegExpProto, |
201 | ErrorProto, |
202 | EvalErrorProto, |
203 | RangeErrorProto, |
204 | ReferenceErrorProto, |
205 | SyntaxErrorProto, |
206 | TypeErrorProto, |
207 | URIErrorProto, |
208 | PromiseProto, |
209 | VariantProto, |
210 | SequenceProto, |
211 | SharedArrayBufferProto, |
212 | ArrayBufferProto, |
213 | DataViewProto, |
214 | WeakSetProto, |
215 | SetProto, |
216 | WeakMapProto, |
217 | MapProto, |
218 | IntrinsicTypedArrayProto, |
219 | ValueTypeProto, |
220 | TypeWrapperProto, |
221 | SignalHandlerProto, |
222 | IteratorProto, |
223 | ForInIteratorProto, |
224 | SetIteratorProto, |
225 | MapIteratorProto, |
226 | ArrayIteratorProto, |
227 | StringIteratorProto, |
228 | UrlProto, |
229 | UrlSearchParamsProto, |
230 | |
231 | Object_Ctor, |
232 | String_Ctor, |
233 | Symbol_Ctor, |
234 | Number_Ctor, |
235 | Boolean_Ctor, |
236 | Array_Ctor, |
237 | Function_Ctor, |
238 | GeneratorFunction_Ctor, |
239 | Date_Ctor, |
240 | RegExp_Ctor, |
241 | Error_Ctor, |
242 | EvalError_Ctor, |
243 | RangeError_Ctor, |
244 | ReferenceError_Ctor, |
245 | SyntaxError_Ctor, |
246 | TypeError_Ctor, |
247 | URIError_Ctor, |
248 | SharedArrayBuffer_Ctor, |
249 | Promise_Ctor, |
250 | ArrayBuffer_Ctor, |
251 | DataView_Ctor, |
252 | WeakSet_Ctor, |
253 | Set_Ctor, |
254 | WeakMap_Ctor, |
255 | Map_Ctor, |
256 | IntrinsicTypedArray_Ctor, |
257 | Url_Ctor, |
258 | UrlSearchParams_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 *urlCtor() const |
300 | { |
301 | return reinterpret_cast<FunctionObject *>(jsObjects + Url_Ctor); |
302 | } |
303 | FunctionObject *urlSearchParamsCtor() const |
304 | { |
305 | return reinterpret_cast<FunctionObject *>(jsObjects + UrlSearchParams_Ctor); |
306 | } |
307 | FunctionObject *typedArrayCtors; |
308 | |
309 | FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); } |
310 | |
311 | Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); } |
312 | Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); } |
313 | Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); } |
314 | Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); } |
315 | Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); } |
316 | Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); } |
317 | Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); } |
318 | Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); } |
319 | Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); } |
320 | Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); } |
321 | Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); } |
322 | Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); } |
323 | Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); } |
324 | Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); } |
325 | Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); } |
326 | Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); } |
327 | Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); } |
328 | Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); } |
329 | Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); } |
330 | Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); } |
331 | Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); } |
332 | Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); } |
333 | |
334 | Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); } |
335 | Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); } |
336 | Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); } |
337 | Object *weakSetPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakSetProto); } |
338 | Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); } |
339 | Object *weakMapPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakMapProto); } |
340 | Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); } |
341 | Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + IntrinsicTypedArrayProto); } |
342 | Object *typedArrayPrototype; |
343 | |
344 | Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); } |
345 | Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); } |
346 | Object *typeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeWrapperProto); } |
347 | Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); } |
348 | Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); } |
349 | Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); } |
350 | Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); } |
351 | Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); } |
352 | Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); } |
353 | Object *urlPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlProto); } |
354 | Object *urlSearchParamsPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlSearchParamsProto); } |
355 | |
356 | EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); } |
357 | FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); } |
358 | FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); } |
359 | |
360 | #if QT_CONFIG(qml_network) |
361 | QNetworkAccessManager* (*networkAccessManager)(ExecutionEngine*) = detail::getNetworkAccessManager; |
362 | #endif |
363 | |
364 | enum JSStrings { |
365 | String_Empty, |
366 | String_undefined, |
367 | String_null, |
368 | String_true, |
369 | String_false, |
370 | String_boolean, |
371 | String_number, |
372 | String_string, |
373 | String_default, |
374 | String_symbol, |
375 | String_object, |
376 | String_function, |
377 | String_length, |
378 | String_prototype, |
379 | String_constructor, |
380 | String_arguments, |
381 | String_caller, |
382 | String_callee, |
383 | String_this, |
384 | String___proto__, |
385 | String_enumerable, |
386 | String_configurable, |
387 | String_writable, |
388 | String_value, |
389 | String_get, |
390 | String_set, |
391 | String_eval, |
392 | String_uintMax, |
393 | String_name, |
394 | String_index, |
395 | String_input, |
396 | String_toString, |
397 | String_toLocaleString, |
398 | String_destroy, |
399 | String_valueOf, |
400 | String_byteLength, |
401 | String_byteOffset, |
402 | String_buffer, |
403 | String_lastIndex, |
404 | String_next, |
405 | String_done, |
406 | String_return, |
407 | String_throw, |
408 | String_global, |
409 | String_ignoreCase, |
410 | String_multiline, |
411 | String_unicode, |
412 | String_sticky, |
413 | String_source, |
414 | String_flags, |
415 | |
416 | NJSStrings |
417 | }; |
418 | Value *jsStrings; |
419 | |
420 | enum JSSymbols { |
421 | Symbol_hasInstance, |
422 | Symbol_isConcatSpreadable, |
423 | Symbol_iterator, |
424 | Symbol_match, |
425 | Symbol_replace, |
426 | Symbol_search, |
427 | Symbol_species, |
428 | Symbol_split, |
429 | Symbol_toPrimitive, |
430 | Symbol_toStringTag, |
431 | Symbol_unscopables, |
432 | Symbol_revokableProxy, |
433 | NJSSymbols |
434 | }; |
435 | Value *jsSymbols; |
436 | |
437 | String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); } |
438 | String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); } |
439 | String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); } |
440 | String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); } |
441 | String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); } |
442 | String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); } |
443 | String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); } |
444 | String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); } |
445 | String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); } |
446 | String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); } |
447 | String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); } |
448 | String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); } |
449 | String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); } |
450 | String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); } |
451 | String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); } |
452 | String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); } |
453 | String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); } |
454 | String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); } |
455 | String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); } |
456 | String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); } |
457 | String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); } |
458 | String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); } |
459 | String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); } |
460 | String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); } |
461 | String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); } |
462 | String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); } |
463 | String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); } |
464 | String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); } |
465 | String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); } |
466 | String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); } |
467 | String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); } |
468 | String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); } |
469 | String *id_toLocaleString() const { return reinterpret_cast<String *>(jsStrings + String_toLocaleString); } |
470 | String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); } |
471 | String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); } |
472 | String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); } |
473 | String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); } |
474 | String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); } |
475 | String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); } |
476 | String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); } |
477 | String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); } |
478 | String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); } |
479 | String *id_throw() const { return reinterpret_cast<String *>(jsStrings + String_throw); } |
480 | String *id_global() const { return reinterpret_cast<String *>(jsStrings + String_global); } |
481 | String *id_ignoreCase() const { return reinterpret_cast<String *>(jsStrings + String_ignoreCase); } |
482 | String *id_multiline() const { return reinterpret_cast<String *>(jsStrings + String_multiline); } |
483 | String *id_unicode() const { return reinterpret_cast<String *>(jsStrings + String_unicode); } |
484 | String *id_sticky() const { return reinterpret_cast<String *>(jsStrings + String_sticky); } |
485 | String *id_source() const { return reinterpret_cast<String *>(jsStrings + String_source); } |
486 | String *id_flags() const { return reinterpret_cast<String *>(jsStrings + String_flags); } |
487 | |
488 | Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); } |
489 | Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); } |
490 | Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); } |
491 | Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); } |
492 | Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); } |
493 | Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); } |
494 | Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); } |
495 | Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); } |
496 | Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); } |
497 | Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); } |
498 | Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); } |
499 | Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); } |
500 | |
501 | quint32 m_engineId; |
502 | |
503 | RegExpCache *regExpCache; |
504 | |
505 | // Scarce resources are "exceptionally high cost" QVariant types where allowing the |
506 | // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other |
507 | // out-of-resource situations. When such a resource is passed into JavaScript we |
508 | // add it to the scarceResources list and it is destroyed when we return from the |
509 | // JavaScript execution that created it. The user can prevent this behavior by |
510 | // calling preserve() on the object which removes it from this scarceResource list. |
511 | class ScarceResourceData { |
512 | public: |
513 | ScarceResourceData() = default; |
514 | ScarceResourceData(const QMetaType type, const void *data) : data(type, data) {} |
515 | QVariant data; |
516 | QIntrusiveListNode node; |
517 | }; |
518 | QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources; |
519 | |
520 | // Normally the JS wrappers for QObjects are stored in the QQmlData/QObjectPrivate, |
521 | // but any time a QObject is wrapped a second time in another engine, we have to do |
522 | // bookkeeping. |
523 | MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects; |
524 | #if QT_CONFIG(qml_jit) |
525 | const bool m_canAllocateExecutableMemory; |
526 | #endif |
527 | |
528 | quintptr protoIdCount = 1; |
529 | |
530 | ExecutionEngine(QJSEngine *jsEngine = nullptr); |
531 | ~ExecutionEngine(); |
532 | |
533 | #if !QT_CONFIG(qml_debug) |
534 | QV4::Debugging::Debugger *debugger() const { return nullptr; } |
535 | QV4::Profiling::Profiler *profiler() const { return nullptr; } |
536 | |
537 | void setDebugger(Debugging::Debugger *) {} |
538 | void setProfiler(Profiling::Profiler *) {} |
539 | static void setPreviewing(bool) {} |
540 | #else |
541 | QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); } |
542 | QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); } |
543 | |
544 | void setDebugger(Debugging::Debugger *debugger); |
545 | void setProfiler(Profiling::Profiler *profiler); |
546 | static void setPreviewing(bool enabled); |
547 | #endif // QT_CONFIG(qml_debug) |
548 | |
549 | // We don't want to #include <private/qv4stackframe_p.h> here, but we still want |
550 | // currentContext() to be inline. Therefore we shift the requirement to provide the |
551 | // complete type of CppStackFrame to the caller by making this a template. |
552 | template<typename StackFrame = CppStackFrame> |
553 | ExecutionContext *currentContext() const |
554 | { |
555 | return static_cast<const StackFrame *>(currentStackFrame)->context(); |
556 | } |
557 | |
558 | // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast |
559 | quintptr newProtoId() { return (protoIdCount += 2); } |
560 | |
561 | Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype); |
562 | |
563 | Heap::Object *newObject(); |
564 | Heap::Object *newObject(Heap::InternalClass *internalClass); |
565 | |
566 | Heap::String *newString(char16_t c) { return newString(s: QChar(c)); } |
567 | Heap::String *newString(const QString &s = QString()); |
568 | Heap::String *newIdentifier(const QString &text); |
569 | |
570 | Heap::Object *newStringObject(const String *string); |
571 | Heap::Object *newSymbolObject(const Symbol *symbol); |
572 | Heap::Object *newNumberObject(double value); |
573 | Heap::Object *newBooleanObject(bool b); |
574 | |
575 | Heap::ArrayObject *newArrayObject(int count = 0); |
576 | Heap::ArrayObject *newArrayObject(const Value *values, int length); |
577 | Heap::ArrayObject *newArrayObject(const QStringList &list); |
578 | Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic); |
579 | |
580 | Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array); |
581 | Heap::ArrayBuffer *newArrayBuffer(size_t length); |
582 | |
583 | Heap::DateObject *newDateObject(double dateTime); |
584 | Heap::DateObject *newDateObject(const QDateTime &dateTime); |
585 | Heap::DateObject *newDateObject(QDate date, Heap::Object *parent, int index, uint flags); |
586 | Heap::DateObject *newDateObject(QTime time, Heap::Object *parent, int index, uint flags); |
587 | Heap::DateObject *newDateObject(QDateTime dateTime, Heap::Object *parent, int index, uint flags); |
588 | |
589 | Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags); |
590 | Heap::RegExpObject *newRegExpObject(RegExp *re); |
591 | #if QT_CONFIG(regularexpression) |
592 | Heap::RegExpObject *newRegExpObject(const QRegularExpression &re); |
593 | #endif |
594 | |
595 | Heap::UrlObject *newUrlObject(); |
596 | Heap::UrlObject *newUrlObject(const QUrl &url); |
597 | Heap::UrlSearchParamsObject *newUrlSearchParamsObject(); |
598 | |
599 | Heap::Object *newErrorObject(const Value &value); |
600 | Heap::Object *newErrorObject(const QString &message); |
601 | Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column); |
602 | Heap::Object *newSyntaxErrorObject(const QString &message); |
603 | Heap::Object *newReferenceErrorObject(const QString &message); |
604 | Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column); |
605 | Heap::Object *newTypeErrorObject(const QString &message); |
606 | Heap::Object *newRangeErrorObject(const QString &message); |
607 | Heap::Object *newURIErrorObject(const QString &message); |
608 | Heap::Object *newURIErrorObject(const Value &message); |
609 | Heap::Object *newEvalErrorObject(const QString &message); |
610 | |
611 | Heap::PromiseObject *newPromiseObject(); |
612 | Heap::Object *newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability); |
613 | Promise::ReactionHandler *getPromiseReactionHandler(); |
614 | |
615 | Heap::Object *newVariantObject(const QMetaType type, const void *data); |
616 | |
617 | Heap::Object *newForInIteratorObject(Object *o); |
618 | Heap::Object *newSetIteratorObject(Object *o); |
619 | Heap::Object *newMapIteratorObject(Object *o); |
620 | Heap::Object *newArrayIteratorObject(Object *o); |
621 | |
622 | static Heap::ExecutionContext *qmlContext(Heap::ExecutionContext *ctx) |
623 | { |
624 | Heap::ExecutionContext *outer = ctx->outer; |
625 | |
626 | if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !outer) |
627 | return nullptr; |
628 | |
629 | while (outer && outer->type != Heap::ExecutionContext::Type_GlobalContext) { |
630 | ctx = outer; |
631 | outer = ctx->outer; |
632 | } |
633 | |
634 | Q_ASSERT(ctx); |
635 | if (ctx->type != Heap::ExecutionContext::Type_QmlContext) |
636 | return nullptr; |
637 | |
638 | return ctx; |
639 | } |
640 | |
641 | Heap::QmlContext *qmlContext() const; |
642 | QObject *qmlScopeObject() const; |
643 | QQmlRefPointer<QQmlContextData> callingQmlContext() const; |
644 | |
645 | |
646 | StackTrace stackTrace(int frameLimit = -1) const; |
647 | QUrl resolvedUrl(const QString &file); |
648 | |
649 | void markObjects(MarkStack *markStack); |
650 | |
651 | void initRootContext(); |
652 | |
653 | Heap::InternalClass *newClass(Heap::InternalClass *other); |
654 | |
655 | StackTrace exceptionStackTrace; |
656 | |
657 | ReturnedValue throwError(const Value &value); |
658 | ReturnedValue catchException(StackTrace *trace = nullptr); |
659 | |
660 | ReturnedValue throwError(const QString &message); |
661 | ReturnedValue throwSyntaxError(const QString &message); |
662 | ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column); |
663 | ReturnedValue throwTypeError(); |
664 | ReturnedValue throwTypeError(const QString &message); |
665 | ReturnedValue throwReferenceError(const Value &value); |
666 | ReturnedValue throwReferenceError(const QString &name); |
667 | ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column); |
668 | ReturnedValue throwRangeError(const Value &value); |
669 | ReturnedValue throwRangeError(const QString &message); |
670 | ReturnedValue throwURIError(const Value &msg); |
671 | ReturnedValue throwUnimplemented(const QString &message); |
672 | |
673 | // Use only inside catch(...) -- will re-throw if no JS exception |
674 | QQmlError catchExceptionAsQmlError(); |
675 | |
676 | // variant conversions |
677 | static QVariant toVariant( |
678 | const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols = true); |
679 | static QVariant toVariantLossy(const QV4::Value &value); |
680 | QV4::ReturnedValue fromVariant(const QVariant &); |
681 | QV4::ReturnedValue fromVariant( |
682 | const QVariant &variant, Heap::Object *parent, int property, uint flags); |
683 | |
684 | static QVariantMap variantMapFromJS(const QV4::Object *o); |
685 | |
686 | static bool metaTypeFromJS(const Value &value, QMetaType type, void *data); |
687 | QV4::ReturnedValue metaTypeToJS(QMetaType type, const void *data); |
688 | |
689 | int maxJSStackSize() const; |
690 | int maxGCStackSize() const; |
691 | |
692 | bool checkStackLimits(); |
693 | int safeForAllocLength(qint64 len64); |
694 | |
695 | bool canJIT(Function *f = nullptr) |
696 | { |
697 | #if QT_CONFIG(qml_jit) |
698 | if (!m_canAllocateExecutableMemory) |
699 | return false; |
700 | if (f) { |
701 | return f->kind != Function::AotCompiled |
702 | && !f->isGenerator() |
703 | && f->interpreterCallCount >= s_jitCallCountThreshold; |
704 | } |
705 | return true; |
706 | #else |
707 | Q_UNUSED(f); |
708 | return false; |
709 | #endif |
710 | } |
711 | |
712 | QV4::ReturnedValue global(); |
713 | void initQmlGlobalObject(); |
714 | void initializeGlobal(); |
715 | void createQtObject(); |
716 | |
717 | void freezeObject(const QV4::Value &value); |
718 | void lockObject(const QV4::Value &value); |
719 | |
720 | // Return the list of illegal id names (the names of the properties on the global object) |
721 | const QSet<QString> &illegalNames() const; |
722 | |
723 | #if QT_CONFIG(qml_xml_http_request) |
724 | void *xmlHttpRequestData() const { return m_xmlHttpRequestData; } |
725 | #endif |
726 | |
727 | void setQmlEngine(QQmlEngine *engine); |
728 | |
729 | QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; } |
730 | |
731 | // used for console.time(), console.timeEnd() |
732 | void startTimer(const QString &timerName); |
733 | qint64 stopTimer(const QString &timerName, bool *wasRunning); |
734 | |
735 | // used for console.count() |
736 | int consoleCountHelper(const QString &file, quint16 line, quint16 column); |
737 | |
738 | struct Deletable { |
739 | virtual ~Deletable() {} |
740 | }; |
741 | |
742 | static QMutex *registrationMutex(); |
743 | static int registerExtension(); |
744 | |
745 | void setExtensionData(int, Deletable *); |
746 | Deletable *extensionData(int index) const |
747 | { |
748 | if (index < m_extensionData.size()) |
749 | return m_extensionData[index]; |
750 | else |
751 | return nullptr; |
752 | } |
753 | |
754 | double localTZA = 0.0; // local timezone, initialized at startup |
755 | |
756 | QQmlRefPointer<ExecutableCompilationUnit> compileModule(const QUrl &url); |
757 | QQmlRefPointer<ExecutableCompilationUnit> compileModule( |
758 | const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp); |
759 | |
760 | QQmlRefPointer<ExecutableCompilationUnit> compilationUnitForUrl(const QUrl &url) const; |
761 | |
762 | QQmlRefPointer<ExecutableCompilationUnit> executableCompilationUnit( |
763 | QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&unit); |
764 | |
765 | QQmlRefPointer<ExecutableCompilationUnit> insertCompilationUnit( |
766 | QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&unit); |
767 | |
768 | QMultiHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> compilationUnits() const |
769 | { |
770 | return m_compilationUnits; |
771 | } |
772 | void trimCompilationUnits(); |
773 | |
774 | QV4::Value *registerNativeModule(const QUrl &url, const QV4::Value &module); |
775 | |
776 | struct Module { |
777 | QQmlRefPointer<ExecutableCompilationUnit> compiled; |
778 | |
779 | // We can pass a raw value pointer here, but nowhere else. See below. |
780 | Value *native = nullptr; |
781 | }; |
782 | |
783 | Module moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const; |
784 | Module loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr); |
785 | |
786 | DiskCacheOptions diskCacheOptions() const; |
787 | |
788 | void callInContext(QV4::Function *function, QObject *self, QV4::ExecutionContext *ctxt, |
789 | int argc, void **args, QMetaType *types); |
790 | QV4::ReturnedValue callInContext(QV4::Function *function, QObject *self, |
791 | QV4::ExecutionContext *ctxt, int argc, const QV4::Value *argv); |
792 | |
793 | QV4::ReturnedValue fromData( |
794 | QMetaType type, const void *ptr, |
795 | Heap::Object *parent = nullptr, int property = -1, uint flags = 0); |
796 | |
797 | |
798 | static void setMaxCallDepth(int maxCallDepth) { s_maxCallDepth = maxCallDepth; } |
799 | static int maxCallDepth() { return s_maxCallDepth; } |
800 | |
801 | template<typename Value> |
802 | static QJSPrimitiveValue createPrimitive(const Value &v) |
803 | { |
804 | if (v->isUndefined()) |
805 | return QJSPrimitiveValue(QJSPrimitiveUndefined()); |
806 | if (v->isNull()) |
807 | return QJSPrimitiveValue(QJSPrimitiveNull()); |
808 | if (v->isBoolean()) |
809 | return QJSPrimitiveValue(v->toBoolean()); |
810 | if (v->isInteger()) |
811 | return QJSPrimitiveValue(v->integerValue()); |
812 | if (v->isDouble()) |
813 | return QJSPrimitiveValue(v->doubleValue()); |
814 | bool ok; |
815 | const QString result = v->toQString(&ok); |
816 | return ok ? QJSPrimitiveValue(result) : QJSPrimitiveValue(QJSPrimitiveUndefined()); |
817 | } |
818 | |
819 | ReturnedValue nativeModule(const QUrl &url) const |
820 | { |
821 | const auto it = nativeModules.find(key: url); |
822 | return it == nativeModules.end() |
823 | ? QV4::Value::emptyValue().asReturnedValue() |
824 | : (*it)->asReturnedValue(); |
825 | } |
826 | |
827 | private: |
828 | template<int Frames> |
829 | friend struct ExecutionEngineCallDepthRecorder; |
830 | |
831 | static void initializeStaticMembers(); |
832 | |
833 | bool inStack(const void *current) const |
834 | { |
835 | #if Q_STACK_GROWTH_DIRECTION > 0 |
836 | return current < cppStackLimit && current >= cppStackBase; |
837 | #else |
838 | return current > cppStackLimit && current <= cppStackBase; |
839 | #endif |
840 | } |
841 | |
842 | bool hasCppStackOverflow() |
843 | { |
844 | if (s_maxCallDepth >= 0) |
845 | return callDepth >= s_maxCallDepth; |
846 | |
847 | if (inStack(current: currentStackPointer())) |
848 | return false; |
849 | |
850 | // Double check the stack limits on failure. |
851 | // We may have moved to a different thread. |
852 | const StackProperties stack = stackProperties(); |
853 | cppStackBase = stack.base; |
854 | cppStackLimit = stack.softLimit; |
855 | return !inStack(current: currentStackPointer()); |
856 | } |
857 | |
858 | bool hasJsStackOverflow() const |
859 | { |
860 | return jsStackTop > jsStackLimit; |
861 | } |
862 | |
863 | bool hasStackOverflow() |
864 | { |
865 | return hasJsStackOverflow() || hasCppStackOverflow(); |
866 | } |
867 | |
868 | static int s_maxCallDepth; |
869 | static int s_jitCallCountThreshold; |
870 | static int s_maxJSStackSize; |
871 | static int s_maxGCStackSize; |
872 | |
873 | #if QT_CONFIG(qml_debug) |
874 | QScopedPointer<QV4::Debugging::Debugger> m_debugger; |
875 | QScopedPointer<QV4::Profiling::Profiler> m_profiler; |
876 | #endif |
877 | QSet<QString> m_illegalNames; |
878 | |
879 | // used by generated Promise objects to handle 'then' events |
880 | QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler; |
881 | |
882 | #if QT_CONFIG(qml_xml_http_request) |
883 | void *m_xmlHttpRequestData; |
884 | #endif |
885 | |
886 | QQmlEngine *m_qmlEngine; |
887 | |
888 | QQmlDelayedCallQueue m_delayedCallQueue; |
889 | |
890 | QElapsedTimer m_time; |
891 | QHash<QString, qint64> m_startedTimers; |
892 | |
893 | QHash<QString, quint32> m_consoleCount; |
894 | |
895 | QVector<Deletable *> m_extensionData; |
896 | |
897 | QMultiHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> m_compilationUnits; |
898 | |
899 | // QV4::PersistentValue would be preferred, but using QHash will create copies, |
900 | // and QV4::PersistentValue doesn't like creating copies. |
901 | // Instead, we allocate a raw pointer using the same manual memory management |
902 | // technique in QV4::PersistentValue. |
903 | QHash<QUrl, Value *> nativeModules; |
904 | }; |
905 | |
906 | #define CHECK_STACK_LIMITS(v4) \ |
907 | if (v4->checkStackLimits()) \ |
908 | return Encode::undefined(); \ |
909 | ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4); |
910 | |
911 | template<int Frames = 1> |
912 | struct ExecutionEngineCallDepthRecorder |
913 | { |
914 | ExecutionEngine *ee; |
915 | |
916 | ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) |
917 | { |
918 | if (ExecutionEngine::s_maxCallDepth >= 0) |
919 | ee->callDepth += Frames; |
920 | } |
921 | |
922 | ~ExecutionEngineCallDepthRecorder() |
923 | { |
924 | if (ExecutionEngine::s_maxCallDepth >= 0) |
925 | ee->callDepth -= Frames; |
926 | } |
927 | |
928 | bool hasOverflow() const |
929 | { |
930 | return ee->hasCppStackOverflow(); |
931 | } |
932 | }; |
933 | |
934 | inline bool ExecutionEngine::checkStackLimits() |
935 | { |
936 | if (Q_UNLIKELY(hasStackOverflow())) { |
937 | throwRangeError(QStringLiteral("Maximum call stack size exceeded.")); |
938 | return true; |
939 | } |
940 | |
941 | return false; |
942 | } |
943 | |
944 | Q_DECLARE_OPERATORS_FOR_FLAGS(ExecutionEngine::DiskCacheOptions); |
945 | |
946 | } // namespace QV4 |
947 | |
948 | QT_END_NAMESPACE |
949 | |
950 | #endif // QV4ENGINE_H |
951 |
Definitions
- QQmlV4Function
- length
- operator[]
- setReturnValue
- v4engine
- QQmlV4Function
- ExecutionEngine
- DiskCache
- jsAlloca
- jsEngine
- qmlEngine
- typeLoader
- JSObjects
- rootContext
- scriptContext
- setScriptContext
- objectCtor
- stringCtor
- symbolCtor
- numberCtor
- booleanCtor
- arrayCtor
- functionCtor
- generatorFunctionCtor
- dateCtor
- regExpCtor
- errorCtor
- evalErrorCtor
- rangeErrorCtor
- referenceErrorCtor
- syntaxErrorCtor
- typeErrorCtor
- uRIErrorCtor
- sharedArrayBufferCtor
- promiseCtor
- arrayBufferCtor
- dataViewCtor
- weakSetCtor
- setCtor
- weakMapCtor
- mapCtor
- intrinsicTypedArrayCtor
- urlCtor
- urlSearchParamsCtor
- getSymbolSpecies
- objectPrototype
- symbolPrototype
- arrayPrototype
- arrayProtoValues
- propertyListPrototype
- stringPrototype
- numberPrototype
- booleanPrototype
- datePrototype
- functionPrototype
- generatorPrototype
- regExpPrototype
- errorPrototype
- evalErrorPrototype
- rangeErrorPrototype
- referenceErrorPrototype
- syntaxErrorPrototype
- typeErrorPrototype
- uRIErrorPrototype
- promisePrototype
- variantPrototype
- sequencePrototype
- sharedArrayBufferPrototype
- arrayBufferPrototype
- dataViewPrototype
- weakSetPrototype
- setPrototype
- weakMapPrototype
- mapPrototype
- intrinsicTypedArrayPrototype
- valueTypeWrapperPrototype
- signalHandlerPrototype
- typeWrapperPrototype
- iteratorPrototype
- forInIteratorPrototype
- setIteratorPrototype
- mapIteratorPrototype
- arrayIteratorPrototype
- stringIteratorPrototype
- urlPrototype
- urlSearchParamsPrototype
- evalFunction
- getStackFunction
- thrower
- JSStrings
- JSSymbols
- id_empty
- id_undefined
- id_null
- id_true
- id_false
- id_boolean
- id_number
- id_string
- id_default
- id_symbol
- id_object
- id_function
- id_length
- id_prototype
- id_constructor
- id_arguments
- id_caller
- id_callee
- id_this
- id___proto__
- id_enumerable
- id_configurable
- id_writable
- id_value
- id_get
- id_set
- id_eval
- id_uintMax
- id_name
- id_index
- id_input
- id_toString
- id_toLocaleString
- id_destroy
- id_valueOf
- id_byteLength
- id_byteOffset
- id_buffer
- id_lastIndex
- id_next
- id_done
- id_return
- id_throw
- id_global
- id_ignoreCase
- id_multiline
- id_unicode
- id_sticky
- id_source
- id_flags
- symbol_hasInstance
- symbol_isConcatSpreadable
- symbol_iterator
- symbol_match
- symbol_replace
- symbol_search
- symbol_species
- symbol_split
- symbol_toPrimitive
- symbol_toStringTag
- symbol_unscopables
- symbol_revokableProxy
- ScarceResourceData
- ScarceResourceData
- ScarceResourceData
- debugger
- profiler
- currentContext
- newProtoId
- newString
- qmlContext
- canJIT
- xmlHttpRequestData
- delayedCallQueue
- Deletable
- ~Deletable
- extensionData
- compilationUnits
- Module
- setMaxCallDepth
- maxCallDepth
- createPrimitive
- nativeModule
- inStack
- hasCppStackOverflow
- hasJsStackOverflow
- hasStackOverflow
- ExecutionEngineCallDepthRecorder
- ExecutionEngineCallDepthRecorder
- ~ExecutionEngineCallDepthRecorder
- hasOverflow
Start learning QML with our Intro Training
Find out more