Remove some QByteArray<->QString conversions
[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/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/qv8bindings_p.h"
62 #include "private/qdeclarativeglobal_p.h"
63 #include "qdeclarativescriptstring.h"
64 #include "qdeclarativescriptstring_p.h"
65
66 #include <QStack>
67 #include <QWidget>
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);
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 (o->isWidgetType()) { 
279                     QWidget *widget = static_cast<QWidget*>(o); 
280                     if (parent->isWidgetType()) { 
281                         QWidget *parentWidget = static_cast<QWidget*>(parent); 
282                         widget->setParent(parentWidget); 
283                     } else { 
284                         // TODO: parent might be a layout 
285                     } 
286                 } else { 
287                         QDeclarative_setParent_noEvent(o, parent);
288                 } 
289             }
290             stack.push(o);
291         QML_END_INSTR(CreateObject)
292
293         QML_BEGIN_INSTR(CreateSimpleObject)
294             QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));   
295             ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
296             instr.create(o);
297
298             QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
299             const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.type);
300             if (!ddata->propertyCache && ref.typePropertyCache) {
301                 ddata->propertyCache = ref.typePropertyCache;
302                 ddata->propertyCache->addref();
303             }
304             ddata->lineNumber = instr.line;
305             ddata->columnNumber = instr.column;
306
307             QObjectPrivate::get(o)->declarativeData = ddata;                                                      
308             ddata->context = ddata->outerContext = ctxt;
309             ddata->nextContextObject = ctxt->contextObjects; 
310             if (ddata->nextContextObject) 
311                 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject; 
312             ddata->prevContextObject = &ctxt->contextObjects; 
313             ctxt->contextObjects = ddata; 
314
315             QObject *parent = stack.top();                                                                    
316             QDeclarative_setParent_noEvent(o, parent);                                                        
317
318             stack.push(o);
319         QML_END_INSTR(CreateSimpleObject)
320
321         QML_BEGIN_INSTR(SetId)
322             QObject *target = stack.top();
323             ctxt->setIdProperty(instr.index, target);
324         QML_END_INSTR(SetId)
325
326         QML_BEGIN_INSTR(SetDefault)
327             ctxt->contextObject = stack.top();
328         QML_END_INSTR(SetDefault)
329
330         QML_BEGIN_INSTR(CreateComponent)
331             QDeclarativeComponent *qcomp = 
332                 new QDeclarativeComponent(ctxt->engine, comp, instructionStream - comp->bytecode.constData(),
333                                           stack.isEmpty() ? 0 : stack.top());
334
335             QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
336             Q_ASSERT(ddata);
337
338             ctxt->addObject(qcomp);
339
340             if (stack.isEmpty()) 
341                 ddata->ownContext = true;
342
343             ddata->setImplicitDestructible();
344             ddata->outerContext = ctxt;
345             ddata->lineNumber = instr.line;
346             ddata->columnNumber = instr.column;
347
348             QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
349
350             stack.push(qcomp);
351             instructionStream += instr.count;
352         QML_END_INSTR(CreateComponent)
353
354         QML_BEGIN_INSTR(StoreMetaObject)
355             QObject *target = stack.top();
356
357             QMetaObject mo;
358             const QByteArray &metadata = datas.at(instr.data);
359             QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
360
361             const QDeclarativeVMEMetaData *data = 
362                 (const QDeclarativeVMEMetaData *)datas.at(instr.aliasData).constData();
363
364             (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
365
366             if (instr.propertyCache != -1) {
367                 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
368                 if (ddata->propertyCache) ddata->propertyCache->release();
369                 ddata->propertyCache = propertyCaches.at(instr.propertyCache);
370                 ddata->propertyCache->addref();
371             }
372         QML_END_INSTR(StoreMetaObject)
373
374         QML_BEGIN_INSTR(StoreVariant)
375             QObject *target = stack.top();
376             CLEAN_PROPERTY(target, instr.propertyIndex);
377
378             // XXX - can be more efficient
379             QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.value));
380             void *a[] = { &v, 0, &status, &flags };
381             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
382                                   instr.propertyIndex, a);
383         QML_END_INSTR(StoreVariant)
384
385         QML_BEGIN_INSTR(StoreVariantInteger)
386             QObject *target = stack.top();
387             CLEAN_PROPERTY(target, instr.propertyIndex);
388
389             QVariant v(instr.value);
390             void *a[] = { &v, 0, &status, &flags };
391             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
392                                   instr.propertyIndex, a);
393         QML_END_INSTR(StoreVariantInteger)
394
395         QML_BEGIN_INSTR(StoreVariantDouble)
396             QObject *target = stack.top();
397             CLEAN_PROPERTY(target, instr.propertyIndex);
398
399             QVariant v(instr.value);
400             void *a[] = { &v, 0, &status, &flags };
401             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
402                                   instr.propertyIndex, a);
403         QML_END_INSTR(StoreVariantDouble)
404
405         QML_BEGIN_INSTR(StoreVariantBool)
406             QObject *target = stack.top();
407             CLEAN_PROPERTY(target, instr.propertyIndex);
408
409             QVariant v(instr.value);
410             void *a[] = { &v, 0, &status, &flags };
411             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
412                                   instr.propertyIndex, a);
413         QML_END_INSTR(StoreVariantBool)
414
415         QML_BEGIN_INSTR(StoreString)
416             QObject *target = stack.top();
417             CLEAN_PROPERTY(target, instr.propertyIndex);
418
419             void *a[] = { (void *)&primitives.at(instr.value), 0, &status, &flags };
420             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
421                                   instr.propertyIndex, a);
422         QML_END_INSTR(StoreString)
423
424         QML_BEGIN_INSTR(StoreByteArray)
425             QObject *target = stack.top();
426             void *a[] = { (void *)&datas.at(instr.value), 0, &status, &flags };
427             QMetaObject::metacall(target, QMetaObject::WriteProperty,
428                                   instr.propertyIndex, a);
429         QML_END_INSTR(StoreByteArray)
430
431         QML_BEGIN_INSTR(StoreUrl)
432             QObject *target = stack.top();
433             CLEAN_PROPERTY(target, instr.propertyIndex);
434
435             void *a[] = { (void *)&urls.at(instr.value), 0, &status, &flags };
436             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
437                                   instr.propertyIndex, a);
438         QML_END_INSTR(StoreUrl)
439
440         QML_BEGIN_INSTR(StoreFloat)
441             QObject *target = stack.top();
442             CLEAN_PROPERTY(target, instr.propertyIndex);
443
444             float f = instr.value;
445             void *a[] = { &f, 0, &status, &flags };
446             QMetaObject::metacall(target, QMetaObject::WriteProperty,
447                                   instr.propertyIndex, a);
448         QML_END_INSTR(StoreFloat)
449
450         QML_BEGIN_INSTR(StoreDouble)
451             QObject *target = stack.top();
452             CLEAN_PROPERTY(target, instr.propertyIndex);
453
454             double d = instr.value;
455             void *a[] = { &d, 0, &status, &flags };
456             QMetaObject::metacall(target, QMetaObject::WriteProperty,
457                                   instr.propertyIndex, a);
458         QML_END_INSTR(StoreDouble)
459
460         QML_BEGIN_INSTR(StoreBool)
461             QObject *target = stack.top();
462             CLEAN_PROPERTY(target, instr.propertyIndex);
463
464             void *a[] = { (void *)&instr.value, 0, &status, &flags };
465             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
466                                   instr.propertyIndex, a);
467         QML_END_INSTR(StoreBool)
468
469         QML_BEGIN_INSTR(StoreInteger)
470             QObject *target = stack.top();
471             CLEAN_PROPERTY(target, instr.propertyIndex);
472
473             void *a[] = { (void *)&instr.value, 0, &status, &flags };
474             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
475                                   instr.propertyIndex, a);
476         QML_END_INSTR(StoreInteger)
477
478         QML_BEGIN_INSTR(StoreColor)
479             QObject *target = stack.top();
480             CLEAN_PROPERTY(target, instr.propertyIndex);
481
482             QColor c = QColor::fromRgba(instr.value);
483             void *a[] = { &c, 0, &status, &flags };
484             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
485                                   instr.propertyIndex, a);
486         QML_END_INSTR(StoreColor)
487
488         QML_BEGIN_INSTR(StoreDate)
489             QObject *target = stack.top();
490             CLEAN_PROPERTY(target, instr.propertyIndex);
491
492             QDate d = QDate::fromJulianDay(instr.value);
493             void *a[] = { &d, 0, &status, &flags };
494             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
495                                   instr.propertyIndex, a);
496         QML_END_INSTR(StoreDate)
497
498         QML_BEGIN_INSTR(StoreTime)
499             QObject *target = stack.top();
500             CLEAN_PROPERTY(target, instr.propertyIndex);
501
502             QTime *t = (QTime *)&instr.time;
503             void *a[] = { t, 0, &status, &flags };
504             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
505                                   instr.propertyIndex, a);
506         QML_END_INSTR(StoreTime)
507
508         QML_BEGIN_INSTR(StoreDateTime)
509             QObject *target = stack.top();
510             CLEAN_PROPERTY(target, instr.propertyIndex);
511
512             QTime *t = (QTime *)&instr.time;
513             QDateTime dt(QDate::fromJulianDay(instr.date), *t);
514             void *a[] = { &dt, 0, &status, &flags };
515             QMetaObject::metacall(target, QMetaObject::WriteProperty,
516                                   instr.propertyIndex, a);
517         QML_END_INSTR(StoreDateTime)
518
519         QML_BEGIN_INSTR(StorePoint)
520             QObject *target = stack.top();
521             CLEAN_PROPERTY(target, instr.propertyIndex);
522
523             QPoint *p = (QPoint *)&instr.point;
524             void *a[] = { p, 0, &status, &flags };
525             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
526                                   instr.propertyIndex, a);
527         QML_END_INSTR(StorePoint)
528
529         QML_BEGIN_INSTR(StorePointF)
530             QObject *target = stack.top();
531             CLEAN_PROPERTY(target, instr.propertyIndex);
532
533             QPointF *p = (QPointF *)&instr.point;
534             void *a[] = { p, 0, &status, &flags };
535             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
536                                   instr.propertyIndex, a);
537         QML_END_INSTR(StorePointF)
538
539         QML_BEGIN_INSTR(StoreSize)
540             QObject *target = stack.top();
541             CLEAN_PROPERTY(target, instr.propertyIndex);
542
543             QSize *s = (QSize *)&instr.size;
544             void *a[] = { s, 0, &status, &flags };
545             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
546                                   instr.propertyIndex, a);
547         QML_END_INSTR(StoreSize)
548
549         QML_BEGIN_INSTR(StoreSizeF)
550             QObject *target = stack.top();
551             CLEAN_PROPERTY(target, instr.propertyIndex);
552
553             QSizeF *s = (QSizeF *)&instr.size;
554             void *a[] = { s, 0, &status, &flags };
555             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
556                                   instr.propertyIndex, a);
557         QML_END_INSTR(StoreSizeF)
558
559         QML_BEGIN_INSTR(StoreRect)
560             QObject *target = stack.top();
561             CLEAN_PROPERTY(target, instr.propertyIndex);
562
563             QRect *r = (QRect *)&instr.rect;
564             void *a[] = { r, 0, &status, &flags };
565             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
566                                   instr.propertyIndex, a);
567         QML_END_INSTR(StoreRect)
568
569         QML_BEGIN_INSTR(StoreRectF)
570             QObject *target = stack.top();
571             CLEAN_PROPERTY(target, instr.propertyIndex);
572
573             QRectF *r = (QRectF *)&instr.rect;
574             void *a[] = { r, 0, &status, &flags };
575             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
576                                   instr.propertyIndex, a);
577         QML_END_INSTR(StoreRectF)
578
579         QML_BEGIN_INSTR(StoreVector3D)
580             QObject *target = stack.top();
581             CLEAN_PROPERTY(target, instr.propertyIndex);
582
583             QVector3D *v = (QVector3D *)&instr.vector;
584             void *a[] = { v, 0, &status, &flags };
585             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
586                                   instr.propertyIndex, a);
587         QML_END_INSTR(StoreVector3D)
588
589         QML_BEGIN_INSTR(StoreVector4D)
590             QObject *target = stack.top();
591             CLEAN_PROPERTY(target, instr.propertyIndex);
592
593             QVector4D *v = (QVector4D *)&instr.vector;
594             void *a[] = { v, 0, &status, &flags };
595             QMetaObject::metacall(target, QMetaObject::WriteProperty,
596                                   instr.propertyIndex, a);
597         QML_END_INSTR(StoreVector4D)
598
599         QML_BEGIN_INSTR(StoreObject)
600             QObject *assignObj = stack.pop();
601             QObject *target = stack.top();
602             CLEAN_PROPERTY(target, instr.propertyIndex);
603
604             void *a[] = { (void *)&assignObj, 0, &status, &flags };
605             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
606                                   instr.propertyIndex, a);
607         QML_END_INSTR(StoreObject)
608
609         QML_BEGIN_INSTR(AssignCustomType)
610             QObject *target = stack.top();
611             CLEAN_PROPERTY(target, instr.propertyIndex);
612
613             const QString &primitive = primitives.at(instr.primitive);
614             int type = instr.type;
615             QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
616             QVariant v = (*converter)(primitive);
617
618             QMetaProperty prop = 
619                     target->metaObject()->property(instr.propertyIndex);
620             if (v.isNull() || ((int)prop.type() != type && prop.userType() != type)) 
621                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
622
623             void *a[] = { (void *)v.data(), 0, &status, &flags };
624             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
625                                   instr.propertyIndex, a);
626         QML_END_INSTR(AssignCustomType)
627
628         QML_BEGIN_INSTR(AssignSignalObject)
629             // XXX optimize
630
631             QObject *assign = stack.pop();
632             QObject *target = stack.top();
633             int sigIdx = instr.signal;
634             const QString &pr = primitives.at(sigIdx);
635
636             QDeclarativeProperty prop(target, pr);
637             if (prop.type() & QDeclarativeProperty::SignalProperty) {
638
639                 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
640                 if (method.signature() == 0)
641                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
642
643                 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
644                     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);
645
646                 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
647
648             } else {
649                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(pr), instr.line);
650             }
651
652
653         QML_END_INSTR(AssignSignalObject)
654
655         QML_BEGIN_INSTR(StoreSignal)
656             QObject *target = stack.top();
657             QObject *context = stack.at(stack.count() - 1 - instr.context);
658
659             QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
660
661             QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
662             QDeclarativeExpression *expr = 
663                 new QDeclarativeExpression(ctxt, context, primitives.at(instr.value));
664             expr->setSourceLocation(comp->name, instr.line);
665             static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.name);
666             bs->setExpression(expr);
667         QML_END_INSTR(StoreSignal)
668
669         QML_BEGIN_INSTR(StoreImportedScript)
670             ctxt->importedScripts << run(ctxt, scripts.at(instr.value));
671         QML_END_INSTR(StoreImportedScript)
672
673         QML_BEGIN_INSTR(StoreScriptString)
674             QObject *target = stack.top();
675             QObject *scope = stack.at(stack.count() - 1 - instr.scope);
676             QDeclarativeScriptString ss;
677             ss.setContext(ctxt->asQDeclarativeContext());
678             ss.setScopeObject(scope);
679             ss.setScript(primitives.at(instr.value));
680             ss.d.data()->bindingId = instr.bindingId;
681             ss.d.data()->lineNumber = instr.line;
682
683             void *a[] = { &ss, 0, &status, &flags };
684             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
685                                   instr.propertyIndex, a);
686         QML_END_INSTR(StoreScriptString)
687
688         QML_BEGIN_INSTR(BeginObject)
689             QObject *target = stack.top();
690             QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
691             parserStatus.append(status);
692             status->d = &parserStatus.values[parserStatus.count - 1];
693
694             status->classBegin();
695         QML_END_INSTR(BeginObject)
696
697         QML_BEGIN_INSTR(InitV8Bindings)
698             ctxt->v8bindings = new QV8Bindings(primitives.at(instr.program), instr.programIndex, 
699                                                instr.line, comp, ctxt);
700         QML_END_INSTR(InitV8Bindings)
701
702         QML_BEGIN_INSTR(StoreBinding)
703             QObject *target = 
704                 stack.at(stack.count() - 1 - instr.owner);
705             QObject *context = 
706                 stack.at(stack.count() - 1 - instr.context);
707
708             QDeclarativeProperty mp = 
709                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
710
711             int coreIndex = mp.index();
712
713             if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex)) 
714                 break;
715
716             QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true, 
717                                                                 context, ctxt, comp->name, instr.line);
718             bindValues.append(bind);
719             bind->m_mePtr = &bindValues.values[bindValues.count - 1];
720             bind->setTarget(mp);
721
722             bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
723         QML_END_INSTR(StoreBinding)
724
725         QML_BEGIN_INSTR(StoreBindingOnAlias)
726             QObject *target = 
727                 stack.at(stack.count() - 1 - instr.owner);
728             QObject *context = 
729                 stack.at(stack.count() - 1 - instr.context);
730
731             QDeclarativeProperty mp = 
732                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
733
734             int coreIndex = mp.index();
735
736             if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex)) 
737                 break;
738
739             QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
740                                                                 context, ctxt, comp->name, instr.line);
741             bindValues.append(bind);
742             bind->m_mePtr = &bindValues.values[bindValues.count - 1];
743             bind->setTarget(mp);
744
745             QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
746             if (old) { old->destroy(); }
747         QML_END_INSTR(StoreBindingOnAlias)
748
749         QML_BEGIN_INSTR(StoreV4Binding)
750             QObject *target = 
751                 stack.at(stack.count() - 1 - instr.owner);
752             QObject *scope = 
753                 stack.at(stack.count() - 1 - instr.context);
754
755             int property = instr.property;
756             if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))  
757                 break;
758
759             QDeclarativeAbstractBinding *binding = 
760                 ctxt->v4bindings->configBinding(instr.value, target, scope, property);
761             bindValues.append(binding);
762             binding->m_mePtr = &bindValues.values[bindValues.count - 1];
763             binding->addToObject(target, property);
764         QML_END_INSTR(StoreV4Binding)
765
766         QML_BEGIN_INSTR(StoreV8Binding)
767             QObject *target = 
768                 stack.at(stack.count() - 1 - instr.owner);
769             QObject *scope = 
770                 stack.at(stack.count() - 1 - instr.context);
771
772             QDeclarativeProperty mp = 
773                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
774
775             int coreIndex = mp.index();
776
777             if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
778                 break;
779
780             QDeclarativeAbstractBinding *binding = 
781                 ctxt->v8bindings->configBinding(instr.value, target, scope, mp, instr.line);
782             bindValues.append(binding);
783             binding->m_mePtr = &bindValues.values[bindValues.count - 1];
784             binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
785         QML_END_INSTR(StoreV8Binding)
786
787         QML_BEGIN_INSTR(StoreValueSource)
788             QObject *obj = stack.pop();
789             QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
790             QObject *target = stack.at(stack.count() - 1 - instr.owner);
791
792             QDeclarativeProperty prop = 
793                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
794             obj->setParent(target);
795             vs->setTarget(prop);
796         QML_END_INSTR(StoreValueSource)
797
798         QML_BEGIN_INSTR(StoreValueInterceptor)
799             QObject *obj = stack.pop();
800             QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
801             QObject *target = stack.at(stack.count() - 1 - instr.owner);
802             QDeclarativeProperty prop = 
803                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
804             obj->setParent(target);
805             vi->setTarget(prop);
806             QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
807             mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
808         QML_END_INSTR(StoreValueInterceptor)
809
810         QML_BEGIN_INSTR(StoreObjectQList)
811             QObject *assign = stack.pop();
812
813             const ListInstance &list = qliststack.top();
814             list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
815         QML_END_INSTR(StoreObjectQList)
816
817         QML_BEGIN_INSTR(AssignObjectList)
818             // This is only used for assigning interfaces
819             QObject *assign = stack.pop();
820             const ListInstance &list = qliststack.top();
821
822             int type = list.type;
823
824             void *ptr = 0;
825
826             const char *iid = QDeclarativeMetaType::interfaceIId(type);
827             if (iid) 
828                 ptr = assign->qt_metacast(iid);
829             if (!ptr) 
830                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line);
831
832
833             list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
834         QML_END_INSTR(AssignObjectList)
835
836         QML_BEGIN_INSTR(StoreVariantObject)
837             QObject *assign = stack.pop();
838             QObject *target = stack.top();
839             CLEAN_PROPERTY(target, instr.propertyIndex);
840
841             QVariant v = QVariant::fromValue(assign);
842             void *a[] = { &v, 0, &status, &flags };
843             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
844                                   instr.propertyIndex, a);
845         QML_END_INSTR(StoreVariantObject)
846
847         QML_BEGIN_INSTR(StoreInterface)
848             QObject *assign = stack.pop();
849             QObject *target = stack.top();
850             CLEAN_PROPERTY(target, instr.propertyIndex);
851
852             int coreIdx = instr.propertyIndex;
853             QMetaProperty prop = target->metaObject()->property(coreIdx);
854             int t = prop.userType();
855             const char *iid = QDeclarativeMetaType::interfaceIId(t);
856             bool ok = false;
857             if (iid) {
858                 void *ptr = assign->qt_metacast(iid);
859                 if (ptr) {
860                     void *a[] = { &ptr, 0, &status, &flags };
861                     QMetaObject::metacall(target, 
862                                           QMetaObject::WriteProperty,
863                                           coreIdx, a);
864                     ok = true;
865                 }
866             } 
867
868             if (!ok) 
869                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line);
870         QML_END_INSTR(StoreInterface)
871             
872         QML_BEGIN_INSTR(FetchAttached)
873             QObject *target = stack.top();
874
875             QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
876
877             if (!qmlObject)
878                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line);
879
880             stack.push(qmlObject);
881         QML_END_INSTR(FetchAttached)
882
883         QML_BEGIN_INSTR(FetchQList)
884             QObject *target = stack.top();
885
886             qliststack.push(ListInstance(instr.type));
887
888             void *a[1];
889             a[0] = (void *)&(qliststack.top().qListProperty);
890             QMetaObject::metacall(target, QMetaObject::ReadProperty, 
891                                   instr.property, a);
892         QML_END_INSTR(FetchQList)
893
894         QML_BEGIN_INSTR(FetchObject)
895             QObject *target = stack.top();
896
897             QObject *obj = 0;
898             // NOTE: This assumes a cast to QObject does not alter the 
899             // object pointer
900             void *a[1];
901             a[0] = &obj;
902             QMetaObject::metacall(target, QMetaObject::ReadProperty, 
903                                   instr.property, a);
904
905             if (!obj)
906                 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);
907
908             stack.push(obj);
909         QML_END_INSTR(FetchObject)
910
911         QML_BEGIN_INSTR(PopQList)
912             qliststack.pop();
913         QML_END_INSTR(PopQList)
914
915         QML_BEGIN_INSTR(Defer)
916             if (instr.deferCount) {
917                 QObject *target = stack.top();
918                 QDeclarativeData *data = 
919                     QDeclarativeData::get(target, true);
920                 comp->addref();
921                 data->deferredComponent = comp;
922                 data->deferredIdx = instructionStream - comp->bytecode.constData();
923                 instructionStream += instr.deferCount;
924             }
925         QML_END_INSTR(Defer)
926
927         QML_BEGIN_INSTR(PopFetchedObject)
928             stack.pop();
929         QML_END_INSTR(PopFetchedObject)
930
931         QML_BEGIN_INSTR(FetchValueType)
932             QObject *target = stack.top();
933
934             if (instr.bindingSkipList != 0) {
935                 // Possibly need to clear bindings
936                 QDeclarativeData *targetData = QDeclarativeData::get(target);
937                 if (targetData) {
938                     QDeclarativeAbstractBinding *binding = 
939                         QDeclarativePropertyPrivate::binding(target, instr.property, -1);
940
941                     if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
942                         QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
943                         binding->destroy();
944                     } else if (binding) {
945                         QDeclarativeValueTypeProxyBinding *proxy = 
946                             static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
947                         proxy->removeBindings(instr.bindingSkipList);
948                     }
949                 }
950             }
951
952             QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
953             valueHandler->read(target, instr.property);
954             stack.push(valueHandler);
955         QML_END_INSTR(FetchValueType)
956
957         QML_BEGIN_INSTR(PopValueType)
958             QDeclarativeValueType *valueHandler = 
959                 static_cast<QDeclarativeValueType *>(stack.pop());
960             QObject *target = stack.top();
961             valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
962         QML_END_INSTR(PopValueType)
963
964         default:
965             qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type());
966             break;
967         }
968     }
969
970     if (isError()) {
971         if (!stack.isEmpty()) {
972             delete stack.at(0); // ### What about failures in deferred creation?
973         } else {
974             ctxt->destroy();
975         }
976
977         QDeclarativeEnginePrivate::clear(bindValues);
978         QDeclarativeEnginePrivate::clear(parserStatus);
979         return 0;
980     }
981
982     if (bindValues.count)
983         ep->bindValues << bindValues;
984     else if (bindValues.values)
985         bindValues.clear();
986
987     if (parserStatus.count)
988         ep->parserStatus << parserStatus;
989     else if (parserStatus.values)
990         parserStatus.clear();
991
992     Q_ASSERT(stack.count() == 1);
993     return stack.top();
994 }
995
996 bool QDeclarativeVME::isError() const
997 {
998     return !vmeErrors.isEmpty();
999 }
1000
1001 QList<QDeclarativeError> QDeclarativeVME::errors() const
1002 {
1003     return vmeErrors;
1004 }
1005
1006 QObject *
1007 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
1008                                                         const QBitField &bindings,
1009                                                         QList<QDeclarativeError> *errors) const
1010 {
1011     if (type) {
1012         QObject *rv = 0;
1013         void *memory = 0;
1014
1015         type->create(&rv, &memory, sizeof(QDeclarativeData));
1016         QDeclarativeData *ddata = new (memory) QDeclarativeData;
1017         ddata->ownMemory = false;
1018         QObjectPrivate::get(rv)->declarativeData = ddata;
1019
1020         if (typePropertyCache && !ddata->propertyCache) {
1021             ddata->propertyCache = typePropertyCache;
1022             ddata->propertyCache->addref();
1023         }
1024
1025         return rv;
1026     } else {
1027         Q_ASSERT(component);
1028         return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings);
1029     } 
1030 }
1031
1032 v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1033 {
1034     if (script->m_loaded)
1035         return qPersistentNew<v8::Object>(script->m_value);
1036
1037     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1038     QV8Engine *v8engine = ep->v8engine();
1039
1040     bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
1041
1042     QDeclarativeContextData *effectiveCtxt = parentCtxt;
1043     if (shared)
1044         effectiveCtxt = 0;
1045
1046     // Create the script context if required
1047     QDeclarativeContextData *ctxt = new QDeclarativeContextData;
1048     ctxt->isInternal = true;
1049     ctxt->isJSContext = true;
1050     if (shared)
1051         ctxt->isPragmaLibraryContext = true;
1052     else
1053         ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
1054     ctxt->url = script->url;
1055
1056     // For backward compatibility, if there are no imports, we need to use the
1057     // imports from the parent context.  See QTBUG-17518.
1058     if (!script->importCache->isEmpty()) {
1059         ctxt->imports = script->importCache;
1060     } else if (effectiveCtxt) {
1061         ctxt->imports = effectiveCtxt->imports;
1062         ctxt->importedScripts = effectiveCtxt->importedScripts;
1063         for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
1064             ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
1065     }
1066
1067     if (ctxt->imports) {
1068         ctxt->imports->addref();
1069     }
1070
1071     if (effectiveCtxt)
1072         ctxt->setParent(effectiveCtxt, true);
1073
1074     for (int ii = 0; ii < script->scripts.count(); ++ii) {
1075         ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1076     }
1077
1078     v8::HandleScope handle_scope;
1079     v8::Context::Scope scope(v8engine->context());
1080
1081     v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
1082
1083     v8::TryCatch try_catch;
1084     script->m_program->Run(qmlglobal);
1085
1086     v8::Persistent<v8::Object> rv;
1087     
1088     if (try_catch.HasCaught()) {
1089         v8::Local<v8::Message> message = try_catch.Message();
1090         if (!message.IsEmpty()) {
1091             QDeclarativeError error;
1092             QDeclarativeExpressionPrivate::exceptionToError(message, error);
1093             ep->warning(error);
1094         }
1095     } 
1096
1097     rv = qPersistentNew<v8::Object>(qmlglobal);
1098     if (shared) {
1099         script->m_value = qPersistentNew<v8::Object>(qmlglobal);
1100         script->m_loaded = true;
1101     }
1102
1103     return rv;
1104 }
1105
1106 template<typename T>
1107 QDeclarativeVMEStack<T>::QDeclarativeVMEStack()
1108 : _index(-1)
1109 {
1110 }
1111
1112 template<typename T>
1113 bool QDeclarativeVMEStack<T>::isEmpty() const {
1114     return _index == -1;
1115 }
1116
1117 template<typename T>
1118 const T &QDeclarativeVMEStack<T>::top() const {
1119     return at(_index);
1120 }
1121
1122 template<typename T>
1123 void QDeclarativeVMEStack<T>::push(const T &o) {
1124     _index++;
1125
1126     Q_ASSERT(_index <= VLA::size());
1127     if (_index == VLA::size())
1128         append(o);
1129     else
1130         VLA::data()[_index] = o;
1131 }
1132
1133 template<typename T>
1134 T QDeclarativeVMEStack<T>::pop() {
1135     Q_ASSERT(_index >= 0);
1136     --_index;
1137     return VLA::data()[_index + 1];
1138 }
1139
1140 template<typename T>
1141 int QDeclarativeVMEStack<T>::count() const {
1142     return _index + 1;
1143 }
1144
1145 template<typename T>
1146 const T &QDeclarativeVMEStack<T>::at(int index) const {
1147     return VLA::data()[index];
1148 }
1149
1150 QT_END_NAMESPACE