671 lines
30 KiB
C++
671 lines
30 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
#ifndef QV4ENGINE_H
|
|
#define QV4ENGINE_H
|
|
|
|
//
|
|
// W A R N I N G
|
|
// -------------
|
|
//
|
|
// This file is not part of the Qt API. It exists purely as an
|
|
// implementation detail. This header file may change from version to
|
|
// version without notice, or even be removed.
|
|
//
|
|
// We mean it.
|
|
//
|
|
|
|
#include "qv4global_p.h"
|
|
#include "qv4managed_p.h"
|
|
#include "qv4context_p.h"
|
|
#include <private/qintrusivelist_p.h>
|
|
#include "qv4enginebase_p.h"
|
|
#include <private/qqmlrefcount_p.h>
|
|
#include <private/qqmljsengine_p.h>
|
|
|
|
#ifndef V4_BOOTSTRAP
|
|
# include "qv4function_p.h"
|
|
# include <private/qv8engine_p.h>
|
|
# include <private/qv4compileddata_p.h>
|
|
#endif
|
|
|
|
namespace WTF {
|
|
class BumpPointerAllocator;
|
|
class PageAllocation;
|
|
}
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
class QV8Engine;
|
|
class QQmlError;
|
|
class QJSEngine;
|
|
class QQmlEngine;
|
|
class QQmlContextData;
|
|
|
|
namespace QV4 {
|
|
namespace Debugging {
|
|
class Debugger;
|
|
} // namespace Debugging
|
|
namespace Profiling {
|
|
class Profiler;
|
|
} // namespace Profiling
|
|
namespace CompiledData {
|
|
struct CompilationUnit;
|
|
}
|
|
|
|
namespace Heap {
|
|
struct Module;
|
|
};
|
|
|
|
struct Function;
|
|
|
|
namespace Promise {
|
|
class ReactionHandler;
|
|
};
|
|
|
|
struct Q_QML_EXPORT ExecutionEngine : public EngineBase
|
|
{
|
|
private:
|
|
static qint32 maxCallDepth;
|
|
|
|
friend struct ExecutionContextSaver;
|
|
friend struct ExecutionContext;
|
|
friend struct Heap::ExecutionContext;
|
|
public:
|
|
ExecutableAllocator *executableAllocator;
|
|
ExecutableAllocator *regExpAllocator;
|
|
|
|
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
|
|
|
|
enum {
|
|
JSStackLimit = 4*1024*1024,
|
|
GCStackLimit = 2*1024*1024
|
|
};
|
|
WTF::PageAllocation *jsStack;
|
|
|
|
WTF::PageAllocation *gcStack;
|
|
|
|
QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) {
|
|
Value *ptr = jsStackTop;
|
|
jsStackTop = ptr + nValues;
|
|
return ptr;
|
|
}
|
|
|
|
Function *globalCode;
|
|
|
|
#ifdef V4_BOOTSTRAP
|
|
QJSEngine *jsEngine() const;
|
|
QQmlEngine *qmlEngine() const;
|
|
#else // !V4_BOOTSTRAP
|
|
QJSEngine *jsEngine() const { return publicEngine; }
|
|
QQmlEngine *qmlEngine() const { return v8Engine ? v8Engine->engine() : nullptr; }
|
|
#endif // V4_BOOTSTRAP
|
|
QV8Engine *v8Engine;
|
|
QJSEngine *publicEngine;
|
|
|
|
enum JSObjects {
|
|
RootContext,
|
|
ScriptContext,
|
|
IntegerNull, // Has to come after the RootContext to make the context stack safe
|
|
ObjectProto,
|
|
SymbolProto,
|
|
ArrayProto,
|
|
ArrayProtoValues,
|
|
PropertyListProto,
|
|
StringProto,
|
|
NumberProto,
|
|
BooleanProto,
|
|
DateProto,
|
|
FunctionProto,
|
|
GeneratorProto,
|
|
RegExpProto,
|
|
ErrorProto,
|
|
EvalErrorProto,
|
|
RangeErrorProto,
|
|
ReferenceErrorProto,
|
|
SyntaxErrorProto,
|
|
TypeErrorProto,
|
|
URIErrorProto,
|
|
PromiseProto,
|
|
VariantProto,
|
|
#if QT_CONFIG(qml_sequence_object)
|
|
SequenceProto,
|
|
#endif
|
|
SharedArrayBufferProto,
|
|
ArrayBufferProto,
|
|
DataViewProto,
|
|
WeakSetProto,
|
|
SetProto,
|
|
WeakMapProto,
|
|
MapProto,
|
|
IntrinsicTypedArrayProto,
|
|
ValueTypeProto,
|
|
SignalHandlerProto,
|
|
IteratorProto,
|
|
ForInIteratorProto,
|
|
SetIteratorProto,
|
|
MapIteratorProto,
|
|
ArrayIteratorProto,
|
|
StringIteratorProto,
|
|
|
|
Object_Ctor,
|
|
String_Ctor,
|
|
Symbol_Ctor,
|
|
Number_Ctor,
|
|
Boolean_Ctor,
|
|
Array_Ctor,
|
|
Function_Ctor,
|
|
GeneratorFunction_Ctor,
|
|
Date_Ctor,
|
|
RegExp_Ctor,
|
|
Error_Ctor,
|
|
EvalError_Ctor,
|
|
RangeError_Ctor,
|
|
ReferenceError_Ctor,
|
|
SyntaxError_Ctor,
|
|
TypeError_Ctor,
|
|
URIError_Ctor,
|
|
SharedArrayBuffer_Ctor,
|
|
Promise_Ctor,
|
|
ArrayBuffer_Ctor,
|
|
DataView_Ctor,
|
|
WeakSet_Ctor,
|
|
Set_Ctor,
|
|
WeakMap_Ctor,
|
|
Map_Ctor,
|
|
IntrinsicTypedArray_Ctor,
|
|
|
|
GetSymbolSpecies,
|
|
|
|
Eval_Function,
|
|
GetStack_Function,
|
|
ThrowerObject,
|
|
NJSObjects
|
|
};
|
|
Value *jsObjects;
|
|
enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
|
|
|
|
ExecutionContext *rootContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + RootContext); }
|
|
ExecutionContext *scriptContext() const { return reinterpret_cast<ExecutionContext *>(jsObjects + ScriptContext); }
|
|
void setScriptContext(ReturnedValue c) { jsObjects[ScriptContext] = c; }
|
|
FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
|
|
FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
|
|
FunctionObject *symbolCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Symbol_Ctor); }
|
|
FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
|
|
FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
|
|
FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
|
|
FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
|
|
FunctionObject *generatorFunctionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + GeneratorFunction_Ctor); }
|
|
FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
|
|
FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
|
|
FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
|
|
FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
|
|
FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
|
|
FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
|
|
FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
|
|
FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
|
|
FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
|
|
FunctionObject *sharedArrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SharedArrayBuffer_Ctor); }
|
|
FunctionObject *promiseCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Promise_Ctor); }
|
|
FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
|
|
FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
|
|
FunctionObject *weakSetCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakSet_Ctor); }
|
|
FunctionObject *setCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Set_Ctor); }
|
|
FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
|
|
FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
|
|
FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
|
|
FunctionObject *typedArrayCtors;
|
|
|
|
FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
|
|
|
|
Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
|
|
Object *symbolPrototype() const { return reinterpret_cast<Object *>(jsObjects + SymbolProto); }
|
|
Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
|
|
Object *arrayProtoValues() const { return reinterpret_cast<Object *>(jsObjects + ArrayProtoValues); }
|
|
Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
|
|
Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
|
|
Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
|
|
Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
|
|
Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
|
|
Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
|
|
Object *generatorPrototype() const { return reinterpret_cast<Object *>(jsObjects + GeneratorProto); }
|
|
Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
|
|
Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
|
|
Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
|
|
Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
|
|
Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
|
|
Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
|
|
Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
|
|
Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
|
|
Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); }
|
|
Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
|
|
#if QT_CONFIG(qml_sequence_object)
|
|
Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
|
|
#endif
|
|
|
|
Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); }
|
|
Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
|
|
Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
|
|
Object *weakSetPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakSetProto); }
|
|
Object *setPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetProto); }
|
|
Object *weakMapPrototype() const { return reinterpret_cast<Object *>(jsObjects + WeakMapProto); }
|
|
Object *mapPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapProto); }
|
|
Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + IntrinsicTypedArrayProto); }
|
|
Object *typedArrayPrototype;
|
|
|
|
Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
|
|
Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
|
|
Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
|
|
Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
|
|
Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
|
|
Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
|
|
Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
|
|
Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
|
|
|
|
EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
|
|
FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
|
|
FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
|
|
|
|
enum JSStrings {
|
|
String_Empty,
|
|
String_undefined,
|
|
String_null,
|
|
String_true,
|
|
String_false,
|
|
String_boolean,
|
|
String_number,
|
|
String_string,
|
|
String_default,
|
|
String_symbol,
|
|
String_object,
|
|
String_function,
|
|
String_length,
|
|
String_prototype,
|
|
String_constructor,
|
|
String_arguments,
|
|
String_caller,
|
|
String_callee,
|
|
String_this,
|
|
String___proto__,
|
|
String_enumerable,
|
|
String_configurable,
|
|
String_writable,
|
|
String_value,
|
|
String_get,
|
|
String_set,
|
|
String_eval,
|
|
String_uintMax,
|
|
String_name,
|
|
String_index,
|
|
String_input,
|
|
String_toString,
|
|
String_toLocaleString,
|
|
String_destroy,
|
|
String_valueOf,
|
|
String_byteLength,
|
|
String_byteOffset,
|
|
String_buffer,
|
|
String_lastIndex,
|
|
String_next,
|
|
String_done,
|
|
String_return,
|
|
String_throw,
|
|
String_global,
|
|
String_ignoreCase,
|
|
String_multiline,
|
|
String_unicode,
|
|
String_sticky,
|
|
String_source,
|
|
String_flags,
|
|
|
|
NJSStrings
|
|
};
|
|
Value *jsStrings;
|
|
|
|
enum JSSymbols {
|
|
Symbol_hasInstance,
|
|
Symbol_isConcatSpreadable,
|
|
Symbol_iterator,
|
|
Symbol_match,
|
|
Symbol_replace,
|
|
Symbol_search,
|
|
Symbol_species,
|
|
Symbol_split,
|
|
Symbol_toPrimitive,
|
|
Symbol_toStringTag,
|
|
Symbol_unscopables,
|
|
Symbol_revokableProxy,
|
|
NJSSymbols
|
|
};
|
|
Value *jsSymbols;
|
|
|
|
String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
|
|
String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
|
|
String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
|
|
String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
|
|
String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
|
|
String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
|
|
String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
|
|
String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
|
|
String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); }
|
|
String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); }
|
|
String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
|
|
String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
|
|
String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
|
|
String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
|
|
String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
|
|
String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
|
|
String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
|
|
String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
|
|
String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
|
|
String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
|
|
String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
|
|
String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
|
|
String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
|
|
String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
|
|
String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
|
|
String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
|
|
String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
|
|
String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
|
|
String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
|
|
String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
|
|
String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
|
|
String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
|
|
String *id_toLocaleString() const { return reinterpret_cast<String *>(jsStrings + String_toLocaleString); }
|
|
String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
|
|
String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
|
|
String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
|
|
String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
|
|
String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
|
|
String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
|
|
String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
|
|
String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
|
|
String *id_return() const { return reinterpret_cast<String *>(jsStrings + String_return); }
|
|
String *id_throw() const { return reinterpret_cast<String *>(jsStrings + String_throw); }
|
|
String *id_global() const { return reinterpret_cast<String *>(jsStrings + String_global); }
|
|
String *id_ignoreCase() const { return reinterpret_cast<String *>(jsStrings + String_ignoreCase); }
|
|
String *id_multiline() const { return reinterpret_cast<String *>(jsStrings + String_multiline); }
|
|
String *id_unicode() const { return reinterpret_cast<String *>(jsStrings + String_unicode); }
|
|
String *id_sticky() const { return reinterpret_cast<String *>(jsStrings + String_sticky); }
|
|
String *id_source() const { return reinterpret_cast<String *>(jsStrings + String_source); }
|
|
String *id_flags() const { return reinterpret_cast<String *>(jsStrings + String_flags); }
|
|
|
|
Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
|
|
Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
|
|
Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
|
|
Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
|
|
Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
|
|
Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
|
|
Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
|
|
Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
|
|
Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
|
|
Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
|
|
Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
|
|
Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
|
|
|
|
#ifndef V4_BOOTSTRAP
|
|
QIntrusiveList<CompiledData::CompilationUnit, &CompiledData::CompilationUnit::nextCompilationUnit> compilationUnits;
|
|
#endif
|
|
|
|
quint32 m_engineId;
|
|
|
|
RegExpCache *regExpCache;
|
|
|
|
// Scarce resources are "exceptionally high cost" QVariant types where allowing the
|
|
// normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
|
|
// out-of-resource situations. When such a resource is passed into JavaScript we
|
|
// add it to the scarceResources list and it is destroyed when we return from the
|
|
// JavaScript execution that created it. The user can prevent this behavior by
|
|
// calling preserve() on the object which removes it from this scarceResource list.
|
|
class ScarceResourceData {
|
|
public:
|
|
ScarceResourceData(const QVariant &data = QVariant()) : data(data) {}
|
|
QVariant data;
|
|
QIntrusiveListNode node;
|
|
};
|
|
QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
|
|
|
|
// Normally the JS wrappers for QObjects are stored in the QQmlData/QObjectPrivate,
|
|
// but any time a QObject is wrapped a second time in another engine, we have to do
|
|
// bookkeeping.
|
|
MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects;
|
|
#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
|
|
const bool m_canAllocateExecutableMemory;
|
|
#endif
|
|
|
|
quintptr protoIdCount = 1;
|
|
|
|
ExecutionEngine(QJSEngine *jsEngine = nullptr);
|
|
~ExecutionEngine();
|
|
|
|
#if !QT_CONFIG(qml_debug)
|
|
QV4::Debugging::Debugger *debugger() const { return nullptr; }
|
|
QV4::Profiling::Profiler *profiler() const { return nullptr; }
|
|
|
|
void setDebugger(Debugging::Debugger *) {}
|
|
void setProfiler(Profiling::Profiler *) {}
|
|
#else
|
|
QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
|
|
QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); }
|
|
|
|
void setDebugger(Debugging::Debugger *debugger);
|
|
void setProfiler(Profiling::Profiler *profiler);
|
|
#endif // QT_CONFIG(qml_debug)
|
|
|
|
ExecutionContext *currentContext() const;
|
|
|
|
// ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
|
|
quintptr newProtoId() { return (protoIdCount += 2); }
|
|
|
|
Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
|
|
|
|
Heap::Object *newObject();
|
|
Heap::Object *newObject(Heap::InternalClass *internalClass);
|
|
|
|
Heap::String *newString(const QString &s = QString());
|
|
Heap::String *newIdentifier(const QString &text);
|
|
|
|
Heap::Object *newStringObject(const String *string);
|
|
Heap::Object *newSymbolObject(const Symbol *symbol);
|
|
Heap::Object *newNumberObject(double value);
|
|
Heap::Object *newBooleanObject(bool b);
|
|
|
|
Heap::ArrayObject *newArrayObject(int count = 0);
|
|
Heap::ArrayObject *newArrayObject(const Value *values, int length);
|
|
Heap::ArrayObject *newArrayObject(const QStringList &list);
|
|
Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic);
|
|
|
|
Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
|
|
Heap::ArrayBuffer *newArrayBuffer(size_t length);
|
|
|
|
Heap::DateObject *newDateObject(const Value &value);
|
|
Heap::DateObject *newDateObject(const QDateTime &dt);
|
|
Heap::DateObject *newDateObjectFromTime(const QTime &t);
|
|
|
|
Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
|
|
Heap::RegExpObject *newRegExpObject(RegExp *re);
|
|
Heap::RegExpObject *newRegExpObject(const QRegExp &re);
|
|
|
|
Heap::Object *newErrorObject(const Value &value);
|
|
Heap::Object *newErrorObject(const QString &message);
|
|
Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
|
|
Heap::Object *newSyntaxErrorObject(const QString &message);
|
|
Heap::Object *newReferenceErrorObject(const QString &message);
|
|
Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column);
|
|
Heap::Object *newTypeErrorObject(const QString &message);
|
|
Heap::Object *newRangeErrorObject(const QString &message);
|
|
Heap::Object *newURIErrorObject(const QString &message);
|
|
Heap::Object *newURIErrorObject(const Value &message);
|
|
Heap::Object *newEvalErrorObject(const QString &message);
|
|
|
|
Heap::PromiseObject *newPromiseObject();
|
|
Heap::Object *newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability);
|
|
Promise::ReactionHandler *getPromiseReactionHandler();
|
|
|
|
Heap::Object *newVariantObject(const QVariant &v);
|
|
|
|
Heap::Object *newForInIteratorObject(Object *o);
|
|
Heap::Object *newSetIteratorObject(Object *o);
|
|
Heap::Object *newMapIteratorObject(Object *o);
|
|
Heap::Object *newArrayIteratorObject(Object *o);
|
|
|
|
Heap::QmlContext *qmlContext() const;
|
|
QObject *qmlScopeObject() const;
|
|
QQmlContextData *callingQmlContext() const;
|
|
|
|
|
|
StackTrace stackTrace(int frameLimit = -1) const;
|
|
QUrl resolvedUrl(const QString &file);
|
|
|
|
void markObjects(MarkStack *markStack);
|
|
|
|
void initRootContext();
|
|
|
|
Heap::InternalClass *newClass(Heap::InternalClass *other);
|
|
|
|
StackTrace exceptionStackTrace;
|
|
|
|
ReturnedValue throwError(const Value &value);
|
|
ReturnedValue catchException(StackTrace *trace = nullptr);
|
|
|
|
ReturnedValue throwError(const QString &message);
|
|
ReturnedValue throwSyntaxError(const QString &message);
|
|
ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column);
|
|
ReturnedValue throwTypeError();
|
|
ReturnedValue throwTypeError(const QString &message);
|
|
ReturnedValue throwReferenceError(const Value &value);
|
|
ReturnedValue throwReferenceError(const QString &name);
|
|
ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column);
|
|
ReturnedValue throwRangeError(const Value &value);
|
|
ReturnedValue throwRangeError(const QString &message);
|
|
ReturnedValue throwURIError(const Value &msg);
|
|
ReturnedValue throwUnimplemented(const QString &message);
|
|
|
|
// Use only inside catch(...) -- will re-throw if no JS exception
|
|
QQmlError catchExceptionAsQmlError();
|
|
|
|
// variant conversions
|
|
QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
|
|
QV4::ReturnedValue fromVariant(const QVariant &);
|
|
|
|
QVariantMap variantMapFromJS(const QV4::Object *o);
|
|
|
|
bool metaTypeFromJS(const Value *value, int type, void *data);
|
|
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
|
|
|
|
bool checkStackLimits();
|
|
|
|
bool canJIT(Function *f = nullptr)
|
|
{
|
|
#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
|
|
if (!m_canAllocateExecutableMemory)
|
|
return false;
|
|
if (f)
|
|
return !f->isGenerator() && f->interpreterCallCount >= jitCallCountThreshold;
|
|
return true;
|
|
#else
|
|
Q_UNUSED(f);
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
QV4::ReturnedValue global();
|
|
|
|
double localTZA = 0.0; // local timezone, initialized at startup
|
|
|
|
static QQmlRefPointer<CompiledData::CompilationUnit> compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics);
|
|
#ifndef V4_BOOTSTRAP
|
|
QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url);
|
|
QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
|
|
|
|
mutable QMutex moduleMutex;
|
|
QHash<QUrl, QQmlRefPointer<CompiledData::CompilationUnit>> modules;
|
|
void injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit);
|
|
QQmlRefPointer<CompiledData::CompilationUnit> moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr) const;
|
|
QQmlRefPointer<CompiledData::CompilationUnit> loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr);
|
|
#endif
|
|
|
|
private:
|
|
#if QT_CONFIG(qml_debug)
|
|
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
|
|
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
|
|
#endif
|
|
int jitCallCountThreshold;
|
|
|
|
// used by generated Promise objects to handle 'then' events
|
|
QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler;
|
|
};
|
|
|
|
// This is a trick to tell the code generators that functions taking a NoThrowContext won't
|
|
// throw exceptions and therefore don't need a check after the call.
|
|
#ifndef V4_BOOTSTRAP
|
|
struct NoThrowEngine : public ExecutionEngine
|
|
{
|
|
};
|
|
#else
|
|
struct NoThrowEngine;
|
|
#endif
|
|
|
|
|
|
#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
|
|
ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
|
|
|
|
struct ExecutionEngineCallDepthRecorder
|
|
{
|
|
ExecutionEngine *ee;
|
|
|
|
ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; }
|
|
~ExecutionEngineCallDepthRecorder() { --ee->callDepth; }
|
|
};
|
|
|
|
inline bool ExecutionEngine::checkStackLimits()
|
|
{
|
|
if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) {
|
|
throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
} // namespace QV4
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
#endif // QV4ENGINE_H
|