//// ScriptEngineQtScript.h// libraries/script-engine/src/qtscript//// Created by Brad Hefta-Gaub on 12/14/13.// Copyright 2013 High Fidelity, Inc.// Copyright 2020 Vircadia contributors.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// /// @addtogroup ScriptEngine/// @{ #ifndef hifi_ScriptEngineQtScript_h#define hifi_ScriptEngineQtScript_h #include <QtCore/QByteArray>#include <QtCore/QEnableSharedFromThis>#include <QtCore/QMetaEnum>#include <QtCore/QObject>#include <QtCore/QPointer>#include <QtCore/QSharedPointer>#include <QtCore/QString> #include <QtScript/QScriptEngine>#include <QtScriptTools/QScriptEngineDebugger> #include "../ScriptEngine.h"#include "../ScriptManager.h" #include "ArrayBufferClass.h" class ScriptContextQtWrapper;class ScriptEngineQtScript;class ScriptManager;using ScriptEngineQtScriptPointer = QSharedPointer<ScriptEngineQtScript>;using ScriptContextQtPointer = QSharedPointer<ScriptContextQtWrapper>; Q_DECLARE_METATYPE(ScriptEngineQtScriptPointer); /// [QtScript] Implements ScriptEngine for QtScript and translates calls for QScriptEngineclass ScriptEngineQtScript : public QScriptEngine, public ScriptEngine, public QEnableSharedFromThis<ScriptEngineQtScript> { Q_OBJECT public: // ScriptEngine implementation virtual void abortEvaluation(); virtual void clearExceptions(); virtual ScriptValuePointer cloneUncaughtException(const QString& detail = QString()); virtual ScriptContext* currentContext() const; //virtual ScriptValuePointer evaluate(const QString& program, const QString& fileName = QString()); //virtual ScriptValuePointer evaluate(const ScriptProgramPointer &program); //virtual ScriptValuePointer evaluateInClosure(const ScriptValuePointer& locals, const ScriptProgramPointer& program); virtual ScriptValuePointer globalObject() const; virtual bool hasUncaughtException() const; virtual bool isEvaluating() const; virtual ScriptValuePointer lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1); virtual ScriptValuePointer makeError(const ScriptValuePointer& other, const QString& type = "Error"); virtual ScriptManager* manager() const; // if there is a pending exception and we are at the top level (non-recursive) stack frame, this emits and resets it virtual bool maybeEmitUncaughtException(const QString& debugHint = QString()); virtual ScriptValuePointer newArray(uint length = 0); virtual ScriptValuePointer newArrayBuffer(const QByteArray& message); virtual ScriptValuePointer newFunction(ScriptEngine::FunctionSignature fun, int length = 0); virtual ScriptValuePointer newObject(); virtual ScriptProgramPointer newProgram(const QString& sourceCode, const QString& fileName); virtual ScriptValuePointer newQObject(QObject *object, ScriptEngine::ValueOwnership ownership = ScriptEngine::QtOwnership, const ScriptEngine::QObjectWrapOptions &options = ScriptEngine::QObjectWrapOptions()); virtual ScriptValuePointer newValue(bool value); virtual ScriptValuePointer newValue(int value); virtual ScriptValuePointer newValue(uint value); virtual ScriptValuePointer newValue(double value); virtual ScriptValuePointer newValue(const QString& value); virtual ScriptValuePointer newValue(const QLatin1String& value); virtual ScriptValuePointer newValue(const char* value); virtual ScriptValuePointer newVariant(const QVariant& value); virtual ScriptValuePointer nullValue(); virtual bool raiseException(const ScriptValuePointer& exception); //virtual void registerEnum(const QString& enumName, QMetaEnum newEnum); //Q_INVOKABLE virtual void registerFunction(const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1); //Q_INVOKABLE virtual void registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1); //Q_INVOKABLE virtual void registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, ScriptEngine::FunctionSignature setter, const QString& parent = QString("")); //virtual void registerGlobalObject(const QString& name, QObject* object); virtual void setDefaultPrototype(int metaTypeId, const ScriptValuePointer& prototype); virtual void setObjectName(const QString& name); virtual bool setProperty(const char* name, const QVariant& value); virtual void setProcessEventsInterval(int interval); virtual QThread* thread() const; virtual ScriptValuePointer undefinedValue(); virtual ScriptValuePointer uncaughtException() const; virtual QStringList uncaughtExceptionBacktrace() const; virtual int uncaughtExceptionLineNumber() const; // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways inline bool IS_THREADSAFE_INVOCATION(const QString& method) { return ScriptEngine::IS_THREADSAFE_INVOCATION(method); } protected: // brought over from BaseScriptEngine /**jsdoc * @function Script.makeError * @param {object} [other] - Other. * @param {string} [type="Error"] - Error. * @returns {object} Object. * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error"); // if the currentContext() is valid then throw the passed exception; otherwise, immediately emit it. // note: this is used in cases where C++ code might call into JS API methods directly bool raiseException(const QScriptValue& exception); // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways static bool IS_THREADSAFE_INVOCATION(const QThread* thread, const QString& method); public: ScriptEngineQtScript(ScriptManager* scriptManager = nullptr); ~ScriptEngineQtScript(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can // properly ensure they are only called on the correct thread /**jsdoc * @function Script.registerGlobalObject * @param {string} name - Name. * @param {object} object - Object. * @deprecated This function is deprecated and will be removed. */ /// registers a global object by name Q_INVOKABLE virtual void registerGlobalObject(const QString& name, QObject* object); /**jsdoc * @function Script.registerGetterSetter * @param {string} name - Name. * @param {function} getter - Getter. * @param {function} setter - Setter. * @param {string} [parent=""] - Parent. * @deprecated This function is deprecated and will be removed. */ /// registers a global getter/setter Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter, QScriptEngine::FunctionSignature setter, const QString& parent = QString("")); Q_INVOKABLE virtual void registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, ScriptEngine::FunctionSignature setter, const QString& parent = QString("")); /**jsdoc * @function Script.registerFunction * @param {string} name - Name. * @param {function} function - Function. * @param {number} [numArguments=-1] - Number of arguments. * @deprecated This function is deprecated and will be removed. */ /// register a global function Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1); Q_INVOKABLE virtual void registerFunction(const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1); /**jsdoc * @function Script.registerFunction * @param {string} parent - Parent. * @param {string} name - Name. * @param {function} function - Function. * @param {number} [numArguments=-1] - Number of arguments. * @deprecated This function is deprecated and will be removed. */ /// register a function as a method on a previously registered global object Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1); Q_INVOKABLE virtual void registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1); /**jsdoc * @function Script.registerEnum * @param {string} name - Name. * @param {object} enum - Enum. * @deprecated This function is deprecated and will be removed. */ // WARNING: This function must be called after a registerGlobalObject that creates the namespace this enum is located in, or // the globalObject won't function. E.g., if you have a Foo object and a Foo.FooType enum, Foo must be registered first. /// registers a global enum Q_INVOKABLE virtual void registerEnum(const QString& enumName, QMetaEnum newEnum); /**jsdoc * @function Script.registerValue * @param {string} name - Name. * @param {object} value - Value. * @deprecated This function is deprecated and will be removed. */ /// registers a global object by name Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value); /**jsdoc * @function Script.evaluate * @param {string} program - Program. * @param {string} filename - File name. * @param {number} [lineNumber=-1] - Line number. * @returns {object} Object. * @deprecated This function is deprecated and will be removed. */ /// evaluate some code in the context of the ScriptEngineQtScript and return the result Q_INVOKABLE virtual ScriptValuePointer evaluate(const QString& program, const QString& fileName); // this is also used by the script tool widget Q_INVOKABLE virtual ScriptValuePointer evaluate(const ScriptProgramPointer& program); /**jsdoc * @function Script.evaluateInClosure * @param {object} locals - Locals. * @param {object} program - Program. * @returns {object} Object. * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE virtual ScriptValuePointer evaluateInClosure(const ScriptValuePointer& locals, const ScriptProgramPointer& program); /**jsdoc * Checks whether the application was compiled as a debug build. * @function Script.isDebugMode * @returns {boolean} <code>true</code> if the application was compiled as a debug build, <code>false</code> if it was * compiled as a release build. */ Q_INVOKABLE bool isDebugMode() const; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MODULE related methods /**jsdoc * Prints a message to the program log and emits {@link Script.printedMessage}. * <p>Alternatively, you can use {@link print} or one of the {@link console} API methods.</p> * @function Script.print * @param {string} message - The message to print. */ Q_INVOKABLE void print(const QString& message); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Entity Script Related methods /**jsdoc * Manually runs the JavaScript garbage collector which reclaims memory by disposing of objects that are no longer * reachable. * @function Script.requestGarbageCollection */ Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); } bool isRunning() const { return _isRunning; } // used by ScriptWidget bool isDebuggable() const { return _debuggable; } void disconnectNonEssentialSignals(); // NOTE - this is used by the TypedArray implementation. we need to review this for thread safety ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; } /**jsdoc * @function Script.updateMemoryCost * @param {number} deltaSize - Delta size. * @deprecated This function is deprecated and will be removed. */ virtual void updateMemoryCost(const qint64& deltaSize); signals: /**jsdoc * Triggered frequently at a system-determined interval. * @function Script.update * @param {number} deltaTime - The time since the last update, in s. * @returns {Signal} * @example <caption>Report script update intervals.</caption> * Script.update.connect(function (deltaTime) { * print("Update: " + deltaTime); * }); */ void update(float deltaTime); /**jsdoc * @function Script.finished * @param {string} filename - File name. * @param {object} engine - Engine. * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void finished(const QString& fileNameString, ScriptEngineQtScriptPointer); /**jsdoc * @function Script.cleanupMenuItem * @param {string} menuItem - Menu item. * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void cleanupMenuItem(const QString& menuItemString); /**jsdoc * Triggered when the script prints a message to the program log via {@link print}, {@link Script.print}, * {@link console.log}, {@link console.debug}, {@link console.group}, {@link console.groupEnd}, {@link console.time}, or * {@link console.timeEnd}. * @function Script.printedMessage * @param {string} message - The message. * @param {string} scriptName - The name of the script that generated the message. * @returns {Signal} */ void printedMessage(const QString& message, const QString& scriptName); /**jsdoc * Triggered when the script generates an error, {@link console.error} or {@link console.exception} is called, or * {@link console.assert} is called and fails. * @function Script.errorMessage * @param {string} message - The error message. * @param {string} scriptName - The name of the script that generated the error message. * @returns {Signal} */ void errorMessage(const QString& message, const QString& scriptName); /**jsdoc * Triggered when the script generates a warning or {@link console.warn} is called. * @function Script.warningMessage * @param {string} message - The warning message. * @param {string} scriptName - The name of the script that generated the warning message. * @returns {Signal} */ void warningMessage(const QString& message, const QString& scriptName); /**jsdoc * Triggered when the script generates an information message or {@link console.info} is called. * @function Script.infoMessage * @param {string} message - The information message. * @param {string} scriptName - The name of the script that generated the information message. * @returns {Signal} */ void infoMessage(const QString& message, const QString& scriptName); /**jsdoc * Triggered when the running state of the script changes, e.g., from running to stopping. * @function Script.runningStateChanged * @returns {Signal} */ void runningStateChanged(); /**jsdoc * @function Script.clearDebugWindow * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void clearDebugWindow(); /**jsdoc * @function Script.loadScript * @param {string} scriptName - Script name. * @param {boolean} isUserLoaded - Is user loaded. * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void loadScript(const QString& scriptName, bool isUserLoaded); /**jsdoc * @function Script.reloadScript * @param {string} scriptName - Script name. * @param {boolean} isUserLoaded - Is user loaded. * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void reloadScript(const QString& scriptName, bool isUserLoaded); /**jsdoc * Triggered when the script has stopped. * @function Script.doneRunning * @returns {Signal} */ void doneRunning(); /**jsdoc * @function Script.entityScriptDetailsUpdated * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ // Emitted when an entity script is added or removed, or when the status of an entity // script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example) void entityScriptDetailsUpdated(); public: // not for public use, but I don't like how Qt strings this along with private friend functions virtual ScriptValuePointer create(int type, const void* ptr); virtual bool convert(const ScriptValuePointer& value, int type, void* ptr); virtual void registerCustomType(int type, ScriptEngine::MarshalFunction mf, ScriptEngine::DemarshalFunction df, const ScriptValuePointer& prototype); protected: // like `newFunction`, but allows mapping inline C++ lambdas with captures as callable QScriptValues // even though the context/engine parameters are redundant in most cases, the function signature matches `newFunction` // anyway so that newLambdaFunction can be used to rapidly prototype / test utility APIs and then if becoming // permanent more easily promoted into regular static newFunction scenarios. QScriptValue newLambdaFunction(std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation, const QScriptValue& data = QScriptValue(), const QScriptEngine::ValueOwnership& ownership = QScriptEngine::AutoOwnership); protected: /**jsdoc * @function Script.executeOnScriptThread * @param {function} function - Function. * @param {ConnectionType} [type=2] - Connection type. * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type = Qt::QueuedConnection ); QPointer<ScriptManager> _manager; ScriptValuePointer _nullValue; ScriptValuePointer _undefinedValue; mutable ScriptContextQtPointer _currContext; std::atomic<bool> _isRunning { false }; bool _isThreaded { false }; QScriptEngineDebugger* _debugger { nullptr }; bool _debuggable { false }; qint64 _lastUpdate; ArrayBufferClass* _arrayBufferClass;}; // Lambda helps create callable QScriptValues out of std::functions:// (just meant for use from within the script engine itself)class Lambda : public QObject { Q_OBJECTpublic: Lambda(ScriptEngineQtScript* engine, std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation, QScriptValue data); ~Lambda();public slots: QScriptValue call(); QString toString() const; private: ScriptEngineQtScript* engine; std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation; QScriptValue data;}; #endif // hifi_ScriptEngineQtScript_h /// @}
//
// ScriptEngineQtScript.h
// libraries/script-engine/src/qtscript
//
// Created by Brad Hefta-Gaub on 12/14/13.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/// @addtogroup ScriptEngine
/// @{
#ifndef hifi_ScriptEngineQtScript_h
#define hifi_ScriptEngineQtScript_h
#include <QtCore/QByteArray>
#include <QtCore/QEnableSharedFromThis>
#include <QtCore/QMetaEnum>
#include <QtCore/QObject>
#include <QtCore/QPointer>
#include <QtCore/QSharedPointer>
#include <QtCore/QString>
#include <QtScript/QScriptEngine>
#include <QtScriptTools/QScriptEngineDebugger>
#include "../ScriptEngine.h"
#include "../ScriptManager.h"
#include "ArrayBufferClass.h"
class ScriptContextQtWrapper;
class ScriptEngineQtScript;
class ScriptManager;
using ScriptEngineQtScriptPointer = QSharedPointer<ScriptEngineQtScript>;
using ScriptContextQtPointer = QSharedPointer<ScriptContextQtWrapper>;
Q_DECLARE_METATYPE(ScriptEngineQtScriptPointer);
/// [QtScript] Implements ScriptEngine for QtScript and translates calls for QScriptEngine
class ScriptEngineQtScript : public QScriptEngine, public ScriptEngine, public QEnableSharedFromThis<ScriptEngineQtScript> {
Q_OBJECT
public: // ScriptEngine implementation
virtual void abortEvaluation();
virtual void clearExceptions();
virtual ScriptValuePointer cloneUncaughtException(const QString& detail = QString());
virtual ScriptContext* currentContext() const;
//virtual ScriptValuePointer evaluate(const QString& program, const QString& fileName = QString());
//virtual ScriptValuePointer evaluate(const ScriptProgramPointer &program);
//virtual ScriptValuePointer evaluateInClosure(const ScriptValuePointer& locals, const ScriptProgramPointer& program);
virtual ScriptValuePointer globalObject() const;
virtual bool hasUncaughtException() const;
virtual bool isEvaluating() const;
virtual ScriptValuePointer lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1);
virtual ScriptValuePointer makeError(const ScriptValuePointer& other, const QString& type = "Error");
virtual ScriptManager* manager() const;
// if there is a pending exception and we are at the top level (non-recursive) stack frame, this emits and resets it
virtual bool maybeEmitUncaughtException(const QString& debugHint = QString());
virtual ScriptValuePointer newArray(uint length = 0);
virtual ScriptValuePointer newArrayBuffer(const QByteArray& message);
virtual ScriptValuePointer newFunction(ScriptEngine::FunctionSignature fun, int length = 0);
virtual ScriptValuePointer newObject();
virtual ScriptProgramPointer newProgram(const QString& sourceCode, const QString& fileName);
virtual ScriptValuePointer newQObject(QObject *object, ScriptEngine::ValueOwnership ownership = ScriptEngine::QtOwnership,
const ScriptEngine::QObjectWrapOptions &options = ScriptEngine::QObjectWrapOptions());
virtual ScriptValuePointer newValue(bool value);
virtual ScriptValuePointer newValue(int value);
virtual ScriptValuePointer newValue(uint value);
virtual ScriptValuePointer newValue(double value);
virtual ScriptValuePointer newValue(const QString& value);
virtual ScriptValuePointer newValue(const QLatin1String& value);
virtual ScriptValuePointer newValue(const char* value);
virtual ScriptValuePointer newVariant(const QVariant& value);
virtual ScriptValuePointer nullValue();
virtual bool raiseException(const ScriptValuePointer& exception);
//virtual void registerEnum(const QString& enumName, QMetaEnum newEnum);
//Q_INVOKABLE virtual void registerFunction(const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1);
//Q_INVOKABLE virtual void registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1);
//Q_INVOKABLE virtual void registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, ScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
//virtual void registerGlobalObject(const QString& name, QObject* object);
virtual void setDefaultPrototype(int metaTypeId, const ScriptValuePointer& prototype);
virtual void setObjectName(const QString& name);
virtual bool setProperty(const char* name, const QVariant& value);
virtual void setProcessEventsInterval(int interval);
virtual QThread* thread() const;
virtual ScriptValuePointer undefinedValue();
virtual ScriptValuePointer uncaughtException() const;
virtual QStringList uncaughtExceptionBacktrace() const;
virtual int uncaughtExceptionLineNumber() const;
// helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
inline bool IS_THREADSAFE_INVOCATION(const QString& method) { return ScriptEngine::IS_THREADSAFE_INVOCATION(method); }
protected: // brought over from BaseScriptEngine
/**jsdoc
* @function Script.makeError
* @param {object} [other] - Other.
* @param {string} [type="Error"] - Error.
* @returns {object} Object.
* @deprecated This function is deprecated and will be removed.
*/
Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error");
// if the currentContext() is valid then throw the passed exception; otherwise, immediately emit it.
// note: this is used in cases where C++ code might call into JS API methods directly
bool raiseException(const QScriptValue& exception);
// helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
static bool IS_THREADSAFE_INVOCATION(const QThread* thread, const QString& method);
public:
ScriptEngineQtScript(ScriptManager* scriptManager = nullptr);
~ScriptEngineQtScript();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can
// properly ensure they are only called on the correct thread
/**jsdoc
* @function Script.registerGlobalObject
* @param {string} name - Name.
* @param {object} object - Object.
* @deprecated This function is deprecated and will be removed.
*/
/// registers a global object by name
Q_INVOKABLE virtual void registerGlobalObject(const QString& name, QObject* object);
/**jsdoc
* @function Script.registerGetterSetter
* @param {string} name - Name.
* @param {function} getter - Getter.
* @param {function} setter - Setter.
* @param {string} [parent=""] - Parent.
* @deprecated This function is deprecated and will be removed.
*/
/// registers a global getter/setter
Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
QScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
Q_INVOKABLE virtual void registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, ScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
/**jsdoc
* @function Script.registerFunction
* @param {string} name - Name.
* @param {function} function - Function.
* @param {number} [numArguments=-1] - Number of arguments.
* @deprecated This function is deprecated and will be removed.
*/
/// register a global function
Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
Q_INVOKABLE virtual void registerFunction(const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1);
/**jsdoc
* @function Script.registerFunction
* @param {string} parent - Parent.
* @param {string} name - Name.
* @param {function} function - Function.
* @param {number} [numArguments=-1] - Number of arguments.
* @deprecated This function is deprecated and will be removed.
*/
/// register a function as a method on a previously registered global object
Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun,
int numArguments = -1);
Q_INVOKABLE virtual void registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1);
/**jsdoc
* @function Script.registerEnum
* @param {string} name - Name.
* @param {object} enum - Enum.
* @deprecated This function is deprecated and will be removed.
*/
// WARNING: This function must be called after a registerGlobalObject that creates the namespace this enum is located in, or
// the globalObject won't function. E.g., if you have a Foo object and a Foo.FooType enum, Foo must be registered first.
/// registers a global enum
Q_INVOKABLE virtual void registerEnum(const QString& enumName, QMetaEnum newEnum);
/**jsdoc
* @function Script.registerValue
* @param {string} name - Name.
* @param {object} value - Value.
* @deprecated This function is deprecated and will be removed.
*/
/// registers a global object by name
Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value);
/**jsdoc
* @function Script.evaluate
* @param {string} program - Program.
* @param {string} filename - File name.
* @param {number} [lineNumber=-1] - Line number.
* @returns {object} Object.
* @deprecated This function is deprecated and will be removed.
*/
/// evaluate some code in the context of the ScriptEngineQtScript and return the result
Q_INVOKABLE virtual ScriptValuePointer evaluate(const QString& program, const QString& fileName); // this is also used by the script tool widget
Q_INVOKABLE virtual ScriptValuePointer evaluate(const ScriptProgramPointer& program);
/**jsdoc
* @function Script.evaluateInClosure
* @param {object} locals - Locals.
* @param {object} program - Program.
* @returns {object} Object.
* @deprecated This function is deprecated and will be removed.
*/
Q_INVOKABLE virtual ScriptValuePointer evaluateInClosure(const ScriptValuePointer& locals, const ScriptProgramPointer& program);
/**jsdoc
* Checks whether the application was compiled as a debug build.
* @function Script.isDebugMode
* @returns {boolean} <code>true</code> if the application was compiled as a debug build, <code>false</code> if it was
* compiled as a release build.
*/
Q_INVOKABLE bool isDebugMode() const;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MODULE related methods
/**jsdoc
* Prints a message to the program log and emits {@link Script.printedMessage}.
* <p>Alternatively, you can use {@link print} or one of the {@link console} API methods.</p>
* @function Script.print
* @param {string} message - The message to print.
*/
Q_INVOKABLE void print(const QString& message);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Entity Script Related methods
/**jsdoc
* Manually runs the JavaScript garbage collector which reclaims memory by disposing of objects that are no longer
* reachable.
* @function Script.requestGarbageCollection
*/
Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); }
bool isRunning() const { return _isRunning; } // used by ScriptWidget
bool isDebuggable() const { return _debuggable; }
void disconnectNonEssentialSignals();
// NOTE - this is used by the TypedArray implementation. we need to review this for thread safety
ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; }
/**jsdoc
* @function Script.updateMemoryCost
* @param {number} deltaSize - Delta size.
* @deprecated This function is deprecated and will be removed.
*/
virtual void updateMemoryCost(const qint64& deltaSize);
signals:
/**jsdoc
* Triggered frequently at a system-determined interval.
* @function Script.update
* @param {number} deltaTime - The time since the last update, in s.
* @returns {Signal}
* @example <caption>Report script update intervals.</caption>
* Script.update.connect(function (deltaTime) {
* print("Update: " + deltaTime);
* });
*/
void update(float deltaTime);
/**jsdoc
* @function Script.finished
* @param {string} filename - File name.
* @param {object} engine - Engine.
* @returns {Signal}
* @deprecated This signal is deprecated and will be removed.
*/
void finished(const QString& fileNameString, ScriptEngineQtScriptPointer);
/**jsdoc
* @function Script.cleanupMenuItem
* @param {string} menuItem - Menu item.
* @returns {Signal}
* @deprecated This signal is deprecated and will be removed.
*/
void cleanupMenuItem(const QString& menuItemString);
/**jsdoc
* Triggered when the script prints a message to the program log via {@link print}, {@link Script.print},
* {@link console.log}, {@link console.debug}, {@link console.group}, {@link console.groupEnd}, {@link console.time}, or
* {@link console.timeEnd}.
* @function Script.printedMessage
* @param {string} message - The message.
* @param {string} scriptName - The name of the script that generated the message.
* @returns {Signal}
*/
void printedMessage(const QString& message, const QString& scriptName);
/**jsdoc
* Triggered when the script generates an error, {@link console.error} or {@link console.exception} is called, or
* {@link console.assert} is called and fails.
* @function Script.errorMessage
* @param {string} message - The error message.
* @param {string} scriptName - The name of the script that generated the error message.
* @returns {Signal}
*/
void errorMessage(const QString& message, const QString& scriptName);
/**jsdoc
* Triggered when the script generates a warning or {@link console.warn} is called.
* @function Script.warningMessage
* @param {string} message - The warning message.
* @param {string} scriptName - The name of the script that generated the warning message.
* @returns {Signal}
*/
void warningMessage(const QString& message, const QString& scriptName);
/**jsdoc
* Triggered when the script generates an information message or {@link console.info} is called.
* @function Script.infoMessage
* @param {string} message - The information message.
* @param {string} scriptName - The name of the script that generated the information message.
* @returns {Signal}
*/
void infoMessage(const QString& message, const QString& scriptName);
/**jsdoc
* Triggered when the running state of the script changes, e.g., from running to stopping.
* @function Script.runningStateChanged
* @returns {Signal}
*/
void runningStateChanged();
/**jsdoc
* @function Script.clearDebugWindow
* @returns {Signal}
* @deprecated This signal is deprecated and will be removed.
*/
void clearDebugWindow();
/**jsdoc
* @function Script.loadScript
* @param {string} scriptName - Script name.
* @param {boolean} isUserLoaded - Is user loaded.
* @returns {Signal}
* @deprecated This signal is deprecated and will be removed.
*/
void loadScript(const QString& scriptName, bool isUserLoaded);
/**jsdoc
* @function Script.reloadScript
* @param {string} scriptName - Script name.
* @param {boolean} isUserLoaded - Is user loaded.
* @returns {Signal}
* @deprecated This signal is deprecated and will be removed.
*/
void reloadScript(const QString& scriptName, bool isUserLoaded);
/**jsdoc
* Triggered when the script has stopped.
* @function Script.doneRunning
* @returns {Signal}
*/
void doneRunning();
/**jsdoc
* @function Script.entityScriptDetailsUpdated
* @returns {Signal}
* @deprecated This signal is deprecated and will be removed.
*/
// Emitted when an entity script is added or removed, or when the status of an entity
// script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example)
void entityScriptDetailsUpdated();
public: // not for public use, but I don't like how Qt strings this along with private friend functions
virtual ScriptValuePointer create(int type, const void* ptr);
virtual bool convert(const ScriptValuePointer& value, int type, void* ptr);
virtual void registerCustomType(int type, ScriptEngine::MarshalFunction mf, ScriptEngine::DemarshalFunction df, const ScriptValuePointer& prototype);
protected:
// like `newFunction`, but allows mapping inline C++ lambdas with captures as callable QScriptValues
// even though the context/engine parameters are redundant in most cases, the function signature matches `newFunction`
// anyway so that newLambdaFunction can be used to rapidly prototype / test utility APIs and then if becoming
// permanent more easily promoted into regular static newFunction scenarios.
QScriptValue newLambdaFunction(std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation,
const QScriptValue& data = QScriptValue(),
const QScriptEngine::ValueOwnership& ownership = QScriptEngine::AutoOwnership);
protected:
/**jsdoc
* @function Script.executeOnScriptThread
* @param {function} function - Function.
* @param {ConnectionType} [type=2] - Connection type.
* @deprecated This function is deprecated and will be removed.
*/
Q_INVOKABLE void executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type = Qt::QueuedConnection );
QPointer<ScriptManager> _manager;
ScriptValuePointer _nullValue;
ScriptValuePointer _undefinedValue;
mutable ScriptContextQtPointer _currContext;
std::atomic<bool> _isRunning { false };
bool _isThreaded { false };
QScriptEngineDebugger* _debugger { nullptr };
bool _debuggable { false };
qint64 _lastUpdate;
ArrayBufferClass* _arrayBufferClass;
};
// Lambda helps create callable QScriptValues out of std::functions:
// (just meant for use from within the script engine itself)
class Lambda : public QObject {
Q_OBJECT
public:
Lambda(ScriptEngineQtScript* engine,
std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation,
QScriptValue data);
~Lambda();
public slots:
QScriptValue call();
QString toString() const;
private:
ScriptEngineQtScript* engine;
std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation;
QScriptValue data;
};
#endif // hifi_ScriptEngineQtScript_h
/// @}