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