Initial import from qtquick2.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativevme.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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativevme_p.h"
43
44 #include "private/qdeclarativecompiler_p.h"
45 #include "private/qdeclarativeboundsignal_p.h"
46 #include "private/qdeclarativestringconverters_p.h"
47 #include "private/qmetaobjectbuilder_p.h"
48 #include "private/qdeclarativedata_p.h"
49 #include "qdeclarative.h"
50 #include "private/qdeclarativecustomparser_p.h"
51 #include "qdeclarativeengine.h"
52 #include "qdeclarativecontext.h"
53 #include "qdeclarativecomponent.h"
54 #include "private/qdeclarativebinding_p.h"
55 #include "private/qdeclarativeengine_p.h"
56 #include "private/qdeclarativecomponent_p.h"
57 #include "private/qdeclarativevmemetaobject_p.h"
58 #include "private/qdeclarativebinding_p_p.h"
59 #include "private/qdeclarativecontext_p.h"
60 #include "private/qdeclarativev4bindings_p.h"
61 #include "private/qdeclarativeglobal_p.h"
62 #include "private/qdeclarativeglobalscriptclass_p.h"
63 #include "qdeclarativescriptstring.h"
64
65 #include <QStack>
66 #include <QWidget>
67 #include <QColor>
68 #include <QPointF>
69 #include <QSizeF>
70 #include <QRectF>
71 #include <QtCore/qdebug.h>
72 #include <QtCore/qvarlengtharray.h>
73 #include <QtCore/qcoreapplication.h>
74 #include <QtCore/qdatetime.h>
75 #include <QtScript/qscriptvalue.h>
76
77 QT_BEGIN_NAMESPACE
78
79 QDeclarativeVME::QDeclarativeVME()
80 {
81 }
82
83 #define VME_EXCEPTION(desc) \
84     { \
85         QDeclarativeError error; \
86         error.setDescription(desc.trimmed()); \
87         error.setLine(instr.line); \
88         error.setUrl(comp->url); \
89         vmeErrors << error; \
90         break; \
91     }
92
93 struct ListInstance
94 {
95     ListInstance() 
96         : type(0) {}
97     ListInstance(int t) 
98         : type(t) {}
99
100     int type;
101     QDeclarativeListProperty<void> qListProperty;
102 };
103
104 QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, 
105                               int start, int count, const QBitField &bindingSkipList)
106 {
107     QDeclarativeVMEStack<QObject *> stack;
108
109     if (start == -1) start = 0;
110     if (count == -1) count = comp->bytecode.count();
111
112     return run(stack, ctxt, comp, start, count, bindingSkipList);
113 }
114
115 void QDeclarativeVME::runDeferred(QObject *object)
116 {
117     QDeclarativeData *data = QDeclarativeData::get(object);
118
119     if (!data || !data->context || !data->deferredComponent)
120         return;
121
122     QDeclarativeContextData *ctxt = data->context;
123     QDeclarativeCompiledData *comp = data->deferredComponent;
124     int start = data->deferredIdx + 1;
125     int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount;
126     QDeclarativeVMEStack<QObject *> stack;
127     stack.push(object);
128
129     run(stack, ctxt, comp, start, count, QBitField());
130 }
131
132 inline bool fastHasBinding(QObject *o, int index) 
133 {
134     QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
135
136     return ddata && (ddata->bindingBitsSize > index) && 
137            (ddata->bindingBits[index / 32] & (1 << (index % 32)));
138 }
139
140 static void removeBindingOnProperty(QObject *o, int index)
141 {
142     QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
143     if (binding) binding->destroy();
144 }
145
146 #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
147
148 QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, 
149                               QDeclarativeContextData *ctxt, 
150                               QDeclarativeCompiledData *comp, 
151                               int start, int count, 
152                               const QBitField &bindingSkipList)
153 {
154     Q_ASSERT(comp);
155     Q_ASSERT(ctxt);
156     const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types;
157     const QList<QString> &primitives = comp->primitives;
158     const QList<QByteArray> &datas = comp->datas;
159     const QList<QDeclarativeCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
160     const QList<int> &intData = comp->intData;
161     const QList<float> &floatData = comp->floatData;
162     const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches;
163     const QList<QDeclarativeScriptData *> &scripts = comp->scripts;
164     const QList<QUrl> &urls = comp->urls;
165
166     QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues;
167     QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus;
168
169     QDeclarativeVMEStack<ListInstance> qliststack;
170
171     vmeErrors.clear();
172     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
173
174     int status = -1;    //for dbus
175     QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
176                                                     QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
177
178     for (int ii = start; !isError() && ii < (start + count); ++ii) {
179         const QDeclarativeInstruction &instr = comp->bytecode.at(ii);
180
181         switch(instr.type) {
182         case QDeclarativeInstruction::Init:
183             {
184                 if (instr.init.bindingsSize) 
185                     bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.init.bindingsSize);
186                 if (instr.init.parserStatusSize)
187                     parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.init.parserStatusSize);
188                 if (instr.init.contextCache != -1) 
189                     ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
190                 if (instr.init.compiledBinding != -1) 
191                     ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.init.compiledBinding).constData(), ctxt);
192             }
193             break;
194
195         case QDeclarativeInstruction::CreateObject:
196             {
197                 QBitField bindings;
198                 if (instr.create.bindingBits != -1) {
199                     const QByteArray &bits = datas.at(instr.create.bindingBits);
200                     bindings = QBitField((const quint32*)bits.constData(),
201                                          bits.size() * 8);
202                 }
203                 if (stack.isEmpty())
204                     bindings = bindings.united(bindingSkipList);
205
206                 QObject *o = 
207                     types.at(instr.create.type).createInstance(ctxt, bindings, &vmeErrors);
208
209                 if (!o) {
210                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)));
211                 }
212
213                 QDeclarativeData *ddata = QDeclarativeData::get(o);
214                 Q_ASSERT(ddata);
215
216                 if (stack.isEmpty()) {
217                     if (ddata->context) {
218                         Q_ASSERT(ddata->context != ctxt);
219                         Q_ASSERT(ddata->outerContext);
220                         Q_ASSERT(ddata->outerContext != ctxt);
221                         QDeclarativeContextData *c = ddata->context;
222                         while (c->linkedContext) c = c->linkedContext;
223                         c->linkedContext = ctxt;
224                     } else {
225                         ctxt->addObject(o);
226                     }
227
228                     ddata->ownContext = true;
229                 } else if (!ddata->context) {
230                     ctxt->addObject(o);
231                 }
232
233                 ddata->setImplicitDestructible();
234                 ddata->outerContext = ctxt;
235                 ddata->lineNumber = instr.line;
236                 ddata->columnNumber = instr.create.column;
237
238                 if (instr.create.data != -1) {
239                     QDeclarativeCustomParser *customParser =
240                         types.at(instr.create.type).type->customParser();
241                     customParser->setCustomData(o, datas.at(instr.create.data));
242                 }
243                 if (!stack.isEmpty()) {
244                     QObject *parent = stack.top();
245                     if (o->isWidgetType()) { 
246                         QWidget *widget = static_cast<QWidget*>(o); 
247                         if (parent->isWidgetType()) { 
248                             QWidget *parentWidget = static_cast<QWidget*>(parent); 
249                             widget->setParent(parentWidget); 
250                         } else { 
251                             // TODO: parent might be a layout 
252                         } 
253                     } else { 
254                             QDeclarative_setParent_noEvent(o, parent);
255                     } 
256                 }
257                 stack.push(o);
258             }
259             break;
260
261         case QDeclarativeInstruction::CreateSimpleObject:
262             {
263                 QObject *o = (QObject *)operator new(instr.createSimple.typeSize + 
264                                                      sizeof(QDeclarativeData));   
265                 ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeData));
266                 instr.createSimple.create(o);
267
268                 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize);
269                 const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.createSimple.type);
270                 if (!ddata->propertyCache && ref.typePropertyCache) {
271                     ddata->propertyCache = ref.typePropertyCache;
272                     ddata->propertyCache->addref();
273                 }
274                 ddata->lineNumber = instr.line;
275                 ddata->columnNumber = instr.createSimple.column;
276
277                 QObjectPrivate::get(o)->declarativeData = ddata;                                                      
278                 ddata->context = ddata->outerContext = ctxt;
279                 ddata->nextContextObject = ctxt->contextObjects; 
280                 if (ddata->nextContextObject) 
281                     ddata->nextContextObject->prevContextObject = &ddata->nextContextObject; 
282                 ddata->prevContextObject = &ctxt->contextObjects; 
283                 ctxt->contextObjects = ddata; 
284
285                 QObject *parent = stack.top();                                                                    
286                 QDeclarative_setParent_noEvent(o, parent);                                                        
287
288                 stack.push(o);
289             }
290             break;
291
292         case QDeclarativeInstruction::SetId:
293             {
294                 QObject *target = stack.top();
295                 ctxt->setIdProperty(instr.setId.index, target);
296             }
297             break;
298
299
300         case QDeclarativeInstruction::SetDefault:
301             {
302                 ctxt->contextObject = stack.top();
303             }
304             break;
305
306         case QDeclarativeInstruction::CreateComponent:
307             {
308                 QDeclarativeComponent *qcomp = 
309                     new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count,
310                                               stack.isEmpty() ? 0 : stack.top());
311
312                 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
313                 Q_ASSERT(ddata);
314
315                 ctxt->addObject(qcomp);
316
317                 if (stack.isEmpty()) 
318                     ddata->ownContext = true;
319
320                 ddata->setImplicitDestructible();
321                 ddata->outerContext = ctxt;
322                 ddata->lineNumber = instr.line;
323                 ddata->columnNumber = instr.create.column;
324
325                 QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
326
327                 stack.push(qcomp);
328                 ii += instr.createComponent.count;
329             }
330             break;
331
332         case QDeclarativeInstruction::StoreMetaObject:
333             {
334                 QObject *target = stack.top();
335
336                 QMetaObject mo;
337                 const QByteArray &metadata = datas.at(instr.storeMeta.data);
338                 QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
339
340                 const QDeclarativeVMEMetaData *data = 
341                     (const QDeclarativeVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
342
343                 (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
344
345                 if (instr.storeMeta.propertyCache != -1) {
346                     QDeclarativeData *ddata = QDeclarativeData::get(target, true);
347                     if (ddata->propertyCache) ddata->propertyCache->release();
348                     ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache);
349                     ddata->propertyCache->addref();
350                 }
351             }
352             break;
353
354         case QDeclarativeInstruction::StoreVariant:
355             {
356                 QObject *target = stack.top();
357                 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
358
359                 // XXX - can be more efficient
360                 QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.storeString.value));
361                 void *a[] = { &v, 0, &status, &flags };
362                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
363                                       instr.storeString.propertyIndex, a);
364             }
365             break;
366
367         case QDeclarativeInstruction::StoreVariantInteger:
368             {
369                 QObject *target = stack.top();
370                 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
371
372                 QVariant v(instr.storeInteger.value);
373                 void *a[] = { &v, 0, &status, &flags };
374                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
375                                       instr.storeString.propertyIndex, a);
376             }
377             break;
378
379         case QDeclarativeInstruction::StoreVariantDouble:
380             {
381                 QObject *target = stack.top();
382                 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
383
384                 QVariant v(instr.storeDouble.value);
385                 void *a[] = { &v, 0, &status, &flags };
386                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
387                                       instr.storeString.propertyIndex, a);
388             }
389             break;
390
391         case QDeclarativeInstruction::StoreVariantBool:
392             {
393                 QObject *target = stack.top();
394                 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
395
396                 QVariant v(instr.storeBool.value);
397                 void *a[] = { &v, 0, &status, &flags };
398                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
399                                       instr.storeString.propertyIndex, a);
400             }
401             break;
402
403         case QDeclarativeInstruction::StoreString:
404             {
405                 QObject *target = stack.top();
406                 CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
407
408                 void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags };
409                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
410                                       instr.storeString.propertyIndex, a);
411             }
412             break;
413
414         case QDeclarativeInstruction::StoreByteArray:
415             {
416                 QObject *target = stack.top();
417                 void *a[] = { (void *)&datas.at(instr.storeByteArray.value), 0, &status, &flags };
418                 QMetaObject::metacall(target, QMetaObject::WriteProperty,
419                                       instr.storeByteArray.propertyIndex, a);
420             }
421             break;
422
423         case QDeclarativeInstruction::StoreUrl:
424             {
425                 QObject *target = stack.top();
426                 CLEAN_PROPERTY(target, instr.storeUrl.propertyIndex);
427
428                 void *a[] = { (void *)&urls.at(instr.storeUrl.value), 0, &status, &flags };
429                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
430                                       instr.storeUrl.propertyIndex, a);
431             }
432             break;
433
434         case QDeclarativeInstruction::StoreFloat:
435             {
436                 QObject *target = stack.top();
437                 CLEAN_PROPERTY(target, instr.storeFloat.propertyIndex);
438
439                 float f = instr.storeFloat.value;
440                 void *a[] = { &f, 0, &status, &flags };
441                 QMetaObject::metacall(target, QMetaObject::WriteProperty,
442                                       instr.storeFloat.propertyIndex, a);
443             }
444             break;
445
446         case QDeclarativeInstruction::StoreDouble:
447             {
448                 QObject *target = stack.top();
449                 CLEAN_PROPERTY(target, instr.storeDouble.propertyIndex);
450
451                 double d = instr.storeDouble.value;
452                 void *a[] = { &d, 0, &status, &flags };
453                 QMetaObject::metacall(target, QMetaObject::WriteProperty,
454                                       instr.storeDouble.propertyIndex, a);
455             }
456             break;
457
458         case QDeclarativeInstruction::StoreBool:
459             {
460                 QObject *target = stack.top();
461                 CLEAN_PROPERTY(target, instr.storeBool.propertyIndex);
462
463                 void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags };
464                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
465                                       instr.storeBool.propertyIndex, a);
466             }
467             break;
468
469         case QDeclarativeInstruction::StoreInteger:
470             {
471                 QObject *target = stack.top();
472                 CLEAN_PROPERTY(target, instr.storeInteger.propertyIndex);
473
474                 void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags };
475                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
476                                       instr.storeInteger.propertyIndex, a);
477             }
478             break;
479
480         case QDeclarativeInstruction::StoreColor:
481             {
482                 QObject *target = stack.top();
483                 CLEAN_PROPERTY(target, instr.storeColor.propertyIndex);
484
485                 QColor c = QColor::fromRgba(instr.storeColor.value);
486                 void *a[] = { &c, 0, &status, &flags };
487                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
488                                       instr.storeColor.propertyIndex, a);
489             }
490             break;
491
492         case QDeclarativeInstruction::StoreDate:
493             {
494                 QObject *target = stack.top();
495                 CLEAN_PROPERTY(target, instr.storeDate.propertyIndex);
496
497                 QDate d = QDate::fromJulianDay(instr.storeDate.value);
498                 void *a[] = { &d, 0, &status, &flags };
499                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
500                                       instr.storeDate.propertyIndex, a);
501             }
502             break;
503
504         case QDeclarativeInstruction::StoreTime:
505             {
506                 QObject *target = stack.top();
507                 CLEAN_PROPERTY(target, instr.storeTime.propertyIndex);
508
509                 QTime t;
510                 t.setHMS(intData.at(instr.storeTime.valueIndex),
511                          intData.at(instr.storeTime.valueIndex+1),
512                          intData.at(instr.storeTime.valueIndex+2),
513                          intData.at(instr.storeTime.valueIndex+3));
514                 void *a[] = { &t, 0, &status, &flags };
515                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
516                                       instr.storeTime.propertyIndex, a);
517             }
518             break;
519
520         case QDeclarativeInstruction::StoreDateTime:
521             {
522                 QObject *target = stack.top();
523                 CLEAN_PROPERTY(target, instr.storeDateTime.propertyIndex);
524
525                 QTime t;
526                 t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
527                          intData.at(instr.storeDateTime.valueIndex+2),
528                          intData.at(instr.storeDateTime.valueIndex+3),
529                          intData.at(instr.storeDateTime.valueIndex+4));
530                 QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
531                 void *a[] = { &dt, 0, &status, &flags };
532                 QMetaObject::metacall(target, QMetaObject::WriteProperty,
533                                       instr.storeDateTime.propertyIndex, a);
534             }
535             break;
536
537         case QDeclarativeInstruction::StorePoint:
538             {
539                 QObject *target = stack.top();
540                 CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
541
542                 QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
543                                    floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
544                 void *a[] = { &p, 0, &status, &flags };
545                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
546                                       instr.storeRealPair.propertyIndex, a);
547             }
548             break;
549
550         case QDeclarativeInstruction::StorePointF:
551             {
552                 QObject *target = stack.top();
553                 CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
554
555                 QPointF p(floatData.at(instr.storeRealPair.valueIndex),
556                           floatData.at(instr.storeRealPair.valueIndex+1));
557                 void *a[] = { &p, 0, &status, &flags };
558                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
559                                       instr.storeRealPair.propertyIndex, a);
560             }
561             break;
562
563         case QDeclarativeInstruction::StoreSize:
564             {
565                 QObject *target = stack.top();
566                 CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
567
568                 QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
569                                  floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
570                 void *a[] = { &p, 0, &status, &flags };
571                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
572                                       instr.storeRealPair.propertyIndex, a);
573             }
574             break;
575
576         case QDeclarativeInstruction::StoreSizeF:
577             {
578                 QObject *target = stack.top();
579                 CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
580
581                 QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
582                          floatData.at(instr.storeRealPair.valueIndex+1));
583                 void *a[] = { &s, 0, &status, &flags };
584                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
585                                       instr.storeRealPair.propertyIndex, a);
586             }
587             break;
588
589         case QDeclarativeInstruction::StoreRect:
590             {
591                 QObject *target = stack.top();
592                 CLEAN_PROPERTY(target, instr.storeRect.propertyIndex);
593
594                 QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
595                                  floatData.at(instr.storeRect.valueIndex+1),
596                                  floatData.at(instr.storeRect.valueIndex+2),
597                                  floatData.at(instr.storeRect.valueIndex+3)).toRect();
598                 void *a[] = { &r, 0, &status, &flags };
599                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
600                                       instr.storeRect.propertyIndex, a);
601             }
602             break;
603
604         case QDeclarativeInstruction::StoreRectF:
605             {
606                 QObject *target = stack.top();
607                 CLEAN_PROPERTY(target, instr.storeRect.propertyIndex);
608
609                 QRectF r(floatData.at(instr.storeRect.valueIndex),
610                          floatData.at(instr.storeRect.valueIndex+1),
611                          floatData.at(instr.storeRect.valueIndex+2),
612                          floatData.at(instr.storeRect.valueIndex+3));
613                 void *a[] = { &r, 0, &status, &flags };
614                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
615                                       instr.storeRect.propertyIndex, a);
616             }
617             break;
618
619         case QDeclarativeInstruction::StoreVector3D:
620             {
621                 QObject *target = stack.top();
622                 CLEAN_PROPERTY(target, instr.storeVector3D.propertyIndex);
623
624                 QVector3D p(floatData.at(instr.storeVector3D.valueIndex),
625                             floatData.at(instr.storeVector3D.valueIndex+1),
626                             floatData.at(instr.storeVector3D.valueIndex+2));
627                 void *a[] = { &p, 0, &status, &flags };
628                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
629                                       instr.storeVector3D.propertyIndex, a);
630             }
631             break;
632
633         case QDeclarativeInstruction::StoreObject:
634             {
635                 QObject *assignObj = stack.pop();
636                 QObject *target = stack.top();
637                 CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
638
639                 void *a[] = { (void *)&assignObj, 0, &status, &flags };
640                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
641                                       instr.storeObject.propertyIndex, a);
642             }
643             break;
644
645
646         case QDeclarativeInstruction::AssignCustomType:
647             {
648                 QObject *target = stack.top();
649                 CLEAN_PROPERTY(target, instr.assignCustomType.propertyIndex);
650
651                 QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
652                 const QString &primitive = primitives.at(data.index);
653                 QDeclarativeMetaType::StringConverter converter = 
654                     QDeclarativeMetaType::customStringConverter(data.type);
655                 QVariant v = (*converter)(primitive);
656
657                 QMetaProperty prop = 
658                         target->metaObject()->property(instr.assignCustomType.propertyIndex);
659                 if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) 
660                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())));
661
662                 void *a[] = { (void *)v.data(), 0, &status, &flags };
663                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
664                                       instr.assignCustomType.propertyIndex, a);
665             }
666             break;
667
668         case QDeclarativeInstruction::AssignSignalObject:
669             {
670                 // XXX optimize
671
672                 QObject *assign = stack.pop();
673                 QObject *target = stack.top();
674                 int sigIdx = instr.assignSignalObject.signal;
675                 const QByteArray &pr = datas.at(sigIdx);
676
677                 QDeclarativeProperty prop(target, QString::fromUtf8(pr));
678                 if (prop.type() & QDeclarativeProperty::SignalProperty) {
679
680                     QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
681                     if (method.signature() == 0)
682                         VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())));
683
684                     if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
685                         VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())));
686
687                     QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
688
689                 } else {
690                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)));
691                 }
692
693
694             }
695             break;
696
697         case QDeclarativeInstruction::StoreSignal:
698             {
699                 QObject *target = stack.top();
700                 QObject *context = stack.at(stack.count() - 1 - instr.storeSignal.context);
701
702                 QMetaMethod signal = target->metaObject()->method(instr.storeSignal.signalIndex);
703
704                 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
705                 QDeclarativeExpression *expr = 
706                     new QDeclarativeExpression(ctxt, context, primitives.at(instr.storeSignal.value));
707                 expr->setSourceLocation(comp->name, instr.line);
708                 static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.storeSignal.name);
709                 bs->setExpression(expr);
710             }
711             break;
712
713         case QDeclarativeInstruction::StoreImportedScript:
714             {
715                 ctxt->importedScripts << run(ctxt, scripts.at(instr.storeScript.value));
716             }
717             break;
718
719         case QDeclarativeInstruction::StoreScriptString:
720             {
721                 QObject *target = stack.top();
722                 QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope);
723                 QDeclarativeScriptString ss;
724                 ss.setContext(ctxt->asQDeclarativeContext());
725                 ss.setScopeObject(scope);
726                 ss.setScript(primitives.at(instr.storeScriptString.value));
727
728                 void *a[] = { &ss, 0, &status, &flags };
729                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
730                                       instr.storeScriptString.propertyIndex, a);
731             }
732             break;
733
734         case QDeclarativeInstruction::BeginObject:
735             {
736                 QObject *target = stack.top();
737                 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
738                 parserStatus.append(status);
739                 status->d = &parserStatus.values[parserStatus.count - 1];
740
741                 status->classBegin();
742             }
743             break;
744
745         case QDeclarativeInstruction::StoreBinding:
746         case QDeclarativeInstruction::StoreBindingOnAlias:
747             {
748                 QObject *target = 
749                     stack.at(stack.count() - 1 - instr.assignBinding.owner);
750                 QObject *context = 
751                     stack.at(stack.count() - 1 - instr.assignBinding.context);
752
753                 QDeclarativeProperty mp = 
754                     QDeclarativePropertyPrivate::restore(datas.at(instr.assignBinding.property), target, ctxt);
755
756                 int coreIndex = mp.index();
757
758                 if ((stack.count() - instr.assignBinding.owner) == 1 && bindingSkipList.testBit(coreIndex)) 
759                     break;
760
761                 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
762                 bindValues.append(bind);
763                 bind->m_mePtr = &bindValues.values[bindValues.count - 1];
764                 bind->setTarget(mp);
765
766                 if (instr.type == QDeclarativeInstruction::StoreBindingOnAlias) {
767                     QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
768                     if (old) { old->destroy(); }
769                 } else {
770                     bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
771                 }
772             }
773             break;
774
775         case QDeclarativeInstruction::StoreCompiledBinding:
776             {
777                 QObject *target = 
778                     stack.at(stack.count() - 1 - instr.assignBinding.owner);
779                 QObject *scope = 
780                     stack.at(stack.count() - 1 - instr.assignBinding.context);
781
782                 int property = instr.assignBinding.property;
783                 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))  
784                     break;
785
786                 QDeclarativeAbstractBinding *binding = 
787                     ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property);
788                 bindValues.append(binding);
789                 binding->m_mePtr = &bindValues.values[bindValues.count - 1];
790                 binding->addToObject(target, property);
791             }
792             break;
793
794         case QDeclarativeInstruction::StoreValueSource:
795             {
796                 QObject *obj = stack.pop();
797                 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.assignValueSource.castValue);
798                 QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner);
799
800                 QDeclarativeProperty prop = 
801                     QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueSource.property), target, ctxt);
802                 obj->setParent(target);
803                 vs->setTarget(prop);
804             }
805             break;
806
807         case QDeclarativeInstruction::StoreValueInterceptor:
808             {
809                 QObject *obj = stack.pop();
810                 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue);
811                 QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner);
812                 QDeclarativeProperty prop = 
813                     QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueInterceptor.property), target, ctxt);
814                 obj->setParent(target);
815                 vi->setTarget(prop);
816                 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
817                 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
818             }
819             break;
820
821         case QDeclarativeInstruction::StoreObjectQList:
822             {
823                 QObject *assign = stack.pop();
824
825                 const ListInstance &list = qliststack.top();
826                 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
827             }
828             break;
829
830         case QDeclarativeInstruction::AssignObjectList:
831             {
832                 // This is only used for assigning interfaces
833                 QObject *assign = stack.pop();
834                 const ListInstance &list = qliststack.top();
835
836                 int type = list.type;
837
838                 void *ptr = 0;
839
840                 const char *iid = QDeclarativeMetaType::interfaceIId(type);
841                 if (iid) 
842                     ptr = assign->qt_metacast(iid);
843                 if (!ptr) 
844                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"));
845
846
847                 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
848             }
849             break;
850
851         case QDeclarativeInstruction::StoreVariantObject:
852             {
853                 QObject *assign = stack.pop();
854                 QObject *target = stack.top();
855                 CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
856
857                 QVariant v = QVariant::fromValue(assign);
858                 void *a[] = { &v, 0, &status, &flags };
859                 QMetaObject::metacall(target, QMetaObject::WriteProperty, 
860                                       instr.storeObject.propertyIndex, a);
861             }
862             break;
863
864         case QDeclarativeInstruction::StoreInterface:
865             {
866                 QObject *assign = stack.pop();
867                 QObject *target = stack.top();
868                 CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
869
870                 int coreIdx = instr.storeObject.propertyIndex;
871                 QMetaProperty prop = target->metaObject()->property(coreIdx);
872                 int t = prop.userType();
873                 const char *iid = QDeclarativeMetaType::interfaceIId(t);
874                 bool ok = false;
875                 if (iid) {
876                     void *ptr = assign->qt_metacast(iid);
877                     if (ptr) {
878                         void *a[] = { &ptr, 0, &status, &flags };
879                         QMetaObject::metacall(target, 
880                                               QMetaObject::WriteProperty,
881                                               coreIdx, a);
882                         ok = true;
883                     }
884                 } 
885
886                 if (!ok) 
887                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"));
888             }
889             break;
890             
891         case QDeclarativeInstruction::FetchAttached:
892             {
893                 QObject *target = stack.top();
894
895                 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target);
896
897                 if (!qmlObject)
898                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"));
899
900                 stack.push(qmlObject);
901             }
902             break;
903
904         case QDeclarativeInstruction::FetchQList:
905             {
906                 QObject *target = stack.top();
907
908                 qliststack.push(ListInstance(instr.fetchQmlList.type));
909
910                 void *a[1];
911                 a[0] = (void *)&(qliststack.top().qListProperty);
912                 QMetaObject::metacall(target, QMetaObject::ReadProperty, 
913                                       instr.fetchQmlList.property, a);
914             }
915             break;
916
917         case QDeclarativeInstruction::FetchObject:
918             {
919                 QObject *target = stack.top();
920
921                 QObject *obj = 0;
922                 // NOTE: This assumes a cast to QObject does not alter the 
923                 // object pointer
924                 void *a[1];
925                 a[0] = &obj;
926                 QMetaObject::metacall(target, QMetaObject::ReadProperty, 
927                                       instr.fetch.property, a);
928
929                 if (!obj)
930                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name())));
931
932                 stack.push(obj);
933             }
934             break;
935
936         case QDeclarativeInstruction::PopQList:
937             {
938                 qliststack.pop();
939             }
940             break;
941
942         case QDeclarativeInstruction::Defer:
943             {
944                 if (instr.defer.deferCount) {
945                     QObject *target = stack.top();
946                     QDeclarativeData *data = 
947                         QDeclarativeData::get(target, true);
948                     comp->addref();
949                     data->deferredComponent = comp;
950                     data->deferredIdx = ii;
951                     ii += instr.defer.deferCount;
952                 }
953             }
954             break;
955
956         case QDeclarativeInstruction::PopFetchedObject:
957             {
958                 stack.pop();
959             }
960             break;
961
962         case QDeclarativeInstruction::FetchValueType:
963             {
964                 QObject *target = stack.top();
965
966                 if (instr.fetchValue.bindingSkipList != 0) {
967                     // Possibly need to clear bindings
968                     QDeclarativeData *targetData = QDeclarativeData::get(target);
969                     if (targetData) {
970                         QDeclarativeAbstractBinding *binding = 
971                             QDeclarativePropertyPrivate::binding(target, instr.fetchValue.property, -1);
972
973                         if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
974                             QDeclarativePropertyPrivate::setBinding(target, instr.fetchValue.property, -1, 0);
975                             binding->destroy();
976                         } else if (binding) {
977                             QDeclarativeValueTypeProxyBinding *proxy = 
978                                 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
979                             proxy->removeBindings(instr.fetchValue.bindingSkipList);
980                         }
981                     }
982                 }
983
984                 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.fetchValue.type];
985                 valueHandler->read(target, instr.fetchValue.property);
986                 stack.push(valueHandler);
987             }
988             break;
989
990         case QDeclarativeInstruction::PopValueType:
991             {
992                 QDeclarativeValueType *valueHandler = 
993                     static_cast<QDeclarativeValueType *>(stack.pop());
994                 QObject *target = stack.top();
995                 valueHandler->write(target, instr.fetchValue.property, 
996                                     QDeclarativePropertyPrivate::BypassInterceptor);
997             }
998             break;
999
1000         default:
1001             qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", instr.type);
1002             break;
1003         }
1004     }
1005
1006     if (isError()) {
1007         if (!stack.isEmpty()) {
1008             delete stack.at(0); // ### What about failures in deferred creation?
1009         } else {
1010             ctxt->destroy();
1011         }
1012
1013         QDeclarativeEnginePrivate::clear(bindValues);
1014         QDeclarativeEnginePrivate::clear(parserStatus);
1015         return 0;
1016     }
1017
1018     if (bindValues.count)
1019         ep->bindValues << bindValues;
1020     else if (bindValues.values)
1021         bindValues.clear();
1022
1023     if (parserStatus.count)
1024         ep->parserStatus << parserStatus;
1025     else if (parserStatus.values)
1026         parserStatus.clear();
1027
1028     Q_ASSERT(stack.count() == 1);
1029     return stack.top();
1030 }
1031
1032 bool QDeclarativeVME::isError() const
1033 {
1034     return !vmeErrors.isEmpty();
1035 }
1036
1037 QList<QDeclarativeError> QDeclarativeVME::errors() const
1038 {
1039     return vmeErrors;
1040 }
1041
1042 QObject *
1043 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
1044                                                         const QBitField &bindings,
1045                                                         QList<QDeclarativeError> *errors) const
1046 {
1047     if (type) {
1048         QObject *rv = 0;
1049         void *memory = 0;
1050
1051         type->create(&rv, &memory, sizeof(QDeclarativeData));
1052         QDeclarativeData *ddata = new (memory) QDeclarativeData;
1053         ddata->ownMemory = false;
1054         QObjectPrivate::get(rv)->declarativeData = ddata;
1055
1056         if (typePropertyCache && !ddata->propertyCache) {
1057             ddata->propertyCache = typePropertyCache;
1058             ddata->propertyCache->addref();
1059         }
1060
1061         return rv;
1062     } else {
1063         Q_ASSERT(component);
1064         return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, -1, 0, errors, bindings);
1065     } 
1066 }
1067
1068 QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1069 {
1070     if (script->m_loaded)
1071         return script->m_value;
1072
1073     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1074     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine);
1075
1076     bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
1077
1078     // Create the script context if required
1079     QDeclarativeContextData *ctxt = 0;
1080     if (!shared) {
1081         ctxt = new QDeclarativeContextData;
1082         ctxt->isInternal = true;
1083         ctxt->url = script->url;
1084
1085         // For backward compatibility, if there are no imports, we need to use the
1086         // imports from the parent context.  See QTBUG-17518.
1087         if (!script->importCache->isEmpty()) {
1088             ctxt->imports = script->importCache;
1089         } else {
1090             ctxt->imports = parentCtxt->imports;
1091         }
1092
1093         if (ctxt->imports) {
1094             ctxt->imports->addref();
1095         }
1096
1097         ctxt->setParent(parentCtxt, true);
1098
1099         for (int ii = 0; ii < script->scripts.count(); ++ii)
1100             ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1101     }
1102
1103     QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
1104     if (shared) {
1105         scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()?
1106     } else {
1107         scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString()));
1108     }
1109
1110     scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
1111     QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
1112     scriptContext->pushScope(scope);
1113
1114     scriptEngine->evaluate(script->m_program);
1115
1116     if (scriptEngine->hasUncaughtException()) {
1117         QDeclarativeError error;
1118         QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
1119         enginePriv->warning(error);
1120     }
1121
1122     scriptEngine->popContext();
1123
1124     if (shared) {
1125         script->m_loaded = true;
1126         script->m_value = scope;
1127     }
1128
1129     return scope;
1130 }
1131
1132 QT_END_NAMESPACE