19 #ifndef hifi_ScriptEngineV8_h
20 #define hifi_ScriptEngineV8_h
24 #include <QtCore/QByteArray>
25 #include <QtCore/QHash>
26 #include <QtCore/QMetaEnum>
27 #include <QtCore/QMutex>
28 #include <QtCore/QObject>
29 #include <QtCore/QPointer>
30 #include <QtCore/QSharedPointer>
31 #include <QtCore/QString>
33 #include <v8-profiler.h>
35 #include "libplatform/libplatform.h"
38 #include "../ScriptEngine.h"
39 #include "../ScriptManager.h"
40 #include "../ScriptException.h"
43 #include "ArrayBufferClass.h"
49 class ScriptMethodV8Proxy;
51 class ScriptSignalV8Proxy;
53 template <
typename T>
class V8ScriptValueTemplate;
54 typedef V8ScriptValueTemplate<v8::Value> V8ScriptValue;
55 typedef V8ScriptValueTemplate<v8::Script> V8ScriptProgram;
57 using ScriptContextV8Pointer = std::shared_ptr<ScriptContextV8Wrapper>;
59 const double GARBAGE_COLLECTION_TIME_LIMIT_S = 1.0;
61 #define OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
63 Q_DECLARE_METATYPE(ScriptEngine::FunctionSignature)
67 public std::enable_shared_from_this<ScriptEngineV8> {
72 virtual ~ScriptEngineV8();
82 Q_INVOKABLE
virtual ScriptValue evaluate(
const QString& program,
const QString& fileName = QString())
override;
90 virtual ScriptValue newArray(uint length = 0)
override;
91 virtual ScriptValue newArrayBuffer(
const QByteArray& message)
override;
92 virtual ScriptValue newFunction(ScriptEngine::FunctionSignature fun,
int length = 0)
override;
94 virtual ScriptValue newMethod(QObject*
object, V8ScriptValue lifetime,
95 const QList<QMetaMethod>& metas,
int numMaxParams);
96 virtual ScriptProgramPointer newProgram(
const QString& sourceCode,
const QString& fileName)
override;
98 const ScriptEngine::QObjectWrapOptions& options = ScriptEngine::QObjectWrapOptions())
override;
102 virtual ScriptValue newValue(
double value)
override;
103 virtual ScriptValue newValue(
const QString& value)
override;
104 virtual ScriptValue newValue(
const QLatin1String& value)
override;
105 virtual ScriptValue newValue(
const char* value)
override;
106 virtual ScriptValue newVariant(
const QVariant& value)
override;
111 virtual bool raiseException(
const QString& exception,
const QString &reason = QString())
override;
113 Q_INVOKABLE
virtual void registerEnum(
const QString& enumName, QMetaEnum newEnum)
override;
114 Q_INVOKABLE
virtual void registerFunction(
const QString& name,
115 ScriptEngine::FunctionSignature fun,
116 int numArguments = -1)
override;
117 Q_INVOKABLE
virtual void registerFunction(
const QString& parent,
119 ScriptEngine::FunctionSignature fun,
120 int numArguments = -1)
override;
121 Q_INVOKABLE
virtual void registerGetterSetter(
const QString& name,
122 ScriptEngine::FunctionSignature getter,
123 ScriptEngine::FunctionSignature setter,
124 const QString& parent = QString(
""))
override;
126 virtual void setDefaultPrototype(
int metaTypeId,
const ScriptValue& prototype)
override;
127 virtual void setObjectName(
const QString& name)
override;
128 virtual bool setProperty(
const char* name,
const QVariant& value)
override;
129 virtual void setProcessEventsInterval(
int interval)
override;
130 virtual QThread* thread()
const override;
131 virtual void setThread(QThread* thread)
override;
134 virtual void updateMemoryCost(
const qint64& deltaSize)
override;
135 virtual void requestCollectGarbage()
override {
while(!_v8Isolate->IdleNotificationDeadline(getV8Platform()->MonotonicallyIncreasingTime() + GARBAGE_COLLECTION_TIME_LIMIT_S)) {}; }
137 virtual QString scriptValueDebugDetails(
const ScriptValue &value)
override;
138 QString scriptValueDebugDetailsV8(
const V8ScriptValue &value);
139 virtual QString scriptValueDebugListMembers(
const ScriptValue &value)
override;
140 QString scriptValueDebugListMembersV8(
const V8ScriptValue &v8Value);
141 virtual void logBacktrace(
const QString &title = QString(
""))
override;
147 void scheduleValueWrapperForDeletion(
ScriptValueV8Wrapper* wrapper) {_scriptValueWrappersToDelete.enqueue(wrapper);}
148 void deleteUnusedValueWrappers();
149 virtual void perManagerLoopIterationCleanup()
override;
153 inline bool IS_THREADSAFE_INVOCATION(
const QString& method) {
return ScriptEngine::IS_THREADSAFE_INVOCATION(method); }
163 static bool IS_THREADSAFE_INVOCATION(
const QThread* thread,
const QString& method);
168 Q_INVOKABLE
void registerValue(
const QString& valueName, V8ScriptValue value);
175 virtual ScriptValue create(
int type,
const void* ptr)
override;
176 virtual QVariant convert(
const ScriptValue& value,
int typeId)
override;
177 virtual void registerCustomType(
int type, ScriptEngine::MarshalFunction marshalFunc,
178 ScriptEngine::DemarshalFunction demarshalFunc)
override;
179 int computeCastPenalty(
const V8ScriptValue& val,
int destTypeId);
180 bool castValueToVariant(
const V8ScriptValue& val, QVariant& dest,
int destTypeId);
183 bool convertJSArrayToVariant(v8::Local<v8::Array> array, QVariant &dest);
184 bool convertJSObjectToVariant(v8::Local<v8::Object>
object, QVariant &dest);
185 V8ScriptValue castVariantToValue(
const QVariant& val);
186 QString valueType(
const V8ScriptValue& val);
187 v8::Isolate* getIsolate() {
188 Q_ASSERT(_v8Isolate !=
nullptr);
190 v8::Local<v8::Context> getContext();
191 const v8::Local<v8::Context> getConstContext()
const;
192 QString formatErrorMessageFromTryCatch(v8::TryCatch &tryCatch);
194 virtual QStringList getCurrentScriptURLs()
const override;
196 using ObjectWrapperMap = QMap<QObject*, QWeakPointer<ScriptObjectV8Proxy>>;
197 mutable QMutex _qobjectWrapperMapProtect;
198 ObjectWrapperMap _qobjectWrapperMap;
200 QMap<QObject*, QSharedPointer<ScriptObjectV8Proxy>> _qobjectWrapperMapV8;
205 QQueue<ScriptValueV8Wrapper*> _scriptValueWrappersToDelete;
208 v8::Local<v8::ObjectTemplate> getObjectProxyTemplate();
209 v8::Local<v8::ObjectTemplate> getMethodDataTemplate();
210 v8::Local<v8::ObjectTemplate> getFunctionDataTemplate();
211 v8::Local<v8::ObjectTemplate> getVariantDataTemplate();
212 v8::Local<v8::ObjectTemplate> getVariantProxyTemplate();
214 ScriptContextV8Pointer pushContext(v8::Local<v8::Context> context);
216 void storeGlobalObjectContents();
217 #ifdef OVERTE_V8_MEMORY_DEBUG
218 void incrementScriptValueCounter() { scriptValueCount++; };
219 void decrementScriptValueCounter() { scriptValueCount--; };
220 void incrementScriptValueProxyCounter() { scriptValueProxyCount++; };
221 void decrementScriptValueProxyCounter() { scriptValueProxyCount--; };
226 void registerSystemTypes();
229 static QMutex _v8InitMutex;
230 static std::once_flag _v8InitOnceFlag;
231 static v8::Platform* getV8Platform();
233 void setUncaughtEngineException(
const QString &message,
const QString& info = QString());
234 void setUncaughtException(
const v8::TryCatch &tryCatch,
const QString& info = QString());
235 void setUncaughtException(std::shared_ptr<ScriptException> exception);
237 friend class ScriptSignalV8Proxy;
239 std::shared_ptr<ScriptException> _uncaughtException;
243 v8::Isolate* _v8Isolate;
245 struct CustomMarshal {
246 ScriptEngine::MarshalFunction marshalFunc;
247 ScriptEngine::DemarshalFunction demarshalFunc;
249 using CustomMarshalMap = QHash<int, CustomMarshal>;
250 using CustomPrototypeMap = QHash<int, V8ScriptValue>;
252 mutable QReadWriteLock _customTypeProtect { QReadWriteLock::Recursive };
253 CustomMarshalMap _customTypes;
254 CustomPrototypeMap _customPrototypes;
258 QList<ScriptContextV8Pointer> _contexts;
260 v8::Persistent<v8::Object> _globalObjectContents;
261 bool areGlobalObjectContentsStored {
false};
265 v8::Persistent<v8::ObjectTemplate> _objectProxyTemplate;
266 v8::Persistent<v8::ObjectTemplate> _methodDataTemplate;
267 v8::Persistent<v8::ObjectTemplate> _functionDataTemplate;
268 v8::Persistent<v8::ObjectTemplate> _variantDataTemplate;
269 v8::Persistent<v8::ObjectTemplate> _variantProxyTemplate;
272 volatile int _memoryCorruptionIndicator = 12345678;
277 int _evaluatingCounter;
278 #ifdef OVERTE_V8_MEMORY_DEBUG
279 std::atomic<size_t> scriptValueCount{0};
280 std::atomic<size_t> scriptValueProxyCount{0};
283 #ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
284 bool _wasDestroyed{
false};
288 v8::CpuProfiler *_profiler{
nullptr};
289 v8::ProfilerId _profilerId{0};
293 QReadWriteLock _signalProxySetLock;
294 QSet<ScriptSignalV8Proxy*> _signalProxySet;
297 friend ScriptSignalV8Proxy;
308 bool _isContextChangeNeeded;
309 ScriptEngineV8* _engine;
312 QString getFileNameFromTryCatch(v8::TryCatch &tryCatch, v8::Isolate *isolate, v8::Local<v8::Context> &context );
[V8] Implements ScriptEngine for V8 and translates calls for QScriptEngine
Definition: ScriptEngineV8.h:303
[ScriptInterface] Provides an engine-independent interface for QScriptContext
Definition: ScriptContext.h:55
[V8] Implements ScriptContext for V8 and translates calls for V8ScriptContextInfo
Definition: ScriptContextV8Wrapper.h:33
Provides an engine-independent interface for a scripting engine.
Definition: ScriptEngine.h:93
virtual ScriptValue makeError(const ScriptValue &other, const QString &type="Error")=0
Make a ScriptValue that contains an error.
virtual void logBacktrace(const QString &title)=0
Log the current backtrace.
virtual ScriptValue checkScriptSyntax(ScriptProgramPointer program)=0
Check a program for syntax errors.
virtual ScriptValue evaluate(const QString &program, const QString &fileName=QString())=0
Runs a script.
virtual bool raiseException(const ScriptValue &exception, const QString &reason=QString())=0
Causes an exception to be raised in the currently executing script.
virtual void stopProfilingAndSave()=0
Stops collecting profiling data and saves it to a CSV file in Logs directory.
virtual bool isEvaluating() const =0
Whether a script is currently being evaluated.
virtual std::shared_ptr< ScriptException > uncaughtException() const =0
Last uncaught exception, if any.
virtual void dumpHeapObjectStatistics()=0
Prints heap statistics to a file. Collecting needs to first be started with dumpHeapObjectStatistics(...
virtual void abortEvaluation()=0
Stops the currently running script.
virtual ScriptValue evaluateInClosure(const ScriptValue &locals, const ScriptProgramPointer &program)=0
Evaluate a script in a separate environment.
virtual ScriptContext * currentContext() const =0
Context of the currently running script.
virtual void clearExceptions()=0
Clears uncaughtException and related.
virtual bool hasUncaughtException() const =0
Whether the script has an uncaught exception.
virtual void compileTest()=0
Test the underlying scripting engine.
virtual void startCollectingObjectStatistics()=0
Start collecting object statistics that can later be reported with dumpHeapObjectStatistics().
ValueOwnership
Who owns a given object.
Definition: ScriptEngine.h:109
@ QtOwnership
Object is managed by Qt.
Definition: ScriptEngine.h:114
virtual ScriptEngineMemoryStatistics getMemoryUsageStatistics()=0
Return memory usage statistics data.
virtual void startProfiling()=0
Starts collecting profiling data.
virtual void disconnectSignalProxies()=0
Cleanup function that disconnects signals connected to script proxies to avoid use-after-delete crash...
virtual ScriptValue globalObject()
Global object which holds all the functions and variables available everywhere.
Definition: ScriptEngine.h:251
Manages a single scripting engine.
Definition: ScriptManager.h:281
Definition: ScriptObjectV8Proxy.h:43
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40
[V8] Implements ScriptValue for V8 and translates calls for V8ScriptValue
Definition: ScriptValueV8Wrapper.h:32