source: trunk/src/script/api/qscriptvalue.cpp@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 66.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtScript module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL-ONLY$
10** GNU Lesser General Public License Usage
11** This file may be used under the terms of the GNU Lesser
12** General Public License version 2.1 as published by the Free Software
13** Foundation and appearing in the file LICENSE.LGPL included in the
14** packaging of this file. Please review the following information to
15** ensure the GNU Lesser General Public License version 2.1 requirements
16** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17**
18** If you have questions regarding the use of this file, please contact
19** Nokia at [email protected].
20** $QT_END_LICENSE$
21**
22****************************************************************************/
23
24#include "config.h"
25#include "qscriptvalue.h"
26
27#include "qscriptvalue_p.h"
28#include "qscriptengine.h"
29#include "qscriptengine_p.h"
30#include "qscriptstring_p.h"
31
32#include "JSGlobalObject.h"
33#include "JSImmediate.h"
34#include "JSObject.h"
35#include "JSValue.h"
36#include "JSFunction.h"
37#include "Identifier.h"
38#include "Operations.h"
39#include "Arguments.h"
40
41#include <QtCore/qvariant.h>
42#include <QtCore/qvarlengtharray.h>
43#include <QtCore/qnumeric.h>
44
45/*!
46 \since 4.3
47 \class QScriptValue
48
49 \brief The QScriptValue class acts as a container for the Qt Script data types.
50
51 \ingroup script
52 \mainclass
53
54 QScriptValue supports the types defined in the \l{ECMA-262}
55 standard: The primitive types, which are Undefined, Null, Boolean,
56 Number, and String; and the Object type. Additionally, Qt Script
57 has built-in support for QVariant, QObject and QMetaObject.
58
59 For the object-based types (including Date and RegExp), use the
60 newT() functions in QScriptEngine (e.g. QScriptEngine::newObject())
61 to create a QScriptValue of the desired type. For the primitive types,
62 use one of the QScriptValue constructor overloads.
63
64 The methods named isT() (e.g. isBool(), isUndefined()) can be
65 used to test if a value is of a certain type. The methods named
66 toT() (e.g. toBool(), toString()) can be used to convert a
67 QScriptValue to another type. You can also use the generic
68 qscriptvalue_cast() function.
69
70 Object values have zero or more properties which are themselves
71 QScriptValues. Use setProperty() to set a property of an object, and
72 call property() to retrieve the value of a property.
73
74 \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 0
75
76 Each property can have a set of attributes; these are specified as
77 the third (optional) argument to setProperty(). The attributes of a
78 property can be queried by calling the propertyFlags() function. The
79 following code snippet creates a property that cannot be modified by
80 script code:
81
82 \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 1
83
84 If you want to iterate over the properties of a script object, use
85 the QScriptValueIterator class.
86
87 Object values have an internal \c{prototype} property, which can be
88 accessed with prototype() and setPrototype(). Properties added to a
89 prototype are shared by all objects having that prototype; this is
90 referred to as prototype-based inheritance. In practice, it means
91 that (by default) the property() function will automatically attempt
92 to look up look the property in the prototype() (and in the
93 prototype of the prototype(), and so on), if the object itself does
94 not have the requested property. Note that this prototype-based
95 lookup is not performed by setProperty(); setProperty() will always
96 create the property in the script object itself. For more
97 information, see the \l{QtScript} documentation.
98
99 Function objects (objects for which isFunction() returns true) can
100 be invoked by calling call(). Constructor functions can be used to
101 construct new objects by calling construct().
102
103 Use equals(), strictlyEquals() and lessThan() to compare a QScriptValue
104 to another.
105
106 Object values can have custom data associated with them; see the
107 setData() and data() functions. By default, this data is not
108 accessible to scripts; it can be used to store any data you want to
109 associate with the script object. Typically this is used by custom
110 class objects (see QScriptClass) to store a C++ type that contains
111 the "native" object data.
112
113 Note that a QScriptValue for which isObject() is true only carries a
114 reference to an actual object; copying the QScriptValue will only
115 copy the object reference, not the object itself. If you want to
116 clone an object (i.e. copy an object's properties to another
117 object), you can do so with the help of a \c{for-in} statement in
118 script code, or QScriptValueIterator in C++.
119
120 \sa QScriptEngine, QScriptValueIterator
121*/
122
123/*!
124 \enum QScriptValue::SpecialValue
125
126 This enum is used to specify a single-valued type.
127
128 \value UndefinedValue An undefined value.
129
130 \value NullValue A null value.
131*/
132
133/*!
134 \enum QScriptValue::PropertyFlag
135
136 This enum describes the attributes of a property.
137
138 \value ReadOnly The property is read-only. Attempts by Qt Script code to write to the property will be ignored.
139
140 \value Undeletable Attempts by Qt Script code to \c{delete} the property will be ignored.
141
142 \value SkipInEnumeration The property is not to be enumerated by a \c{for-in} enumeration.
143
144 \value PropertyGetter The property is defined by a function which will be called to get the property value.
145
146 \value PropertySetter The property is defined by a function which will be called to set the property value.
147
148 \value QObjectMember This flag is used to indicate that an existing property is a QObject member (a property or method).
149
150 \value KeepExistingFlags This value is used to indicate to setProperty() that the property's flags should be left unchanged. If the property doesn't exist, the default flags (0) will be used.
151
152 \value UserRange Flags in this range are not used by Qt Script, and can be used for custom purposes.
153*/
154
155/*!
156 \enum QScriptValue::ResolveFlag
157
158 This enum specifies how to look up a property of an object.
159
160 \value ResolveLocal Only check the object's own properties.
161
162 \value ResolvePrototype Check the object's own properties first, then search the prototype chain. This is the default.
163
164 \omitvalue ResolveScope Check the object's own properties first, then search the scope chain.
165
166 \omitvalue ResolveFull Check the object's own properties first, then search the prototype chain, and finally search the scope chain.
167*/
168
169QT_BEGIN_NAMESPACE
170
171void QScriptValuePrivate::detachFromEngine()
172{
173 if (isJSC())
174 jscValue = JSC::JSValue();
175 engine = 0;
176}
177
178/*!
179 \internal
180*/
181QScriptValue::QScriptValue(QScriptValuePrivate *d)
182 : d_ptr(d)
183{
184}
185
186/*!
187 Constructs an invalid QScriptValue.
188*/
189QScriptValue::QScriptValue()
190 : d_ptr(0)
191{
192}
193
194/*!
195 Destroys this QScriptValue.
196*/
197QScriptValue::~QScriptValue()
198{
199}
200
201/*!
202 Constructs a new QScriptValue that is a copy of \a other.
203
204 Note that if \a other is an object (i.e., isObject() would return
205 true), then only a reference to the underlying object is copied into
206 the new script value (i.e., the object itself is not copied).
207*/
208QScriptValue::QScriptValue(const QScriptValue &other)
209 : d_ptr(other.d_ptr)
210{
211}
212
213/*!
214 \obsolete
215
216 Constructs a new QScriptValue with the special \a value and
217 registers it with the script \a engine.
218*/
219QScriptValue::QScriptValue(QScriptEngine *engine, QScriptValue::SpecialValue value)
220 : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
221{
222 switch (value) {
223 case NullValue:
224 d_ptr->initFrom(JSC::jsNull());
225 break;
226 case UndefinedValue:
227 d_ptr->initFrom(JSC::jsUndefined());
228 break;
229 }
230}
231
232/*!
233 \obsolete
234
235 \fn QScriptValue::QScriptValue(QScriptEngine *engine, bool value)
236
237 Constructs a new QScriptValue with the boolean \a value and
238 registers it with the script \a engine.
239*/
240QScriptValue::QScriptValue(QScriptEngine *engine, bool val)
241 : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
242{
243 d_ptr->initFrom(JSC::jsBoolean(val));
244}
245
246/*!
247 \fn QScriptValue::QScriptValue(QScriptEngine *engine, int value)
248 \obsolete
249
250 Constructs a new QScriptValue with the integer \a value and
251 registers it with the script \a engine.
252*/
253QScriptValue::QScriptValue(QScriptEngine *engine, int val)
254 : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
255{
256 if (engine) {
257 JSC::ExecState *exec = d_ptr->engine->currentFrame;
258 d_ptr->initFrom(JSC::jsNumber(exec, val));
259 } else
260 d_ptr->initFrom(val);
261}
262
263/*!
264 \fn QScriptValue::QScriptValue(QScriptEngine *engine, uint value)
265 \obsolete
266
267 Constructs a new QScriptValue with the unsigned integer \a value and
268 registers it with the script \a engine.
269 */
270QScriptValue::QScriptValue(QScriptEngine *engine, uint val)
271 : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
272{
273 if (engine) {
274 JSC::ExecState *exec = d_ptr->engine->currentFrame;
275 d_ptr->initFrom(JSC::jsNumber(exec, val));
276 } else
277 d_ptr->initFrom(val);
278}
279
280/*!
281 \fn QScriptValue::QScriptValue(QScriptEngine *engine, qsreal value)
282 \obsolete
283
284 Constructs a new QScriptValue with the qsreal \a value and
285 registers it with the script \a engine.
286*/
287QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val)
288 : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
289{
290 if (engine) {
291 JSC::ExecState *exec = d_ptr->engine->currentFrame;
292 d_ptr->initFrom(JSC::jsNumber(exec, val));
293 } else
294 d_ptr->initFrom(val);
295}
296
297/*!
298 \fn QScriptValue::QScriptValue(QScriptEngine *engine, const QString &value)
299 \obsolete
300
301 Constructs a new QScriptValue with the string \a value and
302 registers it with the script \a engine.
303*/
304QScriptValue::QScriptValue(QScriptEngine *engine, const QString &val)
305 : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
306{
307 if (engine) {
308 JSC::ExecState *exec = d_ptr->engine->currentFrame;
309 d_ptr->initFrom(JSC::jsString(exec, val));
310 } else {
311 d_ptr->initFrom(val);
312 }
313}
314
315/*!
316 \fn QScriptValue::QScriptValue(QScriptEngine *engine, const char *value)
317 \obsolete
318
319 Constructs a new QScriptValue with the string \a value and
320 registers it with the script \a engine.
321*/
322
323#ifndef QT_NO_CAST_FROM_ASCII
324QScriptValue::QScriptValue(QScriptEngine *engine, const char *val)
325 : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine)))
326{
327 if (engine) {
328 JSC::ExecState *exec = d_ptr->engine->currentFrame;
329 d_ptr->initFrom(JSC::jsString(exec, val));
330 } else {
331 d_ptr->initFrom(QString::fromAscii(val));
332 }
333}
334#endif
335
336/*!
337 \since 4.5
338
339 Constructs a new QScriptValue with a special \a value.
340*/
341QScriptValue::QScriptValue(SpecialValue value)
342 : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
343{
344 switch (value) {
345 case NullValue:
346 d_ptr->initFrom(JSC::jsNull());
347 break;
348 case UndefinedValue:
349 d_ptr->initFrom(JSC::jsUndefined());
350 break;
351 }
352}
353
354/*!
355 \since 4.5
356
357 Constructs a new QScriptValue with a boolean \a value.
358*/
359QScriptValue::QScriptValue(bool value)
360 : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
361{
362 d_ptr->initFrom(JSC::jsBoolean(value));
363}
364
365/*!
366 \since 4.5
367
368 Constructs a new QScriptValue with a number \a value.
369*/
370QScriptValue::QScriptValue(int value)
371 : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
372{
373 d_ptr->initFrom(value);
374}
375
376/*!
377 \since 4.5
378
379 Constructs a new QScriptValue with a number \a value.
380*/
381QScriptValue::QScriptValue(uint value)
382 : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
383{
384 d_ptr->initFrom(value);
385}
386
387/*!
388 \since 4.5
389
390 Constructs a new QScriptValue with a number \a value.
391*/
392QScriptValue::QScriptValue(qsreal value)
393 : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
394{
395 d_ptr->initFrom(value);
396}
397
398/*!
399 \since 4.5
400
401 Constructs a new QScriptValue with a string \a value.
402*/
403QScriptValue::QScriptValue(const QString &value)
404 : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
405{
406 d_ptr->initFrom(value);
407}
408
409/*!
410 \since 4.5
411
412 Constructs a new QScriptValue with a string \a value.
413*/
414QScriptValue::QScriptValue(const QLatin1String &value)
415 : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
416{
417 d_ptr->initFrom(value);
418}
419
420/*!
421 \since 4.5
422
423 Constructs a new QScriptValue with a string \a value.
424*/
425
426#ifndef QT_NO_CAST_FROM_ASCII
427QScriptValue::QScriptValue(const char *value)
428 : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0))
429{
430 d_ptr->initFrom(QString::fromAscii(value));
431}
432#endif
433
434/*!
435 Assigns the \a other value to this QScriptValue.
436
437 Note that if \a other is an object (isObject() returns true),
438 only a reference to the underlying object will be assigned;
439 the object itself will not be copied.
440*/
441QScriptValue &QScriptValue::operator=(const QScriptValue &other)
442{
443 d_ptr = other.d_ptr;
444 return *this;
445}
446
447/*!
448 Returns true if this QScriptValue is an object of the Error class;
449 otherwise returns false.
450
451 \sa QScriptContext::throwError()
452*/
453bool QScriptValue::isError() const
454{
455 Q_D(const QScriptValue);
456 if (!d || !d->isJSC())
457 return false;
458 return QScriptEnginePrivate::isError(d->jscValue);
459}
460
461/*!
462 Returns true if this QScriptValue is an object of the Array class;
463 otherwise returns false.
464
465 \sa QScriptEngine::newArray()
466*/
467bool QScriptValue::isArray() const
468{
469 Q_D(const QScriptValue);
470 if (!d || !d->isJSC())
471 return false;
472 return QScriptEnginePrivate::isArray(d->jscValue);
473}
474
475/*!
476 Returns true if this QScriptValue is an object of the Date class;
477 otherwise returns false.
478
479 \sa QScriptEngine::newDate()
480*/
481bool QScriptValue::isDate() const
482{
483 Q_D(const QScriptValue);
484 if (!d || !d->isJSC())
485 return false;
486 return QScriptEnginePrivate::isDate(d->jscValue);
487}
488
489/*!
490 Returns true if this QScriptValue is an object of the RegExp class;
491 otherwise returns false.
492
493 \sa QScriptEngine::newRegExp()
494*/
495bool QScriptValue::isRegExp() const
496{
497 Q_D(const QScriptValue);
498 if (!d || !d->isJSC())
499 return false;
500 return QScriptEnginePrivate::isRegExp(d->jscValue);
501}
502
503/*!
504 If this QScriptValue is an object, returns the internal prototype
505 (\c{__proto__} property) of this object; otherwise returns an
506 invalid QScriptValue.
507
508 \sa setPrototype(), isObject()
509*/
510QScriptValue QScriptValue::prototype() const
511{
512 Q_D(const QScriptValue);
513 if (!d || !d->isObject())
514 return QScriptValue();
515 return d->engine->scriptValueFromJSCValue(JSC::asObject(d->jscValue)->prototype());
516}
517
518/*!
519 If this QScriptValue is an object, sets the internal prototype
520 (\c{__proto__} property) of this object to be \a prototype;
521 otherwise does nothing.
522
523 The internal prototype should not be confused with the public
524 property with name "prototype"; the public prototype is usually
525 only set on functions that act as constructors.
526
527 \sa prototype(), isObject()
528*/
529void QScriptValue::setPrototype(const QScriptValue &prototype)
530{
531 Q_D(QScriptValue);
532 if (!d || !d->isObject())
533 return;
534 if (prototype.isValid() && QScriptValuePrivate::getEngine(prototype)
535 && (QScriptValuePrivate::getEngine(prototype) != d->engine)) {
536 qWarning("QScriptValue::setPrototype() failed: "
537 "cannot set a prototype created in "
538 "a different engine");
539 return;
540 }
541 JSC::JSObject *thisObject = JSC::asObject(d->jscValue);
542 JSC::JSValue other = d->engine->scriptValueToJSCValue(prototype);
543
544 // check for cycle
545 JSC::JSValue nextPrototypeValue = other;
546 while (nextPrototypeValue && nextPrototypeValue.isObject()) {
547 JSC::JSObject *nextPrototype = JSC::asObject(nextPrototypeValue);
548 if (nextPrototype == thisObject) {
549 qWarning("QScriptValue::setPrototype() failed: cyclic prototype value");
550 return;
551 }
552 nextPrototypeValue = nextPrototype->prototype();
553 }
554
555 thisObject->setPrototype(other);
556
557 // Sync the internal Global Object prototype if appropriate.
558 if (((thisObject == d->engine->originalGlobalObjectProxy)
559 && !d->engine->customGlobalObject())
560 || (thisObject == d->engine->customGlobalObject())) {
561 d->engine->originalGlobalObject()->setPrototype(other);
562 }
563}
564
565/*!
566 \internal
567*/
568QScriptValue QScriptValue::scope() const
569{
570 Q_D(const QScriptValue);
571 if (!d || !d->isObject())
572 return QScriptValue();
573 QScript::APIShim shim(d->engine);
574 // ### make hidden property
575 JSC::JSValue result = d->property("__qt_scope__", QScriptValue::ResolveLocal);
576 return d->engine->scriptValueFromJSCValue(result);
577}
578
579/*!
580 \internal
581*/
582void QScriptValue::setScope(const QScriptValue &scope)
583{
584 Q_D(QScriptValue);
585 if (!d || !d->isObject())
586 return;
587 if (scope.isValid() && QScriptValuePrivate::getEngine(scope)
588 && (QScriptValuePrivate::getEngine(scope) != d->engine)) {
589 qWarning("QScriptValue::setScope() failed: "
590 "cannot set a scope object created in "
591 "a different engine");
592 return;
593 }
594 JSC::JSValue other = d->engine->scriptValueToJSCValue(scope);
595 JSC::ExecState *exec = d->engine->currentFrame;
596 JSC::Identifier id = JSC::Identifier(exec, "__qt_scope__");
597 if (!scope.isValid()) {
598 JSC::asObject(d->jscValue)->removeDirect(id);
599 } else {
600 // ### make hidden property
601 JSC::asObject(d->jscValue)->putDirect(id, other);
602 }
603}
604
605/*!
606 Returns true if this QScriptValue is an instance of
607 \a other; otherwise returns false.
608
609 This QScriptValue is considered to be an instance of \a other if
610 \a other is a function and the value of the \c{prototype}
611 property of \a other is in the prototype chain of this
612 QScriptValue.
613*/
614bool QScriptValue::instanceOf(const QScriptValue &other) const
615{
616 Q_D(const QScriptValue);
617 if (!d || !d->isObject() || !other.isObject())
618 return false;
619 if (QScriptValuePrivate::getEngine(other) != d->engine) {
620 qWarning("QScriptValue::instanceof: "
621 "cannot perform operation on a value created in "
622 "a different engine");
623 return false;
624 }
625 JSC::JSValue jscProto = d->engine->scriptValueToJSCValue(other.property(QLatin1String("prototype")));
626 if (!jscProto)
627 jscProto = JSC::jsUndefined();
628 JSC::ExecState *exec = d->engine->currentFrame;
629 JSC::JSValue jscOther = d->engine->scriptValueToJSCValue(other);
630 return JSC::asObject(jscOther)->hasInstance(exec, d->jscValue, jscProto);
631}
632
633// ### move
634
635namespace QScript
636{
637
638enum Type {
639 Undefined,
640 Null,
641 Boolean,
642 String,
643 Number,
644 Object
645};
646
647static Type type(const QScriptValue &v)
648{
649 if (v.isUndefined())
650 return Undefined;
651 else if (v.isNull())
652 return Null;
653 else if (v.isBoolean())
654 return Boolean;
655 else if (v.isString())
656 return String;
657 else if (v.isNumber())
658 return Number;
659 Q_ASSERT(v.isObject());
660 return Object;
661}
662
663static QScriptValue ToPrimitive(const QScriptValue &object, JSC::PreferredPrimitiveType hint = JSC::NoPreference)
664{
665 Q_ASSERT(object.isObject());
666 QScriptValuePrivate *pp = QScriptValuePrivate::get(object);
667 Q_ASSERT(pp->engine != 0);
668 QScript::APIShim shim(pp->engine);
669 JSC::ExecState *exec = pp->engine->currentFrame;
670 JSC::JSValue savedException;
671 QScriptEnginePrivate::saveException(exec, &savedException);
672 JSC::JSValue result = JSC::asObject(pp->jscValue)->toPrimitive(exec, hint);
673 QScriptEnginePrivate::restoreException(exec, savedException);
674 return pp->engine->scriptValueFromJSCValue(result);
675}
676
677static bool IsNumerical(const QScriptValue &value)
678{
679 return value.isNumber() || value.isBool();
680}
681
682static bool LessThan(QScriptValue lhs, QScriptValue rhs)
683{
684 if (type(lhs) == type(rhs)) {
685 switch (type(lhs)) {
686 case Undefined:
687 case Null:
688 return false;
689
690 case Number:
691#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET
692 if (qIsNaN(lhs.toNumber()) || qIsNaN(rhs.toNumber()))
693 return false;
694#endif
695 return lhs.toNumber() < rhs.toNumber();
696
697 case Boolean:
698 return lhs.toBool() < rhs.toBool();
699
700 case String:
701 return lhs.toString() < rhs.toString();
702
703 case Object:
704 break;
705 } // switch
706 }
707
708 if (lhs.isObject())
709 lhs = ToPrimitive(lhs, JSC::PreferNumber);
710
711 if (rhs.isObject())
712 rhs = ToPrimitive(rhs, JSC::PreferNumber);
713
714 if (lhs.isString() && rhs.isString())
715 return lhs.toString() < rhs.toString();
716
717 qsreal n1 = lhs.toNumber();
718 qsreal n2 = rhs.toNumber();
719#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET
720 if (qIsNaN(n1) || qIsNaN(n2))
721 return false;
722#endif
723 return n1 < n2;
724}
725
726static bool Equals(QScriptValue lhs, QScriptValue rhs)
727{
728 if (type(lhs) == type(rhs)) {
729 switch (type(lhs)) {
730 case QScript::Undefined:
731 case QScript::Null:
732 return true;
733
734 case QScript::Number:
735 return lhs.toNumber() == rhs.toNumber();
736
737 case QScript::Boolean:
738 return lhs.toBool() == rhs.toBool();
739
740 case QScript::String:
741 return lhs.toString() == rhs.toString();
742
743 case QScript::Object:
744 if (lhs.isVariant())
745 return lhs.strictlyEquals(rhs) || (lhs.toVariant() == rhs.toVariant());
746#ifndef QT_NO_QOBJECT
747 else if (lhs.isQObject())
748 return (lhs.strictlyEquals(rhs)) || (lhs.toQObject() == rhs.toQObject());
749#endif
750 else
751 return lhs.strictlyEquals(rhs);
752 }
753 }
754
755 if (lhs.isNull() && rhs.isUndefined())
756 return true;
757
758 else if (lhs.isUndefined() && rhs.isNull())
759 return true;
760
761 else if (IsNumerical(lhs) && rhs.isString())
762 return lhs.toNumber() == rhs.toNumber();
763
764 else if (lhs.isString() && IsNumerical(rhs))
765 return lhs.toNumber() == rhs.toNumber();
766
767 else if (lhs.isBool())
768 return Equals(lhs.toNumber(), rhs);
769
770 else if (rhs.isBool())
771 return Equals(lhs, rhs.toNumber());
772
773 else if (lhs.isObject() && !rhs.isNull()) {
774 lhs = ToPrimitive(lhs);
775
776 if (lhs.isValid() && !lhs.isObject())
777 return Equals(lhs, rhs);
778 }
779
780 else if (rhs.isObject() && ! lhs.isNull()) {
781 rhs = ToPrimitive(rhs);
782 if (rhs.isValid() && !rhs.isObject())
783 return Equals(lhs, rhs);
784 }
785
786 return false;
787}
788
789} // namespace QScript
790
791/*!
792 Returns true if this QScriptValue is less than \a other, otherwise
793 returns false. The comparison follows the behavior described in
794 \l{ECMA-262} section 11.8.5, "The Abstract Relational Comparison
795 Algorithm".
796
797 Note that if this QScriptValue or the \a other value are objects,
798 calling this function has side effects on the script engine, since
799 the engine will call the object's valueOf() function (and possibly
800 toString()) in an attempt to convert the object to a primitive value
801 (possibly resulting in an uncaught script exception).
802
803 \sa equals()
804*/
805bool QScriptValue::lessThan(const QScriptValue &other) const
806{
807 Q_D(const QScriptValue);
808 // no equivalent function in JSC? There's a jsLess() in VM/Machine.cpp
809 if (!isValid() || !other.isValid())
810 return false;
811 if (QScriptValuePrivate::getEngine(other) && d->engine
812 && (QScriptValuePrivate::getEngine(other) != d->engine)) {
813 qWarning("QScriptValue::lessThan: "
814 "cannot compare to a value created in "
815 "a different engine");
816 return false;
817 }
818 return QScript::LessThan(*this, other);
819}
820
821/*!
822 Returns true if this QScriptValue is equal to \a other, otherwise
823 returns false. The comparison follows the behavior described in
824 \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison
825 Algorithm".
826
827 This function can return true even if the type of this QScriptValue
828 is different from the type of the \a other value; i.e. the
829 comparison is not strict. For example, comparing the number 9 to
830 the string "9" returns true; comparing an undefined value to a null
831 value returns true; comparing a \c{Number} object whose primitive
832 value is 6 to a \c{String} object whose primitive value is "6"
833 returns true; and comparing the number 1 to the boolean value
834 \c{true} returns true. If you want to perform a comparison
835 without such implicit value conversion, use strictlyEquals().
836
837 Note that if this QScriptValue or the \a other value are objects,
838 calling this function has side effects on the script engine, since
839 the engine will call the object's valueOf() function (and possibly
840 toString()) in an attempt to convert the object to a primitive value
841 (possibly resulting in an uncaught script exception).
842
843 \sa strictlyEquals(), lessThan()
844*/
845bool QScriptValue::equals(const QScriptValue &other) const
846{
847 Q_D(const QScriptValue);
848 if (!d || !other.d_ptr)
849 return (d_ptr == other.d_ptr);
850 if (QScriptValuePrivate::getEngine(other) && d->engine
851 && (QScriptValuePrivate::getEngine(other) != d->engine)) {
852 qWarning("QScriptValue::equals: "
853 "cannot compare to a value created in "
854 "a different engine");
855 return false;
856 }
857 if (d->isJSC() && other.d_ptr->isJSC()) {
858 QScriptEnginePrivate *eng_p = d->engine;
859 if (!eng_p)
860 eng_p = other.d_ptr->engine;
861 if (eng_p) {
862 QScript::APIShim shim(eng_p);
863 JSC::ExecState *exec = eng_p->currentFrame;
864 JSC::JSValue savedException;
865 QScriptEnginePrivate::saveException(exec, &savedException);
866 bool result = JSC::JSValue::equal(exec, d->jscValue, other.d_ptr->jscValue);
867 QScriptEnginePrivate::restoreException(exec, savedException);
868 return result;
869 }
870 }
871 return QScript::Equals(*this, other);
872}
873
874/*!
875 Returns true if this QScriptValue is equal to \a other using strict
876 comparison (no conversion), otherwise returns false. The comparison
877 follows the behavior described in \l{ECMA-262} section 11.9.6, "The
878 Strict Equality Comparison Algorithm".
879
880 If the type of this QScriptValue is different from the type of the
881 \a other value, this function returns false. If the types are equal,
882 the result depends on the type, as shown in the following table:
883
884 \table
885 \header \o Type \o Result
886 \row \o Undefined \o true
887 \row \o Null \o true
888 \row \o Boolean \o true if both values are true, false otherwise
889 \row \o Number \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise
890 \row \o String \o true if both values are exactly the same sequence of characters, false otherwise
891 \row \o Object \o true if both values refer to the same object, false otherwise
892 \endtable
893
894 \sa equals()
895*/
896bool QScriptValue::strictlyEquals(const QScriptValue &other) const
897{
898 Q_D(const QScriptValue);
899 if (!d || !other.d_ptr)
900 return (d_ptr == other.d_ptr);
901 if (QScriptValuePrivate::getEngine(other) && d->engine
902 && (QScriptValuePrivate::getEngine(other) != d->engine)) {
903 qWarning("QScriptValue::strictlyEquals: "
904 "cannot compare to a value created in "
905 "a different engine");
906 return false;
907 }
908
909 if (d->type != other.d_ptr->type) {
910 if (d->type == QScriptValuePrivate::JavaScriptCore) {
911 QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine;
912 if (eng_p)
913 return JSC::JSValue::strictEqual(eng_p->currentFrame, d->jscValue, eng_p->scriptValueToJSCValue(other));
914 } else if (other.d_ptr->type == QScriptValuePrivate::JavaScriptCore) {
915 QScriptEnginePrivate *eng_p = other.d_ptr->engine ? other.d_ptr->engine : d->engine;
916 if (eng_p)
917 return JSC::JSValue::strictEqual(eng_p->currentFrame, eng_p->scriptValueToJSCValue(*this), other.d_ptr->jscValue);
918 }
919
920 return false;
921 }
922 switch (d->type) {
923 case QScriptValuePrivate::JavaScriptCore: {
924 QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine;
925 JSC::ExecState *exec = eng_p ? eng_p->currentFrame : 0;
926 return JSC::JSValue::strictEqual(exec, d->jscValue, other.d_ptr->jscValue);
927 }
928 case QScriptValuePrivate::Number:
929 return (d->numberValue == other.d_ptr->numberValue);
930 case QScriptValuePrivate::String:
931 return (d->stringValue == other.d_ptr->stringValue);
932 }
933 return false;
934}
935
936/*!
937 Returns the string value of this QScriptValue, as defined in
938 \l{ECMA-262} section 9.8, "ToString".
939
940 Note that if this QScriptValue is an object, calling this function
941 has side effects on the script engine, since the engine will call
942 the object's toString() function (and possibly valueOf()) in an
943 attempt to convert the object to a primitive value (possibly
944 resulting in an uncaught script exception).
945
946 \sa isString()
947*/
948QString QScriptValue::toString() const
949{
950 Q_D(const QScriptValue);
951 if (!d)
952 return QString();
953 switch (d->type) {
954 case QScriptValuePrivate::JavaScriptCore: {
955 if (d->engine) {
956 QScript::APIShim shim(d->engine);
957 return QScriptEnginePrivate::toString(d->engine->currentFrame, d->jscValue);
958 } else {
959 return QScriptEnginePrivate::toString(0, d->jscValue);
960 } }
961 case QScriptValuePrivate::Number:
962 return QScript::ToString(d->numberValue);
963 case QScriptValuePrivate::String:
964 return d->stringValue;
965 }
966 return QString();
967}
968
969/*!
970 Returns the number value of this QScriptValue, as defined in
971 \l{ECMA-262} section 9.3, "ToNumber".
972
973 Note that if this QScriptValue is an object, calling this function
974 has side effects on the script engine, since the engine will call
975 the object's valueOf() function (and possibly toString()) in an
976 attempt to convert the object to a primitive value (possibly
977 resulting in an uncaught script exception).
978
979 \sa isNumber(), toInteger(), toInt32(), toUInt32(), toUInt16()
980*/
981qsreal QScriptValue::toNumber() const
982{
983 Q_D(const QScriptValue);
984 if (!d)
985 return 0;
986 switch (d->type) {
987 case QScriptValuePrivate::JavaScriptCore: {
988 if (d->engine) {
989 QScript::APIShim shim(d->engine);
990 return QScriptEnginePrivate::toNumber(d->engine->currentFrame, d->jscValue);
991 } else {
992 return QScriptEnginePrivate::toNumber(0, d->jscValue);
993 }
994 }
995 case QScriptValuePrivate::Number:
996 return d->numberValue;
997 case QScriptValuePrivate::String:
998 return QScript::ToNumber(d->stringValue);
999 }
1000 return 0;
1001}
1002
1003/*!
1004 \obsolete
1005
1006 Use toBool() instead.
1007*/
1008bool QScriptValue::toBoolean() const
1009{
1010 Q_D(const QScriptValue);
1011 if (!d)
1012 return false;
1013 switch (d->type) {
1014 case QScriptValuePrivate::JavaScriptCore: {
1015 if (d->engine) {
1016 QScript::APIShim shim(d->engine);
1017 return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue);
1018 } else {
1019 return QScriptEnginePrivate::toBool(0, d->jscValue);
1020 }
1021 }
1022 case QScriptValuePrivate::Number:
1023 return QScript::ToBool(d->numberValue);
1024 case QScriptValuePrivate::String:
1025 return QScript::ToBool(d->stringValue);
1026 }
1027 return false;
1028}
1029
1030/*!
1031 \since 4.5
1032
1033 Returns the boolean value of this QScriptValue, using the conversion
1034 rules described in \l{ECMA-262} section 9.2, "ToBoolean".
1035
1036 Note that if this QScriptValue is an object, calling this function
1037 has side effects on the script engine, since the engine will call
1038 the object's valueOf() function (and possibly toString()) in an
1039 attempt to convert the object to a primitive value (possibly
1040 resulting in an uncaught script exception).
1041
1042 \sa isBool()
1043*/
1044bool QScriptValue::toBool() const
1045{
1046 Q_D(const QScriptValue);
1047 if (!d)
1048 return false;
1049 switch (d->type) {
1050 case QScriptValuePrivate::JavaScriptCore: {
1051 if (d->engine) {
1052 QScript::APIShim shim(d->engine);
1053 return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue);
1054 } else {
1055 return QScriptEnginePrivate::toBool(0, d->jscValue);
1056 }
1057 }
1058 case QScriptValuePrivate::Number:
1059 return QScript::ToBool(d->numberValue);
1060 case QScriptValuePrivate::String:
1061 return QScript::ToBool(d->stringValue);
1062 }
1063 return false;
1064}
1065
1066/*!
1067 Returns the signed 32-bit integer value of this QScriptValue, using
1068 the conversion rules described in \l{ECMA-262} section 9.5, "ToInt32".
1069
1070 Note that if this QScriptValue is an object, calling this function
1071 has side effects on the script engine, since the engine will call
1072 the object's valueOf() function (and possibly toString()) in an
1073 attempt to convert the object to a primitive value (possibly
1074 resulting in an uncaught script exception).
1075
1076 \sa toNumber(), toUInt32()
1077*/
1078qint32 QScriptValue::toInt32() const
1079{
1080 Q_D(const QScriptValue);
1081 if (!d)
1082 return 0;
1083 switch (d->type) {
1084 case QScriptValuePrivate::JavaScriptCore: {
1085 if (d->engine) {
1086 QScript::APIShim shim(d->engine);
1087 return QScriptEnginePrivate::toInt32(d->engine->currentFrame, d->jscValue);
1088 } else {
1089 return QScriptEnginePrivate::toInt32(0, d->jscValue);
1090 }
1091 }
1092 case QScriptValuePrivate::Number:
1093 return QScript::ToInt32(d->numberValue);
1094 case QScriptValuePrivate::String:
1095 return QScript::ToInt32(d->stringValue);
1096 }
1097 return 0;
1098}
1099
1100/*!
1101 Returns the unsigned 32-bit integer value of this QScriptValue, using
1102 the conversion rules described in \l{ECMA-262} section 9.6, "ToUint32".
1103
1104 Note that if this QScriptValue is an object, calling this function
1105 has side effects on the script engine, since the engine will call
1106 the object's valueOf() function (and possibly toString()) in an
1107 attempt to convert the object to a primitive value (possibly
1108 resulting in an uncaught script exception).
1109
1110 \sa toNumber(), toInt32()
1111*/
1112quint32 QScriptValue::toUInt32() const
1113{
1114 Q_D(const QScriptValue);
1115 if (!d)
1116 return 0;
1117 switch (d->type) {
1118 case QScriptValuePrivate::JavaScriptCore: {
1119 if (d->engine) {
1120 QScript::APIShim shim(d->engine);
1121 return QScriptEnginePrivate::toUInt32(d->engine->currentFrame, d->jscValue);
1122 } else {
1123 return QScriptEnginePrivate::toUInt32(0, d->jscValue);
1124 }
1125 }
1126 case QScriptValuePrivate::Number:
1127 return QScript::ToUInt32(d->numberValue);
1128 case QScriptValuePrivate::String:
1129 return QScript::ToUInt32(d->stringValue);
1130 }
1131 return 0;
1132}
1133
1134/*!
1135 Returns the unsigned 16-bit integer value of this QScriptValue, using
1136 the conversion rules described in \l{ECMA-262} section 9.7, "ToUint16".
1137
1138 Note that if this QScriptValue is an object, calling this function
1139 has side effects on the script engine, since the engine will call
1140 the object's valueOf() function (and possibly toString()) in an
1141 attempt to convert the object to a primitive value (possibly
1142 resulting in an uncaught script exception).
1143
1144 \sa toNumber()
1145*/
1146quint16 QScriptValue::toUInt16() const
1147{
1148 Q_D(const QScriptValue);
1149 if (!d)
1150 return 0;
1151 switch (d->type) {
1152 case QScriptValuePrivate::JavaScriptCore: {
1153 if (d->engine) {
1154 QScript::APIShim shim(d->engine);
1155 return QScriptEnginePrivate::toUInt16(d->engine->currentFrame, d->jscValue);
1156 } else {
1157 return QScriptEnginePrivate::toUInt16(0, d->jscValue);
1158 }
1159 }
1160 case QScriptValuePrivate::Number:
1161 return QScript::ToUInt16(d->numberValue);
1162 case QScriptValuePrivate::String:
1163 return QScript::ToUInt16(d->stringValue);
1164 }
1165 return 0;
1166}
1167
1168/*!
1169 Returns the integer value of this QScriptValue, using the conversion
1170 rules described in \l{ECMA-262} section 9.4, "ToInteger".
1171
1172 Note that if this QScriptValue is an object, calling this function
1173 has side effects on the script engine, since the engine will call
1174 the object's valueOf() function (and possibly toString()) in an
1175 attempt to convert the object to a primitive value (possibly
1176 resulting in an uncaught script exception).
1177
1178 \sa toNumber()
1179*/
1180qsreal QScriptValue::toInteger() const
1181{
1182 Q_D(const QScriptValue);
1183 if (!d)
1184 return 0;
1185 switch (d->type) {
1186 case QScriptValuePrivate::JavaScriptCore: {
1187 if (d->engine) {
1188 QScript::APIShim shim(d->engine);
1189 return QScriptEnginePrivate::toInteger(d->engine->currentFrame, d->jscValue);
1190 } else {
1191 return QScriptEnginePrivate::toInteger(0, d->jscValue);
1192 }
1193 }
1194 case QScriptValuePrivate::Number:
1195 return QScript::ToInteger(d->numberValue);
1196 case QScriptValuePrivate::String:
1197 return QScript::ToInteger(d->stringValue);
1198 }
1199 return 0;
1200}
1201
1202/*!
1203 Returns the QVariant value of this QScriptValue, if it can be
1204 converted to a QVariant; otherwise returns an invalid QVariant.
1205 The conversion is performed according to the following table:
1206
1207 \table
1208 \header \o Input Type \o Result
1209 \row \o Undefined \o An invalid QVariant.
1210 \row \o Null \o An invalid QVariant.
1211 \row \o Boolean \o A QVariant containing the value of the boolean.
1212 \row \o Number \o A QVariant containing the value of the number.
1213 \row \o String \o A QVariant containing the value of the string.
1214 \row \o QVariant Object \o The result is the QVariant value of the object (no conversion).
1215 \row \o QObject Object \o A QVariant containing a pointer to the QObject.
1216 \row \o Date Object \o A QVariant containing the date value (toDateTime()).
1217 \row \o RegExp Object \o A QVariant containing the regular expression value (toRegExp()).
1218 \row \o Array Object \o The array is converted to a QVariantList. Each element is converted to a QVariant, recursively; cyclic references are not followed.
1219 \row \o Object \o The object is converted to a QVariantMap. Each property is converted to a QVariant, recursively; cyclic references are not followed.
1220 \endtable
1221
1222 \sa isVariant()
1223*/
1224QVariant QScriptValue::toVariant() const
1225{
1226 Q_D(const QScriptValue);
1227 if (!d)
1228 return QVariant();
1229 switch (d->type) {
1230 case QScriptValuePrivate::JavaScriptCore: {
1231 if (d->engine) {
1232 QScript::APIShim shim(d->engine);
1233 return QScriptEnginePrivate::toVariant(d->engine->currentFrame, d->jscValue);
1234 } else {
1235 return QScriptEnginePrivate::toVariant(0, d->jscValue);
1236 }
1237 }
1238 case QScriptValuePrivate::Number:
1239 return QVariant(d->numberValue);
1240 case QScriptValuePrivate::String:
1241 return QVariant(d->stringValue);
1242 }
1243 return QVariant();
1244}
1245
1246/*!
1247 \obsolete
1248
1249 This function is obsolete; use QScriptEngine::toObject() instead.
1250*/
1251QScriptValue QScriptValue::toObject() const
1252{
1253 Q_D(const QScriptValue);
1254 if (!d || !d->engine)
1255 return QScriptValue();
1256 return engine()->toObject(*this);
1257}
1258
1259/*!
1260 Returns a QDateTime representation of this value, in local time.
1261 If this QScriptValue is not a date, or the value of the date is NaN
1262 (Not-a-Number), an invalid QDateTime is returned.
1263
1264 \sa isDate()
1265*/
1266QDateTime QScriptValue::toDateTime() const
1267{
1268 Q_D(const QScriptValue);
1269 if (!d || !d->engine)
1270 return QDateTime();
1271 QScript::APIShim shim(d->engine);
1272 return QScriptEnginePrivate::toDateTime(d->engine->currentFrame, d->jscValue);
1273}
1274
1275#ifndef QT_NO_REGEXP
1276/*!
1277 Returns the QRegExp representation of this value.
1278 If this QScriptValue is not a regular expression, an empty
1279 QRegExp is returned.
1280
1281 \sa isRegExp()
1282*/
1283QRegExp QScriptValue::toRegExp() const
1284{
1285 Q_D(const QScriptValue);
1286 if (!d || !d->engine)
1287 return QRegExp();
1288 QScript::APIShim shim(d->engine);
1289 return QScriptEnginePrivate::toRegExp(d->engine->currentFrame, d->jscValue);
1290}
1291#endif // QT_NO_REGEXP
1292
1293/*!
1294 If this QScriptValue is a QObject, returns the QObject pointer
1295 that the QScriptValue represents; otherwise, returns 0.
1296
1297 If the QObject that this QScriptValue wraps has been deleted,
1298 this function returns 0 (i.e. it is possible for toQObject()
1299 to return 0 even when isQObject() returns true).
1300
1301 \sa isQObject()
1302*/
1303QObject *QScriptValue::toQObject() const
1304{
1305 Q_D(const QScriptValue);
1306 if (!d || !d->engine)
1307 return 0;
1308 QScript::APIShim shim(d->engine);
1309 return QScriptEnginePrivate::toQObject(d->engine->currentFrame, d->jscValue);
1310}
1311
1312/*!
1313 If this QScriptValue is a QMetaObject, returns the QMetaObject pointer
1314 that the QScriptValue represents; otherwise, returns 0.
1315
1316 \sa isQMetaObject()
1317*/
1318const QMetaObject *QScriptValue::toQMetaObject() const
1319{
1320 Q_D(const QScriptValue);
1321 if (!d || !d->engine)
1322 return 0;
1323 QScript::APIShim shim(d->engine);
1324 return QScriptEnginePrivate::toQMetaObject(d->engine->currentFrame, d->jscValue);
1325}
1326
1327/*!
1328 Sets the value of this QScriptValue's property with the given \a name to
1329 the given \a value.
1330
1331 If this QScriptValue is not an object, this function does nothing.
1332
1333 If this QScriptValue does not already have a property with name \a name,
1334 a new property is created; the given \a flags then specify how this
1335 property may be accessed by script code.
1336
1337 If \a value is invalid, the property is removed.
1338
1339 If the property is implemented using a setter function (i.e. has the
1340 PropertySetter flag set), calling setProperty() has side-effects on
1341 the script engine, since the setter function will be called with the
1342 given \a value as argument (possibly resulting in an uncaught script
1343 exception).
1344
1345 Note that you cannot specify custom getter or setter functions for
1346 built-in properties, such as the \c{length} property of Array objects
1347 or meta properties of QObject objects.
1348
1349 \sa property()
1350*/
1351
1352void QScriptValue::setProperty(const QString &name, const QScriptValue &value,
1353 const PropertyFlags &flags)
1354{
1355 Q_D(QScriptValue);
1356 if (!d || !d->isObject())
1357 return;
1358 QScript::APIShim shim(d->engine);
1359 QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value);
1360 if (valueEngine && (valueEngine != d->engine)) {
1361 qWarning("QScriptValue::setProperty(%s) failed: "
1362 "cannot set value created in a different engine",
1363 qPrintable(name));
1364 return;
1365 }
1366 JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
1367 d->setProperty(name, jsValue, flags);
1368}
1369
1370/*!
1371 Returns the value of this QScriptValue's property with the given \a name,
1372 using the given \a mode to resolve the property.
1373
1374 If no such property exists, an invalid QScriptValue is returned.
1375
1376 If the property is implemented using a getter function (i.e. has the
1377 PropertyGetter flag set), calling property() has side-effects on the
1378 script engine, since the getter function will be called (possibly
1379 resulting in an uncaught script exception). If an exception
1380 occurred, property() returns the value that was thrown (typically
1381 an \c{Error} object).
1382
1383 \sa setProperty(), propertyFlags(), QScriptValueIterator
1384*/
1385QScriptValue QScriptValue::property(const QString &name,
1386 const ResolveFlags &mode) const
1387{
1388 Q_D(const QScriptValue);
1389 if (!d || !d->isObject())
1390 return QScriptValue();
1391 QScript::APIShim shim(d->engine);
1392 return d->engine->scriptValueFromJSCValue(d->property(name, mode));
1393}
1394
1395/*!
1396 \overload
1397
1398 Returns the property at the given \a arrayIndex, using the given \a
1399 mode to resolve the property.
1400
1401 This function is provided for convenience and performance when
1402 working with array objects.
1403
1404 If this QScriptValue is not an Array object, this function behaves
1405 as if property() was called with the string representation of \a
1406 arrayIndex.
1407*/
1408QScriptValue QScriptValue::property(quint32 arrayIndex,
1409 const ResolveFlags &mode) const
1410{
1411 Q_D(const QScriptValue);
1412 if (!d || !d->isObject())
1413 return QScriptValue();
1414 QScript::APIShim shim(d->engine);
1415 return d->engine->scriptValueFromJSCValue(d->property(arrayIndex, mode));
1416}
1417
1418/*!
1419 \overload
1420
1421 Sets the property at the given \a arrayIndex to the given \a value.
1422
1423 This function is provided for convenience and performance when
1424 working with array objects.
1425
1426 If this QScriptValue is not an Array object, this function behaves
1427 as if setProperty() was called with the string representation of \a
1428 arrayIndex.
1429*/
1430void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue &value,
1431 const PropertyFlags &flags)
1432{
1433 Q_D(QScriptValue);
1434 if (!d || !d->isObject())
1435 return;
1436 if (QScriptValuePrivate::getEngine(value)
1437 && (QScriptValuePrivate::getEngine(value) != d->engine)) {
1438 qWarning("QScriptValue::setProperty() failed: "
1439 "cannot set value created in a different engine");
1440 return;
1441 }
1442 QScript::APIShim shim(d->engine);
1443 JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
1444 d->setProperty(arrayIndex, jsValue, flags);
1445}
1446
1447/*!
1448 \since 4.4
1449
1450 Returns the value of this QScriptValue's property with the given \a name,
1451 using the given \a mode to resolve the property.
1452
1453 This overload of property() is useful when you need to look up the
1454 same property repeatedly, since the lookup can be performed faster
1455 when the name is represented as an interned string.
1456
1457 \sa QScriptEngine::toStringHandle(), setProperty()
1458*/
1459QScriptValue QScriptValue::property(const QScriptString &name,
1460 const ResolveFlags &mode) const
1461{
1462 Q_D(const QScriptValue);
1463 if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
1464 return QScriptValue();
1465 QScript::APIShim shim(d->engine);
1466 return d->engine->scriptValueFromJSCValue(d->property(name.d_ptr->identifier, mode));
1467}
1468
1469/*!
1470 \since 4.4
1471
1472 Sets the value of this QScriptValue's property with the given \a
1473 name to the given \a value. The given \a flags specify how this
1474 property may be accessed by script code.
1475
1476 This overload of setProperty() is useful when you need to set the
1477 same property repeatedly, since the operation can be performed
1478 faster when the name is represented as an interned string.
1479
1480 \sa QScriptEngine::toStringHandle()
1481*/
1482void QScriptValue::setProperty(const QScriptString &name,
1483 const QScriptValue &value,
1484 const PropertyFlags &flags)
1485{
1486 Q_D(QScriptValue);
1487 if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
1488 return;
1489 QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value);
1490 if (valueEngine && (valueEngine != d->engine)) {
1491 qWarning("QScriptValue::setProperty(%s) failed: "
1492 "cannot set value created in a different engine",
1493 qPrintable(name.toString()));
1494 return;
1495 }
1496 QScript::APIShim shim(d->engine);
1497 JSC::JSValue jsValue = d->engine->scriptValueToJSCValue(value);
1498 d->setProperty(name.d_ptr->identifier, jsValue, flags);
1499}
1500
1501/*!
1502 Returns the flags of the property with the given \a name, using the
1503 given \a mode to resolve the property.
1504
1505 \sa property()
1506*/
1507QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString &name,
1508 const ResolveFlags &mode) const
1509{
1510 Q_D(const QScriptValue);
1511 if (!d || !d->isObject())
1512 return 0;
1513 QScript::APIShim shim(d->engine);
1514 JSC::ExecState *exec = d->engine->currentFrame;
1515 return d->propertyFlags(JSC::Identifier(exec, name), mode);
1516
1517}
1518
1519/*!
1520 \since 4.4
1521
1522 Returns the flags of the property with the given \a name, using the
1523 given \a mode to resolve the property.
1524
1525 \sa property()
1526*/
1527QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString &name,
1528 const ResolveFlags &mode) const
1529{
1530 Q_D(const QScriptValue);
1531 if (!d || !d->isObject() || !QScriptStringPrivate::isValid(name))
1532 return 0;
1533 return d->propertyFlags(name.d_ptr->identifier, mode);
1534}
1535
1536/*!
1537 Calls this QScriptValue as a function, using \a thisObject as
1538 the `this' object in the function call, and passing \a args
1539 as arguments to the function. Returns the value returned from
1540 the function.
1541
1542 If this QScriptValue is not a function, call() does nothing
1543 and returns an invalid QScriptValue.
1544
1545 Note that if \a thisObject is not an object, the global object
1546 (see \l{QScriptEngine::globalObject()}) will be used as the
1547 `this' object.
1548
1549 Calling call() can cause an exception to occur in the script engine;
1550 in that case, call() returns the value that was thrown (typically an
1551 \c{Error} object). You can call
1552 QScriptEngine::hasUncaughtException() to determine if an exception
1553 occurred.
1554
1555 \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2
1556
1557 \sa construct()
1558*/
1559QScriptValue QScriptValue::call(const QScriptValue &thisObject,
1560 const QScriptValueList &args)
1561{
1562 Q_D(const QScriptValue);
1563 if (!d || !d->isObject())
1564 return QScriptValue();
1565 QScript::APIShim shim(d->engine);
1566 JSC::JSValue callee = d->jscValue;
1567 JSC::CallData callData;
1568 JSC::CallType callType = callee.getCallData(callData);
1569 if (callType == JSC::CallTypeNone)
1570 return QScriptValue();
1571
1572 if (QScriptValuePrivate::getEngine(thisObject)
1573 && (QScriptValuePrivate::getEngine(thisObject) != d->engine)) {
1574 qWarning("QScriptValue::call() failed: "
1575 "cannot call function with thisObject created in "
1576 "a different engine");
1577 return QScriptValue();
1578 }
1579
1580 JSC::ExecState *exec = d->engine->currentFrame;
1581
1582 JSC::JSValue jscThisObject = d->engine->scriptValueToJSCValue(thisObject);
1583 if (!jscThisObject || !jscThisObject.isObject())
1584 jscThisObject = d->engine->globalObject();
1585
1586 QVarLengthArray<JSC::JSValue, 8> argsVector(args.size());
1587 for (int i = 0; i < args.size(); ++i) {
1588 const QScriptValue &arg = args.at(i);
1589 if (!arg.isValid()) {
1590 argsVector[i] = JSC::jsUndefined();
1591 } else if (QScriptValuePrivate::getEngine(arg)
1592 && (QScriptValuePrivate::getEngine(arg) != d->engine)) {
1593 qWarning("QScriptValue::call() failed: "
1594 "cannot call function with argument created in "
1595 "a different engine");
1596 return QScriptValue();
1597 } else {
1598 argsVector[i] = d->engine->scriptValueToJSCValue(arg);
1599 }
1600 }
1601 JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
1602
1603 JSC::JSValue savedException;
1604 QScriptEnginePrivate::saveException(exec, &savedException);
1605 JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, jscArgs);
1606 if (exec->hadException()) {
1607 result = exec->exception();
1608 } else {
1609 QScriptEnginePrivate::restoreException(exec, savedException);
1610 }
1611 return d->engine->scriptValueFromJSCValue(result);
1612}
1613
1614/*!
1615 Calls this QScriptValue as a function, using \a thisObject as
1616 the `this' object in the function call, and passing \a arguments
1617 as arguments to the function. Returns the value returned from
1618 the function.
1619
1620 If this QScriptValue is not a function, call() does nothing
1621 and returns an invalid QScriptValue.
1622
1623 \a arguments can be an arguments object, an array, null or
1624 undefined; any other type will cause a TypeError to be thrown.
1625
1626 Note that if \a thisObject is not an object, the global object
1627 (see \l{QScriptEngine::globalObject()}) will be used as the
1628 `this' object.
1629
1630 One common usage of this function is to forward native function
1631 calls to another function:
1632
1633 \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 3
1634
1635 \sa construct(), QScriptContext::argumentsObject()
1636*/
1637QScriptValue QScriptValue::call(const QScriptValue &thisObject,
1638 const QScriptValue &arguments)
1639{
1640 Q_D(QScriptValue);
1641 if (!d || !d->isObject())
1642 return QScriptValue();
1643 QScript::APIShim shim(d->engine);
1644 JSC::JSValue callee = d->jscValue;
1645 JSC::CallData callData;
1646 JSC::CallType callType = callee.getCallData(callData);
1647 if (callType == JSC::CallTypeNone)
1648 return QScriptValue();
1649
1650 if (QScriptValuePrivate::getEngine(thisObject)
1651 && (QScriptValuePrivate::getEngine(thisObject) != d->engine)) {
1652 qWarning("QScriptValue::call() failed: "
1653 "cannot call function with thisObject created in "
1654 "a different engine");
1655 return QScriptValue();
1656 }
1657
1658 JSC::ExecState *exec = d->engine->currentFrame;
1659
1660 JSC::JSValue jscThisObject = d->engine->scriptValueToJSCValue(thisObject);
1661 if (!jscThisObject || !jscThisObject.isObject())
1662 jscThisObject = d->engine->globalObject();
1663
1664 JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments);
1665 // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply()
1666 JSC::MarkedArgumentBuffer applyArgs;
1667 if (!array.isUndefinedOrNull()) {
1668 if (!array.isObject()) {
1669 return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
1670 }
1671 if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info)
1672 JSC::asArguments(array)->fillArgList(exec, applyArgs);
1673 else if (JSC::isJSArray(&exec->globalData(), array))
1674 JSC::asArray(array)->fillArgList(exec, applyArgs);
1675 else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) {
1676 unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
1677 for (unsigned i = 0; i < length; ++i)
1678 applyArgs.append(JSC::asArray(array)->get(exec, i));
1679 } else {
1680 return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
1681 }
1682 }
1683
1684 JSC::JSValue savedException;
1685 QScriptEnginePrivate::saveException(exec, &savedException);
1686 JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, applyArgs);
1687 if (exec->hadException()) {
1688 result = exec->exception();
1689 } else {
1690 QScriptEnginePrivate::restoreException(exec, savedException);
1691 }
1692 return d->engine->scriptValueFromJSCValue(result);
1693}
1694
1695/*!
1696 Creates a new \c{Object} and calls this QScriptValue as a
1697 constructor, using the created object as the `this' object and
1698 passing \a args as arguments. If the return value from the
1699 constructor call is an object, then that object is returned;
1700 otherwise the default constructed object is returned.
1701
1702 If this QScriptValue is not a function, construct() does nothing
1703 and returns an invalid QScriptValue.
1704
1705 Calling construct() can cause an exception to occur in the script
1706 engine; in that case, construct() returns the value that was thrown
1707 (typically an \c{Error} object). You can call
1708 QScriptEngine::hasUncaughtException() to determine if an exception
1709 occurred.
1710
1711 \sa call(), QScriptEngine::newObject()
1712*/
1713QScriptValue QScriptValue::construct(const QScriptValueList &args)
1714{
1715 Q_D(const QScriptValue);
1716 if (!d || !d->isObject())
1717 return QScriptValue();
1718 QScript::APIShim shim(d->engine);
1719 JSC::JSValue callee = d->jscValue;
1720 JSC::ConstructData constructData;
1721 JSC::ConstructType constructType = callee.getConstructData(constructData);
1722 if (constructType == JSC::ConstructTypeNone)
1723 return QScriptValue();
1724
1725 JSC::ExecState *exec = d->engine->currentFrame;
1726
1727 QVarLengthArray<JSC::JSValue, 8> argsVector(args.size());
1728 for (int i = 0; i < args.size(); ++i) {
1729 if (!args.at(i).isValid())
1730 argsVector[i] = JSC::jsUndefined();
1731 else
1732 argsVector[i] = d->engine->scriptValueToJSCValue(args.at(i));
1733 }
1734
1735 JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
1736
1737 JSC::JSValue savedException;
1738 QScriptEnginePrivate::saveException(exec, &savedException);
1739 JSC::JSValue result;
1740 JSC::JSObject *newObject = JSC::construct(exec, callee, constructType, constructData, jscArgs);
1741 if (exec->hadException()) {
1742 result = exec->exception();
1743 } else {
1744 result = newObject;
1745 QScriptEnginePrivate::restoreException(exec, savedException);
1746 }
1747 return d->engine->scriptValueFromJSCValue(result);
1748}
1749
1750/*!
1751 Creates a new \c{Object} and calls this QScriptValue as a
1752 constructor, using the created object as the `this' object and
1753 passing \a arguments as arguments. If the return value from the
1754 constructor call is an object, then that object is returned;
1755 otherwise the default constructed object is returned.
1756
1757 If this QScriptValue is not a function, construct() does nothing
1758 and returns an invalid QScriptValue.
1759
1760 \a arguments can be an arguments object, an array, null or
1761 undefined. Any other type will cause a TypeError to be thrown.
1762
1763 \sa call(), QScriptEngine::newObject(), QScriptContext::argumentsObject()
1764*/
1765QScriptValue QScriptValue::construct(const QScriptValue &arguments)
1766{
1767 Q_D(QScriptValue);
1768 if (!d || !d->isObject())
1769 return QScriptValue();
1770 QScript::APIShim shim(d->engine);
1771 JSC::JSValue callee = d->jscValue;
1772 JSC::ConstructData constructData;
1773 JSC::ConstructType constructType = callee.getConstructData(constructData);
1774 if (constructType == JSC::ConstructTypeNone)
1775 return QScriptValue();
1776
1777 JSC::ExecState *exec = d->engine->currentFrame;
1778
1779 JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments);
1780 // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply()
1781 JSC::MarkedArgumentBuffer applyArgs;
1782 if (!array.isUndefinedOrNull()) {
1783 if (!array.isObject()) {
1784 return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
1785 }
1786 if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info)
1787 JSC::asArguments(array)->fillArgList(exec, applyArgs);
1788 else if (JSC::isJSArray(&exec->globalData(), array))
1789 JSC::asArray(array)->fillArgList(exec, applyArgs);
1790 else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) {
1791 unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
1792 for (unsigned i = 0; i < length; ++i)
1793 applyArgs.append(JSC::asArray(array)->get(exec, i));
1794 } else {
1795 return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array"));
1796 }
1797 }
1798
1799 JSC::JSValue savedException;
1800 QScriptEnginePrivate::saveException(exec, &savedException);
1801 JSC::JSValue result;
1802 JSC::JSObject *newObject = JSC::construct(exec, callee, constructType, constructData, applyArgs);
1803 if (exec->hadException()) {
1804 result = exec->exception();
1805 } else {
1806 result = newObject;
1807 QScriptEnginePrivate::restoreException(exec, savedException);
1808 }
1809 return d->engine->scriptValueFromJSCValue(result);
1810}
1811
1812/*!
1813 Returns the QScriptEngine that created this QScriptValue,
1814 or 0 if this QScriptValue is invalid or the value is not
1815 associated with a particular engine.
1816*/
1817QScriptEngine *QScriptValue::engine() const
1818{
1819 Q_D(const QScriptValue);
1820 if (!d)
1821 return 0;
1822 return QScriptEnginePrivate::get(d->engine);
1823}
1824
1825/*!
1826 \obsolete
1827
1828 Use isBool() instead.
1829*/
1830bool QScriptValue::isBoolean() const
1831{
1832 Q_D(const QScriptValue);
1833 return d && d->isJSC() && d->jscValue.isBoolean();
1834}
1835
1836/*!
1837 \since 4.5
1838
1839 Returns true if this QScriptValue is of the primitive type Boolean;
1840 otherwise returns false.
1841
1842 \sa toBool()
1843*/
1844bool QScriptValue::isBool() const
1845{
1846 Q_D(const QScriptValue);
1847 return d && d->isJSC() && d->jscValue.isBoolean();
1848}
1849
1850/*!
1851 Returns true if this QScriptValue is of the primitive type Number;
1852 otherwise returns false.
1853
1854 \sa toNumber()
1855*/
1856bool QScriptValue::isNumber() const
1857{
1858 Q_D(const QScriptValue);
1859 if (!d)
1860 return false;
1861 switch (d->type) {
1862 case QScriptValuePrivate::JavaScriptCore:
1863 return d->jscValue.isNumber();
1864 case QScriptValuePrivate::Number:
1865 return true;
1866 case QScriptValuePrivate::String:
1867 return false;
1868 }
1869 return false;
1870}
1871
1872/*!
1873 Returns true if this QScriptValue is of the primitive type String;
1874 otherwise returns false.
1875
1876 \sa toString()
1877*/
1878bool QScriptValue::isString() const
1879{
1880 Q_D(const QScriptValue);
1881 if (!d)
1882 return false;
1883 switch (d->type) {
1884 case QScriptValuePrivate::JavaScriptCore:
1885 return d->jscValue.isString();
1886 case QScriptValuePrivate::Number:
1887 return false;
1888 case QScriptValuePrivate::String:
1889 return true;
1890 }
1891 return false;
1892}
1893
1894/*!
1895 Returns true if this QScriptValue is a function; otherwise returns
1896 false.
1897
1898 \sa call()
1899*/
1900bool QScriptValue::isFunction() const
1901{
1902 Q_D(const QScriptValue);
1903 if (!d || !d->isJSC())
1904 return false;
1905 return QScript::isFunction(d->jscValue);
1906}
1907
1908/*!
1909 Returns true if this QScriptValue is of the primitive type Null;
1910 otherwise returns false.
1911
1912 \sa QScriptEngine::nullValue()
1913*/
1914bool QScriptValue::isNull() const
1915{
1916 Q_D(const QScriptValue);
1917 return d && d->isJSC() && d->jscValue.isNull();
1918}
1919
1920/*!
1921 Returns true if this QScriptValue is of the primitive type Undefined;
1922 otherwise returns false.
1923
1924 \sa QScriptEngine::undefinedValue()
1925*/
1926bool QScriptValue::isUndefined() const
1927{
1928 Q_D(const QScriptValue);
1929 return d && d->isJSC() && d->jscValue.isUndefined();
1930}
1931
1932/*!
1933 Returns true if this QScriptValue is of the Object type; otherwise
1934 returns false.
1935
1936 Note that function values, variant values, and QObject values are
1937 objects, so this function returns true for such values.
1938
1939 \sa toObject(), QScriptEngine::newObject()
1940*/
1941bool QScriptValue::isObject() const
1942{
1943 Q_D(const QScriptValue);
1944 return d && d->isObject();
1945}
1946
1947/*!
1948 Returns true if this QScriptValue is a variant value;
1949 otherwise returns false.
1950
1951 \sa toVariant(), QScriptEngine::newVariant()
1952*/
1953bool QScriptValue::isVariant() const
1954{
1955 Q_D(const QScriptValue);
1956 if (!d || !d->isJSC())
1957 return false;
1958 return QScriptEnginePrivate::isVariant(d->jscValue);
1959}
1960
1961/*!
1962 Returns true if this QScriptValue is a QObject; otherwise returns
1963 false.
1964
1965 Note: This function returns true even if the QObject that this
1966 QScriptValue wraps has been deleted.
1967
1968 \sa toQObject(), QScriptEngine::newQObject()
1969*/
1970bool QScriptValue::isQObject() const
1971{
1972 Q_D(const QScriptValue);
1973 if (!d || !d->isJSC())
1974 return false;
1975 return QScriptEnginePrivate::isQObject(d->jscValue);
1976}
1977
1978/*!
1979 Returns true if this QScriptValue is a QMetaObject; otherwise returns
1980 false.
1981
1982 \sa toQMetaObject(), QScriptEngine::newQMetaObject()
1983*/
1984bool QScriptValue::isQMetaObject() const
1985{
1986 Q_D(const QScriptValue);
1987 if (!d || !d->isJSC())
1988 return false;
1989 return QScriptEnginePrivate::isQMetaObject(d->jscValue);
1990}
1991
1992/*!
1993 Returns true if this QScriptValue is valid; otherwise returns
1994 false.
1995*/
1996bool QScriptValue::isValid() const
1997{
1998 Q_D(const QScriptValue);
1999 return d && (!d->isJSC() || !!d->jscValue);
2000}
2001
2002/*!
2003 \since 4.4
2004
2005 Returns the internal data of this QScriptValue object. QtScript uses
2006 this property to store the primitive value of Date, String, Number
2007 and Boolean objects. For other types of object, custom data may be
2008 stored using setData().
2009*/
2010QScriptValue QScriptValue::data() const
2011{
2012 Q_D(const QScriptValue);
2013 if (!d || !d->isObject())
2014 return QScriptValue();
2015 if (d->jscValue.inherits(&QScriptObject::info)) {
2016 QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
2017 return d->engine->scriptValueFromJSCValue(scriptObject->data());
2018 } else {
2019 // ### make hidden property
2020 return property(QLatin1String("__qt_data__"), QScriptValue::ResolveLocal);
2021 }
2022}
2023
2024/*!
2025 \since 4.4
2026
2027 Sets the internal \a data of this QScriptValue object. You can use
2028 this function to set object-specific data that won't be directly
2029 accessible to scripts, but may be retrieved in C++ using the data()
2030 function.
2031
2032 \sa QScriptEngine::reportAdditionalMemoryCost()
2033*/
2034void QScriptValue::setData(const QScriptValue &data)
2035{
2036 Q_D(QScriptValue);
2037 if (!d || !d->isObject())
2038 return;
2039 QScript::APIShim shim(d->engine);
2040 JSC::JSValue other = d->engine->scriptValueToJSCValue(data);
2041 if (d->jscValue.inherits(&QScriptObject::info)) {
2042 QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
2043 scriptObject->setData(other);
2044 } else {
2045 JSC::ExecState *exec = d->engine->currentFrame;
2046 JSC::Identifier id = JSC::Identifier(exec, "__qt_data__");
2047 if (!data.isValid()) {
2048 JSC::asObject(d->jscValue)->removeDirect(id);
2049 } else {
2050 // ### make hidden property
2051 JSC::asObject(d->jscValue)->putDirect(id, other);
2052 }
2053 }
2054}
2055
2056/*!
2057 \since 4.4
2058
2059 Returns the custom script class that this script object is an
2060 instance of, or 0 if the object is not of a custom class.
2061
2062 \sa setScriptClass()
2063*/
2064QScriptClass *QScriptValue::scriptClass() const
2065{
2066 Q_D(const QScriptValue);
2067 if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
2068 return 0;
2069 QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
2070 QScriptObjectDelegate *delegate = scriptObject->delegate();
2071 if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject))
2072 return 0;
2073 return static_cast<QScript::ClassObjectDelegate*>(delegate)->scriptClass();
2074}
2075
2076/*!
2077 \since 4.4
2078
2079 Sets the custom script class of this script object to \a scriptClass.
2080 This can be used to "promote" a plain script object (e.g. created
2081 by the "new" operator in a script, or by QScriptEngine::newObject() in C++)
2082 to an object of a custom type.
2083
2084 If \a scriptClass is 0, the object will be demoted to a plain
2085 script object.
2086
2087 \sa scriptClass(), setData()
2088*/
2089void QScriptValue::setScriptClass(QScriptClass *scriptClass)
2090{
2091 Q_D(QScriptValue);
2092 if (!d || !d->isObject())
2093 return;
2094 if (!d->jscValue.inherits(&QScriptObject::info)) {
2095 qWarning("QScriptValue::setScriptClass() failed: "
2096 "cannot change class of non-QScriptObject");
2097 return;
2098 }
2099 QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
2100 if (!scriptClass) {
2101 scriptObject->setDelegate(0);
2102 } else {
2103 QScriptObjectDelegate *delegate = scriptObject->delegate();
2104 if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) {
2105 delegate = new QScript::ClassObjectDelegate(scriptClass);
2106 scriptObject->setDelegate(delegate);
2107 }
2108 static_cast<QScript::ClassObjectDelegate*>(delegate)->setScriptClass(scriptClass);
2109 }
2110}
2111
2112/*!
2113 \internal
2114
2115 Returns the ID of this object, or -1 if this QScriptValue is not an
2116 object.
2117
2118 \sa QScriptEngine::objectById()
2119*/
2120qint64 QScriptValue::objectId() const
2121{
2122 return d_ptr?d_ptr->objectId():-1;
2123}
2124QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.