Overte C++ Documentation
ScriptValue.h
1 //
2 // ScriptValue.h
3 // libraries/script-engine/src
4 //
5 // Created by Heather Anderson on 4/25/21.
6 // Copyright 2021 Vircadia contributors.
7 // Copyright 2022-2023 Overte e.V.
8 //
9 // Distributed under the Apache License, Version 2.0.
10 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11 // SPDX-License-Identifier: Apache-2.0
12 //
13 
16 
17 #ifndef hifi_ScriptValue_h
18 #define hifi_ScriptValue_h
19 
20 #include <memory>
21 
22 #include <QtCore/QObject>
23 #include <QtCore/QFlags>
24 #include <QtCore/QList>
25 #include <QtCore/QString>
26 #include <QtCore/QVariant>
27 #include <QtCore/QDebug>
28 
29 #include "ScriptEngineLogging.h"
30 
31 class ScriptEngine;
32 class ScriptValue;
34 class ScriptValueProxy;
35 using ScriptEnginePointer = std::shared_ptr<ScriptEngine>;
36 using ScriptValueList = QList<ScriptValue>;
37 using ScriptValueIteratorPointer = std::shared_ptr<ScriptValueIterator>;
38 
40 class ScriptValue {
41 public:
42  enum ResolveFlag
43  {
44  ResolveLocal = 0,
45  ResolvePrototype = 1,
46  };
47  using ResolveFlags = QFlags<ResolveFlag>;
48 
49  enum PropertyFlag
50  {
51  ReadOnly = 0x00000001,
52  Undeletable = 0x00000002,
53  SkipInEnumeration = 0x00000004,
54  PropertyGetter = 0x00000008,
55  PropertySetter = 0x00000010,
56  QObjectMember = 0x00000020,
57  KeepExistingFlags = 0x00000800,
58  };
59  Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag);
60 
61 
62 public:
63  ScriptValue();
64  inline ScriptValue(const ScriptValue& src);
65  inline ~ScriptValue();
66  inline ScriptValue(ScriptValueProxy* proxy) : _proxy(proxy) {}
67  inline ScriptValueProxy* ptr() const { return _proxy; }
68  inline ScriptValue& operator=(const ScriptValue& other);
69 
70 public:
71  inline ScriptValue call(const ScriptValue& thisObject = ScriptValue(),
72  const ScriptValueList& args = ScriptValueList()) const;
73  inline ScriptValue call(const ScriptValue& thisObject, const ScriptValue& arguments) const;
74  inline ScriptValue construct(const ScriptValueList& args = ScriptValueList()) const;
75  inline ScriptValue construct(const ScriptValue& arguments) const;
76  inline ScriptValue data() const;
77  inline ScriptEnginePointer engine() const;
78  inline bool equals(const ScriptValue& other) const;
79  inline bool isArray() const;
80  inline bool isBool() const;
81  inline bool isError() const;
82  inline bool isFunction() const;
83  inline bool isNumber() const;
84  inline bool isNull() const;
85  inline bool isObject() const;
86  inline bool isString() const;
87  inline bool isUndefined() const;
88  inline bool isValid() const;
89  inline bool isVariant() const;
90  inline ScriptValueIteratorPointer newIterator() const;
91  inline ScriptValue property(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
92  inline ScriptValue property(quint32 arrayIndex, const ResolveFlags& mode = ResolvePrototype) const;
93  inline ScriptValue prototype() const;
94  inline void setData(const ScriptValue& val);
95  inline bool hasProperty(const QString &name) const;
96  inline void setProperty(const QString& name,
97  const ScriptValue& value,
98  const PropertyFlags& flags = KeepExistingFlags);
99  inline void setProperty(quint32 arrayIndex,
100  const ScriptValue& value,
101  const PropertyFlags& flags = KeepExistingFlags);
102  template <typename TYP, class ScriptEnginePointer = ScriptEnginePointer>
103  inline void setProperty(const QString& name, const TYP& value,
104  const PropertyFlags& flags = KeepExistingFlags);
105  template <typename TYP, class ScriptEnginePointer = ScriptEnginePointer>
106  inline void setProperty(quint32 arrayIndex, const TYP& value,
107  const PropertyFlags& flags = KeepExistingFlags);
108  inline void setPrototype(const ScriptValue& prototype);
109  inline bool strictlyEquals(const ScriptValue& other) const;
110  inline QList<QString> getPropertyNames() const;
111 
112  inline bool toBool() const;
113  inline qint32 toInt32() const;
114  inline double toInteger() const;
115  inline double toNumber() const;
116  inline QString toString() const;
117  inline quint16 toUInt16() const;
118  inline quint32 toUInt32() const;
119  inline QVariant toVariant() const;
120  inline QObject* toQObject() const;
121 
122 protected:
123  ScriptValueProxy* _proxy;
124 };
125 Q_DECLARE_OPERATORS_FOR_FLAGS(ScriptValue::PropertyFlags);
126 
129 public:
130  virtual void release() = 0;
131  virtual ScriptValueProxy* copy() const = 0;
132 
133 public:
134  virtual ScriptValue call(const ScriptValue& thisObject = ScriptValue(),
135  const ScriptValueList& args = ScriptValueList()) = 0;
136  virtual ScriptValue call(const ScriptValue& thisObject, const ScriptValue& arguments) = 0;
137  virtual ScriptValue construct(const ScriptValueList& args = ScriptValueList()) = 0;
138  virtual ScriptValue construct(const ScriptValue& arguments) = 0;
139  virtual ScriptValue data() const = 0;
140  virtual ScriptEnginePointer engine() const = 0;
141  virtual bool equals(const ScriptValue& other) const = 0;
142  virtual bool isArray() const = 0;
143  virtual bool isBool() const = 0;
144  virtual bool isError() const = 0;
145  virtual bool isFunction() const = 0;
146  virtual bool isNumber() const = 0;
147  virtual bool isNull() const = 0;
148  virtual bool isObject() const = 0;
149  virtual bool isString() const = 0;
150  virtual bool isUndefined() const = 0;
151  virtual bool isValid() const = 0;
152  virtual bool isVariant() const = 0;
153  virtual ScriptValueIteratorPointer newIterator() const = 0;
154  virtual ScriptValue property(const QString& name,
155  const ScriptValue::ResolveFlags& mode = ScriptValue::ResolvePrototype) const = 0;
156  virtual ScriptValue property(quint32 arrayIndex,
157  const ScriptValue::ResolveFlags& mode = ScriptValue::ResolvePrototype) const = 0;
158  virtual ScriptValue prototype() const = 0;
159  virtual void setData(const ScriptValue& val) = 0;
160  virtual bool hasProperty(const QString &name) const = 0;
161  virtual void setProperty(const QString& name,
162  const ScriptValue& value,
163  const ScriptValue::PropertyFlags& flags = ScriptValue::KeepExistingFlags) = 0;
164  virtual void setProperty(quint32 arrayIndex,
165  const ScriptValue& value,
166  const ScriptValue::PropertyFlags& flags = ScriptValue::KeepExistingFlags) = 0;
167  virtual void setPrototype(const ScriptValue& prototype) = 0;
168  virtual bool strictlyEquals(const ScriptValue& other) const = 0;
169  virtual QList<QString> getPropertyNames() const = 0;
170 
171  virtual bool toBool() const = 0;
172  virtual qint32 toInt32() const = 0;
173  virtual double toInteger() const = 0;
174  virtual double toNumber() const = 0;
175  virtual QString toString() const = 0;
176  virtual quint16 toUInt16() const = 0;
177  virtual quint32 toUInt32() const = 0;
178  virtual QVariant toVariant() const = 0;
179  virtual QObject* toQObject() const = 0;
180 
181 protected:
182  virtual ~ScriptValueProxy() {} // prevent explicit deletion of base class
183 };
184 
185 // the second template parameter is used to defer evaluation of calls to the engine until ScriptEngine isn't forward-declared
186 template <typename TYP, class ScriptEnginePointer>
187 void ScriptValue::setProperty(const QString& name, const TYP& value, const PropertyFlags& flags) {
188  setProperty(name, static_cast<const ScriptEnginePointer&>(engine())->newValue(value), flags);
189 }
190 
191 // the second template parameter is used to defer evaluation of calls to the engine until ScriptEngine isn't forward-declared
192 template <typename TYP, class ScriptEnginePointer>
193 void ScriptValue::setProperty(quint32 arrayIndex, const TYP& value, const PropertyFlags& flags) {
194  setProperty(arrayIndex, static_cast<const ScriptEnginePointer&>(engine())->newValue(value), flags);
195 }
196 
197 ScriptValue::ScriptValue(const ScriptValue& src) : _proxy(src.ptr()->copy()) {
198  Q_ASSERT(_proxy != nullptr);
199 }
200 
201 ScriptValue::~ScriptValue() {
202  Q_ASSERT(_proxy != nullptr);
203  _proxy->release();
204 }
205 
206 ScriptValue& ScriptValue::operator=(const ScriptValue& other) {
207  Q_ASSERT(_proxy != nullptr);
208  _proxy->release();
209  _proxy = other.ptr()->copy();
210  return *this;
211 }
212 
213 ScriptValue ScriptValue::call(const ScriptValue& thisObject, const ScriptValueList& args) const {
214  Q_ASSERT(_proxy != nullptr);
215  ScriptEnginePointer scriptEngine = _proxy->engine();
216  if (scriptEngine == nullptr) {
217  qCDebug(scriptengine) << "Call to deleted or non-existing script engine";
218  return ScriptValue();
219  }
220  return _proxy->call(thisObject, args);
221 }
222 
223 ScriptValue ScriptValue::call(const ScriptValue& thisObject, const ScriptValue& arguments) const {
224  Q_ASSERT(_proxy != nullptr);
225  return _proxy->call(thisObject, arguments);
226 }
227 
228 ScriptValue ScriptValue::construct(const ScriptValueList& args) const {
229  Q_ASSERT(_proxy != nullptr);
230  return _proxy->construct(args);
231 }
232 
233 ScriptValue ScriptValue::construct(const ScriptValue& arguments) const {
234  Q_ASSERT(_proxy != nullptr);
235  return _proxy->construct(arguments);
236 }
237 
238 ScriptValue ScriptValue::data() const {
239  Q_ASSERT(_proxy != nullptr);
240  return _proxy->data();
241 }
242 
243 ScriptEnginePointer ScriptValue::engine() const {
244  Q_ASSERT(_proxy != nullptr);
245  return _proxy->engine();
246 }
247 
248 bool ScriptValue::equals(const ScriptValue& other) const {
249  Q_ASSERT(_proxy != nullptr);
250  return _proxy->equals(other);
251 }
252 
253 bool ScriptValue::isArray() const {
254  Q_ASSERT(_proxy != nullptr);
255  return _proxy->isArray();
256 }
257 
258 bool ScriptValue::isBool() const {
259  Q_ASSERT(_proxy != nullptr);
260  return _proxy->isBool();
261 }
262 
263 bool ScriptValue::isError() const {
264  Q_ASSERT(_proxy != nullptr);
265  return _proxy->isError();
266 }
267 
268 bool ScriptValue::isFunction() const {
269  Q_ASSERT(_proxy != nullptr);
270  return _proxy->isFunction();
271 }
272 
273 bool ScriptValue::isNumber() const {
274  Q_ASSERT(_proxy != nullptr);
275  return _proxy->isNumber();
276 }
277 
278 bool ScriptValue::isNull() const {
279  Q_ASSERT(_proxy != nullptr);
280  return _proxy->isNull();
281 }
282 
283 bool ScriptValue::isObject() const {
284  Q_ASSERT(_proxy != nullptr);
285  return _proxy->isObject();
286 }
287 
288 bool ScriptValue::isString() const {
289  Q_ASSERT(_proxy != nullptr);
290  return _proxy->isString();
291 }
292 
293 bool ScriptValue::isUndefined() const {
294  Q_ASSERT(_proxy != nullptr);
295  return _proxy->isUndefined();
296 }
297 
298 bool ScriptValue::isValid() const {
299  Q_ASSERT(_proxy != nullptr);
300  return _proxy->isValid();
301 }
302 
303 bool ScriptValue::isVariant() const {
304  Q_ASSERT(_proxy != nullptr);
305  return _proxy->isVariant();
306 }
307 
308 ScriptValueIteratorPointer ScriptValue::newIterator() const {
309  Q_ASSERT(_proxy != nullptr);
310  return _proxy->newIterator();
311 }
312 
313 ScriptValue ScriptValue::property(const QString& name, const ResolveFlags& mode) const {
314  Q_ASSERT(_proxy != nullptr);
315  return _proxy->property(name, mode);
316 }
317 
318 ScriptValue ScriptValue::property(quint32 arrayIndex, const ResolveFlags& mode) const {
319  Q_ASSERT(_proxy != nullptr);
320  return _proxy->property(arrayIndex, mode);
321 }
322 
323 ScriptValue ScriptValue::prototype() const {
324  Q_ASSERT(_proxy != nullptr);
325  return _proxy->prototype();
326 }
327 
328 void ScriptValue::setData(const ScriptValue& val) {
329  Q_ASSERT(_proxy != nullptr);
330  return _proxy->setData(val);
331 }
332 
333 
334 bool ScriptValue::hasProperty(const QString& name) const {
335  Q_ASSERT(_proxy != nullptr);
336  return _proxy->hasProperty(name);
337 }
338 
339 void ScriptValue::setProperty(const QString& name, const ScriptValue& value, const PropertyFlags& flags) {
340  Q_ASSERT(_proxy != nullptr);
341  return _proxy->setProperty(name, value, flags);
342 }
343 
344 void ScriptValue::setProperty(quint32 arrayIndex, const ScriptValue& value, const PropertyFlags& flags) {
345  Q_ASSERT(_proxy != nullptr);
346  return _proxy->setProperty(arrayIndex, value, flags);
347 }
348 
349 void ScriptValue::setPrototype(const ScriptValue& prototype) {
350  Q_ASSERT(_proxy != nullptr);
351  return _proxy->setPrototype(prototype);
352 }
353 
354 bool ScriptValue::strictlyEquals(const ScriptValue& other) const {
355  Q_ASSERT(_proxy != nullptr);
356  return _proxy->strictlyEquals(other);
357 }
358 
359 inline QList<QString> ScriptValue::getPropertyNames() const {
360  Q_ASSERT(_proxy != nullptr);
361  return _proxy->getPropertyNames();
362 };
363 
364 bool ScriptValue::toBool() const {
365  Q_ASSERT(_proxy != nullptr);
366  return _proxy->toBool();
367 }
368 
369 qint32 ScriptValue::toInt32() const {
370  Q_ASSERT(_proxy != nullptr);
371  return _proxy->toInt32();
372 }
373 
374 double ScriptValue::toInteger() const {
375  Q_ASSERT(_proxy != nullptr);
376  return _proxy->toInteger();
377 }
378 
379 double ScriptValue::toNumber() const {
380  Q_ASSERT(_proxy != nullptr);
381  return _proxy->toNumber();
382 }
383 
384 QString ScriptValue::toString() const {
385  Q_ASSERT(_proxy != nullptr);
386  return _proxy->toString();
387 }
388 
389 quint16 ScriptValue::toUInt16() const {
390  Q_ASSERT(_proxy != nullptr);
391  return _proxy->toUInt16();
392 }
393 
394 quint32 ScriptValue::toUInt32() const {
395  Q_ASSERT(_proxy != nullptr);
396  return _proxy->toUInt32();
397 }
398 
399 QVariant ScriptValue::toVariant() const {
400  Q_ASSERT(_proxy != nullptr);
401  return _proxy->toVariant();
402 }
403 
404 QObject* ScriptValue::toQObject() const {
405  Q_ASSERT(_proxy != nullptr);
406  return _proxy->toQObject();
407 }
408 
409 #endif // hifi_ScriptValue_h
410 
Provides an engine-independent interface for a scripting engine.
Definition: ScriptEngine.h:93
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40
[ScriptInterface] Provides an engine-independent interface for QScriptValueIterator
Definition: ScriptValueIterator.h:30
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:128