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