// // 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 #include #include #include #include #include #include #include "ScriptEngineLogging.h" class ScriptEngine; class ScriptValue; class ScriptValueIterator; class ScriptValueProxy; using ScriptEnginePointer = std::shared_ptr; using ScriptValueList = QList; using ScriptValueIteratorPointer = std::shared_ptr; /// [ScriptInterface] Provides an engine-independent interface for QScriptValue class ScriptValue { public: enum ResolveFlag { ResolveLocal = 0, ResolvePrototype = 1, }; using ResolveFlags = QFlags; 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 inline void setProperty(const QString& name, const TYP& value, const PropertyFlags& flags = KeepExistingFlags); template 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 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; protected: ScriptValueProxy* _proxy; }; Q_DECLARE_OPERATORS_FOR_FLAGS(ScriptValue::PropertyFlags); /// [ScriptInterface] Provides an engine-independent interface for QScriptValue class ScriptValueProxy { public: 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 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; 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-declared template void ScriptValue::setProperty(const QString& name, const TYP& value, const PropertyFlags& flags) { setProperty(name, static_cast(engine())->newValue(value), flags); } // the second template parameter is used to defer evaluation of calls to the engine until ScriptEngine isn't forward-declared template void ScriptValue::setProperty(quint32 arrayIndex, const TYP& value, const PropertyFlags& flags) { setProperty(arrayIndex, static_cast(engine())->newValue(value), flags); } ScriptValue::ScriptValue(const ScriptValue& src) : _proxy(src.ptr()->copy()) { Q_ASSERT(_proxy != nullptr); } ScriptValue::~ScriptValue() { Q_ASSERT(_proxy != nullptr); _proxy->release(); } ScriptValue& ScriptValue::operator=(const ScriptValue& other) { Q_ASSERT(_proxy != nullptr); _proxy->release(); _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 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(); } #endif // hifi_ScriptValue_h /// @}