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