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