Merge branch 'v8'
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativevme.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativevme_p.h"
43
44 #include "private/qdeclarativecompiler_p.h"
45 #include "private/qdeclarativeboundsignal_p.h"
46 #include "private/qdeclarativestringconverters_p.h"
47 #include "private/qmetaobjectbuilder_p.h"
48 #include "private/qdeclarativedata_p.h"
49 #include "qdeclarative.h"
50 #include "private/qdeclarativecustomparser_p.h"
51 #include "qdeclarativeengine.h"
52 #include "qdeclarativecontext.h"
53 #include "qdeclarativecomponent.h"
54 #include "private/qdeclarativebinding_p.h"
55 #include "private/qdeclarativeengine_p.h"
56 #include "private/qdeclarativecomponent_p.h"
57 #include "private/qdeclarativevmemetaobject_p.h"
58 #include "private/qdeclarativebinding_p_p.h"
59 #include "private/qdeclarativecontext_p.h"
60 #include "private/qdeclarativev4bindings_p.h"
61 #include "private/qv8bindings_p.h"
62 #include "private/qdeclarativeglobal_p.h"
63 #include "qdeclarativescriptstring.h"
64 #include "qdeclarativescriptstring_p.h"
65
66 #include <QStack>
67 #include <QWidget>
68 #include <QColor>
69 #include <QPointF>
70 #include <QSizeF>
71 #include <QRectF>
72 #include <QtCore/qdebug.h>
73 #include <QtCore/qvarlengtharray.h>
74 #include <QtCore/qcoreapplication.h>
75 #include <QtCore/qdatetime.h>
76 #include <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                 const char *v4data = datas.at(instr.compiledBinding).constData();
197                 ctxt->v4bindings = new QDeclarativeV4Bindings(v4data, ctxt);
198             }
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 = (QTime *)&instr.time;
479             void *a[] = { t, 0, &status, &flags };
480             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
481                                   instr.propertyIndex, a);
482         QML_END_INSTR(StoreTime)
483
484         QML_BEGIN_INSTR(StoreDateTime)
485             QObject *target = stack.top();
486             CLEAN_PROPERTY(target, instr.propertyIndex);
487
488             QTime *t = (QTime *)&instr.time;
489             QDateTime dt(QDate::fromJulianDay(instr.date), *t);
490             void *a[] = { &dt, 0, &status, &flags };
491             QMetaObject::metacall(target, QMetaObject::WriteProperty,
492                                   instr.propertyIndex, a);
493         QML_END_INSTR(StoreDateTime)
494
495         QML_BEGIN_INSTR(StorePoint)
496             QObject *target = stack.top();
497             CLEAN_PROPERTY(target, instr.propertyIndex);
498
499             QPoint *p = (QPoint *)&instr.point;
500             void *a[] = { p, 0, &status, &flags };
501             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
502                                   instr.propertyIndex, a);
503         QML_END_INSTR(StorePoint)
504
505         QML_BEGIN_INSTR(StorePointF)
506             QObject *target = stack.top();
507             CLEAN_PROPERTY(target, instr.propertyIndex);
508
509             QPointF *p = (QPointF *)&instr.point;
510             void *a[] = { p, 0, &status, &flags };
511             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
512                                   instr.propertyIndex, a);
513         QML_END_INSTR(StorePointF)
514
515         QML_BEGIN_INSTR(StoreSize)
516             QObject *target = stack.top();
517             CLEAN_PROPERTY(target, instr.propertyIndex);
518
519             QSize *s = (QSize *)&instr.size;
520             void *a[] = { s, 0, &status, &flags };
521             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
522                                   instr.propertyIndex, a);
523         QML_END_INSTR(StoreSize)
524
525         QML_BEGIN_INSTR(StoreSizeF)
526             QObject *target = stack.top();
527             CLEAN_PROPERTY(target, instr.propertyIndex);
528
529             QSizeF *s = (QSizeF *)&instr.size;
530             void *a[] = { s, 0, &status, &flags };
531             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
532                                   instr.propertyIndex, a);
533         QML_END_INSTR(StoreSizeF)
534
535         QML_BEGIN_INSTR(StoreRect)
536             QObject *target = stack.top();
537             CLEAN_PROPERTY(target, instr.propertyIndex);
538
539             QRect *r = (QRect *)&instr.rect;
540             void *a[] = { r, 0, &status, &flags };
541             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
542                                   instr.propertyIndex, a);
543         QML_END_INSTR(StoreRect)
544
545         QML_BEGIN_INSTR(StoreRectF)
546             QObject *target = stack.top();
547             CLEAN_PROPERTY(target, instr.propertyIndex);
548
549             QRectF *r = (QRectF *)&instr.rect;
550             void *a[] = { r, 0, &status, &flags };
551             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
552                                   instr.propertyIndex, a);
553         QML_END_INSTR(StoreRectF)
554
555         QML_BEGIN_INSTR(StoreVector3D)
556             QObject *target = stack.top();
557             CLEAN_PROPERTY(target, instr.propertyIndex);
558
559             QVector3D *v = (QVector3D *)&instr.vector;
560             void *a[] = { v, 0, &status, &flags };
561             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
562                                   instr.propertyIndex, a);
563         QML_END_INSTR(StoreVector3D)
564
565         QML_BEGIN_INSTR(StoreObject)
566             QObject *assignObj = stack.pop();
567             QObject *target = stack.top();
568             CLEAN_PROPERTY(target, instr.propertyIndex);
569
570             void *a[] = { (void *)&assignObj, 0, &status, &flags };
571             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
572                                   instr.propertyIndex, a);
573         QML_END_INSTR(StoreObject)
574
575         QML_BEGIN_INSTR(AssignCustomType)
576             QObject *target = stack.top();
577             CLEAN_PROPERTY(target, instr.propertyIndex);
578
579             const QString &primitive = primitives.at(instr.primitive);
580             int type = instr.type;
581             QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
582             QVariant v = (*converter)(primitive);
583
584             QMetaProperty prop = 
585                     target->metaObject()->property(instr.propertyIndex);
586             if (v.isNull() || ((int)prop.type() != type && prop.userType() != type)) 
587                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
588
589             void *a[] = { (void *)v.data(), 0, &status, &flags };
590             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
591                                   instr.propertyIndex, a);
592         QML_END_INSTR(AssignCustomType)
593
594         QML_BEGIN_INSTR(AssignSignalObject)
595             // XXX optimize
596
597             QObject *assign = stack.pop();
598             QObject *target = stack.top();
599             int sigIdx = instr.signal;
600             const QByteArray &pr = datas.at(sigIdx);
601
602             QDeclarativeProperty prop(target, QString::fromUtf8(pr));
603             if (prop.type() & QDeclarativeProperty::SignalProperty) {
604
605                 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
606                 if (method.signature() == 0)
607                     VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
608
609                 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
610                     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);
611
612                 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
613
614             } else {
615                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.line);
616             }
617
618
619         QML_END_INSTR(AssignSignalObject)
620
621         QML_BEGIN_INSTR(StoreSignal)
622             QObject *target = stack.top();
623             QObject *context = stack.at(stack.count() - 1 - instr.context);
624
625             QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
626
627             QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
628             QDeclarativeExpression *expr = 
629                 new QDeclarativeExpression(ctxt, context, primitives.at(instr.value));
630             expr->setSourceLocation(comp->name, instr.line);
631             static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.name);
632             bs->setExpression(expr);
633         QML_END_INSTR(StoreSignal)
634
635         QML_BEGIN_INSTR(StoreImportedScript)
636             ctxt->importedScripts << run(ctxt, scripts.at(instr.value));
637         QML_END_INSTR(StoreImportedScript)
638
639         QML_BEGIN_INSTR(StoreScriptString)
640             QObject *target = stack.top();
641             QObject *scope = stack.at(stack.count() - 1 - instr.scope);
642             QDeclarativeScriptString ss;
643             ss.setContext(ctxt->asQDeclarativeContext());
644             ss.setScopeObject(scope);
645             ss.setScript(primitives.at(instr.value));
646             ss.d.data()->bindingId = instr.bindingId;
647             ss.d.data()->lineNumber = instr.line;
648
649             void *a[] = { &ss, 0, &status, &flags };
650             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
651                                   instr.propertyIndex, a);
652         QML_END_INSTR(StoreScriptString)
653
654         QML_BEGIN_INSTR(BeginObject)
655             QObject *target = stack.top();
656             QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
657             parserStatus.append(status);
658             status->d = &parserStatus.values[parserStatus.count - 1];
659
660             status->classBegin();
661         QML_END_INSTR(BeginObject)
662
663         QML_BEGIN_INSTR(InitV8Bindings)
664             ctxt->v8bindings = new QV8Bindings(primitives.at(instr.program), instr.programIndex, 
665                                                instr.line, comp, ctxt);
666         QML_END_INSTR(InitV8Bindings)
667
668         QML_BEGIN_INSTR(StoreBinding)
669             QObject *target = 
670                 stack.at(stack.count() - 1 - instr.owner);
671             QObject *context = 
672                 stack.at(stack.count() - 1 - instr.context);
673
674             QDeclarativeProperty mp = 
675                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
676
677             int coreIndex = mp.index();
678
679             if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex)) 
680                 break;
681
682             QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true, 
683                                                                 context, ctxt, comp->name, instr.line);
684             bindValues.append(bind);
685             bind->m_mePtr = &bindValues.values[bindValues.count - 1];
686             bind->setTarget(mp);
687
688             bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
689         QML_END_INSTR(StoreBinding)
690
691         QML_BEGIN_INSTR(StoreBindingOnAlias)
692             QObject *target = 
693                 stack.at(stack.count() - 1 - instr.owner);
694             QObject *context = 
695                 stack.at(stack.count() - 1 - instr.context);
696
697             QDeclarativeProperty mp = 
698                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
699
700             int coreIndex = mp.index();
701
702             if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex)) 
703                 break;
704
705             QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
706                                                                 context, ctxt, comp->name, instr.line);
707             bindValues.append(bind);
708             bind->m_mePtr = &bindValues.values[bindValues.count - 1];
709             bind->setTarget(mp);
710
711             QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
712             if (old) { old->destroy(); }
713         QML_END_INSTR(StoreBindingOnAlias)
714
715         QML_BEGIN_INSTR(StoreV4Binding)
716             QObject *target = 
717                 stack.at(stack.count() - 1 - instr.owner);
718             QObject *scope = 
719                 stack.at(stack.count() - 1 - instr.context);
720
721             int property = instr.property;
722             if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))  
723                 break;
724
725             QDeclarativeAbstractBinding *binding = 
726                 ctxt->v4bindings->configBinding(instr.value, target, scope, property);
727             bindValues.append(binding);
728             binding->m_mePtr = &bindValues.values[bindValues.count - 1];
729             binding->addToObject(target, property);
730         QML_END_INSTR(StoreV4Binding)
731
732         QML_BEGIN_INSTR(StoreV8Binding)
733             QObject *target = 
734                 stack.at(stack.count() - 1 - instr.owner);
735             QObject *scope = 
736                 stack.at(stack.count() - 1 - instr.context);
737
738             QDeclarativeProperty mp = 
739                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
740
741             int coreIndex = mp.index();
742
743             if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
744                 break;
745
746             QDeclarativeAbstractBinding *binding = 
747                 ctxt->v8bindings->configBinding(instr.value, target, scope, mp, instr.line);
748             bindValues.append(binding);
749             binding->m_mePtr = &bindValues.values[bindValues.count - 1];
750             binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
751         QML_END_INSTR(StoreV8Binding)
752
753         QML_BEGIN_INSTR(StoreValueSource)
754             QObject *obj = stack.pop();
755             QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
756             QObject *target = stack.at(stack.count() - 1 - instr.owner);
757
758             QDeclarativeProperty prop = 
759                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
760             obj->setParent(target);
761             vs->setTarget(prop);
762         QML_END_INSTR(StoreValueSource)
763
764         QML_BEGIN_INSTR(StoreValueInterceptor)
765             QObject *obj = stack.pop();
766             QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
767             QObject *target = stack.at(stack.count() - 1 - instr.owner);
768             QDeclarativeProperty prop = 
769                 QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
770             obj->setParent(target);
771             vi->setTarget(prop);
772             QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
773             mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
774         QML_END_INSTR(StoreValueInterceptor)
775
776         QML_BEGIN_INSTR(StoreObjectQList)
777             QObject *assign = stack.pop();
778
779             const ListInstance &list = qliststack.top();
780             list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
781         QML_END_INSTR(StoreObjectQList)
782
783         QML_BEGIN_INSTR(AssignObjectList)
784             // This is only used for assigning interfaces
785             QObject *assign = stack.pop();
786             const ListInstance &list = qliststack.top();
787
788             int type = list.type;
789
790             void *ptr = 0;
791
792             const char *iid = QDeclarativeMetaType::interfaceIId(type);
793             if (iid) 
794                 ptr = assign->qt_metacast(iid);
795             if (!ptr) 
796                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"), instr.line);
797
798
799             list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
800         QML_END_INSTR(AssignObjectList)
801
802         QML_BEGIN_INSTR(StoreVariantObject)
803             QObject *assign = stack.pop();
804             QObject *target = stack.top();
805             CLEAN_PROPERTY(target, instr.propertyIndex);
806
807             QVariant v = QVariant::fromValue(assign);
808             void *a[] = { &v, 0, &status, &flags };
809             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
810                                   instr.propertyIndex, a);
811         QML_END_INSTR(StoreVariantObject)
812
813         QML_BEGIN_INSTR(StoreInterface)
814             QObject *assign = stack.pop();
815             QObject *target = stack.top();
816             CLEAN_PROPERTY(target, instr.propertyIndex);
817
818             int coreIdx = instr.propertyIndex;
819             QMetaProperty prop = target->metaObject()->property(coreIdx);
820             int t = prop.userType();
821             const char *iid = QDeclarativeMetaType::interfaceIId(t);
822             bool ok = false;
823             if (iid) {
824                 void *ptr = assign->qt_metacast(iid);
825                 if (ptr) {
826                     void *a[] = { &ptr, 0, &status, &flags };
827                     QMetaObject::metacall(target, 
828                                           QMetaObject::WriteProperty,
829                                           coreIdx, a);
830                     ok = true;
831                 }
832             } 
833
834             if (!ok) 
835                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"), instr.line);
836         QML_END_INSTR(StoreInterface)
837             
838         QML_BEGIN_INSTR(FetchAttached)
839             QObject *target = stack.top();
840
841             QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
842
843             if (!qmlObject)
844                 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"), instr.line);
845
846             stack.push(qmlObject);
847         QML_END_INSTR(FetchAttached)
848
849         QML_BEGIN_INSTR(FetchQList)
850             QObject *target = stack.top();
851
852             qliststack.push(ListInstance(instr.type));
853
854             void *a[1];
855             a[0] = (void *)&(qliststack.top().qListProperty);
856             QMetaObject::metacall(target, QMetaObject::ReadProperty, 
857                                   instr.property, a);
858         QML_END_INSTR(FetchQList)
859
860         QML_BEGIN_INSTR(FetchObject)
861             QObject *target = stack.top();
862
863             QObject *obj = 0;
864             // NOTE: This assumes a cast to QObject does not alter the 
865             // object pointer
866             void *a[1];
867             a[0] = &obj;
868             QMetaObject::metacall(target, QMetaObject::ReadProperty, 
869                                   instr.property, a);
870
871             if (!obj)
872                 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);
873
874             stack.push(obj);
875         QML_END_INSTR(FetchObject)
876
877         QML_BEGIN_INSTR(PopQList)
878             qliststack.pop();
879         QML_END_INSTR(PopQList)
880
881         QML_BEGIN_INSTR(Defer)
882             if (instr.deferCount) {
883                 QObject *target = stack.top();
884                 QDeclarativeData *data = 
885                     QDeclarativeData::get(target, true);
886                 comp->addref();
887                 data->deferredComponent = comp;
888                 data->deferredIdx = instructionStream - comp->bytecode.constData();
889                 instructionStream += instr.deferCount;
890             }
891         QML_END_INSTR(Defer)
892
893         QML_BEGIN_INSTR(PopFetchedObject)
894             stack.pop();
895         QML_END_INSTR(PopFetchedObject)
896
897         QML_BEGIN_INSTR(FetchValueType)
898             QObject *target = stack.top();
899
900             if (instr.bindingSkipList != 0) {
901                 // Possibly need to clear bindings
902                 QDeclarativeData *targetData = QDeclarativeData::get(target);
903                 if (targetData) {
904                     QDeclarativeAbstractBinding *binding = 
905                         QDeclarativePropertyPrivate::binding(target, instr.property, -1);
906
907                     if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
908                         QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
909                         binding->destroy();
910                     } else if (binding) {
911                         QDeclarativeValueTypeProxyBinding *proxy = 
912                             static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
913                         proxy->removeBindings(instr.bindingSkipList);
914                     }
915                 }
916             }
917
918             QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
919             valueHandler->read(target, instr.property);
920             stack.push(valueHandler);
921         QML_END_INSTR(FetchValueType)
922
923         QML_BEGIN_INSTR(PopValueType)
924             QDeclarativeValueType *valueHandler = 
925                 static_cast<QDeclarativeValueType *>(stack.pop());
926             QObject *target = stack.top();
927             valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
928         QML_END_INSTR(PopValueType)
929
930         default:
931             qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type());
932             break;
933         }
934     }
935
936     if (isError()) {
937         if (!stack.isEmpty()) {
938             delete stack.at(0); // ### What about failures in deferred creation?
939         } else {
940             ctxt->destroy();
941         }
942
943         QDeclarativeEnginePrivate::clear(bindValues);
944         QDeclarativeEnginePrivate::clear(parserStatus);
945         return 0;
946     }
947
948     if (bindValues.count)
949         ep->bindValues << bindValues;
950     else if (bindValues.values)
951         bindValues.clear();
952
953     if (parserStatus.count)
954         ep->parserStatus << parserStatus;
955     else if (parserStatus.values)
956         parserStatus.clear();
957
958     Q_ASSERT(stack.count() == 1);
959     return stack.top();
960 }
961
962 bool QDeclarativeVME::isError() const
963 {
964     return !vmeErrors.isEmpty();
965 }
966
967 QList<QDeclarativeError> QDeclarativeVME::errors() const
968 {
969     return vmeErrors;
970 }
971
972 QObject *
973 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
974                                                         const QBitField &bindings,
975                                                         QList<QDeclarativeError> *errors) const
976 {
977     if (type) {
978         QObject *rv = 0;
979         void *memory = 0;
980
981         type->create(&rv, &memory, sizeof(QDeclarativeData));
982         QDeclarativeData *ddata = new (memory) QDeclarativeData;
983         ddata->ownMemory = false;
984         QObjectPrivate::get(rv)->declarativeData = ddata;
985
986         if (typePropertyCache && !ddata->propertyCache) {
987             ddata->propertyCache = typePropertyCache;
988             ddata->propertyCache->addref();
989         }
990
991         return rv;
992     } else {
993         Q_ASSERT(component);
994         return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, 0, errors, bindings);
995     } 
996 }
997
998 v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
999 {
1000     if (script->m_loaded)
1001         return qPersistentNew<v8::Object>(script->m_value);
1002
1003     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1004     QV8Engine *v8engine = &ep->v8engine;
1005
1006     bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
1007
1008     QDeclarativeContextData *effectiveCtxt = parentCtxt;
1009     if (shared)
1010         effectiveCtxt = 0;
1011
1012     // Create the script context if required
1013     QDeclarativeContextData *ctxt = new QDeclarativeContextData;
1014     ctxt->isInternal = true;
1015     ctxt->isJSContext = true;
1016     if (shared)
1017         ctxt->isPragmaLibraryContext = true;
1018     else
1019         ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
1020     ctxt->url = script->url;
1021
1022     // For backward compatibility, if there are no imports, we need to use the
1023     // imports from the parent context.  See QTBUG-17518.
1024     if (!script->importCache->isEmpty()) {
1025         ctxt->imports = script->importCache;
1026     } else if (effectiveCtxt) {
1027         ctxt->imports = effectiveCtxt->imports;
1028         ctxt->importedScripts = effectiveCtxt->importedScripts;
1029         for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
1030             ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
1031     }
1032
1033     if (ctxt->imports) {
1034         ctxt->imports->addref();
1035     }
1036
1037     if (effectiveCtxt)
1038         ctxt->setParent(effectiveCtxt, true);
1039
1040     for (int ii = 0; ii < script->scripts.count(); ++ii) {
1041         ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1042     }
1043
1044     v8::HandleScope handle_scope;
1045     v8::Context::Scope scope(v8engine->context());
1046
1047     v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
1048
1049     v8::TryCatch try_catch;
1050     script->m_program->Run(qmlglobal);
1051
1052     v8::Persistent<v8::Object> rv;
1053     
1054     if (try_catch.HasCaught()) {
1055         v8::Local<v8::Message> message = try_catch.Message();
1056         if (!message.IsEmpty()) {
1057             QDeclarativeError error;
1058             QDeclarativeExpressionPrivate::exceptionToError(message, error);
1059             ep->warning(error);
1060         }
1061     } 
1062
1063     rv = qPersistentNew<v8::Object>(qmlglobal);
1064     if (shared) {
1065         script->m_value = qPersistentNew<v8::Object>(qmlglobal);
1066         script->m_loaded = true;
1067     }
1068
1069     return rv;
1070 }
1071
1072 QT_END_NAMESPACE