1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdeclarativevme_p.h"
44 #include "qdeclarativecompiler_p.h"
45 #include "qdeclarativeboundsignal_p.h"
46 #include "qdeclarativestringconverters_p.h"
47 #include <private/qmetaobjectbuilder_p.h>
48 #include <private/qfastmetabuilder_p.h>
49 #include "qdeclarativedata_p.h"
50 #include "qdeclarative.h"
51 #include "qdeclarativecustomparser_p.h"
52 #include "qdeclarativeengine.h"
53 #include "qdeclarativecontext.h"
54 #include "qdeclarativecomponent.h"
55 #include "qdeclarativebinding_p.h"
56 #include "qdeclarativeengine_p.h"
57 #include "qdeclarativecomponent_p.h"
58 #include "qdeclarativevmemetaobject_p.h"
59 #include "qdeclarativebinding_p_p.h"
60 #include "qdeclarativecontext_p.h"
61 #include <private/qv4bindings_p.h>
62 #include <private/qv8bindings_p.h>
63 #include "qdeclarativeglobal_p.h"
64 #include <private/qfinitestack_p.h>
65 #include "qdeclarativescriptstring.h"
66 #include "qdeclarativescriptstring_p.h"
73 #include <QtCore/qdebug.h>
74 #include <QtCore/qvarlengtharray.h>
75 #include <QtCore/qcoreapplication.h>
76 #include <QtCore/qdatetime.h>
77 #include <QtCore/qvarlengtharray.h>
78 #include <QtDeclarative/qjsvalue.h>
82 using namespace QDeclarativeVMETypes;
84 #define VME_EXCEPTION(desc, line) \
86 QDeclarativeError error; \
87 error.setDescription(desc.trimmed()); \
88 error.setLine(line); \
89 error.setUrl(COMP->url); \
94 void QDeclarativeVME::init(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, int start,
95 QDeclarativeContextData *creation)
103 creationContext = creation;
107 initState.context = ctxt;
108 initState.compiledData = comp;
109 initState.instructionStream = comp->bytecode.constData() + start;
110 states.push(initState);
112 typedef QDeclarativeInstruction I;
113 I *i = (I *)initState.instructionStream;
115 Q_ASSERT(comp->instructionType(i) == I::Init);
117 objects.allocate(i->init.objectStackSize);
118 lists.allocate(i->init.listStackSize);
119 bindValues.allocate(i->init.bindingsSize);
120 parserStatus.allocate(i->init.parserStatusSize);
123 engine = ctxt->engine;
126 bool QDeclarativeVME::initDeferred(QObject *object)
128 QDeclarativeData *data = QDeclarativeData::get(object);
130 if (!data || !data->context || !data->deferredComponent)
133 QDeclarativeContextData *ctxt = data->context;
134 QDeclarativeCompiledData *comp = data->deferredComponent;
135 int start = data->deferredIdx;
138 initState.flags = State::Deferred;
139 initState.context = ctxt;
140 initState.compiledData = comp;
141 initState.instructionStream = comp->bytecode.constData() + start;
142 states.push(initState);
144 typedef QDeclarativeInstruction I;
145 I *i = (I *)initState.instructionStream;
147 Q_ASSERT(comp->instructionType(i) == I::DeferInit);
149 objects.allocate(i->deferInit.objectStackSize);
150 lists.allocate(i->deferInit.listStackSize);
151 bindValues.allocate(i->deferInit.bindingsSize);
152 parserStatus.allocate(i->deferInit.parserStatusSize);
154 objects.push(object);
157 engine = ctxt->engine;
163 struct ActiveVMERestorer
165 ActiveVMERestorer(QDeclarativeVME *me, QDeclarativeEnginePrivate *ep)
166 : ep(ep), oldVME(ep->activeVME) { ep->activeVME = me; }
167 ~ActiveVMERestorer() { ep->activeVME = oldVME; }
169 QDeclarativeEnginePrivate *ep;
170 QDeclarativeVME *oldVME;
174 QObject *QDeclarativeVME::execute(QList<QDeclarativeError> *errors, const Interrupt &interrupt)
176 Q_ASSERT(states.count() >= 1);
178 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(states.at(0).context->engine);
180 ActiveVMERestorer restore(this, ep);
182 QObject *rv = run(errors, interrupt);
187 inline bool fastHasBinding(QObject *o, int index)
189 QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
191 return ddata && (ddata->bindingBitsSize > index) &&
192 (ddata->bindingBits[index / 32] & (1 << (index % 32)));
195 static void removeBindingOnProperty(QObject *o, int index)
197 QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
198 if (binding) binding->destroy();
201 // XXX we probably need some form of "work count" here to prevent us checking this
202 // for every instruction.
203 #define QML_BEGIN_INSTR_COMMON(I) { \
204 const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(*genericInstr); \
205 INSTRUCTIONSTREAM += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \
208 #ifdef QML_THREADED_VME_INTERPRETER
209 # define QML_BEGIN_INSTR(I) op_##I: \
210 QML_BEGIN_INSTR_COMMON(I)
212 # define QML_NEXT_INSTR(I) { \
213 if (watcher.hasRecursed()) return 0; \
214 genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
215 goto *genericInstr->common.code; \
218 # define QML_END_INSTR(I) } \
219 if (watcher.hasRecursed()) return 0; \
220 genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
221 if (interrupt.shouldInterrupt()) return 0; \
222 goto *genericInstr->common.code;
225 # define QML_BEGIN_INSTR(I) \
226 case QDeclarativeInstruction::I: \
227 QML_BEGIN_INSTR_COMMON(I)
229 # define QML_NEXT_INSTR(I) { \
230 if (watcher.hasRecursed()) return 0; \
234 # define QML_END_INSTR(I) \
235 if (watcher.hasRecursed() || interrupt.shouldInterrupt()) return 0; \
239 #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
241 QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
242 const Interrupt &interrupt
243 #ifdef QML_THREADED_VME_INTERPRETER
244 , void ***storeJumpTable
248 #ifdef QML_THREADED_VME_INTERPRETER
249 if (storeJumpTable) {
250 #define QML_INSTR_ADDR(I, FMT) &&op_##I,
251 static void *jumpTable[] = {
252 FOR_EACH_QML_INSTR(QML_INSTR_ADDR)
254 #undef QML_INSTR_ADDR
255 *storeJumpTable = jumpTable;
259 Q_ASSERT(errors->isEmpty());
260 Q_ASSERT(states.count() >= 1);
262 QDeclarativeEngine *engine = states.at(0).context->engine;
263 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
265 // Need a v8 handle scope and execution context for StoreVar instructions.
266 v8::HandleScope handleScope;
267 v8::Context::Scope contextScope(ep->v8engine()->context());
269 int status = -1; // needed for dbus
270 QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
271 QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
273 QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
275 #define COMP states.top().compiledData
276 #define CTXT states.top().context
277 #define INSTRUCTIONSTREAM states.top().instructionStream
278 #define BINDINGSKIPLIST states.top().bindingSkipList
280 #define TYPES COMP->types
281 #define PRIMITIVES COMP->primitives
282 #define DATAS COMP->datas
283 #define PROPERTYCACHES COMP->propertyCaches
284 #define SCRIPTS COMP->scripts
285 #define URLS COMP->urls
287 #ifdef QML_THREADED_VME_INTERPRETER
288 const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM);
289 goto *genericInstr->common.code;
292 const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM);
294 switch (genericInstr->common.instructionType) {
296 QML_BEGIN_INSTR(Init)
297 // Ensure that the compiled data has been initialized
298 if (!COMP->isInitialized()) COMP->initialize(engine);
300 QDeclarativeContextData *parentCtxt = CTXT;
301 CTXT = new QDeclarativeContextData;
302 CTXT->isInternal = true;
303 CTXT->url = COMP->url;
304 CTXT->imports = COMP->importCache;
305 CTXT->imports->addref();
306 CTXT->setParent(parentCtxt);
307 if (instr.contextCache != -1)
308 CTXT->setIdPropertyData(COMP->contextCaches.at(instr.contextCache));
309 if (instr.compiledBinding != -1) {
310 const char *v4data = DATAS.at(instr.compiledBinding).constData();
311 CTXT->v4bindings = new QV4Bindings(v4data, CTXT, COMP);
313 if (states.count() == 1) {
315 rootContext->activeVMEData = data;
317 if (states.count() == 1 && !creationContext.isNull()) {
318 // A component that is logically created within another component instance shares the
319 // same instances of script imports. For example:
321 // import QtQuick 1.0
322 // import "test.js" as Test
324 // model: Test.getModel()
325 // delegate: Component {
326 // Text { text: Test.getValue(index); }
330 // Has the same "Test" instance. To implement this, we simply copy the v8 handles into
331 // the inner context. We have to create a fresh persistent handle for each to prevent
332 // double dispose. It is possible we could do this more efficiently using some form of
333 // referencing instead.
334 CTXT->importedScripts = creationContext->importedScripts;
335 for (int ii = 0; ii < CTXT->importedScripts.count(); ++ii)
336 CTXT->importedScripts[ii] = qPersistentNew<v8::Object>(CTXT->importedScripts[ii]);
340 QML_BEGIN_INSTR(DeferInit)
341 QML_END_INSTR(DeferInit)
343 QML_BEGIN_INSTR(Done)
346 if (states.isEmpty())
350 QML_BEGIN_INSTR(CreateQMLObject)
351 const QDeclarativeCompiledData::TypeReference &type = TYPES.at(instr.type);
352 Q_ASSERT(type.component);
354 states.push(State());
356 State *cState = &states[states.count() - 2];
357 State *nState = &states[states.count() - 1];
359 nState->context = cState->context;
360 nState->compiledData = type.component;
361 nState->instructionStream = type.component->bytecode.constData();
363 if (instr.bindingBits != -1) {
364 const QByteArray &bits = cState->compiledData->datas.at(instr.bindingBits);
365 nState->bindingSkipList = QBitField((const quint32*)bits.constData(),
369 nState->bindingSkipList = nState->bindingSkipList.united(cState->bindingSkipList);
371 // As the state in the state stack changed, execution will continue in the new program.
372 QML_END_INSTR(CreateQMLObject)
374 QML_BEGIN_INSTR(CompleteQMLObject)
375 QObject *o = objects.top();
377 QDeclarativeData *ddata = QDeclarativeData::get(o);
381 if (ddata->context) {
382 Q_ASSERT(ddata->context != CTXT);
383 Q_ASSERT(ddata->outerContext);
384 Q_ASSERT(ddata->outerContext != CTXT);
385 QDeclarativeContextData *c = ddata->context;
386 while (c->linkedContext) c = c->linkedContext;
387 c->linkedContext = CTXT;
392 ddata->ownContext = true;
393 } else if (!ddata->context) {
397 ddata->setImplicitDestructible();
398 ddata->outerContext = CTXT;
399 ddata->lineNumber = instr.line;
400 ddata->columnNumber = instr.column;
401 QML_END_INSTR(CompleteQMLObject)
403 QML_BEGIN_INSTR(CreateCppObject)
404 const QDeclarativeCompiledData::TypeReference &type = TYPES.at(instr.type);
409 type.type->create(&o, &memory, sizeof(QDeclarativeData));
410 QDeclarativeData *ddata = new (memory) QDeclarativeData;
411 ddata->ownMemory = false;
412 QObjectPrivate::get(o)->declarativeData = ddata;
414 if (type.typePropertyCache && !ddata->propertyCache) {
415 ddata->propertyCache = type.typePropertyCache;
416 ddata->propertyCache->addref();
420 VME_EXCEPTION(tr("Unable to create object of type %1").arg(type.className), instr.line);
423 if (ddata->context) {
424 Q_ASSERT(ddata->context != CTXT);
425 Q_ASSERT(ddata->outerContext);
426 Q_ASSERT(ddata->outerContext != CTXT);
427 QDeclarativeContextData *c = ddata->context;
428 while (c->linkedContext) c = c->linkedContext;
429 c->linkedContext = CTXT;
434 ddata->ownContext = true;
435 } else if (!ddata->context) {
439 ddata->setImplicitDestructible();
440 ddata->outerContext = CTXT;
441 ddata->lineNumber = instr.line;
442 ddata->columnNumber = instr.column;
444 if (instr.data != -1) {
445 QDeclarativeCustomParser *customParser =
446 TYPES.at(instr.type).type->customParser();
447 customParser->setCustomData(o, DATAS.at(instr.data));
449 if (!objects.isEmpty()) {
450 QObject *parent = objects.top();
451 #if 0 // ### refactor
452 if (o->isWidgetType() && parent->isWidgetType())
453 static_cast<QWidget*>(o)->setParent(static_cast<QWidget*>(parent));
456 QDeclarative_setParent_noEvent(o, parent);
459 QML_END_INSTR(CreateCppObject)
461 QML_BEGIN_INSTR(CreateSimpleObject)
462 QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));
463 ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
466 QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
467 const QDeclarativeCompiledData::TypeReference &ref = TYPES.at(instr.type);
468 if (!ddata->propertyCache && ref.typePropertyCache) {
469 ddata->propertyCache = ref.typePropertyCache;
470 ddata->propertyCache->addref();
472 ddata->lineNumber = instr.line;
473 ddata->columnNumber = instr.column;
475 QObjectPrivate::get(o)->declarativeData = ddata;
476 ddata->context = ddata->outerContext = CTXT;
477 ddata->nextContextObject = CTXT->contextObjects;
478 if (ddata->nextContextObject)
479 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
480 ddata->prevContextObject = &CTXT->contextObjects;
481 CTXT->contextObjects = ddata;
483 QObject *parent = objects.top();
484 QDeclarative_setParent_noEvent(o, parent);
487 QML_END_INSTR(CreateSimpleObject)
489 QML_BEGIN_INSTR(SetId)
490 QObject *target = objects.top();
491 CTXT->setIdProperty(instr.index, target);
494 QML_BEGIN_INSTR(SetDefault)
495 CTXT->contextObject = objects.top();
496 QML_END_INSTR(SetDefault)
498 QML_BEGIN_INSTR(CreateComponent)
499 QDeclarativeComponent *qcomp =
500 new QDeclarativeComponent(CTXT->engine, COMP, INSTRUCTIONSTREAM - COMP->bytecode.constData(),
501 objects.isEmpty() ? 0 : objects.top());
503 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
506 CTXT->addObject(qcomp);
509 ddata->ownContext = true;
511 ddata->setImplicitDestructible();
512 ddata->outerContext = CTXT;
513 ddata->lineNumber = instr.line;
514 ddata->columnNumber = instr.column;
516 QDeclarativeComponentPrivate::get(qcomp)->creationContext = CTXT;
519 INSTRUCTIONSTREAM += instr.count;
520 QML_END_INSTR(CreateComponent)
522 QML_BEGIN_INSTR(StoreMetaObject)
523 QObject *target = objects.top();
526 const QByteArray &metadata = DATAS.at(instr.data);
527 QFastMetaBuilder::fromData(&mo, 0, metadata);
529 const QDeclarativeVMEMetaData *data =
530 (const QDeclarativeVMEMetaData *)DATAS.at(instr.aliasData).constData();
532 (void)new QDeclarativeVMEMetaObject(target, &mo, data, COMP);
534 if (instr.propertyCache != -1) {
535 QDeclarativeData *ddata = QDeclarativeData::get(target, true);
536 if (ddata->propertyCache) ddata->propertyCache->release();
537 ddata->propertyCache = PROPERTYCACHES.at(instr.propertyCache);
538 ddata->propertyCache->addref();
540 QML_END_INSTR(StoreMetaObject)
542 QML_BEGIN_INSTR(StoreVariant)
543 QObject *target = objects.top();
544 CLEAN_PROPERTY(target, instr.propertyIndex);
546 // XXX - can be more efficient
547 QVariant v = QDeclarativeStringConverters::variantFromString(PRIMITIVES.at(instr.value));
548 void *a[] = { &v, 0, &status, &flags };
549 QMetaObject::metacall(target, QMetaObject::WriteProperty,
550 instr.propertyIndex, a);
551 QML_END_INSTR(StoreVariant)
553 QML_BEGIN_INSTR(StoreVariantInteger)
554 QObject *target = objects.top();
555 CLEAN_PROPERTY(target, instr.propertyIndex);
557 QVariant v(instr.value);
558 void *a[] = { &v, 0, &status, &flags };
559 QMetaObject::metacall(target, QMetaObject::WriteProperty,
560 instr.propertyIndex, a);
561 QML_END_INSTR(StoreVariantInteger)
563 QML_BEGIN_INSTR(StoreVariantDouble)
564 QObject *target = objects.top();
565 CLEAN_PROPERTY(target, instr.propertyIndex);
567 QVariant v(instr.value);
568 void *a[] = { &v, 0, &status, &flags };
569 QMetaObject::metacall(target, QMetaObject::WriteProperty,
570 instr.propertyIndex, a);
571 QML_END_INSTR(StoreVariantDouble)
573 QML_BEGIN_INSTR(StoreVariantBool)
574 QObject *target = objects.top();
575 CLEAN_PROPERTY(target, instr.propertyIndex);
577 QVariant v(instr.value);
578 void *a[] = { &v, 0, &status, &flags };
579 QMetaObject::metacall(target, QMetaObject::WriteProperty,
580 instr.propertyIndex, a);
581 QML_END_INSTR(StoreVariantBool)
583 QML_BEGIN_INSTR(StoreVar)
584 QObject *target = objects.top();
585 CLEAN_PROPERTY(target, instr.propertyIndex);
587 // Note that we don't use QDeclarativeStringConverters::variantFromString() here, which
588 // means that automatic generation of value types from strings doesn't occur.
589 // This is a deliberate behaviour difference to variant properties.
590 v8::Handle<v8::Value> v8Value = ep->v8engine()->fromVariant(PRIMITIVES.at(instr.value));
591 static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
592 QML_END_INSTR(StoreVar)
594 QML_BEGIN_INSTR(StoreVarInteger)
595 QObject *target = objects.top();
596 CLEAN_PROPERTY(target, instr.propertyIndex);
598 v8::Handle<v8::Value> v8Value = v8::Integer::New(instr.value);
599 static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
600 QML_END_INSTR(StoreVarInteger)
602 QML_BEGIN_INSTR(StoreVarDouble)
603 QObject *target = objects.top();
604 CLEAN_PROPERTY(target, instr.propertyIndex);
606 v8::Handle<v8::Value> v8Value = v8::Number::New(instr.value);
607 static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
608 QML_END_INSTR(StoreVarDouble)
610 QML_BEGIN_INSTR(StoreVarBool)
611 QObject *target = objects.top();
612 CLEAN_PROPERTY(target, instr.propertyIndex);
614 v8::Handle<v8::Value> v8Value = v8::Boolean::New(instr.value);
615 static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
616 QML_END_INSTR(StoreVarBool)
618 QML_BEGIN_INSTR(StoreString)
619 QObject *target = objects.top();
620 CLEAN_PROPERTY(target, instr.propertyIndex);
622 void *a[] = { (void *)&PRIMITIVES.at(instr.value), 0, &status, &flags };
623 QMetaObject::metacall(target, QMetaObject::WriteProperty,
624 instr.propertyIndex, a);
625 QML_END_INSTR(StoreString)
627 QML_BEGIN_INSTR(StoreByteArray)
628 QObject *target = objects.top();
629 void *a[] = { (void *)&DATAS.at(instr.value), 0, &status, &flags };
630 QMetaObject::metacall(target, QMetaObject::WriteProperty,
631 instr.propertyIndex, a);
632 QML_END_INSTR(StoreByteArray)
634 QML_BEGIN_INSTR(StoreUrl)
635 QObject *target = objects.top();
636 CLEAN_PROPERTY(target, instr.propertyIndex);
638 void *a[] = { (void *)&URLS.at(instr.value), 0, &status, &flags };
639 QMetaObject::metacall(target, QMetaObject::WriteProperty,
640 instr.propertyIndex, a);
641 QML_END_INSTR(StoreUrl)
643 QML_BEGIN_INSTR(StoreFloat)
644 QObject *target = objects.top();
645 CLEAN_PROPERTY(target, instr.propertyIndex);
647 float f = instr.value;
648 void *a[] = { &f, 0, &status, &flags };
649 QMetaObject::metacall(target, QMetaObject::WriteProperty,
650 instr.propertyIndex, a);
651 QML_END_INSTR(StoreFloat)
653 QML_BEGIN_INSTR(StoreDouble)
654 QObject *target = objects.top();
655 CLEAN_PROPERTY(target, instr.propertyIndex);
657 double d = instr.value;
658 void *a[] = { &d, 0, &status, &flags };
659 QMetaObject::metacall(target, QMetaObject::WriteProperty,
660 instr.propertyIndex, a);
661 QML_END_INSTR(StoreDouble)
663 QML_BEGIN_INSTR(StoreBool)
664 QObject *target = objects.top();
665 CLEAN_PROPERTY(target, instr.propertyIndex);
667 void *a[] = { (void *)&instr.value, 0, &status, &flags };
668 QMetaObject::metacall(target, QMetaObject::WriteProperty,
669 instr.propertyIndex, a);
670 QML_END_INSTR(StoreBool)
672 QML_BEGIN_INSTR(StoreInteger)
673 QObject *target = objects.top();
674 CLEAN_PROPERTY(target, instr.propertyIndex);
676 void *a[] = { (void *)&instr.value, 0, &status, &flags };
677 QMetaObject::metacall(target, QMetaObject::WriteProperty,
678 instr.propertyIndex, a);
679 QML_END_INSTR(StoreInteger)
681 QML_BEGIN_INSTR(StoreColor)
682 QObject *target = objects.top();
683 CLEAN_PROPERTY(target, instr.propertyIndex);
685 QColor c = QColor::fromRgba(instr.value);
686 void *a[] = { &c, 0, &status, &flags };
687 QMetaObject::metacall(target, QMetaObject::WriteProperty,
688 instr.propertyIndex, a);
689 QML_END_INSTR(StoreColor)
691 QML_BEGIN_INSTR(StoreDate)
692 QObject *target = objects.top();
693 CLEAN_PROPERTY(target, instr.propertyIndex);
695 QDate d = QDate::fromJulianDay(instr.value);
696 void *a[] = { &d, 0, &status, &flags };
697 QMetaObject::metacall(target, QMetaObject::WriteProperty,
698 instr.propertyIndex, a);
699 QML_END_INSTR(StoreDate)
701 QML_BEGIN_INSTR(StoreTime)
702 QObject *target = objects.top();
703 CLEAN_PROPERTY(target, instr.propertyIndex);
705 QTime *t = (QTime *)&instr.time;
706 void *a[] = { t, 0, &status, &flags };
707 QMetaObject::metacall(target, QMetaObject::WriteProperty,
708 instr.propertyIndex, a);
709 QML_END_INSTR(StoreTime)
711 QML_BEGIN_INSTR(StoreDateTime)
712 QObject *target = objects.top();
713 CLEAN_PROPERTY(target, instr.propertyIndex);
715 QTime *t = (QTime *)&instr.time;
716 QDateTime dt(QDate::fromJulianDay(instr.date), *t);
717 void *a[] = { &dt, 0, &status, &flags };
718 QMetaObject::metacall(target, QMetaObject::WriteProperty,
719 instr.propertyIndex, a);
720 QML_END_INSTR(StoreDateTime)
722 QML_BEGIN_INSTR(StorePoint)
723 QObject *target = objects.top();
724 CLEAN_PROPERTY(target, instr.propertyIndex);
726 QPoint *p = (QPoint *)&instr.point;
727 void *a[] = { p, 0, &status, &flags };
728 QMetaObject::metacall(target, QMetaObject::WriteProperty,
729 instr.propertyIndex, a);
730 QML_END_INSTR(StorePoint)
732 QML_BEGIN_INSTR(StorePointF)
733 QObject *target = objects.top();
734 CLEAN_PROPERTY(target, instr.propertyIndex);
736 QPointF *p = (QPointF *)&instr.point;
737 void *a[] = { p, 0, &status, &flags };
738 QMetaObject::metacall(target, QMetaObject::WriteProperty,
739 instr.propertyIndex, a);
740 QML_END_INSTR(StorePointF)
742 QML_BEGIN_INSTR(StoreSize)
743 QObject *target = objects.top();
744 CLEAN_PROPERTY(target, instr.propertyIndex);
746 QSize *s = (QSize *)&instr.size;
747 void *a[] = { s, 0, &status, &flags };
748 QMetaObject::metacall(target, QMetaObject::WriteProperty,
749 instr.propertyIndex, a);
750 QML_END_INSTR(StoreSize)
752 QML_BEGIN_INSTR(StoreSizeF)
753 QObject *target = objects.top();
754 CLEAN_PROPERTY(target, instr.propertyIndex);
756 QSizeF *s = (QSizeF *)&instr.size;
757 void *a[] = { s, 0, &status, &flags };
758 QMetaObject::metacall(target, QMetaObject::WriteProperty,
759 instr.propertyIndex, a);
760 QML_END_INSTR(StoreSizeF)
762 QML_BEGIN_INSTR(StoreRect)
763 QObject *target = objects.top();
764 CLEAN_PROPERTY(target, instr.propertyIndex);
766 QRect *r = (QRect *)&instr.rect;
767 void *a[] = { r, 0, &status, &flags };
768 QMetaObject::metacall(target, QMetaObject::WriteProperty,
769 instr.propertyIndex, a);
770 QML_END_INSTR(StoreRect)
772 QML_BEGIN_INSTR(StoreRectF)
773 QObject *target = objects.top();
774 CLEAN_PROPERTY(target, instr.propertyIndex);
776 QRectF *r = (QRectF *)&instr.rect;
777 void *a[] = { r, 0, &status, &flags };
778 QMetaObject::metacall(target, QMetaObject::WriteProperty,
779 instr.propertyIndex, a);
780 QML_END_INSTR(StoreRectF)
782 QML_BEGIN_INSTR(StoreVector3D)
783 QObject *target = objects.top();
784 CLEAN_PROPERTY(target, instr.propertyIndex);
786 QVector3D *v = (QVector3D *)&instr.vector;
787 void *a[] = { v, 0, &status, &flags };
788 QMetaObject::metacall(target, QMetaObject::WriteProperty,
789 instr.propertyIndex, a);
790 QML_END_INSTR(StoreVector3D)
792 QML_BEGIN_INSTR(StoreVector4D)
793 QObject *target = objects.top();
794 CLEAN_PROPERTY(target, instr.propertyIndex);
796 QVector4D *v = (QVector4D *)&instr.vector;
797 void *a[] = { v, 0, &status, &flags };
798 QMetaObject::metacall(target, QMetaObject::WriteProperty,
799 instr.propertyIndex, a);
800 QML_END_INSTR(StoreVector4D)
802 QML_BEGIN_INSTR(StoreObject)
803 QObject *assignObj = objects.pop();
804 QObject *target = objects.top();
805 CLEAN_PROPERTY(target, instr.propertyIndex);
807 void *a[] = { (void *)&assignObj, 0, &status, &flags };
808 QMetaObject::metacall(target, QMetaObject::WriteProperty,
809 instr.propertyIndex, a);
810 QML_END_INSTR(StoreObject)
812 QML_BEGIN_INSTR(AssignCustomType)
813 QObject *target = objects.top();
814 CLEAN_PROPERTY(target, instr.propertyIndex);
816 const QString &primitive = PRIMITIVES.at(instr.primitive);
817 int type = instr.type;
818 QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
819 QVariant v = (*converter)(primitive);
822 target->metaObject()->property(instr.propertyIndex);
823 if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
824 VME_EXCEPTION(tr("Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
826 void *a[] = { (void *)v.data(), 0, &status, &flags };
827 QMetaObject::metacall(target, QMetaObject::WriteProperty,
828 instr.propertyIndex, a);
829 QML_END_INSTR(AssignCustomType)
831 QML_BEGIN_INSTR(AssignSignalObject)
834 QObject *assign = objects.pop();
835 QObject *target = objects.top();
836 int sigIdx = instr.signal;
837 const QString &pr = PRIMITIVES.at(sigIdx);
839 QDeclarativeProperty prop(target, pr);
840 if (prop.type() & QDeclarativeProperty::SignalProperty) {
842 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
843 if (method.signature() == 0)
844 VME_EXCEPTION(tr("Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
846 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
847 VME_EXCEPTION(tr("Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.line);
849 QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
852 VME_EXCEPTION(tr("Cannot assign an object to signal property %1").arg(pr), instr.line);
856 QML_END_INSTR(AssignSignalObject)
858 QML_BEGIN_INSTR(StoreSignal)
859 QObject *target = objects.top();
860 QObject *context = objects.at(objects.count() - 1 - instr.context);
862 QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
864 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
865 QDeclarativeExpression *expr =
866 new QDeclarativeExpression(CTXT, context, PRIMITIVES.at(instr.value), true, COMP->name, instr.line, *new QDeclarativeExpressionPrivate);
867 bs->setExpression(expr);
868 QML_END_INSTR(StoreSignal)
870 QML_BEGIN_INSTR(StoreImportedScript)
871 CTXT->importedScripts << run(CTXT, SCRIPTS.at(instr.value));
872 QML_END_INSTR(StoreImportedScript)
874 QML_BEGIN_INSTR(StoreScriptString)
875 QObject *target = objects.top();
876 QObject *scope = objects.at(objects.count() - 1 - instr.scope);
877 QDeclarativeScriptString ss;
878 ss.setContext(CTXT->asQDeclarativeContext());
879 ss.setScopeObject(scope);
880 ss.setScript(PRIMITIVES.at(instr.value));
881 ss.d.data()->bindingId = instr.bindingId;
882 ss.d.data()->lineNumber = instr.line;
884 void *a[] = { &ss, 0, &status, &flags };
885 QMetaObject::metacall(target, QMetaObject::WriteProperty,
886 instr.propertyIndex, a);
887 QML_END_INSTR(StoreScriptString)
889 QML_BEGIN_INSTR(BeginObject)
890 QObject *target = objects.top();
891 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
892 parserStatus.push(status);
893 status->d = &parserStatus.top();
895 status->classBegin();
896 QML_END_INSTR(BeginObject)
898 QML_BEGIN_INSTR(InitV8Bindings)
899 CTXT->v8bindings = new QV8Bindings(PRIMITIVES.at(instr.program), instr.programIndex,
900 instr.line, COMP, CTXT);
901 QML_END_INSTR(InitV8Bindings)
903 QML_BEGIN_INSTR(StoreBinding)
905 objects.at(objects.count() - 1 - instr.owner);
907 objects.at(objects.count() - 1 - instr.context);
909 QDeclarativeProperty mp =
910 QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
912 int coreIndex = mp.index();
914 if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex))
915 QML_NEXT_INSTR(StoreBinding);
917 QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true,
918 context, CTXT, COMP->name, instr.line);
919 bindValues.push(bind);
920 bind->m_mePtr = &bindValues.top();
923 bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
924 QML_END_INSTR(StoreBinding)
926 QML_BEGIN_INSTR(StoreBindingOnAlias)
928 objects.at(objects.count() - 1 - instr.owner);
930 objects.at(objects.count() - 1 - instr.context);
932 QDeclarativeProperty mp =
933 QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
935 int coreIndex = mp.index();
937 if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex))
938 QML_NEXT_INSTR(StoreBindingOnAlias);
940 QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true,
941 context, CTXT, COMP->name, instr.line);
942 bindValues.push(bind);
943 bind->m_mePtr = &bindValues.top();
946 QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
947 if (old) { old->destroy(); }
948 QML_END_INSTR(StoreBindingOnAlias)
950 QML_BEGIN_INSTR(StoreV4Binding)
952 objects.at(objects.count() - 1 - instr.owner);
954 objects.at(objects.count() - 1 - instr.context);
956 int property = instr.property;
957 if (instr.isRoot && BINDINGSKIPLIST.testBit(property & 0xFFFF))
958 QML_NEXT_INSTR(StoreV4Binding);
960 QDeclarativeAbstractBinding *binding =
961 CTXT->v4bindings->configBinding(instr.value, target, scope, property, instr.line);
962 bindValues.push(binding);
963 binding->m_mePtr = &bindValues.top();
964 binding->addToObject(target, property);
965 QML_END_INSTR(StoreV4Binding)
967 QML_BEGIN_INSTR(StoreV8Binding)
969 objects.at(objects.count() - 1 - instr.owner);
971 objects.at(objects.count() - 1 - instr.context);
973 if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
974 QML_NEXT_INSTR(StoreV8Binding);
976 QDeclarativeAbstractBinding *binding =
977 CTXT->v8bindings->configBinding(instr.value, target, scope,
978 instr.property, instr.line);
979 bindValues.push(binding);
980 binding->m_mePtr = &bindValues.top();
981 binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(instr.property));
982 QML_END_INSTR(StoreV8Binding)
984 QML_BEGIN_INSTR(StoreValueSource)
985 QObject *obj = objects.pop();
986 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
987 QObject *target = objects.at(objects.count() - 1 - instr.owner);
989 QDeclarativeProperty prop =
990 QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
991 obj->setParent(target);
993 QML_END_INSTR(StoreValueSource)
995 QML_BEGIN_INSTR(StoreValueInterceptor)
996 QObject *obj = objects.pop();
997 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
998 QObject *target = objects.at(objects.count() - 1 - instr.owner);
999 QDeclarativeProperty prop =
1000 QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
1001 obj->setParent(target);
1002 vi->setTarget(prop);
1003 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
1004 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
1005 QML_END_INSTR(StoreValueInterceptor)
1007 QML_BEGIN_INSTR(StoreObjectQList)
1008 QObject *assign = objects.pop();
1010 const List &list = lists.top();
1011 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
1012 QML_END_INSTR(StoreObjectQList)
1014 QML_BEGIN_INSTR(AssignObjectList)
1015 // This is only used for assigning interfaces
1016 QObject *assign = objects.pop();
1017 const List &list = lists.top();
1019 int type = list.type;
1023 const char *iid = QDeclarativeMetaType::interfaceIId(type);
1025 ptr = assign->qt_metacast(iid);
1027 VME_EXCEPTION(tr("Cannot assign object to list"), instr.line);
1030 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
1031 QML_END_INSTR(AssignObjectList)
1033 QML_BEGIN_INSTR(StoreVariantObject)
1034 QObject *assign = objects.pop();
1035 QObject *target = objects.top();
1036 CLEAN_PROPERTY(target, instr.propertyIndex);
1038 QVariant v = QVariant::fromValue(assign);
1039 void *a[] = { &v, 0, &status, &flags };
1040 QMetaObject::metacall(target, QMetaObject::WriteProperty,
1041 instr.propertyIndex, a);
1042 QML_END_INSTR(StoreVariantObject)
1044 QML_BEGIN_INSTR(StoreVarObject)
1045 QObject *assign = objects.pop();
1046 QObject *target = objects.top();
1047 CLEAN_PROPERTY(target, instr.propertyIndex);
1049 v8::Handle<v8::Value> v8Value = ep->v8engine()->newQObject(assign);
1050 static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
1051 QML_END_INSTR(StoreVarObject)
1053 QML_BEGIN_INSTR(StoreInterface)
1054 QObject *assign = objects.pop();
1055 QObject *target = objects.top();
1056 CLEAN_PROPERTY(target, instr.propertyIndex);
1058 int coreIdx = instr.propertyIndex;
1059 QMetaProperty prop = target->metaObject()->property(coreIdx);
1060 int t = prop.userType();
1061 const char *iid = QDeclarativeMetaType::interfaceIId(t);
1064 void *ptr = assign->qt_metacast(iid);
1066 void *a[] = { &ptr, 0, &status, &flags };
1067 QMetaObject::metacall(target,
1068 QMetaObject::WriteProperty,
1075 VME_EXCEPTION(tr("Cannot assign object to interface property"), instr.line);
1076 QML_END_INSTR(StoreInterface)
1078 QML_BEGIN_INSTR(FetchAttached)
1079 QObject *target = objects.top();
1081 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
1084 VME_EXCEPTION(tr("Unable to create attached object"), instr.line);
1086 objects.push(qmlObject);
1087 QML_END_INSTR(FetchAttached)
1089 QML_BEGIN_INSTR(FetchQList)
1090 QObject *target = objects.top();
1092 lists.push(List(instr.type));
1095 a[0] = (void *)&(lists.top().qListProperty);
1096 QMetaObject::metacall(target, QMetaObject::ReadProperty,
1098 QML_END_INSTR(FetchQList)
1100 QML_BEGIN_INSTR(FetchObject)
1101 QObject *target = objects.top();
1104 // NOTE: This assumes a cast to QObject does not alter the
1108 QMetaObject::metacall(target, QMetaObject::ReadProperty,
1112 VME_EXCEPTION(tr("Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line);
1115 QML_END_INSTR(FetchObject)
1117 QML_BEGIN_INSTR(PopQList)
1119 QML_END_INSTR(PopQList)
1121 QML_BEGIN_INSTR(Defer)
1122 if (instr.deferCount) {
1123 QObject *target = objects.top();
1124 QDeclarativeData *data =
1125 QDeclarativeData::get(target, true);
1127 data->deferredComponent = COMP;
1128 data->deferredIdx = INSTRUCTIONSTREAM - COMP->bytecode.constData();
1129 INSTRUCTIONSTREAM += instr.deferCount;
1131 QML_END_INSTR(Defer)
1133 QML_BEGIN_INSTR(PopFetchedObject)
1135 QML_END_INSTR(PopFetchedObject)
1137 QML_BEGIN_INSTR(FetchValueType)
1138 QObject *target = objects.top();
1140 if (instr.bindingSkipList != 0) {
1141 // Possibly need to clear bindings
1142 QDeclarativeData *targetData = QDeclarativeData::get(target);
1144 QDeclarativeAbstractBinding *binding =
1145 QDeclarativePropertyPrivate::binding(target, instr.property, -1);
1147 if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
1148 QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
1150 } else if (binding) {
1151 QDeclarativeValueTypeProxyBinding *proxy =
1152 static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
1153 proxy->removeBindings(instr.bindingSkipList);
1158 QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
1159 valueHandler->read(target, instr.property);
1160 objects.push(valueHandler);
1161 QML_END_INSTR(FetchValueType)
1163 QML_BEGIN_INSTR(PopValueType)
1164 QDeclarativeValueType *valueHandler =
1165 static_cast<QDeclarativeValueType *>(objects.pop());
1166 QObject *target = objects.top();
1167 valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
1168 QML_END_INSTR(PopValueType)
1170 #ifdef QML_THREADED_VME_INTERPRETER
1174 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr->common.instructionType);
1181 Q_ASSERT(!states.isEmpty());
1182 Q_ASSERT(!errors->isEmpty());
1189 Q_ASSERT(objects.count() == 1);
1191 QObject *rv = objects.top();
1193 objects.deallocate();
1200 void QDeclarativeVME::reset()
1202 Q_ASSERT(!states.isEmpty() || objects.isEmpty());
1204 QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
1206 if (!objects.isEmpty() && !(states.at(0).flags & State::Deferred))
1207 delete objects.at(0);
1209 if (!rootContext.isNull())
1210 rootContext->activeVMEData = 0;
1212 // Remove the QDeclarativeParserStatus and QDeclarativeAbstractBinding back pointers
1213 blank(parserStatus);
1216 while (componentAttached) {
1217 QDeclarativeComponentAttached *a = componentAttached;
1222 objects.deallocate();
1224 bindValues.deallocate();
1225 parserStatus.deallocate();
1226 finalizeCallbacks.clear();
1229 creationContext = 0;
1232 // Must be called with a handle scope and context
1233 void QDeclarativeScriptData::initialize(QDeclarativeEngine *engine)
1235 Q_ASSERT(m_program.IsEmpty());
1237 Q_ASSERT(!hasEngine());
1239 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
1240 QV8Engine *v8engine = ep->v8engine();
1242 // If compilation throws an error, a surrounding v8::TryCatch will record it.
1243 v8::Local<v8::Script> program = v8engine->qmlModeCompile(m_programSource, url.toString(), 1);
1244 if (program.IsEmpty())
1247 m_program = qPersistentNew<v8::Script>(program);
1249 addToEngine(engine);
1254 v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
1256 if (script->m_loaded)
1257 return qPersistentNew<v8::Object>(script->m_value);
1259 Q_ASSERT(parentCtxt && parentCtxt->engine);
1260 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
1261 QV8Engine *v8engine = ep->v8engine();
1263 bool shared = script->pragmas & QDeclarativeScript::Object::ScriptBlock::Shared;
1265 QDeclarativeContextData *effectiveCtxt = parentCtxt;
1269 // Create the script context if required
1270 QDeclarativeContextData *ctxt = new QDeclarativeContextData;
1271 ctxt->isInternal = true;
1272 ctxt->isJSContext = true;
1274 ctxt->isPragmaLibraryContext = true;
1276 ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
1277 ctxt->url = script->url;
1279 // For backward compatibility, if there are no imports, we need to use the
1280 // imports from the parent context. See QTBUG-17518.
1281 if (!script->importCache->isEmpty()) {
1282 ctxt->imports = script->importCache;
1283 } else if (effectiveCtxt) {
1284 ctxt->imports = effectiveCtxt->imports;
1285 ctxt->importedScripts = effectiveCtxt->importedScripts;
1286 for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
1287 ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
1290 if (ctxt->imports) {
1291 ctxt->imports->addref();
1294 if (effectiveCtxt) {
1295 ctxt->setParent(effectiveCtxt, true);
1297 ctxt->engine = parentCtxt->engine; // Fix for QTBUG-21620
1300 for (int ii = 0; ii < script->scripts.count(); ++ii) {
1301 ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
1304 v8::HandleScope handle_scope;
1305 v8::Context::Scope scope(v8engine->context());
1307 v8::TryCatch try_catch;
1308 if (!script->isInitialized())
1309 script->initialize(parentCtxt->engine);
1311 v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
1313 if (!script->m_program.IsEmpty()) {
1314 script->m_program->Run(qmlglobal);
1316 // Compilation failed.
1317 Q_ASSERT(try_catch.HasCaught());
1320 v8::Persistent<v8::Object> rv;
1322 if (try_catch.HasCaught()) {
1323 v8::Local<v8::Message> message = try_catch.Message();
1324 if (!message.IsEmpty()) {
1325 QDeclarativeError error;
1326 QDeclarativeExpressionPrivate::exceptionToError(message, error);
1331 rv = qPersistentNew<v8::Object>(qmlglobal);
1333 script->m_value = qPersistentNew<v8::Object>(qmlglobal);
1334 script->m_loaded = true;
1340 #ifdef QML_THREADED_VME_INTERPRETER
1341 void **QDeclarativeVME::instructionJumpTable()
1343 static void **jumpTable = 0;
1345 QDeclarativeVME dummy;
1346 QDeclarativeVME::Interrupt i;
1347 dummy.run(0, i, &jumpTable);
1353 QDeclarativeContextData *QDeclarativeVME::complete(const Interrupt &interrupt)
1356 (bindValues.isEmpty() &&
1357 parserStatus.isEmpty() &&
1358 componentAttached == 0 &&
1359 rootContext.isNull() &&
1360 finalizeCallbacks.isEmpty()));
1365 ActiveVMERestorer restore(this, QDeclarativeEnginePrivate::get(engine));
1366 QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
1368 while (!bindValues.isEmpty()) {
1369 QDeclarativeAbstractBinding *b = bindValues.pop();
1373 b->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor |
1374 QDeclarativePropertyPrivate::DontRemoveBinding);
1377 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1380 bindValues.deallocate();
1382 while (!parserStatus.isEmpty()) {
1383 QDeclarativeParserStatus *status = parserStatus.pop();
1385 if (status && status->d) {
1387 status->componentComplete();
1390 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1393 parserStatus.deallocate();
1395 for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) {
1396 QDeclarativeEnginePrivate::FinalizeCallback callback = finalizeCallbacks.at(ii);
1397 QObject *obj = callback.first;
1399 void *args[] = { 0 };
1400 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
1402 if (watcher.hasRecursed())
1405 finalizeCallbacks.clear();
1407 while (componentAttached) {
1408 QDeclarativeComponentAttached *a = componentAttached;
1410 QDeclarativeData *d = QDeclarativeData::get(a->parent());
1412 Q_ASSERT(d->context);
1413 a->add(&d->context->componentAttached);
1414 emit a->completed();
1416 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1420 QDeclarativeContextData *rv = rootContext;
1424 if (rv) rv->activeVMEData = data;
1429 void QDeclarativeVME::blank(QFiniteStack<QDeclarativeAbstractBinding *> &bs)
1431 for (int ii = 0; ii < bs.count(); ++ii) {
1432 QDeclarativeAbstractBinding *b = bs.at(ii);
1433 if (b) b->m_mePtr = 0;
1437 void QDeclarativeVME::blank(QFiniteStack<QDeclarativeParserStatus *> &pss)
1439 for (int ii = 0; ii < pss.count(); ++ii) {
1440 QDeclarativeParserStatus *ps = pss.at(ii);
1445 QDeclarativeVMEGuard::QDeclarativeVMEGuard()
1446 : m_objectCount(0), m_objects(0), m_contextCount(0), m_contexts(0)
1450 QDeclarativeVMEGuard::~QDeclarativeVMEGuard()
1455 void QDeclarativeVMEGuard::guard(QDeclarativeVME *vme)
1459 m_objectCount = vme->objects.count();
1460 m_objects = new QDeclarativeGuard<QObject>[m_objectCount];
1461 for (int ii = 0; ii < m_objectCount; ++ii)
1462 m_objects[ii] = vme->objects[ii];
1464 m_contextCount = (vme->rootContext.isNull()?0:1) + vme->states.count();
1465 m_contexts = new QDeclarativeGuardedContextData[m_contextCount];
1466 for (int ii = 0; ii < vme->states.count(); ++ii)
1467 m_contexts[ii] = vme->states.at(ii).context;
1468 if (!vme->rootContext.isNull())
1469 m_contexts[m_contextCount - 1] = vme->rootContext.contextData();
1472 void QDeclarativeVMEGuard::clear()
1474 delete [] m_objects;
1475 delete [] m_contexts;
1483 bool QDeclarativeVMEGuard::isOK() const
1485 for (int ii = 0; ii < m_objectCount; ++ii)
1486 if (m_objects[ii].isNull())
1489 for (int ii = 0; ii < m_contextCount; ++ii)
1490 if (m_contexts[ii].isNull())