423 lines · 13.6 KB · C
RawDownload
////  ScriptValue.h//  libraries/script-engine/src////  Created by Heather Anderson on 4/25/21.//  Copyright 2021 Vircadia contributors.//  Copyright 2022-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//  SPDX-License-Identifier: Apache-2.0// /// @addtogroup ScriptEngine/// @{ #ifndef hifi_ScriptValue_h#define hifi_ScriptValue_h #include <memory> #include <QtCore/QObject>#include <QtCore/QFlags>#include <QtCore/QList>#include <QtCore/QString>#include <QtCore/QVariant>#include <QtCore/QDebug> #include "ScriptEngineLogging.h" class ScriptEngine;class ScriptValue;class ScriptValueIterator;class ScriptValueProxy;using ScriptEnginePointer = std::shared_ptr<ScriptEngine>;using ScriptValueList = QList<ScriptValue>;using ScriptValueIteratorPointer = std::shared_ptr<ScriptValueIterator>; /// [ScriptInterface] Provides an engine-independent interface for QScriptValueclass ScriptValue {public:    enum ResolveFlag    {        ResolveLocal = 0,        ResolvePrototype = 1,    };    using ResolveFlags = QFlags<ResolveFlag>;     enum PropertyFlag    {        ReadOnly = 0x00000001,        Undeletable = 0x00000002,        SkipInEnumeration = 0x00000004,        PropertyGetter = 0x00000008,        PropertySetter = 0x00000010,        QObjectMember = 0x00000020,        KeepExistingFlags = 0x00000800,    };    Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag);  public:    ScriptValue();    inline ScriptValue(const ScriptValue& src);    inline ~ScriptValue();    inline ScriptValue(ScriptValueProxy* proxy) : _proxy(proxy) {}    inline ScriptValueProxy* ptr() const { return _proxy; }    inline ScriptValue& operator=(const ScriptValue& other); public:    inline ScriptValue call(const ScriptValue& thisObject = ScriptValue(),                                    const ScriptValueList& args = ScriptValueList()) const;    inline ScriptValue call(const ScriptValue& thisObject, const ScriptValue& arguments) const;    inline ScriptValue construct(const ScriptValueList& args = ScriptValueList()) const;    inline ScriptValue construct(const ScriptValue& arguments) const;    inline ScriptValue data() const;    inline ScriptEnginePointer engine() const;    inline bool equals(const ScriptValue& other) const;    inline bool isArray() const;    inline bool isBool() const;    inline bool isError() const;    inline bool isFunction() const;    inline bool isNumber() const;    inline bool isNull() const;    inline bool isObject() const;    inline bool isString() const;    inline bool isUndefined() const;    inline bool isValid() const;    inline bool isVariant() const;    inline ScriptValueIteratorPointer newIterator() const;    inline ScriptValue property(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;    inline ScriptValue property(quint32 arrayIndex, const ResolveFlags& mode = ResolvePrototype) const;    inline ScriptValue prototype() const;    inline void setData(const ScriptValue& val);    inline bool hasProperty(const QString &name) const;    inline void setProperty(const QString& name,                             const ScriptValue& value,                             const PropertyFlags& flags = KeepExistingFlags);    inline void setProperty(quint32 arrayIndex,                             const ScriptValue& value,                             const PropertyFlags& flags = KeepExistingFlags);    template <typename TYP, class ScriptEnginePointer = ScriptEnginePointer>    inline void setProperty(const QString& name, const TYP& value,                             const PropertyFlags& flags = KeepExistingFlags);    template <typename TYP, class ScriptEnginePointer = ScriptEnginePointer>    inline void setProperty(quint32 arrayIndex, const TYP& value,                             const PropertyFlags& flags = KeepExistingFlags);    inline void setPrototype(const ScriptValue& prototype);    inline bool strictlyEquals(const ScriptValue& other) const;    inline QList<QString> getPropertyNames() const;     inline bool toBool() const;    inline qint32 toInt32() const;    inline double toInteger() const;    inline double toNumber() const;    inline QString toString() const;    inline quint16 toUInt16() const;    inline quint32 toUInt32() const;    inline QVariant toVariant() const;    inline QObject* toQObject() const;     // Human-readable string representation of a value,    // string objects are returned literally    inline QString repr() const; protected:    ScriptValueProxy* _proxy;};Q_DECLARE_OPERATORS_FOR_FLAGS(ScriptValue::PropertyFlags); /// [ScriptInterface] Provides an engine-independent interface for QScriptValueclass ScriptValueProxy {public:    virtual void enqueueRelease() = 0;    virtual void release() = 0;    virtual ScriptValueProxy* copy() const = 0; public:    virtual ScriptValue call(const ScriptValue& thisObject = ScriptValue(),                             const ScriptValueList& args = ScriptValueList()) = 0;    virtual ScriptValue call(const ScriptValue& thisObject, const ScriptValue& arguments) = 0;    virtual ScriptValue construct(const ScriptValueList& args = ScriptValueList()) = 0;    virtual ScriptValue construct(const ScriptValue& arguments) = 0;    virtual ScriptValue data() const = 0;    virtual ScriptEnginePointer engine() const = 0;    virtual bool equals(const ScriptValue& other) const = 0;    virtual bool isArray() const = 0;    virtual bool isBool() const = 0;    virtual bool isError() const = 0;    virtual bool isFunction() const = 0;    virtual bool isNumber() const = 0;    virtual bool isNull() const = 0;    virtual bool isObject() const = 0;    virtual bool isString() const = 0;    virtual bool isUndefined() const = 0;    virtual bool isValid() const = 0;    virtual bool isVariant() const = 0;    virtual ScriptValueIteratorPointer newIterator() const = 0;    virtual ScriptValue property(const QString& name,                                 const ScriptValue::ResolveFlags& mode = ScriptValue::ResolvePrototype) const = 0;    virtual ScriptValue property(quint32 arrayIndex,                                 const ScriptValue::ResolveFlags& mode = ScriptValue::ResolvePrototype) const = 0;    virtual ScriptValue prototype() const = 0;    virtual void setData(const ScriptValue& val) = 0;    virtual bool hasProperty(const QString &name) const = 0;    virtual void setProperty(const QString& name,                             const ScriptValue& value,                             const ScriptValue::PropertyFlags& flags = ScriptValue::KeepExistingFlags) = 0;    virtual void setProperty(quint32 arrayIndex,                             const ScriptValue& value,                             const ScriptValue::PropertyFlags& flags = ScriptValue::KeepExistingFlags) = 0;    virtual void setPrototype(const ScriptValue& prototype) = 0;    virtual bool strictlyEquals(const ScriptValue& other) const = 0;    virtual QList<QString> getPropertyNames() const = 0;     virtual bool toBool() const = 0;    virtual qint32 toInt32() const = 0;    virtual double toInteger() const = 0;    virtual double toNumber() const = 0;    virtual QString toString() const = 0;    virtual quint16 toUInt16() const = 0;    virtual quint32 toUInt32() const = 0;    virtual QVariant toVariant() const = 0;    virtual QObject* toQObject() const = 0;     virtual QString repr() const = 0; protected:    virtual ~ScriptValueProxy() {}  // prevent explicit deletion of base class}; // the second template parameter is used to defer evaluation of calls to the engine until ScriptEngine isn't forward-declaredtemplate <typename TYP, class ScriptEnginePointer>void ScriptValue::setProperty(const QString& name, const TYP& value, const PropertyFlags& flags) {    setProperty(name, static_cast<const ScriptEnginePointer&>(engine())->newValue(value), flags);} // the second template parameter is used to defer evaluation of calls to the engine until ScriptEngine isn't forward-declaredtemplate <typename TYP, class ScriptEnginePointer>void ScriptValue::setProperty(quint32 arrayIndex, const TYP& value, const PropertyFlags& flags) {    setProperty(arrayIndex, static_cast<const ScriptEnginePointer&>(engine())->newValue(value), flags);} ScriptValue::ScriptValue(const ScriptValue& src) : _proxy(src.ptr()->copy()) {    Q_ASSERT(_proxy != nullptr);} ScriptValue::~ScriptValue() {    Q_ASSERT(_proxy != nullptr);    _proxy->enqueueRelease();} ScriptValue& ScriptValue::operator=(const ScriptValue& other) {    Q_ASSERT(_proxy != nullptr);    _proxy->enqueueRelease();    _proxy = other.ptr()->copy();    return *this;} ScriptValue ScriptValue::call(const ScriptValue& thisObject, const ScriptValueList& args) const {    Q_ASSERT(_proxy != nullptr);    ScriptEnginePointer scriptEngine = _proxy->engine();    if (scriptEngine == nullptr) {        qCDebug(scriptengine) << "Call to deleted or non-existing script engine";        return ScriptValue();    }    return _proxy->call(thisObject, args);} ScriptValue ScriptValue::call(const ScriptValue& thisObject, const ScriptValue& arguments) const {    Q_ASSERT(_proxy != nullptr);    return _proxy->call(thisObject, arguments);} ScriptValue ScriptValue::construct(const ScriptValueList& args) const {    Q_ASSERT(_proxy != nullptr);    return _proxy->construct(args);} ScriptValue ScriptValue::construct(const ScriptValue& arguments) const {    Q_ASSERT(_proxy != nullptr);    return _proxy->construct(arguments);} ScriptValue ScriptValue::data() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->data();} ScriptEnginePointer ScriptValue::engine() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->engine();} bool ScriptValue::equals(const ScriptValue& other) const {    Q_ASSERT(_proxy != nullptr);    return _proxy->equals(other);} bool ScriptValue::isArray() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isArray();} bool ScriptValue::isBool() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isBool();} bool ScriptValue::isError() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isError();} bool ScriptValue::isFunction() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isFunction();} bool ScriptValue::isNumber() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isNumber();} bool ScriptValue::isNull() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isNull();} bool ScriptValue::isObject() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isObject();} bool ScriptValue::isString() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isString();} bool ScriptValue::isUndefined() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isUndefined();} bool ScriptValue::isValid() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isValid();} bool ScriptValue::isVariant() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->isVariant();} ScriptValueIteratorPointer ScriptValue::newIterator() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->newIterator();} ScriptValue ScriptValue::property(const QString& name, const ResolveFlags& mode) const {    Q_ASSERT(_proxy != nullptr);    return _proxy->property(name, mode);} ScriptValue ScriptValue::property(quint32 arrayIndex, const ResolveFlags& mode) const {    Q_ASSERT(_proxy != nullptr);    return _proxy->property(arrayIndex, mode);} ScriptValue ScriptValue::prototype() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->prototype();} void ScriptValue::setData(const ScriptValue& val) {    Q_ASSERT(_proxy != nullptr);    return _proxy->setData(val);}  bool ScriptValue::hasProperty(const QString& name) const {    Q_ASSERT(_proxy != nullptr);    return _proxy->hasProperty(name);} void ScriptValue::setProperty(const QString& name, const ScriptValue& value, const PropertyFlags& flags) {    Q_ASSERT(_proxy != nullptr);    return _proxy->setProperty(name, value, flags);} void ScriptValue::setProperty(quint32 arrayIndex, const ScriptValue& value, const PropertyFlags& flags) {    Q_ASSERT(_proxy != nullptr);    return _proxy->setProperty(arrayIndex, value, flags);} void ScriptValue::setPrototype(const ScriptValue& prototype) {    Q_ASSERT(_proxy != nullptr);    return _proxy->setPrototype(prototype);} bool ScriptValue::strictlyEquals(const ScriptValue& other) const {    Q_ASSERT(_proxy != nullptr);    return _proxy->strictlyEquals(other);} inline QList<QString> ScriptValue::getPropertyNames() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->getPropertyNames();}; bool ScriptValue::toBool() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toBool();} qint32 ScriptValue::toInt32() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toInt32();} double ScriptValue::toInteger() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toInteger();} double ScriptValue::toNumber() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toNumber();} QString ScriptValue::toString() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toString();} quint16 ScriptValue::toUInt16() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toUInt16();} quint32 ScriptValue::toUInt32() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toUInt32();} QVariant ScriptValue::toVariant() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toVariant();} QObject* ScriptValue::toQObject() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->toQObject();} QString ScriptValue::repr() const {    Q_ASSERT(_proxy != nullptr);    return _proxy->repr();} #endif // hifi_ScriptValue_h /// @}