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

source code of qtdeclarative/src/qml/jsapi/qjsvalue.cpp