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