source: branches/4.5.1/src/script/qscriptvalueimpl_p.h@ 559

Last change on this file since 559 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 20.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtScript module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QSCRIPTVALUEIMPL_P_H
43#define QSCRIPTVALUEIMPL_P_H
44
45#include "qscriptvalueimplfwd_p.h"
46
47#ifndef QT_NO_SCRIPT
48
49#include "qscriptclassinfo_p.h"
50#include "qscriptecmaarray_p.h"
51#include "qscriptecmadate_p.h"
52#include "qscriptecmaerror_p.h"
53#include "qscriptecmaregexp_p.h"
54#include "qscriptextqobject_p.h"
55#include "qscriptextvariant_p.h"
56#include "qscriptvaluefwd_p.h"
57#include "qscriptnameid_p.h"
58#include "qscriptenginefwd_p.h"
59#include "qscriptcontextfwd_p.h"
60
61#include <QtCore/QDateTime>
62
63QT_BEGIN_NAMESPACE
64
65//
66// W A R N I N G
67// -------------
68//
69// This file is not part of the Qt API. It exists purely as an
70// implementation detail. This header file may change from version to
71// version without notice, or even be removed.
72//
73// We mean it.
74//
75
76inline QScriptValueImpl::QScriptValueImpl()
77 : m_type(QScript::InvalidType) {}
78
79inline QScriptValueImpl::QScriptValueImpl(QScriptValue::SpecialValue val)
80{
81 if (val == QScriptValue::NullValue)
82 m_type = QScript::NullType;
83 else if (val == QScriptValue::UndefinedValue)
84 m_type = QScript::UndefinedType;
85 else
86 m_type = QScript::InvalidType;
87}
88
89inline QScriptValueImpl::QScriptValueImpl(bool val)
90 : m_type(QScript::BooleanType), m_bool_value(val)
91{
92}
93
94inline QScriptValueImpl::QScriptValueImpl(int val)
95 : m_type(QScript::NumberType), m_number_value(val)
96{
97}
98
99inline QScriptValueImpl::QScriptValueImpl(uint val)
100 : m_type(QScript::NumberType), m_number_value(val)
101{
102}
103
104inline QScriptValueImpl::QScriptValueImpl(qsreal val)
105 : m_type(QScript::NumberType), m_number_value(val)
106{
107}
108
109inline QScriptValueImpl::QScriptValueImpl(QScriptEnginePrivate *engine, const QString &val)
110{
111 engine->newString(this, val);
112}
113
114inline QScriptValueImpl::QScriptValueImpl(QScriptNameIdImpl *val)
115 : m_type(QScript::StringType), m_string_value(val)
116{
117}
118
119inline QScript::Type QScriptValueImpl::type() const
120{
121 return m_type;
122}
123
124inline QScriptEnginePrivate *QScriptValueImpl::engine() const
125{
126 if (!isObject())
127 return 0;
128 return m_object_value->m_class->engine();
129}
130
131inline QScriptClassInfo *QScriptValueImpl::classInfo() const
132{
133 if (!isObject())
134 return 0;
135 return m_object_value->m_class;
136}
137
138inline void QScriptValueImpl::setClassInfo(QScriptClassInfo *cls)
139{
140 Q_ASSERT(isObject());
141 m_object_value->m_class = cls;
142}
143
144inline QScriptNameIdImpl *QScriptValueImpl::stringValue() const
145{
146 Q_ASSERT(isString());
147 return m_string_value;
148}
149
150inline QScriptObject *QScriptValueImpl::objectValue() const
151{
152 Q_ASSERT(isObject());
153 return m_object_value;
154}
155
156inline void QScriptValueImpl::incr()
157{
158 ++m_number_value;
159}
160
161inline void QScriptValueImpl::decr()
162{
163 --m_number_value;
164}
165
166inline void QScriptValueImpl::invalidate()
167{
168 m_type = QScript::InvalidType;
169}
170
171inline bool QScriptValueImpl::isValid() const
172{
173 return m_type != QScript::InvalidType;
174}
175
176inline bool QScriptValueImpl::isUndefined() const
177{
178 return (m_type == QScript::UndefinedType);
179}
180
181inline bool QScriptValueImpl::isNull() const
182{
183 return (m_type == QScript::NullType);
184}
185
186inline bool QScriptValueImpl::isBoolean() const
187{
188 return (m_type == QScript::BooleanType);
189}
190
191inline bool QScriptValueImpl::isNumber() const
192{
193 return (m_type == QScript::NumberType);
194}
195
196inline bool QScriptValueImpl::isString() const
197{
198 return (m_type == QScript::StringType)
199 || (m_type == QScript::LazyStringType);
200}
201
202inline bool QScriptValueImpl::isReference() const
203{
204 return (m_type == QScript::ReferenceType);
205}
206
207inline bool QScriptValueImpl::isObject() const
208{
209 return (m_type == QScript::ObjectType);
210}
211
212inline bool QScriptValueImpl::isFunction() const
213{
214 return (m_type == QScript::ObjectType)
215 && (classInfo()->type() & QScriptClassInfo::FunctionBased);
216}
217
218inline bool QScriptValueImpl::isVariant() const
219{
220 return (m_type == QScript::ObjectType)
221 && (classInfo()->type() == QScriptClassInfo::VariantType);
222}
223
224inline bool QScriptValueImpl::isQObject() const
225{
226 return (m_type == QScript::ObjectType)
227 && (classInfo()->type() == QScriptClassInfo::QObjectType);
228}
229
230inline bool QScriptValueImpl::isQMetaObject() const
231{
232 return (m_type == QScript::ObjectType)
233 && (classInfo()->type() == QScriptClassInfo::QMetaObjectType);
234}
235
236inline bool QScriptValueImpl::isArray() const
237{
238 if (!isObject())
239 return false;
240 return classInfo() == engine()->arrayConstructor->classInfo();
241}
242
243inline bool QScriptValueImpl::isDate() const
244{
245 if (!isObject())
246 return false;
247 return classInfo() == engine()->dateConstructor->classInfo();
248}
249
250inline bool QScriptValueImpl::isError() const
251{
252 if (!isObject())
253 return false;
254 return classInfo() == engine()->errorConstructor->classInfo();
255}
256
257inline bool QScriptValueImpl::isRegExp() const
258{
259 if (!isObject())
260 return false;
261 return classInfo() == engine()->regexpConstructor->classInfo();
262}
263
264inline qsreal QScriptValueImpl::toNumber() const
265{
266 if (!isValid())
267 return 0;
268 return QScriptEnginePrivate::convertToNativeDouble(*this);
269}
270
271inline bool QScriptValueImpl::toBoolean() const
272{
273 if (!isValid())
274 return false;
275 return QScriptEnginePrivate::convertToNativeBoolean(*this);
276}
277
278inline QString QScriptValueImpl::toString() const
279{
280 if (!isValid())
281 return QString();
282 return QScriptEnginePrivate::convertToNativeString(*this);
283}
284
285inline qint32 QScriptValueImpl::toInt32() const
286{
287 if (!isValid())
288 return 0;
289 double d = QScriptEnginePrivate::convertToNativeDouble(*this);
290 return QScriptEnginePrivate::toInt32(d);
291}
292
293inline quint32 QScriptValueImpl::toUInt32() const
294{
295 if (!isValid())
296 return 0;
297 double d = QScriptEnginePrivate::convertToNativeDouble(*this);
298 return QScriptEnginePrivate::toUint32(d);
299}
300
301inline quint16 QScriptValueImpl::toUInt16() const
302{
303 if (!isValid())
304 return 0;
305 double d = QScriptEnginePrivate::convertToNativeDouble(*this);
306 return QScriptEnginePrivate::toUint16(d);
307}
308
309inline qsreal QScriptValueImpl::toInteger() const
310{
311 if (!isValid())
312 return 0;
313 double d = QScriptEnginePrivate::convertToNativeDouble(*this);
314 return QScriptEnginePrivate::toInteger(d);
315}
316
317inline QDateTime QScriptValueImpl::toDateTime() const
318{
319 if (!isDate())
320 return QDateTime();
321 return engine()->toDateTime(*this);
322}
323
324#ifndef QT_NO_REGEXP
325inline QRegExp QScriptValueImpl::toRegExp() const
326{
327 if (!isRegExp())
328 return QRegExp();
329 return engine()->regexpConstructor->toRegExp(*this);
330}
331#endif // QT_NO_REGEXP
332
333inline QObject *QScriptValueImpl::toQObject() const
334{
335#ifndef QT_NO_QOBJECT
336 if (isQObject()) {
337 QScript::ExtQObject *ctor = engine()->qobjectConstructor;
338 Q_ASSERT(ctor != 0);
339
340 QScript::ExtQObject::Instance *data = ctor->get(*this);
341 Q_ASSERT(data != 0);
342
343 return data->value;
344 } else if (isVariant()) {
345 int type = variantValue().userType();
346 if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar))
347 return *reinterpret_cast<QObject* const *>(variantValue().constData());
348 }
349#endif
350 return 0;
351}
352
353inline const QMetaObject *QScriptValueImpl::toQMetaObject() const
354{
355#ifndef QT_NO_QOBJECT
356 if (isQMetaObject()) {
357 QScript::ExtQMetaObject *ctor = engine()->qmetaObjectConstructor;
358 Q_ASSERT(ctor != 0);
359
360 QScript::ExtQMetaObject::Instance *data = ctor->get(*this);
361 Q_ASSERT(data != 0);
362
363 return data->value;
364 }
365#endif
366 return 0;
367}
368
369inline QScriptValueImpl QScriptValueImpl::prototype() const
370{
371 if (!isObject())
372 return QScriptValueImpl();
373 return m_object_value->m_prototype;
374}
375
376inline void QScriptValueImpl::setPrototype(const QScriptValueImpl &prototype)
377{
378 if (isObject())
379 m_object_value->m_prototype = prototype;
380}
381
382inline QScriptObjectData *QScriptValueImpl::objectData() const
383{
384 Q_ASSERT(isObject());
385 return m_object_value->m_data;
386}
387
388inline void QScriptValueImpl::setObjectData(QScriptObjectData *data)
389{
390 Q_ASSERT(isObject());
391 m_object_value->m_data = data;
392}
393
394inline bool QScriptValueImpl::resolve(QScriptNameIdImpl *nameId, QScript::Member *member,
395 QScriptValueImpl *object, QScriptValue::ResolveFlags mode,
396 QScript::AccessMode access) const
397{
398 Q_ASSERT(isValid());
399 Q_ASSERT(isObject());
400 Q_ASSERT(member);
401 Q_ASSERT(object);
402
403 Q_ASSERT(nameId->unique);
404
405 QScriptObject *object_data = m_object_value;
406
407 // Search in properties...
408 if (object_data->findMember(nameId, member)) {
409 *object = *this;
410 return true;
411 }
412
413 return resolve_helper(nameId, member, object, mode, access);
414}
415
416inline void QScriptValueImpl::get(const QScript::Member &member, QScriptValueImpl *out) const
417{
418 Q_ASSERT(out);
419 Q_ASSERT(isObject());
420 Q_ASSERT(member.isValid());
421
422 if (! member.isObjectProperty()) {
423 get_helper(member, out);
424 return;
425 }
426
427 Q_ASSERT(member.id() >= 0);
428 Q_ASSERT(member.id() < m_object_value->memberCount());
429
430 m_object_value->get(member, out);
431}
432
433inline void QScriptValueImpl::get(QScriptNameIdImpl *nameId, QScriptValueImpl *out)
434{
435 QScript::Member m;
436 QScriptValueImpl o;
437 if (resolve(nameId, &m, &o, QScriptValue::ResolvePrototype, QScript::Read))
438 o.get(m, out);
439 else
440 *out = QScriptValueImpl(QScriptValue::UndefinedValue);
441}
442
443inline void QScriptValueImpl::get_helper(const QScript::Member &member, QScriptValueImpl *out) const
444{
445 if (member.nameId() == engine()->idTable()->id___proto__) {
446 *out = prototype();
447
448 if (!out->isValid())
449 *out = QScriptValueImpl(QScriptValue::UndefinedValue);
450
451 return;
452 }
453
454 if (QScriptClassData *data = classInfo()->data()) {
455 if (data->get(*this, member, out))
456 return;
457 }
458
459 out->invalidate();
460}
461
462inline void QScriptValueImpl::put(const QScript::Member &member, const QScriptValueImpl &value)
463{
464 Q_ASSERT(isObject());
465 Q_ASSERT(member.isValid());
466 // Q_ASSERT(member.isWritable());
467
468 QScriptEnginePrivate *eng_p = engine();
469
470 if (member.isObjectProperty()) {
471 Q_ASSERT(member.nameId()->unique);
472 Q_ASSERT(member.id() >= 0);
473 Q_ASSERT(member.id() < m_object_value->memberCount());
474 m_object_value->put(member, value);
475 }
476
477 else if (member.nameId() == eng_p->idTable()->id___proto__) {
478 if (value.isNull()) // only Object.prototype.__proto__ can be null
479 setPrototype(eng_p->undefinedValue());
480 else {
481 QScriptValueImpl was = prototype();
482 setPrototype(value);
483 if (detectedCycle()) {
484 eng_p->currentContext()->throwError(QLatin1String("cycle in prototype chain"));
485 setPrototype(was);
486 }
487 }
488 }
489
490 else {
491 Q_ASSERT(classInfo()->data());
492 classInfo()->data()->put(this, member, value);
493 }
494}
495
496inline void QScriptValueImpl::setQObjectValue(QObject *object)
497{
498#ifndef QT_NO_QOBJECT
499 Q_ASSERT(isQObject());
500
501 QScript::ExtQObject *ctor = engine()->qobjectConstructor;
502 Q_ASSERT(ctor != 0);
503
504 QScript::ExtQObject::Instance *data = ctor->get(*this);
505 Q_ASSERT(data != 0);
506
507 data->value = object;
508#else
509 Q_UNUSED(object);
510#endif
511}
512
513inline QVariant &QScriptValueImpl::variantValue() const
514{
515 Q_ASSERT(isVariant());
516
517 QScript::Ext::Variant *ctor = engine()->variantConstructor;
518 Q_ASSERT(ctor != 0);
519
520 QScript::Ext::Variant::Instance *data = ctor->get(*this);
521 Q_ASSERT(data != 0);
522
523 return data->value;
524}
525
526inline void QScriptValueImpl::setVariantValue(const QVariant &value)
527{
528 if (!isVariant())
529 return;
530
531 QScript::Ext::Variant *ctor = engine()->variantConstructor;
532 Q_ASSERT(ctor != 0);
533
534 QScript::Ext::Variant::Instance *data = ctor->get(*this);
535 Q_ASSERT(data != 0);
536
537 data->value = value;
538}
539
540inline QScriptValueImpl QScriptValueImpl::internalValue() const
541{
542 Q_ASSERT(isObject());
543 return m_object_value->m_internalValue;
544}
545
546inline void QScriptValueImpl::setInternalValue(const QScriptValueImpl &internalValue)
547{
548 Q_ASSERT(isObject());
549 m_object_value->m_internalValue = internalValue;
550}
551
552inline void QScriptValueImpl::removeMember(const QScript::Member &member)
553{
554 if (member.isObjectProperty())
555 m_object_value->removeMember(member);
556
557 else if (QScriptClassData *data = classInfo()->data())
558 data->removeMember(*this, member);
559}
560
561inline void QScriptValueImpl::createMember(QScriptNameIdImpl *nameId,
562 QScript::Member *member, uint flags)
563{
564 Q_ASSERT(isObject());
565
566 QScriptObject *object_data = m_object_value;
567 object_data->createMember(nameId, member, flags);
568 Q_ASSERT(member->isObjectProperty());
569}
570
571inline QScriptValueImpl QScriptValueImpl::scope() const
572{
573 Q_ASSERT(isObject());
574 return m_object_value->m_scope;
575}
576
577inline void QScriptValueImpl::setScope(const QScriptValueImpl &scope)
578{
579 Q_ASSERT(isObject());
580 m_object_value->m_scope = scope;
581}
582
583inline int QScriptValueImpl::memberCount() const
584{
585 Q_ASSERT(isObject());
586 return m_object_value->memberCount();
587}
588
589inline void QScriptValueImpl::member(int index, QScript::Member *member) const
590{
591 Q_ASSERT(isObject());
592 Q_ASSERT(index >= 0);
593 Q_ASSERT(index < m_object_value->memberCount());
594 m_object_value->member(index, member);
595}
596
597inline QScriptFunction *QScriptValueImpl::toFunction() const
598{
599 if (!isFunction())
600 return 0;
601 return engine()->convertToNativeFunction(*this);
602}
603
604inline QScriptValueImpl QScriptValueImpl::property(QScriptNameIdImpl *nameId,
605 const QScriptValue::ResolveFlags &mode) const
606{
607 if (!isObject())
608 return QScriptValueImpl();
609
610 QScriptValueImpl base;
611 QScript::Member member;
612
613 if (! resolve(nameId, &member, &base, mode, QScript::Read))
614 return QScriptValueImpl();
615
616 QScriptValueImpl value;
617 base.get(member, &value);
618 if (member.isGetterOrSetter()) {
619 QScriptValueImpl getter;
620 if (member.isObjectProperty() && !member.isGetter()) {
621 if (!base.m_object_value->findGetter(&member))
622 return QScriptValueImpl();
623 }
624 base.get(member, &getter);
625 value = getter.call(*this);
626 }
627 return value;
628}
629
630inline void QScriptValueImpl::setProperty(const QString &name, const QScriptValueImpl &value,
631 const QScriptValue::PropertyFlags &flags)
632{
633 if (!isObject())
634 return;
635 QScriptNameIdImpl *nameId = engine()->nameId(name);
636 setProperty(nameId, value, flags);
637}
638
639inline QScriptValueImpl QScriptValueImpl::property(const QString &name,
640 const QScriptValue::ResolveFlags &mode) const
641{
642 if (!isObject())
643 return QScriptValueImpl();
644 QScriptNameIdImpl *nameId = engine()->nameId(name);
645 return property(nameId, mode);
646}
647
648inline QScriptValueImpl QScriptValueImpl::property(quint32 arrayIndex,
649 const QScriptValue::ResolveFlags &mode) const
650{
651 if (!isObject())
652 return QScriptValueImpl();
653
654 QScriptEnginePrivate *eng_p = engine();
655 QScript::Ecma::Array::Instance *instance = eng_p->arrayConstructor->get(*this);
656 if (instance && (arrayIndex != 0xFFFFFFFF))
657 return instance->value.at(arrayIndex);
658
659 return property(QScriptValueImpl(arrayIndex).toString(), mode);
660}
661
662inline void QScriptValueImpl::setProperty(quint32 arrayIndex, const QScriptValueImpl &value,
663 const QScriptValue::PropertyFlags &flags)
664{
665 if (!isObject())
666 return;
667
668 QScriptEnginePrivate *eng_p = engine();
669 QScript::Ecma::Array::Instance *instance = eng_p->arrayConstructor->get(*this);
670 if (instance && (arrayIndex != 0xFFFFFFFF)) {
671 instance->value.assign(arrayIndex, value);
672 return;
673 }
674
675 setProperty(QScriptValueImpl(arrayIndex).toString(), value, flags);
676}
677
678inline QScriptValue::PropertyFlags QScriptValueImpl::propertyFlags(const QString &name,
679 const QScriptValue::ResolveFlags &mode) const
680{
681 QScriptNameIdImpl *nameId = engine()->nameId(name);
682 return propertyFlags(nameId, mode);
683}
684
685inline QScriptValue::PropertyFlags QScriptValueImpl::propertyFlags(QScriptNameIdImpl *nameId,
686 const QScriptValue::ResolveFlags &mode) const
687{
688 if (!isObject())
689 return 0;
690
691 QScriptValueImpl base;
692 QScript::Member member;
693 if (! resolve(nameId, &member, &base, mode, QScript::ReadWrite))
694 return 0;
695
696 return QScriptValue::PropertyFlags(member.flags() & ~QScript::Member::InternalRange);
697}
698
699inline bool QScriptValueImpl::deleteProperty(QScriptNameIdImpl *nameId,
700 const QScriptValue::ResolveFlags &mode)
701{
702 if (!isObject())
703 return true;
704 QScript::Member member;
705 QScriptValueImpl base;
706 if (resolve(nameId, &member, &base, mode, QScript::Write)) {
707 if (!member.isDeletable())
708 return false;
709 base.removeMember(member);
710 if (member.isGetterOrSetter() && (member.isGetter() != member.isSetter())) {
711 // delete the "other half" of the property too (getter or setter)
712 return deleteProperty(nameId, mode);
713 }
714 }
715 return true;
716}
717
718inline QScriptValueImpl QScriptValueImpl::call(const QScriptValueImpl &thisObject,
719 const QScriptValueImplList &args)
720{
721 if (!isFunction())
722 return QScriptValueImpl();
723
724 return engine()->call(*this, thisObject, args, /*asConstructor=*/false);
725}
726
727inline QScriptValueImpl QScriptValueImpl::call(const QScriptValueImpl &thisObject,
728 const QScriptValueImpl &args)
729{
730 if (!isFunction())
731 return QScriptValueImpl();
732
733 return engine()->call(*this, thisObject, args, /*asConstructor=*/false);
734}
735
736inline QScriptValueImpl QScriptValueImpl::construct(const QScriptValueImplList &args)
737{
738 if (!isFunction())
739 return QScriptValueImpl();
740
741 QScriptEnginePrivate *eng_p = engine();
742
743 QScriptValueImpl proto = property(QLatin1String("prototype"), QScriptValue::ResolveLocal);
744 QScriptValueImpl object;
745 eng_p->newObject(&object, proto);
746
747 QScriptValueImpl result = eng_p->call(*this, object, args, /*asConstructor=*/true);
748 if (result.isObject())
749 return result;
750 return object;
751}
752
753inline QScriptValueImpl QScriptValueImpl::construct(const QScriptValueImpl &args)
754{
755 if (!isFunction())
756 return QScriptValueImpl();
757
758 QScriptEnginePrivate *eng_p = engine();
759
760 QScriptValueImpl proto = property(QLatin1String("prototype"), QScriptValue::ResolveLocal);
761 QScriptValueImpl object;
762 eng_p->newObject(&object, proto);
763
764 QScriptValueImpl result = eng_p->call(*this, object, args, /*asConstructor=*/true);
765 if (result.isObject())
766 return result;
767 return object;
768}
769
770inline void QScriptValueImpl::mark(int generation) const
771{
772 if (! isValid())
773 return;
774
775 else if (isString())
776 engine()->markString(m_string_value, generation);
777
778 else if (isObject())
779 engine()->markObject(*this, generation);
780}
781
782QT_END_NAMESPACE
783
784#endif // QT_NO_SCRIPT
785
786#endif
Note: See TracBrowser for help on using the repository browser.