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