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  // Human-readable string representation of a value,
123  // string objects are returned literally
124  inline QString repr() const;
125 
126 protected:
127  ScriptValueProxy* _proxy;
128 };
129 Q_DECLARE_OPERATORS_FOR_FLAGS(ScriptValue::PropertyFlags);
130 
133 public:
134  virtual void enqueueRelease() = 0;
135  virtual void release() = 0;
136  virtual ScriptValueProxy* copy() const = 0;
137 
138 public:
139  virtual ScriptValue call(const ScriptValue& thisObject = ScriptValue(),
140  const ScriptValueList& args = ScriptValueList()) = 0;
141  virtual ScriptValue call(const ScriptValue& thisObject, const ScriptValue& arguments) = 0;
142  virtual ScriptValue construct(const ScriptValueList& args = ScriptValueList()) = 0;
143  virtual ScriptValue construct(const ScriptValue& arguments) = 0;
144  virtual ScriptValue data() const = 0;
145  virtual ScriptEnginePointer engine() const = 0;
146  virtual bool equals(const ScriptValue& other) const = 0;
147  virtual bool isArray() const = 0;
148  virtual bool isBool() const = 0;
149  virtual bool isError() const = 0;
150  virtual bool isFunction() const = 0;
151  virtual bool isNumber() const = 0;
152  virtual bool isNull() const = 0;
153  virtual bool isObject() const = 0;
154  virtual bool isString() const = 0;
155  virtual bool isUndefined() const = 0;
156  virtual bool isValid() const = 0;
157  virtual bool isVariant() const = 0;
158  virtual ScriptValueIteratorPointer newIterator() const = 0;
159  virtual ScriptValue property(const QString& name,
160  const ScriptValue::ResolveFlags& mode = ScriptValue::ResolvePrototype) const = 0;
161  virtual ScriptValue property(quint32 arrayIndex,
162  const ScriptValue::ResolveFlags& mode = ScriptValue::ResolvePrototype) const = 0;
163  virtual ScriptValue prototype() const = 0;
164  virtual void setData(const ScriptValue& val) = 0;
165  virtual bool hasProperty(const QString &name) const = 0;
166  virtual void setProperty(const QString& name,
167  const ScriptValue& value,
168  const ScriptValue::PropertyFlags& flags = ScriptValue::KeepExistingFlags) = 0;
169  virtual void setProperty(quint32 arrayIndex,
170  const ScriptValue& value,
171  const ScriptValue::PropertyFlags& flags = ScriptValue::KeepExistingFlags) = 0;
172  virtual void setPrototype(const ScriptValue& prototype) = 0;
173  virtual bool strictlyEquals(const ScriptValue& other) const = 0;
174  virtual QList<QString> getPropertyNames() const = 0;
175 
176  virtual bool toBool() const = 0;
177  virtual qint32 toInt32() const = 0;
178  virtual double toInteger() const = 0;
179  virtual double toNumber() const = 0;
180  virtual QString toString() const = 0;
181  virtual quint16 toUInt16() const = 0;
182  virtual quint32 toUInt32() const = 0;
183  virtual QVariant toVariant() const = 0;
184  virtual QObject* toQObject() const = 0;
185 
186  virtual QString repr() const = 0;
187 
188 protected:
189  virtual ~ScriptValueProxy() {} // prevent explicit deletion of base class
190 };
191 
192 // the second template parameter is used to defer evaluation of calls to the engine until ScriptEngine isn't forward-declared
193 template <typename TYP, class ScriptEnginePointer>
194 void ScriptValue::setProperty(const QString& name, const TYP& value, const PropertyFlags& flags) {
195  setProperty(name, static_cast<const ScriptEnginePointer&>(engine())->newValue(value), flags);
196 }
197 
198 // the second template parameter is used to defer evaluation of calls to the engine until ScriptEngine isn't forward-declared
199 template <typename TYP, class ScriptEnginePointer>
200 void ScriptValue::setProperty(quint32 arrayIndex, const TYP& value, const PropertyFlags& flags) {
201  setProperty(arrayIndex, static_cast<const ScriptEnginePointer&>(engine())->newValue(value), flags);
202 }
203 
204 ScriptValue::ScriptValue(const ScriptValue& src) : _proxy(src.ptr()->copy()) {
205  Q_ASSERT(_proxy != nullptr);
206 }
207 
208 ScriptValue::~ScriptValue() {
209  Q_ASSERT(_proxy != nullptr);
210  _proxy->enqueueRelease();
211 }
212 
213 ScriptValue& ScriptValue::operator=(const ScriptValue& other) {
214  Q_ASSERT(_proxy != nullptr);
215  _proxy->enqueueRelease();
216  _proxy = other.ptr()->copy();
217  return *this;
218 }
219 
220 ScriptValue ScriptValue::call(const ScriptValue& thisObject, const ScriptValueList& args) const {
221  Q_ASSERT(_proxy != nullptr);
222  ScriptEnginePointer scriptEngine = _proxy->engine();
223  if (scriptEngine == nullptr) {
224  qCDebug(scriptengine) << "Call to deleted or non-existing script engine";
225  return ScriptValue();
226  }
227  return _proxy->call(thisObject, args);
228 }
229 
230 ScriptValue ScriptValue::call(const ScriptValue& thisObject, const ScriptValue& arguments) const {
231  Q_ASSERT(_proxy != nullptr);
232  return _proxy->call(thisObject, arguments);
233 }
234 
235 ScriptValue ScriptValue::construct(const ScriptValueList& args) const {
236  Q_ASSERT(_proxy != nullptr);
237  return _proxy->construct(args);
238 }
239 
240 ScriptValue ScriptValue::construct(const ScriptValue& arguments) const {
241  Q_ASSERT(_proxy != nullptr);
242  return _proxy->construct(arguments);
243 }
244 
245 ScriptValue ScriptValue::data() const {
246  Q_ASSERT(_proxy != nullptr);
247  return _proxy->data();
248 }
249 
250 ScriptEnginePointer ScriptValue::engine() const {
251  Q_ASSERT(_proxy != nullptr);
252  return _proxy->engine();
253 }
254 
255 bool ScriptValue::equals(const ScriptValue& other) const {
256  Q_ASSERT(_proxy != nullptr);
257  return _proxy->equals(other);
258 }
259 
260 bool ScriptValue::isArray() const {
261  Q_ASSERT(_proxy != nullptr);
262  return _proxy->isArray();
263 }
264 
265 bool ScriptValue::isBool() const {
266  Q_ASSERT(_proxy != nullptr);
267  return _proxy->isBool();
268 }
269 
270 bool ScriptValue::isError() const {
271  Q_ASSERT(_proxy != nullptr);
272  return _proxy->isError();
273 }
274 
275 bool ScriptValue::isFunction() const {
276  Q_ASSERT(_proxy != nullptr);
277  return _proxy->isFunction();
278 }
279 
280 bool ScriptValue::isNumber() const {
281  Q_ASSERT(_proxy != nullptr);
282  return _proxy->isNumber();
283 }
284 
285 bool ScriptValue::isNull() const {
286  Q_ASSERT(_proxy != nullptr);
287  return _proxy->isNull();
288 }
289 
290 bool ScriptValue::isObject() const {
291  Q_ASSERT(_proxy != nullptr);
292  return _proxy->isObject();
293 }
294 
295 bool ScriptValue::isString() const {
296  Q_ASSERT(_proxy != nullptr);
297  return _proxy->isString();
298 }
299 
300 bool ScriptValue::isUndefined() const {
301  Q_ASSERT(_proxy != nullptr);
302  return _proxy->isUndefined();
303 }
304 
305 bool ScriptValue::isValid() const {
306  Q_ASSERT(_proxy != nullptr);
307  return _proxy->isValid();
308 }
309 
310 bool ScriptValue::isVariant() const {
311  Q_ASSERT(_proxy != nullptr);
312  return _proxy->isVariant();
313 }
314 
315 ScriptValueIteratorPointer ScriptValue::newIterator() const {
316  Q_ASSERT(_proxy != nullptr);
317  return _proxy->newIterator();
318 }
319 
320 ScriptValue ScriptValue::property(const QString& name, const ResolveFlags& mode) const {
321  Q_ASSERT(_proxy != nullptr);
322  return _proxy->property(name, mode);
323 }
324 
325 ScriptValue ScriptValue::property(quint32 arrayIndex, const ResolveFlags& mode) const {
326  Q_ASSERT(_proxy != nullptr);
327  return _proxy->property(arrayIndex, mode);
328 }
329 
330 ScriptValue ScriptValue::prototype() const {
331  Q_ASSERT(_proxy != nullptr);
332  return _proxy->prototype();
333 }
334 
335 void ScriptValue::setData(const ScriptValue& val) {
336  Q_ASSERT(_proxy != nullptr);
337  return _proxy->setData(val);
338 }
339 
340 
341 bool ScriptValue::hasProperty(const QString& name) const {
342  Q_ASSERT(_proxy != nullptr);
343  return _proxy->hasProperty(name);
344 }
345 
346 void ScriptValue::setProperty(const QString& name, const ScriptValue& value, const PropertyFlags& flags) {
347  Q_ASSERT(_proxy != nullptr);
348  return _proxy->setProperty(name, value, flags);
349 }
350 
351 void ScriptValue::setProperty(quint32 arrayIndex, const ScriptValue& value, const PropertyFlags& flags) {
352  Q_ASSERT(_proxy != nullptr);
353  return _proxy->setProperty(arrayIndex, value, flags);
354 }
355 
356 void ScriptValue::setPrototype(const ScriptValue& prototype) {
357  Q_ASSERT(_proxy != nullptr);
358  return _proxy->setPrototype(prototype);
359 }
360 
361 bool ScriptValue::strictlyEquals(const ScriptValue& other) const {
362  Q_ASSERT(_proxy != nullptr);
363  return _proxy->strictlyEquals(other);
364 }
365 
366 inline QList<QString> ScriptValue::getPropertyNames() const {
367  Q_ASSERT(_proxy != nullptr);
368  return _proxy->getPropertyNames();
369 };
370 
371 bool ScriptValue::toBool() const {
372  Q_ASSERT(_proxy != nullptr);
373  return _proxy->toBool();
374 }
375 
376 qint32 ScriptValue::toInt32() const {
377  Q_ASSERT(_proxy != nullptr);
378  return _proxy->toInt32();
379 }
380 
381 double ScriptValue::toInteger() const {
382  Q_ASSERT(_proxy != nullptr);
383  return _proxy->toInteger();
384 }
385 
386 double ScriptValue::toNumber() const {
387  Q_ASSERT(_proxy != nullptr);
388  return _proxy->toNumber();
389 }
390 
391 QString ScriptValue::toString() const {
392  Q_ASSERT(_proxy != nullptr);
393  return _proxy->toString();
394 }
395 
396 quint16 ScriptValue::toUInt16() const {
397  Q_ASSERT(_proxy != nullptr);
398  return _proxy->toUInt16();
399 }
400 
401 quint32 ScriptValue::toUInt32() const {
402  Q_ASSERT(_proxy != nullptr);
403  return _proxy->toUInt32();
404 }
405 
406 QVariant ScriptValue::toVariant() const {
407  Q_ASSERT(_proxy != nullptr);
408  return _proxy->toVariant();
409 }
410 
411 QObject* ScriptValue::toQObject() const {
412  Q_ASSERT(_proxy != nullptr);
413  return _proxy->toQObject();
414 }
415 
416 QString ScriptValue::repr() const {
417  Q_ASSERT(_proxy != nullptr);
418  return _proxy->repr();
419 }
420 
421 #endif // hifi_ScriptValue_h
422 
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:132