8f11b2842d1ba77f9478195574b4cfa3ca356aae
[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 "qdeclarativevme_p.h"
43
44 #include "qdeclarativecompiler_p.h"
45 #include "qdeclarativeboundsignal_p.h"
46 #include "qdeclarativestringconverters_p.h"
47 #include <private/qmetaobjectbuilder_p.h>
48 #include <private/qfastmetabuilder_p.h>
49 #include "qdeclarativedata_p.h"
50 #include "qdeclarative.h"
51 #include "qdeclarativecustomparser_p.h"
52 #include "qdeclarativeengine.h"
53 #include "qdeclarativecontext.h"
54 #include "qdeclarativecomponent.h"
55 #include "qdeclarativebinding_p.h"
56 #include "qdeclarativeengine_p.h"
57 #include "qdeclarativecomponent_p.h"
58 #include "qdeclarativevmemetaobject_p.h"
59 #include "qdeclarativebinding_p_p.h"
60 #include "qdeclarativecontext_p.h"
61 #include <private/qv4bindings_p.h>
62 #include <private/qv8bindings_p.h>
63 #include "qdeclarativeglobal_p.h"
64 #include <private/qfinitestack_p.h>
65 #include "qdeclarativescriptstring.h"
66 #include "qdeclarativescriptstring_p.h"
67
68 #include <QStack>
69 #include <QColor>
70 #include <QPointF>
71 #include <QSizeF>
72 #include <QRectF>
73 #include <QtCore/qdebug.h>
74 #include <QtCore/qvarlengtharray.h>
75 #include <QtCore/qcoreapplication.h>
76 #include <QtCore/qdatetime.h>
77 #include <QtCore/qvarlengtharray.h>
78 #include <QtDeclarative/qjsvalue.h>
79
80 QT_BEGIN_NAMESPACE
81
82 using namespace QDeclarativeVMETypes;
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         *errors << error; \
91         goto exceptionExit; \
92     }
93
94 void QDeclarativeVME::init(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, int start,
95                            QDeclarativeContextData *creation)
96 {
97     Q_ASSERT(ctxt);
98     Q_ASSERT(comp);
99
100     if (start == -1) {
101         start = 0;
102     } else {
103         creationContext = creation;
104     }
105
106     State initState;
107     initState.context = ctxt;
108     initState.compiledData = comp;
109     initState.instructionStream = comp->bytecode.constData() + start;
110     states.push(initState);
111
112     typedef QDeclarativeInstruction I;
113     I *i = (I *)initState.instructionStream;
114
115     Q_ASSERT(comp->instructionType(i) == I::Init);
116
117     objects.allocate(i->init.objectStackSize);
118     lists.allocate(i->init.listStackSize);
119     bindValues.allocate(i->init.bindingsSize);
120     parserStatus.allocate(i->init.parserStatusSize);
121
122     rootContext = 0;
123     engine = ctxt->engine;
124 }
125
126 bool QDeclarativeVME::initDeferred(QObject *object)
127 {
128     QDeclarativeData *data = QDeclarativeData::get(object);
129
130     if (!data || !data->context || !data->deferredComponent)
131         return false;
132
133     QDeclarativeContextData *ctxt = data->context;
134     QDeclarativeCompiledData *comp = data->deferredComponent;
135     int start = data->deferredIdx;
136
137     State initState;
138     initState.flags = State::Deferred;
139     initState.context = ctxt;
140     initState.compiledData = comp;
141     initState.instructionStream = comp->bytecode.constData() + start;
142     states.push(initState);
143
144     typedef QDeclarativeInstruction I;
145     I *i = (I *)initState.instructionStream;
146
147     Q_ASSERT(comp->instructionType(i) == I::DeferInit);
148
149     objects.allocate(i->deferInit.objectStackSize);
150     lists.allocate(i->deferInit.listStackSize);
151     bindValues.allocate(i->deferInit.bindingsSize);
152     parserStatus.allocate(i->deferInit.parserStatusSize);
153
154     objects.push(object);
155
156     rootContext = 0;
157     engine = ctxt->engine;
158
159     return true;
160 }
161
162 namespace {
163 struct ActiveVMERestorer 
164 {
165     ActiveVMERestorer(QDeclarativeVME *me, QDeclarativeEnginePrivate *ep) 
166     : ep(ep), oldVME(ep->activeVME) { ep->activeVME = me; }
167     ~ActiveVMERestorer() { ep->activeVME = oldVME; }
168
169     QDeclarativeEnginePrivate *ep;
170     QDeclarativeVME *oldVME;
171 };
172 }
173
174 QObject *QDeclarativeVME::execute(QList<QDeclarativeError> *errors, const Interrupt &interrupt)
175 {
176     Q_ASSERT(states.count() >= 1);
177
178     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(states.at(0).context->engine);
179
180     ActiveVMERestorer restore(this, ep);
181
182     QObject *rv = run(errors, interrupt);
183
184     return rv;
185 }
186
187 inline bool fastHasBinding(QObject *o, int index) 
188 {
189     QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
190
191     return ddata && (ddata->bindingBitsSize > index) && 
192            (ddata->bindingBits[index / 32] & (1 << (index % 32)));
193 }
194
195 static void removeBindingOnProperty(QObject *o, int index)
196 {
197     QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
198     if (binding) binding->destroy();
199 }
200
201 // XXX we probably need some form of "work count" here to prevent us checking this 
202 // for every instruction.
203 #define QML_BEGIN_INSTR_COMMON(I) { \
204     const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(*genericInstr); \
205     INSTRUCTIONSTREAM += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \
206     Q_UNUSED(instr);
207
208 #ifdef QML_THREADED_VME_INTERPRETER
209 #  define QML_BEGIN_INSTR(I) op_##I: \
210     QML_BEGIN_INSTR_COMMON(I)
211
212 #  define QML_NEXT_INSTR(I) { \
213     if (watcher.hasRecursed()) return 0; \
214     genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
215     goto *genericInstr->common.code; \
216     }
217
218 #  define QML_END_INSTR(I) } \
219     if (watcher.hasRecursed()) return 0; \
220     genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
221     if (interrupt.shouldInterrupt()) return 0; \
222     goto *genericInstr->common.code;
223
224 #else
225 #  define QML_BEGIN_INSTR(I) \
226     case QDeclarativeInstruction::I: \
227     QML_BEGIN_INSTR_COMMON(I)
228
229 #  define QML_NEXT_INSTR(I) { \
230     if (watcher.hasRecursed()) return 0; \
231     break; \
232     }
233
234 #  define QML_END_INSTR(I) \
235     if (watcher.hasRecursed() || interrupt.shouldInterrupt()) return 0; \
236     } break;
237 #endif
238
239 #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
240
241 QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
242                               const Interrupt &interrupt
243 #ifdef QML_THREADED_VME_INTERPRETER
244                               , void ***storeJumpTable
245 #endif
246                               )
247 {
248 #ifdef QML_THREADED_VME_INTERPRETER
249     if (storeJumpTable) {
250 #define QML_INSTR_ADDR(I, FMT) &&op_##I,
251         static void *jumpTable[] = {
252             FOR_EACH_QML_INSTR(QML_INSTR_ADDR)
253         };
254 #undef QML_INSTR_ADDR
255         *storeJumpTable = jumpTable;
256         return 0;
257     }
258 #endif
259     Q_ASSERT(errors->isEmpty());
260     Q_ASSERT(states.count() >= 1);
261
262     QDeclarativeEngine *engine = states.at(0).context->engine;
263     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
264
265     // Need a v8 handle scope and execution context for StoreVar instructions.
266     v8::HandleScope handleScope;
267     v8::Context::Scope contextScope(ep->v8engine()->context());
268
269     int status = -1; // needed for dbus
270     QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
271                                                     QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
272
273     QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
274
275 #define COMP states.top().compiledData
276 #define CTXT states.top().context
277 #define INSTRUCTIONSTREAM states.top().instructionStream
278 #define BINDINGSKIPLIST states.top().bindingSkipList
279
280 #define TYPES COMP->types
281 #define PRIMITIVES COMP->primitives
282 #define DATAS COMP->datas
283 #define PROPERTYCACHES COMP->propertyCaches
284 #define SCRIPTS COMP->scripts
285 #define URLS COMP->urls
286
287 #ifdef QML_THREADED_VME_INTERPRETER
288     const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM);
289     goto *genericInstr->common.code;
290 #else
291     for (;;) {
292         const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM);
293
294         switch (genericInstr->common.instructionType) {
295 #endif
296         QML_BEGIN_INSTR(Init)
297             // Ensure that the compiled data has been initialized
298             if (!COMP->isInitialized()) COMP->initialize(engine);
299
300             QDeclarativeContextData *parentCtxt = CTXT;
301             CTXT = new QDeclarativeContextData;
302             CTXT->isInternal = true;
303             CTXT->url = COMP->url;
304             CTXT->imports = COMP->importCache;
305             CTXT->imports->addref();
306             CTXT->setParent(parentCtxt);
307             if (instr.contextCache != -1) 
308                 CTXT->setIdPropertyData(COMP->contextCaches.at(instr.contextCache));
309             if (instr.compiledBinding != -1) {
310                 const char *v4data = DATAS.at(instr.compiledBinding).constData();
311                 CTXT->v4bindings = new QV4Bindings(v4data, CTXT, COMP);
312             }
313             if (states.count() == 1) {
314                 rootContext = CTXT;
315                 rootContext->activeVMEData = data;
316             }
317             if (states.count() == 1 && !creationContext.isNull()) {
318                 // A component that is logically created within another component instance shares the 
319                 // same instances of script imports.  For example:
320                 //
321                 //     import QtQuick 1.0
322                 //     import "test.js" as Test
323                 //     ListView {
324                 //         model: Test.getModel()
325                 //         delegate: Component {
326                 //             Text { text: Test.getValue(index); }
327                 //         }
328                 //     }
329                 //
330                 // Has the same "Test" instance.  To implement this, we simply copy the v8 handles into
331                 // the inner context.  We have to create a fresh persistent handle for each to prevent 
332                 // double dispose.  It is possible we could do this more efficiently using some form of
333                 // referencing instead.
334                 CTXT->importedScripts = creationContext->importedScripts;
335                 for (int ii = 0; ii < CTXT->importedScripts.count(); ++ii)
336                     CTXT->importedScripts[ii] = qPersistentNew<v8::Object>(CTXT->importedScripts[ii]);
337             }
338         QML_END_INSTR(Init)
339
340         QML_BEGIN_INSTR(DeferInit)
341         QML_END_INSTR(DeferInit)
342
343         QML_BEGIN_INSTR(Done)
344             states.pop();
345
346             if (states.isEmpty())
347                 goto normalExit;
348         QML_END_INSTR(Done)
349
350         QML_BEGIN_INSTR(CreateQMLObject)
351             const QDeclarativeCompiledData::TypeReference &type = TYPES.at(instr.type);
352             Q_ASSERT(type.component);
353
354             states.push(State());
355
356             State *cState = &states[states.count() - 2];
357             State *nState = &states[states.count() - 1];
358
359             nState->context = cState->context;
360             nState->compiledData = type.component;
361             nState->instructionStream = type.component->bytecode.constData();
362
363             if (instr.bindingBits != -1) {
364                 const QByteArray &bits = cState->compiledData->datas.at(instr.bindingBits);
365                 nState->bindingSkipList = QBitField((const quint32*)bits.constData(),
366                                                     bits.size() * 8);
367             }
368             if (instr.isRoot)
369                 nState->bindingSkipList = nState->bindingSkipList.united(cState->bindingSkipList);
370
371             // As the state in the state stack changed, execution will continue in the new program.
372         QML_END_INSTR(CreateQMLObject)
373
374         QML_BEGIN_INSTR(CompleteQMLObject)
375             QObject *o = objects.top();
376
377             QDeclarativeData *ddata = QDeclarativeData::get(o);
378             Q_ASSERT(ddata);
379
380             if (instr.isRoot) {
381                 if (ddata->context) {
382                     Q_ASSERT(ddata->context != CTXT);
383                     Q_ASSERT(ddata->outerContext);
384                     Q_ASSERT(ddata->outerContext != CTXT);
385                     QDeclarativeContextData *c = ddata->context;
386                     while (c->linkedContext) c = c->linkedContext;
387                     c->linkedContext = CTXT;
388                 } else {
389                     CTXT->addObject(o);
390                 }
391
392                 ddata->ownContext = true;
393             } else if (!ddata->context) {
394                 CTXT->addObject(o);
395             }
396
397             ddata->setImplicitDestructible();
398             ddata->outerContext = CTXT;
399             ddata->lineNumber = instr.line;
400             ddata->columnNumber = instr.column;
401         QML_END_INSTR(CompleteQMLObject)
402
403         QML_BEGIN_INSTR(CreateCppObject)
404             const QDeclarativeCompiledData::TypeReference &type = TYPES.at(instr.type);
405             Q_ASSERT(type.type);
406
407             QObject *o = 0;
408             void *memory = 0;
409             type.type->create(&o, &memory, sizeof(QDeclarativeData));
410             QDeclarativeData *ddata = new (memory) QDeclarativeData;
411             ddata->ownMemory = false;
412             QObjectPrivate::get(o)->declarativeData = ddata;
413
414             if (type.typePropertyCache && !ddata->propertyCache) {
415                 ddata->propertyCache = type.typePropertyCache;
416                 ddata->propertyCache->addref();
417             }
418
419             if (!o) 
420                 VME_EXCEPTION(tr("Unable to create object of type %1").arg(type.className), instr.line);
421
422             if (instr.isRoot) {
423                 if (ddata->context) {
424                     Q_ASSERT(ddata->context != CTXT);
425                     Q_ASSERT(ddata->outerContext);
426                     Q_ASSERT(ddata->outerContext != CTXT);
427                     QDeclarativeContextData *c = ddata->context;
428                     while (c->linkedContext) c = c->linkedContext;
429                     c->linkedContext = CTXT;
430                 } else {
431                     CTXT->addObject(o);
432                 }
433
434                 ddata->ownContext = true;
435             } else if (!ddata->context) {
436                 CTXT->addObject(o);
437             }
438
439             ddata->setImplicitDestructible();
440             ddata->outerContext = CTXT;
441             ddata->lineNumber = instr.line;
442             ddata->columnNumber = instr.column;
443
444             if (instr.data != -1) {
445                 QDeclarativeCustomParser *customParser =
446                     TYPES.at(instr.type).type->customParser();
447                 customParser->setCustomData(o, DATAS.at(instr.data));
448             }
449             if (!objects.isEmpty()) {
450                 QObject *parent = objects.top();
451 #if 0 // ### refactor
452                 if (o->isWidgetType() && parent->isWidgetType()) 
453                     static_cast<QWidget*>(o)->setParent(static_cast<QWidget*>(parent));
454                 else 
455 #endif
456                     QDeclarative_setParent_noEvent(o, parent);
457             }
458             objects.push(o);
459         QML_END_INSTR(CreateCppObject)
460
461         QML_BEGIN_INSTR(CreateSimpleObject)
462             QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));   
463             ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
464             instr.create(o);
465
466             QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
467             const QDeclarativeCompiledData::TypeReference &ref = TYPES.at(instr.type);
468             if (!ddata->propertyCache && ref.typePropertyCache) {
469                 ddata->propertyCache = ref.typePropertyCache;
470                 ddata->propertyCache->addref();
471             }
472             ddata->lineNumber = instr.line;
473             ddata->columnNumber = instr.column;
474
475             QObjectPrivate::get(o)->declarativeData = ddata;                                                      
476             ddata->context = ddata->outerContext = CTXT;
477             ddata->nextContextObject = CTXT->contextObjects; 
478             if (ddata->nextContextObject) 
479                 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject; 
480             ddata->prevContextObject = &CTXT->contextObjects; 
481             CTXT->contextObjects = ddata; 
482
483             QObject *parent = objects.top();                                                                    
484             QDeclarative_setParent_noEvent(o, parent);                                                        
485
486             objects.push(o);
487         QML_END_INSTR(CreateSimpleObject)
488
489         QML_BEGIN_INSTR(SetId)
490             QObject *target = objects.top();
491             CTXT->setIdProperty(instr.index, target);
492         QML_END_INSTR(SetId)
493
494         QML_BEGIN_INSTR(SetDefault)
495             CTXT->contextObject = objects.top();
496         QML_END_INSTR(SetDefault)
497
498         QML_BEGIN_INSTR(CreateComponent)
499             QDeclarativeComponent *qcomp = 
500                 new QDeclarativeComponent(CTXT->engine, COMP, INSTRUCTIONSTREAM - COMP->bytecode.constData(),
501                                           objects.isEmpty() ? 0 : objects.top());
502
503             QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
504             Q_ASSERT(ddata);
505
506             CTXT->addObject(qcomp);
507
508             if (instr.isRoot)
509                 ddata->ownContext = true;
510
511             ddata->setImplicitDestructible();
512             ddata->outerContext = CTXT;
513             ddata->lineNumber = instr.line;
514             ddata->columnNumber = instr.column;
515
516             QDeclarativeComponentPrivate::get(qcomp)->creationContext = CTXT;
517
518             objects.push(qcomp);
519             INSTRUCTIONSTREAM += instr.count;
520         QML_END_INSTR(CreateComponent)
521
522         QML_BEGIN_INSTR(StoreMetaObject)
523             QObject *target = objects.top();
524
525             QMetaObject mo;
526             const QByteArray &metadata = DATAS.at(instr.data);
527             QFastMetaBuilder::fromData(&mo, 0, metadata);
528
529             const QDeclarativeVMEMetaData *data = 
530                 (const QDeclarativeVMEMetaData *)DATAS.at(instr.aliasData).constData();
531
532             (void)new QDeclarativeVMEMetaObject(target, &mo, data, COMP);
533
534             if (instr.propertyCache != -1) {
535                 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
536                 if (ddata->propertyCache) ddata->propertyCache->release();
537                 ddata->propertyCache = PROPERTYCACHES.at(instr.propertyCache);
538                 ddata->propertyCache->addref();
539             }
540         QML_END_INSTR(StoreMetaObject)
541
542         QML_BEGIN_INSTR(StoreVariant)
543             QObject *target = objects.top();
544             CLEAN_PROPERTY(target, instr.propertyIndex);
545
546             // XXX - can be more efficient
547             QVariant v = QDeclarativeStringConverters::variantFromString(PRIMITIVES.at(instr.value));
548             void *a[] = { &v, 0, &status, &flags };
549             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
550                                   instr.propertyIndex, a);
551         QML_END_INSTR(StoreVariant)
552
553         QML_BEGIN_INSTR(StoreVariantInteger)
554             QObject *target = objects.top();
555             CLEAN_PROPERTY(target, instr.propertyIndex);
556
557             QVariant v(instr.value);
558             void *a[] = { &v, 0, &status, &flags };
559             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
560                                   instr.propertyIndex, a);
561         QML_END_INSTR(StoreVariantInteger)
562
563         QML_BEGIN_INSTR(StoreVariantDouble)
564             QObject *target = objects.top();
565             CLEAN_PROPERTY(target, instr.propertyIndex);
566
567             QVariant v(instr.value);
568             void *a[] = { &v, 0, &status, &flags };
569             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
570                                   instr.propertyIndex, a);
571         QML_END_INSTR(StoreVariantDouble)
572
573         QML_BEGIN_INSTR(StoreVariantBool)
574             QObject *target = objects.top();
575             CLEAN_PROPERTY(target, instr.propertyIndex);
576
577             QVariant v(instr.value);
578             void *a[] = { &v, 0, &status, &flags };
579             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
580                                   instr.propertyIndex, a);
581         QML_END_INSTR(StoreVariantBool)
582
583         QML_BEGIN_INSTR(StoreVar)
584             QObject *target = objects.top();
585             CLEAN_PROPERTY(target, instr.propertyIndex);
586
587             // Note that we don't use QDeclarativeStringConverters::variantFromString() here, which
588             // means that automatic generation of value types from strings doesn't occur.
589             // This is a deliberate behaviour difference to variant properties.
590             v8::Handle<v8::Value> v8Value = ep->v8engine()->fromVariant(PRIMITIVES.at(instr.value));
591             static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
592         QML_END_INSTR(StoreVar)
593
594         QML_BEGIN_INSTR(StoreVarInteger)
595             QObject *target = objects.top();
596             CLEAN_PROPERTY(target, instr.propertyIndex);
597
598             v8::Handle<v8::Value> v8Value = v8::Integer::New(instr.value);
599             static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
600         QML_END_INSTR(StoreVarInteger)
601
602         QML_BEGIN_INSTR(StoreVarDouble)
603             QObject *target = objects.top();
604             CLEAN_PROPERTY(target, instr.propertyIndex);
605
606             v8::Handle<v8::Value> v8Value = v8::Number::New(instr.value);
607             static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
608         QML_END_INSTR(StoreVarDouble)
609
610         QML_BEGIN_INSTR(StoreVarBool)
611             QObject *target = objects.top();
612             CLEAN_PROPERTY(target, instr.propertyIndex);
613
614             v8::Handle<v8::Value> v8Value = v8::Boolean::New(instr.value);
615             static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
616         QML_END_INSTR(StoreVarBool)
617
618         QML_BEGIN_INSTR(StoreString)
619             QObject *target = objects.top();
620             CLEAN_PROPERTY(target, instr.propertyIndex);
621
622             void *a[] = { (void *)&PRIMITIVES.at(instr.value), 0, &status, &flags };
623             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
624                                   instr.propertyIndex, a);
625         QML_END_INSTR(StoreString)
626
627         QML_BEGIN_INSTR(StoreByteArray)
628             QObject *target = objects.top();
629             void *a[] = { (void *)&DATAS.at(instr.value), 0, &status, &flags };
630             QMetaObject::metacall(target, QMetaObject::WriteProperty,
631                                   instr.propertyIndex, a);
632         QML_END_INSTR(StoreByteArray)
633
634         QML_BEGIN_INSTR(StoreUrl)
635             QObject *target = objects.top();
636             CLEAN_PROPERTY(target, instr.propertyIndex);
637
638             void *a[] = { (void *)&URLS.at(instr.value), 0, &status, &flags };
639             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
640                                   instr.propertyIndex, a);
641         QML_END_INSTR(StoreUrl)
642
643         QML_BEGIN_INSTR(StoreFloat)
644             QObject *target = objects.top();
645             CLEAN_PROPERTY(target, instr.propertyIndex);
646
647             float f = instr.value;
648             void *a[] = { &f, 0, &status, &flags };
649             QMetaObject::metacall(target, QMetaObject::WriteProperty,
650                                   instr.propertyIndex, a);
651         QML_END_INSTR(StoreFloat)
652
653         QML_BEGIN_INSTR(StoreDouble)
654             QObject *target = objects.top();
655             CLEAN_PROPERTY(target, instr.propertyIndex);
656
657             double d = instr.value;
658             void *a[] = { &d, 0, &status, &flags };
659             QMetaObject::metacall(target, QMetaObject::WriteProperty,
660                                   instr.propertyIndex, a);
661         QML_END_INSTR(StoreDouble)
662
663         QML_BEGIN_INSTR(StoreBool)
664             QObject *target = objects.top();
665             CLEAN_PROPERTY(target, instr.propertyIndex);
666
667             void *a[] = { (void *)&instr.value, 0, &status, &flags };
668             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
669                                   instr.propertyIndex, a);
670         QML_END_INSTR(StoreBool)
671
672         QML_BEGIN_INSTR(StoreInteger)
673             QObject *target = objects.top();
674             CLEAN_PROPERTY(target, instr.propertyIndex);
675
676             void *a[] = { (void *)&instr.value, 0, &status, &flags };
677             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
678                                   instr.propertyIndex, a);
679         QML_END_INSTR(StoreInteger)
680
681         QML_BEGIN_INSTR(StoreColor)
682             QObject *target = objects.top();
683             CLEAN_PROPERTY(target, instr.propertyIndex);
684
685             QColor c = QColor::fromRgba(instr.value);
686             void *a[] = { &c, 0, &status, &flags };
687             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
688                                   instr.propertyIndex, a);
689         QML_END_INSTR(StoreColor)
690
691         QML_BEGIN_INSTR(StoreDate)
692             QObject *target = objects.top();
693             CLEAN_PROPERTY(target, instr.propertyIndex);
694
695             QDate d = QDate::fromJulianDay(instr.value);
696             void *a[] = { &d, 0, &status, &flags };
697             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
698                                   instr.propertyIndex, a);
699         QML_END_INSTR(StoreDate)
700
701         QML_BEGIN_INSTR(StoreTime)
702             QObject *target = objects.top();
703             CLEAN_PROPERTY(target, instr.propertyIndex);
704
705             QTime *t = (QTime *)&instr.time;
706             void *a[] = { t, 0, &status, &flags };
707             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
708                                   instr.propertyIndex, a);
709         QML_END_INSTR(StoreTime)
710
711         QML_BEGIN_INSTR(StoreDateTime)
712             QObject *target = objects.top();
713             CLEAN_PROPERTY(target, instr.propertyIndex);
714
715             QTime *t = (QTime *)&instr.time;
716             QDateTime dt(QDate::fromJulianDay(instr.date), *t);
717             void *a[] = { &dt, 0, &status, &flags };
718             QMetaObject::metacall(target, QMetaObject::WriteProperty,
719                                   instr.propertyIndex, a);
720         QML_END_INSTR(StoreDateTime)
721
722         QML_BEGIN_INSTR(StorePoint)
723             QObject *target = objects.top();
724             CLEAN_PROPERTY(target, instr.propertyIndex);
725
726             QPoint *p = (QPoint *)&instr.point;
727             void *a[] = { p, 0, &status, &flags };
728             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
729                                   instr.propertyIndex, a);
730         QML_END_INSTR(StorePoint)
731
732         QML_BEGIN_INSTR(StorePointF)
733             QObject *target = objects.top();
734             CLEAN_PROPERTY(target, instr.propertyIndex);
735
736             QPointF *p = (QPointF *)&instr.point;
737             void *a[] = { p, 0, &status, &flags };
738             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
739                                   instr.propertyIndex, a);
740         QML_END_INSTR(StorePointF)
741
742         QML_BEGIN_INSTR(StoreSize)
743             QObject *target = objects.top();
744             CLEAN_PROPERTY(target, instr.propertyIndex);
745
746             QSize *s = (QSize *)&instr.size;
747             void *a[] = { s, 0, &status, &flags };
748             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
749                                   instr.propertyIndex, a);
750         QML_END_INSTR(StoreSize)
751
752         QML_BEGIN_INSTR(StoreSizeF)
753             QObject *target = objects.top();
754             CLEAN_PROPERTY(target, instr.propertyIndex);
755
756             QSizeF *s = (QSizeF *)&instr.size;
757             void *a[] = { s, 0, &status, &flags };
758             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
759                                   instr.propertyIndex, a);
760         QML_END_INSTR(StoreSizeF)
761
762         QML_BEGIN_INSTR(StoreRect)
763             QObject *target = objects.top();
764             CLEAN_PROPERTY(target, instr.propertyIndex);
765
766             QRect *r = (QRect *)&instr.rect;
767             void *a[] = { r, 0, &status, &flags };
768             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
769                                   instr.propertyIndex, a);
770         QML_END_INSTR(StoreRect)
771
772         QML_BEGIN_INSTR(StoreRectF)
773             QObject *target = objects.top();
774             CLEAN_PROPERTY(target, instr.propertyIndex);
775
776             QRectF *r = (QRectF *)&instr.rect;
777             void *a[] = { r, 0, &status, &flags };
778             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
779                                   instr.propertyIndex, a);
780         QML_END_INSTR(StoreRectF)
781
782         QML_BEGIN_INSTR(StoreVector3D)
783             QObject *target = objects.top();
784             CLEAN_PROPERTY(target, instr.propertyIndex);
785
786             QVector3D *v = (QVector3D *)&instr.vector;
787             void *a[] = { v, 0, &status, &flags };
788             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
789                                   instr.propertyIndex, a);
790         QML_END_INSTR(StoreVector3D)
791
792         QML_BEGIN_INSTR(StoreVector4D)
793             QObject *target = objects.top();
794             CLEAN_PROPERTY(target, instr.propertyIndex);
795
796             QVector4D *v = (QVector4D *)&instr.vector;
797             void *a[] = { v, 0, &status, &flags };
798             QMetaObject::metacall(target, QMetaObject::WriteProperty,
799                                   instr.propertyIndex, a);
800         QML_END_INSTR(StoreVector4D)
801
802         QML_BEGIN_INSTR(StoreObject)
803             QObject *assignObj = objects.pop();
804             QObject *target = objects.top();
805             CLEAN_PROPERTY(target, instr.propertyIndex);
806
807             void *a[] = { (void *)&assignObj, 0, &status, &flags };
808             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
809                                   instr.propertyIndex, a);
810         QML_END_INSTR(StoreObject)
811
812         QML_BEGIN_INSTR(AssignCustomType)
813             QObject *target = objects.top();
814             CLEAN_PROPERTY(target, instr.propertyIndex);
815
816             const QString &primitive = PRIMITIVES.at(instr.primitive);
817             int type = instr.type;
818             QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
819             QVariant v = (*converter)(primitive);
820
821             QMetaProperty prop = 
822                     target->metaObject()->property(instr.propertyIndex);
823             if (v.isNull() || ((int)prop.type() != type && prop.userType() != type)) 
824                 VME_EXCEPTION(tr("Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
825
826             void *a[] = { (void *)v.data(), 0, &status, &flags };
827             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
828                                   instr.propertyIndex, a);
829         QML_END_INSTR(AssignCustomType)
830
831         QML_BEGIN_INSTR(AssignSignalObject)
832             // XXX optimize
833
834             QObject *assign = objects.pop();
835             QObject *target = objects.top();
836             int sigIdx = instr.signal;
837             const QString &pr = PRIMITIVES.at(sigIdx);
838
839             QDeclarativeProperty prop(target, pr);
840             if (prop.type() & QDeclarativeProperty::SignalProperty) {
841
842                 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
843                 if (method.signature() == 0)
844                     VME_EXCEPTION(tr("Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
845
846                 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
847                     VME_EXCEPTION(tr("Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.line);
848
849                 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
850
851             } else {
852                 VME_EXCEPTION(tr("Cannot assign an object to signal property %1").arg(pr), instr.line);
853             }
854
855
856         QML_END_INSTR(AssignSignalObject)
857
858         QML_BEGIN_INSTR(StoreSignal)
859             QObject *target = objects.top();
860             QObject *context = objects.at(objects.count() - 1 - instr.context);
861
862             QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
863
864             QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
865             QDeclarativeExpression *expr = 
866                 new QDeclarativeExpression(CTXT, context, PRIMITIVES.at(instr.value));
867             expr->setSourceLocation(COMP->name, instr.line);
868             static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = QString::fromUtf8(DATAS.at(instr.name));
869             bs->setExpression(expr);
870         QML_END_INSTR(StoreSignal)
871
872         QML_BEGIN_INSTR(StoreImportedScript)
873             CTXT->importedScripts << run(CTXT, SCRIPTS.at(instr.value));
874         QML_END_INSTR(StoreImportedScript)
875
876         QML_BEGIN_INSTR(StoreScriptString)
877             QObject *target = objects.top();
878             QObject *scope = objects.at(objects.count() - 1 - instr.scope);
879             QDeclarativeScriptString ss;
880             ss.setContext(CTXT->asQDeclarativeContext());
881             ss.setScopeObject(scope);
882             ss.setScript(PRIMITIVES.at(instr.value));
883             ss.d.data()->bindingId = instr.bindingId;
884             ss.d.data()->lineNumber = instr.line;
885
886             void *a[] = { &ss, 0, &status, &flags };
887             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
888                                   instr.propertyIndex, a);
889         QML_END_INSTR(StoreScriptString)
890
891         QML_BEGIN_INSTR(BeginObject)
892             QObject *target = objects.top();
893             QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
894             parserStatus.push(status);
895             status->d = &parserStatus.top();
896
897             status->classBegin();
898         QML_END_INSTR(BeginObject)
899
900         QML_BEGIN_INSTR(InitV8Bindings)
901             CTXT->v8bindings = new QV8Bindings(PRIMITIVES.at(instr.program), instr.programIndex, 
902                                                        instr.line, COMP, CTXT);
903         QML_END_INSTR(InitV8Bindings)
904
905         QML_BEGIN_INSTR(StoreBinding)
906             QObject *target = 
907                 objects.at(objects.count() - 1 - instr.owner);
908             QObject *context = 
909                 objects.at(objects.count() - 1 - instr.context);
910
911             QDeclarativeProperty mp = 
912                 QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
913
914             int coreIndex = mp.index();
915
916             if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex)) 
917                 QML_NEXT_INSTR(StoreBinding);
918
919             QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true, 
920                                                                 context, CTXT, COMP->name, instr.line);
921             bindValues.push(bind);
922             bind->m_mePtr = &bindValues.top();
923             bind->setTarget(mp);
924
925             bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
926         QML_END_INSTR(StoreBinding)
927
928         QML_BEGIN_INSTR(StoreBindingOnAlias)
929             QObject *target = 
930                 objects.at(objects.count() - 1 - instr.owner);
931             QObject *context = 
932                 objects.at(objects.count() - 1 - instr.context);
933
934             QDeclarativeProperty mp = 
935                 QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
936
937             int coreIndex = mp.index();
938
939             if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex)) 
940                 QML_NEXT_INSTR(StoreBindingOnAlias);
941
942             QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true,
943                                                                 context, CTXT, COMP->name, instr.line);
944             bindValues.push(bind);
945             bind->m_mePtr = &bindValues.top();
946             bind->setTarget(mp);
947
948             QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
949             if (old) { old->destroy(); }
950         QML_END_INSTR(StoreBindingOnAlias)
951
952         QML_BEGIN_INSTR(StoreV4Binding)
953             QObject *target = 
954                 objects.at(objects.count() - 1 - instr.owner);
955             QObject *scope = 
956                 objects.at(objects.count() - 1 - instr.context);
957
958             int property = instr.property;
959             if (instr.isRoot && BINDINGSKIPLIST.testBit(property & 0xFFFF))
960                 QML_NEXT_INSTR(StoreV4Binding);
961
962             QDeclarativeAbstractBinding *binding = 
963                 CTXT->v4bindings->configBinding(instr.value, target, scope, property);
964             bindValues.push(binding);
965             binding->m_mePtr = &bindValues.top();
966             binding->addToObject(target, property);
967         QML_END_INSTR(StoreV4Binding)
968
969         QML_BEGIN_INSTR(StoreV8Binding)
970             QObject *target = 
971                 objects.at(objects.count() - 1 - instr.owner);
972             QObject *scope = 
973                 objects.at(objects.count() - 1 - instr.context);
974
975             if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
976                 QML_NEXT_INSTR(StoreV8Binding);
977
978             QDeclarativeAbstractBinding *binding = 
979                 CTXT->v8bindings->configBinding(instr.value, target, scope, 
980                                                 instr.property, instr.line);
981             bindValues.push(binding);
982             binding->m_mePtr = &bindValues.top();
983             binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(instr.property));
984         QML_END_INSTR(StoreV8Binding)
985
986         QML_BEGIN_INSTR(StoreValueSource)
987             QObject *obj = objects.pop();
988             QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
989             QObject *target = objects.at(objects.count() - 1 - instr.owner);
990
991             QDeclarativeProperty prop = 
992                 QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
993             obj->setParent(target);
994             vs->setTarget(prop);
995         QML_END_INSTR(StoreValueSource)
996
997         QML_BEGIN_INSTR(StoreValueInterceptor)
998             QObject *obj = objects.pop();
999             QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
1000             QObject *target = objects.at(objects.count() - 1 - instr.owner);
1001             QDeclarativeProperty prop = 
1002                 QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
1003             obj->setParent(target);
1004             vi->setTarget(prop);
1005             QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
1006             mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
1007         QML_END_INSTR(StoreValueInterceptor)
1008
1009         QML_BEGIN_INSTR(StoreObjectQList)
1010             QObject *assign = objects.pop();
1011
1012             const List &list = lists.top();
1013             list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
1014         QML_END_INSTR(StoreObjectQList)
1015
1016         QML_BEGIN_INSTR(AssignObjectList)
1017             // This is only used for assigning interfaces
1018             QObject *assign = objects.pop();
1019             const List &list = lists.top();
1020
1021             int type = list.type;
1022
1023             void *ptr = 0;
1024
1025             const char *iid = QDeclarativeMetaType::interfaceIId(type);
1026             if (iid) 
1027                 ptr = assign->qt_metacast(iid);
1028             if (!ptr) 
1029                 VME_EXCEPTION(tr("Cannot assign object to list"), instr.line);
1030
1031
1032             list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
1033         QML_END_INSTR(AssignObjectList)
1034
1035         QML_BEGIN_INSTR(StoreVariantObject)
1036             QObject *assign = objects.pop();
1037             QObject *target = objects.top();
1038             CLEAN_PROPERTY(target, instr.propertyIndex);
1039
1040             QVariant v = QVariant::fromValue(assign);
1041             void *a[] = { &v, 0, &status, &flags };
1042             QMetaObject::metacall(target, QMetaObject::WriteProperty, 
1043                                   instr.propertyIndex, a);
1044         QML_END_INSTR(StoreVariantObject)
1045
1046         QML_BEGIN_INSTR(StoreVarObject)
1047             QObject *assign = objects.pop();
1048             QObject *target = objects.top();
1049             CLEAN_PROPERTY(target, instr.propertyIndex);
1050
1051             v8::Handle<v8::Value> v8Value = ep->v8engine()->newQObject(assign);
1052             static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
1053         QML_END_INSTR(StoreVarObject)
1054
1055         QML_BEGIN_INSTR(StoreInterface)
1056             QObject *assign = objects.pop();
1057             QObject *target = objects.top();
1058             CLEAN_PROPERTY(target, instr.propertyIndex);
1059
1060             int coreIdx = instr.propertyIndex;
1061             QMetaProperty prop = target->metaObject()->property(coreIdx);
1062             int t = prop.userType();
1063             const char *iid = QDeclarativeMetaType::interfaceIId(t);
1064             bool ok = false;
1065             if (iid) {
1066                 void *ptr = assign->qt_metacast(iid);
1067                 if (ptr) {
1068                     void *a[] = { &ptr, 0, &status, &flags };
1069                     QMetaObject::metacall(target, 
1070                                           QMetaObject::WriteProperty,
1071                                           coreIdx, a);
1072                     ok = true;
1073                 }
1074             } 
1075
1076             if (!ok) 
1077                 VME_EXCEPTION(tr("Cannot assign object to interface property"), instr.line);
1078         QML_END_INSTR(StoreInterface)
1079             
1080         QML_BEGIN_INSTR(FetchAttached)
1081             QObject *target = objects.top();
1082
1083             QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
1084
1085             if (!qmlObject)
1086                 VME_EXCEPTION(tr("Unable to create attached object"), instr.line);
1087
1088             objects.push(qmlObject);
1089         QML_END_INSTR(FetchAttached)
1090
1091         QML_BEGIN_INSTR(FetchQList)
1092             QObject *target = objects.top();
1093
1094             lists.push(List(instr.type));
1095
1096             void *a[1];
1097             a[0] = (void *)&(lists.top().qListProperty);
1098             QMetaObject::metacall(target, QMetaObject::ReadProperty, 
1099                                   instr.property, a);
1100         QML_END_INSTR(FetchQList)
1101
1102         QML_BEGIN_INSTR(FetchObject)
1103             QObject *target = objects.top();
1104
1105             QObject *obj = 0;
1106             // NOTE: This assumes a cast to QObject does not alter the 
1107             // object pointer
1108             void *a[1];
1109             a[0] = &obj;
1110             QMetaObject::metacall(target, QMetaObject::ReadProperty, 
1111                                   instr.property, a);
1112
1113             if (!obj)
1114                 VME_EXCEPTION(tr("Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line);
1115
1116             objects.push(obj);
1117         QML_END_INSTR(FetchObject)
1118
1119         QML_BEGIN_INSTR(PopQList)
1120             lists.pop();
1121         QML_END_INSTR(PopQList)
1122
1123         QML_BEGIN_INSTR(Defer)
1124             if (instr.deferCount) {
1125                 QObject *target = objects.top();
1126                 QDeclarativeData *data = 
1127                     QDeclarativeData::get(target, true);
1128                 COMP->addref();
1129                 data->deferredComponent = COMP;
1130                 data->deferredIdx = INSTRUCTIONSTREAM - COMP->bytecode.constData();
1131                 INSTRUCTIONSTREAM += instr.deferCount;
1132             }
1133         QML_END_INSTR(Defer)
1134
1135         QML_BEGIN_INSTR(PopFetchedObject)
1136             objects.pop();
1137         QML_END_INSTR(PopFetchedObject)
1138
1139         QML_BEGIN_INSTR(FetchValueType)
1140             QObject *target = objects.top();
1141
1142             if (instr.bindingSkipList != 0) {
1143                 // Possibly need to clear bindings
1144                 QDeclarativeData *targetData = QDeclarativeData::get(target);
1145                 if (targetData) {
1146                     QDeclarativeAbstractBinding *binding = 
1147                         QDeclarativePropertyPrivate::binding(target, instr.property, -1);
1148
1149                     if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
1150                         QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
1151                         binding->destroy();
1152                     } else if (binding) {
1153                         QDeclarativeValueTypeProxyBinding *proxy = 
1154                             static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
1155                         proxy->removeBindings(instr.bindingSkipList);
1156                     }
1157                 }
1158             }
1159
1160             QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
1161             valueHandler->read(target, instr.property);
1162             objects.push(valueHandler);
1163         QML_END_INSTR(FetchValueType)
1164
1165         QML_BEGIN_INSTR(PopValueType)
1166             QDeclarativeValueType *valueHandler = 
1167                 static_cast<QDeclarativeValueType *>(objects.pop());
1168             QObject *target = objects.top();
1169             valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
1170         QML_END_INSTR(PopValueType)
1171
1172 #ifdef QML_THREADED_VME_INTERPRETER
1173     // nothing to do
1174 #else
1175         default:
1176             qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr->common.instructionType);
1177             break;
1178         }
1179     }
1180 #endif
1181
1182 exceptionExit:
1183     Q_ASSERT(!states.isEmpty());
1184     Q_ASSERT(!errors->isEmpty());
1185
1186     reset();
1187
1188     return 0;
1189
1190 normalExit:
1191     Q_ASSERT(objects.count() == 1);
1192
1193     QObject *rv = objects.top();
1194
1195     objects.deallocate();
1196     lists.deallocate();
1197     states.clear();
1198
1199     return rv;
1200 }
1201
1202 void QDeclarativeVME::reset()
1203 {
1204     Q_ASSERT(!states.isEmpty() || objects.isEmpty());
1205
1206     QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
1207
1208     if (!objects.isEmpty() && !(states.at(0).flags & State::Deferred))
1209         delete objects.at(0); 
1210     
1211     if (!rootContext.isNull()) 
1212         rootContext->activeVMEData = 0;
1213
1214     // Remove the QDeclarativeParserStatus and QDeclarativeAbstractBinding back pointers
1215     blank(parserStatus);
1216     blank(bindValues);
1217
1218     while (componentAttached) {
1219         QDeclarativeComponentAttached *a = componentAttached;
1220         a->rem();
1221     }
1222     
1223     engine = 0;
1224     objects.deallocate();
1225     lists.deallocate();
1226     bindValues.deallocate();
1227     parserStatus.deallocate();
1228     finalizeCallbacks.clear();
1229     states.clear();
1230     rootContext = 0;
1231     creationContext = 0;
1232 }
1233
1234 // Must be called with a handle scope and context
1235 void QDeclarativeScriptData::initialize(QDeclarativeEngine *engine)
1236 {
1237     Q_ASSERT(m_program.IsEmpty());
1238     Q_ASSERT(engine);
1239     Q_ASSERT(!hasEngine());
1240
1241     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
1242     QV8Engine *v8engine = ep->v8engine();
1243
1244     // XXX Handle errors during the script compile!
1245     v8::Local<v8::Script> program = v8engine->qmlModeCompile(m_programSource, url.toString(), 1);
1246     m_program = qPersistentNew<v8::Script>(program);
1247
1248     addToEngine(engine);
1249
1250     addref();
1251 }
1252
1253 v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1254 {
1255     if (script->m_loaded)
1256         return qPersistentNew<v8::Object>(script->m_value);
1257
1258     Q_ASSERT(parentCtxt && parentCtxt->engine);
1259     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1260     QV8Engine *v8engine = ep->v8engine();
1261
1262     bool shared = script->pragmas & QDeclarativeScript::Object::ScriptBlock::Shared;
1263
1264     QDeclarativeContextData *effectiveCtxt = parentCtxt;
1265     if (shared)
1266         effectiveCtxt = 0;
1267
1268     // Create the script context if required
1269     QDeclarativeContextData *ctxt = new QDeclarativeContextData;
1270     ctxt->isInternal = true;
1271     ctxt->isJSContext = true;
1272     if (shared)
1273         ctxt->isPragmaLibraryContext = true;
1274     else
1275         ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
1276     ctxt->url = script->url;
1277
1278     // For backward compatibility, if there are no imports, we need to use the
1279     // imports from the parent context.  See QTBUG-17518.
1280     if (!script->importCache->isEmpty()) {
1281         ctxt->imports = script->importCache;
1282     } else if (effectiveCtxt) {
1283         ctxt->imports = effectiveCtxt->imports;
1284         ctxt->importedScripts = effectiveCtxt->importedScripts;
1285         for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
1286             ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
1287     }
1288
1289     if (ctxt->imports) {
1290         ctxt->imports->addref();
1291     }
1292
1293     if (effectiveCtxt) {
1294         ctxt->setParent(effectiveCtxt, true);
1295     } else {
1296         ctxt->engine = parentCtxt->engine; // Fix for QTBUG-21620
1297     }
1298
1299     for (int ii = 0; ii < script->scripts.count(); ++ii) {
1300         ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1301     }
1302
1303     v8::HandleScope handle_scope;
1304     v8::Context::Scope scope(v8engine->context());
1305
1306     if (!script->isInitialized()) 
1307         script->initialize(parentCtxt->engine);
1308
1309     v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
1310
1311     v8::TryCatch try_catch;
1312     script->m_program->Run(qmlglobal);
1313
1314     v8::Persistent<v8::Object> rv;
1315     
1316     if (try_catch.HasCaught()) {
1317         v8::Local<v8::Message> message = try_catch.Message();
1318         if (!message.IsEmpty()) {
1319             QDeclarativeError error;
1320             QDeclarativeExpressionPrivate::exceptionToError(message, error);
1321             ep->warning(error);
1322         }
1323     } 
1324
1325     rv = qPersistentNew<v8::Object>(qmlglobal);
1326     if (shared) {
1327         script->m_value = qPersistentNew<v8::Object>(qmlglobal);
1328         script->m_loaded = true;
1329     }
1330
1331     return rv;
1332 }
1333
1334 #ifdef QML_THREADED_VME_INTERPRETER
1335 void **QDeclarativeVME::instructionJumpTable()
1336 {
1337     static void **jumpTable = 0;
1338     if (!jumpTable) {
1339         QDeclarativeVME dummy;
1340         QDeclarativeVME::Interrupt i;
1341         dummy.run(0, i, &jumpTable);
1342     }
1343     return jumpTable;
1344 }
1345 #endif
1346
1347 QDeclarativeContextData *QDeclarativeVME::complete(const Interrupt &interrupt)
1348 {
1349     Q_ASSERT(engine ||
1350              (bindValues.isEmpty() &&
1351               parserStatus.isEmpty() &&
1352               componentAttached == 0 &&
1353               rootContext.isNull() &&
1354               finalizeCallbacks.isEmpty()));
1355
1356     if (!engine)
1357         return 0;
1358
1359     ActiveVMERestorer restore(this, QDeclarativeEnginePrivate::get(engine));
1360     QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
1361
1362     while (!bindValues.isEmpty()) {
1363         QDeclarativeAbstractBinding *b = bindValues.pop();
1364
1365         if(b) {
1366             b->m_mePtr = 0;
1367             b->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor | 
1368                                 QDeclarativePropertyPrivate::DontRemoveBinding);
1369         }
1370
1371         if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1372             return 0;
1373     }
1374     bindValues.deallocate();
1375
1376     while (!parserStatus.isEmpty()) {
1377         QDeclarativeParserStatus *status = parserStatus.pop();
1378
1379         if (status && status->d) {
1380             status->d = 0;
1381             status->componentComplete();
1382         }
1383         
1384         if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1385             return 0;
1386     }
1387     parserStatus.deallocate();
1388
1389     for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) {
1390         QDeclarativeEnginePrivate::FinalizeCallback callback = finalizeCallbacks.at(ii);
1391         QObject *obj = callback.first;
1392         if (obj) {
1393             void *args[] = { 0 };
1394             QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
1395         }
1396         if (watcher.hasRecursed())
1397             return 0;
1398     }
1399     finalizeCallbacks.clear();
1400
1401     while (componentAttached) {
1402         QDeclarativeComponentAttached *a = componentAttached;
1403         a->rem();
1404         QDeclarativeData *d = QDeclarativeData::get(a->parent());
1405         Q_ASSERT(d);
1406         Q_ASSERT(d->context);
1407         a->add(&d->context->componentAttached);
1408         emit a->completed();
1409
1410         if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1411             return 0;
1412     }
1413
1414     QDeclarativeContextData *rv = rootContext;
1415
1416     reset();
1417
1418     if (rv) rv->activeVMEData = data;
1419
1420     return rv;
1421 }
1422
1423 void QDeclarativeVME::blank(QFiniteStack<QDeclarativeAbstractBinding *> &bs)
1424 {
1425     for (int ii = 0; ii < bs.count(); ++ii) {
1426         QDeclarativeAbstractBinding *b = bs.at(ii);
1427         if (b) b->m_mePtr = 0;
1428     }
1429 }
1430
1431 void QDeclarativeVME::blank(QFiniteStack<QDeclarativeParserStatus *> &pss)
1432 {
1433     for (int ii = 0; ii < pss.count(); ++ii) {
1434         QDeclarativeParserStatus *ps = pss.at(ii);
1435         if(ps) ps->d = 0;
1436     }
1437 }
1438
1439 QDeclarativeVMEGuard::QDeclarativeVMEGuard()
1440 : m_objectCount(0), m_objects(0), m_contextCount(0), m_contexts(0)
1441 {
1442 }
1443
1444 QDeclarativeVMEGuard::~QDeclarativeVMEGuard()
1445 {
1446     clear();
1447 }
1448
1449 void QDeclarativeVMEGuard::guard(QDeclarativeVME *vme)
1450 {
1451     clear();
1452     
1453     m_objectCount = vme->objects.count();
1454     m_objects = new QDeclarativeGuard<QObject>[m_objectCount];
1455     for (int ii = 0; ii < m_objectCount; ++ii)
1456         m_objects[ii] = vme->objects[ii];
1457
1458     m_contextCount = (vme->rootContext.isNull()?0:1) + vme->states.count();
1459     m_contexts = new QDeclarativeGuardedContextData[m_contextCount];
1460     for (int ii = 0; ii < vme->states.count(); ++ii) 
1461         m_contexts[ii] = vme->states.at(ii).context;
1462     if (!vme->rootContext.isNull())
1463         m_contexts[m_contextCount - 1] = vme->rootContext.contextData();
1464 }
1465
1466 void QDeclarativeVMEGuard::clear()
1467 {
1468     delete [] m_objects;
1469     delete [] m_contexts;
1470
1471     m_objectCount = 0;
1472     m_objects = 0;
1473     m_contextCount = 0;
1474     m_contexts = 0;
1475 }
1476
1477 bool QDeclarativeVMEGuard::isOK() const
1478 {
1479     for (int ii = 0; ii < m_objectCount; ++ii)
1480         if (m_objects[ii].isNull())
1481             return false;
1482
1483     for (int ii = 0; ii < m_contextCount; ++ii)
1484         if (m_contexts[ii].isNull())
1485             return false;
1486
1487     return true;
1488 }
1489
1490 QT_END_NAMESPACE