Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qjsvalue.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qjsvalue.h"
5
6#include <private/qjsvalue_p.h>
7#include <private/qqmlbuiltins_p.h>
8#include <private/qv4dateobject_p.h>
9#include <private/qv4errorobject_p.h>
10#include <private/qv4functionobject_p.h>
11#include <private/qv4jscall_p.h>
12#include <private/qv4mm_p.h>
13#include <private/qv4object_p.h>
14#include <private/qv4qmetaobjectwrapper_p.h>
15#include <private/qv4qobjectwrapper_p.h>
16#include <private/qv4regexpobject_p.h>
17#include <private/qv4runtime_p.h>
18#include <private/qv4urlobject_p.h>
19#include <private/qv4value_p.h>
20#include <private/qv4variantassociationobject_p.h>
21#include <private/qv4variantobject_p.h>
22
23#include <QtQml/qjsprimitivevalue.h>
24#include <QtQml/qjsmanagedvalue.h>
25
26#include <QtCore/qstring.h>
27#include <QtCore/qvarlengtharray.h>
28#include <QtCore/qdatetime.h>
29
30/*!
31 \since 5.0
32 \class QJSValue
33
34 \brief The QJSValue class acts as a container for Qt/JavaScript data types.
35
36 \ingroup qtjavascript
37 \inmodule QtQml
38
39 QJSValue supports the types defined in the \l{ECMA-262}
40 standard: The primitive types, which are Undefined, Null, Boolean,
41 Number, and String; and the Object and Array types. Additionally, built-in
42 support is provided for Qt/C++ types such as QVariant and QObject.
43
44 For the object-based types (including Date and RegExp), use the
45 newT() functions in QJSEngine (e.g. QJSEngine::newObject())
46 to create a QJSValue of the desired type. For the primitive types,
47 use one of the QJSValue constructor overloads. For other types, e.g.
48 registered gadget types such as QPoint, you can use QJSEngine::toScriptValue.
49
50 The methods named isT() (e.g. isBool(), isUndefined()) can be
51 used to test if a value is of a certain type. The methods named
52 toT() (e.g. toBool(), toString()) can be used to convert a
53 QJSValue to another type. You can also use the generic
54 qjsvalue_cast() function.
55
56 Object values have zero or more properties which are themselves
57 QJSValues. Use setProperty() to set a property of an object, and
58 call property() to retrieve the value of a property.
59
60 \snippet code/src_script_qjsvalue.cpp 0
61
62 If you want to iterate over the properties of a script object, use
63 the QJSValueIterator class.
64
65 Object values have an internal \c{prototype} property, which can be
66 accessed with prototype() and setPrototype().
67
68 Function objects (objects for which isCallable()) returns true) can
69 be invoked by calling call(). Constructor functions can be used to
70 construct new objects by calling callAsConstructor().
71
72 Use equals() or strictlyEquals() to compare a QJSValue to another.
73
74 Note that a QJSValue for which isObject() is true only carries a
75 reference to an actual object; copying the QJSValue will only
76 copy the object reference, not the object itself. If you want to
77 clone an object (i.e. copy an object's properties to another
78 object), you can do so with the help of a \c{for-in} statement in
79 script code, or QJSValueIterator in C++.
80
81 \sa QJSEngine, QJSValueIterator
82
83 \section1 Working With Arrays
84
85 To create an array using QJSValue, use \l QJSEngine::newArray():
86
87 \code
88 // Assumes that this class was declared in QML.
89 QJSValue jsArray = engine->newArray(3);
90 \endcode
91
92 To set individual elements in the array, use
93 the \l {QJSValue::}{setProperty(quint32 arrayIndex, const QJSValue &value)}
94 overload. For example, to fill the array above with integers:
95
96 \code
97 for (int i = 0; i < 3; ++i) {
98 jsArray.setProperty(i, QRandomGenerator::global().generate());
99 }
100 \endcode
101
102 To determine the length of the array, access the \c "length" property.
103 To access array elements, use the
104 \l {QJSValue::}{property(quint32 arrayIndex)} overload. The following code
105 reads the array we created above back into a list:
106
107 \code
108 QVector<int> integers;
109 const int length = jsArray.property("length").toInt();
110 for (int i = 0; i < length; ++i) {
111 integers.append(jsArray.property(i).toInt());
112 }
113 \endcode
114
115 \section2 Converting to JSON
116
117 It's possible to convert a QJSValue to a JSON type. For example,
118 to convert to an array, use \l QJSEngine::fromScriptValue():
119
120 \code
121 const QJsonValue jsonValue = engine.fromScriptValue<QJsonValue>(jsValue);
122 const QJsonArray jsonArray = jsonValue.toArray();
123 \endcode
124*/
125
126/*!
127 \enum QJSValue::SpecialValue
128
129 This enum is used to specify a single-valued type.
130
131 \value UndefinedValue An undefined value.
132
133 \value NullValue A null value.
134*/
135
136/*!
137 \typedef QJSValueList
138 \relates QJSValue
139
140 This is a typedef for a QList<QJSValue>.
141*/
142
143/*!
144 \enum QJSValue::ErrorType
145 \since 5.12
146
147 Use this enum for JavaScript language-specific types of Error objects.
148
149 They may be useful when emulating language features in C++ requires the use
150 of specialized exception types. In addition, they may help to more clearly
151 communicate certain typical conditions, instead of throwing a generic
152 JavaScript exception. For example, code that deals with networking and
153 resource locators may find it useful to propagate errors related to
154 malformed locators using the URIError type.
155
156 \omitvalue NoError
157 \value GenericError A generic Error object, but not of a specific sub-type.
158 \omitvalue EvalError
159 \value RangeError A value did not match the expected set or range.
160 \value ReferenceError A non-existing variable referenced.
161 \value SyntaxError An invalid token or sequence of tokens was encountered
162 that does not conform with the syntax of the language.
163 \value TypeError An operand or argument is incompatible with the type
164 expected.
165 \value URIError A URI handling function was used incorrectly or the URI
166 provided is malformed.
167*/
168
169/*!
170 \enum QJSValue::ObjectConversionBehavior
171
172 This enum is used to specify how JavaScript objects and symbols without an equivalent
173 native Qt type should be treated when converting to QVariant.
174
175 \value ConvertJSObjects A best-effort, possibly lossy, conversion is attempted.
176 Symbols are converted to QString.
177
178 \value RetainJSObjects The value is retained as QJSValue wrapped in QVariant.
179*/
180
181QT_BEGIN_NAMESPACE
182
183using namespace QV4;
184
185/*!
186 Constructs a new QJSValue with a boolean \a value.
187*/
188QJSValue::QJSValue(bool value) : d(QJSValuePrivate::encode(value))
189{
190}
191
192/*!
193 Constructs a new QJSValue with a number \a value.
194*/
195QJSValue::QJSValue(int value) : d(QJSValuePrivate::encode(value))
196{
197}
198
199/*!
200 Constructs a new QJSValue with a number \a value.
201*/
202QJSValue::QJSValue(uint value) : d(QJSValuePrivate::encode(value))
203{
204}
205
206/*!
207 Constructs a new QJSValue with a number \a value.
208*/
209QJSValue::QJSValue(double value) : d(QJSValuePrivate::encode(value))
210{
211}
212
213/*!
214 Constructs a new QJSValue with a string \a value.
215*/
216QJSValue::QJSValue(const QString &value) : d(QJSValuePrivate::encode(value))
217{
218}
219
220/*!
221 Constructs a new QJSValue with a special \a value.
222*/
223QJSValue::QJSValue(SpecialValue value)
224 : d(value == NullValue ? QJSValuePrivate::encodeNull() : QJSValuePrivate::encodeUndefined())
225{
226}
227
228/*!
229 Constructs a new QJSValue with a string \a value.
230*/
231QJSValue::QJSValue(const QLatin1String &value) : d(QJSValuePrivate::encode(value))
232{
233}
234
235/*!
236 Constructs a new QJSValue with a string \a value.
237*/
238#ifndef QT_NO_CAST_FROM_ASCII
239QJSValue::QJSValue(const char *value) : d(QJSValuePrivate::encode(QString::fromUtf8(value)))
240{
241}
242#endif
243
244/*!
245 Constructs a new QJSValue that is a copy of \a other.
246
247 Note that if \a other is an object (i.e., isObject() would return
248 true), then only a reference to the underlying object is copied into
249 the new script value (i.e., the object itself is not copied).
250*/
251QJSValue::QJSValue(const QJSValue &other) : d(other.d)
252{
253 switch (QJSValuePrivate::tag(d)) {
254 case QJSValuePrivate::Kind::Undefined:
255 case QJSValuePrivate::Kind::Null:
256 case QJSValuePrivate::Kind::IntValue:
257 case QJSValuePrivate::Kind::BoolValue:
258 return;
259 case QJSValuePrivate::Kind::DoublePtr:
260 d = QJSValuePrivate::encode(*QJSValuePrivate::doublePtr(d));
261 return;
262 case QJSValuePrivate::Kind::QV4ValuePtr:
263 d = QJSValuePrivate::encode(*QJSValuePrivate::qv4ValuePtr(d));
264 return;
265 case QJSValuePrivate::Kind::QStringPtr:
266 d = QJSValuePrivate::encode(*QJSValuePrivate::qStringPtr(d));
267 break;
268 }
269}
270
271/*!
272 \fn QJSValue::QJSValue(QJSValue && other)
273
274 Move constructor. Moves from \a other into this QJSValue object.
275*/
276
277/*!
278 \fn QJSValue &QJSValue::operator=(QJSValue && other)
279
280 Move-assigns \a other to this QJSValue object.
281*/
282
283/*!
284 Destroys this QJSValue.
285*/
286QJSValue::~QJSValue()
287{
288 QJSValuePrivate::free(this);
289}
290
291/*!
292 Returns true if this QJSValue is of the primitive type Boolean;
293 otherwise returns false.
294
295 \sa toBool()
296*/
297bool QJSValue::isBool() const
298{
299 return QJSValuePrivate::tag(d) == QJSValuePrivate::Kind::BoolValue;
300}
301
302/*!
303 Returns true if this QJSValue is of the primitive type Number;
304 otherwise returns false.
305
306 \sa toNumber()
307*/
308bool QJSValue::isNumber() const
309{
310 switch (QJSValuePrivate::tag(d)) {
311 case QJSValuePrivate::Kind::IntValue:
312 case QJSValuePrivate::Kind::DoublePtr:
313 return true;
314 default:
315 break;
316 }
317
318 return false;
319}
320
321/*!
322 Returns true if this QJSValue is of the primitive type Null;
323 otherwise returns false.
324*/
325bool QJSValue::isNull() const
326{
327 return QJSValuePrivate::tag(d) == QJSValuePrivate::Kind::Null;
328}
329
330/*!
331 Returns true if this QJSValue is of the primitive type String;
332 otherwise returns false.
333
334 \sa toString()
335*/
336bool QJSValue::isString() const
337{
338 switch (QJSValuePrivate::tag(d)) {
339 case QJSValuePrivate::Kind::QStringPtr:
340 return true;
341 case QJSValuePrivate::Kind::QV4ValuePtr: {
342 return QJSValuePrivate::qv4ValuePtr(d)->isString();
343 }
344 default:
345 break;
346 }
347
348 return false;
349}
350
351/*!
352 Returns true if this QJSValue is of the primitive type Undefined or if the managed value
353 has been cleared (by deleting the engine). Otherwise returns false.
354*/
355bool QJSValue::isUndefined() const
356{
357 switch (QJSValuePrivate::tag(d)) {
358 case QJSValuePrivate::Kind::Undefined:
359 return true;
360 case QJSValuePrivate::Kind::QV4ValuePtr:
361 return QJSValuePrivate::qv4ValuePtr(d)->isUndefined();
362 default:
363 break;
364 }
365
366 return false;
367}
368
369/*!
370 Returns true if this QJSValue is an object of the Error class;
371 otherwise returns false.
372
373 \sa errorType(), {QJSEngine#Script Exceptions}{QJSEngine - Script Exceptions}
374*/
375bool QJSValue::isError() const
376{
377 return QJSValuePrivate::asManagedType<ErrorObject>(this);
378}
379
380/*!
381 Returns true if this QJSValue is an object of the URL JavaScript class;
382 otherwise returns false.
383
384 \note For a QJSValue that contains a QUrl, this function returns false.
385 However, \c{toVariant().value<QUrl>()} works in both cases.
386*/
387bool QJSValue::isUrl() const
388{
389 return QJSValuePrivate::asManagedType<UrlObject>(this);
390}
391
392/*!
393 \since 5.12
394 Returns the error type this QJSValue represents if it is an Error object.
395 Otherwise, returns \c NoError."
396
397 \sa isError(), {QJSEngine#Script Exceptions}{QJSEngine - Script Exceptions}
398*/
399QJSValue::ErrorType QJSValue::errorType() const
400{
401 const QV4::ErrorObject *error = QJSValuePrivate::asManagedType<ErrorObject>(this);
402 if (!error)
403 return NoError;
404 switch (error->d()->errorType) {
405 case QV4::Heap::ErrorObject::Error:
406 return GenericError;
407 case QV4::Heap::ErrorObject::EvalError:
408 return EvalError;
409 case QV4::Heap::ErrorObject::RangeError:
410 return RangeError;
411 case QV4::Heap::ErrorObject::ReferenceError:
412 return ReferenceError;
413 case QV4::Heap::ErrorObject::SyntaxError:
414 return SyntaxError;
415 case QV4::Heap::ErrorObject::TypeError:
416 return TypeError;
417 case QV4::Heap::ErrorObject::URIError:
418 return URIError;
419 }
420 Q_UNREACHABLE_RETURN(NoError);
421}
422
423/*!
424 Returns true if this QJSValue is an object of the Array class;
425 otherwise returns false.
426
427 \note This method is the equivalent of \e Array.isArray() in JavaScript. You
428 can use it to identify JavaScript arrays, but it will return \c false
429 for any array-like objects that are not JavaScript arrays. This includes
430 QML \e list objects for either value types or object types, JavaScript
431 typed arrays, JavaScript ArrayBuffer objects, and any custom array-like
432 objects you may create yourself. All of these \e behave like JavaScript
433 arrays, though: They generally expose the same methods and the
434 subscript operator can be used on them. Therefore, using this method to
435 determine whether an object could be used like an array is not
436 advisable.
437
438 \sa QJSEngine::newArray()
439*/
440bool QJSValue::isArray() const
441{
442 return QJSValuePrivate::asManagedType<ArrayObject>(this);
443}
444
445/*!
446 Returns true if this QJSValue is of the Object type; otherwise
447 returns false.
448
449 Note that function values, variant values, and QObject values are
450 objects, so this function returns true for such values.
451
452 \sa QJSEngine::newObject()
453*/
454bool QJSValue::isObject() const
455{
456 return QJSValuePrivate::asManagedType<QV4::Object>(this);
457}
458
459/*!
460 Returns true if this QJSValue is a function, otherwise
461 returns false.
462
463 \sa call()
464*/
465bool QJSValue::isCallable() const
466{
467 return QJSValuePrivate::asManagedType<FunctionObject>(this);
468}
469
470#if QT_DEPRECATED_SINCE(6, 9)
471/*!
472 \deprecated [6.9]
473 Returns true if this QJSValue is a variant value;
474 otherwise returns false.
475
476 \warning This function is likely to give unexpected results.
477 A variant value is only constructed by the QJSEngine in a very
478 limited number of cases. This used to be different before Qt
479 5.14, where \l{QJSEngine::toScriptValue} would have created
480 them for more types instead of corresponding ECMAScript types.
481 You can get a valid \l QVariant via \l toVariant for many values
482 for which \c{isVariant} returns false.
483
484 \sa toVariant()
485*/
486bool QJSValue::isVariant() const
487{
488 if (QJSValuePrivate::asManagedType<QV4::VariantObject>(this))
489 return true;
490 if (auto vt = QJSValuePrivate::asManagedType<QV4::QQmlValueTypeWrapper>(this))
491 if (vt->metaObject() == &QQmlVarForeign::staticMetaObject)
492 return true;
493 return false;
494}
495#endif
496
497/*!
498 Returns the string value of this QJSValue, as defined in
499 \l{ECMA-262} section 9.8, "ToString".
500
501 Note that if this QJSValue is an object, calling this function
502 has side effects on the script engine, since the engine will call
503 the object's toString() function (and possibly valueOf()) in an
504 attempt to convert the object to a primitive value (possibly
505 resulting in an uncaught script exception).
506
507 \sa isString()
508*/
509QString QJSValue::toString() const
510{
511 if (const QString *string = QJSValuePrivate::asQString(this))
512 return *string;
513
514 return QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)).toQStringNoThrow();
515}
516
517template<typename T>
518T caughtResult(const QJSValue *v, T (QV4::Value::*convert)() const)
519{
520 const T result = (QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(v)).*convert)();
521 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(v);
522 if (engine && engine->hasException) {
523 engine->catchException();
524 return T();
525 }
526 return result;
527}
528
529/*!
530 Returns the number value of this QJSValue, as defined in
531 \l{ECMA-262} section 9.3, "ToNumber".
532
533 Note that if this QJSValue is an object, calling this function
534 has side effects on the script engine, since the engine will call
535 the object's valueOf() function (and possibly toString()) in an
536 attempt to convert the object to a primitive value (possibly
537 resulting in an uncaught script exception).
538
539 \sa isNumber(), toInt(), toUInt()
540*/
541double QJSValue::toNumber() const
542{
543 if (const QString *string = QJSValuePrivate::asQString(this))
544 return RuntimeHelpers::stringToNumber(*string);
545
546 return caughtResult<double>(this, &QV4::Value::toNumber);
547}
548
549/*!
550 Returns the boolean value of this QJSValue, using the conversion
551 rules described in \l{ECMA-262} section 9.2, "ToBoolean".
552
553 Note that if this QJSValue is an object, calling this function
554 has side effects on the script engine, since the engine will call
555 the object's valueOf() function (and possibly toString()) in an
556 attempt to convert the object to a primitive value (possibly
557 resulting in an uncaught script exception).
558
559 \sa isBool()
560*/
561bool QJSValue::toBool() const
562{
563 if (const QString *string = QJSValuePrivate::asQString(this))
564 return string->size() > 0;
565
566 return caughtResult<bool>(this, &QV4::Value::toBoolean);
567}
568
569/*!
570 Returns the signed 32-bit integer value of this QJSValue, using
571 the conversion rules described in \l{ECMA-262} section 9.5, "ToInt32".
572
573 Note that if this QJSValue is an object, calling this function
574 has side effects on the script engine, since the engine will call
575 the object's valueOf() function (and possibly toString()) in an
576 attempt to convert the object to a primitive value (possibly
577 resulting in an uncaught script exception).
578
579 \sa toNumber(), toUInt()
580*/
581qint32 QJSValue::toInt() const
582{
583 if (const QString *string = QJSValuePrivate::asQString(this))
584 return QV4::Value::toInt32(RuntimeHelpers::stringToNumber(*string));
585
586 return caughtResult<qint32>(this, &QV4::Value::toInt32);
587}
588
589/*!
590 Returns the unsigned 32-bit integer value of this QJSValue, using
591 the conversion rules described in \l{ECMA-262} section 9.6, "ToUint32".
592
593 Note that if this QJSValue is an object, calling this function
594 has side effects on the script engine, since the engine will call
595 the object's valueOf() function (and possibly toString()) in an
596 attempt to convert the object to a primitive value (possibly
597 resulting in an uncaught script exception).
598
599 \sa toNumber(), toInt()
600*/
601quint32 QJSValue::toUInt() const
602{
603 if (const QString *string = QJSValuePrivate::asQString(this))
604 return QV4::Value::toUInt32(RuntimeHelpers::stringToNumber(*string));
605
606 return caughtResult<quint32>(this, &QV4::Value::toUInt32);
607}
608
609/*!
610 \overload
611
612 Returns toVariant(ConvertJSObjects).
613
614 \sa isVariant()
615*/
616QVariant QJSValue::toVariant() const
617{
618 return toVariant(ConvertJSObjects);
619}
620
621/*!
622 Returns the QVariant value of this QJSValue, if it can be
623 converted to a QVariant; otherwise returns an invalid QVariant.
624 Some JavaScript types and objects have native expressions in Qt.
625 Those are converted to their native expressions. For example:
626
627 \table
628 \header \li Input Type \li Result
629 \row \li Undefined \li An invalid QVariant.
630 \row \li Null \li A QVariant containing a null pointer (QMetaType::Nullptr).
631 \row \li Boolean \li A QVariant containing the value of the boolean.
632 \row \li Number \li A QVariant containing the value of the number.
633 \row \li String \li A QVariant containing the value of the string.
634 \row \li QVariant Object \li The result is the QVariant value of the object (no conversion).
635 \row \li QVariantMap Object \li A QVariant containing the QVariantMap stored in the object (no conversion).
636 \row \li QVariantHash Object \li A QVariant containing the QVariantHash stored in the object (no conversion).
637 \row \li QObject Object \li A QVariant containing a pointer to the QObject.
638 \row \li Date Object \li A QVariant containing the date value (toDateTime()).
639 \row \li RegularExpression Object \li A QVariant containing the regular expression value.
640 \endtable
641
642 For other types the \a behavior parameter is relevant. If
643 \c ConvertJSObjects is given, a best effort but possibly lossy conversion is
644 attempted. Generic JavaScript objects are converted to QVariantMap.
645 JavaScript arrays are converted to QVariantList. Each property or element is
646 converted to a QVariant, recursively; cyclic references are not followed.
647 JavaScript function objects are dropped. If \c RetainJSObjects is given, the
648 QJSValue is wrapped into a QVariant via QVariant::fromValue(). The resulting
649 conversion is lossless but the internal structure of the objects is not
650 immediately accessible.
651
652 \sa isVariant()
653*/
654QVariant QJSValue::toVariant(QJSValue::ObjectConversionBehavior behavior) const
655{
656 if (const QString *string = QJSValuePrivate::asQString(this))
657 return QVariant(*string);
658
659 QV4::Value val = QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this));
660 if (val.isUndefined())
661 return QVariant();
662 if (val.isNull())
663 return QVariant(QMetaType::fromType<std::nullptr_t>(), nullptr);
664 if (val.isBoolean())
665 return QVariant(val.booleanValue());
666 if (val.isInt32()) // Includes doubles that can be losslessly casted to int
667 return QVariant(val.integerValue());
668 if (val.isNumber())
669 return QVariant(val.doubleValue());
670
671 Q_ASSERT(val.isManaged());
672
673 if (val.isString())
674 return QVariant(val.toQString());
675
676 if (behavior == RetainJSObjects) {
677 return QV4::ExecutionEngine::toVariant(
678 val, /*typeHint*/ QMetaType{}, /*createJSValueForObjectsAndSymbols=*/ true);
679 } else {
680 return QV4::ExecutionEngine::toVariantLossy(val);
681 }
682
683 Q_ASSERT(false);
684 return QVariant();
685}
686
687/*!
688 * Converts the value to a QJSPrimitiveValue. If the value holds a type
689 * supported by QJSPrimitiveValue, the value is copied. Otherwise the
690 * value is converted to a string, and the string is stored in
691 * QJSPrimitiveValue.
692 *
693 * \note Conversion of a managed value to a string can throw an exception. In
694 * particular, symbols cannot be coerced into strings, or a custom
695 * toString() method may throw. In this case the result is the undefined
696 * value and the engine carries an error after the conversion.
697 */
698QJSPrimitiveValue QJSValue::toPrimitive() const
699{
700 if (const QString *string = QJSValuePrivate::asQString(this))
701 return *string;
702
703 const QV4::Value val = QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this));
704 return QV4::ExecutionEngine::createPrimitive(&val);
705}
706
707/*!
708 Calls this QJSValue as a function, passing \a args as arguments
709 to the function, and using the globalObject() as the "this"-object.
710 Returns the value returned from the function.
711
712 If this QJSValue is not callable, call() does nothing and
713 returns an undefined QJSValue.
714
715 Calling call() can cause an exception to occur in the script engine;
716 in that case, call() returns the value that was thrown (typically an
717 \c{Error} object). You can call isError() on the return value to
718 determine whether an exception occurred.
719
720 \sa isCallable(), callWithInstance(), callAsConstructor()
721*/
722QJSValue QJSValue::call(const QJSValueList &args) const
723{
724 const FunctionObject *f = QJSValuePrivate::asManagedType<FunctionObject>(this);
725 if (!f)
726 return QJSValue();
727
728 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
729 Q_ASSERT(engine);
730
731 Scope scope(engine);
732 JSCallArguments jsCallData(scope, args.size());
733 *jsCallData.thisObject = engine->globalObject;
734 for (int i = 0; i < args.size(); ++i) {
735 if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
736 qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
737 return QJSValue();
738 }
739 jsCallData.args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
740 }
741
742 ScopedValue result(scope, f->call(jsCallData));
743 if (engine->hasException)
744 result = engine->catchException();
745 if (engine->isInterrupted.loadRelaxed())
746 result = engine->newErrorObject(QStringLiteral("Interrupted"));
747
748 return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
749}
750
751/*!
752 Calls this QJSValue as a function, using \a instance as
753 the `this' object in the function call, and passing \a args
754 as arguments to the function. Returns the value returned from
755 the function.
756
757 If this QJSValue is not a function, call() does nothing
758 and returns an undefined QJSValue.
759
760 Note that if \a instance is not an object, the global object
761 (see \l{QJSEngine::globalObject()}) will be used as the
762 `this' object.
763
764 Calling call() can cause an exception to occur in the script engine;
765 in that case, call() returns the value that was thrown (typically an
766 \c{Error} object). You can call isError() on the return value to
767 determine whether an exception occurred.
768
769 \sa call()
770*/
771QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList &args) const
772{
773 const FunctionObject *f = QJSValuePrivate::asManagedType<FunctionObject>(this);
774 if (!f)
775 return QJSValue();
776
777 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
778 Q_ASSERT(engine);
779 Scope scope(engine);
780
781 if (!QJSValuePrivate::checkEngine(engine, instance)) {
782 qWarning("QJSValue::call() failed: cannot call function with thisObject created in a different engine");
783 return QJSValue();
784 }
785
786 JSCallArguments jsCallData(scope, args.size());
787 *jsCallData.thisObject = QJSValuePrivate::convertToReturnedValue(engine, instance);
788 for (int i = 0; i < args.size(); ++i) {
789 if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
790 qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
791 return QJSValue();
792 }
793 jsCallData.args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
794 }
795
796 ScopedValue result(scope, f->call(jsCallData));
797 if (engine->hasException)
798 result = engine->catchException();
799 if (engine->isInterrupted.loadRelaxed())
800 result = engine->newErrorObject(QStringLiteral("Interrupted"));
801
802 return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
803}
804
805/*!
806 Creates a new \c{Object} and calls this QJSValue as a
807 constructor, using the created object as the `this' object and
808 passing \a args as arguments. If the return value from the
809 constructor call is an object, then that object is returned;
810 otherwise the default constructed object is returned.
811
812 If this QJSValue is not a function, callAsConstructor() does
813 nothing and returns an undefined QJSValue.
814
815 Calling this function can cause an exception to occur in the
816 script engine; in that case, the value that was thrown
817 (typically an \c{Error} object) is returned. You can call
818 isError() on the return value to determine whether an
819 exception occurred.
820
821 \sa call(), QJSEngine::newObject()
822*/
823QJSValue QJSValue::callAsConstructor(const QJSValueList &args) const
824{
825 const FunctionObject *f = QJSValuePrivate::asManagedType<FunctionObject>(this);
826 if (!f)
827 return QJSValue();
828
829 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
830 Q_ASSERT(engine);
831
832 Scope scope(engine);
833 JSCallArguments jsCallData(scope, args.size());
834 for (int i = 0; i < args.size(); ++i) {
835 if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
836 qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
837 return QJSValue();
838 }
839 jsCallData.args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
840 }
841
842 ScopedValue result(scope, f->callAsConstructor(jsCallData));
843 if (engine->hasException)
844 result = engine->catchException();
845 if (engine->isInterrupted.loadRelaxed())
846 result = engine->newErrorObject(QStringLiteral("Interrupted"));
847
848 return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
849}
850
851/*!
852 If this QJSValue is an object, returns the internal prototype
853 (\c{__proto__} property) of this object; otherwise returns an
854 undefined QJSValue.
855
856 \sa setPrototype(), isObject()
857*/
858QJSValue QJSValue::prototype() const
859{
860 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
861 if (!engine)
862 return QJSValue();
863 QV4::Scope scope(engine);
864 ScopedObject o(scope, QJSValuePrivate::asManagedType<QV4::Object>(this));
865 if (!o)
866 return QJSValue();
867 ScopedObject p(scope, o->getPrototypeOf());
868 if (!p)
869 return QJSValue(NullValue);
870 return QJSValuePrivate::fromReturnedValue(p.asReturnedValue());
871}
872
873/*!
874 If this QJSValue is an object, sets the internal prototype
875 (\c{__proto__} property) of this object to be \a prototype;
876 if the QJSValue is null, it sets the prototype to null;
877 otherwise does nothing.
878
879 The internal prototype should not be confused with the public
880 property with name "prototype"; the public prototype is usually
881 only set on functions that act as constructors.
882
883 \sa prototype(), isObject()
884*/
885void QJSValue::setPrototype(const QJSValue& prototype)
886{
887 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
888 if (!engine)
889 return;
890 Scope scope(engine);
891 ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
892 if (!o)
893 return;
894 QV4::Value val = QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&prototype));
895 if (val.isNull()) {
896 o->setPrototypeOf(nullptr);
897 return;
898 }
899
900 ScopedObject p(scope, val);
901 if (!p)
902 return;
903 if (o->engine() != p->engine()) {
904 qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
905 return;
906 }
907 if (!o->setPrototypeOf(p))
908 qWarning("QJSValue::setPrototype() failed: cyclic prototype value");
909}
910
911/*!
912 Assigns the \a other value to this QJSValue.
913
914 Note that if \a other is an object (isObject() returns true),
915 only a reference to the underlying object will be assigned;
916 the object itself will not be copied.
917*/
918QJSValue& QJSValue::operator=(const QJSValue& other)
919{
920 if (d == other.d)
921 return *this;
922
923 QJSValuePrivate::free(this);
924 d = 0;
925
926 if (const QString *string = QJSValuePrivate::asQString(&other))
927 QJSValuePrivate::setString(this, *string);
928 else
929 // fomReturnedValue is safe, as the QJSValue still has a persistent reference
930 QJSValuePrivate::setValue(
931 this,
932 QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&other)));
933
934 return *this;
935}
936
937QJSValue::QJSValue(QJSPrimitiveValue &&value)
938{
939 switch (value.type()) {
940 case QJSPrimitiveValue::Undefined:
941 d = QJSValuePrivate::encodeUndefined();
942 return;
943 case QJSPrimitiveValue::Null:
944 d = QJSValuePrivate::encodeNull();
945 return;
946 case QJSPrimitiveValue::Boolean:
947 d = QJSValuePrivate::encode(value.asBoolean());
948 return;
949 case QJSPrimitiveValue::Integer:
950 d = QJSValuePrivate::encode(value.asInteger());
951 return;
952 case QJSPrimitiveValue::Double:
953 d = QJSValuePrivate::encode(value.asDouble());
954 return;
955 case QJSPrimitiveValue::String:
956 d = QJSValuePrivate::encode(value.asString());
957 return;
958 }
959
960 Q_UNREACHABLE();
961}
962
963QJSValue::QJSValue(QJSManagedValue &&value)
964{
965 if (!value.d) {
966 d = QV4::Encode::undefined();
967 } else if (value.d->isManaged()) {
968 // If it's managed, we can adopt the persistent value.
969 QJSValuePrivate::adoptPersistentValue(this, value.d);
970 value.d = nullptr;
971 } else {
972 d = QJSValuePrivate::encode(*value.d);
973 QV4::PersistentValueStorage::free(value.d);
974 value.d = nullptr;
975 }
976}
977
978static bool js_equal(const QString &string, const QV4::Value &value)
979{
980 if (String *s = value.stringValue())
981 return string == s->toQString();
982 if (value.isNumber())
983 return RuntimeHelpers::stringToNumber(string) == value.asDouble();
984 if (value.isBoolean())
985 return RuntimeHelpers::stringToNumber(string) == double(value.booleanValue());
986 if (QV4::Object *o = value.objectValue()) {
987 Scope scope(o->engine());
988 ScopedValue p(scope, RuntimeHelpers::toPrimitive(value, PREFERREDTYPE_HINT));
989 return js_equal(string, p);
990 }
991 return false;
992}
993
994/*!
995 Returns true if this QJSValue is equal to \a other, otherwise
996 returns false. The comparison follows the behavior described in
997 \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison
998 Algorithm".
999
1000 This function can return true even if the type of this QJSValue
1001 is different from the type of the \a other value; i.e. the
1002 comparison is not strict. For example, comparing the number 9 to
1003 the string "9" returns true; comparing an undefined value to a null
1004 value returns true; comparing a \c{Number} object whose primitive
1005 value is 6 to a \c{String} object whose primitive value is "6"
1006 returns true; and comparing the number 1 to the boolean value
1007 \c{true} returns true. If you want to perform a comparison
1008 without such implicit value conversion, use strictlyEquals().
1009
1010 Note that if this QJSValue or the \a other value are objects,
1011 calling this function has side effects on the script engine, since
1012 the engine will call the object's valueOf() function (and possibly
1013 toString()) in an attempt to convert the object to a primitive value
1014 (possibly resulting in an uncaught script exception).
1015
1016 \sa strictlyEquals()
1017*/
1018bool QJSValue::equals(const QJSValue& other) const
1019{
1020 // QJSValue stores heap items in persistent values, which already ensures marking
1021 // therefore, fromReturnedValue below is safe
1022 if (const QString *string = QJSValuePrivate::asQString(this)) {
1023 if (const QString *otherString = QJSValuePrivate::asQString(&other))
1024 return *string == *otherString;
1025 return js_equal(*string, Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&other)));
1026 }
1027
1028 if (const QString *otherString = QJSValuePrivate::asQString(&other))
1029 return js_equal(*otherString, Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)));
1030
1031 return Runtime::CompareEqual::call(Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)),
1032 Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&other)));
1033}
1034
1035/*!
1036 Returns true if this QJSValue is equal to \a other using strict
1037 comparison (no conversion), otherwise returns false. The comparison
1038 follows the behavior described in \l{ECMA-262} section 11.9.6, "The
1039 Strict Equality Comparison Algorithm".
1040
1041 If the type of this QJSValue is different from the type of the
1042 \a other value, this function returns false. If the types are equal,
1043 the result depends on the type, as shown in the following table:
1044
1045 \table
1046 \header \li Type \li Result
1047 \row \li Undefined \li true
1048 \row \li Null \li true
1049 \row \li Boolean \li true if values are both true or both false, false otherwise
1050 \row \li Number \li false if either value is NaN (Not-a-Number); true if values are equal, false otherwise
1051 \row \li String \li true if both values are exactly the same sequence of characters, false otherwise
1052 \row \li Object \li true if both values refer to the same object, false otherwise
1053 \endtable
1054
1055 \sa equals()
1056*/
1057bool QJSValue::strictlyEquals(const QJSValue& other) const
1058{
1059 if (const QString *string = QJSValuePrivate::asQString(this)) {
1060 if (const QString *otherString = QJSValuePrivate::asQString(&other))
1061 return *string == *otherString;
1062 if (const String *s = QJSValuePrivate::asManagedType<String>(&other))
1063 return *string == s->toQString();
1064 return false;
1065 }
1066
1067 if (const QString *otherString = QJSValuePrivate::asQString(&other)) {
1068 if (const String *s = QJSValuePrivate::asManagedType<String>(this))
1069 return *otherString == s->toQString();
1070 return false;
1071 }
1072
1073 // QJSValue stores heap objects persistently, so we can be sure that they'll be marked
1074 // thus we can safely use fromReturnedValue
1075 return RuntimeHelpers::strictEqual(Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)),
1076 Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&other)));
1077}
1078
1079/*!
1080 Returns the value of this QJSValue's property with the given \a name.
1081 If no such property exists, an undefined QJSValue is returned.
1082
1083 If the property is implemented using a getter function (i.e. has the
1084 PropertyGetter flag set), calling property() has side-effects on the
1085 script engine, since the getter function will be called (possibly
1086 resulting in an uncaught script exception). If an exception
1087 occurred, property() returns the value that was thrown (typically
1088 an \c{Error} object).
1089
1090 To access array elements, use the
1091 \l {QJSValue::}{setProperty(quint32 arrayIndex, const QJSValue &value)}
1092 overload instead.
1093
1094 \sa setProperty(), hasProperty(), QJSValueIterator
1095*/
1096QJSValue QJSValue::property(const QString& name) const
1097{
1098 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1099 if (!engine)
1100 return QJSValue();
1101
1102 QV4::Scope scope(engine);
1103 ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
1104 if (!o)
1105 return QJSValue();
1106
1107 ScopedString s(scope, engine->newString(name));
1108 QV4::ScopedValue result(scope, o->get(s->toPropertyKey()));
1109 if (engine->hasException)
1110 result = engine->catchException();
1111
1112 return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
1113}
1114
1115/*!
1116 \overload
1117
1118 Returns the property at the given \a arrayIndex.
1119
1120 It is possible to access elements in an array in two ways. The first is to
1121 use the array index as the property name:
1122
1123 \code
1124 qDebug() << jsValueArray.property(QLatin1String("4")).toString();
1125 \endcode
1126
1127 The second is to use the overload that takes an index:
1128
1129 \code
1130 qDebug() << jsValueArray.property(4).toString();
1131 \endcode
1132
1133 Both of these approaches achieve the same result, except that the latter:
1134
1135 \list
1136 \li Is easier to use (can use an integer directly)
1137 \li Is faster (no conversion to integer)
1138 \endlist
1139
1140 If this QJSValue is not an Array object, this function behaves
1141 as if property() was called with the string representation of \a
1142 arrayIndex.
1143*/
1144QJSValue QJSValue::property(quint32 arrayIndex) const
1145{
1146 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1147 if (!engine)
1148 return QJSValue();
1149
1150 QV4::Scope scope(engine);
1151 ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
1152 if (!o)
1153 return QJSValue();
1154
1155 QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax()) : o->get(arrayIndex));
1156 if (engine->hasException)
1157 engine->catchException();
1158 return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
1159}
1160
1161/*!
1162 Sets the value of this QJSValue's property with the given \a name to
1163 the given \a value.
1164
1165 If this QJSValue is not an object, this function does nothing.
1166
1167 If this QJSValue does not already have a property with name \a name,
1168 a new property is created.
1169
1170 To modify array elements, use the
1171 \l {QJSValue::}{setProperty(quint32 arrayIndex, const QJSValue &value)}
1172 overload instead.
1173
1174 \sa property(), deleteProperty()
1175*/
1176void QJSValue::setProperty(const QString& name, const QJSValue& value)
1177{
1178 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1179 if (!engine)
1180 return;
1181 Scope scope(engine);
1182
1183 ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
1184 if (!o)
1185 return;
1186
1187 if (!QJSValuePrivate::checkEngine(engine, value)) {
1188 qWarning("QJSValue::setProperty(%s) failed: cannot set value created in a different engine", name.toUtf8().constData());
1189 return;
1190 }
1191
1192 ScopedString s(scope, engine->newString(name));
1193 QV4::ScopedValue v(scope, QJSValuePrivate::convertToReturnedValue(engine, value));
1194 o->put(s->toPropertyKey(), v);
1195 if (engine->hasException)
1196 engine->catchException();
1197}
1198
1199/*!
1200 \overload
1201
1202 Sets the property at the given \a arrayIndex to the given \a value.
1203
1204 It is possible to modify elements in an array in two ways. The first is to
1205 use the array index as the property name:
1206
1207 \code
1208 jsValueArray.setProperty(QLatin1String("4"), value);
1209 \endcode
1210
1211 The second is to use the overload that takes an index:
1212
1213 \code
1214 jsValueArray.setProperty(4, value);
1215 \endcode
1216
1217 Both of these approaches achieve the same result, except that the latter:
1218
1219 \list
1220 \li Is easier to use (can use an integer directly)
1221 \li Is faster (no conversion to integer)
1222 \endlist
1223
1224 If this QJSValue is not an Array object, this function behaves
1225 as if setProperty() was called with the string representation of \a
1226 arrayIndex.
1227
1228 \sa {QJSValue::}{property(quint32 arrayIndex)}, {Working With Arrays}
1229*/
1230void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
1231{
1232 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1233 if (!engine)
1234 return;
1235 Scope scope(engine);
1236
1237 ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
1238 if (!o)
1239 return;
1240
1241 if (!QJSValuePrivate::checkEngine(engine, value)) {
1242 qWarning("QJSValue::setProperty(%d) failed: cannot set value created in a different engine", arrayIndex);
1243 return;
1244 }
1245
1246 QV4::ScopedValue v(scope, QJSValuePrivate::convertToReturnedValue(engine, value));
1247 PropertyKey id = arrayIndex != UINT_MAX ? PropertyKey::fromArrayIndex(arrayIndex) : engine->id_uintMax()->propertyKey();
1248 o->put(id, v);
1249 if (engine->hasException)
1250 engine->catchException();
1251}
1252
1253/*!
1254 Attempts to delete this object's property of the given \a name.
1255 Returns true if the property was deleted, otherwise returns false.
1256
1257 The behavior of this function is consistent with the JavaScript
1258 delete operator. In particular:
1259
1260 \list
1261 \li Non-configurable properties cannot be deleted.
1262 \li This function will return true even if this object doesn't
1263 have a property of the given \a name (i.e., non-existent
1264 properties are "trivially deletable").
1265 \li If this object doesn't have an own property of the given
1266 \a name, but an object in the prototype() chain does, the
1267 prototype object's property is not deleted, and this function
1268 returns true.
1269 \endlist
1270
1271 \sa setProperty(), hasOwnProperty()
1272*/
1273bool QJSValue::deleteProperty(const QString &name)
1274{
1275 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1276 if (!engine)
1277 return false;
1278
1279 Scope scope(engine);
1280 ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
1281 if (!o)
1282 return false;
1283
1284 ScopedString s(scope, engine->newString(name));
1285 return o->deleteProperty(s->toPropertyKey());
1286}
1287
1288/*!
1289 Returns true if this object has a property of the given \a name,
1290 otherwise returns false.
1291
1292 \sa property(), hasOwnProperty()
1293*/
1294bool QJSValue::hasProperty(const QString &name) const
1295{
1296 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1297 if (!engine)
1298 return false;
1299
1300 Scope scope(engine);
1301 ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
1302 if (!o)
1303 return false;
1304
1305 ScopedString s(scope, engine->newString(name));
1306 return o->hasProperty(s->toPropertyKey());
1307}
1308
1309/*!
1310 Returns true if this object has an own (not prototype-inherited)
1311 property of the given \a name, otherwise returns false.
1312
1313 \sa property(), hasProperty()
1314*/
1315bool QJSValue::hasOwnProperty(const QString &name) const
1316{
1317 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1318 if (!engine)
1319 return false;
1320
1321 Scope scope(engine);
1322 ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
1323 if (!o)
1324 return false;
1325
1326 ScopedString s(scope, engine->newIdentifier(name));
1327 return o->getOwnProperty(s->propertyKey()) != Attr_Invalid;
1328}
1329
1330/*!
1331 * If this QJSValue is a QObject, returns the QObject pointer
1332 * that the QJSValue represents; otherwise, returns \nullptr.
1333 *
1334 * If the QObject that this QJSValue wraps has been deleted,
1335 * this function returns \nullptr (i.e. it is possible for toQObject()
1336 * to return \nullptr even when isQObject() returns true).
1337 *
1338 * \sa isQObject()
1339 */
1340QObject *QJSValue::toQObject() const
1341{
1342 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1343 if (!engine)
1344 return nullptr;
1345 QV4::Scope scope(engine);
1346 QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, QJSValuePrivate::asReturnedValue(this));
1347 if (!wrapper)
1348 return nullptr;
1349
1350 return wrapper->object();
1351}
1352
1353/*!
1354 \since 5.8
1355
1356 * If this QJSValue is a QMetaObject, returns the QMetaObject pointer
1357 * that the QJSValue represents; otherwise, returns \nullptr.
1358 *
1359 * \sa isQMetaObject()
1360 */
1361const QMetaObject *QJSValue::toQMetaObject() const
1362{
1363 QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
1364 if (!engine)
1365 return nullptr;
1366 QV4::Scope scope(engine);
1367 QV4::Scoped<QV4::QMetaObjectWrapper> wrapper(scope, QJSValuePrivate::asReturnedValue(this));
1368 if (!wrapper)
1369 return nullptr;
1370
1371 return wrapper->metaObject();
1372}
1373
1374
1375/*!
1376 Returns a QDateTime representation of this value, in local time.
1377 If this QJSValue is not a date, or the value of the date is NaN
1378 (Not-a-Number), an invalid QDateTime is returned.
1379
1380 \sa isDate()
1381*/
1382QDateTime QJSValue::toDateTime() const
1383{
1384 if (const QV4::DateObject *date = QJSValuePrivate::asManagedType<DateObject>(this))
1385 return date->toQDateTime();
1386 return QDateTime();
1387}
1388
1389/*!
1390 Returns true if this QJSValue is an object of the Date class;
1391 otherwise returns false.
1392*/
1393bool QJSValue::isDate() const
1394{
1395 return QJSValuePrivate::asManagedType<DateObject>(this);
1396}
1397
1398/*!
1399 Returns true if this QJSValue is an object of the RegExp class;
1400 otherwise returns false.
1401*/
1402bool QJSValue::isRegExp() const
1403{
1404 return QJSValuePrivate::asManagedType<RegExpObject>(this);
1405}
1406
1407/*!
1408 Returns true if this QJSValue is a QObject; otherwise returns
1409 false.
1410
1411 Note: This function returns true even if the QObject that this
1412 QJSValue wraps has been deleted.
1413
1414 \sa toQObject(), QJSEngine::newQObject()
1415*/
1416bool QJSValue::isQObject() const
1417{
1418 return QJSValuePrivate::asManagedType<QV4::QObjectWrapper>(this);
1419}
1420
1421/*!
1422 \since 5.8
1423
1424 Returns true if this QJSValue is a QMetaObject; otherwise returns
1425 false.
1426
1427 \sa toQMetaObject(), QJSEngine::newQMetaObject()
1428*/
1429bool QJSValue::isQMetaObject() const
1430{
1431 return QJSValuePrivate::asManagedType<QV4::QMetaObjectWrapper>(this);
1432}
1433
1434#ifndef QT_NO_DATASTREAM
1435QDataStream &operator<<(QDataStream &stream, const QJSValue &jsv)
1436{
1437 quint32 isNullOrUndefined = 0;
1438 if (jsv.isNull())
1439 isNullOrUndefined |= 0x1;
1440 if (jsv.isUndefined())
1441 isNullOrUndefined |= 0x2;
1442 stream << isNullOrUndefined;
1443 if (!isNullOrUndefined) {
1444 const QVariant v = jsv.toVariant();
1445 switch (v.userType()) {
1446 case QMetaType::Bool:
1447 case QMetaType::Double:
1448 case QMetaType::Int:
1449 case QMetaType::QString:
1450 v.save(stream);
1451 break;
1452 default:
1453 qWarning() << "QDataStream::operator<< was to save a non-trivial QJSValue."
1454 << "This is not supported anymore, please stream a QVariant instead.";
1455 QVariant().save(stream);
1456 break;
1457 }
1458
1459 }
1460 return stream;
1461}
1462
1463QDataStream &operator>>(QDataStream &stream, QJSValue &jsv)
1464{
1465 quint32 isNullOrUndefined;
1466 stream >> isNullOrUndefined;
1467
1468 if (isNullOrUndefined & 0x1) {
1469 jsv = QJSValue(QJSValue::NullValue);
1470 } else if (isNullOrUndefined & 0x2) {
1471 jsv = QJSValue();
1472 } else {
1473 QVariant v;
1474 v.load(stream);
1475
1476 switch (v.userType()) {
1477 case QMetaType::Bool:
1478 jsv = QJSValue(v.toBool());
1479 break;
1480 case QMetaType::Double:
1481 jsv = QJSValue(v.toDouble());
1482 break;
1483 case QMetaType::Int:
1484 jsv = QJSValue(v.toInt());
1485 break;
1486 case QMetaType::QString:
1487 jsv = QJSValue(v.toString());
1488 break;
1489 default:
1490 qWarning() << "QDataStream::operator>> to restore a non-trivial QJSValue."
1491 << "This is not supported anymore, please stream a QVariant instead.";
1492 break;
1493 }
1494 }
1495 return stream;
1496}
1497#endif
1498
1499QT_END_NAMESPACE
Definition qjsvalue.h:23
T caughtResult(const QJSValue *v, T(QV4::Value::*convert)() const)
Definition qjsvalue.cpp:518
static bool js_equal(const QString &string, const QV4::Value &value)
Definition qjsvalue.cpp:978
QDataStream & operator<<(QDataStream &stream, const QJSValue &jsv)
QDataStream & operator>>(QDataStream &stream, QJSValue &jsv)