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