mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 10:02:24 +02:00
Add more Doxygen docs
Doesn't work right in ScriptManager, looks like a conflict with JSDoc
This commit is contained in:
parent
887ebd5365
commit
e35aa8046d
5 changed files with 265 additions and 30 deletions
|
@ -5,6 +5,7 @@
|
|||
// Created by Brad Hefta-Gaub on 12/14/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
// Copyright 2023 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -44,48 +45,126 @@ template <typename T>
|
|||
inline T scriptvalue_cast(const ScriptValue& value);
|
||||
|
||||
|
||||
/// [ScriptInterface] Provides an engine-independent interface for QScriptEngine
|
||||
/**
|
||||
* @brief Provides an engine-independent interface for a scripting engine
|
||||
*
|
||||
* Each script engine is strictly single threaded.
|
||||
*
|
||||
* This class only provides an interface to the underlying scripting engine, and doesn't
|
||||
* provide the full environment needed to execute scripts.
|
||||
*
|
||||
* To execute scripts that have access to the API, use ScriptManager.
|
||||
*/
|
||||
class ScriptEngine {
|
||||
public:
|
||||
typedef ScriptValue (*FunctionSignature)(ScriptContext*, ScriptEngine*);
|
||||
typedef ScriptValue (*MarshalFunction)(ScriptEngine*, const void*);
|
||||
typedef bool (*DemarshalFunction)(const ScriptValue&, QVariant &dest);
|
||||
|
||||
/**
|
||||
* @brief Who owns a given object
|
||||
*
|
||||
*/
|
||||
enum ValueOwnership {
|
||||
QtOwnership = 0,
|
||||
ScriptOwnership = 1,
|
||||
AutoOwnership = 2,
|
||||
QtOwnership = 0, /** Object is managed by Qt */
|
||||
ScriptOwnership = 1, /** Object is managed by the script */
|
||||
AutoOwnership = 2, /** Ownership is determined automatically */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Which part of an object is exposed to the script
|
||||
*
|
||||
*/
|
||||
enum QObjectWrapOption {
|
||||
//ExcludeChildObjects = 0x0001, // The script object will not expose child objects as properties.
|
||||
ExcludeSuperClassMethods = 0x0002, // The script object will not expose signals and slots inherited from the superclass.
|
||||
ExcludeSuperClassProperties = 0x0004, // The script object will not expose properties inherited from the superclass.
|
||||
//ExcludeChildObjects = 0x0001, /** The script object will not expose child objects as properties. */
|
||||
ExcludeSuperClassMethods = 0x0002, /** The script object will not expose signals and slots inherited from the superclass. */
|
||||
ExcludeSuperClassProperties = 0x0004, /** The script object will not expose properties inherited from the superclass. */
|
||||
ExcludeSuperClassContents = ExcludeSuperClassMethods | ExcludeSuperClassProperties,
|
||||
//ExcludeDeleteLater = 0x0010, // The script object will not expose the QObject::deleteLater() slot.
|
||||
ExcludeSlots = 0x0020, // The script object will not expose the QObject's slots.
|
||||
AutoCreateDynamicProperties = 0x0100, // Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object.
|
||||
PreferExistingWrapperObject = 0x0200, // If a wrapper object with the requested configuration already exists, return that object.
|
||||
SkipMethodsInEnumeration = 0x0008, // Don't include methods (signals and slots) when enumerating the object's properties.
|
||||
//ExcludeDeleteLater = 0x0010, /** The script object will not expose the QObject::deleteLater() slot. */
|
||||
ExcludeSlots = 0x0020, /** The script object will not expose the QObject's slots. */
|
||||
AutoCreateDynamicProperties = 0x0100, /** Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object. */
|
||||
PreferExistingWrapperObject = 0x0200, /** If a wrapper object with the requested configuration already exists, return that object. */
|
||||
SkipMethodsInEnumeration = 0x0008, /** Don't include methods (signals and slots) when enumerating the object's properties. */
|
||||
};
|
||||
Q_DECLARE_FLAGS(QObjectWrapOptions, QObjectWrapOption);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Stops the currently running script
|
||||
*
|
||||
*/
|
||||
virtual void abortEvaluation() = 0;
|
||||
|
||||
/**
|
||||
* @brief Clears uncaughtException and related
|
||||
*
|
||||
*/
|
||||
virtual void clearExceptions() = 0;
|
||||
|
||||
virtual ScriptValue cloneUncaughtException(const QString& detail = QString()) = 0;
|
||||
|
||||
/**
|
||||
* @brief Context of the currently running script
|
||||
*
|
||||
* This allows getting a backtrace, the local variables of the currently running function, etc.
|
||||
*
|
||||
* @return ScriptContext*
|
||||
*/
|
||||
virtual ScriptContext* currentContext() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Runs a script
|
||||
*
|
||||
* This may be called several times during the lifetime of a scripting engine, with the
|
||||
* side effects accumulating.
|
||||
*
|
||||
* @param program Code to run
|
||||
* @param fileName Name of the script, for informational purposes
|
||||
* @return ScriptValue Return value of the script when it finishes running.
|
||||
*/
|
||||
virtual ScriptValue evaluate(const QString& program, const QString& fileName = QString()) = 0;
|
||||
|
||||
/**
|
||||
* @brief Evaluates a pre-compiled program
|
||||
*
|
||||
* @param program Program to evaluaate
|
||||
* @return ScriptValue
|
||||
*/
|
||||
virtual ScriptValue evaluate(const ScriptProgramPointer &program) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Evaluate a script in a separate environment
|
||||
*
|
||||
* Used for evaluating included scripts
|
||||
*
|
||||
* @param locals Local variables available to the script
|
||||
* @param program Code to run
|
||||
* @return ScriptValue
|
||||
*/
|
||||
virtual ScriptValue evaluateInClosure(const ScriptValue& locals, const ScriptProgramPointer& program) = 0;
|
||||
|
||||
/**
|
||||
* @brief Global namespace, containing all the public APIs
|
||||
*
|
||||
* @return ScriptValue
|
||||
*/
|
||||
virtual ScriptValue globalObject() {
|
||||
Q_ASSERT(false);
|
||||
return ScriptValue();
|
||||
}
|
||||
virtual bool hasUncaughtException() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Whether a script is currently being evaluated
|
||||
*
|
||||
* @return true A script is currently being evaluated
|
||||
* @return false No script is being evaluated
|
||||
*/
|
||||
virtual bool isEvaluating() const = 0;
|
||||
//virtual ScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1) = 0;
|
||||
virtual ScriptValue checkScriptSyntax(ScriptProgramPointer program) = 0;
|
||||
|
||||
virtual ScriptValue checkScriptSyntax(ScriptProgramPointer program) = 0;
|
||||
virtual ScriptValue makeError(const ScriptValue& other = ScriptValue(), const QString& type = "Error") = 0;
|
||||
virtual ScriptManager* manager() const = 0;
|
||||
virtual bool maybeEmitUncaughtException(const QString& debugHint = QString()) = 0;
|
||||
|
@ -107,6 +186,15 @@ public:
|
|||
virtual ScriptValue newValue(const char* value) = 0;
|
||||
virtual ScriptValue newVariant(const QVariant& value) = 0;
|
||||
virtual ScriptValue nullValue() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Causes an exception to be raised in the currently executing script
|
||||
*
|
||||
* @param exception
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
virtual bool raiseException(const ScriptValue& exception) = 0;
|
||||
virtual void registerEnum(const QString& enumName, QMetaEnum newEnum) = 0;
|
||||
virtual void registerFunction(const QString& name, FunctionSignature fun, int numArguments = -1) = 0;
|
||||
|
|
|
@ -112,6 +112,8 @@ public:
|
|||
#define STATIC_SCRIPT_INITIALIZER(init) \
|
||||
static ScriptManager::StaticInitializerNode static_script_initializer_(init);
|
||||
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* The <code>Script</code> API provides facilities for working with scripts.
|
||||
*
|
||||
|
@ -144,6 +146,21 @@ public:
|
|||
* <em>Read-only.</em>
|
||||
* @property {Script.ResourceBuckets} ExternalPaths - External resource buckets.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Manages a single scripting engine
|
||||
*
|
||||
* This class manages and sets up a single scripting engine to make it execute scripts.
|
||||
*
|
||||
* It passes the objects needed to expose the public API, provides console access and error
|
||||
* reporting and event management.
|
||||
*
|
||||
* This manipulates a single underlying instance of ScriptEngine.
|
||||
*
|
||||
* TODO: Split this class apart, create a ScriptManagerScriptingInterface to handle the JS API
|
||||
* side separately.
|
||||
*
|
||||
*/
|
||||
class ScriptManager : public QObject, public EntitiesScriptEngineProvider, public std::enable_shared_from_this<ScriptManager> {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString context READ getContext)
|
||||
|
@ -153,6 +170,10 @@ public:
|
|||
static const QString SCRIPT_EXCEPTION_FORMAT;
|
||||
static const QString SCRIPT_BACKTRACE_SEP;
|
||||
|
||||
/**
|
||||
* @brief Context of the script
|
||||
*
|
||||
*/
|
||||
enum Context {
|
||||
CLIENT_SCRIPT,
|
||||
ENTITY_CLIENT_SCRIPT,
|
||||
|
@ -190,16 +211,34 @@ public:
|
|||
inline StaticTypesInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticTypesInitializer(this); }
|
||||
};
|
||||
static void registerNewStaticTypesInitializer(StaticTypesInitializerNode* dest);
|
||||
/// run the script in a dedicated thread. This will have the side effect of evalulating
|
||||
/// the current script contents and calling run(). Callers will likely want to register the script with external
|
||||
/// services before calling this.
|
||||
|
||||
/**
|
||||
* @brief Run the script in a dedicated thread
|
||||
*
|
||||
* This will have the side effect of evaluating the current script contents and calling run().
|
||||
* Callers will likely want to register the script with external services before calling this.
|
||||
*/
|
||||
void runInThread();
|
||||
|
||||
/// run the script in the callers thread, exit when stop() is called.
|
||||
/**
|
||||
* @brief Run the script in the caller's thread, exit when stop() is called.
|
||||
*
|
||||
*/
|
||||
void run();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the filename of the running script
|
||||
*
|
||||
* @return QString Filename
|
||||
*/
|
||||
QString getFilename() const;
|
||||
|
||||
/**
|
||||
* @brief Underlying scripting engine
|
||||
*
|
||||
* @return ScriptEnginePointer Scripting engine
|
||||
*/
|
||||
inline ScriptEnginePointer engine() { return _engine; }
|
||||
|
||||
QList<EntityItemID> getListOfEntityScriptIDs();
|
||||
|
@ -225,16 +264,29 @@ public:
|
|||
// NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts
|
||||
Q_INVOKABLE void stop(bool marshal = false);
|
||||
|
||||
// Stop any evaluating scripts and wait for the scripting thread to finish.
|
||||
/**
|
||||
* @brief Stop any evaluating scripts and wait for the scripting thread to finish.
|
||||
*
|
||||
* @param shutdown True if we are currently shutting down
|
||||
*/
|
||||
void waitTillDoneRunning(bool shutdown = false);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
/// if the script engine is not already running, this will download the URL and start the process of seting it up
|
||||
/// to run... NOTE - this is used by Application currently to load the url. We don't really want it to be exposed
|
||||
/// to scripts. we may not need this to be invokable
|
||||
|
||||
/**
|
||||
* @brief Load a script from a given URL
|
||||
*
|
||||
* If the script engine is not already running, this will download the URL and start the process of seting it up
|
||||
* to run.
|
||||
* @note This is used by Application currently to load the url. We don't really want it to be exposed
|
||||
* to scripts. we may not need this to be invokable
|
||||
*
|
||||
* @param scriptURL URL where to load the script from
|
||||
* @param reload
|
||||
*/
|
||||
void loadURL(const QUrl& scriptURL, bool reload);
|
||||
bool hasValidScriptSuffix(const QString& scriptFileName);
|
||||
|
||||
|
@ -648,9 +700,26 @@ public:
|
|||
void disconnectNonEssentialSignals();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// These are currently used by Application to track if a script is user loaded or not. Consider finding a solution
|
||||
// inside of Application so that the ScriptManager class is not polluted by this notion
|
||||
|
||||
/**
|
||||
* @brief Set whether this script was user-loaded
|
||||
*
|
||||
* This is used by Application to track if a script is user loaded or not.
|
||||
* @note Consider finding a solution inside of Application so that the ScriptManager class is not polluted by this notion
|
||||
*
|
||||
* @param isUserLoaded Script is user-loaded.
|
||||
*/
|
||||
void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; }
|
||||
|
||||
/**
|
||||
* @brief Whether the script was user-loaded.
|
||||
*
|
||||
* This is used by Application to track if a script is user loaded or not.
|
||||
* @note Consider finding a solution inside of Application so that the ScriptManager class is not polluted by this notion
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool isUserLoaded() const { return _isUserLoaded; }
|
||||
|
||||
void setQuitWhenFinished(const bool quitWhenFinished) { _quitWhenFinished = quitWhenFinished; }
|
||||
|
@ -669,10 +738,21 @@ public:
|
|||
|
||||
void setScriptEngines(QSharedPointer<ScriptEngines>& scriptEngines) { _scriptEngines = scriptEngines; }
|
||||
|
||||
// call all the registered event handlers on an entity for the specified name.
|
||||
|
||||
/**
|
||||
* @brief Call all the registered event handlers on an entity for the specified name.
|
||||
*
|
||||
* @param entityID
|
||||
* @param eventName
|
||||
* @param eventHanderArgs
|
||||
*/
|
||||
void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, const ScriptValueList& eventHanderArgs);
|
||||
|
||||
// remove all event handlers for the specified entityID (i.e. the entity is being removed)
|
||||
/**
|
||||
* @brief Remove all event handlers for the specified entityID (i.e. the entity is being removed)
|
||||
*
|
||||
* @param entityID
|
||||
*/
|
||||
void removeAllEventHandlers(const EntityItemID& entityID);
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Heather Anderson on 5/2/21.
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
// Copyright 2023 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -22,32 +23,93 @@ class ScriptSyntaxCheckResult;
|
|||
using ScriptProgramPointer = std::shared_ptr<ScriptProgram>;
|
||||
using ScriptSyntaxCheckResultPointer = std::shared_ptr<ScriptSyntaxCheckResult>;
|
||||
|
||||
/// [ScriptInterface] Provides an engine-independent interface for QScriptProgram
|
||||
/**
|
||||
* @brief Engine-independent representation of a script program
|
||||
*
|
||||
* This is an analog of QScriptProgram from Qt5.
|
||||
*
|
||||
* It's used to pre-compile scripts, and to check their syntax.
|
||||
*
|
||||
*/
|
||||
class ScriptProgram {
|
||||
public:
|
||||
virtual ScriptSyntaxCheckResultPointer checkSyntax() = 0; //It cannot be const anymore because V8 doesn't have separate syntax checking function
|
||||
|
||||
/**
|
||||
* @brief Returns the filename associated with this program.
|
||||
*
|
||||
* @return QString
|
||||
*/
|
||||
virtual QString fileName() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the source code of this program.
|
||||
*
|
||||
* @return QString
|
||||
*/
|
||||
virtual QString sourceCode() const = 0;
|
||||
|
||||
protected:
|
||||
~ScriptProgram() {} // prevent explicit deletion of base class
|
||||
};
|
||||
|
||||
/// [ScriptInterface] Provides an engine-independent interface for QScriptSyntaxCheckResult
|
||||
|
||||
/**
|
||||
* @brief Engine-independent representation of a script syntax check
|
||||
*
|
||||
* This is an analog of QScriptSyntaxCheckResult from Qt5.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class ScriptSyntaxCheckResult {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief State of the syntax check
|
||||
*
|
||||
*/
|
||||
enum State
|
||||
{
|
||||
Error = 0,
|
||||
Intermediate = 1,
|
||||
Valid = 2
|
||||
Error = 0, /** The program contains a syntax error. */
|
||||
Intermediate = 1, /** The program is incomplete. */
|
||||
Valid = 2 /** The program is a syntactically correct program. */
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Returns the error column number of this ScriptSyntaxCheckResult, or -1 if there is no error.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
virtual int errorColumnNumber() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the error line number of this ScriptSyntaxCheckResult, or -1 if there is no error.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
virtual int errorLineNumber() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the error message of this ScriptSyntaxCheckResult, or an empty string if there is no error.
|
||||
*
|
||||
* @return QString
|
||||
*/
|
||||
virtual QString errorMessage() const = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @return QString
|
||||
*/
|
||||
virtual QString errorBacktrace() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the state of this ScriptSyntaxCheckResult.
|
||||
*
|
||||
* @return State
|
||||
*/
|
||||
virtual State state() const = 0;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include "ScriptEngineV8.h"
|
||||
#include "V8Types.h"
|
||||
|
||||
|
||||
// V8TODO: This class is likely unnecessary, and it'd be enough
|
||||
// to just use a non-abstract version of ScriptSyntaxCheckResult instead.
|
||||
class ScriptSyntaxCheckResultV8Wrapper final : public ScriptSyntaxCheckResult {
|
||||
public: // construction
|
||||
inline ScriptSyntaxCheckResultV8Wrapper() : _errorColumnNumber(0), _errorLineNumber(0), _errorMessage("Not compiled"), _state(ScriptSyntaxCheckResult::Error) {}
|
||||
|
|
|
@ -102,4 +102,6 @@ void ScriptEngineTests::scriptTest() {
|
|||
//ac->shutdownScripting();
|
||||
|
||||
|
||||
|
||||
//TODO: Add a test for Script.require(JSON)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue