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