Overte C++ Documentation
ScriptEngine.h
1 //
2 // ScriptEngine.h
3 // libraries/script-engine/src
4 //
5 // Created by Brad Hefta-Gaub on 12/14/13.
6 // Copyright 2013 High Fidelity, Inc.
7 // Copyright 2020 Vircadia contributors.
8 // Copyright 2023 Overte e.V.
9 //
10 // Distributed under the Apache License, Version 2.0.
11 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
12 // SPDX-License-Identifier: Apache-2.0
13 //
14 
17 
18 #ifndef hifi_ScriptEngine_h
19 #define hifi_ScriptEngine_h
20 
21 #include <memory>
22 
23 #include <QtCore/QFlags>
24 #include <QtCore/QObject>
25 
26 #include "ScriptValue.h"
27 #include "ScriptException.h"
28 
29 // These are used for debugging memory leaks caused by persistent handles
30 //#define OVERTE_V8_MEMORY_DEBUG
31 
32 class QByteArray;
33 class QLatin1String;
34 class QString;
35 class QThread;
36 class QVariant;
37 class ScriptContext;
38 class ScriptEngine;
39 class ScriptManager;
40 class ScriptProgram;
41 using ScriptEnginePointer = std::shared_ptr<ScriptEngine>;
42 using ScriptProgramPointer = std::shared_ptr<ScriptProgram>;
43 
44 Q_DECLARE_METATYPE(ScriptEnginePointer);
45 
46 template <typename T>
47 inline ScriptValue
48 
49 scriptValueFromValue(ScriptEngine* engine, const T& t);
50 
51 template <typename T>
52 inline T scriptvalue_cast(const ScriptValue& value);
53 
54 class ScriptEngineMemoryStatistics {
55 public:
56  size_t totalHeapSize;
57  size_t usedHeapSize;
58  size_t totalAvailableSize;
59  size_t totalGlobalHandlesSize;
60  size_t usedGlobalHandlesSize;
61 #ifdef OVERTE_V8_MEMORY_DEBUG
62  size_t scriptValueCount;
63  size_t scriptValueProxyCount;
64  size_t qObjectCount;
65  //size_t qVariantProxyCount;
66 #endif
67 };
68 
93 class ScriptEngine : public QObject {
94  Q_OBJECT
95 public:
96 
97  ScriptEngine(ScriptManager *manager = nullptr) : _manager(manager) {
98 
99  }
100 
101  typedef ScriptValue (*FunctionSignature)(ScriptContext*, ScriptEngine*);
102  typedef ScriptValue (*MarshalFunction)(ScriptEngine*, const void*);
103  typedef bool (*DemarshalFunction)(const ScriptValue&, QVariant &dest);
104 
115 
121 
129  };
130 
136 
141  //ExcludeChildObjects = 0x0001,
142 
148 
154 
160 
161  //ExcludeDeleteLater = 0x0010,
162 
167  ExcludeSlots = 0x0020,
168 
174 
180 
186  };
187  Q_DECLARE_FLAGS(QObjectWrapOptions, QObjectWrapOption);
188 
189 public:
194  virtual void abortEvaluation() = 0;
195 
200  virtual void clearExceptions() = 0;
201 
209  virtual ScriptContext* currentContext() const = 0;
210 
221  virtual ScriptValue evaluate(const QString& program, const QString& fileName = QString()) = 0;
222 
229  virtual ScriptValue evaluate(const ScriptProgramPointer &program) = 0;
230 
231 
241  virtual ScriptValue evaluateInClosure(const ScriptValue& locals, const ScriptProgramPointer& program) = 0;
242 
252  Q_ASSERT(false);
253  return ScriptValue();
254  }
255 
262  virtual bool hasUncaughtException() const = 0;
263 
270  virtual bool isEvaluating() const = 0;
271  //virtual ScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1) = 0;
272 
287  virtual ScriptValue checkScriptSyntax(ScriptProgramPointer program) = 0;
288 
294  ScriptManager* manager() const { return _manager; }
295 
296  virtual ScriptValue newArray(uint length = 0) = 0;
297  virtual ScriptValue newArrayBuffer(const QByteArray& message) = 0;
298  virtual ScriptValue newFunction(FunctionSignature fun, int length = 0) {
299  Q_ASSERT(false);
300  return ScriptValue();
301  }
302  virtual ScriptValue newObject() = 0;
303  virtual ScriptProgramPointer newProgram(const QString& sourceCode, const QString& fileName) = 0;
304  virtual ScriptValue newQObject(QObject *object, ValueOwnership ownership = QtOwnership, const QObjectWrapOptions &options = QObjectWrapOptions()) = 0;
305  virtual ScriptValue newValue(bool value) = 0;
306  virtual ScriptValue newValue(int value) = 0;
307  virtual ScriptValue newValue(uint value) = 0;
308  virtual ScriptValue newValue(double value) = 0;
309  virtual ScriptValue newValue(const QString& value) = 0;
310  virtual ScriptValue newValue(const QLatin1String& value) = 0;
311  virtual ScriptValue newValue(const char* value) = 0;
312  virtual ScriptValue newVariant(const QVariant& value) = 0;
313  virtual ScriptValue nullValue() = 0;
314 
315 
325  virtual ScriptValue makeError(const ScriptValue& other, const QString& type = "Error") = 0;
326 
327 
336  virtual bool raiseException(const ScriptValue& exception, const QString &reason = QString()) = 0;
337 
346  virtual bool raiseException(const QString& error, const QString &reason = QString()) = 0;
347 
348 
349  virtual void registerEnum(const QString& enumName, QMetaEnum newEnum) = 0;
350  virtual void registerFunction(const QString& name, FunctionSignature fun, int numArguments = -1) = 0;
351  virtual void registerFunction(const QString& parent, const QString& name, FunctionSignature fun, int numArguments = -1) = 0;
352  virtual void registerGetterSetter(const QString& name, FunctionSignature getter, FunctionSignature setter, const QString& parent = QString("")) = 0;
353  virtual void registerGlobalObject(const QString& name, QObject* object, ScriptEngine::ValueOwnership = ScriptEngine::QtOwnership) = 0;
354  virtual void setDefaultPrototype(int metaTypeId, const ScriptValue& prototype) = 0;
355  virtual void setObjectName(const QString& name) = 0;
356  virtual bool setProperty(const char* name, const QVariant& value) = 0;
357  virtual void setProcessEventsInterval(int interval) = 0;
358  virtual QThread* thread() const = 0;
359  virtual void setThread(QThread* thread) = 0;
360  //Q_INVOKABLE virtual void enterIsolateOnThisThread() = 0;
361  virtual ScriptValue undefinedValue() = 0;
362 
371  virtual std::shared_ptr<ScriptException> uncaughtException() const = 0;
372 
373  virtual void updateMemoryCost(const qint64& deltaSize) = 0;
374  virtual void requestCollectGarbage() = 0;
375 
384  virtual void compileTest() = 0;
385  virtual QString scriptValueDebugDetails(const ScriptValue &value) = 0;
386  virtual QString scriptValueDebugListMembers(const ScriptValue &value) = 0;
387 
395  virtual void logBacktrace(const QString &title) = 0;
396 
404  virtual ScriptEngineMemoryStatistics getMemoryUsageStatistics() = 0;
405 
410 
414  virtual void dumpHeapObjectStatistics() = 0;
415 
419  virtual void startProfiling() = 0;
420 
424  virtual void stopProfilingAndSave() = 0;
425 
429  virtual void disconnectSignalProxies() = 0;
430 
431 public:
432  // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
433  bool IS_THREADSAFE_INVOCATION(const QString& method);
434 
435 public:
436  template <typename T>
437  inline T fromScriptValue(const ScriptValue& value) {
438  return scriptvalue_cast<T>(value);
439  }
440 
441  template <typename T>
442  inline ScriptValue toScriptValue(const T& value) {
443  return scriptValueFromValue(this, value);
444  }
445 
446 public: // not for public use, but I don't like how Qt strings this along with private friend functions
447  virtual ScriptValue create(int type, const void* ptr) = 0;
448  virtual QVariant convert(const ScriptValue& value, int type) = 0;
449  virtual void registerCustomType(int type, MarshalFunction mf, DemarshalFunction df) = 0;
450  virtual QStringList getCurrentScriptURLs() const = 0;
451  virtual void perManagerLoopIterationCleanup() = 0;
452 
453 signals:
459  void exception(std::shared_ptr<ScriptException> exception);
460 
461 protected:
462  virtual ~ScriptEngine() {} // prevent explicit deletion of base class
463 
464  ScriptManager *_manager;
465 };
466 Q_DECLARE_OPERATORS_FOR_FLAGS(ScriptEngine::QObjectWrapOptions);
467 
468 ScriptEnginePointer newScriptEngine(ScriptManager* manager = nullptr);
469 
470 // Standardized CPS callback helpers (see: http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/)
471 // These two helpers allow async JS APIs that use a callback parameter to be more friendly to scripters by accepting thisObject
472 // context and adopting a consistent and intuitable callback signature:
473 // function callback(err, result) { if (err) { ... } else { /* do stuff with result */ } }
474 //
475 // To use, first pass the user-specified callback args in the same order used with optionally-scoped Qt signal connections:
476 // auto handler = makeScopedHandlerObject(scopeOrCallback, optionalMethodOrName);
477 // And then invoke the scoped handler later per CPS conventions:
478 // auto result = callScopedHandlerObject(handler, err, result);
479 ScriptValue makeScopedHandlerObject(const ScriptValue& scopeOrCallback, const ScriptValue& methodOrName);
480 ScriptValue callScopedHandlerObject(const ScriptValue& handler, const ScriptValue& err, const ScriptValue& result);
481 
483 // Inline implementations
484 /*
485 QThread* ScriptEngine::thread() const {
486  QObject* qobject = toQObject();
487  if (qobject == nullptr) {
488  return nullptr;
489  }
490  return qobject->thread();
491 }
492 */
493 
494 #endif // hifi_ScriptEngine_h
495 
[ScriptInterface] Provides an engine-independent interface for QScriptContext
Definition: ScriptContext.h:55
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 bool raiseException(const QString &error, const QString &reason=QString())=0
Causes an exception to be raised in the currently executing script.
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
@ ScriptOwnership
Object is managed by the script.
Definition: ScriptEngine.h:120
@ AutoOwnership
Ownership is determined automatically. If the object has a parent, it's deemed QtOwnership....
Definition: ScriptEngine.h:128
virtual ScriptValue evaluate(const ScriptProgramPointer &program)=0
Evaluates a pre-compiled program.
ScriptManager * manager() const
Pointer to the ScriptManager that controls this scripting engine.
Definition: ScriptEngine.h:294
QObjectWrapOption
Which part of an object is exposed to the script.
Definition: ScriptEngine.h:135
@ SkipMethodsInEnumeration
Don't include methods (signals and slots) when enumerating the object's properties.
Definition: ScriptEngine.h:185
@ ExcludeSuperClassContents
The script object will not expose the QObject::deleteLater() slot.
Definition: ScriptEngine.h:159
@ ExcludeSuperClassProperties
The script object will not expose properties inherited from the superclass.
Definition: ScriptEngine.h:153
@ PreferExistingWrapperObject
If a wrapper object with the requested configuration already exists, return that object.
Definition: ScriptEngine.h:179
@ ExcludeSuperClassMethods
The script object will not expose child objects as properties.
Definition: ScriptEngine.h:147
@ ExcludeSlots
The script object will not expose the QObject's slots.
Definition: ScriptEngine.h:167
@ AutoCreateDynamicProperties
Properties that don't already exist in the QObject will be created as dynamic properties of that obje...
Definition: ScriptEngine.h:173
virtual ScriptEngineMemoryStatistics getMemoryUsageStatistics()=0
Return memory usage statistics data.
virtual void startProfiling()=0
Starts collecting profiling data.
void exception(std::shared_ptr< ScriptException > exception)
The script being run threw an exception.
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
Engine-independent representation of a script program.
Definition: ScriptProgram.h:35
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40