Improve QJSValueIterator implementation.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativevmemetaobject.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativevmemetaobject_p.h"
43
44 #include "qdeclarative.h"
45 #include "private/qdeclarativerefcount_p.h"
46 #include "qdeclarativeexpression.h"
47 #include "private/qdeclarativeexpression_p.h"
48 #include "private/qdeclarativecontext_p.h"
49 #include "private/qdeclarativebinding_p.h"
50
51 Q_DECLARE_METATYPE(QJSValue);
52
53 QT_BEGIN_NAMESPACE
54
55 class QDeclarativeVMEVariant
56 {
57 public:
58     inline QDeclarativeVMEVariant();
59     inline ~QDeclarativeVMEVariant();
60
61     inline const void *dataPtr() const;
62     inline void *dataPtr();
63     inline int dataType() const;
64
65     inline QObject *asQObject();
66     inline const QVariant &asQVariant();
67     inline int asInt();
68     inline bool asBool();
69     inline double asDouble();
70     inline const QString &asQString();
71     inline const QUrl &asQUrl();
72     inline const QColor &asQColor();
73     inline const QTime &asQTime();
74     inline const QDate &asQDate();
75     inline const QDateTime &asQDateTime();
76     inline const QJSValue &asQJSValue();
77
78     inline void setValue(QObject *);
79     inline void setValue(const QVariant &);
80     inline void setValue(int);
81     inline void setValue(bool);
82     inline void setValue(double);
83     inline void setValue(const QString &);
84     inline void setValue(const QUrl &);
85     inline void setValue(const QColor &);
86     inline void setValue(const QTime &);
87     inline void setValue(const QDate &);
88     inline void setValue(const QDateTime &);
89     inline void setValue(const QJSValue &);
90 private:
91     int type;
92     void *data[4]; // Large enough to hold all types
93
94     inline void cleanup();
95 };
96
97 QDeclarativeVMEVariant::QDeclarativeVMEVariant()
98 : type(QVariant::Invalid)
99 {
100 }
101
102 QDeclarativeVMEVariant::~QDeclarativeVMEVariant()
103 {
104     cleanup();
105 }
106
107 void QDeclarativeVMEVariant::cleanup()
108 {
109     if (type == QVariant::Invalid) {
110     } else if (type == QMetaType::Int ||
111                type == QMetaType::Bool ||
112                type == QMetaType::Double) {
113         type = QVariant::Invalid;
114     } else if (type == QMetaType::QObjectStar) {
115         ((QDeclarativeGuard<QObject>*)dataPtr())->~QDeclarativeGuard<QObject>();
116         type = QVariant::Invalid;
117     } else if (type == QMetaType::QString) {
118         ((QString *)dataPtr())->~QString();
119         type = QVariant::Invalid;
120     } else if (type == QMetaType::QUrl) {
121         ((QUrl *)dataPtr())->~QUrl();
122         type = QVariant::Invalid;
123     } else if (type == QMetaType::QColor) {
124         ((QColor *)dataPtr())->~QColor();
125         type = QVariant::Invalid;
126     } else if (type == QMetaType::QTime) {
127         ((QTime *)dataPtr())->~QTime();
128         type = QVariant::Invalid;
129     } else if (type == QMetaType::QDate) {
130         ((QDate *)dataPtr())->~QDate();
131         type = QVariant::Invalid;
132     } else if (type == QMetaType::QDateTime) {
133         ((QDateTime *)dataPtr())->~QDateTime();
134         type = QVariant::Invalid;
135     } else if (type == qMetaTypeId<QVariant>()) {
136         ((QVariant *)dataPtr())->~QVariant();
137         type = QVariant::Invalid;
138     } else if (type == qMetaTypeId<QJSValue>()) {
139         ((QJSValue *)dataPtr())->~QJSValue();
140         type = QVariant::Invalid;
141     }
142
143 }
144
145 int QDeclarativeVMEVariant::dataType() const
146 {
147     return type;
148 }
149
150 const void *QDeclarativeVMEVariant::dataPtr() const
151 {
152     return &data;
153 }
154
155 void *QDeclarativeVMEVariant::dataPtr() 
156 {
157     return &data;
158 }
159
160 QObject *QDeclarativeVMEVariant::asQObject() 
161 {
162     if (type != QMetaType::QObjectStar) 
163         setValue((QObject *)0);
164
165     return *(QDeclarativeGuard<QObject> *)(dataPtr());
166 }
167
168 const QVariant &QDeclarativeVMEVariant::asQVariant() 
169 {
170     if (type != QMetaType::QVariant)
171         setValue(QVariant());
172
173     return *(QVariant *)(dataPtr());
174 }
175
176 int QDeclarativeVMEVariant::asInt() 
177 {
178     if (type != QMetaType::Int)
179         setValue(int(0));
180
181     return *(int *)(dataPtr());
182 }
183
184 bool QDeclarativeVMEVariant::asBool() 
185 {
186     if (type != QMetaType::Bool)
187         setValue(bool(false));
188
189     return *(bool *)(dataPtr());
190 }
191
192 double QDeclarativeVMEVariant::asDouble() 
193 {
194     if (type != QMetaType::Double)
195         setValue(double(0));
196
197     return *(double *)(dataPtr());
198 }
199
200 const QString &QDeclarativeVMEVariant::asQString() 
201 {
202     if (type != QMetaType::QString)
203         setValue(QString());
204
205     return *(QString *)(dataPtr());
206 }
207
208 const QUrl &QDeclarativeVMEVariant::asQUrl() 
209 {
210     if (type != QMetaType::QUrl)
211         setValue(QUrl());
212
213     return *(QUrl *)(dataPtr());
214 }
215
216 const QColor &QDeclarativeVMEVariant::asQColor() 
217 {
218     if (type != QMetaType::QColor)
219         setValue(QColor());
220
221     return *(QColor *)(dataPtr());
222 }
223
224 const QTime &QDeclarativeVMEVariant::asQTime() 
225 {
226     if (type != QMetaType::QTime)
227         setValue(QTime());
228
229     return *(QTime *)(dataPtr());
230 }
231
232 const QDate &QDeclarativeVMEVariant::asQDate() 
233 {
234     if (type != QMetaType::QDate)
235         setValue(QDate());
236
237     return *(QDate *)(dataPtr());
238 }
239
240 const QDateTime &QDeclarativeVMEVariant::asQDateTime() 
241 {
242     if (type != QMetaType::QDateTime)
243         setValue(QDateTime());
244
245     return *(QDateTime *)(dataPtr());
246 }
247
248 const QJSValue &QDeclarativeVMEVariant::asQJSValue()
249 {
250     if (type != qMetaTypeId<QJSValue>())
251         setValue(QJSValue());
252
253     return *(QJSValue *)(dataPtr());
254 }
255
256 void QDeclarativeVMEVariant::setValue(QObject *v)
257 {
258     if (type != QMetaType::QObjectStar) {
259         cleanup();
260         type = QMetaType::QObjectStar;
261         new (dataPtr()) QDeclarativeGuard<QObject>();
262     }
263     *(QDeclarativeGuard<QObject>*)(dataPtr()) = v;
264 }
265
266 void QDeclarativeVMEVariant::setValue(const QVariant &v)
267 {
268     if (type != qMetaTypeId<QVariant>()) {
269         cleanup();
270         type = qMetaTypeId<QVariant>();
271         new (dataPtr()) QVariant(v);
272     } else {
273         *(QVariant *)(dataPtr()) = v;
274     }
275 }
276
277 void QDeclarativeVMEVariant::setValue(int v)
278 {
279     if (type != QMetaType::Int) {
280         cleanup();
281         type = QMetaType::Int;
282     }
283     *(int *)(dataPtr()) = v;
284 }
285
286 void QDeclarativeVMEVariant::setValue(bool v)
287 {
288     if (type != QMetaType::Bool) {
289         cleanup();
290         type = QMetaType::Bool;
291     }
292     *(bool *)(dataPtr()) = v;
293 }
294
295 void QDeclarativeVMEVariant::setValue(double v)
296 {
297     if (type != QMetaType::Double) {
298         cleanup();
299         type = QMetaType::Double;
300     }
301     *(double *)(dataPtr()) = v;
302 }
303
304 void QDeclarativeVMEVariant::setValue(const QString &v)
305 {
306     if (type != QMetaType::QString) {
307         cleanup();
308         type = QMetaType::QString;
309         new (dataPtr()) QString(v);
310     } else {
311         *(QString *)(dataPtr()) = v;
312     }
313 }
314
315 void QDeclarativeVMEVariant::setValue(const QUrl &v)
316 {
317     if (type != QMetaType::QUrl) {
318         cleanup();
319         type = QMetaType::QUrl;
320         new (dataPtr()) QUrl(v);
321     } else {
322         *(QUrl *)(dataPtr()) = v;
323     }
324 }
325
326 void QDeclarativeVMEVariant::setValue(const QColor &v)
327 {
328     if (type != QMetaType::QColor) {
329         cleanup();
330         type = QMetaType::QColor;
331         new (dataPtr()) QColor(v);
332     } else {
333         *(QColor *)(dataPtr()) = v;
334     }
335 }
336
337 void QDeclarativeVMEVariant::setValue(const QTime &v)
338 {
339     if (type != QMetaType::QTime) {
340         cleanup();
341         type = QMetaType::QTime;
342         new (dataPtr()) QTime(v);
343     } else {
344         *(QTime *)(dataPtr()) = v;
345     }
346 }
347
348 void QDeclarativeVMEVariant::setValue(const QDate &v)
349 {
350     if (type != QMetaType::QDate) {
351         cleanup();
352         type = QMetaType::QDate;
353         new (dataPtr()) QDate(v);
354     } else {
355         *(QDate *)(dataPtr()) = v;
356     }
357 }
358
359 void QDeclarativeVMEVariant::setValue(const QDateTime &v)
360 {
361     if (type != QMetaType::QDateTime) {
362         cleanup();
363         type = QMetaType::QDateTime;
364         new (dataPtr()) QDateTime(v);
365     } else {
366         *(QDateTime *)(dataPtr()) = v;
367     }
368 }
369
370 void QDeclarativeVMEVariant::setValue(const QJSValue &v)
371 {
372     if (type != qMetaTypeId<QJSValue>()) {
373         cleanup();
374         type = qMetaTypeId<QJSValue>();
375         new (dataPtr()) QJSValue(v);
376     } else {
377         *(QJSValue *)(dataPtr()) = v;
378     }
379 }
380
381 QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj,
382                                                      const QMetaObject *other, 
383                                                      const QDeclarativeVMEMetaData *meta,
384                                                      QDeclarativeCompiledData *cdata)
385 : object(obj), compiledData(cdata), ctxt(QDeclarativeData::get(obj, true)->outerContext),
386   metaData(meta), data(0), v8methods(0), parent(0)
387 {
388     compiledData->addref();
389
390     *static_cast<QMetaObject *>(this) = *other;
391     this->d.superdata = obj->metaObject();
392
393     QObjectPrivate *op = QObjectPrivate::get(obj);
394     if (op->metaObject)
395         parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
396     op->metaObject = this;
397
398     propOffset = QAbstractDynamicMetaObject::propertyOffset();
399     methodOffset = QAbstractDynamicMetaObject::methodOffset();
400
401     data = new QDeclarativeVMEVariant[metaData->propertyCount];
402
403     aConnected.resize(metaData->aliasCount);
404     int list_type = qMetaTypeId<QDeclarativeListProperty<QObject> >();
405
406     // ### Optimize
407     for (int ii = 0; ii < metaData->propertyCount; ++ii) {
408         int t = (metaData->propertyData() + ii)->propertyType;
409         if (t == list_type) {
410             listProperties.append(List(methodOffset + ii));
411             data[ii].setValue(listProperties.count() - 1);
412         } 
413     }
414 }
415
416 QDeclarativeVMEMetaObject::~QDeclarativeVMEMetaObject()
417 {
418     compiledData->release();
419     delete parent;
420     delete [] data;
421
422     for (int ii = 0; v8methods && ii < metaData->methodCount; ++ii) {
423         qPersistentDispose(v8methods[ii]);
424     }
425 }
426
427 int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
428 {
429     int id = _id;
430     if(c == QMetaObject::WriteProperty) {
431         int flags = *reinterpret_cast<int*>(a[3]);
432         if (!(flags & QDeclarativePropertyPrivate::BypassInterceptor)
433             && !aInterceptors.isEmpty()
434             && aInterceptors.testBit(id)) {
435             QPair<int, QDeclarativePropertyValueInterceptor*> pair = interceptors.value(id);
436             int valueIndex = pair.first;
437             QDeclarativePropertyValueInterceptor *vi = pair.second;
438             int type = property(id).userType();
439
440             if (type != QVariant::Invalid) {
441                 if (valueIndex != -1) {
442                     QDeclarativeEnginePrivate *ep = ctxt?QDeclarativeEnginePrivate::get(ctxt->engine):0;
443                     QDeclarativeValueType *valueType = 0;
444                     if (ep) valueType = ep->valueTypes[type];
445                     else valueType = QDeclarativeValueTypeFactory::valueType(type);
446                     Q_ASSERT(valueType);
447
448                     valueType->setValue(QVariant(type, a[0]));
449                     QMetaProperty valueProp = valueType->metaObject()->property(valueIndex);
450                     vi->write(valueProp.read(valueType));
451
452                     if (!ep) delete valueType;
453                     return -1;
454                 } else {
455                     vi->write(QVariant(type, a[0]));
456                     return -1;
457                 }
458             }
459         }
460     }
461     if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
462         if (id >= propOffset) {
463             id -= propOffset;
464
465             if (id < metaData->propertyCount) {
466                int t = (metaData->propertyData() + id)->propertyType;
467                 bool needActivate = false;
468
469                 if (t == -1) {
470
471                     if (c == QMetaObject::ReadProperty) {
472                         *reinterpret_cast<QVariant *>(a[0]) = readVarPropertyAsVariant(id);
473                     } else if (c == QMetaObject::WriteProperty) {
474                         writeVarProperty(id, *reinterpret_cast<QVariant *>(a[0]));
475                     }
476
477                 } else {
478
479                     if (c == QMetaObject::ReadProperty) {
480                         switch(t) {
481                         case QVariant::Int:
482                             *reinterpret_cast<int *>(a[0]) = data[id].asInt();
483                             break;
484                         case QVariant::Bool:
485                             *reinterpret_cast<bool *>(a[0]) = data[id].asBool();
486                             break;
487                         case QVariant::Double:
488                             *reinterpret_cast<double *>(a[0]) = data[id].asDouble();
489                             break;
490                         case QVariant::String:
491                             *reinterpret_cast<QString *>(a[0]) = data[id].asQString();
492                             break;
493                         case QVariant::Url:
494                             *reinterpret_cast<QUrl *>(a[0]) = data[id].asQUrl();
495                             break;
496                         case QVariant::Color:
497                             *reinterpret_cast<QColor *>(a[0]) = data[id].asQColor();
498                             break;
499                         case QVariant::Date:
500                             *reinterpret_cast<QDate *>(a[0]) = data[id].asQDate();
501                             break;
502                         case QVariant::DateTime:
503                             *reinterpret_cast<QDateTime *>(a[0]) = data[id].asQDateTime();
504                             break;
505                         case QMetaType::QObjectStar:
506                             *reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
507                             break;
508                         default:
509                             break;
510                         }
511                         if (t == qMetaTypeId<QDeclarativeListProperty<QObject> >()) {
512                             int listIndex = data[id].asInt();
513                             const List *list = &listProperties.at(listIndex);
514                             *reinterpret_cast<QDeclarativeListProperty<QObject> *>(a[0]) = 
515                                 QDeclarativeListProperty<QObject>(object, (void *)list,
516                                                                   list_append, list_count, list_at, 
517                                                                   list_clear);
518                         }
519
520                     } else if (c == QMetaObject::WriteProperty) {
521
522                         switch(t) {
523                         case QVariant::Int:
524                             needActivate = *reinterpret_cast<int *>(a[0]) != data[id].asInt();
525                             data[id].setValue(*reinterpret_cast<int *>(a[0]));
526                             break;
527                         case QVariant::Bool:
528                             needActivate = *reinterpret_cast<bool *>(a[0]) != data[id].asBool();
529                             data[id].setValue(*reinterpret_cast<bool *>(a[0]));
530                             break;
531                         case QVariant::Double:
532                             needActivate = *reinterpret_cast<double *>(a[0]) != data[id].asDouble();
533                             data[id].setValue(*reinterpret_cast<double *>(a[0]));
534                             break;
535                         case QVariant::String:
536                             needActivate = *reinterpret_cast<QString *>(a[0]) != data[id].asQString();
537                             data[id].setValue(*reinterpret_cast<QString *>(a[0]));
538                             break;
539                         case QVariant::Url:
540                             needActivate = *reinterpret_cast<QUrl *>(a[0]) != data[id].asQUrl();
541                             data[id].setValue(*reinterpret_cast<QUrl *>(a[0]));
542                             break;
543                         case QVariant::Color:
544                             needActivate = *reinterpret_cast<QColor *>(a[0]) != data[id].asQColor();
545                             data[id].setValue(*reinterpret_cast<QColor *>(a[0]));
546                             break;
547                         case QVariant::Date:
548                             needActivate = *reinterpret_cast<QDate *>(a[0]) != data[id].asQDate();
549                             data[id].setValue(*reinterpret_cast<QDate *>(a[0]));
550                             break;
551                         case QVariant::DateTime:
552                             needActivate = *reinterpret_cast<QDateTime *>(a[0]) != data[id].asQDateTime();
553                             data[id].setValue(*reinterpret_cast<QDateTime *>(a[0]));
554                             break;
555                         case QMetaType::QObjectStar:
556                             needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
557                             data[id].setValue(*reinterpret_cast<QObject **>(a[0]));
558                             break;
559                         default:
560                             break;
561                         }
562                     }
563
564                 }
565
566                 if (c == QMetaObject::WriteProperty && needActivate) {
567                     activate(object, methodOffset + id, 0);
568                 }
569
570                 return -1;
571             }
572
573             id -= metaData->propertyCount;
574
575             if (id < metaData->aliasCount) {
576
577                 QDeclarativeVMEMetaData::AliasData *d = metaData->aliasData() + id;
578
579                 if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty) 
580                         *reinterpret_cast<void **>(a[0]) = 0;
581
582                 if (!ctxt) return -1;
583
584                 QDeclarativeContext *context = ctxt->asQDeclarativeContext();
585                 QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context);
586
587                 QObject *target = ctxtPriv->data->idValues[d->contextIdx].data();
588                 if (!target) 
589                     return -1;
590
591                 connectAlias(id);
592
593                 if (d->isObjectAlias()) {
594                     *reinterpret_cast<QObject **>(a[0]) = target;
595                     return -1;
596                 } 
597                 
598                 // Remove binding (if any) on write
599                 if(c == QMetaObject::WriteProperty) {
600                     int flags = *reinterpret_cast<int*>(a[3]);
601                     if (flags & QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite) {
602                         QDeclarativeData *targetData = QDeclarativeData::get(target);
603                         if (targetData && targetData->hasBindingBit(d->propertyIndex())) {
604                             QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(target, d->propertyIndex(), d->isValueTypeAlias()?d->valueTypeIndex():-1, 0);
605                             if (binding) binding->destroy();
606                         }
607                     }
608                 }
609                 
610                 if (d->isValueTypeAlias()) {
611                     // Value type property
612                     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
613
614                     QDeclarativeValueType *valueType = ep->valueTypes[d->valueType()];
615                     Q_ASSERT(valueType);
616
617                     valueType->read(target, d->propertyIndex());
618                     int rv = QMetaObject::metacall(valueType, c, d->valueTypeIndex(), a);
619                     
620                     if (c == QMetaObject::WriteProperty)
621                         valueType->write(target, d->propertyIndex(), 0x00);
622
623                     return rv;
624
625                 } else {
626                     return QMetaObject::metacall(target, c, d->propertyIndex(), a);
627                 }
628
629             }
630             return -1;
631
632         }
633
634     } else if(c == QMetaObject::InvokeMetaMethod) {
635
636         if (id >= methodOffset) {
637
638             id -= methodOffset;
639             int plainSignals = metaData->signalCount + metaData->propertyCount +
640                                metaData->aliasCount;
641             if (id < plainSignals) {
642                 QMetaObject::activate(object, _id, a);
643                 return -1;
644             }
645
646             id -= plainSignals;
647
648             if (id < metaData->methodCount) {
649                 if (!ctxt->engine)
650                     return -1; // We can't run the method
651
652                 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
653                 ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
654
655                 v8::Handle<v8::Function> function = method(id);
656                 QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + id;
657
658                 v8::HandleScope handle_scope;
659                 v8::Context::Scope scope(ep->v8engine()->context());
660                 v8::Handle<v8::Value> *args = 0;
661
662                 if (data->parameterCount) {
663                     args = new v8::Handle<v8::Value>[data->parameterCount];
664                     for (int ii = 0; ii < data->parameterCount; ++ii) 
665                         args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
666                 }
667
668                 v8::TryCatch try_catch;
669
670                 v8::Local<v8::Value> result = function->Call(ep->v8engine()->global(), data->parameterCount, args);
671
672                 QVariant rv;
673                 if (try_catch.HasCaught()) {
674                     QDeclarativeError error;
675                     QDeclarativeExpressionPrivate::exceptionToError(try_catch.Message(), error);
676                     if (error.isValid())
677                         ep->warning(error);
678                     if (a[0]) *(QVariant *)a[0] = QVariant();
679                 } else {
680                     if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result, 0);
681                 }
682
683                 ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
684                 return -1;
685             }
686             return -1;
687         }
688     }
689
690     if (parent)
691         return parent->metaCall(c, _id, a);
692     else
693         return object->qt_metacall(c, _id, a);
694 }
695
696 v8::Handle<v8::Function> QDeclarativeVMEMetaObject::method(int index)
697 {
698     if (!v8methods) 
699         v8methods = new v8::Persistent<v8::Function>[metaData->methodCount];
700
701     if (v8methods[index].IsEmpty()) {
702         QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + index;
703
704         const QChar *body = 
705             (const QChar *)(((const char*)metaData) + data->bodyOffset);
706
707         QString code = QString::fromRawData(body, data->bodyLength);
708
709         // XXX We should evaluate all methods in a single big script block to 
710         // improve the call time between dynamic methods defined on the same
711         // object
712         v8methods[index] = QDeclarativeExpressionPrivate::evalFunction(ctxt, object, code, ctxt->url.toString(),
713                                                                        data->lineNumber);
714     }
715
716     return v8methods[index];
717 }
718
719 #if 0
720 QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id)
721 {
722     if (data[id].dataType() == qMetaTypeId<QScriptValue>())
723         return data[id].asQJSValue();
724     else if (data[id].dataType() == QMetaType::QObjectStar) 
725         return QDeclarativeEnginePrivate::get(ctxt->engine)->objectClass->newQObject(data[id].asQObject());
726     else
727         return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueFromVariant(data[id].asQVariant());
728 }
729 #endif
730
731 QVariant QDeclarativeVMEMetaObject::readVarPropertyAsVariant(int id)
732 {
733 #if 0
734     if (data[id].dataType() == qMetaTypeId<QScriptValue>())
735         return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueToVariant(data[id].asQJSValue());
736     else 
737 #endif
738     if (data[id].dataType() == QMetaType::QObjectStar) 
739         return QVariant::fromValue(data[id].asQObject());
740     else 
741         return data[id].asQVariant();
742 }
743
744 #if 0
745 void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QScriptValue &value)
746 {
747     data[id].setValue(value);
748     activate(object, methodOffset + id, 0);
749 }
750 #endif
751
752 void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QVariant &value)
753 {
754     bool needActivate = false;
755     if (value.userType() == QMetaType::QObjectStar) {
756         QObject *o = qvariant_cast<QObject *>(value);
757         needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o);
758         data[id].setValue(qvariant_cast<QObject *>(value));
759     } else {
760         needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() || 
761                         data[id].asQVariant().userType() != value.userType() || 
762                         data[id].asQVariant() != value);
763         data[id].setValue(value);
764     }
765     if (needActivate)
766         activate(object, methodOffset + id, 0);
767 }
768
769 void QDeclarativeVMEMetaObject::listChanged(int id)
770 {
771     activate(object, methodOffset + id, 0);
772 }
773
774 void QDeclarativeVMEMetaObject::list_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
775 {
776     List *list = static_cast<List *>(prop->data);
777     list->append(o);
778     QMetaObject::activate(prop->object, list->notifyIndex, 0);
779 }
780
781 int QDeclarativeVMEMetaObject::list_count(QDeclarativeListProperty<QObject> *prop)
782 {
783     return static_cast<List *>(prop->data)->count();
784 }
785
786 QObject *QDeclarativeVMEMetaObject::list_at(QDeclarativeListProperty<QObject> *prop, int index)
787 {
788     return static_cast<List *>(prop->data)->at(index);
789 }
790
791 void QDeclarativeVMEMetaObject::list_clear(QDeclarativeListProperty<QObject> *prop)
792 {
793     List *list = static_cast<List *>(prop->data);
794     list->clear();
795     QMetaObject::activate(prop->object, list->notifyIndex, 0);
796 }
797
798 void QDeclarativeVMEMetaObject::registerInterceptor(int index, int valueIndex, QDeclarativePropertyValueInterceptor *interceptor)
799 {
800     if (aInterceptors.isEmpty())
801         aInterceptors.resize(propertyCount() + metaData->propertyCount);
802     aInterceptors.setBit(index);
803     interceptors.insert(index, qMakePair(valueIndex, interceptor));
804 }
805
806 int QDeclarativeVMEMetaObject::vmeMethodLineNumber(int index)
807 {
808     if (index < methodOffset) {
809         Q_ASSERT(parent);
810         return static_cast<QDeclarativeVMEMetaObject *>(parent)->vmeMethodLineNumber(index);
811     }
812
813     int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
814     Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
815
816     int rawIndex = index - methodOffset - plainSignals;
817
818     QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + rawIndex;
819     return data->lineNumber;
820 }
821
822 v8::Handle<v8::Function> QDeclarativeVMEMetaObject::vmeMethod(int index)
823 {
824     if (index < methodOffset) {
825         Q_ASSERT(parent);
826         return static_cast<QDeclarativeVMEMetaObject *>(parent)->vmeMethod(index);
827     }
828     int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
829     Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
830     return method(index - methodOffset - plainSignals);
831 }
832
833 // Used by debugger
834 void QDeclarativeVMEMetaObject::setVmeMethod(int index, v8::Persistent<v8::Function> value)
835 {
836     if (index < methodOffset) {
837         Q_ASSERT(parent);
838         return static_cast<QDeclarativeVMEMetaObject *>(parent)->setVmeMethod(index, value);
839     }
840     int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
841     Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
842
843     if (!v8methods) 
844         v8methods = new v8::Persistent<v8::Function>[metaData->methodCount];
845
846     int methodIndex = index - methodOffset - plainSignals;
847     if (!v8methods[methodIndex].IsEmpty()) 
848         qPersistentDispose(v8methods[methodIndex]);
849     v8methods[methodIndex] = value;
850 }
851
852 #if 0
853 QScriptValue QDeclarativeVMEMetaObject::vmeProperty(int index)
854 {
855     if (index < propOffset) {
856         Q_ASSERT(parent);
857         return static_cast<QDeclarativeVMEMetaObject *>(parent)->vmeProperty(index);
858     }
859     return readVarProperty(index - propOffset);
860 }
861
862 void QDeclarativeVMEMetaObject::setVMEProperty(int index, const QScriptValue &v)
863 {
864     if (index < propOffset) {
865         Q_ASSERT(parent);
866         static_cast<QDeclarativeVMEMetaObject *>(parent)->setVMEProperty(index, v);
867     }
868     return writeVarProperty(index - propOffset, v);
869 }
870 #endif
871
872 bool QDeclarativeVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
873 {
874     Q_ASSERT(index >= propOffset + metaData->propertyCount);
875
876     *target = 0;
877     *coreIndex = -1;
878     *valueTypeIndex = -1;
879
880     if (!ctxt)
881         return false;
882
883     QDeclarativeVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset - metaData->propertyCount);
884     QDeclarativeContext *context = ctxt->asQDeclarativeContext();
885     QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context);
886
887     *target = ctxtPriv->data->idValues[d->contextIdx].data();
888     if (!*target)
889         return false;
890
891     if (d->isObjectAlias()) {
892     } else if (d->isValueTypeAlias()) {
893         *coreIndex = d->propertyIndex();
894         *valueTypeIndex = d->valueTypeIndex();
895     } else {
896         *coreIndex = d->propertyIndex();
897     }
898
899     return true;
900 }
901
902 void QDeclarativeVMEMetaObject::connectAlias(int aliasId)
903 {
904     if (!aConnected.testBit(aliasId)) {
905         aConnected.setBit(aliasId);
906
907         QDeclarativeContext *context = ctxt->asQDeclarativeContext();
908         QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context);
909
910         QDeclarativeVMEMetaData::AliasData *d = metaData->aliasData() + aliasId;
911
912         QObject *target = ctxtPriv->data->idValues[d->contextIdx].data();
913         if (!target) 
914             return;
915
916         int sigIdx = methodOffset + aliasId + metaData->propertyCount;
917         QMetaObject::connect(context, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx);
918
919         if (!d->isObjectAlias()) {
920             QMetaProperty prop = target->metaObject()->property(d->propertyIndex());
921             if (prop.hasNotifySignal())
922                 QDeclarativePropertyPrivate::connect(target, prop.notifySignalIndex(), object, sigIdx);
923         }
924     }
925 }
926
927 void QDeclarativeVMEMetaObject::connectAliasSignal(int index)
928 {
929     int aliasId = (index - methodOffset) - metaData->propertyCount;
930     if (aliasId < 0 || aliasId >= metaData->aliasCount)
931         return;
932
933     connectAlias(aliasId);
934 }
935
936 QT_END_NAMESPACE